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 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_pull_c
= "$Id$";
45 /* check if we're close enough to the target position */
46 static bool check_convergence(t_pull
*pull
) {
51 rvec dr
; /* distance between target and current position */
53 tol
= pull
->tolerance
;
55 for (i
=0;i
<pull
->pull
.n
;i
++) {
56 rvec_sub(pull
->ref
.x_unc
[0],pull
->pull
.x_unc
[i
],tmp1
);
57 rvec_add(pull
->pull
.xtarget
[i
],tmp1
,dr
);
58 /* multiply by pull->dims to pick the elements we want */
60 dr
[m
] = pull
->dims
[m
]*dr
[m
];
61 bTest
= bTest
&& (norm(dr
) < tol
);
67 static void do_start(t_pull
*pull
, rvec
*x
, matrix box
, t_mdatoms
*md
,
68 real dt
, int step
, t_topology
*top
)
76 /* pull.xtarget[i] is the desired position of group i with respect
77 to the reference group */
79 /* bThereYet is true if all groups have reached their desired position */
80 bThereYet
= check_convergence(pull
);
83 for (i
=0;i
<pull
->pull
.n
;i
++) {
84 copy_rvec(pull
->pull
.xtarget
[i
],tmp
);
85 fprintf(stderr
,"Group %d goal:%8.3f%8.3f%8.3f from reference\n",
86 i
,tmp
[0],tmp
[1],tmp
[2]);
90 /* some groups are not there yet! */
92 for (i
=0;i
<pull
->pull
.n
;i
++) {
93 /* move this group closer to its target position */
94 rvec_sub(pull
->ref
.x_unc
[0],pull
->pull
.x_unc
[i
],tmp
);
95 rvec_add(pull
->pull
.xtarget
[i
],tmp
,dr
);
97 /* multiply by pull->dims to pick the elements we want */
99 dr
[m
] = pull
->dims
[m
]*dr
[m
];
101 /* move over pull->xlt_rate in the direction of dr */
102 svmul(pull
->xlt_rate
/norm(dr
),dr
,dx
);
105 fprintf(stderr
,"To go:%10.2e %10.2e %10.2e\n",
106 dr
[XX
],dr
[YY
],dr
[ZZ
]);
108 /* update the actual positions */
109 for (j
=0;j
<pull
->pull
.ngx
[i
];j
++) {
110 ii
= pull
->pull
.idx
[i
][j
];
111 rvec_add(x
[ii
],dx
,x
[ii
]);
114 /* get the new center of mass in pull.x_unc[i] */
115 (void)calc_com(x
,pull
->pull
.ngx
[i
],pull
->pull
.idx
[i
],
116 md
,pull
->pull
.x_unc
[i
],box
);
120 bDump
= check_convergence(pull
);
123 /* we have to write a coordinate file and reset the desired position */
124 for (i
=0;i
<pull
->pull
.n
;i
++) {
125 for (m
=0;m
<DIM
;m
++) {
126 pull
->pull
.xtarget
[i
][m
] += pull
->pull
.dir
[i
][m
]*pull
->xlt_incr
/
127 norm(pull
->pull
.dir
[i
]);
131 fprintf(stderr
,"New target position: %8.3f%8.3f%8.3f\n",
132 pull
->pull
.xtarget
[i
][0],pull
->pull
.xtarget
[i
][1],
133 pull
->pull
.xtarget
[i
][2]);
135 dump_conf(pull
,x
,box
,top
,nout
,step
*dt
/1000);
140 static void do_umbrella(t_pull
*pull
, rvec
*x
,rvec
*f
,matrix box
,
145 rvec cm
; /* center of mass displacement of reference */
146 rvec dr
; /* distance from com to potential center */
148 /* loop over the groups that are being umbrella sampled */
149 for (i
=0;i
<pull
->pull
.n
;i
++) {
151 /* pull->dims selects which components (x,y,z) we want */
152 for (m
=0;m
<DIM
;m
++) {
153 dr
[m
]=pull
->dims
[m
]*(pull
->pull
.x_ref
[i
][m
]-pull
->pull
.x_unc
[i
][m
]);
154 if (dr
[m
] > box
[m
][m
]/2) dr
[m
]-=box
[m
][m
];
155 if (dr
[m
] < -box
[m
][m
]/2) dr
[m
]+=box
[m
][m
];
159 svmul(pull
->um_width
,dr
,pull
->pull
.f
[i
]);
161 /* distribute the force over all atoms in the group */
162 for (j
=0;j
<pull
->pull
.ngx
[i
];j
++)
163 for (m
=0;m
<DIM
;m
++) {
164 mi
= md
->massT
[pull
->pull
.idx
[i
][j
]];
165 f
[pull
->pull
.idx
[i
][j
]][m
] +=
166 mi
*(pull
->pull
.f
[i
][m
])/(pull
->pull
.tmass
[i
]);
170 /* reset center of mass of the reference group to its starting value */
171 rvec_sub(pull
->ref
.x_unc
[0],pull
->ref
.x_con
[0],cm
);
172 for (i
=0;i
<pull
->ref
.ngx
[0];i
++)
173 rvec_sub(x
[pull
->ref
.idx
[0][i
]],cm
,x
[pull
->ref
.idx
[0][i
]]);
176 /* this implements a constraint run like SHAKE does. */
177 static void do_constraint(t_pull
*pull
, rvec
*x
, matrix box
, t_mdatoms
*md
,
181 rvec r_ij
, /* x_con[i] com of i in prev. step. Obeys constr. -> r_ij */
182 unc_ij
, /* x_unc[i] com of i this step, before constr. -> unc_ij */
183 ref_ij
; /* x_ref[i] com of i at t0, not updated -> ref_ij */
185 rvec
*rinew
; /* current 'new' position of group i */
186 rvec
*rjnew
; /* current 'new' position of group j */
187 real
*direction
; /* direction of dr relative to r_ij */
188 double lambda
, rm
, mass
, tol
= 0.00001;
189 bool bConverged
= FALSE
;
190 int n
=0,i
,ii
,j
,m
,max_iter
=1000;
192 double x1
,x2
,q
,a
,b
,c
; /* for solving the quadratic equation,
193 see Num. Recipes in C ed 2 p. 184 */
194 rvec
*dr
; /* correction for group i */
195 rvec
*ref_dr
; /* correction for group j */
196 rvec tmp
,tmp2
,tmp3
,sum
;
199 snew(ref_dr
,pull
->pull
.n
);
200 snew(rjnew
,pull
->pull
.n
);
205 snew(dr
,pull
->pull
.n
);
206 snew(rinew
,pull
->pull
.n
);
207 snew(direction
,pull
->pull
.n
);
209 /* copy the current unconstraint positions for use in iterations. We
210 iterate until rinew[i] and rjnew[j] obey the constraints. Then
211 rinew - pull.x_unc[i] is the correction dr to group i */
212 for (i
=0;i
<pull
->pull
.n
;i
++)
213 copy_rvec(pull
->pull
.x_unc
[i
],rinew
[i
]);
215 for (i
=0;i
<pull
->pull
.n
;i
++)
216 copy_rvec(pull
->dyna
.x_unc
[i
],rjnew
[i
]);
218 copy_rvec(pull
->ref
.x_unc
[0],rjnew
[0]);
220 while (!bConverged
&& n
<max_iter
) {
221 /* loop over all constraints */
222 for (i
=0;(i
<pull
->pull
.n
);i
++) {
225 fprintf(stderr
,"group %d, iteration %d\n",i
,n
);
228 rvec_sub(pull
->dyna
.x_con
[i
],pull
->pull
.x_con
[i
],r_ij
);
229 rvec_sub(rjnew
[i
],rinew
[i
],unc_ij
);
230 rvec_sub(pull
->dyna
.x_ref
[i
],pull
->pull
.x_ref
[i
],ref_ij
);
232 rvec_sub(pull
->ref
.x_con
[0],pull
->pull
.x_con
[i
],r_ij
);
233 rvec_sub(rjnew
[0],rinew
[i
],unc_ij
);
234 rvec_sub(pull
->ref
.x_ref
[0],pull
->pull
.x_ref
[i
],ref_ij
);
237 /* select components we want */
238 for (m
=0;m
<DIM
;m
++) {
239 r_ij
[m
] *= pull
->dims
[m
];
240 unc_ij
[m
] *= pull
->dims
[m
];
241 ref_ij
[m
] *= pull
->dims
[m
];
243 /* correct for PBC. Is this correct? */
244 if (r_ij
[m
] < -0.5*box
[m
][m
]) r_ij
[m
] += box
[m
][m
];
245 if (r_ij
[m
] > 0.5*box
[m
][m
]) r_ij
[m
] -= box
[m
][m
];
246 if (unc_ij
[m
] < -0.5*box
[m
][m
]) unc_ij
[m
] += box
[m
][m
];
247 if (unc_ij
[m
] > 0.5*box
[m
][m
]) unc_ij
[m
] -= box
[m
][m
];
248 if (ref_ij
[m
] < -0.5*box
[m
][m
]) ref_ij
[m
] += box
[m
][m
];
249 if (ref_ij
[m
] > 0.5*box
[m
][m
]) ref_ij
[m
] -= box
[m
][m
];
254 rm
= 1/pull
->pull
.tmass
[i
] + 1/pull
->dyna
.tmass
[i
];
256 rm
= 1/pull
->pull
.tmass
[i
] + 1/pull
->ref
.tmass
[0];
258 a
= iprod(r_ij
,r_ij
)*dt
*dt
*dt
*dt
*rm
*rm
;
259 b
= iprod(unc_ij
,r_ij
)*2*dt
*dt
*rm
;
260 c
= iprod(unc_ij
,unc_ij
) - norm2(ref_ij
);
263 q
= -0.5*(b
-sqrt(b
*b
-4*a
*c
));
265 q
= -0.5*(b
+sqrt(b
*b
-4*a
*c
));
267 lambda
= x1
> 0 ? x1
: x2
;
270 fprintf(stderr
,"\nax^2+bx+c=0: a=%e b=%e c=%e\n"
271 "x1=%e x2=%e sum:%e,%e, lambda:%e\n",a
,b
,c
,x1
,x2
,
272 a
*x1
*x1
+b
*x1
+c
,a
*x2
*x2
+b
*x2
+c
,lambda
);
274 /* the position corrections dr due to the constraint are: */
276 svmul(-dt
*dt
*lambda
/pull
->pull
.tmass
[i
],r_ij
,dr
[i
]);
277 svmul(dt
*dt
*lambda
/pull
->dyna
.tmass
[i
],r_ij
,ref_dr
[i
]);
279 svmul(-dt
*dt
*lambda
/pull
->pull
.tmass
[i
],r_ij
,dr
[i
]);
280 svmul(dt
*dt
*lambda
/pull
->ref
.tmass
[0],r_ij
,ref_dr
[0]);
283 /* and the direction of the constraint force: */
284 direction
[i
] = cos_angle(r_ij
,dr
[i
]);
287 if (pull
->bVerbose
) {
288 fprintf(stderr
,"Direction: %f\n",direction
[i
]);
290 rvec_sub(rinew
[i
],rjnew
[i
],tmp
);
291 rvec_sub(pull
->pull
.x_ref
[i
],pull
->dyna
.x_ref
[i
],tmp2
);
293 rvec_sub(pull
->pull
.x_ref
[i
],pull
->ref
.x_ref
[0],tmp2
);
294 rvec_sub(rinew
[i
],rjnew
[0],tmp
);
296 rvec_sub(dr
[i
],ref_dr
[0],tmp3
);
297 for (m
=0;m
<DIM
;m
++) {
298 tmp
[m
] *= pull
->dims
[m
];
299 tmp2
[m
] *= pull
->dims
[m
];
300 tmp3
[m
] *= pull
->dims
[m
];
301 if (tmp
[m
] < -0.5*box
[m
][m
]) tmp
[m
] += box
[m
][m
];
302 if (tmp
[m
] > 0.5*box
[m
][m
]) tmp
[m
] -= box
[m
][m
];
303 if (tmp2
[m
] < -0.5*box
[m
][m
]) tmp2
[m
] += box
[m
][m
];
304 if (tmp2
[m
] > 0.5*box
[m
][m
]) tmp2
[m
] -= box
[m
][m
];
305 if (tmp3
[m
] < -0.5*box
[m
][m
]) tmp3
[m
] += box
[m
][m
];
306 if (tmp3
[m
] > 0.5*box
[m
][m
]) tmp3
[m
] -= box
[m
][m
];
311 "cur. i:%f %f %f j:%f %f %f d: %f\n"
312 "ref. i:%f %f %f j:%f %f %f d: %f\n"
313 "cor. i:%f %f %f j:%f %f %f d: %f\n",
314 rinew
[i
][0],rinew
[i
][1],rinew
[i
][2],
315 rjnew
[i
][0],rjnew
[i
][1],rjnew
[i
][2], norm(tmp
),
316 pull
->pull
.x_ref
[i
][0],pull
->pull
.x_ref
[i
][1],
317 pull
->pull
.x_ref
[i
][2],pull
->dyna
.x_ref
[i
][0],
318 pull
->dyna
.x_ref
[i
][1],pull
->dyna
.x_ref
[i
][2],
320 dr
[i
][0],dr
[i
][1],dr
[i
][2],
321 ref_dr
[0][0],ref_dr
[0][1],ref_dr
[0][2],
325 "cur. i:%f %f %f j:%f %f %f d: %f\n"
326 "ref. i:%f %f %f j:%f %f %f d: %f\n"
327 "cor. i:%f %f %f j:%f %f %f d: %f\n",
328 rinew
[i
][0],rinew
[i
][1],rinew
[i
][2],
329 rjnew
[0][0],rjnew
[0][1],rjnew
[0][2], norm(tmp
),
330 pull
->pull
.x_ref
[i
][0],pull
->pull
.x_ref
[i
][1],
331 pull
->pull
.x_ref
[i
][2],pull
->ref
.x_ref
[0][0],
332 pull
->ref
.x_ref
[0][1],pull
->ref
.x_ref
[0][2],
334 dr
[i
][0],dr
[i
][1],dr
[i
][2],
335 ref_dr
[0][0],ref_dr
[0][1],ref_dr
[0][2],
339 /* update the positions with dr */
340 rvec_add(rinew
[i
],dr
[i
],rinew
[i
]);
343 rvec_add(rjnew
[i
],ref_dr
[i
],rjnew
[i
]);
345 /* calculate new distance between the two groups */
346 rvec_sub(rjnew
[i
],rinew
[i
],unc_ij
);
348 /* select components and check PBC again */
349 for (m
=0;m
<DIM
;m
++) {
350 unc_ij
[m
] *= pull
->dims
[m
];
351 if (unc_ij
[m
] < -0.5*box
[m
][m
]) unc_ij
[m
] += box
[m
][m
];
352 if (unc_ij
[m
] > 0.5*box
[m
][m
]) unc_ij
[m
] -= box
[m
][m
];
355 rvec_add(rjnew
[0],ref_dr
[0],rjnew
[0]);
357 /* calculate new distance between the two groups */
358 rvec_sub(rjnew
[0],rinew
[i
],unc_ij
);
360 /* select components again and check PBC again */
361 for (m
=0;m
<DIM
;m
++) {
362 unc_ij
[m
] *= pull
->dims
[m
];
363 if (unc_ij
[m
] < -0.5*box
[m
][m
]) unc_ij
[m
] += box
[m
][m
];
364 if (unc_ij
[m
] > 0.5*box
[m
][m
]) unc_ij
[m
] -= box
[m
][m
];
369 /* check if all constraints are fullfilled now */
371 for (i
=0;i
<pull
->pull
.n
;i
++) {
373 rvec_sub(rjnew
[i
],rinew
[i
],unc_ij
);
374 rvec_sub(pull
->dyna
.x_ref
[i
],pull
->pull
.x_ref
[i
],ref_ij
);
376 rvec_sub(rjnew
[0],rinew
[i
],unc_ij
);
377 rvec_sub(pull
->ref
.x_ref
[0],pull
->pull
.x_ref
[i
],ref_ij
);
380 for (m
=0;m
<DIM
;m
++) {
381 ref_ij
[m
] *= pull
->dims
[m
];
382 unc_ij
[m
] *= pull
->dims
[m
];
383 if (unc_ij
[m
] < -0.5*box
[m
][m
]) unc_ij
[m
] += box
[m
][m
];
384 if (unc_ij
[m
] > 0.5*box
[m
][m
]) unc_ij
[m
] -= box
[m
][m
];
385 if (ref_ij
[m
] < -0.5*box
[m
][m
]) ref_ij
[m
] += box
[m
][m
];
386 if (ref_ij
[m
] > 0.5*box
[m
][m
]) ref_ij
[m
] -= box
[m
][m
];
389 bConverged
= bConverged
&& (fabs(norm(unc_ij
)-norm(ref_ij
)) < tol
);
394 if (pull
->bVerbose
) {
396 fprintf(stderr
,"NOT CONVERGED YET: Group %d (%s):"
397 "d_ref = %f, current d = %f\n",
398 i
,pull
->pull
.grps
[i
], norm(ref_ij
),norm(unc_ij
));
403 /* if after all constraints are dealt with and bConverged is still TRUE
404 we're finished, if not we do another iteration */
407 fatal_error(0,"Too many iterations for constraint run");
409 /* DONE ITERATING, NOW UPDATE COORDINATES AND CALC. CONSTRAINT FORCES */
411 /* update the normal groups */
412 for (i
=0;i
<pull
->pull
.n
;i
++) {
413 /* get the final dr and constraint force for group i */
414 rvec_sub(rinew
[i
],pull
->pull
.x_unc
[i
],dr
[i
]);
415 /* select components of dr */
416 for (m
=0;m
<DIM
;m
++) dr
[i
][m
] *= pull
->dims
[m
];
417 svmul(pull
->pull
.tmass
[i
]/(dt
*dt
),dr
[i
],tmp
);
418 /* get the direction of dr */
419 pull
->pull
.f
[i
][ZZ
] = -norm(tmp
)*direction
[i
];
421 /* copy the new x_unc to x_con */
422 copy_rvec(rinew
[i
],pull
->pull
.x_con
[i
]);
424 /* update the atom positions */
426 for (j
=0;j
<pull
->pull
.ngx
[i
];j
++) {
427 ii
= pull
->pull
.idx
[i
][j
];
428 rvec_add(x
[ii
],dr
[i
],x
[ii
]);
429 svmul(md
->massT
[ii
],dr
[i
],tmp
);
430 rvec_add(tmp
,sum
,sum
);
433 fprintf(stderr
,"Group %i: correction %e %e %e\n",
434 i
,sum
[0],sum
[1],sum
[2]);
437 /* update the reference groups */
439 /* update the dynamic reference groups */
440 for (i
=0;i
<pull
->pull
.n
;i
++) {
441 rvec_sub(rjnew
[i
],pull
->dyna
.x_unc
[i
],ref_dr
[i
]);
442 /* copy the new x_unc to x_con */
443 copy_rvec(rjnew
[i
],pull
->dyna
.x_con
[i
]);
444 /* select components of ref_dr */
445 for (m
=0;m
<DIM
;m
++) ref_dr
[i
][m
] *= pull
->dims
[m
];
448 for (j
=0;j
<pull
->dyna
.ngx
[i
];j
++) {
449 /* reset the atoms with dr, weighted by w_i */
450 svmul(pull
->dyna
.weights
[i
][j
],ref_dr
[i
],tmp
);
451 ii
= pull
->dyna
.idx
[i
][j
];
452 rvec_add(x
[ii
],tmp
,x
[ii
]);
453 svmul(md
->massT
[ii
],tmp
,tmp2
);
454 rvec_add(tmp2
,sum
,sum
);
457 fprintf(stderr
,"Dyna grp %i: correction %e %e %e\n",
458 i
,sum
[0],sum
[1],sum
[2]);
461 /* update the reference group */
462 rvec_sub(rjnew
[0],pull
->ref
.x_unc
[0], ref_dr
[0]);
463 /* copy the new x_unc to x_con */
464 copy_rvec(rjnew
[0],pull
->ref
.x_con
[0]);
465 /* select components of ref_dr */
466 for (m
=0;m
<DIM
;m
++) ref_dr
[0][m
] *= pull
->dims
[m
];
469 for (j
=0;j
<pull
->ref
.ngx
[0];j
++) {
470 ii
= pull
->ref
.idx
[0][j
];
471 rvec_add(x
[ii
],ref_dr
[0],x
[ii
]);
472 svmul(md
->massT
[ii
],ref_dr
[0],tmp
);
473 rvec_add(tmp
,sum
,sum
);
476 fprintf(stderr
,"Reference: correction %e %e %e\n",
477 sum
[0],sum
[1],sum
[2]);
481 /* finished! I hope. Give back some memory */
489 /* mimicks an AFM experiment, groups are pulled via a spring */
490 static void do_afm(t_pull
*pull
,rvec
*f
,matrix box
,t_mdatoms
*md
)
494 rvec cm
; /* center of mass displacement of reference */
495 rvec dr
; /* extension of the springs */
497 /* loop over the groups that are being pulled */
498 for (i
=0;i
<pull
->pull
.n
;i
++) {
499 /* compute how far the springs are stretched */
500 for (m
=0;m
<DIM
;m
++) {
501 dr
[m
]=pull
->dims
[m
]*(pull
->pull
.spring
[i
][m
]-pull
->pull
.x_unc
[i
][m
]);
502 while (dr
[m
] > box
[m
][m
]/2) dr
[m
]-=box
[m
][m
];
503 while (dr
[m
] < -box
[m
][m
]/2) dr
[m
]+=box
[m
][m
];
506 /* calculate force from the spring on the pull group: f = - k*dr */
508 pull
->pull
.f
[i
][m
] = pull
->k
*dr
[m
];
510 /* distribute force on com over individual atoms in the group */
511 for (j
=0;j
<pull
->pull
.ngx
[i
];j
++) {
512 ii
= pull
->pull
.idx
[i
][j
];
513 for (m
=0;m
<DIM
;m
++) {
515 f
[ii
][m
] += mi
*(pull
->pull
.f
[i
][m
])/(pull
->pull
.tmass
[i
]);
519 /* move pulling spring along dir, over pull->rate */
521 pull
->pull
.spring
[i
][m
]+=pull
->pull
.dir
[i
][m
]*pull
->rate
;
526 void pull(t_pull
*pull
,rvec
*x
,rvec
*f
,matrix box
, t_topology
*top
,
527 real dt
, int step
, int natoms
, t_mdatoms
*md
)
530 static rvec
*x_s
= NULL
;
533 bShakeFirst
= (f
== NULL
);
536 snew(x_s
,md
->nr
); /* can't rely on natoms */
538 /* copy x to temp array x_s. We assume all molecules are whole already */
539 for (i
=0;i
<md
->nr
;i
++)
540 copy_rvec(x
[i
],x_s
[i
]);
542 switch (pull
->runtype
) {
545 /* calculate center of mass of the pull groups */
546 for (i
=0;i
<pull
->pull
.n
;i
++)
547 (void)calc_com(x_s
,pull
->pull
.ngx
[i
],pull
->pull
.idx
[i
],md
,
548 pull
->pull
.x_unc
[i
],box
);
549 do_afm(pull
,f
,box
,md
);
550 print_afm(pull
,step
);
556 for (i
=0;i
<pull
->pull
.n
;i
++)
557 (void)calc_com(x_s
,pull
->pull
.ngx
[i
],pull
->pull
.idx
[i
],md
,
558 pull
->pull
.x_unc
[i
],box
);
560 make_refgrps(pull
,x_s
,md
);
562 (void)calc_com(x_s
,pull
->ref
.ngx
[0],pull
->ref
.idx
[0],md
,
563 pull
->ref
.x_unc
[0],box
);
564 do_start(pull
,x
,box
,md
,dt
,step
,top
);
565 print_start(pull
,step
);
570 /* if necessary, correct for particles jumping across the box
571 this makes sure pull->ref.x0 has the pbc-corrected coordinates
572 Else just copy the normal coordinates to ref.x0
574 if (pull
->reftype
== eComT0
|| pull
->reftype
== eDynT0
) {
576 fprintf(stderr
,"\nCalling correct_t0_pbc\n");
577 correct_t0_pbc(pull
,x_s
,md
,box
);
579 for (i
=0;i
<pull
->ref
.ngx
[0];i
++)
580 copy_rvec(x_s
[pull
->ref
.idx
[0][i
]],pull
->ref
.x0
[0][i
]);
583 /* get centers of mass for the pull groups. Does this work correctly
585 for (i
=0;i
<pull
->pull
.n
;i
++) {
586 (void)calc_com(x_s
,pull
->pull
.ngx
[i
],pull
->pull
.idx
[i
],md
,
587 pull
->pull
.x_unc
[i
],box
);
590 /* get new centers of mass for reference groups, from the, possibly
591 corrected, pull->ref.x0 */
594 if (step
% pull
->update
== 0) /* make new ones? */
595 make_refgrps(pull
,x_s
,md
);
597 for (i
=0;i
<pull
->pull
.n
;i
++) {
598 (void)calc_com2(pull
->ref
.x0
[0],pull
->dyna
.ngx
[i
],pull
->dyna
.idx
[i
],
599 md
,pull
->dyna
.x_unc
[i
],box
);
601 fprintf(stderr
,"dynacom: %8.3f%8.3f%8.3f\n",pull
->dyna
.x_unc
[i
][0],
602 pull
->dyna
.x_unc
[i
][1],pull
->dyna
.x_unc
[i
][2]);
609 (void)calc_com2(pull
->ref
.x0
[0],pull
->ref
.ngx
[0],pull
->ref
.idx
[0],
610 md
,pull
->ref
.x_unc
[0],box
);
612 /* if necessary, do a running average over the last reflag steps for com */
613 if (pull
->reflag
> 1) {
615 fprintf(stderr
,"Calling calc_running_com\n");
616 calc_running_com(pull
);
619 /* print some debug info if necessary */
620 if (pull
->bVerbose
) {
622 for (i
=0;i
<pull
->pull
.n
;i
++) {
623 fprintf(stderr
,"I :%9.6f %9.6f %9.6f\n",pull
->pull
.x_unc
[i
][0],
624 pull
->pull
.x_unc
[i
][1],pull
->pull
.x_unc
[i
][2]);
625 fprintf(stderr
,"dyna xref: unconstr. com:%9.6f %9.6f %9.6f\n",
626 pull
->dyna
.x_unc
[i
][0],
627 pull
->dyna
.x_unc
[i
][1],pull
->dyna
.x_unc
[i
][2]);
630 fprintf(stderr
,"xref: unconstr. com:%9.6f %9.6f %9.6f\n",
631 pull
->ref
.x_unc
[0][0], pull
->ref
.x_unc
[0][1],
632 pull
->ref
.x_unc
[0][2]);
636 /* do the actual constraint calculation */
637 do_constraint(pull
,x
,box
,md
,dt
);
638 print_constraint(pull
,f
,step
,box
);
643 do_umbrella(pull
,x
,f
,box
,md
);
644 print_umbrella(pull
,step
);
650 /* code to test reference groups, without actually doing anything
653 (void)calc_com(x
,pull
->ref
.ngx
[0],pull
->ref
.idx
[0],
654 md
,pull
->ref
.x_unc
[0],box
);
655 fprintf(stderr
,"ref: %8.3f %8.3f %8.3f\n",pull
->ref
.x_unc
[0][XX
],
656 pull
->ref
.x_unc
[0][YY
],pull
->ref
.x_unc
[0][ZZ
]);
657 correct_t0_pbc(pull
,x
,md
,box
);
658 (void)calc_com2(pull
->ref
.x0
[0],pull
->ref
.ngx
[0],pull
->ref
.idx
[0],
659 md
,pull
->ref
.x_unc
[0],box
);
660 fprintf(stderr
,"ref_t0: %8.3f %8.3f %8.3f\n",pull
->ref
.x_unc
[0][XX
],
661 pull
->ref
.x_unc
[0][YY
],pull
->ref
.x_unc
[0][ZZ
]);
666 fatal_error(0,"undetermined runtype");