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_pullinit_c
= "$Id$";
51 static void get_pullmemory(t_pullgrps
*pull
, int ngrps
)
53 snew(pull
->ngx
,ngrps
);
54 snew(pull
->x_con
,ngrps
);
55 snew(pull
->xprev
,ngrps
);
56 snew(pull
->tmass
,ngrps
);
57 snew(pull
->idx
,ngrps
);
59 snew(pull
->spring
,ngrps
);
60 snew(pull
->dir
,ngrps
);
61 snew(pull
->x_unc
,ngrps
);
62 snew(pull
->x_ref
,ngrps
);
63 snew(pull
->d_ref
,ngrps
);
66 snew(pull
->comhist
,ngrps
);
69 static void print_info(FILE *log
,t_pull
*pull
)
72 fprintf(log
,"\n**************************************************\n"
74 "**************************************************\n");
76 switch (pull
->runtype
) {
78 fprintf(log
,"RUN TYPE: Generating Starting structures\n");
81 fprintf(log
,"RUN TYPE: Afm\n");
84 fprintf(log
,"RUN TYPE: Constraint\n");
87 fprintf(log
,"RUN TYPE: Umbrella sampling\n");
90 fprintf(log
,"RUN TYPE: Test run\n");
93 fprintf(log
,"RUN TYPE: WARNING! pullinit does not know this runtype\n");
96 if (pull
->runtype
== eConstraint
|| pull
->runtype
== eStart
)
97 switch (pull
->reftype
) {
99 fprintf(log
,"REFERENCE TYPE: center of mass of reference group\n");
103 "REFERENCE TYPE: center of mass of reference group at t=0\n");
107 "REFERENCE TYPE: center of mass of dynamically made groups\n");
108 fprintf(log
,"Using dynamic reference groups: r=%8.3f, rc=%8.3f\n",
113 "REFERENCE TYPE: center of mass of dynamically made groups,\n"
114 "based on the positions of its atoms at t=0\n");
115 fprintf(log
,"Using dynamic reference groups: r=%8.3f, rc=%8.3f\n",
119 fprintf(log
,"REFERENCE TYPE: no clue! What did you do wrong?\n");
123 static void get_named_indexgroup(FILE *log
,atom_id
**target
,int *isize
,
124 char *name
,atom_id
**index
,int ngx
[],
125 char **grpnames
,int ngrps
)
131 fprintf(log
,"Looking for group %s: ",name
);
132 for (i
=0;i
<ngrps
;i
++) {
133 if (!strcmp(name
,grpnames
[i
])) {
134 /* found the group we're looking for */
136 for (j
=0;j
<ngx
[i
];j
++)
140 fprintf(log
,"found group %s: %d elements. First: %d\n",name
,ngx
[i
],
147 fatal_error(0,"Can't find group %s in the index file",name
);
150 static void read_whole_index(char *indexfile
,char ***grpnames
,
151 atom_id
***index
, int **ngx
,int *totalgrps
)
158 fatal_error(0,"No index file specified");
160 grps
= init_index(indexfile
,&gnames
);
162 fatal_error(0,"No groups in indexfile\n");
164 *totalgrps
= grps
->nr
;
165 snew(*index
,grps
->nr
);
166 snew(*grpnames
,grps
->nr
);
167 snew((*ngx
),grps
->nr
);
168 /* memory leak, can't free ngx anymore. 4bytes/group */
170 for(i
=0; (i
<*totalgrps
); i
++) {
171 (*grpnames
)[i
]=strdup(gnames
[i
]);
172 (*ngx
)[i
]=grps
->index
[i
+1]-grps
->index
[i
];
173 snew((*index
)[i
],(*ngx
)[i
]);
174 for(j
=0; (j
<(*ngx
)[i
]); j
++)
175 (*index
)[i
][j
]=grps
->a
[grps
->index
[i
]+j
];
178 for(i
=0; (i
<grps
->nr
); i
++)
185 static void print_whole_index(char **grpnames
, atom_id
**index
, int *ngx
,
191 tmp
= ffopen("indexcheck","w");
192 for (i
=0;i
<ngrps
;i
++) {
193 fprintf(tmp
,"\nGrp %d: %s. %d elements\n",i
,grpnames
[i
],ngx
[i
]);
194 for (j
=0;j
<ngx
[i
];j
++)
195 fprintf(tmp
," %d ",index
[i
][j
]);
200 void init_pull(FILE *log
,int nfile
,t_filenm fnm
[],t_pull
*pull
,rvec
*x
,
201 t_mdatoms
*md
,rvec boxsize
)
211 int totalgrps
; /* total number of groups in the index file */
215 box
[m
][m
]=boxsize
[m
];
217 /* do we have to do any pulling at all? If not return */
218 pull
->bPull
= opt2bSet("-pi",nfile
,fnm
);
219 if (!pull
->bPull
) return;
221 pull
->out
= ffopen(opt2fn("-pd",nfile
,fnm
),"w");
222 read_pullparams(pull
, opt2fn("-pi",nfile
,fnm
), opt2fn("-po",nfile
,fnm
));
223 ngrps
= pull
->pull
.n
;
225 if (pull
->reftype
== eDyn
|| pull
->reftype
== eDynT0
)
230 if (pull
->bCyl
&& (pull
->rc
< 0.01 || pull
->r
< 0.01))
231 fatal_error(0,"rc or r is too small or zero.");
233 print_info(log
,pull
);
235 get_pullmemory(&pull
->pull
,ngrps
);
236 get_pullmemory(&pull
->dyna
,ngrps
);
237 get_pullmemory(&pull
->ref
,1);
239 /* read the whole index file */
240 read_whole_index(opt2fn("-pn",nfile
,fnm
),&grpnames
,&index
,&ngx
,&totalgrps
);
242 if (pull
->bVerbose
) {
243 fprintf(stderr
,"read_whole_index: %d groups total\n",totalgrps
);
244 for(i
=0;i
<totalgrps
;i
++)
245 fprintf(stderr
,"group %i (%s) %d elements\n",
246 i
,grpnames
[i
],ngx
[i
]);
247 /* print_whole_index(grpnames,index,ngx,totalgrps); */
250 /* grab the groups that are specified in the param file */
251 for (i
=0;i
<pull
->pull
.n
;i
++)
252 get_named_indexgroup(log
,&pull
->pull
.idx
[i
],&pull
->pull
.ngx
[i
],
253 pull
->pull
.grps
[i
],index
,ngx
,grpnames
,totalgrps
) ;
254 get_named_indexgroup(log
,&pull
->ref
.idx
[0],&pull
->ref
.ngx
[0],
255 pull
->ref
.grps
[0],index
,ngx
,grpnames
,totalgrps
);
257 /* get more memory! Don't we love C? */
258 snew(pull
->ref
.x0
[0],pull
->ref
.ngx
[0]);
259 snew(pull
->ref
.xp
[0],pull
->ref
.ngx
[0]);
260 snew(pull
->ref
.comhist
[0],pull
->reflag
);
261 for (i
=0;i
<pull
->pull
.n
;i
++)
262 snew(pull
->dyna
.comhist
[i
],pull
->reflag
);
264 for (i
=0;i
<ngrps
;i
++) {
265 tm
= calc_com(x
,pull
->pull
.ngx
[i
],pull
->pull
.idx
[i
],
267 copy_rvec(tmp
,pull
->pull
.x_con
[i
]);
268 copy_rvec(tmp
,pull
->pull
.x_unc
[i
]);
269 copy_rvec(tmp
,pull
->pull
.x_ref
[i
]);
270 copy_rvec(tmp
,pull
->pull
.spring
[i
]);
271 fprintf(log
,"Initializing pull groups. Mass of group %d: %8.3f\n"
272 "Initial coordinates center of mass: %8.3f %8.3f %8.3f\n",
273 i
,tm
,tmp
[XX
],tmp
[YY
],tmp
[ZZ
]);
274 pull
->pull
.tmass
[i
] = tm
;
277 /* initialize the reference group, in all cases */
278 tm
= calc_com(x
,pull
->ref
.ngx
[0],pull
->ref
.idx
[0],md
,
281 copy_rvec(tmp
,pull
->ref
.x_unc
[0]);
282 copy_rvec(tmp
,pull
->ref
.x_con
[0]);
283 copy_rvec(tmp
,pull
->ref
.x_ref
[0]);
285 for (j
=0;j
<pull
->reflag
;j
++)
286 copy_rvec(pull
->ref
.x_unc
[0],pull
->ref
.comhist
[0][j
]);
288 fprintf(log
,"Initializing reference group. Mass: %8.3f\n"
289 "Initial coordinates center of mass: %8.3f %8.3f %8.3f\n",
290 tm
,tmp
[XX
],tmp
[YY
],tmp
[ZZ
]);
291 /* keep the initial coordinates for center of mass at t0 */
292 for (j
=0;j
<pull
->ref
.ngx
[0];j
++) {
293 copy_rvec(x
[pull
->ref
.idx
[0][j
]],pull
->ref
.x0
[0][j
]);
294 copy_rvec(x
[pull
->ref
.idx
[0][j
]],pull
->ref
.xp
[0][j
]);
296 pull
->ref
.tmass
[0] = tm
;
298 /* if we use dynamic reference groups, do some initialising for them */
300 make_refgrps(pull
,x
,md
);
301 for (i
=0;i
<ngrps
;i
++) {
302 copy_rvec(pull
->dyna
.x_unc
[i
],pull
->dyna
.x_con
[i
]);
303 copy_rvec(pull
->dyna
.x_unc
[i
],pull
->dyna
.x_ref
[i
]);
305 /* initialize comhist values for running averages */
306 for (j
=0;j
<pull
->reflag
;j
++)
307 copy_rvec(pull
->dyna
.x_unc
[i
],pull
->dyna
.comhist
[i
][j
]);
309 fprintf(log
,"Initializing dynamic groups. %d atoms. Weighted mass"
311 "Initial coordinates center of mass: %8.3f %8.3f %8.3f\n",
312 pull
->dyna
.ngx
[i
],i
,pull
->dyna
.tmass
[i
],pull
->dyna
.x_ref
[i
][XX
],
313 pull
->dyna
.x_ref
[i
][YY
],pull
->dyna
.x_ref
[i
][ZZ
]);
317 /* set the reference distances and directions, taking into account pbc */
318 for (i
=0;i
<ngrps
;i
++) {
320 rvec_sub(pull
->pull
.x_ref
[i
],pull
->dyna
.x_ref
[i
],tmp
);
321 for (m
=0;m
<DIM
;m
++) {
322 if (tmp
[m
] < -0.5*boxsize
[m
]) tmp
[m
] += boxsize
[m
];
323 if (tmp
[m
] > 0.5*boxsize
[m
]) tmp
[m
] -= boxsize
[m
];
326 rvec_sub(pull
->pull
.x_ref
[i
],pull
->ref
.x_ref
[0],tmp
);
327 for (m
=0;m
<DIM
;m
++) {
328 if (tmp
[m
] < -0.5*boxsize
[m
]) tmp
[m
] += boxsize
[m
];
329 if (tmp
[m
] > 0.5*boxsize
[m
]) tmp
[m
] -= boxsize
[m
];
333 /* reference distance for constraint run */
334 pull
->pull
.d_ref
[i
] = norm(tmp
);
336 /* select elements of direction vector to use for Afm and Start runs */
338 tmp
[m
] = tmp
[m
] * pull
->dims
[m
];
339 svmul(1/norm(tmp
),tmp
,pull
->pull
.dir
[i
]);
341 svmul(-1.0,pull
->pull
.dir
[i
],pull
->pull
.dir
[i
]);
343 if (pull
->runtype
== eAfm
)
344 fprintf(log
,"\nPull rate: %e nm/step. Force constant: %e kJ/(mol nm)",
346 if (pull
->runtype
== eAfm
|| pull
->runtype
== eStart
)
347 fprintf(log
,"\nPull direction: %8.3f %8.3f %8.3f bReverse = %d\n",
348 pull
->pull
.dir
[i
][XX
],pull
->pull
.dir
[i
][YY
],
349 pull
->pull
.dir
[i
][ZZ
],pull
->bReverse
);
352 fprintf(log
,"**************************************************\n"
354 "**************************************************\n\n");