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 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
44 #include "gromacs/utility/futil.h"
46 #include "types/commrec.h"
50 #include "gromacs/pbcutil/pbc.h"
51 #include "gromacs/topology/mtop_util.h"
53 #include "gmx_ga2la.h"
57 #include "gromacs/fileio/filenm.h"
58 #include "gromacs/fileio/gmxfio.h"
59 #include "gromacs/fileio/xvgr.h"
60 #include "gromacs/math/vec.h"
61 #include "gromacs/utility/smalloc.h"
63 static void pull_print_group_x(FILE *out
, ivec dim
, const t_pull_group
*pgrp
)
67 for (m
= 0; m
< DIM
; m
++)
71 fprintf(out
, "\t%g", pgrp
->x
[m
]);
76 static void pull_print_coord_dr(FILE *out
, ivec dim
, const t_pull_coord
*pcrd
)
80 for (m
= 0; m
< DIM
; m
++)
84 fprintf(out
, "\t%g", pcrd
->dr
[m
]);
89 static void pull_print_x(FILE *out
, t_pull
*pull
, double t
)
92 const t_pull_coord
*pcrd
;
94 fprintf(out
, "%.4f", t
);
96 for (c
= 0; c
< pull
->ncoord
; c
++)
98 pcrd
= &pull
->coord
[c
];
104 pull_print_group_x(out
, pull
->dim
, &pull
->dyna
[c
]);
108 pull_print_group_x(out
, pull
->dim
, &pull
->group
[pcrd
->group
[0]]);
111 pull_print_coord_dr(out
, pull
->dim
, pcrd
);
116 static void pull_print_f(FILE *out
, t_pull
*pull
, double t
)
120 fprintf(out
, "%.4f", t
);
122 for (c
= 0; c
< pull
->ncoord
; c
++)
124 fprintf(out
, "\t%g", pull
->coord
[c
].f_scal
);
129 void pull_print_output(t_pull
*pull
, gmx_int64_t step
, double time
)
131 if ((pull
->nstxout
!= 0) && (step
% pull
->nstxout
== 0))
133 pull_print_x(pull
->out_x
, pull
, time
);
136 if ((pull
->nstfout
!= 0) && (step
% pull
->nstfout
== 0))
138 pull_print_f(pull
->out_f
, pull
, time
);
142 static FILE *open_pull_out(const char *fn
, t_pull
*pull
, const output_env_t oenv
,
143 gmx_bool bCoord
, unsigned long Flags
)
147 char **setname
, buf
[10];
149 if (Flags
& MD_APPENDFILES
)
151 fp
= gmx_fio_fopen(fn
, "a+");
155 fp
= gmx_fio_fopen(fn
, "w+");
158 xvgr_header(fp
, "Pull COM", "Time (ps)", "Position (nm)",
163 xvgr_header(fp
, "Pull force", "Time (ps)", "Force (kJ/mol/nm)",
167 snew(setname
, 2*pull
->ncoord
*DIM
);
169 for (c
= 0; c
< pull
->ncoord
; c
++)
175 for (m
= 0; m
< DIM
; m
++)
179 sprintf(buf
, "%d %s%c", c
+1, "c", 'X'+m
);
180 setname
[nsets
] = strdup(buf
);
185 for (m
= 0; m
< DIM
; m
++)
189 sprintf(buf
, "%d %s%c", c
+1, "d", 'X'+m
);
190 setname
[nsets
] = strdup(buf
);
197 sprintf(buf
, "%d", c
+1);
198 setname
[nsets
] = strdup(buf
);
204 xvgr_legend(fp
, nsets
, (const char**)setname
, oenv
);
206 for (c
= 0; c
< nsets
; c
++)
216 /* Apply forces in a mass weighted fashion */
217 static void apply_forces_grp(const t_pull_group
*pgrp
, const t_mdatoms
*md
,
218 const dvec f_pull
, int sign
, rvec
*f
)
221 double wmass
, inv_wm
;
223 inv_wm
= pgrp
->wscale
*pgrp
->invtm
;
225 for (i
= 0; i
< pgrp
->nat_loc
; i
++)
227 ii
= pgrp
->ind_loc
[i
];
228 wmass
= md
->massT
[ii
];
229 if (pgrp
->weight_loc
)
231 wmass
*= pgrp
->weight_loc
[i
];
234 for (m
= 0; m
< DIM
; m
++)
236 f
[ii
][m
] += sign
* wmass
* f_pull
[m
] * inv_wm
;
241 /* Apply forces in a mass weighted fashion */
242 static void apply_forces(t_pull
* pull
, t_mdatoms
* md
, rvec
*f
)
245 const t_pull_coord
*pcrd
;
247 for (c
= 0; c
< pull
->ncoord
; c
++)
249 pcrd
= &pull
->coord
[c
];
253 apply_forces_grp(&pull
->dyna
[c
], md
, pcrd
->f
, -1, f
);
257 if (pull
->group
[pcrd
->group
[0]].nat
> 0)
259 apply_forces_grp(&pull
->group
[pcrd
->group
[0]], md
, pcrd
->f
, -1, f
);
262 apply_forces_grp(&pull
->group
[pcrd
->group
[1]], md
, pcrd
->f
, 1, f
);
266 static double max_pull_distance2(const t_pull
*pull
, const t_pbc
*pbc
)
271 max_d2
= GMX_DOUBLE_MAX
;
273 if (pull
->eGeom
!= epullgDIRPBC
)
275 for (m
= 0; m
< pbc
->ndim_ePBC
; m
++)
277 if (pull
->dim
[m
] != 0)
279 max_d2
= min(max_d2
, norm2(pbc
->box
[m
]));
287 static void low_get_pull_coord_dr(const t_pull
*pull
,
288 const t_pull_coord
*pcrd
,
289 const t_pbc
*pbc
, double t
,
290 dvec xg
, dvec xref
, double max_dist2
,
293 const t_pull_group
*pgrp0
, *pgrp1
;
295 dvec xrefr
, dref
= {0, 0, 0};
298 pgrp0
= &pull
->group
[pcrd
->group
[0]];
299 pgrp1
= &pull
->group
[pcrd
->group
[1]];
301 /* Only the first group can be an absolute reference, in that case nat=0 */
304 for (m
= 0; m
< DIM
; m
++)
306 xref
[m
] = pcrd
->origin
[m
];
310 copy_dvec(xref
, xrefr
);
312 if (pull
->eGeom
== epullgDIRPBC
)
314 for (m
= 0; m
< DIM
; m
++)
316 dref
[m
] = (pcrd
->init
+ pcrd
->rate
*t
)*pcrd
->vec
[m
];
318 /* Add the reference position, so we use the correct periodic image */
319 dvec_inc(xrefr
, dref
);
322 pbc_dx_d(pbc
, xg
, xrefr
, dr
);
324 for (m
= 0; m
< DIM
; m
++)
326 dr
[m
] *= pull
->dim
[m
];
329 if (max_dist2
>= 0 && dr2
> 0.98*0.98*max_dist2
)
331 gmx_fatal(FARGS
, "Distance between pull groups %d and %d (%f nm) is larger than 0.49 times the box size (%f).\nYou might want to consider using \"pull-geometry = direction-periodic\" instead.\n",
332 pcrd
->group
[0], pcrd
->group
[1], sqrt(dr2
), sqrt(max_dist2
));
335 if (pull
->eGeom
== epullgDIRPBC
)
341 static void get_pull_coord_dr(const t_pull
*pull
,
343 const t_pbc
*pbc
, double t
,
347 const t_pull_coord
*pcrd
;
349 if (pull
->eGeom
== epullgDIRPBC
)
355 md2
= max_pull_distance2(pull
, pbc
);
358 pcrd
= &pull
->coord
[coord_ind
];
360 low_get_pull_coord_dr(pull
, pcrd
, pbc
, t
,
361 pull
->group
[pcrd
->group
[1]].x
,
362 PULL_CYL(pull
) ? pull
->dyna
[coord_ind
].x
: pull
->group
[pcrd
->group
[0]].x
,
367 void get_pull_coord_distance(const t_pull
*pull
,
369 const t_pbc
*pbc
, double t
,
370 dvec dr
, double *dev
)
372 static gmx_bool bWarned
= FALSE
; /* TODO: this should be fixed for thread-safety,
373 but is fairly benign */
374 const t_pull_coord
*pcrd
;
376 double ref
, drs
, inpr
;
378 pcrd
= &pull
->coord
[coord_ind
];
380 get_pull_coord_dr(pull
, coord_ind
, pbc
, t
, dr
);
382 ref
= pcrd
->init
+ pcrd
->rate
*t
;
387 /* Pull along the vector between the com's */
388 if (ref
< 0 && !bWarned
)
390 fprintf(stderr
, "\nPull reference distance for coordinate %d is negative (%f)\n", coord_ind
+1, ref
);
396 /* With no vector we can not determine the direction for the force,
397 * so we set the force to zero.
403 /* Determine the deviation */
412 for (m
= 0; m
< DIM
; m
++)
414 inpr
+= pcrd
->vec
[m
]*dr
[m
];
421 void clear_pull_forces(t_pull
*pull
)
425 /* Zeroing the forces is only required for constraint pulling.
426 * It can happen that multiple constraint steps need to be applied
427 * and therefore the constraint forces need to be accumulated.
429 for (i
= 0; i
< pull
->ncoord
; i
++)
431 clear_dvec(pull
->coord
[i
].f
);
432 pull
->coord
[i
].f_scal
= 0;
436 /* Apply constraint using SHAKE */
437 static void do_constraint(t_pull
*pull
, t_pbc
*pbc
,
439 gmx_bool bMaster
, tensor vir
,
443 dvec
*r_ij
; /* x[i] com of i in prev. step. Obeys constr. -> r_ij[i] */
444 dvec unc_ij
; /* xp[i] com of i this step, before constr. -> unc_ij */
445 dvec
*rnew
; /* current 'new' positions of the groups */
446 double *dr_tot
; /* the total update of the coords */
450 double lambda
, rm
, mass
, invdt
= 0;
451 gmx_bool bConverged_all
, bConverged
= FALSE
;
452 int niter
= 0, g
, c
, ii
, j
, m
, max_iter
= 100;
454 dvec f
; /* the pull force */
456 t_pull_group
*pdyna
, *pgrp0
, *pgrp1
;
459 snew(r_ij
, pull
->ncoord
);
460 snew(dr_tot
, pull
->ncoord
);
462 snew(rnew
, pull
->ngroup
);
464 /* copy the current unconstrained positions for use in iterations. We
465 iterate until rinew[i] and rjnew[j] obey the constraints. Then
466 rinew - pull.x_unc[i] is the correction dr to group i */
467 for (g
= 0; g
< pull
->ngroup
; g
++)
469 copy_dvec(pull
->group
[g
].xp
, rnew
[g
]);
473 /* There is only one pull coordinate and reference group */
474 copy_dvec(pull
->dyna
[0].xp
, rnew
[pull
->coord
[0].group
[0]]);
477 /* Determine the constraint directions from the old positions */
478 for (c
= 0; c
< pull
->ncoord
; c
++)
480 get_pull_coord_dr(pull
, c
, pbc
, t
, r_ij
[c
]);
481 /* Store the difference vector at time t for printing */
482 copy_dvec(r_ij
[c
], pull
->coord
[c
].dr
);
485 fprintf(debug
, "Pull coord %d dr %f %f %f\n",
486 c
, r_ij
[c
][XX
], r_ij
[c
][YY
], r_ij
[c
][ZZ
]);
489 if (pull
->eGeom
== epullgDIR
|| pull
->eGeom
== epullgDIRPBC
)
491 /* Select the component along vec */
493 for (m
= 0; m
< DIM
; m
++)
495 a
+= pull
->coord
[c
].vec
[m
]*r_ij
[c
][m
];
497 for (m
= 0; m
< DIM
; m
++)
499 r_ij
[c
][m
] = a
*pull
->coord
[c
].vec
[m
];
504 bConverged_all
= FALSE
;
505 while (!bConverged_all
&& niter
< max_iter
)
507 bConverged_all
= TRUE
;
509 /* loop over all constraints */
510 for (c
= 0; c
< pull
->ncoord
; c
++)
514 pcrd
= &pull
->coord
[c
];
515 pgrp0
= &pull
->group
[pcrd
->group
[0]];
516 pgrp1
= &pull
->group
[pcrd
->group
[1]];
518 /* Get the current difference vector */
519 low_get_pull_coord_dr(pull
, pcrd
, pbc
, t
,
520 rnew
[pcrd
->group
[1]],
521 rnew
[pcrd
->group
[0]],
524 ref
= pcrd
->init
+ pcrd
->rate
*t
;
528 fprintf(debug
, "Pull coord %d, iteration %d\n", c
, niter
);
531 rm
= 1.0/(pgrp0
->invtm
+ pgrp1
->invtm
);
538 gmx_fatal(FARGS
, "The pull constraint reference distance for group %d is <= 0 (%f)", c
, ref
);
542 double q
, c_a
, c_b
, c_c
;
544 c_a
= diprod(r_ij
[c
], r_ij
[c
]);
545 c_b
= diprod(unc_ij
, r_ij
[c
])*2;
546 c_c
= diprod(unc_ij
, unc_ij
) - dsqr(ref
);
550 q
= -0.5*(c_b
- sqrt(c_b
*c_b
- 4*c_a
*c_c
));
555 q
= -0.5*(c_b
+ sqrt(c_b
*c_b
- 4*c_a
*c_c
));
562 "Pull ax^2+bx+c=0: a=%e b=%e c=%e lambda=%e\n",
563 c_a
, c_b
, c_c
, lambda
);
567 /* The position corrections dr due to the constraints */
568 dsvmul(-lambda
*rm
*pgrp1
->invtm
, r_ij
[c
], dr1
);
569 dsvmul( lambda
*rm
*pgrp0
->invtm
, r_ij
[c
], dr0
);
570 dr_tot
[c
] += -lambda
*dnorm(r_ij
[c
]);
575 /* A 1-dimensional constraint along a vector */
577 for (m
= 0; m
< DIM
; m
++)
579 vec
[m
] = pcrd
->vec
[m
];
580 a
+= unc_ij
[m
]*vec
[m
];
582 /* Select only the component along the vector */
583 dsvmul(a
, vec
, unc_ij
);
587 fprintf(debug
, "Pull inpr %e lambda: %e\n", a
, lambda
);
590 /* The position corrections dr due to the constraints */
591 dsvmul(-lambda
*rm
*pgrp1
->invtm
, vec
, dr1
);
592 dsvmul( lambda
*rm
*pgrp0
->invtm
, vec
, dr0
);
593 dr_tot
[c
] += -lambda
;
604 low_get_pull_coord_dr(pull
, pcrd
, pbc
, t
, rnew
[g1
], rnew
[g0
], -1, tmp
);
605 low_get_pull_coord_dr(pull
, pcrd
, pbc
, t
, dr1
, dr0
, -1, tmp3
);
607 "Pull cur %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
608 rnew
[g0
][0], rnew
[g0
][1], rnew
[g0
][2],
609 rnew
[g1
][0], rnew
[g1
][1], rnew
[g1
][2], dnorm(tmp
));
611 "Pull ref %8s %8s %8s %8s %8s %8s d: %8.5f\n",
612 "", "", "", "", "", "", ref
);
614 "Pull cor %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
615 dr0
[0], dr0
[1], dr0
[2],
616 dr1
[0], dr1
[1], dr1
[2],
620 /* Update the COMs with dr */
621 dvec_inc(rnew
[pcrd
->group
[1]], dr1
);
622 dvec_inc(rnew
[pcrd
->group
[0]], dr0
);
625 /* Check if all constraints are fullfilled now */
626 for (c
= 0; c
< pull
->ncoord
; c
++)
628 pcrd
= &pull
->coord
[c
];
629 ref
= pcrd
->init
+ pcrd
->rate
*t
;
631 low_get_pull_coord_dr(pull
, pcrd
, pbc
, t
,
632 rnew
[pcrd
->group
[1]],
633 rnew
[pcrd
->group
[0]],
639 bConverged
= fabs(dnorm(unc_ij
) - ref
) < pull
->constr_tol
;
644 for (m
= 0; m
< DIM
; m
++)
646 vec
[m
] = pcrd
->vec
[m
];
648 inpr
= diprod(unc_ij
, vec
);
649 dsvmul(inpr
, vec
, unc_ij
);
651 fabs(diprod(unc_ij
, vec
) - ref
) < pull
->constr_tol
;
659 fprintf(debug
, "NOT CONVERGED YET: Group %d:"
660 "d_ref = %f, current d = %f\n",
661 g
, ref
, dnorm(unc_ij
));
664 bConverged_all
= FALSE
;
669 /* if after all constraints are dealt with and bConverged is still TRUE
670 we're finished, if not we do another iteration */
672 if (niter
> max_iter
)
674 gmx_fatal(FARGS
, "Too many iterations for constraint run: %d", niter
);
677 /* DONE ITERATING, NOW UPDATE COORDINATES AND CALC. CONSTRAINT FORCES */
684 /* update atoms in the groups */
685 for (g
= 0; g
< pull
->ngroup
; g
++)
687 const t_pull_group
*pgrp
;
690 if (PULL_CYL(pull
) && g
== pull
->coord
[0].group
[0])
692 pgrp
= &pull
->dyna
[0];
696 pgrp
= &pull
->group
[g
];
699 /* get the final constraint displacement dr for group g */
700 dvec_sub(rnew
[g
], pgrp
->xp
, dr
);
701 /* select components of dr */
702 for (m
= 0; m
< DIM
; m
++)
704 dr
[m
] *= pull
->dim
[m
];
707 /* update the atom positions */
709 for (j
= 0; j
< pgrp
->nat_loc
; j
++)
711 ii
= pgrp
->ind_loc
[j
];
712 if (pgrp
->weight_loc
)
714 dsvmul(pgrp
->wscale
*pgrp
->weight_loc
[j
], dr
, tmp
);
716 for (m
= 0; m
< DIM
; m
++)
722 for (m
= 0; m
< DIM
; m
++)
724 v
[ii
][m
] += invdt
*tmp
[m
];
730 /* calculate the constraint forces, used for output and virial only */
731 for (c
= 0; c
< pull
->ncoord
; c
++)
733 pcrd
= &pull
->coord
[c
];
734 pcrd
->f_scal
= dr_tot
[c
]/((pull
->group
[pcrd
->group
[0]].invtm
+ pull
->group
[pcrd
->group
[1]].invtm
)*dt
*dt
);
740 /* Add the pull contribution to the virial */
741 f_invr
= pcrd
->f_scal
/dnorm(r_ij
[c
]);
743 for (j
= 0; j
< DIM
; j
++)
745 for (m
= 0; m
< DIM
; m
++)
747 vir
[j
][m
] -= 0.5*f_invr
*r_ij
[c
][j
]*r_ij
[c
][m
];
753 /* finished! I hope. Give back some memory */
759 /* Pulling with a harmonic umbrella potential or constant force */
760 static void do_pull_pot(int ePull
,
761 t_pull
*pull
, t_pbc
*pbc
, double t
, real lambda
,
762 real
*V
, tensor vir
, real
*dVdl
)
765 double dev
, ndr
, invdr
;
769 /* loop over the pull coordinates */
772 for (c
= 0; c
< pull
->ncoord
; c
++)
774 pcrd
= &pull
->coord
[c
];
776 get_pull_coord_distance(pull
, c
, pbc
, t
, pcrd
->dr
, &dev
);
778 k
= (1.0 - lambda
)*pcrd
->k
+ lambda
*pcrd
->kB
;
779 dkdl
= pcrd
->kB
- pcrd
->k
;
784 ndr
= dnorm(pcrd
->dr
);
786 if (ePull
== epullUMBRELLA
)
788 pcrd
->f_scal
= -k
*dev
;
789 *V
+= 0.5* k
*dsqr(dev
);
790 *dVdl
+= 0.5*dkdl
*dsqr(dev
);
798 for (m
= 0; m
< DIM
; m
++)
800 pcrd
->f
[m
] = pcrd
->f_scal
*pcrd
->dr
[m
]*invdr
;
806 if (ePull
== epullUMBRELLA
)
808 pcrd
->f_scal
= -k
*dev
;
809 *V
+= 0.5* k
*dsqr(dev
);
810 *dVdl
+= 0.5*dkdl
*dsqr(dev
);
815 for (m
= 0; m
< DIM
; m
++)
817 ndr
+= pcrd
->vec
[m
]*pcrd
->dr
[m
];
823 for (m
= 0; m
< DIM
; m
++)
825 pcrd
->f
[m
] = pcrd
->f_scal
*pcrd
->vec
[m
];
832 /* Add the pull contribution to the virial */
833 for (j
= 0; j
< DIM
; j
++)
835 for (m
= 0; m
< DIM
; m
++)
837 vir
[j
][m
] -= 0.5*pcrd
->f
[j
]*pcrd
->dr
[m
];
844 real
pull_potential(int ePull
, t_pull
*pull
, t_mdatoms
*md
, t_pbc
*pbc
,
845 t_commrec
*cr
, double t
, real lambda
,
846 rvec
*x
, rvec
*f
, tensor vir
, real
*dvdlambda
)
850 pull_calc_coms(cr
, pull
, md
, pbc
, t
, x
, NULL
);
852 do_pull_pot(ePull
, pull
, pbc
, t
, lambda
,
853 &V
, pull
->bVirial
&& MASTER(cr
) ? vir
: NULL
, &dVdl
);
855 /* Distribute forces over pulled groups */
856 apply_forces(pull
, md
, f
);
863 return (MASTER(cr
) ? V
: 0.0);
866 void pull_constraint(t_pull
*pull
, t_mdatoms
*md
, t_pbc
*pbc
,
867 t_commrec
*cr
, double dt
, double t
,
868 rvec
*x
, rvec
*xp
, rvec
*v
, tensor vir
)
870 pull_calc_coms(cr
, pull
, md
, pbc
, t
, x
, xp
);
872 do_constraint(pull
, pbc
, xp
, v
, pull
->bVirial
&& MASTER(cr
), vir
, dt
, t
);
875 static void make_local_pull_group(gmx_ga2la_t ga2la
,
876 t_pull_group
*pg
, int start
, int end
)
881 for (i
= 0; i
< pg
->nat
; i
++)
886 if (!ga2la_get_home(ga2la
, ii
, &ii
))
891 if (ii
>= start
&& ii
< end
)
893 /* This is a home atom, add it to the local pull group */
894 if (pg
->nat_loc
>= pg
->nalloc_loc
)
896 pg
->nalloc_loc
= over_alloc_dd(pg
->nat_loc
+1);
897 srenew(pg
->ind_loc
, pg
->nalloc_loc
);
898 if (pg
->epgrppbc
== epgrppbcCOS
|| pg
->weight
)
900 srenew(pg
->weight_loc
, pg
->nalloc_loc
);
903 pg
->ind_loc
[pg
->nat_loc
] = ii
;
906 pg
->weight_loc
[pg
->nat_loc
] = pg
->weight
[i
];
913 void dd_make_local_pull_groups(gmx_domdec_t
*dd
, t_pull
*pull
, t_mdatoms
*md
)
927 for (g
= 0; g
< pull
->ngroup
; g
++)
929 make_local_pull_group(ga2la
, &pull
->group
[g
],
934 static void init_pull_group_index(FILE *fplog
, t_commrec
*cr
,
935 int g
, t_pull_group
*pg
, ivec pulldims
,
936 gmx_mtop_t
*mtop
, t_inputrec
*ir
, real lambda
)
938 int i
, ii
, d
, nfrozen
, ndim
;
940 double tmass
, wmass
, wwmass
;
941 gmx_groups_t
*groups
;
942 gmx_mtop_atomlookup_t alook
;
945 if (EI_ENERGY_MINIMIZATION(ir
->eI
) || ir
->eI
== eiBD
)
947 /* There are no masses in the integrator.
948 * But we still want to have the correct mass-weighted COMs.
949 * So we store the real masses in the weights.
950 * We do not set nweight, so these weights do not end up in the tpx file.
952 if (pg
->nweight
== 0)
954 snew(pg
->weight
, pg
->nat
);
963 pg
->weight_loc
= NULL
;
967 pg
->nat_loc
= pg
->nat
;
968 pg
->ind_loc
= pg
->ind
;
969 if (pg
->epgrppbc
== epgrppbcCOS
)
971 snew(pg
->weight_loc
, pg
->nat
);
975 pg
->weight_loc
= pg
->weight
;
979 groups
= &mtop
->groups
;
981 alook
= gmx_mtop_atomlookup_init(mtop
);
987 for (i
= 0; i
< pg
->nat
; i
++)
990 gmx_mtop_atomnr_to_atom(alook
, ii
, &atom
);
991 if (ir
->opts
.nFreeze
)
993 for (d
= 0; d
< DIM
; d
++)
995 if (pulldims
[d
] && ir
->opts
.nFreeze
[ggrpnr(groups
, egcFREEZE
, ii
)][d
])
1001 if (ir
->efep
== efepNO
)
1007 m
= (1 - lambda
)*atom
->m
+ lambda
*atom
->mB
;
1009 if (pg
->nweight
> 0)
1017 if (EI_ENERGY_MINIMIZATION(ir
->eI
))
1019 /* Move the mass to the weight */
1024 else if (ir
->eI
== eiBD
)
1028 mbd
= ir
->bd_fric
*ir
->delta_t
;
1032 if (groups
->grpnr
[egcTC
] == NULL
)
1034 mbd
= ir
->delta_t
/ir
->opts
.tau_t
[0];
1038 mbd
= ir
->delta_t
/ir
->opts
.tau_t
[groups
->grpnr
[egcTC
][ii
]];
1050 gmx_mtop_atomlookup_destroy(alook
);
1054 gmx_fatal(FARGS
, "The total%s mass of pull group %d is zero",
1055 pg
->weight
? " weighted" : "", g
);
1060 "Pull group %d: %5d atoms, mass %9.3f", g
, pg
->nat
, tmass
);
1061 if (pg
->weight
|| EI_ENERGY_MINIMIZATION(ir
->eI
) || ir
->eI
== eiBD
)
1063 fprintf(fplog
, ", weighted mass %9.3f", wmass
*wmass
/wwmass
);
1065 if (pg
->epgrppbc
== epgrppbcCOS
)
1067 fprintf(fplog
, ", cosine weighting will be used");
1069 fprintf(fplog
, "\n");
1074 /* A value > 0 signals not frozen, it is updated later */
1080 for (d
= 0; d
< DIM
; d
++)
1082 ndim
+= pulldims
[d
]*pg
->nat
;
1084 if (fplog
&& nfrozen
> 0 && nfrozen
< ndim
)
1087 "\nWARNING: In pull group %d some, but not all of the degrees of freedom\n"
1088 " that are subject to pulling are frozen.\n"
1089 " For pulling the whole group will be frozen.\n\n",
1097 void init_pull(FILE *fplog
, t_inputrec
*ir
, int nfile
, const t_filenm fnm
[],
1098 gmx_mtop_t
*mtop
, t_commrec
*cr
, const output_env_t oenv
, real lambda
,
1099 gmx_bool bOutFile
, unsigned long Flags
)
1103 int c
, g
, start
= 0, end
= 0, m
;
1107 pull
->ePBC
= ir
->ePBC
;
1110 case epbcNONE
: pull
->npbcdim
= 0; break;
1111 case epbcXY
: pull
->npbcdim
= 2; break;
1112 default: pull
->npbcdim
= 3; break;
1117 gmx_bool bAbs
, bCos
;
1120 for (c
= 0; c
< pull
->ncoord
; c
++)
1122 if (pull
->group
[pull
->coord
[c
].group
[0]].nat
== 0 ||
1123 pull
->group
[pull
->coord
[c
].group
[1]].nat
== 0)
1129 fprintf(fplog
, "\nWill apply %s COM pulling in geometry '%s'\n",
1130 EPULLTYPE(ir
->ePull
), EPULLGEOM(pull
->eGeom
));
1131 fprintf(fplog
, "with %d pull coordinate%s and %d group%s\n",
1132 pull
->ncoord
, pull
->ncoord
== 1 ? "" : "s",
1133 pull
->ngroup
, pull
->ngroup
== 1 ? "" : "s");
1136 fprintf(fplog
, "with an absolute reference\n");
1139 for (g
= 0; g
< pull
->ngroup
; g
++)
1141 if (pull
->group
[g
].nat
> 1 &&
1142 pull
->group
[g
].pbcatom
< 0)
1144 /* We are using cosine weighting */
1145 fprintf(fplog
, "Cosine weighting is used for group %d\n", g
);
1151 please_cite(fplog
, "Engin2010");
1155 /* We always add the virial contribution,
1156 * except for geometry = direction_periodic where this is impossible.
1158 pull
->bVirial
= (pull
->eGeom
!= epullgDIRPBC
);
1159 if (getenv("GMX_NO_PULLVIR") != NULL
)
1163 fprintf(fplog
, "Found env. var., will not add the virial contribution of the COM pull forces\n");
1165 pull
->bVirial
= FALSE
;
1170 pull
->dbuf_cyl
= NULL
;
1171 pull
->bRefAt
= FALSE
;
1173 for (g
= 0; g
< pull
->ngroup
; g
++)
1175 pgrp
= &pull
->group
[g
];
1176 pgrp
->epgrppbc
= epgrppbcNONE
;
1179 /* Determine if we need to take PBC into account for calculating
1180 * the COM's of the pull groups.
1182 for (m
= 0; m
< pull
->npbcdim
; m
++)
1184 if (pull
->dim
[m
] && pgrp
->nat
> 1)
1186 if (pgrp
->pbcatom
>= 0)
1188 pgrp
->epgrppbc
= epgrppbcREFAT
;
1189 pull
->bRefAt
= TRUE
;
1195 gmx_fatal(FARGS
, "Pull groups can not have relative weights and cosine weighting at same time");
1197 pgrp
->epgrppbc
= epgrppbcCOS
;
1198 if (pull
->cosdim
>= 0 && pull
->cosdim
!= m
)
1200 gmx_fatal(FARGS
, "Can only use cosine weighting with pulling in one dimension (use mdp option pull_dim)");
1206 /* Set the indices */
1207 init_pull_group_index(fplog
, cr
, g
, pgrp
, pull
->dim
, mtop
, ir
, lambda
);
1208 if (PULL_CYL(pull
) && pgrp
->invtm
== 0)
1210 gmx_fatal(FARGS
, "Can not have frozen atoms in a cylinder pull group");
1215 /* Absolute reference, set the inverse mass to zero */
1221 /* if we use dynamic reference groups, do some initialising for them */
1224 if (ir
->ePull
== epullCONSTRAINT
&& pull
->ncoord
> 1)
1226 /* We can't easily update the single reference group with multiple
1227 * constraints. This would require recalculating COMs.
1229 gmx_fatal(FARGS
, "Constraint COM pulling supports only one coordinate with geometry=cylinder, you can use umbrella pulling with multiple coordinates");
1232 for (c
= 0; c
< pull
->ncoord
; c
++)
1234 if (pull
->group
[pull
->coord
[c
].group
[0]].nat
== 0)
1236 gmx_fatal(FARGS
, "Dynamic reference groups are not supported when using absolute reference!\n");
1240 snew(pull
->dyna
, pull
->ncoord
);
1243 /* Only do I/O when we are doing dynamics and if we are the MASTER */
1248 if (pull
->nstxout
> 0)
1250 pull
->out_x
= open_pull_out(opt2fn("-px", nfile
, fnm
), pull
, oenv
, TRUE
, Flags
);
1252 if (pull
->nstfout
> 0)
1254 pull
->out_f
= open_pull_out(opt2fn("-pf", nfile
, fnm
), pull
, oenv
,
1260 void finish_pull(t_pull
*pull
)
1264 gmx_fio_fclose(pull
->out_x
);
1268 gmx_fio_fclose(pull
->out_f
);