1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
54 typedef struct gmx_repl_ex {
70 enum { ereTEMP, ereLAMBDA, ereNR };
71 const char *erename[ereNR] = { "temperature", "lambda" };
73 static void repl_quantity(FILE *fplog,const gmx_multisim_t *ms,
74 struct gmx_repl_ex *re,int ere,real q)
82 gmx_sum_sim(ms->nsim,qall,ms);
85 for(s=1; s<ms->nsim; s++)
86 if (qall[s] != qall[0])
90 if (re->type >= 0 && re->type < ereNR) {
91 gmx_fatal(FARGS,"For replica exchange both %s and %s differ",
92 erename[re->type],erename[ere]);
94 /* Set the replica exchange type and quantities */
96 snew(re->q,re->nrepl);
97 for(s=0; s<ms->nsim; s++)
105 gmx_repl_ex_t init_replica_exchange(FILE *fplog,
106 const gmx_multisim_t *ms,
107 const t_state *state,
108 const t_inputrec *ir,
109 int nst,int init_seed)
113 struct gmx_repl_ex *re;
115 fprintf(fplog,"\nInitializing Replica Exchange\n");
117 if (ms == NULL || ms->nsim == 1)
118 gmx_fatal(FARGS,"Nothing to exchange with only one replica, maybe you forgot to set the -multi option of mdrun?");
123 re->nrepl = ms->nsim;
125 fprintf(fplog,"Repl There are %d replicas:\n",re->nrepl);
127 check_multi_int(fplog,ms,state->natoms,"the number of atoms");
128 check_multi_int(fplog,ms,ir->eI,"the integrator");
129 check_multi_int(fplog,ms,ir->init_step+ir->nsteps,"init_step+nsteps");
130 check_multi_int(fplog,ms,(ir->init_step+nst-1)/nst,
131 "first exchange step: init_step/-replex");
132 check_multi_int(fplog,ms,ir->etc,"the temperature coupling");
133 check_multi_int(fplog,ms,ir->opts.ngtc,
134 "the number of temperature coupling groups");
135 check_multi_int(fplog,ms,ir->epc,"the pressure coupling");
136 check_multi_int(fplog,ms,ir->efep,"free energy");
138 re->temp = ir->opts.ref_t[0];
139 for(i=1; (i<ir->opts.ngtc); i++) {
140 if (ir->opts.ref_t[i] != re->temp) {
141 fprintf(fplog,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
142 fprintf(stderr,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
147 for(i=0; i<ereNR; i++)
152 repl_quantity(fplog,ms,re,i,re->temp);
155 if (ir->efep != efepNO)
157 repl_quantity(fplog,ms,re,i,ir->init_lambda);
161 gmx_incons("Unknown replica exchange quantity");
166 gmx_fatal(FARGS,"The properties of the %d systems are all the same, there is nothing to exchange",re->nrepl);
172 please_cite(fplog,"Hukushima96a");
173 if (ir->epc != epcNO)
176 fprintf(fplog,"Repl Using Constant Pressure REMD.\n");
177 please_cite(fplog,"Okabe2001a");
179 if (ir->etc == etcBERENDSEN)
181 gmx_fatal(FARGS,"REMD with the %s thermostat does not produce correct potential energy distributions, consider using the %s thermostat instead",
182 ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
186 if (ir->delta_lambda != 0)
188 gmx_fatal(FARGS,"delta_lambda is not zero");
194 snew(re->pres,re->nrepl);
195 if (ir->epct == epctSURFACETENSION) {
196 pres = ir->ref_p[ZZ][ZZ];
201 if (ir->compress[i][i] != 0) {
202 pres += ir->ref_p[i][i];
207 re->pres[re->repl] = pres;
208 gmx_sum_sim(re->nrepl,re->pres,ms);
211 snew(re->ind,re->nrepl);
212 /* Make an index for increasing temperature order */
213 for(i=0; i<re->nrepl; i++)
215 for(i=0; i<re->nrepl; i++) {
216 for(j=i+1; j<re->nrepl; j++) {
217 if (re->q[re->ind[j]] < re->q[re->ind[i]]) {
219 re->ind[i] = re->ind[j];
221 } else if (re->q[re->ind[j]] == re->q[re->ind[i]]) {
222 gmx_fatal(FARGS,"Two replicas have identical %ss",erename[re->type]);
226 fprintf(fplog,"Repl ");
227 for(i=0; i<re->nrepl; i++)
228 fprintf(fplog," %3d ",re->ind[i]);
231 fprintf(fplog,"\nRepl T");
232 for(i=0; i<re->nrepl; i++)
233 fprintf(fplog," %5.1f",re->q[re->ind[i]]);
236 fprintf(fplog,"\nRepl l");
237 for(i=0; i<re->nrepl; i++)
238 fprintf(fplog," %5.3f",re->q[re->ind[i]]);
241 gmx_incons("Unknown replica exchange quantity");
244 fprintf(fplog,"\nRepl p");
245 for(i=0; i<re->nrepl; i++)
247 fprintf(fplog," %5.2f",re->pres[re->ind[i]]);
250 for(i=0; i<re->nrepl; i++)
252 if ((i > 0) && (re->pres[re->ind[i]] < re->pres[re->ind[i-1]]))
254 gmx_fatal(FARGS,"The reference pressure decreases with increasing temperature");
258 fprintf(fplog,"\nRepl ");
261 if (init_seed == -1) {
263 re->seed = make_seed();
266 gmx_sumi_sim(1,&(re->seed),ms);
268 re->seed = init_seed;
270 fprintf(fplog,"\nRepl exchange interval: %d\n",re->nst);
271 fprintf(fplog,"\nRepl random seed: %d\n",re->seed);
275 snew(re->prob_sum,re->nrepl);
276 snew(re->nexchange,re->nrepl);
279 "Repl below: x=exchange, pr=probability\n");
284 static void exchange_reals(const gmx_multisim_t *ms,int b,real *v,int n)
293 MPI_Sendrecv(v, n*sizeof(real),MPI_BYTE,MSRANK(ms,b),0,
294 buf,n*sizeof(real),MPI_BYTE,MSRANK(ms,b),0,
295 ms->mpi_comm_masters,MPI_STATUS_IGNORE);
300 MPI_Isend(v,n*sizeof(real),MPI_BYTE,MSRANK(ms,b),0,
301 ms->mpi_comm_masters,&mpi_req);
302 MPI_Recv(buf,n*sizeof(real),MPI_BYTE,MSRANK(ms,b),0,
303 ms->mpi_comm_masters,MPI_STATUS_IGNORE);
304 MPI_Wait(&mpi_req,MPI_STATUS_IGNORE);
313 static void exchange_doubles(const gmx_multisim_t *ms,int b,double *v,int n)
322 MPI_Sendrecv(v, n*sizeof(double),MPI_BYTE,MSRANK(ms,b),0,
323 buf,n*sizeof(double),MPI_BYTE,MSRANK(ms,b),0,
324 ms->mpi_comm_masters,MPI_STATUS_IGNORE);
329 MPI_Isend(v,n*sizeof(double),MPI_BYTE,MSRANK(ms,b),0,
330 ms->mpi_comm_masters,&mpi_req);
331 MPI_Recv(buf,n*sizeof(double),MPI_BYTE,MSRANK(ms,b),0,
332 ms->mpi_comm_masters,MPI_STATUS_IGNORE);
333 MPI_Wait(&mpi_req,MPI_STATUS_IGNORE);
342 static void exchange_rvecs(const gmx_multisim_t *ms,int b,rvec *v,int n)
351 MPI_Sendrecv(v[0], n*sizeof(rvec),MPI_BYTE,MSRANK(ms,b),0,
352 buf[0],n*sizeof(rvec),MPI_BYTE,MSRANK(ms,b),0,
353 ms->mpi_comm_masters,MPI_STATUS_IGNORE);
358 MPI_Isend(v[0],n*sizeof(rvec),MPI_BYTE,MSRANK(ms,b),0,
359 ms->mpi_comm_masters,&mpi_req);
360 MPI_Recv(buf[0],n*sizeof(rvec),MPI_BYTE,MSRANK(ms,b),0,
361 ms->mpi_comm_masters,MPI_STATUS_IGNORE);
362 MPI_Wait(&mpi_req,MPI_STATUS_IGNORE);
366 copy_rvec(buf[i],v[i]);
371 static void exchange_state(const gmx_multisim_t *ms,int b,t_state *state)
373 /* When t_state changes, this code should be updated. */
375 ngtc = state->ngtc * state->nhchainlength;
376 nnhpres = state->nnhpres* state->nhchainlength;
377 exchange_rvecs(ms,b,state->box,DIM);
378 exchange_rvecs(ms,b,state->box_rel,DIM);
379 exchange_rvecs(ms,b,state->boxv,DIM);
380 exchange_reals(ms,b,&(state->veta),1);
381 exchange_reals(ms,b,&(state->vol0),1);
382 exchange_rvecs(ms,b,state->svir_prev,DIM);
383 exchange_rvecs(ms,b,state->fvir_prev,DIM);
384 exchange_rvecs(ms,b,state->pres_prev,DIM);
385 exchange_doubles(ms,b,state->nosehoover_xi,ngtc);
386 exchange_doubles(ms,b,state->nosehoover_vxi,ngtc);
387 exchange_doubles(ms,b,state->nhpres_xi,nnhpres);
388 exchange_doubles(ms,b,state->nhpres_vxi,nnhpres);
389 exchange_doubles(ms,b,state->therm_integral,state->ngtc);
390 exchange_rvecs(ms,b,state->x,state->natoms);
391 exchange_rvecs(ms,b,state->v,state->natoms);
392 exchange_rvecs(ms,b,state->sd_X,state->natoms);
395 static void copy_rvecs(rvec *s,rvec *d,int n)
403 copy_rvec(s[i],d[i]);
408 static void copy_doubles(const double *s,double *d,int n)
421 #define scopy_rvecs(v,n) copy_rvecs(state->v,state_local->v,n);
422 #define scopy_doubles(v,n) copy_doubles(state->v,state_local->v,n);
424 static void copy_state_nonatomdata(t_state *state,t_state *state_local)
426 /* When t_state changes, this code should be updated. */
428 ngtc = state->ngtc * state->nhchainlength;
429 nnhpres = state->nnhpres* state->nhchainlength;
430 scopy_rvecs(box,DIM);
431 scopy_rvecs(box_rel,DIM);
432 scopy_rvecs(boxv,DIM);
433 state_local->veta = state->veta;
434 state_local->vol0 = state->vol0;
435 scopy_rvecs(svir_prev,DIM);
436 scopy_rvecs(fvir_prev,DIM);
437 scopy_rvecs(pres_prev,DIM);
438 scopy_doubles(nosehoover_xi,ngtc);
439 scopy_doubles(nosehoover_vxi,ngtc);
440 scopy_doubles(nhpres_xi,nnhpres);
441 scopy_doubles(nhpres_vxi,nnhpres);
442 scopy_doubles(therm_integral,state->ngtc);
443 scopy_rvecs(x,state->natoms);
444 scopy_rvecs(v,state->natoms);
445 scopy_rvecs(sd_X,state->natoms);
448 static void scale_velocities(t_state *state,real fac)
453 for(i=0; i<state->natoms; i++)
454 svmul(fac,state->v[i],state->v[i]);
457 static void pd_collect_state(const t_commrec *cr,t_state *state)
462 fprintf(debug,"Collecting state before exchange\n");
463 shift = cr->nnodes - cr->npmenodes - 1;
464 move_rvecs(cr,FALSE,FALSE,GMX_LEFT,GMX_RIGHT,state->x,NULL,shift,NULL);
466 move_rvecs(cr,FALSE,FALSE,GMX_LEFT,GMX_RIGHT,state->v,NULL,shift,NULL);
468 move_rvecs(cr,FALSE,FALSE,GMX_LEFT,GMX_RIGHT,state->sd_X,NULL,shift,NULL);
471 static void print_ind(FILE *fplog,const char *leg,int n,int *ind,gmx_bool *bEx)
475 fprintf(fplog,"Repl %2s %2d",leg,ind[0]);
477 fprintf(fplog," %c %2d",(bEx!=0 && bEx[i]) ? 'x' : ' ',ind[i]);
482 static void print_prob(FILE *fplog,const char *leg,int n,real *prob)
487 fprintf(fplog,"Repl %2s ",leg);
490 sprintf(buf,"%4.2f",prob[i]);
491 fprintf(fplog," %3s",buf[0]=='1' ? "1.0" : buf+1);
499 static void print_count(FILE *fplog,const char *leg,int n,int *count)
503 fprintf(fplog,"Repl %2s ",leg);
505 fprintf(fplog," %4d",count[i]);
510 static int get_replica_exchange(FILE *fplog,const gmx_multisim_t *ms,
511 struct gmx_repl_ex *re,real *ener,real vol,
515 real *Epot=NULL,*Vol=NULL,*dvdl=NULL,*prob;
516 real ediff=0,delta=0,dpV=0,betaA=0,betaB=0;
517 gmx_bool *bEx,bPrint;
520 fprintf(fplog,"Replica exchange at step %d time %g\n",step,time);
524 snew(Epot,re->nrepl);
526 Epot[re->repl] = ener[F_EPOT];
528 gmx_sum_sim(re->nrepl,Epot,ms);
529 gmx_sum_sim(re->nrepl,Vol,ms);
532 snew(dvdl,re->nrepl);
533 dvdl[re->repl] = ener[F_DVDL];
534 gmx_sum_sim(re->nrepl,dvdl,ms);
539 snew(prob,re->nrepl);
542 m = (step / re->nst) % 2;
543 for(i=1; i<re->nrepl; i++) {
546 bPrint = (re->repl==a || re->repl==b);
550 /* Use equations from:
551 * Okabe et. al. Chem. Phys. Lett. 335 (2001) 435-439
553 ediff = Epot[b] - Epot[a];
554 betaA = 1.0/(re->q[a]*BOLTZ);
555 betaB = 1.0/(re->q[b]*BOLTZ);
556 delta = (betaA - betaB)*ediff;
559 /* Here we exchange based on a linear extrapolation of dV/dlambda.
560 * We would like to have the real energies
561 * from foreign lambda calculations.
563 ediff = (dvdl[a] - dvdl[b])*(re->q[b] - re->q[a]);
564 delta = ediff/(BOLTZ*re->temp);
567 gmx_incons("Unknown replica exchange quantity");
570 fprintf(fplog,"Repl %d <-> %d dE = %10.3e",a,b,delta);
572 dpV = (betaA*re->pres[a]-betaB*re->pres[b])*(Vol[b]-Vol[a])/PRESFAC;
574 fprintf(fplog," dpV = %10.3e d = %10.3e",dpV,delta + dpV);
586 prob[i] = exp(-delta);
587 bEx[i] = (rando(&(re->seed)) < prob[i]);
589 re->prob_sum[i] += prob[i];
593 } else if (b == re->repl) {
603 print_ind(fplog,"ex",re->nrepl,re->ind,bEx);
604 print_prob(fplog,"pr",re->nrepl,prob);
618 static void write_debug_x(t_state *state)
623 for(i=0; i<state->natoms; i+=10)
624 fprintf(debug,"dx %5d %10.5f %10.5f %10.5f\n",i,state->x[i][XX],state->x[i][YY],state->x[i][ZZ]);
628 gmx_bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re,
629 t_state *state,real *ener,
630 t_state *state_local,
634 int exchange=-1,shift;
635 gmx_bool bExchanged=FALSE;
641 exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box),
643 bExchanged = (exchange >= 0);
649 MPI_Bcast(&bExchanged,sizeof(gmx_bool),MPI_BYTE,MASTERRANK(cr),
650 cr->mpi_comm_mygroup);
656 /* Exchange the states */
660 /* Collect the global state on the master node */
661 if (DOMAINDECOMP(cr))
663 dd_collect_state(cr->dd,state_local,state);
667 pd_collect_state(cr,state);
673 /* Exchange the global states between the master nodes */
676 fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange);
678 exchange_state(ms,exchange,state);
680 if (re->type == ereTEMP)
682 scale_velocities(state,sqrt(re->q[ms->sim]/re->q[exchange]));
686 /* With domain decomposition the global state is distributed later */
687 if (!DOMAINDECOMP(cr))
689 /* Copy the global state to the local state data structure */
690 copy_state_nonatomdata(state,state_local);
694 bcast_state(cr,state,FALSE);
702 void print_replica_exchange_statistics(FILE *fplog,struct gmx_repl_ex *re)
707 fprintf(fplog,"\nReplica exchange statistics\n");
708 fprintf(fplog,"Repl %d attempts, %d odd, %d even\n",
709 re->nattempt[0]+re->nattempt[1],re->nattempt[1],re->nattempt[0]);
711 snew(prob,re->nrepl);
713 fprintf(fplog,"Repl average probabilities:\n");
714 for(i=1; i<re->nrepl; i++) {
715 if (re->nattempt[i%2] == 0)
718 prob[i] = re->prob_sum[i]/re->nattempt[i%2];
720 print_ind(fplog,"",re->nrepl,re->ind,NULL);
721 print_prob(fplog,"",re->nrepl,prob);
723 fprintf(fplog,"Repl number of exchanges:\n");
724 print_ind(fplog,"",re->nrepl,re->ind,NULL);
725 print_count(fplog,"",re->nrepl,re->nexchange);
727 fprintf(fplog,"Repl average number of exchanges:\n");
728 for(i=1; i<re->nrepl; i++) {
729 if (re->nattempt[i%2] == 0)
732 prob[i] = ((real)re->nexchange[i])/re->nattempt[i%2];
734 print_ind(fplog,"",re->nrepl,re->ind,NULL);
735 print_prob(fplog,"",re->nrepl,prob);