4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * Green Red Orange Magenta Azure Cyan Skyblue
29 static char *SRCID_disre_c
= "$Id$";
46 /* Some local variables */
47 static int dr_weighting
; /* Weighting of pairs in one restraint */
48 static bool dr_bMixed
; /* Use sqrt of the instantaneous times *
49 * the time averaged violation */
50 static real dr_fc
; /* Force constant for disres, *
51 * which is multiplied by a (possibly) *
52 * different factor for each restraint */
53 static real dr_tau
; /* Time constant for disres */
54 static real ETerm
,ETerm1
; /* Exponential constants */
56 static t_drblock drblock
;
58 void init_disres(FILE *log
,int nfa
,t_inputrec
*ir
)
60 dr_weighting
= ir
->eDisreWeighting
;
67 dr_bMixed
= ir
->bDisreMixed
;
68 ETerm
= exp(-(ir
->delta_t
/dr_tau
));
72 drblock
.ndr
= nfa
/(interaction_function
[F_DISRES
].nratoms
+1);
73 snew(drblock
.rav
, drblock
.ndr
);
74 snew(drblock
.rt
, drblock
.ndr
);
76 if (drblock
.ndr
> 0) {
77 fprintf(log
,"Done init_disre, ndr=%d\n",drblock
.ndr
);
78 please_cite(log
,"Torda89a");
82 t_drblock
*get_drblock(void)
87 real
ta_disres(int nfa
,t_iatom forceatoms
[],t_iparams ip
[],
88 rvec x
[],rvec f
[],t_forcerec
*fr
,t_graph
*g
,
89 matrix box
,real lambda
,real
*dvdlambda
,
90 t_mdatoms
*md
,int ngrp
,real egnb
[],real egcoul
[])
92 #define MAX_DRPAIRS 1000
93 static real sixth
=1.0/6.0;
94 static real seven_three
=7.0/3.0;
97 int fa
,fa_start
,i
,pair
,ki
,kj
,m
;
98 int restraint
,pair_nr
,pair_nr_start
,rindex
,npairs
,type
;
100 real weight_rt_1
[MAX_DRPAIRS
];
102 real smooth_fc
,rt
,Rt
,Rav
,rav_3
,rt_1
,rt_3
,Rav_6
,Rt_6
,rt2
;
103 real k0
,f_scal
,fmax_scal
,fk_scal
,fij
;
104 real tav_viol
,instant_viol
,mixed_viol
,violtot
;
105 real tav_viol_Rav7
,instant_viol_Rav7
;
107 bool bConservative
,bMixed
,bViolation
;
108 static real exp_min_t_tau
=1.0;
110 tav_viol
=instant_viol
=mixed_viol
=tav_viol_Rav7
=instant_viol_Rav7
=0;
111 /* scaling factor to smoothly turn on the restraint forces *
112 * when using time averaging */
113 exp_min_t_tau
*= ETerm
;
114 smooth_fc
= dr_fc
* (1.0 - exp_min_t_tau
);
120 /* 'loop' over all atom pairs (pair_nr=fa/3) involved in restraints, *
121 * the total number of atoms pairs is nfa/3 */
124 restraint
= forceatoms
[fa
];
125 rindex
= ip
[restraint
].disres
.index
;
128 pair_nr_start
= pair_nr
;
133 /* Loop over the atom pairs of 'this' restraint */
134 for(pair
=0; (fa
<nfa
) && (ip
[forceatoms
[fa
]].disres
.index
== rindex
);
135 pair
++,pair_nr
++,fa
+=3) {
136 if (pair
>= MAX_DRPAIRS
)
137 fatal_error(0,"Too many distance restraint pairs");
139 ai
= forceatoms
[fa
+1];
140 aj
= forceatoms
[fa
+2];
142 rvec_sub(x
[ai
],x
[aj
],dx
[pair
]);
143 rt2
= iprod(dx
[pair
],dx
[pair
]);
146 rt_3
= rt_1
*rt_1
*rt_1
;
147 if (drblock
.rav
[pair_nr
] == 0)
150 rav_3
= ETerm
*drblock
.rav
[pair_nr
] + ETerm1
*rt_3
;
152 weight_rt_1
[pair
] = rt_1
;
154 drblock
.rt
[pair_nr
] = rt
;
155 drblock
.rav
[pair_nr
] = rav_3
;
157 Rav_6
+= rav_3
*rav_3
;
162 /* Take action depending on restraint, calculate scalar force */
163 type
= ip
[restraint
].disres
.type
;
164 up1
= ip
[restraint
].disres
.up1
;
165 up2
= ip
[restraint
].disres
.up2
;
166 low
= ip
[restraint
].disres
.low
;
167 k0
= smooth_fc
*ip
[restraint
].disres
.fac
;
169 /* save some flops when there is only one pair */
171 bConservative
= (dr_weighting
== edrwConservative
) && (npairs
>1);
174 bConservative
= npairs
>1;
178 fmax_scal
= -k0
*(up2
-up1
);
180 Rt
= pow(Rt_6
,-sixth
);
181 /* Compute rav from ensemble / restraint averaging */
183 Rav
= pow(Rav_6
,-sixth
);
185 /* Dirty trick to not use time averaging when type=2 */
190 tav_viol
= Rav
- up1
;
191 } else if (Rav
< low
) {
193 tav_viol
= Rav
- low
;
198 f_scal
= -k0
*tav_viol
;
199 violtot
+= fabs(tav_viol
);
203 instant_viol
= Rt
- up1
;
206 } else if (Rt
< low
) {
208 instant_viol
= Rt
- low
;
214 mixed_viol
= sqrt(tav_viol
*instant_viol
);
215 f_scal
= -k0
*mixed_viol
;
216 violtot
+= mixed_viol
;
220 /* save some flops and don't use variables when they are not calculated */
222 /* Correct the force for the number of restraints */
224 f_scal
= max(f_scal
,fmax_scal
);
228 f_scal
/= 2*mixed_viol
;
229 tav_viol_Rav7
= tav_viol
*Rav
/Rav_6
;
230 instant_viol_Rav7
= instant_viol
*Rt
/Rt_6
;
233 f_scal
/= (real
)npairs
;
234 f_scal
= max(f_scal
,fmax_scal
);
237 /* Exert the force ... */
240 for(pair
=0; (pair
<npairs
); pair
++) {
241 restraint
= forceatoms
[i
++];
242 ai
= forceatoms
[i
++];
243 aj
= forceatoms
[i
++];
244 ki
= SHIFT_INDEX(g
,ai
);
245 kj
= SHIFT_INDEX(g
,aj
);
248 rav_3
= drblock
.rav
[pair_nr_start
+pair
];
250 weight_rt_1
[pair
] *= pow(rav_3
,seven_three
);
252 rt
= drblock
.rt
[pair_nr_start
+pair
];
253 weight_rt_1
[pair
] *= tav_viol_Rav7
*pow(rav_3
,seven_three
)+
254 instant_viol_Rav7
*pow(rt
,-7);
258 fk_scal
= f_scal
*weight_rt_1
[pair
];
260 for(m
=0; (m
<DIM
); m
++) {
261 fij
= fk_scal
*dx
[pair
][m
];
265 fshift
[ki
][m
] += fij
;
266 fshift
[kj
][m
] -= fij
;
271 /* Return violation */