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,2015, 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.
46 #include "gromacs/fileio/filenm.h"
47 #include "gromacs/fileio/gmxfio.h"
48 #include "gromacs/fileio/xvgr.h"
49 #include "gromacs/legacyheaders/copyrite.h"
50 #include "gromacs/legacyheaders/gmx_ga2la.h"
51 #include "gromacs/legacyheaders/macros.h"
52 #include "gromacs/legacyheaders/mdrun.h"
53 #include "gromacs/legacyheaders/names.h"
54 #include "gromacs/legacyheaders/network.h"
55 #include "gromacs/legacyheaders/typedefs.h"
56 #include "gromacs/legacyheaders/types/commrec.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/pbcutil/pbc.h"
59 #include "gromacs/topology/mtop_util.h"
60 #include "gromacs/utility/futil.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, const t_pull_coord *pcrd,
77 gmx_bool bPrintRefValue,
78 gmx_bool bPrintComponents)
80 fprintf(out, "\t%g", pcrd->value);
84 fprintf(out, "\t%g", pcrd->value_ref);
91 for (m = 0; m < DIM; m++)
95 fprintf(out, "\t%g", pcrd->dr[m]);
101 static void pull_print_x(FILE *out, t_pull *pull, double t)
106 fprintf(out, "%.4f", t);
108 for (c = 0; c < pull->ncoord; c++)
110 pcrd = &pull->coord[c];
112 if (pull->bPrintCOM1)
114 if (pcrd->eGeom == epullgCYL)
116 pull_print_group_x(out, pcrd->dim, &pull->dyna[c]);
120 pull_print_group_x(out, pcrd->dim, &pull->group[pcrd->group[0]]);
123 if (pull->bPrintCOM2)
125 pull_print_group_x(out, pcrd->dim, &pull->group[pcrd->group[1]]);
127 pull_print_coord_dr(out, pcrd,
128 pull->bPrintRefValue, pull->bPrintComp);
133 static void pull_print_f(FILE *out, t_pull *pull, double t)
137 fprintf(out, "%.4f", t);
139 for (c = 0; c < pull->ncoord; c++)
141 fprintf(out, "\t%g", pull->coord[c].f_scal);
146 void pull_print_output(t_pull *pull, gmx_int64_t step, double time)
148 if ((pull->nstxout != 0) && (step % pull->nstxout == 0))
150 pull_print_x(pull->out_x, pull, time);
153 if ((pull->nstfout != 0) && (step % pull->nstfout == 0))
155 pull_print_f(pull->out_f, pull, time);
159 static FILE *open_pull_out(const char *fn, t_pull *pull, const output_env_t oenv,
160 gmx_bool bCoord, unsigned long Flags)
164 char **setname, buf[10];
166 if (Flags & MD_APPENDFILES)
168 fp = gmx_fio_fopen(fn, "a+");
172 fp = gmx_fio_fopen(fn, "w+");
175 xvgr_header(fp, "Pull COM", "Time (ps)", "Position (nm)",
180 xvgr_header(fp, "Pull force", "Time (ps)", "Force (kJ/mol/nm)",
184 /* With default mdp options only the actual distance is printed,
185 * but optionally 2 COMs, the reference distance and distance
186 * components can also be printed.
188 snew(setname, pull->ncoord*(DIM + DIM + 1 + 1 + DIM));
190 for (c = 0; c < pull->ncoord; c++)
194 /* The order of this legend should match the order of printing
195 * the data in print_pull_x above.
198 if (pull->bPrintCOM1)
200 /* Legend for reference group position */
201 for (m = 0; m < DIM; m++)
203 if (pull->coord[c].dim[m])
205 sprintf(buf, "%d %s%d%c", c+1, "c", 1, 'X'+m);
206 setname[nsets] = gmx_strdup(buf);
211 if (pull->bPrintCOM2)
213 /* Legend for reference group position */
214 for (m = 0; m < DIM; m++)
216 if (pull->coord[c].dim[m])
218 sprintf(buf, "%d %s%d%c", c+1, "c", 2, 'X'+m);
219 setname[nsets] = gmx_strdup(buf);
224 /* The pull coord distance */
225 sprintf(buf, "%d", c+1);
226 setname[nsets] = gmx_strdup(buf);
228 if (pull->bPrintRefValue)
230 sprintf(buf, "%c%d", 'r', c+1);
231 setname[nsets] = gmx_strdup(buf);
234 if (pull->bPrintComp)
236 /* The pull coord distance components */
237 for (m = 0; m < DIM; m++)
239 if (pull->coord[c].dim[m])
241 sprintf(buf, "%d %s%c", c+1, "d", 'X'+m);
242 setname[nsets] = gmx_strdup(buf);
250 /* For the pull force we always only use one scalar */
251 sprintf(buf, "%d", c+1);
252 setname[nsets] = gmx_strdup(buf);
258 xvgr_legend(fp, nsets, (const char**)setname, oenv);
260 for (c = 0; c < nsets; c++)
270 /* Apply forces in a mass weighted fashion */
271 static void apply_forces_grp(const t_pull_group *pgrp, const t_mdatoms *md,
272 const dvec f_pull, int sign, rvec *f)
275 double wmass, inv_wm;
277 inv_wm = pgrp->mwscale;
279 if (pgrp->nat == 1 && pgrp->nat_loc == 1)
281 /* Only one atom and our rank has this atom: we can skip
282 * the mass weighting, which means that this code also works
283 * for mass=0, e.g. with a virtual site.
285 for (m = 0; m < DIM; m++)
287 f[pgrp->ind_loc[0]][m] += sign*f_pull[m];
292 for (i = 0; i < pgrp->nat_loc; i++)
294 ii = pgrp->ind_loc[i];
295 wmass = md->massT[ii];
296 if (pgrp->weight_loc)
298 wmass *= pgrp->weight_loc[i];
301 for (m = 0; m < DIM; m++)
303 f[ii][m] += sign * wmass * f_pull[m] * inv_wm;
309 /* Apply forces in a mass weighted fashion to a cylinder group */
310 static void apply_forces_cyl_grp(const t_pull_group *pgrp, double dv_corr,
312 const dvec f_pull, double f_scal,
316 double mass, weight, inv_wm, dv_com;
318 inv_wm = pgrp->mwscale;
320 for (i = 0; i < pgrp->nat_loc; i++)
322 ii = pgrp->ind_loc[i];
323 mass = md->massT[ii];
324 weight = pgrp->weight_loc[i];
325 /* The stored axial distance from the cylinder center (dv) needs
326 * to be corrected for an offset (dv_corr), which was unknown when
329 dv_com = pgrp->dv[i] + dv_corr;
331 /* Here we not only add the pull force working along vec (f_pull),
332 * but also a radial component, due to the dependence of the weights
333 * on the radial distance.
335 for (m = 0; m < DIM; m++)
337 f[ii][m] += sign*inv_wm*(mass*weight*f_pull[m] +
338 pgrp->mdw[i][m]*dv_com*f_scal);
343 /* Apply torque forces in a mass weighted fashion to the groups that define
344 * the pull vector direction for pull coordinate pcrd.
346 static void apply_forces_vec_torque(const t_pull *pull,
347 const t_pull_coord *pcrd,
355 /* The component inpr along the pull vector is accounted for in the usual
356 * way. Here we account for the component perpendicular to vec.
359 for (m = 0; m < DIM; m++)
361 inpr += pcrd->dr[m]*pcrd->vec[m];
363 /* The torque force works along the component of the distance vector
364 * of between the two "usual" pull groups that is perpendicular to
365 * the pull vector. The magnitude of this force is the "usual" scale force
366 * multiplied with the ratio of the distance between the two "usual" pull
367 * groups and the distance between the two groups that define the vector.
369 for (m = 0; m < DIM; m++)
371 f_perp[m] = (pcrd->dr[m] - inpr*pcrd->vec[m])/pcrd->vec_len*pcrd->f_scal;
374 /* Apply the force to the groups defining the vector using opposite signs */
375 apply_forces_grp(&pull->group[pcrd->group[2]], md, f_perp, -1, f);
376 apply_forces_grp(&pull->group[pcrd->group[3]], md, f_perp, 1, f);
379 /* Apply forces in a mass weighted fashion */
380 static void apply_forces(t_pull * pull, t_mdatoms * md, rvec *f)
383 const t_pull_coord *pcrd;
385 for (c = 0; c < pull->ncoord; c++)
387 pcrd = &pull->coord[c];
389 if (pcrd->eGeom == epullgCYL)
394 apply_forces_cyl_grp(&pull->dyna[c], pcrd->cyl_dev, md,
395 pcrd->f, pcrd->f_scal, -1, f);
397 /* Sum the force along the vector and the radial force */
398 for (m = 0; m < DIM; m++)
400 f_tot[m] = pcrd->f[m] + pcrd->f_scal*pcrd->ffrad[m];
402 apply_forces_grp(&pull->group[pcrd->group[1]], md, f_tot, 1, f);
406 if (pcrd->eGeom == epullgDIRRELATIVE)
408 /* We need to apply the torque forces to the pull groups
409 * that define the pull vector.
411 apply_forces_vec_torque(pull, pcrd, md, f);
414 if (pull->group[pcrd->group[0]].nat > 0)
416 apply_forces_grp(&pull->group[pcrd->group[0]], md, pcrd->f, -1, f);
418 apply_forces_grp(&pull->group[pcrd->group[1]], md, pcrd->f, 1, f);
423 static double max_pull_distance2(const t_pull_coord *pcrd, const t_pbc *pbc)
428 max_d2 = GMX_DOUBLE_MAX;
430 for (m = 0; m < pbc->ndim_ePBC; m++)
432 if (pcrd->dim[m] != 0)
434 max_d2 = min(max_d2, norm2(pbc->box[m]));
441 /* This function returns the distance based on coordinates xg and xref.
442 * Note that the pull coordinate struct pcrd is not modified.
444 static void low_get_pull_coord_dr(const t_pull *pull,
445 const t_pull_coord *pcrd,
447 dvec xg, dvec xref, double max_dist2,
450 const t_pull_group *pgrp0, *pgrp1;
452 dvec xrefr, dref = {0, 0, 0};
455 pgrp0 = &pull->group[pcrd->group[0]];
456 pgrp1 = &pull->group[pcrd->group[1]];
458 /* Only the first group can be an absolute reference, in that case nat=0 */
461 for (m = 0; m < DIM; m++)
463 xref[m] = pcrd->origin[m];
467 copy_dvec(xref, xrefr);
469 if (pcrd->eGeom == epullgDIRPBC)
471 for (m = 0; m < DIM; m++)
473 dref[m] = pcrd->value_ref*pcrd->vec[m];
475 /* Add the reference position, so we use the correct periodic image */
476 dvec_inc(xrefr, dref);
479 pbc_dx_d(pbc, xg, xrefr, dr);
481 for (m = 0; m < DIM; m++)
483 dr[m] *= pcrd->dim[m];
486 if (max_dist2 >= 0 && dr2 > 0.98*0.98*max_dist2)
488 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",
489 pcrd->group[0], pcrd->group[1], sqrt(dr2), sqrt(max_dist2));
492 if (pcrd->eGeom == epullgDIRPBC)
498 /* This function returns the distance based on the contents of the pull struct.
499 * pull->coord[coord_ind].dr, and potentially vector, are updated.
501 static void get_pull_coord_dr(t_pull *pull,
508 pcrd = &pull->coord[coord_ind];
510 if (pcrd->eGeom == epullgDIRPBC)
516 md2 = max_pull_distance2(pcrd, pbc);
519 if (pcrd->eGeom == epullgDIRRELATIVE)
521 /* We need to determine the pull vector */
522 const t_pull_group *pgrp2, *pgrp3;
527 pgrp2 = &pull->group[pcrd->group[2]];
528 pgrp3 = &pull->group[pcrd->group[3]];
530 pbc_dx_d(pbc, pgrp3->x, pgrp2->x, vec);
532 for (m = 0; m < DIM; m++)
534 vec[m] *= pcrd->dim[m];
536 pcrd->vec_len = dnorm(vec);
537 for (m = 0; m < DIM; m++)
539 pcrd->vec[m] = vec[m]/pcrd->vec_len;
543 fprintf(debug, "pull coord %d vector: %6.3f %6.3f %6.3f normalized: %6.3f %6.3f %6.3f\n",
545 vec[XX], vec[YY], vec[ZZ],
546 pcrd->vec[XX], pcrd->vec[YY], pcrd->vec[ZZ]);
550 low_get_pull_coord_dr(pull, pcrd, pbc,
551 pull->group[pcrd->group[1]].x,
552 pcrd->eGeom == epullgCYL ? pull->dyna[coord_ind].x : pull->group[pcrd->group[0]].x,
557 static void update_pull_coord_reference_value(t_pull_coord *pcrd, double t)
559 /* With zero rate the reference value is set initially and doesn't change */
562 pcrd->value_ref = pcrd->init + pcrd->rate*t;
566 /* Calculates pull->coord[coord_ind].value.
567 * This function also updates pull->coord[coord_ind].dr.
569 static void get_pull_coord_distance(t_pull *pull,
576 pcrd = &pull->coord[coord_ind];
578 get_pull_coord_dr(pull, coord_ind, pbc);
583 /* Pull along the vector between the com's */
584 pcrd->value = dnorm(pcrd->dr);
588 case epullgDIRRELATIVE:
592 for (m = 0; m < DIM; m++)
594 pcrd->value += pcrd->vec[m]*pcrd->dr[m];
600 /* Returns the deviation from the reference value.
601 * Updates pull->coord[coord_ind].dr, .value and .value_ref.
603 static double get_pull_coord_deviation(t_pull *pull,
608 static gmx_bool bWarned = FALSE; /* TODO: this should be fixed for thread-safety,
609 but is fairly benign */
613 pcrd = &pull->coord[coord_ind];
615 get_pull_coord_distance(pull, coord_ind, pbc);
617 update_pull_coord_reference_value(pcrd, t);
622 /* Pull along the vector between the com's */
623 if (pcrd->value_ref < 0 && !bWarned)
625 fprintf(stderr, "\nPull reference distance for coordinate %d is negative (%f)\n", coord_ind+1, pcrd->value_ref);
628 if (pcrd->value == 0)
630 /* With no vector we can not determine the direction for the force,
631 * so we set the force to zero.
637 /* Determine the deviation */
638 dev = pcrd->value - pcrd->value_ref;
643 case epullgDIRRELATIVE:
646 dev = pcrd->value - pcrd->value_ref;
653 void get_pull_coord_value(t_pull *pull,
658 get_pull_coord_distance(pull, coord_ind, pbc);
660 *value = pull->coord[coord_ind].value;
663 void clear_pull_forces(t_pull *pull)
667 /* Zeroing the forces is only required for constraint pulling.
668 * It can happen that multiple constraint steps need to be applied
669 * and therefore the constraint forces need to be accumulated.
671 for (i = 0; i < pull->ncoord; i++)
673 clear_dvec(pull->coord[i].f);
674 pull->coord[i].f_scal = 0;
678 /* Apply constraint using SHAKE */
679 static void do_constraint(t_pull *pull, t_pbc *pbc,
681 gmx_bool bMaster, tensor vir,
685 dvec *r_ij; /* x[i] com of i in prev. step. Obeys constr. -> r_ij[i] */
686 dvec unc_ij; /* xp[i] com of i this step, before constr. -> unc_ij */
687 dvec *rnew; /* current 'new' positions of the groups */
688 double *dr_tot; /* the total update of the coords */
691 double lambda, rm, invdt = 0;
692 gmx_bool bConverged_all, bConverged = FALSE;
693 int niter = 0, g, c, ii, j, m, max_iter = 100;
695 dvec f; /* the pull force */
697 t_pull_group *pgrp0, *pgrp1;
700 snew(r_ij, pull->ncoord);
701 snew(dr_tot, pull->ncoord);
703 snew(rnew, pull->ngroup);
705 /* copy the current unconstrained positions for use in iterations. We
706 iterate until rinew[i] and rjnew[j] obey the constraints. Then
707 rinew - pull.x_unc[i] is the correction dr to group i */
708 for (g = 0; g < pull->ngroup; g++)
710 copy_dvec(pull->group[g].xp, rnew[g]);
713 /* Determine the constraint directions from the old positions */
714 for (c = 0; c < pull->ncoord; c++)
716 pcrd = &pull->coord[c];
718 if (pcrd->eType != epullCONSTRAINT)
723 /* Note that get_pull_coord_distance also sets pcrd->dr and pcrd->value.
724 * We don't modify dr and value anymore, so these values are also used
727 get_pull_coord_distance(pull, c, pbc);
731 fprintf(debug, "Pull coord %d dr %f %f %f\n",
732 c, pcrd->dr[XX], pcrd->dr[YY], pcrd->dr[ZZ]);
735 if (pcrd->eGeom == epullgDIR || pcrd->eGeom == epullgDIRPBC)
737 /* Select the component along vec */
739 for (m = 0; m < DIM; m++)
741 a += pcrd->vec[m]*pcrd->dr[m];
743 for (m = 0; m < DIM; m++)
745 r_ij[c][m] = a*pcrd->vec[m];
750 copy_dvec(pcrd->dr, r_ij[c]);
753 if (dnorm2(r_ij[c]) == 0)
755 gmx_fatal(FARGS, "Distance for pull coordinate %d is zero with constraint pulling, which is not allowed.", c + 1);
759 bConverged_all = FALSE;
760 while (!bConverged_all && niter < max_iter)
762 bConverged_all = TRUE;
764 /* loop over all constraints */
765 for (c = 0; c < pull->ncoord; c++)
769 pcrd = &pull->coord[c];
771 if (pcrd->eType != epullCONSTRAINT)
776 update_pull_coord_reference_value(pcrd, t);
778 pgrp0 = &pull->group[pcrd->group[0]];
779 pgrp1 = &pull->group[pcrd->group[1]];
781 /* Get the current difference vector */
782 low_get_pull_coord_dr(pull, pcrd, pbc,
783 rnew[pcrd->group[1]],
784 rnew[pcrd->group[0]],
789 fprintf(debug, "Pull coord %d, iteration %d\n", c, niter);
792 rm = 1.0/(pgrp0->invtm + pgrp1->invtm);
797 if (pcrd->value_ref <= 0)
799 gmx_fatal(FARGS, "The pull constraint reference distance for group %d is <= 0 (%f)", c, pcrd->value_ref);
803 double q, c_a, c_b, c_c;
805 c_a = diprod(r_ij[c], r_ij[c]);
806 c_b = diprod(unc_ij, r_ij[c])*2;
807 c_c = diprod(unc_ij, unc_ij) - dsqr(pcrd->value_ref);
811 q = -0.5*(c_b - sqrt(c_b*c_b - 4*c_a*c_c));
816 q = -0.5*(c_b + sqrt(c_b*c_b - 4*c_a*c_c));
823 "Pull ax^2+bx+c=0: a=%e b=%e c=%e lambda=%e\n",
824 c_a, c_b, c_c, lambda);
828 /* The position corrections dr due to the constraints */
829 dsvmul(-lambda*rm*pgrp1->invtm, r_ij[c], dr1);
830 dsvmul( lambda*rm*pgrp0->invtm, r_ij[c], dr0);
831 dr_tot[c] += -lambda*dnorm(r_ij[c]);
836 /* A 1-dimensional constraint along a vector */
838 for (m = 0; m < DIM; m++)
840 vec[m] = pcrd->vec[m];
841 a += unc_ij[m]*vec[m];
843 /* Select only the component along the vector */
844 dsvmul(a, vec, unc_ij);
845 lambda = a - pcrd->value_ref;
848 fprintf(debug, "Pull inpr %e lambda: %e\n", a, lambda);
851 /* The position corrections dr due to the constraints */
852 dsvmul(-lambda*rm*pgrp1->invtm, vec, dr1);
853 dsvmul( lambda*rm*pgrp0->invtm, vec, dr0);
854 dr_tot[c] += -lambda;
865 low_get_pull_coord_dr(pull, pcrd, pbc, rnew[g1], rnew[g0], -1, tmp);
866 low_get_pull_coord_dr(pull, pcrd, pbc, dr1, dr0, -1, tmp3);
868 "Pull cur %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
869 rnew[g0][0], rnew[g0][1], rnew[g0][2],
870 rnew[g1][0], rnew[g1][1], rnew[g1][2], dnorm(tmp));
872 "Pull ref %8s %8s %8s %8s %8s %8s d: %8.5f\n",
873 "", "", "", "", "", "", pcrd->value_ref);
875 "Pull cor %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
876 dr0[0], dr0[1], dr0[2],
877 dr1[0], dr1[1], dr1[2],
881 /* Update the COMs with dr */
882 dvec_inc(rnew[pcrd->group[1]], dr1);
883 dvec_inc(rnew[pcrd->group[0]], dr0);
886 /* Check if all constraints are fullfilled now */
887 for (c = 0; c < pull->ncoord; c++)
889 pcrd = &pull->coord[c];
891 if (pcrd->eType != epullCONSTRAINT)
896 low_get_pull_coord_dr(pull, pcrd, pbc,
897 rnew[pcrd->group[1]],
898 rnew[pcrd->group[0]],
905 fabs(dnorm(unc_ij) - pcrd->value_ref) < pull->constr_tol;
910 for (m = 0; m < DIM; m++)
912 vec[m] = pcrd->vec[m];
914 inpr = diprod(unc_ij, vec);
915 dsvmul(inpr, vec, unc_ij);
917 fabs(diprod(unc_ij, vec) - pcrd->value_ref) < pull->constr_tol;
925 fprintf(debug, "NOT CONVERGED YET: Group %d:"
926 "d_ref = %f, current d = %f\n",
927 g, pcrd->value_ref, dnorm(unc_ij));
930 bConverged_all = FALSE;
935 /* if after all constraints are dealt with and bConverged is still TRUE
936 we're finished, if not we do another iteration */
938 if (niter > max_iter)
940 gmx_fatal(FARGS, "Too many iterations for constraint run: %d", niter);
943 /* DONE ITERATING, NOW UPDATE COORDINATES AND CALC. CONSTRAINT FORCES */
950 /* update atoms in the groups */
951 for (g = 0; g < pull->ngroup; g++)
953 const t_pull_group *pgrp;
956 pgrp = &pull->group[g];
958 /* get the final constraint displacement dr for group g */
959 dvec_sub(rnew[g], pgrp->xp, dr);
963 /* No displacement, no update necessary */
967 /* update the atom positions */
969 for (j = 0; j < pgrp->nat_loc; j++)
971 ii = pgrp->ind_loc[j];
972 if (pgrp->weight_loc)
974 dsvmul(pgrp->wscale*pgrp->weight_loc[j], dr, tmp);
976 for (m = 0; m < DIM; m++)
982 for (m = 0; m < DIM; m++)
984 v[ii][m] += invdt*tmp[m];
990 /* calculate the constraint forces, used for output and virial only */
991 for (c = 0; c < pull->ncoord; c++)
993 pcrd = &pull->coord[c];
995 if (pcrd->eType != epullCONSTRAINT)
1000 pcrd->f_scal = dr_tot[c]/((pull->group[pcrd->group[0]].invtm + pull->group[pcrd->group[1]].invtm)*dt*dt);
1002 if (vir != NULL && pcrd->eGeom != epullgDIRPBC && bMaster)
1006 /* Add the pull contribution to the virial */
1007 /* We have already checked above that r_ij[c] != 0 */
1008 f_invr = pcrd->f_scal/dnorm(r_ij[c]);
1010 for (j = 0; j < DIM; j++)
1012 for (m = 0; m < DIM; m++)
1014 vir[j][m] -= 0.5*f_invr*r_ij[c][j]*r_ij[c][m];
1020 /* finished! I hope. Give back some memory */
1026 /* Pulling with a harmonic umbrella potential or constant force */
1027 static void do_pull_pot(t_pull *pull, t_pbc *pbc, double t, real lambda,
1028 real *V, tensor vir, real *dVdl)
1031 double dev, ndr, invdr = 0;
1035 /* loop over the pull coordinates */
1038 for (c = 0; c < pull->ncoord; c++)
1040 pcrd = &pull->coord[c];
1042 if (pcrd->eType == epullCONSTRAINT)
1047 dev = get_pull_coord_deviation(pull, c, pbc, t);
1049 k = (1.0 - lambda)*pcrd->k + lambda*pcrd->kB;
1050 dkdl = pcrd->kB - pcrd->k;
1052 if (pcrd->eGeom == epullgDIST)
1054 ndr = dnorm(pcrd->dr);
1061 /* With an harmonic umbrella, the force is 0 at r=0,
1062 * so we can set invdr to any value.
1063 * With a constant force, the force at r=0 is not defined,
1064 * so we zero it (this is anyhow a very rare event).
1072 for (m = 0; m < DIM; m++)
1074 ndr += pcrd->vec[m]*pcrd->dr[m];
1078 switch (pcrd->eType)
1081 case epullFLATBOTTOM:
1082 /* The only difference between an umbrella and a flat-bottom
1083 * potential is that a flat-bottom is zero below zero.
1085 if (pcrd->eType == epullFLATBOTTOM && dev < 0)
1090 pcrd->f_scal = -k*dev;
1091 *V += 0.5* k*dsqr(dev);
1092 *dVdl += 0.5*dkdl*dsqr(dev);
1100 gmx_incons("Unsupported pull type in do_pull_pot");
1103 if (pcrd->eGeom == epullgDIST)
1105 for (m = 0; m < DIM; m++)
1107 pcrd->f[m] = pcrd->f_scal*pcrd->dr[m]*invdr;
1112 for (m = 0; m < DIM; m++)
1114 pcrd->f[m] = pcrd->f_scal*pcrd->vec[m];
1118 if (vir != NULL && pcrd->eGeom != epullgDIRPBC)
1120 /* Add the pull contribution to the virial */
1121 for (j = 0; j < DIM; j++)
1123 for (m = 0; m < DIM; m++)
1125 vir[j][m] -= 0.5*pcrd->f[j]*pcrd->dr[m];
1132 real pull_potential(t_pull *pull, t_mdatoms *md, t_pbc *pbc,
1133 t_commrec *cr, double t, real lambda,
1134 rvec *x, rvec *f, tensor vir, real *dvdlambda)
1138 pull_calc_coms(cr, pull, md, pbc, t, x, NULL);
1140 do_pull_pot(pull, pbc, t, lambda,
1141 &V, MASTER(cr) ? vir : NULL, &dVdl);
1143 /* Distribute forces over pulled groups */
1144 apply_forces(pull, md, f);
1151 return (MASTER(cr) ? V : 0.0);
1154 void pull_constraint(t_pull *pull, t_mdatoms *md, t_pbc *pbc,
1155 t_commrec *cr, double dt, double t,
1156 rvec *x, rvec *xp, rvec *v, tensor vir)
1158 pull_calc_coms(cr, pull, md, pbc, t, x, xp);
1160 do_constraint(pull, pbc, xp, v, MASTER(cr), vir, dt, t);
1163 static void make_local_pull_group(gmx_ga2la_t ga2la,
1164 t_pull_group *pg, int start, int end)
1169 for (i = 0; i < pg->nat; i++)
1174 if (!ga2la_get_home(ga2la, ii, &ii))
1179 if (ii >= start && ii < end)
1181 /* This is a home atom, add it to the local pull group */
1182 if (pg->nat_loc >= pg->nalloc_loc)
1184 pg->nalloc_loc = over_alloc_dd(pg->nat_loc+1);
1185 srenew(pg->ind_loc, pg->nalloc_loc);
1186 if (pg->epgrppbc == epgrppbcCOS || pg->weight)
1188 srenew(pg->weight_loc, pg->nalloc_loc);
1191 pg->ind_loc[pg->nat_loc] = ii;
1194 pg->weight_loc[pg->nat_loc] = pg->weight[i];
1201 void dd_make_local_pull_groups(gmx_domdec_t *dd, t_pull *pull, t_mdatoms *md)
1215 for (g = 0; g < pull->ngroup; g++)
1217 make_local_pull_group(ga2la, &pull->group[g],
1221 /* Since the PBC of atoms might have changed, we need to update the PBC */
1222 pull->bSetPBCatoms = TRUE;
1225 static void init_pull_group_index(FILE *fplog, t_commrec *cr,
1226 int g, t_pull_group *pg,
1227 gmx_bool bConstraint, ivec pulldim_con,
1228 gmx_mtop_t *mtop, t_inputrec *ir, real lambda)
1230 int i, ii, d, nfrozen, ndim;
1232 double tmass, wmass, wwmass;
1233 gmx_groups_t *groups;
1234 gmx_mtop_atomlookup_t alook;
1237 if (EI_ENERGY_MINIMIZATION(ir->eI) || ir->eI == eiBD)
1239 /* There are no masses in the integrator.
1240 * But we still want to have the correct mass-weighted COMs.
1241 * So we store the real masses in the weights.
1242 * We do not set nweight, so these weights do not end up in the tpx file.
1244 if (pg->nweight == 0)
1246 snew(pg->weight, pg->nat);
1255 pg->weight_loc = NULL;
1259 pg->nat_loc = pg->nat;
1260 pg->ind_loc = pg->ind;
1261 if (pg->epgrppbc == epgrppbcCOS)
1263 snew(pg->weight_loc, pg->nat);
1267 pg->weight_loc = pg->weight;
1271 groups = &mtop->groups;
1273 alook = gmx_mtop_atomlookup_init(mtop);
1279 for (i = 0; i < pg->nat; i++)
1282 gmx_mtop_atomnr_to_atom(alook, ii, &atom);
1283 if (bConstraint && ir->opts.nFreeze)
1285 for (d = 0; d < DIM; d++)
1287 if (pulldim_con[d] == 1 &&
1288 ir->opts.nFreeze[ggrpnr(groups, egcFREEZE, ii)][d])
1294 if (ir->efep == efepNO)
1300 m = (1 - lambda)*atom->m + lambda*atom->mB;
1302 if (pg->nweight > 0)
1310 if (EI_ENERGY_MINIMIZATION(ir->eI))
1312 /* Move the mass to the weight */
1317 else if (ir->eI == eiBD)
1321 mbd = ir->bd_fric*ir->delta_t;
1325 if (groups->grpnr[egcTC] == NULL)
1327 mbd = ir->delta_t/ir->opts.tau_t[0];
1331 mbd = ir->delta_t/ir->opts.tau_t[groups->grpnr[egcTC][ii]];
1343 gmx_mtop_atomlookup_destroy(alook);
1347 /* We can have single atom groups with zero mass with potential pulling
1348 * without cosine weighting.
1350 if (pg->nat == 1 && !bConstraint && pg->epgrppbc != epgrppbcCOS)
1352 /* With one atom the mass doesn't matter */
1357 gmx_fatal(FARGS, "The total%s mass of pull group %d is zero",
1358 pg->weight ? " weighted" : "", g);
1364 "Pull group %d: %5d atoms, mass %9.3f", g, pg->nat, tmass);
1365 if (pg->weight || EI_ENERGY_MINIMIZATION(ir->eI) || ir->eI == eiBD)
1367 fprintf(fplog, ", weighted mass %9.3f", wmass*wmass/wwmass);
1369 if (pg->epgrppbc == epgrppbcCOS)
1371 fprintf(fplog, ", cosine weighting will be used");
1373 fprintf(fplog, "\n");
1378 /* A value != 0 signals not frozen, it is updated later */
1384 for (d = 0; d < DIM; d++)
1386 ndim += pulldim_con[d]*pg->nat;
1388 if (fplog && nfrozen > 0 && nfrozen < ndim)
1391 "\nWARNING: In pull group %d some, but not all of the degrees of freedom\n"
1392 " that are subject to pulling are frozen.\n"
1393 " For constraint pulling the whole group will be frozen.\n\n",
1401 void init_pull(FILE *fplog, t_inputrec *ir, int nfile, const t_filenm fnm[],
1402 gmx_mtop_t *mtop, t_commrec *cr, const output_env_t oenv, real lambda,
1403 gmx_bool bOutFile, unsigned long Flags)
1411 pull->bPotential = FALSE;
1412 pull->bConstraint = FALSE;
1413 pull->bCylinder = FALSE;
1414 for (c = 0; c < pull->ncoord; c++)
1417 int calc_com_start, calc_com_end, g;
1419 pcrd = &pull->coord[c];
1421 if (pcrd->eType == epullCONSTRAINT)
1423 /* Check restrictions of the constraint pull code */
1424 if (pcrd->eGeom == epullgCYL ||
1425 pcrd->eGeom == epullgDIRRELATIVE)
1427 gmx_fatal(FARGS, "Pulling of type %s can not be combined with geometry %s. Consider using pull type %s.",
1428 epull_names[pcrd->eType],
1429 epullg_names[pcrd->eGeom],
1430 epull_names[epullUMBRELLA]);
1433 pull->bConstraint = TRUE;
1437 pull->bPotential = TRUE;
1440 if (pcrd->eGeom == epullgCYL)
1442 pull->bCylinder = TRUE;
1444 /* We only need to calculate the plain COM of a group
1445 * when it is not only used as a cylinder group.
1447 calc_com_start = (pcrd->eGeom == epullgCYL ? 1 : 0);
1448 calc_com_end = (pcrd->eGeom == epullgDIRRELATIVE ? 4 : 2);
1450 for (g = calc_com_start; g <= calc_com_end; g++)
1452 pull->group[pcrd->group[g]].bCalcCOM = TRUE;
1455 /* With non-zero rate the reference value is set at every step */
1456 if (pcrd->rate == 0)
1458 /* Initialize the constant reference value */
1459 pcrd->value_ref = pcrd->init;
1463 pull->ePBC = ir->ePBC;
1466 case epbcNONE: pull->npbcdim = 0; break;
1467 case epbcXY: pull->npbcdim = 2; break;
1468 default: pull->npbcdim = 3; break;
1473 gmx_bool bAbs, bCos;
1476 for (c = 0; c < pull->ncoord; c++)
1478 if (pull->group[pull->coord[c].group[0]].nat == 0 ||
1479 pull->group[pull->coord[c].group[1]].nat == 0)
1485 fprintf(fplog, "\n");
1486 if (pull->bPotential)
1488 fprintf(fplog, "Will apply potential COM pulling\n");
1490 if (pull->bConstraint)
1492 fprintf(fplog, "Will apply constraint COM pulling\n");
1494 fprintf(fplog, "with %d pull coordinate%s and %d group%s\n",
1495 pull->ncoord, pull->ncoord == 1 ? "" : "s",
1496 pull->ngroup, pull->ngroup == 1 ? "" : "s");
1499 fprintf(fplog, "with an absolute reference\n");
1502 for (g = 0; g < pull->ngroup; g++)
1504 if (pull->group[g].nat > 1 &&
1505 pull->group[g].pbcatom < 0)
1507 /* We are using cosine weighting */
1508 fprintf(fplog, "Cosine weighting is used for group %d\n", g);
1514 please_cite(fplog, "Engin2010");
1520 pull->dbuf_cyl = NULL;
1521 pull->bRefAt = FALSE;
1523 for (g = 0; g < pull->ngroup; g++)
1525 pgrp = &pull->group[g];
1526 pgrp->epgrppbc = epgrppbcNONE;
1529 /* There is an issue when a group is used in multiple coordinates
1530 * and constraints are applied in different dimensions with atoms
1531 * frozen in some, but not all dimensions.
1532 * Since there is only one mass array per group, we can't have
1533 * frozen/non-frozen atoms for different coords at the same time.
1534 * But since this is a very exotic case, we don't check for this.
1535 * A warning is printed in init_pull_group_index.
1538 gmx_bool bConstraint;
1539 ivec pulldim, pulldim_con;
1541 /* Loop over all pull coordinates to see along which dimensions
1542 * this group is pulled and if it is involved in constraints.
1544 bConstraint = FALSE;
1545 clear_ivec(pulldim);
1546 clear_ivec(pulldim_con);
1547 for (c = 0; c < pull->ncoord; c++)
1549 if (pull->coord[c].group[0] == g ||
1550 pull->coord[c].group[1] == g ||
1551 (pull->coord[c].eGeom == epullgDIRRELATIVE &&
1552 (pull->coord[c].group[2] == g ||
1553 pull->coord[c].group[3] == g)))
1555 for (m = 0; m < DIM; m++)
1557 if (pull->coord[c].dim[m] == 1)
1561 if (pull->coord[c].eType == epullCONSTRAINT)
1571 /* Determine if we need to take PBC into account for calculating
1572 * the COM's of the pull groups.
1574 for (m = 0; m < pull->npbcdim; m++)
1576 if (pulldim[m] == 1 && pgrp->nat > 1)
1578 if (pgrp->pbcatom >= 0)
1580 pgrp->epgrppbc = epgrppbcREFAT;
1581 pull->bRefAt = TRUE;
1587 gmx_fatal(FARGS, "Pull groups can not have relative weights and cosine weighting at same time");
1589 pgrp->epgrppbc = epgrppbcCOS;
1590 if (pull->cosdim >= 0 && pull->cosdim != m)
1592 gmx_fatal(FARGS, "Can only use cosine weighting with pulling in one dimension (use mdp option pull-coord?-dim)");
1598 /* Set the indices */
1599 init_pull_group_index(fplog, cr, g, pgrp,
1600 bConstraint, pulldim_con,
1605 /* Absolute reference, set the inverse mass to zero.
1606 * This is only relevant (and used) with constraint pulling.
1613 /* If we use cylinder coordinates, do some initialising for them */
1614 if (pull->bCylinder)
1616 snew(pull->dyna, pull->ncoord);
1618 for (c = 0; c < pull->ncoord; c++)
1620 const t_pull_coord *pcrd;
1622 pcrd = &pull->coord[c];
1624 if (pcrd->eGeom == epullgCYL)
1626 if (pull->group[pcrd->group[0]].nat == 0)
1628 gmx_fatal(FARGS, "A cylinder pull group is not supported when using absolute reference!\n");
1634 /* We still need to initialize the PBC reference coordinates */
1635 pull->bSetPBCatoms = TRUE;
1637 /* Only do I/O when we are doing dynamics and if we are the MASTER */
1642 if (pull->nstxout > 0)
1644 pull->out_x = open_pull_out(opt2fn("-px", nfile, fnm), pull, oenv,
1647 if (pull->nstfout > 0)
1649 pull->out_f = open_pull_out(opt2fn("-pf", nfile, fnm), pull, oenv,
1655 void finish_pull(t_pull *pull)
1659 gmx_fio_fclose(pull->out_x);
1663 gmx_fio_fclose(pull->out_f);