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 * GROwing Monsters And Cloning Shrimps
53 #include "pull_internal.h"
55 void d_pbc_dx(matrix box
,const dvec x1
, const dvec x2
, dvec dx
)
59 /* Not correct for all trilinic boxes !!!
60 Should be as pbc_dx and moved to pbc.c
63 for(m
=DIM
-1; m
>=0; m
--) {
64 while (dx
[m
] < -0.5*box
[m
][m
])
67 while (dx
[m
] >= 0.5*box
[m
][m
])
73 void put_dvec_in_box(matrix box
, dvec v
)
77 for(m
=DIM
-1; m
>=0; m
--) {
81 while (v
[m
] >= box
[m
][m
])
87 /* calculates center of mass of selection index from all coordinates x */
88 void calc_com(t_pullgrp
*pg
, rvec x
[], t_mdatoms
*md
, matrix box
)
95 for(i
=0; i
<pg
->ngx
; i
++) {
101 com
[m
] += wm
*x
[ii
][m
];
104 com
[m
] *= pg
->wscale
/pg
->tmass
;
105 put_dvec_in_box(box
,com
);
106 copy_dvec(com
,pg
->x_unc
);
109 /* calculates com of all atoms in x[], *index has their index numbers
110 to get the masses from atom[] */
111 void calc_com2(t_pullgrp
*pg
, rvec x
[], t_mdatoms
*md
, matrix box
)
118 for(i
=0; i
<pg
->ngx
; i
++) {
124 com
[m
] += wm
*x
[i
][m
];
127 com
[m
] *= pg
->wscale
/pg
->tmass
;
128 put_dvec_in_box(box
,com
);
129 copy_dvec(com
,pg
->x_unc
);
132 void calc_running_com(t_pull
*pull
) {
137 /* for group i, we have nhist[i] points of history. The maximum nr of points
138 is pull->reflag. The array comhist[i][0..nhist[i]-1] has the positions
139 of the center of mass over the last nhist[i] steps. x_unc[i] has the
140 new ones. Remove the oldest one from the list, add the new one, calculate
141 the average, put that in x_unc instead and return. We just move all coms
142 1 down in the list and add the latest one to the top.
146 /* act on dyna groups */
147 for(i
=0;i
<pull
->ngrp
;i
++) {
149 for(j
=0;j
<(pull
->reflag
-1);j
++) {
150 copy_dvec(pull
->dyna
[i
].comhist
[j
+1],pull
->dyna
[i
].comhist
[j
]);
151 dvec_add(ave
,pull
->dyna
[i
].comhist
[j
],ave
);
153 copy_dvec(pull
->dyna
[i
].x_unc
,pull
->dyna
[i
].comhist
[j
]);
154 dvec_add(ave
,pull
->dyna
[i
].x_unc
,ave
);
155 dsvmul(1.0/pull
->reflag
,ave
,ave
);
157 /* now ave has the running com for group i, copy it to x_unc[i] */
158 copy_dvec(ave
,pull
->dyna
[i
].x_unc
);
162 for(n
=0;n
<pull
->reflag
;n
++)
163 fprintf(stderr
,"Comhist %d, grp %d: %8.3f%8.3f%8.3f\n",n
,i
,
164 pull
->dyna
[i
].comhist
[n
][XX
],
165 pull
->dyna
[i
].comhist
[n
][YY
],
166 pull
->dyna
[i
].comhist
[n
][ZZ
]);
170 /* act on ref group */
173 for(j
=0;j
<(pull
->reflag
-1);j
++) {
174 copy_dvec(pull
->ref
.comhist
[j
+1],pull
->ref
.comhist
[j
]);
175 dvec_add(ave
,pull
->ref
.comhist
[j
],ave
);
178 copy_dvec(pull
->ref
.x_unc
,pull
->ref
.comhist
[j
]);
179 dvec_add(ave
,pull
->ref
.x_unc
,ave
);
180 dsvmul(1.0/pull
->reflag
,ave
,ave
);
181 /* now ave has the running com for group i, copy it to x_unc */
182 copy_dvec(ave
,pull
->ref
.x_unc
);
186 for(i
=0;i
<pull
->reflag
;i
++)
187 fprintf(stderr
,"Comhist %d: %8.3f%8.3f%8.3f\n",i
,
188 pull
->ref
.comhist
[i
][XX
],
189 pull
->ref
.comhist
[i
][YY
],
190 pull
->ref
.comhist
[i
][ZZ
]);
195 void correct_t0_pbc(t_pull
*pull
, rvec x
[], t_mdatoms
*md
, matrix box
) {
199 /* loop over all atoms in index for group i. Check if they moved
200 more than half a box with respect to xp. If so add/subtract a box
201 from x0. Copy x to xp.
203 for(i
=0;i
<pull
->ref
.ngx
;i
++) {
204 ii
= pull
->ref
.idx
[i
];
206 /* correct for jumps across the box */
207 pbc_dx(x
[ii
],pull
->ref
.xp
[i
],dx
);
208 for(m
=0; m
<DIM
; m
++) {
209 pull
->ref
.x0
[i
][m
] += dx
[m
];
210 pull
->ref
.xp
[i
][m
] = x
[ii
][m
];
215 /* switch function, x between r and w */
216 real
get_weight(real x
, real r
, real w
) {
218 /* Removed static stuff. Wasn't being used anyway */
219 /* static bool bFirst = TRUE;
220 static real rw, a0, a1, a2, a3; */
226 a0 = (3*r*w*w-w*w*w)/(rw*rw*rw);
227 a1 = -6*r*w/(rw*rw*rw);
228 a2 = 3*(r+w)/(rw*rw*rw);
239 weight
= (w
- x
)/(w
- r
);
244 static double get_cylinder_distance(rvec x
, dvec com
, matrix box
) {
245 /* Triclinic compatible ??? */
246 double dr
, dx
, dy
, boxx
, boxy
;
251 dx
= fabs(x
[XX
] - com
[XX
]);
252 while(dx
> 0.5*boxx
) dx
-= boxx
;
254 dy
= fabs(x
[YY
] - com
[YY
]);
255 while(dy
> 0.5*boxy
) dy
-= boxy
;
257 dr
= sqrt(dx
*dx
+dy
*dy
);
259 fprintf(stderr
,"x:%8.3f%8.3f%8.3f com:%8.3f%8.3f%8.3f dx,dy,dr:%8.3f%8.3f%8.3f\n",x
[0],x
[1],x
[2],com
[0],com
[1],com
[2],dx
,dy
,dr
);
264 void make_refgrps(t_pull
*pull
,matrix box
,t_mdatoms
*md
)
268 double dr
,mass
,wmass
,wwmass
;
272 /* loop over all groups to make a reference group for each*/
273 for(i
=0;i
<pull
->ngrp
;i
++) {
274 pdyna
= &pull
->dyna
[i
];
280 /* loop over all atoms in the main ref group */
281 for(j
=0;j
<pull
->ref
.ngx
;j
++) {
282 ii
= pull
->ref
.idx
[j
];
284 /* get_distance takes pbc into account */
285 dr
= get_cylinder_distance(pull
->ref
.x0
[j
],pull
->grp
[i
].x_unc
,box
);
288 /* add to index, to sum of COM, to weight array */
289 mass
= md
->massT
[ii
];
291 pdyna
->weight
[k
] = get_weight(dr
,pull
->r
,pull
->rc
);
294 pdyna
->x_unc
[m
] += mass
*pdyna
->weight
[k
]*pull
->ref
.x0
[j
][m
];
295 wmass
+= mass
*pdyna
->weight
[k
];
296 wwmass
+= mass
*sqr(pdyna
->weight
[k
]);
301 pdyna
->wscale
= wmass
/wwmass
;
302 pdyna
->tmass
= pdyna
->wscale
*wmass
;
304 /* normalize the new 'x_unc' */
305 dsvmul(1/wmass
,pdyna
->x_unc
,pdyna
->x_unc
);
307 fprintf(stderr
,"Made group %d:%8.3f%8.3f%8.3f m:%8.3f\n",
308 i
,pdyna
->x_unc
[0],pdyna
->x_unc
[1],
309 pdyna
->x_unc
[2],pdyna
->tmass
);