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_pullinit_c
= "$Id$";
55 #include "pull_internal.h"
59 static void get_pullmemory(t_pullgrps
*pull
, int ngrps
)
61 snew(pull
->ngx
,ngrps
);
62 snew(pull
->x_con
,ngrps
);
63 snew(pull
->xprev
,ngrps
);
64 snew(pull
->tmass
,ngrps
);
65 snew(pull
->idx
,ngrps
);
67 snew(pull
->spring
,ngrps
);
68 snew(pull
->dir
,ngrps
);
69 snew(pull
->x_unc
,ngrps
);
70 snew(pull
->x_ref
,ngrps
);
71 snew(pull
->d_ref
,ngrps
);
74 snew(pull
->comhist
,ngrps
);
77 static void print_info(FILE *log
,t_pull
*pull
)
80 fprintf(log
,"\n**************************************************\n"
82 "**************************************************\n");
84 switch (pull
->runtype
) {
86 fprintf(log
,"RUN TYPE: Generating Starting structures\n");
89 fprintf(log
,"RUN TYPE: Afm\n");
92 fprintf(log
,"RUN TYPE: Constraint\n");
95 fprintf(log
,"RUN TYPE: Umbrella sampling\n");
98 fprintf(log
,"RUN TYPE: Test run\n");
101 fprintf(log
,"RUN TYPE: WARNING! pullinit does not know this runtype\n");
104 if (pull
->runtype
== eConstraint
|| pull
->runtype
== eStart
)
105 switch (pull
->reftype
) {
107 fprintf(log
,"REFERENCE TYPE: center of mass of reference group\n");
111 "REFERENCE TYPE: center of mass of reference group at t=0\n");
115 "REFERENCE TYPE: center of mass of dynamically made groups\n");
116 fprintf(log
,"Using dynamic reference groups: r=%8.3f, rc=%8.3f\n",
121 "REFERENCE TYPE: center of mass of dynamically made groups,\n"
122 "based on the positions of its atoms at t=0\n");
123 fprintf(log
,"Using dynamic reference groups: r=%8.3f, rc=%8.3f\n",
127 fprintf(log
,"REFERENCE TYPE: no clue! What did you do wrong?\n");
131 static void get_named_indexgroup(FILE *log
,atom_id
**target
,int *isize
,
132 char *name
,atom_id
**index
,int ngx
[],
133 char **grpnames
,int ngrps
)
139 fprintf(log
,"Looking for group %s: ",name
);
140 for (i
=0;i
<ngrps
;i
++) {
141 if (!strcmp(name
,grpnames
[i
])) {
142 /* found the group we're looking for */
144 for (j
=0;j
<ngx
[i
];j
++)
148 fprintf(log
,"found group %s: %d elements. First: %d\n",name
,ngx
[i
],
155 fatal_error(0,"Can't find group %s in the index file",name
);
158 static void read_whole_index(char *indexfile
,char ***grpnames
,
159 atom_id
***index
, int **ngx
,int *totalgrps
)
166 fatal_error(0,"No index file specified");
168 grps
= init_index(indexfile
,&gnames
);
170 fatal_error(0,"No groups in indexfile\n");
172 *totalgrps
= grps
->nr
;
173 snew(*index
,grps
->nr
);
174 snew(*grpnames
,grps
->nr
);
175 snew((*ngx
),grps
->nr
);
176 /* memory leak, can't free ngx anymore. 4bytes/group */
178 for(i
=0; (i
<*totalgrps
); i
++) {
179 (*grpnames
)[i
]=strdup(gnames
[i
]);
180 (*ngx
)[i
]=grps
->index
[i
+1]-grps
->index
[i
];
181 snew((*index
)[i
],(*ngx
)[i
]);
182 for(j
=0; (j
<(*ngx
)[i
]); j
++)
183 (*index
)[i
][j
]=grps
->a
[grps
->index
[i
]+j
];
186 for(i
=0; (i
<grps
->nr
); i
++)
193 static void print_whole_index(char **grpnames
, atom_id
**index
, int *ngx
,
199 tmp
= ffopen("indexcheck","w");
200 for (i
=0;i
<ngrps
;i
++) {
201 fprintf(tmp
,"\nGrp %d: %s. %d elements\n",i
,grpnames
[i
],ngx
[i
]);
202 for (j
=0;j
<ngx
[i
];j
++)
203 fprintf(tmp
," %d ",index
[i
][j
]);
208 void init_pull(FILE *log
,int nfile
,t_filenm fnm
[],t_pull
*pull
,rvec
*x
,
209 t_mdatoms
*md
,matrix box
)
218 int totalgrps
; /* total number of groups in the index file */
221 /* do we have to do any pulling at all? If not return */
222 pull
->bPull
= opt2bSet("-pi",nfile
,fnm
);
223 if (!pull
->bPull
) return;
225 read_pullparams(pull
, opt2fn("-pi",nfile
,fnm
), opt2fn("-po",nfile
,fnm
));
226 ngrps
= pull
->pull
.n
;
228 /* Do we need to compress the output? */
229 if(pull
->bCompress
) {
230 /* Set pdo file to be gzipped */
231 sprintf(buf
,"/bin/gzip -f -c > %s",opt2fn("-pd",nfile
,fnm
));
232 if((pull
->out
= popen(buf
,"w"))==NULL
)
233 fatal_error(0,"Could not execute %s.",buf
);
236 pull
->out
= ffopen(opt2fn("-pd",nfile
,fnm
),"w");
240 if (pull
->reftype
== eDyn
|| pull
->reftype
== eDynT0
)
245 if (pull
->bCyl
&& (pull
->rc
< 0.01 || pull
->r
< 0.01))
246 fatal_error(0,"rc or r is too small or zero.");
248 print_info(log
,pull
);
250 get_pullmemory(&pull
->pull
,ngrps
);
251 get_pullmemory(&pull
->dyna
,ngrps
);
252 get_pullmemory(&pull
->ref
,1);
254 /* read the whole index file */
255 read_whole_index(opt2fn("-pn",nfile
,fnm
),&grpnames
,&index
,&ngx
,&totalgrps
);
257 if (pull
->bVerbose
) {
258 fprintf(stderr
,"read_whole_index: %d groups total\n",totalgrps
);
259 for(i
=0;i
<totalgrps
;i
++)
260 fprintf(stderr
,"group %i (%s) %d elements\n",
261 i
,grpnames
[i
],ngx
[i
]);
262 /* print_whole_index(grpnames,index,ngx,totalgrps); */
265 /* grab the groups that are specified in the param file */
266 for (i
=0;i
<pull
->pull
.n
;i
++)
267 get_named_indexgroup(log
,&pull
->pull
.idx
[i
],&pull
->pull
.ngx
[i
],
268 pull
->pull
.grps
[i
],index
,ngx
,grpnames
,totalgrps
) ;
269 get_named_indexgroup(log
,&pull
->ref
.idx
[0],&pull
->ref
.ngx
[0],
270 pull
->ref
.grps
[0],index
,ngx
,grpnames
,totalgrps
);
272 /* get more memory! Don't we love C? */
273 snew(pull
->ref
.x0
[0],pull
->ref
.ngx
[0]);
274 snew(pull
->ref
.xp
[0],pull
->ref
.ngx
[0]);
275 snew(pull
->ref
.comhist
[0],pull
->reflag
);
276 for (i
=0;i
<pull
->pull
.n
;i
++)
277 snew(pull
->dyna
.comhist
[i
],pull
->reflag
);
279 for (i
=0;i
<ngrps
;i
++) {
280 tm
= calc_com(x
,pull
->pull
.ngx
[i
],pull
->pull
.idx
[i
],
282 copy_rvec(tmp
,pull
->pull
.x_con
[i
]);
283 copy_rvec(tmp
,pull
->pull
.x_unc
[i
]);
284 copy_rvec(tmp
,pull
->pull
.x_ref
[i
]);
285 copy_rvec(tmp
,pull
->pull
.spring
[i
]);
286 fprintf(log
,"Initializing pull groups. Mass of group %d: %8.3f\n"
287 "Initial coordinates center of mass: %8.3f %8.3f %8.3f\n",
288 i
,tm
,tmp
[XX
],tmp
[YY
],tmp
[ZZ
]);
289 pull
->pull
.tmass
[i
] = tm
;
292 /* initialize the reference group, in all cases */
293 tm
= calc_com(x
,pull
->ref
.ngx
[0],pull
->ref
.idx
[0],md
,
296 copy_rvec(tmp
,pull
->ref
.x_unc
[0]);
297 copy_rvec(tmp
,pull
->ref
.x_con
[0]);
298 copy_rvec(tmp
,pull
->ref
.x_ref
[0]);
300 for (j
=0;j
<pull
->reflag
;j
++)
301 copy_rvec(pull
->ref
.x_unc
[0],pull
->ref
.comhist
[0][j
]);
303 fprintf(log
,"Initializing reference group. Mass: %8.3f\n"
304 "Initial coordinates center of mass: %8.3f %8.3f %8.3f\n",
305 tm
,tmp
[XX
],tmp
[YY
],tmp
[ZZ
]);
306 /* keep the initial coordinates for center of mass at t0 */
307 for (j
=0;j
<pull
->ref
.ngx
[0];j
++) {
308 copy_rvec(x
[pull
->ref
.idx
[0][j
]],pull
->ref
.x0
[0][j
]);
309 copy_rvec(x
[pull
->ref
.idx
[0][j
]],pull
->ref
.xp
[0][j
]);
311 pull
->ref
.tmass
[0] = tm
;
313 /* if we use dynamic reference groups, do some initialising for them */
315 make_refgrps(pull
,x
,md
);
316 for (i
=0;i
<ngrps
;i
++) {
317 copy_rvec(pull
->dyna
.x_unc
[i
],pull
->dyna
.x_con
[i
]);
318 copy_rvec(pull
->dyna
.x_unc
[i
],pull
->dyna
.x_ref
[i
]);
320 /* initialize comhist values for running averages */
321 for (j
=0;j
<pull
->reflag
;j
++)
322 copy_rvec(pull
->dyna
.x_unc
[i
],pull
->dyna
.comhist
[i
][j
]);
324 fprintf(log
,"Initializing dynamic groups. %d atoms. Weighted mass"
326 "Initial coordinates center of mass: %8.3f %8.3f %8.3f\n",
327 pull
->dyna
.ngx
[i
],i
,pull
->dyna
.tmass
[i
],pull
->dyna
.x_ref
[i
][XX
],
328 pull
->dyna
.x_ref
[i
][YY
],pull
->dyna
.x_ref
[i
][ZZ
]);
332 /* set the reference distances and directions, taking into account pbc */
333 for (i
=0;i
<ngrps
;i
++) {
335 rvec_sub(pull
->pull
.x_ref
[i
],pull
->dyna
.x_ref
[i
],tmp
);
337 rvec_sub(pull
->pull
.x_ref
[i
],pull
->ref
.x_ref
[0],tmp
);
338 for (m
=DIM
-1; m
>=0; m
--) {
339 if (tmp
[m
] < -0.5*box
[m
][m
]) rvec_inc(tmp
,box
[m
]);
340 if (tmp
[m
] > 0.5*box
[m
][m
]) rvec_dec(tmp
,box
[m
]);
343 /* reference distance for constraint run */
344 pull
->pull
.d_ref
[i
] = norm(tmp
);
346 /* select elements of direction vector to use for Afm and Start runs */
348 tmp
[m
] = tmp
[m
] * pull
->dims
[m
];
349 svmul(1/norm(tmp
),tmp
,pull
->pull
.dir
[i
]);
351 svmul(-1.0,pull
->pull
.dir
[i
],pull
->pull
.dir
[i
]);
353 if (pull
->runtype
== eAfm
)
354 fprintf(log
,"\nPull rate: %e nm/step. Force constant: %e kJ/(mol nm)",
356 if (pull
->runtype
== eAfm
|| pull
->runtype
== eStart
)
357 fprintf(log
,"\nPull direction: %8.3f %8.3f %8.3f bReverse = %d\n",
358 pull
->pull
.dir
[i
][XX
],pull
->pull
.dir
[i
][YY
],
359 pull
->pull
.dir
[i
][ZZ
],pull
->bReverse
);
362 fprintf(log
,"**************************************************\n"
364 "**************************************************\n\n");
365 print_pull_header(pull
);