2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
52 #include "gmx_fatal.h"
64 static char pulldim[STRLEN];
66 static void string2dvec(char buf[], dvec nums)
68 if (sscanf(buf,"%lf%lf%lf",&nums[0],&nums[1],&nums[2]) != 3)
69 gmx_fatal(FARGS,"Expected three numbers at input line %s",buf);
72 static void init_pullgrp(t_pullgrp *pg,char *wbuf,
73 gmx_bool bRef,int eGeom,char *s_vec)
80 while (sscanf(wbuf,"%lf %n",&d,&n) == 1) {
81 if (pg->nweight % 100 == 0) {
82 srenew(pg->weight,pg->nweight+100);
84 pg->weight[pg->nweight++] = d;
88 if (eGeom == epullgDIST) {
91 string2dvec(s_vec,vec);
92 if (eGeom == epullgDIR || eGeom == epullgCYL ||
93 (eGeom == epullgPOS && dnorm(vec) != 0))
94 /* Normalize the direction vector */
95 dsvmul(1/dnorm(vec),vec,vec);
102 char **read_pullparams(int *ninp_p,t_inpfile **inp_p,
103 t_pull *pull,gmx_bool *bStart,
106 int ninp,nerror=0,i,nchar,ndim,nscan,m;
110 char dummy[STRLEN],buf[STRLEN],init[STRLEN];
111 const char *init_def1="0.0",*init_def3="0.0 0.0 0.0";
112 char wbuf[STRLEN],VecTemp[STRLEN];
120 /* read pull parameters */
121 CTYPE("Pull geometry: distance, direction, cylinder or position");
122 EETYPE("pull_geometry", pull->eGeom, epullg_names);
123 CTYPE("Select components for the pull vector. default: Y Y Y");
124 STYPE("pull_dim", pulldim, "Y Y Y");
125 CTYPE("Cylinder radius for dynamic reaction force groups (nm)");
126 RTYPE("pull_r1", pull->cyl_r1, 1.0);
127 CTYPE("Switch from r1 to r0 in case of dynamic reaction force");
128 RTYPE("pull_r0", pull->cyl_r0, 1.5);
129 RTYPE("pull_constr_tol", pull->constr_tol, 1E-6);
130 EETYPE("pull_start", *bStart, yesno_names);
131 ITYPE("pull_nstxout", pull->nstxout, 10);
132 ITYPE("pull_nstfout", pull->nstfout, 1);
133 CTYPE("Number of pull groups");
134 ITYPE("pull_ngroups", pull->ngrp,1);
136 if (pull->cyl_r1 > pull->cyl_r0) {
137 warning_error(wi,"pull_r1 > pull_r0");
140 if (pull->ngrp < 1) {
141 gmx_fatal(FARGS,"pull_ngroups should be >= 1");
144 snew(pull->grp,pull->ngrp+1);
146 if (pull->eGeom == epullgPOS) {
152 /* pull group options */
153 CTYPE("Group name, weight (default all 1), vector, init, rate (nm/ps), kJ/(mol*nm^2)");
154 /* Read the pull groups */
155 snew(grpbuf,pull->ngrp+1);
156 for(i=0; i<pull->ngrp+1; i++) {
157 pgrp = &pull->grp[i];
158 snew(grpbuf[i],STRLEN);
159 sprintf(buf,"pull_group%d",i);
160 STYPE(buf, grpbuf[i], "");
161 sprintf(buf,"pull_weights%d",i);
162 STYPE(buf, wbuf, "");
163 sprintf(buf,"pull_pbcatom%d",i);
164 ITYPE(buf, pgrp->pbcatom, 0);
166 sprintf(buf,"pull_vec%d",i);
167 STYPE(buf, VecTemp, "0.0 0.0 0.0");
168 sprintf(buf,"pull_init%d",i);
169 STYPE(buf, init, ndim==1 ? init_def1 : init_def3);
170 nscan = sscanf(init,"%lf %lf %lf",&vec[0],&vec[1],&vec[2]);
172 fprintf(stderr,"ERROR: %s should have %d components\n",buf,ndim);
175 for(m=0; m<DIM; m++) {
176 pgrp->init[m] = (m<ndim ? vec[m] : 0.0);
178 sprintf(buf,"pull_rate%d",i);
179 RTYPE(buf, pgrp->rate, 0.0);
180 sprintf(buf,"pull_k%d",i);
181 RTYPE(buf, pgrp->k, 0.0);
182 sprintf(buf,"pull_kB%d",i);
183 RTYPE(buf, pgrp->kB, pgrp->k);
186 /* Initialize the pull group */
187 init_pullgrp(pgrp,wbuf,i==0,pull->eGeom,VecTemp);
196 void make_pull_groups(t_pull *pull,char **pgnames,t_blocka *grps,char **gnames)
198 int d,nchar,g,ig=-1,i;
199 char *ptr,pulldim1[STRLEN];
204 for(d=0; d<DIM; d++) {
205 if (sscanf(ptr,"%s%n",pulldim1,&nchar) != 1)
206 gmx_fatal(FARGS,"Less than 3 pull dimensions given in pull_dim: '%s'",
209 if (gmx_strncasecmp(pulldim1,"N",1) == 0) {
211 } else if (gmx_strncasecmp(pulldim1,"Y",1) == 0) {
215 gmx_fatal(FARGS,"Please use Y(ES) or N(O) for pull_dim only (not %s)",
221 gmx_fatal(FARGS,"All entries in pull_dim are N");
223 for(g=0; g<pull->ngrp+1; g++) {
224 pgrp = &pull->grp[g];
225 if (g == 0 && strcmp(pgnames[g],"") == 0) {
228 ig = search_string(pgnames[g],grps->nr,gnames);
229 pgrp->nat = grps->index[ig+1] - grps->index[ig];
232 fprintf(stderr,"Pull group %d '%s' has %d atoms\n",
233 g,pgnames[g],pgrp->nat);
234 snew(pgrp->ind,pgrp->nat);
235 for(i=0; i<pgrp->nat; i++)
236 pgrp->ind[i] = grps->a[grps->index[ig]+i];
238 if (pull->eGeom == epullgCYL && g == 0 && pgrp->nweight > 0)
239 gmx_fatal(FARGS,"Weights are not supported for the reference group with cylinder pulling");
240 if (pgrp->nweight > 0 && pgrp->nweight != pgrp->nat)
241 gmx_fatal(FARGS,"Number of weights (%d) for pull group %d '%s' does not match the number of atoms (%d)",
242 pgrp->nweight,g,pgnames[g],pgrp->nat);
244 if (pgrp->nat == 1) {
245 /* No pbc is required for this group */
248 if (pgrp->pbcatom > 0) {
250 } else if (pgrp->pbcatom == 0) {
251 pgrp->pbcatom = pgrp->ind[(pgrp->nat-1)/2];
253 /* Use cosine weighting */
258 if (g > 0 && pull->eGeom != epullgDIST) {
259 for(d=0; d<DIM; d++) {
260 if (pgrp->vec[d] != 0 && pull->dim[d] == 0) {
261 gmx_fatal(FARGS,"ERROR: pull_vec%d has non-zero %c-component while pull_dim in N\n",g,'x'+d);
266 if ((pull->eGeom == epullgDIR || pull->eGeom == epullgCYL) &&
267 g > 0 && norm2(pgrp->vec) == 0)
268 gmx_fatal(FARGS,"pull_vec%d can not be zero with geometry %s",
269 g,EPULLGEOM(pull->eGeom));
270 if ((pull->eGeom == epullgPOS) && pgrp->rate != 0 &&
271 g > 0 && norm2(pgrp->vec) == 0)
272 gmx_fatal(FARGS,"pull_vec%d can not be zero with geometry %s and non-zero rate",
273 g,EPULLGEOM(pull->eGeom));
276 if (pull->eGeom == epullgCYL)
277 gmx_fatal(FARGS,"Absolute reference groups are not supported with geometry %s",EPULLGEOM(pull->eGeom));
279 gmx_fatal(FARGS,"Pull group %d '%s' is empty",g,pgnames[g]);
286 void set_pull_init(t_inputrec *ir,gmx_mtop_t *mtop,rvec *x,matrix box,real lambda,
287 const output_env_t oenv,gmx_bool bStart)
294 double t_start,tinvrate;
298 init_pull(NULL,ir,0,NULL,mtop,NULL,oenv,lambda,FALSE,0);
299 md = init_mdatoms(NULL,mtop,ir->efep);
300 atoms2md(mtop,ir,0,NULL,0,mtop->natoms,md);
303 update_mdatoms(md,lambda);
306 if (pull->eGeom == epullgPOS)
311 set_pbc(&pbc,ir->ePBC,box);
313 t_start = ir->init_t + ir->init_step*ir->delta_t;
315 pull_calc_coms(NULL,pull,md,&pbc,t_start,x,NULL);
317 fprintf(stderr,"Pull group natoms pbc atom distance at start reference at t=0\n");
318 for(g=0; g<pull->ngrp+1; g++) {
319 pgrp = &pull->grp[g];
320 fprintf(stderr,"%8d %8d %8d ",g,pgrp->nat,pgrp->pbcatom+1);
321 copy_rvec(pgrp->init,init);
322 clear_rvec(pgrp->init);
327 tinvrate = t_start/pgrp->rate;
328 get_pullgrp_distance(pull,&pbc,g,0,dr,dev);
329 for(m=0; m<DIM; m++) {
331 fprintf(stderr," %6.3f",dev[m]);
336 for(m=0; m<DIM; m++) {
338 pgrp->init[m] = init[m] + dev[m]
339 - tinvrate*(pull->eGeom==epullgPOS ? pgrp->vec[m] : 1);
341 pgrp->init[m] = init[m];
343 fprintf(stderr," %6.3f",pgrp->init[m]);
348 fprintf(stderr,"\n");