4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
30 * GROup of MAchos and Cynical Suckers
32 static char *SRCID_sim_util_c
= "$Id$";
61 #define difftime(end,start) ((double)(end)-(double)(start))
63 void print_time(FILE *out
,time_t start
,int step
,t_inputrec
*ir
)
65 static real time_per_step
;
71 fprintf(out
,"\rstep %d",step
);
72 if ((step
>= ir
->nstlist
)) {
73 if ((ir
->nstlist
== 0) || ((step
% ir
->nstlist
) == 0)) {
74 /* We have done a full cycle let's update time_per_step */
76 dt
=difftime(end
,start
);
77 time_per_step
=dt
/(step
+1);
79 dt
=(ir
->nsteps
-step
)*time_per_step
;
82 finish
= end
+(time_t)dt
;
83 sprintf(buf
,"%s",ctime(&finish
));
84 buf
[strlen(buf
)-1]='\0';
85 fprintf(out
,", will finish at %s",buf
);
88 fprintf(out
,", remaining runtime: %5d s ",(int)dt
);
97 time_t print_date_and_time(FILE *log
,int nodeid
,char *title
)
100 char *ts
,time_string
[STRLEN
];
105 for (i
=0; ts
[i
]>=' '; i
++) time_string
[i
]=ts
[i
];
107 fprintf(log
,"%s on node %d %s\n",title
,nodeid
,time_string
);
111 static void pr_commrec(FILE *log
,t_commrec
*cr
)
113 fprintf(log
,"commrec: nodeid=%d, nnodes=%d, left=%d, right=%d, threadid=%d, nthreads=%d\n",
114 cr
->nodeid
,cr
->nnodes
,cr
->left
,cr
->right
,cr
->threadid
,cr
->nthreads
);
117 static void sum_forces(int start
,int end
,rvec f
[],rvec flr
[])
122 pr_rvecs(debug
,0,"fsr",f
+start
,end
-start
);
123 pr_rvecs(debug
,0,"flr",flr
+start
,end
-start
);
125 for(i
=start
; (i
<end
); i
++)
126 rvec_inc(f
[i
],flr
[i
]);
129 static void reset_energies(t_grpopts
*opts
,t_groups
*grp
,
130 t_forcerec
*fr
,bool bNS
,real epot
[])
134 /* First reset all energy components but the Long Range, except in
135 * some special cases.
137 for(i
=0; (i
<egNR
); i
++)
138 if (((i
!= egLR
) && (i
!= egLJLR
)) ||
139 (fr
->bTwinRange
&& bNS
) || (!fr
->bTwinRange
))
140 for(j
=0; (j
<grp
->estat
.nn
); j
++)
141 grp
->estat
.ee
[i
][j
]=0.0;
143 /* Normal potential energy components */
144 for(i
=0; (i
<=F_EPOT
); i
++)
147 epot
[F_DVDLKIN
] = 0.0;
151 * calc_f_el calculates forces due to an electric field.
153 * force is kJ mol^-1 nm^-1 = e * kJ mol^-1 nm^-1 / e
155 * Et[] contains the parameters for the time dependent
156 * part of the field (not yet used).
157 * Ex[] contains the parameters for
158 * the spatial dependent part of the field. You can have cool periodic
159 * fields in principle, but only a constant field is supported
161 * The function should return the energy due to the electric field
162 * (if any) but for now returns 0.
165 static real
calc_f_el(int start
,int homenr
,real charge
[],rvec f
[],t_cosines Ex
[])
167 real Emu
,fmu
,strength
;
171 for(m
=0; (m
<DIM
); m
++)
173 /* Convert the field strength from V/nm to MD-units */
174 strength
= Ex
[m
].a
[0]*FIELDFAC
;
175 for(i
=start
; (i
<start
+homenr
); i
++) {
176 fmu
= charge
[i
]*strength
;
184 void do_force(FILE *log
,t_commrec
*cr
,t_commrec
*mcr
,
185 t_parm
*parm
,t_nsborder
*nsb
,tensor vir_part
,tensor pme_vir
,
186 int step
,t_nrnb
*nrnb
,t_topology
*top
,t_groups
*grps
,
187 rvec x
[],rvec v
[],rvec f
[],rvec buf
[],
188 t_mdatoms
*mdatoms
,real ener
[],t_fcdata
*fcd
,bool bVerbose
,
189 real lambda
,t_graph
*graph
,
190 bool bNS
,bool bNBFonly
,t_forcerec
*fr
, rvec mu_tot
,
193 static rvec box_size
;
194 static real dvdl_lr
= 0;
197 static real mu_and_q
[DIM
+1];
201 homenr
= HOMENR(nsb
);
205 update_forcerec(log
,fr
,parm
->box
);
207 /* Calculate total (local) dipole moment in a temporary common array.
208 * This makes it possible to sum them over nodes faster.
210 calc_mu_and_q(nsb
,x
,mdatoms
->chargeT
,mu_and_q
,mu_and_q
+DIM
);
212 if (fr
->ePBC
!= epbcNONE
) {
213 /* Compute shift vectors every step, because of pressure coupling! */
214 if (parm
->ir
.epc
!= epcNO
)
215 calc_shifts(parm
->box
,box_size
,fr
->shift_vec
);
218 put_charge_groups_in_box(log
,cg0
,cg1
,parm
->box
,box_size
,
219 &(top
->blocks
[ebCGS
]),x
,fr
->cg_cm
);
220 inc_nrnb(nrnb
,eNR_RESETX
,homenr
);
221 } else if (parm
->ir
.eI
==eiSteep
|| parm
->ir
.eI
==eiCG
)
222 unshift_self(graph
,parm
->box
,x
);
226 calc_cgcm(log
,cg0
,cg1
,&(top
->blocks
[ebCGS
]),x
,fr
->cg_cm
);
229 inc_nrnb(nrnb
,eNR_CGCM
,cg1
-cg0
);
231 move_cgcm(log
,cr
,fr
->cg_cm
,nsb
->workload
);
233 pr_rvecs(debug
,0,"cgcm",fr
->cg_cm
,nsb
->cgtotal
);
236 /* Communicate coordinates and sum dipole and net charge if necessary */
238 move_x(log
,cr
->left
,cr
->right
,x
,nsb
,nrnb
);
239 gmx_sum(DIM
+1,mu_and_q
,cr
);
242 mu_tot
[i
]=mu_and_q
[i
];
246 reset_energies(&(parm
->ir
.opts
),grps
,fr
,bNS
,ener
);
248 if (fr
->ePBC
!= epbcNONE
)
249 /* Calculate intramolecular shift vectors to make molecules whole */
250 mk_mshift(log
,graph
,parm
->box
,x
);
252 /* Reset long range forces if necessary */
253 if (fr
->bTwinRange
) {
254 clear_rvecs(nsb
->natoms
,fr
->f_twin
);
255 clear_rvecs(SHIFTS
,fr
->fshift_twin
);
257 /* Do the actual neighbour searching and if twin range electrostatics
258 * also do the calculation of long range forces and energies.
262 ns(log
,fr
,x
,f
,parm
->box
,grps
,&(parm
->ir
.opts
),top
,mdatoms
,
263 cr
,nrnb
,nsb
,step
,lambda
,&dvdl_lr
);
265 /* Reset PME/Ewald forces if necessary */
266 if (EEL_LR(fr
->eeltype
))
267 clear_rvecs(homenr
,fr
->f_pme
+start
);
269 /* Copy long range forces into normal buffers */
270 if (fr
->bTwinRange
) {
271 for(i
=0; i
<nsb
->natoms
; i
++)
272 copy_rvec(fr
->f_twin
[i
],f
[i
]);
273 for(i
=0; i
<SHIFTS
; i
++)
274 copy_rvec(fr
->fshift_twin
[i
],fr
->fshift
[i
]);
277 clear_rvecs(nsb
->natoms
,f
);
278 clear_rvecs(SHIFTS
,fr
->fshift
);
281 /* Compute the forces */
282 force(log
,step
,fr
,&(parm
->ir
),&(top
->idef
),nsb
,cr
,mcr
,nrnb
,grps
,mdatoms
,
283 top
->atoms
.grps
[egcENER
].nr
,&(parm
->ir
.opts
),
284 x
,f
,ener
,fcd
,bVerbose
,parm
->box
,lambda
,graph
,&(top
->atoms
.excl
),
285 bNBFonly
,pme_vir
,mu_tot
,qsum
,bGatherOnly
);
287 /* Take long range contribution to free energy into account */
288 ener
[F_DVDL
] += dvdl_lr
;
292 print_nrnb(log
,nrnb
);
295 /* The short-range virial from surrounding boxes */
297 calc_vir(log
,SHIFTS
,fr
->shift_vec
,fr
->fshift
,vir_part
);
298 inc_nrnb(nrnb
,eNR_VIRIAL
,SHIFTS
);
301 pr_rvecs(debug
,0,"vir_shifts",vir_part
,DIM
);
303 /* Compute forces due to electric field */
304 calc_f_el(start
,homenr
,mdatoms
->chargeT
,f
,parm
->ir
.ex
);
306 /* When using PME/Ewald we compute the long range virial (pme_vir) there.
307 * otherwise we do it based on long range forces from twin range
308 * cut-off based calculation (or not at all).
311 /* Communicate the forces */
313 move_f(log
,cr
->left
,cr
->right
,f
,buf
,nsb
,nrnb
);
316 void sum_lrforces(rvec f
[],t_forcerec
*fr
,int start
,int homenr
)
318 /* Now add the forces from the PME calculation. Since this only produces
319 * forces on the local atoms, this can be safely done after the
320 * communication step.
322 if (EEL_LR(fr
->eeltype
))
323 sum_forces(start
,start
+homenr
,f
,fr
->f_pme
);
326 void calc_virial(FILE *log
,int start
,int homenr
,rvec x
[],rvec f
[],
327 tensor vir_part
,tensor pme_vir
,
328 t_graph
*graph
,matrix box
,
329 t_nrnb
*nrnb
,t_forcerec
*fr
,bool bTweak
)
334 /* Now it is time for the short range virial. At this timepoint vir_part
335 * already contains the virial from surrounding boxes.
336 * Calculate partial virial, for local atoms only, based on short range.
337 * Total virial is computed in global_stat, called from do_md
339 f_calc_vir(log
,start
,start
+homenr
,x
,f
,vir_part
,graph
,box
);
340 inc_nrnb(nrnb
,eNR_VIRIAL
,homenr
);
342 /* Add up the long range forces if necessary */
344 sum_lrforces(f,fr,start,homenr);
347 /* Add up virial if necessary */
348 if (EEL_LR(fr
->eeltype
) && (fr
->eeltype
!= eelPPPM
)) {
349 if (debug
&& bTweak
) {
351 f_calc_vir(log
,start
,start
+homenr
,x
,fr
->f_pme
,virtest
,graph
,box
);
352 pr_rvecs(debug
,0,"virtest",virtest
,DIM
);
353 pr_rvecs(debug
,0,"pme_vir",pme_vir
,DIM
);
355 /* PPPM virial sucks */
357 for(i
=0; (i
<DIM
); i
++)
358 for(j
=0; (j
<DIM
); j
++)
359 vir_part
[i
][j
]+=pme_vir
[i
][j
];
362 pr_rvecs(debug
,0,"vir_part",vir_part
,DIM
);
368 static double runtime
=0;
369 static clock_t cprev
;
371 void start_time(void)
377 void update_time(void)
382 runtime
+= (c
-cprev
)/(double)CLOCKS_PER_SEC
;
386 double node_time(void)
391 void do_shakefirst(FILE *log
,bool bTYZ
,real lambda
,real ener
[],
392 t_parm
*parm
,t_nsborder
*nsb
,t_mdatoms
*md
,
393 rvec x
[],rvec vold
[],rvec buf
[],rvec f
[],
394 rvec v
[],t_graph
*graph
,t_commrec
*cr
,t_nrnb
*nrnb
,
395 t_groups
*grps
,t_forcerec
*fr
,t_topology
*top
,
396 t_edsamyn
*edyn
,t_pull
*pulldata
)
398 int i
,m
,start
,homenr
,end
,step
;
400 double mass
,tmass
,vcm
[4];
401 real dt
=parm
->ir
.delta_t
;
404 if (count_constraints(top
,cr
)) {
406 homenr
= HOMENR(nsb
);
409 fprintf(debug
,"vcm: start=%d, homenr=%d, end=%d\n",start
,homenr
,end
);
410 /* Do a first SHAKE to reset particles... */
412 fprintf(log
,"\nConstraining the starting coordinates (step %d)\n",step
);
413 clear_mat(shake_vir
);
414 update(nsb
->natoms
,start
,homenr
,step
,lambda
,&ener
[F_DVDL
],
416 NULL
,NULL
,vold
,NULL
,x
,top
,grps
,shake_vir
,cr
,nrnb
,bTYZ
,
417 FALSE
,edyn
,pulldata
,FALSE
);
418 /* Compute coordinates at t=-dt, store them in buf */
419 /* for(i=0; (i<nsb->natoms); i++) {*/
420 for(i
=start
; (i
<end
); i
++) {
421 for(m
=0; (m
<DIM
); m
++) {
423 buf
[i
][m
]=x
[i
][m
]-dt
*v
[i
][m
];
427 /* Shake the positions at t=-dt with the positions at t=0
428 * as reference coordinates.
431 fprintf(log
,"\nConstraining the coordinates at t0-dt (step %d)\n",step
);
432 clear_mat(shake_vir
);
433 update(nsb
->natoms
,start
,homenr
,
434 step
,lambda
,&ener
[F_DVDL
],parm
,1.0,md
,f
,graph
,
435 NULL
,NULL
,vold
,NULL
,buf
,top
,grps
,shake_vir
,cr
,nrnb
,bTYZ
,FALSE
,
436 edyn
,pulldata
,FALSE
);
438 /* Compute the velocities at t=-dt/2 using the coordinates at
440 * Compute velocity of center of mass and total mass
445 for(i
=start
; (i
<end
); i
++) {
446 /*for(i=0; (i<nsb->natoms); i++) {*/
448 for(m
=0; (m
<DIM
); m
++) {
449 v
[i
][m
]=(x
[i
][m
]-f
[i
][m
])*dt_1
;
450 vcm
[m
] += v
[i
][m
]*mass
;
454 /* Compute the global sum of vcm */
456 fprintf(debug
,"vcm: %8.3f %8.3f %8.3f,"
457 " total mass = %12.5e\n",vcm
[XX
],vcm
[YY
],vcm
[ZZ
],vcm
[3]);
461 for(m
=0; (m
<DIM
); m
++)
464 fprintf(debug
,"vcm: %8.3f %8.3f %8.3f,"
465 " total mass = %12.5e\n",vcm
[XX
],vcm
[YY
],vcm
[ZZ
],tmass
);
466 /* Now we have the velocity of center of mass, let's remove it */
467 for(i
=start
; (i
<end
); i
++) {
468 for(m
=0; (m
<DIM
); m
++)
474 void calc_dispcorr(FILE *log
,int eDispCorr
,t_forcerec
*fr
,int natoms
,
475 matrix box
,tensor pres
,tensor virial
,real ener
[])
477 static bool bFirst
=TRUE
;
478 real vol
,rc3
,spres
,svir
;
481 ener
[F_DISPCORR
] = 0.0;
482 ener
[F_PRES
] = trace(pres
)/3.0;
484 if (eDispCorr
!= edispcNO
) {
486 /* Forget the (small) effect of the shift on the LJ energy *
487 * when fr->bLJShift = TRUE */
488 rc3
= fr
->rvdw
*fr
->rvdw
*fr
->rvdw
;
489 ener
[F_DISPCORR
] = -2.0*natoms
*natoms
*M_PI
*fr
->avcsix
/(3.0*vol
*rc3
);
490 if (eDispCorr
== edispcEnerPres
) {
491 spres
= 2.0*ener
[F_DISPCORR
]*PRESFAC
/vol
;
492 svir
= -6.0*ener
[F_DISPCORR
];
493 ener
[F_PRES
] += spres
;
494 for(m
=0; (m
<DIM
); m
++) {
496 virial
[m
][m
] += svir
;
504 if (eDispCorr
== edispcEner
)
505 fprintf(log
,"Long Range LJ corr. to Epot: %10g\n",ener
[F_DISPCORR
]);
506 else if (eDispCorr
== edispcEnerPres
)
507 fprintf(log
,"Long Range LJ corr. to Epot: %10g, Pres: %10g, Vir: %10g\n",
508 ener
[F_DISPCORR
],spres
,svir
);
512 ener
[F_EPOT
] += ener
[F_DISPCORR
];
513 ener
[F_ETOT
] += ener
[F_DISPCORR
];
516 void do_pbc_first(FILE *log
,t_parm
*parm
,rvec box_size
,t_forcerec
*fr
,
517 t_graph
*graph
,rvec x
[])
519 fprintf(log
,"Removing pbc first time\n");
520 calc_shifts(parm
->box
,box_size
,fr
->shift_vec
);
521 mk_mshift(log
,graph
,parm
->box
,x
);
522 if (getenv ("NOPBC") == NULL
)
523 shift_self(graph
,parm
->box
,x
);
525 fprintf(log
,"Not doing first shift_self\n");
526 fprintf(log
,"Done rmpbc\n");
529 void set_pot_bools(t_inputrec
*ir
,t_topology
*top
,
530 bool *bLR
,bool *bLJLR
,bool *bBHAM
,bool *b14
)
532 *bLR
= (ir
->rcoulomb
> ir
->rlist
) || EEL_LR(ir
->coulombtype
);
533 *bLJLR
= (ir
->rvdw
> ir
->rlist
);
534 *bBHAM
= (top
->idef
.functype
[0]==F_BHAM
);
535 *b14
= (top
->idef
.il
[F_LJ14
].nr
> 0);
538 void finish_run(FILE *log
,t_commrec
*cr
,char *confout
,
539 t_nsborder
*nsb
,t_topology
*top
,t_parm
*parm
,
540 t_nrnb nrnb
[],double nodetime
,double realtime
,int step
,
546 for(i
=0; (i
<eNRNB
); i
++)
548 for(i
=0; (i
<nsb
->nnodes
); i
++)
549 for(j
=0; (j
<eNRNB
); j
++)
550 ntot
.n
[j
]+=nrnb
[i
].n
[j
];
553 runtime
=parm
->ir
.nsteps
*parm
->ir
.delta_t
;
555 fprintf(stderr
,"\n\n");
556 print_perf(stderr
,nodetime
,realtime
,runtime
,&ntot
,nsb
->nnodes
);
559 print_nrnb(log
,&(nrnb
[nsb
->nodeid
]));
563 print_perf(log
,nodetime
,realtime
,runtime
,&ntot
,nsb
->nnodes
);
565 pr_load(log
,nsb
->nnodes
,nrnb
);
569 void init_md(t_commrec
*cr
,t_inputrec
*ir
,tensor box
,real
*t
,real
*t0
,
570 real
*lambda
,real
*lam0
,real
*SAfactor
,
571 t_nrnb
*mynrnb
,bool *bTYZ
,t_topology
*top
,
572 int nfile
,t_filenm fnm
[],char **traj
,
573 char **xtc_traj
,int *fp_ene
,
574 FILE **fp_dgdl
,t_mdebin
**mdebin
,t_groups
*grps
,
575 tensor force_vir
,tensor pme_vir
,
576 tensor shake_vir
,t_mdatoms
*mdatoms
,rvec mu_tot
,
577 bool *bNEMD
,t_vcm
**vcm
,t_nsborder
*nsb
)
579 bool bBHAM
,b14
,bLR
,bLJLR
;
583 *t
= *t0
= ir
->init_t
;
584 if (ir
->efep
!= efepNO
) {
585 *lambda
= *lam0
= ir
->init_lambda
;
588 *lambda
= *lam0
= 0.0;
591 *SAfactor
= 1.0 - *t0
/ir
->zero_temp_time
;
599 /* Check Environment variables & other booleans */
600 *bTYZ
=getenv("TYZ") != NULL
;
601 set_pot_bools(ir
,top
,&bLR
,&bLJLR
,&bBHAM
,&b14
);
605 *traj
= ftp2fn(efTRN
,nfile
,fnm
);
606 *xtc_traj
= ftp2fn(efXTC
,nfile
,fnm
);
609 *fp_ene
= open_enx(ftp2fn(efENX
,nfile
,fnm
),"w");
610 if ((fp_dgdl
!= NULL
) && ir
->efep
!=efepNO
)
612 xvgropen(opt2fn("-dgdl",nfile
,fnm
),
613 "dG/d\\8l\\4","Time (ps)",
614 "dG/d\\8l\\4 (kJ mol\\S-1\\N nm\\S-2\\N \\8l\\4\\S-1\\N)");
618 *mdebin
= init_mdebin(*fp_ene
,grps
,&(top
->atoms
),&(top
->idef
),
619 bLR
,bLJLR
,bBHAM
,b14
,ir
->efep
!=efepNO
,ir
->epc
,
620 ir
->eDispCorr
,(TRICLINIC(ir
->compress
) || TRICLINIC(box
)),
621 (ir
->etc
==etcNOSEHOOVER
),cr
);
624 /* Initiate variables */
625 clear_mat(force_vir
);
627 clear_mat(shake_vir
);
630 /* Set initial values for invmass etc. */
631 init_mdatoms(mdatoms
,*lambda
,TRUE
);
633 *vcm
= init_vcm(stdlog
,top
,cr
,mdatoms
,START(nsb
),HOMENR(nsb
),ir
->nstcomm
);
637 *bNEMD
= (ir
->opts
.ngacc
> 1) || (norm(ir
->opts
.acc
[0]) > 0);
640 init_sd_consts(ir
->opts
.ngtc
,ir
->opts
.tau_t
,ir
->delta_t
);