4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-2001
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
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 * Do check out http://www.gromacs.org , or mail us at gromacs@gromacs.org .
34 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
36 static char *SRCID_pullutil_c
= "$Id$";
53 #include "pull_internal.h"
55 /* calculates center of mass of selection index from all coordines x */
56 real
calc_com(rvec x
[],int gnx
,atom_id
*index
,t_mdatoms
*md
,
64 for(i
=0; (i
<gnx
); i
++) {
68 for(m
=0; (m
<DIM
); m
++)
72 for(m
=DIM
-1; m
>=0; m
--) {
73 if (com
[m
] < 0 ) rvec_inc(com
,box
[m
]);
74 if (com
[m
] > box
[m
][m
]) rvec_dec(com
,box
[m
]);
80 /* calculates com of all atoms in x[], *index has their index numbers
81 to get the masses from atom[] */
82 real
calc_com2(rvec x
[],int gnx
,atom_id
*index
,t_mdatoms
*md
,rvec com
,
90 for(i
=0; (i
<gnx
); i
++) {
94 for(m
=0; (m
<DIM
); m
++)
98 for(m
=DIM
-1; m
>=0; m
--) {
99 /* next two lines used to be commented out */
100 if (com
[m
] < 0 ) rvec_inc(com
,box
[m
]);
101 if (com
[m
] > box
[m
][m
]) rvec_dec(com
,box
[m
]);
106 void calc_running_com(t_pull
*pull
) {
111 /* for group i, we have nhist[i] points of history. The maximum nr of points
112 is pull->reflag. The array comhist[i][0..nhist[i]-1] has the positions
113 of the center of mass over the last nhist[i] steps. x_unc[i] has the
114 new ones. Remove the oldest one from the list, add the new one, calculate
115 the average, put that in x_unc instead and return. We just move all coms
116 1 down in the list and add the latest one to the top.
120 /* act on dyna groups */
121 for (i
=0;i
<pull
->pull
.n
;i
++) {
123 for (j
=0;j
<(pull
->reflag
-1);j
++) {
124 copy_rvec(pull
->dyna
.comhist
[i
][j
+1],pull
->dyna
.comhist
[i
][j
]);
125 rvec_add(ave
,pull
->dyna
.comhist
[i
][j
],ave
);
127 copy_rvec(pull
->dyna
.x_unc
[i
],pull
->dyna
.comhist
[i
][j
]);
128 rvec_add(ave
,pull
->dyna
.x_unc
[i
],ave
);
129 svmul(1.0/pull
->reflag
,ave
,ave
);
131 /* now ave has the running com for group i, copy it to x_unc[i] */
132 copy_rvec(ave
,pull
->dyna
.x_unc
[i
]);
136 for (n
=0;n
<pull
->reflag
;n
++)
137 fprintf(stderr
,"Comhist %d, grp %d: %8.3f%8.3f%8.3f\n",n
,i
,
138 pull
->dyna
.comhist
[i
][n
][XX
],
139 pull
->dyna
.comhist
[i
][n
][YY
],
140 pull
->dyna
.comhist
[i
][n
][ZZ
]);
144 /* act on ref group */
147 for (j
=0;j
<(pull
->reflag
-1);j
++) {
148 copy_rvec(pull
->ref
.comhist
[0][j
+1],pull
->ref
.comhist
[0][j
]);
149 rvec_add(ave
,pull
->ref
.comhist
[0][j
],ave
);
152 copy_rvec(pull
->ref
.x_unc
[0],pull
->ref
.comhist
[0][j
]);
153 rvec_add(ave
,pull
->ref
.x_unc
[0],ave
);
154 svmul(1.0/pull
->reflag
,ave
,ave
);
155 /* now ave has the running com for group i, copy it to x_unc[0] */
156 copy_rvec(ave
,pull
->ref
.x_unc
[0]);
160 for (i
=0;i
<pull
->reflag
;i
++)
161 fprintf(stderr
,"Comhist %d: %8.3f%8.3f%8.3f\n",i
,
162 pull
->ref
.comhist
[0][i
][XX
],
163 pull
->ref
.comhist
[0][i
][YY
],
164 pull
->ref
.comhist
[0][i
][ZZ
]);
169 void correct_t0_pbc(t_pull
*pull
, rvec x
[], t_mdatoms
*md
, matrix box
) {
174 /* loop over all atoms in index for group i. Check if they moved
175 more than half a box with respect to xp. If so add/subtract a box
176 from x0. Copy x to xp.
178 for (i
=0;i
<pull
->ref
.ngx
[0];i
++) {
179 ii
= pull
->ref
.idx
[0][i
];
181 /* correct for jumps across the box */
182 rvec_sub(x
[ii
],pull
->ref
.xp
[0][i
],dx
);
183 for (m
=DIM
-1; m
>=0; m
--) {
184 if (dx
[m
] < -0.5*box
[m
][m
]) {
186 if (pull
->bVerbose
&& pull
->dims
[m
])
187 fprintf(stderr
,"Jumped +box: nr %d dir: %d old:%8.3f\n",ii
,m
,
188 pull
->ref
.x0
[0][i
][m
]);
191 if (dx
[m
] > 0.5*box
[m
][m
]) {
193 if (pull
->bVerbose
&& pull
->dims
[m
])
194 fprintf(stderr
,"Jumped -box: nr %d dir: %d old:%8.3f\n",ii
,m
,
195 pull
->ref
.x0
[0][i
][m
]);
198 pull
->ref
.x0
[0][i
][m
] += dx
[m
];
199 pull
->ref
.xp
[0][i
][m
] = x
[ii
][m
];
202 tm
= calc_com2(pull
->ref
.x0
[0],pull
->ref
.ngx
[0],pull
->ref
.idx
[0],
205 fprintf(stderr
,"correct_t0: Group %s: mass:%8.3f com:%8.3f%8.3f%8.3f\n",
206 pull
->ref
.grps
[0],tm
,com
[0],com
[1],com
[2]);
209 void string2rvec(char buf
[], rvec nums
) {
211 if (sscanf(buf
,"%f%f%f",&a
,&b
,&c
) != 3)
212 fatal_error(0,"Expected three numbers at input line %s",buf
);
213 nums
[0]=a
; nums
[1]=b
; nums
[2]=c
;
216 /* switch function, x between r and w */
217 real
get_weight(real x
, real r
, real w
) {
218 static bool bFirst
= TRUE
;
219 static real rw
, a0
, a1
, a2
, a3
;
224 a0 = (3*r*w*w-w*w*w)/(rw*rw*rw);
225 a1 = -6*r*w/(rw*rw*rw);
226 a2 = 3*(r+w)/(rw*rw*rw);
237 weight
= -w
/(r
-w
) + x
/(r
-w
);
242 static real
get_cylinder_distance(rvec x
, rvec com
, matrix box
) {
243 /* Triclinic compatible ??? */
244 real dr
, dx
, dy
, boxx
, boxy
;
249 dx
= fabs(x
[XX
] - com
[XX
]);
250 while (dx
> 0.5*boxx
) dx
-= boxx
;
252 dy
= fabs(x
[YY
] - com
[YY
]);
253 while (dy
> 0.5*boxy
) dy
-= boxy
;
255 dr
= sqrt(dx
*dx
+dy
*dy
);
257 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
);
262 void make_refgrps(t_pull
*pull
,matrix box
,t_mdatoms
*md
)
264 int ngrps
,i
,ii
,j
,k
,m
;
265 static bool bFirst
= TRUE
;
270 ngrps
= pull
->pull
.n
;
272 snew(pull
->dyna
.ngx
,ngrps
);
273 snew(pull
->dyna
.idx
,ngrps
);
274 snew(pull
->dyna
.weights
,ngrps
);
275 for (i
=0;i
<ngrps
;i
++) {
276 snew(pull
->dyna
.idx
[i
],pull
->ref
.ngx
[0]); /* more than nessary */
277 snew(pull
->dyna
.weights
[i
],pull
->ref
.ngx
[0]);
282 /* loop over all groups to make a reference group for each*/
283 for (i
=0;i
<ngrps
;i
++) {
286 pull
->dyna
.tmass
[i
] = 0;
287 pull
->dyna
.ngx
[i
] = 0;
289 /* loop over all atoms in the main ref group */
290 for (j
=0;j
<pull
->ref
.ngx
[0];j
++) {
291 ii
= pull
->ref
.idx
[0][j
];
293 /* get_distance takes pbc into account */
294 dr
= get_cylinder_distance(pull
->ref
.x0
[0][j
],pull
->pull
.x_unc
[i
],box
);
297 /* add to index, to sum of COM, to weight array */
298 mass
= md
->massT
[ii
];
301 pull
->dyna
.weights
[i
][k
] = get_weight(dr
,pull
->r
,pull
->rc
);
302 pull
->dyna
.idx
[i
][k
] = ii
;
304 pull
->dyna
.x_unc
[i
][m
] += mass
*pull
->dyna
.weights
[i
][k
]*
305 pull
->ref
.x0
[0][j
][m
];
306 pull
->dyna
.tmass
[i
] += mass
*pull
->dyna
.weights
[i
][k
];
311 /* normalize the new 'x_unc' */
312 svmul(1/pull
->dyna
.tmass
[i
],pull
->dyna
.x_unc
[i
],pull
->dyna
.x_unc
[i
]);
314 fprintf(stderr
,"Made group %d:%8.3f%8.3f%8.3f wm:%8.3f m:%8.3f\n",
315 i
,pull
->dyna
.x_unc
[i
][0],pull
->dyna
.x_unc
[i
][1],
316 pull
->dyna
.x_unc
[i
][2],pull
->dyna
.tmass
[i
],truemass
);