Merge release-4-5-patches into release-4-6
[alexxy/gromacs.git] / src / kernel / md_openmm.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  * 
4  *                This source code is part of
5  * 
6  *                 G   R   O   M   A   C   S
7  * 
8  *          GROningen MAchine for Chemical Simulations
9  * 
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2010, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <signal.h>
41 #include <stdlib.h>
42
43 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
44 /* _isnan() */
45 #include <float.h>
46 #endif
47
48 #include "typedefs.h"
49 #include "smalloc.h"
50 #include "sysstuff.h"
51 #include "vec.h"
52 #include "statutil.h"
53 #include "vcm.h"
54 #include "mdebin.h"
55 #include "nrnb.h"
56 #include "calcmu.h"
57 #include "index.h"
58 #include "vsite.h"
59 #include "update.h"
60 #include "ns.h"
61 #include "trnio.h"
62 #include "xtcio.h"
63 #include "mdrun.h"
64 #include "confio.h"
65 #include "network.h"
66 #include "pull.h"
67 #include "xvgr.h"
68 #include "physics.h"
69 #include "names.h"
70 #include "xmdrun.h"
71 #include "ionize.h"
72 #include "disre.h"
73 #include "orires.h"
74 #include "dihre.h"
75 #include "pppm.h"
76 #include "pme.h"
77 #include "mdatoms.h"
78 #include "qmmm.h"
79 #include "mpelogging.h"
80 #include "domdec.h"
81 #include "partdec.h"
82 #include "topsort.h"
83 #include "coulomb.h"
84 #include "constr.h"
85 #include "compute_io.h"
86 #include "mvdata.h"
87 #include "checkpoint.h"
88 #include "mtop_util.h"
89 #include "sighandler.h"
90 #include "genborn.h"
91 #include "string2.h"
92 #include "copyrite.h"
93
94 #ifdef GMX_THREAD_MPI
95 #include "tmpi.h"
96 #endif
97
98 /* include even when OpenMM not used to force compilation of do_md_openmm */
99 #include "openmm_wrapper.h"
100
101 double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
102                     const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
103                     int nstglobalcomm,
104                     gmx_vsite_t *vsite,gmx_constr_t constr,
105                     int stepout,t_inputrec *ir,
106                     gmx_mtop_t *top_global,
107                     t_fcdata *fcd,
108                     t_state *state_global,
109                     t_mdatoms *mdatoms,
110                     t_nrnb *nrnb,gmx_wallcycle_t wcycle,
111                     gmx_edsam_t ed,t_forcerec *fr,
112                     int repl_ex_nst,int repl_ex_seed,
113                     real cpt_period,real max_hours,
114                     const char *deviceOptions,
115                     unsigned long Flags,
116                     gmx_runtime_t *runtime)
117 {
118     gmx_mdoutf_t *outf;
119     gmx_large_int_t step,step_rel;
120     double     run_time;
121     double     t,t0,lam0;
122     gmx_bool       bSimAnn,
123     bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt;
124     gmx_bool       bInitStep=TRUE;
125     gmx_bool       do_ene,do_log, do_verbose,
126     bX,bV,bF,bCPT;
127     tensor     force_vir,shake_vir,total_vir,pres;
128     int        i,m;
129     int        mdof_flags;
130     rvec       mu_tot;
131     t_vcm      *vcm;
132     int        nchkpt=1;
133     gmx_localtop_t *top;
134     t_mdebin *mdebin;
135     t_state    *state=NULL;
136     rvec       *f_global=NULL;
137     int        n_xtc=-1;
138     rvec       *x_xtc=NULL;
139     gmx_enerdata_t *enerd;
140     rvec       *f=NULL;
141     gmx_global_stat_t gstat;
142     gmx_update_t upd=NULL;
143     t_graph    *graph=NULL;
144     globsig_t   gs;
145
146     gmx_groups_t *groups;
147     gmx_ekindata_t *ekind, *ekind_save;
148     gmx_bool        bAppend;
149     int         a0,a1;
150     matrix      lastbox;
151     real        reset_counters=0,reset_counters_now=0;
152     char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
153     int         handled_stop_condition=gmx_stop_cond_none; 
154
155     const char *ommOptions = NULL;
156     void   *openmmData;
157
158 #ifdef GMX_DOUBLE
159     /* Checks in cmake should prevent the compilation in double precision
160      * with OpenMM, but just to be sure we check here.
161      */
162     gmx_fatal(FARGS,"Compilation was performed in double precision, but OpenMM only supports single precision. If you want to use to OpenMM, compile in single precision.");
163 #endif
164
165     bAppend  = (Flags & MD_APPENDFILES);
166     check_ir_old_tpx_versions(cr,fplog,ir,top_global);
167
168     groups = &top_global->groups;
169
170     /* Initial values */
171     init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
172             nrnb,top_global,&upd,
173             nfile,fnm,&outf,&mdebin,
174             force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
175
176     clear_mat(total_vir);
177     clear_mat(pres);
178     /* Energy terms and groups */
179     snew(enerd,1);
180     init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
181     snew(f,top_global->natoms);
182
183     /* Kinetic energy data */
184     snew(ekind,1);
185     init_ekindata(fplog,top_global,&(ir->opts),ekind);
186     /* needed for iteration of constraints */
187     snew(ekind_save,1);
188     init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
189     /* Copy the cos acceleration to the groups struct */
190     ekind->cosacc.cos_accel = ir->cos_accel;
191
192     gstat = global_stat_init(ir);
193     debug_gmx();
194
195     {
196         double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
197         if ((io > 2000) && MASTER(cr))
198             fprintf(stderr,
199                     "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
200                     io);
201     }
202
203     top = gmx_mtop_generate_local_top(top_global,ir);
204
205     a0 = 0;
206     a1 = top_global->natoms;
207
208     state = partdec_init_local_state(cr,state_global);
209     f_global = f;
210
211     atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
212
213     if (vsite)
214     {
215         set_vsite_top(vsite,top,mdatoms,cr);
216     }
217
218     if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
219     {
220         graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
221     }
222
223     update_mdatoms(mdatoms,state->lambda);
224
225     if (deviceOptions[0]=='\0')
226     {
227         /* empty options, which should default to OpenMM in this build */
228         ommOptions=deviceOptions;
229     }
230     else
231     {
232         if (gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0)
233         {
234             gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\"");
235         }
236         else
237         {
238             ommOptions=strchr(deviceOptions,':');
239             if (NULL!=ommOptions)
240             {
241                 /* Increase the pointer to skip the colon */
242                 ommOptions++;
243             }
244         }
245     }
246
247     openmmData = openmm_init(fplog, ommOptions, ir, top_global, top, mdatoms, fr, state);
248     please_cite(fplog,"Friedrichs2009");
249
250     if (MASTER(cr))
251     {
252         /* Update mdebin with energy history if appending to output files */
253         if ( Flags & MD_APPENDFILES )
254         {
255             restore_energyhistory_from_state(mdebin,&state_global->enerhist);
256         }
257         /* Set the initial energy history in state to zero by updating once */
258         update_energyhistory(&state_global->enerhist,mdebin);
259     }
260
261     if (constr)
262     {
263         set_constraints(constr,top,ir,mdatoms,cr);
264     }
265
266     if (!ir->bContinuation)
267     {
268         if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
269         {
270             /* Set the velocities of frozen particles to zero */
271             for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
272             {
273                 for (m=0; m<DIM; m++)
274                 {
275                     if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
276                     {
277                         state->v[i][m] = 0;
278                     }
279                 }
280             }
281         }
282
283         if (constr)
284         {
285             /* Constrain the initial coordinates and velocities */
286             do_constrain_first(fplog,constr,ir,mdatoms,state,f,
287                                graph,cr,nrnb,fr,top,shake_vir);
288         }
289         if (vsite)
290         {
291             /* Construct the virtual sites for the initial configuration */
292             construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
293                              top->idef.iparams,top->idef.il,
294                              fr->ePBC,fr->bMolPBC,graph,cr,state->box);
295         }
296     }
297
298     debug_gmx();
299
300     if (MASTER(cr))
301     {
302         char tbuf[20];
303         fprintf(stderr,"starting mdrun '%s'\n",
304                 *(top_global->name));
305         if (ir->nsteps >= 0)
306         {
307             sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
308         }
309         else
310         {
311             sprintf(tbuf,"%s","infinite");
312         }
313         if (ir->init_step > 0)
314         {
315             fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
316                     gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
317                     gmx_step_str(ir->init_step,sbuf2),
318                     ir->init_step*ir->delta_t);
319         }
320         else
321         {
322             fprintf(stderr,"%s steps, %s ps.\n",
323                     gmx_step_str(ir->nsteps,sbuf),tbuf);
324         }
325     }
326
327     fprintf(fplog,"\n");
328
329     /* Set and write start time */
330     runtime_start(runtime);
331     print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
332     wallcycle_start(wcycle,ewcRUN);
333     if (fplog)
334         fprintf(fplog,"\n");
335
336     /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
337
338     debug_gmx();
339     /***********************************************************
340      *
341      *             Loop over MD steps
342      *
343      ************************************************************/
344
345     /* loop over MD steps or if rerunMD to end of input trajectory */
346     bFirstStep = TRUE;
347     /* Skip the first Nose-Hoover integration when we get the state from tpx */
348     bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
349     bInitStep = bFirstStep && bStateFromTPX;
350     bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
351     bLastStep = FALSE;
352
353     init_global_signals(&gs,cr,ir,repl_ex_nst);
354
355     step = ir->init_step;
356     step_rel = 0;
357
358     while (!bLastStep)
359     {
360         wallcycle_start(wcycle,ewcSTEP);
361
362         GMX_MPE_LOG(ev_timestep1);
363
364         bLastStep = (step_rel == ir->nsteps);
365         t = t0 + step*ir->delta_t;
366
367         if (gs.set[eglsSTOPCOND] != 0)
368         {
369             bLastStep = TRUE;
370         }
371
372         do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
373         do_verbose = bVerbose &&
374                      (step % stepout == 0 || bFirstStep || bLastStep);
375
376         if (MASTER(cr) && do_log)
377         {
378             print_ebin_header(fplog,step,t,state->lambda);
379         }
380
381         clear_mat(force_vir);
382         GMX_MPE_LOG(ev_timestep2);
383
384         /* We write a checkpoint at this MD step when:
385          * either when we signalled through gs (in OpenMM NS works different),
386          * or at the last step (but not when we do not want confout),
387          * but never at the first step.
388          */
389         bCPT = ((gs.set[eglsCHKPT] ||
390                  (bLastStep && (Flags & MD_CONFOUT))) &&
391                 step > ir->init_step );
392         if (bCPT)
393         {
394             gs.set[eglsCHKPT] = 0;
395         }
396
397         /* Now we have the energies and forces corresponding to the
398          * coordinates at time t. We must output all of this before
399          * the update.
400          * for RerunMD t is read from input trajectory
401          */
402         GMX_MPE_LOG(ev_output_start);
403
404         mdof_flags = 0;
405         if (do_per_step(step,ir->nstxout))
406         {
407             mdof_flags |= MDOF_X;
408         }
409         if (do_per_step(step,ir->nstvout))
410         {
411             mdof_flags |= MDOF_V;
412         }
413         if (do_per_step(step,ir->nstfout))
414         {
415             mdof_flags |= MDOF_F;
416         }
417         if (do_per_step(step,ir->nstxtcout))
418         {
419             mdof_flags |= MDOF_XTC;
420         }
421         if (bCPT)
422         {
423             mdof_flags |= MDOF_CPT;
424         };
425         do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
426
427         if (mdof_flags != 0 || do_ene || do_log)
428         {
429             wallcycle_start(wcycle,ewcTRAJ);
430             bF = (mdof_flags & MDOF_F);
431             bX = (mdof_flags & (MDOF_X | MDOF_XTC | MDOF_CPT));
432             bV = (mdof_flags & (MDOF_V | MDOF_CPT));
433
434             openmm_copy_state(openmmData, state, &t, f, enerd, bX, bV, bF, do_ene);
435
436             upd_mdebin(mdebin,FALSE,TRUE,
437                        t,mdatoms->tmass,enerd,state,lastbox,
438                        shake_vir,force_vir,total_vir,pres,
439                        ekind,mu_tot,constr);
440             print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,do_log?fplog:NULL,
441                        step,t,
442                        eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
443             write_traj(fplog,cr,outf,mdof_flags,top_global,
444                        step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
445             if (bCPT)
446             {
447                 nchkpt++;
448                 bCPT = FALSE;
449             }
450             debug_gmx();
451             if (bLastStep && step_rel == ir->nsteps &&
452                     (Flags & MD_CONFOUT) && MASTER(cr))
453             {
454                 /* x and v have been collected in write_traj,
455                  * because a checkpoint file will always be written
456                  * at the last step.
457                  */
458                 fprintf(stderr,"\nWriting final coordinates.\n");
459                 if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
460                 {
461                     /* Make molecules whole only for confout writing */
462                     do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
463                 }
464                 write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
465                                     *top_global->name,top_global,
466                                     state_global->x,state_global->v,
467                                     ir->ePBC,state->box);
468                 debug_gmx();
469             }
470             wallcycle_stop(wcycle,ewcTRAJ);
471         }
472         GMX_MPE_LOG(ev_output_finish);
473
474
475         /* Determine the wallclock run time up till now */
476         run_time = gmx_gettime() - (double)runtime->real;
477
478         /* Check whether everything is still allright */
479         if (((int)gmx_get_stop_condition() > handled_stop_condition)
480 #ifdef GMX_THREAD_MPI
481             && MASTER(cr)
482 #endif
483             )
484         {
485            /* this is just make gs.sig compatible with the hack 
486                of sending signals around by MPI_Reduce with together with
487                other floats */
488             /* NOTE: this only works for serial code. For code that allows
489                MPI nodes to propagate their condition, see kernel/md.c*/
490             if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
491                 gs.set[eglsSTOPCOND]=1;
492             if ( gmx_get_stop_condition() == gmx_stop_cond_next )
493                 gs.set[eglsSTOPCOND]=1;
494             /* < 0 means stop at next step, > 0 means stop at next NS step */
495             if (fplog)
496             {
497                 fprintf(fplog,
498                         "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
499                         gmx_get_signal_name(),
500                         gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
501                 fflush(fplog);
502             }
503             fprintf(stderr,
504                     "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
505                     gmx_get_signal_name(),
506                     gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
507             fflush(stderr);
508             handled_stop_condition=(int)gmx_get_stop_condition();
509         }
510         else if (MASTER(cr) &&
511                  (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
512                  gs.set[eglsSTOPCOND] == 0)
513         {
514             /* Signal to terminate the run */
515             gs.set[eglsSTOPCOND] = 1;
516             if (fplog)
517             {
518                 fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
519             }
520             fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
521         }
522
523         /* checkpoints */
524         if (MASTER(cr) && (cpt_period >= 0 &&
525                            (cpt_period == 0 ||
526                             run_time >= nchkpt*cpt_period*60.0)) &&
527                 gs.set[eglsCHKPT] == 0)
528         {
529             gs.set[eglsCHKPT] = 1;
530         }
531
532         /* Time for performance */
533         if (((step % stepout) == 0) || bLastStep)
534         {
535             runtime_upd_proc(runtime);
536         }
537
538         if (do_per_step(step,ir->nstlog))
539         {
540             if (fflush(fplog) != 0)
541             {
542                 gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of disk space?");
543             }
544         }
545
546         /* Remaining runtime */
547         if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
548         {
549             print_time(stderr,runtime,step,ir,cr);
550         }
551
552         bFirstStep = FALSE;
553         bInitStep = FALSE;
554         bStartingFromCpt = FALSE;
555         step++;
556         step_rel++;
557
558         openmm_take_one_step(openmmData);
559     }
560     /* End of main MD loop */
561     debug_gmx();
562
563     /* Stop the time */
564     runtime_end(runtime);
565
566     if (MASTER(cr))
567     {
568         if (ir->nstcalcenergy > 0) 
569         {
570             print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
571                        eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
572         }
573     }
574
575     openmm_cleanup(fplog, openmmData);
576
577     done_mdoutf(outf);
578
579     debug_gmx();
580
581     runtime->nsteps_done = step_rel;
582
583     return 0;
584 }