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 * GROningen Mixture of Alchemy and Childrens' Stories
36 /* This file is completely threadsafe - keep it that way! */
49 #include "gmx_fatal.h"
54 #include "mtop_util.h"
56 void init_disres(FILE *fplog
,const gmx_mtop_t
*mtop
,
57 t_inputrec
*ir
,const t_commrec
*cr
,gmx_bool bPartDecomp
,
58 t_fcdata
*fcd
,t_state
*state
, gmx_bool bIsREMD
)
60 int fa
,nmol
,i
,npair
,np
;
64 gmx_mtop_ilistloop_t iloop
;
70 if (gmx_mtop_ftype_count(mtop
,F_DISRES
) == 0)
79 fprintf(fplog
,"Initializing the distance restraints\n");
83 if (ir
->eDisre
== edrEnsemble
)
85 gmx_fatal(FARGS
,"Sorry, distance restraints with ensemble averaging over multiple molecules in one system are not functional in this version of GROMACS");
88 dd
->dr_weighting
= ir
->eDisreWeighting
;
89 dd
->dr_fc
= ir
->dr_fc
;
90 if (EI_DYNAMICS(ir
->eI
))
92 dd
->dr_tau
= ir
->dr_tau
;
98 if (dd
->dr_tau
== 0.0)
100 dd
->dr_bMixed
= FALSE
;
105 dd
->dr_bMixed
= ir
->bDisreMixed
;
106 dd
->ETerm
= exp(-(ir
->delta_t
/ir
->dr_tau
));
108 dd
->ETerm1
= 1.0 - dd
->ETerm
;
110 ip
= mtop
->ffparams
.iparams
;
114 iloop
= gmx_mtop_ilistloop_init(mtop
);
115 while (gmx_mtop_ilistloop_next(iloop
,&il
,&nmol
)) {
117 for(fa
=0; fa
<il
[F_DISRES
].nr
; fa
+=3)
120 npair
= mtop
->ffparams
.iparams
[il
[F_DISRES
].iatoms
[fa
]].disres
.npair
;
123 dd
->nres
+= (ir
->eDisre
==edrEnsemble
? 1 : nmol
)*npair
;
124 dd
->npair
+= nmol
*npair
;
130 if (cr
&& PAR(cr
) && !bPartDecomp
)
132 /* Temporary check, will be removed when disre is implemented with DD */
133 const char *notestr
="NOTE: atoms involved in distance restraints should be within the longest cut-off distance, if this is not the case mdrun generates a fatal error, in that case use particle decomposition (mdrun option -pd)";
136 fprintf(stderr
,"\n%s\n\n",notestr
);
138 fprintf(fplog
,"%s\n",notestr
);
140 if (dd
->dr_tau
!= 0 || ir
->eDisre
== edrEnsemble
|| cr
->ms
!= NULL
||
141 dd
->nres
!= dd
->npair
)
143 gmx_fatal(FARGS
,"Time or ensemble averaged or multiple pair distance restraints do not work (yet) with domain decomposition, use particle decomposition (mdrun option -pd)");
145 if (ir
->nstdisreout
!= 0)
149 fprintf(fplog
,"\nWARNING: Can not write distance restraint data to energy file with domain decomposition\n\n");
153 fprintf(stderr
,"\nWARNING: Can not write distance restraint data to energy file with domain decomposition\n");
159 snew(dd
->rt
,dd
->npair
);
161 if (dd
->dr_tau
!= 0.0)
164 /* Set the "history lack" factor to 1 */
165 state
->flags
|= (1<<estDISRE_INITF
);
166 hist
->disre_initf
= 1.0;
167 /* Allocate space for the r^-3 time averages */
168 state
->flags
|= (1<<estDISRE_RM3TAV
);
169 hist
->ndisrepairs
= dd
->npair
;
170 snew(hist
->disre_rm3tav
,hist
->ndisrepairs
);
172 /* Allocate space for a copy of rm3tav,
173 * so we can call do_force without modifying the state.
175 snew(dd
->rm3tav
,dd
->npair
);
177 /* Allocate Rt_6 and Rtav_6 consecutively in memory so they can be
178 * averaged over the processors in one call (in calc_disre_R_6)
180 snew(dd
->Rt_6
,2*dd
->nres
);
181 dd
->Rtav_6
= &(dd
->Rt_6
[dd
->nres
]);
183 ptr
= getenv("GMX_DISRE_ENSEMBLE_SIZE");
184 if (cr
&& cr
->ms
!= NULL
&& ptr
!= NULL
&& !bIsREMD
)
188 sscanf(ptr
,"%d",&dd
->nsystems
);
191 fprintf(fplog
,"Found GMX_DISRE_ENSEMBLE_SIZE set to %d systems per ensemble\n",dd
->nsystems
);
193 /* This check is only valid on MASTER(cr), so probably
194 * ensemble-averaged distance restraints are broken on more
195 * than one processor per simulation system. */
198 check_multi_int(fplog
,cr
->ms
,dd
->nsystems
,
199 "the number of systems per ensemble");
201 gmx_bcast_sim(sizeof(int), &dd
->nsystems
, cr
);
203 if (dd
->nsystems
<= 0 || cr
->ms
->nsim
% dd
->nsystems
!= 0)
205 gmx_fatal(FARGS
,"The number of systems %d is not divisible by the number of systems per ensemble %d\n",cr
->ms
->nsim
,dd
->nsystems
);
207 /* Split the inter-master communicator into different ensembles */
208 MPI_Comm_split(cr
->ms
->mpi_comm_masters
,
209 cr
->ms
->sim
/dd
->nsystems
,
211 &dd
->mpi_comm_ensemble
);
214 fprintf(fplog
,"Our ensemble consists of systems:");
215 for(i
=0; i
<dd
->nsystems
; i
++)
218 (cr
->ms
->sim
/dd
->nsystems
)*dd
->nsystems
+i
);
222 snew(dd
->Rtl_6
,dd
->nres
);
228 dd
->Rtl_6
= dd
->Rt_6
;
234 fprintf(fplog
,"There are %d distance restraints involving %d atom pairs\n",dd
->nres
,dd
->npair
);
236 /* Have to avoid g_disre de-referencing cr blindly, mdrun not
237 * doing consistency checks for ensemble-averaged distance
238 * restraints when that's not happening, and only doing those
239 * checks from appropriate processes (since check_multi_int is
240 * too broken to check whether the communication will
242 if (cr
&& cr
->ms
&& dd
->nsystems
> 1 && MASTER(cr
))
244 check_multi_int(fplog
,cr
->ms
,fcd
->disres
.nres
,
245 "the number of distance restraints");
247 please_cite(fplog
,"Tropp80a");
248 please_cite(fplog
,"Torda89a");
252 void calc_disres_R_6(const gmx_multisim_t
*ms
,
253 int nfa
,const t_iatom forceatoms
[],const t_iparams ip
[],
254 const rvec x
[],const t_pbc
*pbc
,
255 t_fcdata
*fcd
,history_t
*hist
)
258 int fa
,res
,i
,pair
,ki
,kj
,m
;
261 real
*rt
,*rm3tav
,*Rtl_6
,*Rt_6
,*Rtav_6
;
265 real ETerm
,ETerm1
,cf1
=0,cf2
=0,invn
=0;
269 bTav
= (dd
->dr_tau
!= 0);
280 /* scaling factor to smoothly turn on the restraint forces *
281 * when using time averaging */
282 dd
->exp_min_t_tau
= hist
->disre_initf
*ETerm
;
284 cf1
= dd
->exp_min_t_tau
;
285 cf2
= 1.0/(1.0 - dd
->exp_min_t_tau
);
288 if (dd
->nsystems
> 1)
290 invn
= 1.0/dd
->nsystems
;
293 /* 'loop' over all atom pairs (pair_nr=fa/3) involved in restraints, *
294 * the total number of atoms pairs is nfa/3 */
299 type
= forceatoms
[fa
];
300 npair
= ip
[type
].disres
.npair
;
305 /* Loop over the atom pairs of 'this' restraint */
307 while (fa
< nfa
&& np
< npair
)
310 ai
= forceatoms
[fa
+1];
311 aj
= forceatoms
[fa
+2];
315 pbc_dx_aiuc(pbc
,x
[ai
],x
[aj
],dx
);
319 rvec_sub(x
[ai
],x
[aj
],dx
);
322 rt_1
= gmx_invsqrt(rt2
);
323 rt_3
= rt_1
*rt_1
*rt_1
;
325 rt
[pair
] = sqrt(rt2
);
328 /* Here we update rm3tav in t_fcdata using the data
330 * Thus the results stay correct when this routine
331 * is called multiple times.
333 rm3tav
[pair
] = cf2
*((ETerm
- cf1
)*hist
->disre_rm3tav
[pair
] +
341 Rt_6
[res
] += rt_3
*rt_3
;
342 Rtav_6
[res
] += rm3tav
[pair
]*rm3tav
[pair
];
347 if (dd
->nsystems
> 1)
349 Rtl_6
[res
] = Rt_6
[res
];
358 if (dd
->nsystems
> 1)
360 gmx_sum_comm(2*dd
->nres
,Rt_6
,dd
->mpi_comm_ensemble
);
365 real
ta_disres(int nfa
,const t_iatom forceatoms
[],const t_iparams ip
[],
366 const rvec x
[],rvec f
[],rvec fshift
[],
367 const t_pbc
*pbc
,const t_graph
*g
,
368 real lambda
,real
*dvdlambda
,
369 const t_mdatoms
*md
,t_fcdata
*fcd
,
370 int *global_atom_index
)
372 const real sixth
=1.0/6.0;
373 const real seven_three
=7.0/3.0;
376 int fa
,res
,npair
,p
,pair
,ki
=CENTRAL
,m
;
380 real smooth_fc
,Rt
,Rtav
,rt2
,*Rtl_6
,*Rt_6
,*Rtav_6
;
381 real k0
,f_scal
=0,fmax_scal
,fk_scal
,fij
;
382 real tav_viol
,instant_viol
,mixed_viol
,violtot
,vtot
;
383 real tav_viol_Rtav7
,instant_viol_Rtav7
;
385 gmx_bool bConservative
,bMixed
,bViolation
;
392 dr_weighting
= dd
->dr_weighting
;
393 dr_bMixed
= dd
->dr_bMixed
;
398 tav_viol
=instant_viol
=mixed_viol
=tav_viol_Rtav7
=instant_viol_Rtav7
=0;
400 smooth_fc
= dd
->dr_fc
;
403 /* scaling factor to smoothly turn on the restraint forces *
404 * when using time averaging */
405 smooth_fc
*= (1.0 - dd
->exp_min_t_tau
);
411 /* 'loop' over all atom pairs (pair_nr=fa/3) involved in restraints, *
412 * the total number of atoms pairs is nfa/3 */
417 type
= forceatoms
[fa
];
418 /* Take action depending on restraint, calculate scalar force */
419 npair
= ip
[type
].disres
.npair
;
420 up1
= ip
[type
].disres
.up1
;
421 up2
= ip
[type
].disres
.up2
;
422 low
= ip
[type
].disres
.low
;
423 k0
= smooth_fc
*ip
[type
].disres
.kfac
;
425 /* save some flops when there is only one pair */
426 if (ip
[type
].disres
.type
!= 2)
428 bConservative
= (dr_weighting
== edrwConservative
) && (npair
> 1);
430 Rt
= pow(Rt_6
[res
],-sixth
);
431 Rtav
= pow(Rtav_6
[res
],-sixth
);
435 /* When rtype=2 use instantaneous not ensemble avereged distance */
436 bConservative
= (npair
> 1);
438 Rt
= pow(Rtl_6
[res
],-sixth
);
445 tav_viol
= Rtav
- up1
;
450 tav_viol
= Rtav
- low
;
460 * there is no real potential when time averaging is applied
462 vtot
+= 0.5*k0
*sqr(tav_viol
);
465 printf("vtot is inf: %f\n",vtot
);
469 f_scal
= -k0
*tav_viol
;
470 violtot
+= fabs(tav_viol
);
478 instant_viol
= Rt
- up1
;
489 instant_viol
= Rt
- low
;
502 mixed_viol
= sqrt(tav_viol
*instant_viol
);
503 f_scal
= -k0
*mixed_viol
;
504 violtot
+= mixed_viol
;
511 fmax_scal
= -k0
*(up2
-up1
);
512 /* Correct the force for the number of restraints */
515 f_scal
= max(f_scal
,fmax_scal
);
518 f_scal
*= Rtav
/Rtav_6
[res
];
522 f_scal
/= 2*mixed_viol
;
523 tav_viol_Rtav7
= tav_viol
*Rtav
/Rtav_6
[res
];
524 instant_viol_Rtav7
= instant_viol
*Rt
/Rt_6
[res
];
529 f_scal
/= (real
)npair
;
530 f_scal
= max(f_scal
,fmax_scal
);
533 /* Exert the force ... */
535 /* Loop over the atom pairs of 'this' restraint */
536 for(p
=0; p
<npair
; p
++)
539 ai
= forceatoms
[fa
+1];
540 aj
= forceatoms
[fa
+2];
544 ki
= pbc_dx_aiuc(pbc
,x
[ai
],x
[aj
],dx
);
548 rvec_sub(x
[ai
],x
[aj
],dx
);
552 weight_rt_1
= gmx_invsqrt(rt2
);
558 weight_rt_1
*= pow(dd
->rm3tav
[pair
],seven_three
);
562 weight_rt_1
*= tav_viol_Rtav7
*pow(dd
->rm3tav
[pair
],seven_three
)+
563 instant_viol_Rtav7
*pow(dd
->rt
[pair
],-7);
567 fk_scal
= f_scal
*weight_rt_1
;
571 ivec_sub(SHIFT_IVEC(g
,ai
),SHIFT_IVEC(g
,aj
),dt
);
581 fshift
[ki
][m
] += fij
;
582 fshift
[CENTRAL
][m
] -= fij
;
589 /* No violation so force and potential contributions */
595 dd
->sumviol
= violtot
;
601 void update_disres_history(t_fcdata
*fcd
,history_t
*hist
)
609 /* Copy the new time averages that have been calculated
610 * in calc_disres_R_6.
612 hist
->disre_initf
= dd
->exp_min_t_tau
;
613 for(pair
=0; pair
<dd
->npair
; pair
++)
615 hist
->disre_rm3tav
[pair
] = dd
->rm3tav
[pair
];