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.
61 #include "mtop_util.h"
63 #include "gmx_ga2la.h"
66 static void pull_print_x_grp(FILE *out, gmx_bool bRef, ivec dim, t_pullgrp *pgrp)
70 for (m = 0; m < DIM; m++)
74 fprintf(out, "\t%g", bRef ? pgrp->x[m] : pgrp->dr[m]);
79 static void pull_print_x(FILE *out, t_pull *pull, double t)
83 fprintf(out, "%.4f", t);
87 for (g = 1; g < 1+pull->ngrp; g++)
89 pull_print_x_grp(out, TRUE, pull->dim, &pull->dyna[g]);
90 pull_print_x_grp(out, FALSE, pull->dim, &pull->grp[g]);
95 for (g = 0; g < 1+pull->ngrp; g++)
97 if (pull->grp[g].nat > 0)
99 pull_print_x_grp(out, g == 0, pull->dim, &pull->grp[g]);
106 static void pull_print_f(FILE *out, t_pull *pull, double t)
110 fprintf(out, "%.4f", t);
112 for (g = 1; g < 1+pull->ngrp; g++)
114 if (pull->eGeom == epullgPOS)
116 for (d = 0; d < DIM; d++)
120 fprintf(out, "\t%g", pull->grp[g].f[d]);
126 fprintf(out, "\t%g", pull->grp[g].f_scal);
132 void pull_print_output(t_pull *pull, gmx_large_int_t step, double time)
134 if ((pull->nstxout != 0) && (step % pull->nstxout == 0))
136 pull_print_x(pull->out_x, pull, time);
139 if ((pull->nstfout != 0) && (step % pull->nstfout == 0))
141 pull_print_f(pull->out_f, pull, time);
145 static FILE *open_pull_out(const char *fn, t_pull *pull, const output_env_t oenv,
146 gmx_bool bCoord, unsigned long Flags)
150 char **setname, buf[10];
152 if (Flags & MD_APPENDFILES)
154 fp = gmx_fio_fopen(fn, "a+");
158 fp = gmx_fio_fopen(fn, "w+");
161 xvgr_header(fp, "Pull COM", "Time (ps)", "Position (nm)",
166 xvgr_header(fp, "Pull force", "Time (ps)", "Force (kJ/mol/nm)",
170 snew(setname, (1+pull->ngrp)*DIM);
172 for (g = 0; g < 1+pull->ngrp; g++)
174 if (pull->grp[g].nat > 0 &&
175 (g > 0 || (bCoord && !PULL_CYL(pull))))
177 if (bCoord || pull->eGeom == epullgPOS)
181 for (m = 0; m < DIM; m++)
185 sprintf(buf, "%d %s%c", g, "c", 'X'+m);
186 setname[nsets] = strdup(buf);
191 for (m = 0; m < DIM; m++)
195 sprintf(buf, "%d %s%c",
196 g, (bCoord && g > 0) ? "d" : "", 'X'+m);
197 setname[nsets] = strdup(buf);
204 sprintf(buf, "%d", g);
205 setname[nsets] = strdup(buf);
210 if (bCoord || nsets > 1)
212 xvgr_legend(fp, nsets, (const char**)setname, oenv);
214 for (g = 0; g < nsets; g++)
224 /* Apply forces in a mass weighted fashion */
225 static void apply_forces_grp(t_pullgrp *pgrp, t_mdatoms * md,
227 dvec f_pull, int sign, rvec *f)
229 int i, ii, m, start, end;
230 double wmass, inv_wm;
233 end = md->homenr + start;
235 inv_wm = pgrp->wscale*pgrp->invtm;
237 for (i = 0; i < pgrp->nat_loc; i++)
239 ii = pgrp->ind_loc[i];
240 wmass = md->massT[ii];
241 if (pgrp->weight_loc)
243 wmass *= pgrp->weight_loc[i];
246 for (m = 0; m < DIM; m++)
248 f[ii][m] += sign * wmass * f_pull[m] * inv_wm;
253 /* Apply forces in a mass weighted fashion */
254 static void apply_forces(t_pull * pull, t_mdatoms * md, gmx_ga2la_t ga2la,
260 for (i = 1; i < pull->ngrp+1; i++)
262 pgrp = &(pull->grp[i]);
263 apply_forces_grp(pgrp, md, ga2la, pgrp->f, 1, f);
264 if (pull->grp[0].nat)
268 apply_forces_grp(&(pull->dyna[i]), md, ga2la, pgrp->f, -1, f);
272 apply_forces_grp(&(pull->grp[0]), md, ga2la, pgrp->f, -1, f);
278 static double max_pull_distance2(const t_pull *pull, const t_pbc *pbc)
283 max_d2 = GMX_DOUBLE_MAX;
285 if (pull->eGeom != epullgDIRPBC)
287 for (m = 0; m < pbc->ndim_ePBC; m++)
289 if (pull->dim[m] != 0)
291 max_d2 = min(max_d2, norm2(pbc->box[m]));
299 static void get_pullgrps_dr(const t_pull *pull, const t_pbc *pbc, int g, double t,
300 dvec xg, dvec xref, double max_dist2,
303 t_pullgrp *pref, *pgrp;
305 dvec xrefr, dref = {0, 0, 0};
308 pgrp = &pull->grp[g];
310 copy_dvec(xref, xrefr);
312 if (pull->eGeom == epullgDIRPBC)
314 for (m = 0; m < DIM; m++)
316 dref[m] = (pgrp->init[0] + pgrp->rate*t)*pull->grp[g].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 of pull group %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", g, sqrt(dr2), sqrt(max_dist2));
335 if (pull->eGeom == epullgDIRPBC)
341 static void get_pullgrp_dr(const t_pull *pull, const t_pbc *pbc, int g, double t,
346 if (pull->eGeom == epullgDIRPBC)
352 md2 = max_pull_distance2(pull, pbc);
355 get_pullgrps_dr(pull, pbc, g, t,
357 PULL_CYL(pull) ? pull->dyna[g].x : pull->grp[0].x,
362 void get_pullgrp_distance(t_pull *pull, t_pbc *pbc, int g, double t,
365 static gmx_bool bWarned = FALSE; /* TODO: this should be fixed for thread-safety,
366 but is fairly benign */
372 pgrp = &pull->grp[g];
374 get_pullgrp_dr(pull, pbc, g, t, dr);
376 if (pull->eGeom == epullgPOS)
378 for (m = 0; m < DIM; m++)
380 ref[m] = pgrp->init[m] + pgrp->rate*t*pgrp->vec[m];
385 ref[0] = pgrp->init[0] + pgrp->rate*t;
391 /* Pull along the vector between the com's */
392 if (ref[0] < 0 && !bWarned)
394 fprintf(stderr, "\nPull reference distance for group %d is negative (%f)\n", g, ref[0]);
400 /* With no vector we can not determine the direction for the force,
401 * so we set the force to zero.
407 /* Determine the deviation */
408 dev[0] = drs - ref[0];
416 for (m = 0; m < DIM; m++)
418 inpr += pgrp->vec[m]*dr[m];
420 dev[0] = inpr - ref[0];
423 /* Determine the difference of dr and ref along each dimension */
424 for (m = 0; m < DIM; m++)
426 dev[m] = (dr[m] - ref[m])*pull->dim[m];
432 void clear_pull_forces(t_pull *pull)
436 /* Zeroing the forces is only required for constraint pulling.
437 * It can happen that multiple constraint steps need to be applied
438 * and therefore the constraint forces need to be accumulated.
440 for (i = 0; i < 1+pull->ngrp; i++)
442 clear_dvec(pull->grp[i].f);
443 pull->grp[i].f_scal = 0;
447 /* Apply constraint using SHAKE */
448 static void do_constraint(t_pull *pull, t_mdatoms *md, t_pbc *pbc,
450 gmx_bool bMaster, tensor vir,
454 dvec *r_ij; /* x[i] com of i in prev. step. Obeys constr. -> r_ij[i] */
455 dvec unc_ij; /* xp[i] com of i this step, before constr. -> unc_ij */
457 dvec *rinew; /* current 'new' position of group i */
458 dvec *rjnew; /* current 'new' position of group j */
461 double lambda, rm, mass, invdt = 0;
462 gmx_bool bConverged_all, bConverged = FALSE;
463 int niter = 0, g, ii, j, m, max_iter = 100;
464 double q, a, b, c; /* for solving the quadratic equation,
465 see Num. Recipes in C ed 2 p. 184 */
466 dvec *dr; /* correction for group i */
467 dvec ref_dr; /* correction for group j */
468 dvec f; /* the pull force */
470 t_pullgrp *pdyna, *pgrp, *pref;
472 snew(r_ij, pull->ngrp+1);
475 snew(rjnew, pull->ngrp+1);
481 snew(dr, pull->ngrp+1);
482 snew(rinew, pull->ngrp+1);
484 /* copy the current unconstrained positions for use in iterations. We
485 iterate until rinew[i] and rjnew[j] obey the constraints. Then
486 rinew - pull.x_unc[i] is the correction dr to group i */
487 for (g = 1; g < 1+pull->ngrp; g++)
489 copy_dvec(pull->grp[g].xp, rinew[g]);
493 for (g = 1; g < 1+pull->ngrp; g++)
495 copy_dvec(pull->dyna[g].xp, rjnew[g]);
500 copy_dvec(pull->grp[0].xp, rjnew[0]);
503 /* Determine the constraint directions from the old positions */
504 for (g = 1; g < 1+pull->ngrp; g++)
506 get_pullgrp_dr(pull, pbc, g, t, r_ij[g]);
507 /* Store the difference vector at time t for printing */
508 copy_dvec(r_ij[g], pull->grp[g].dr);
511 fprintf(debug, "Pull group %d dr %f %f %f\n",
512 g, r_ij[g][XX], r_ij[g][YY], r_ij[g][ZZ]);
515 if (pull->eGeom == epullgDIR || pull->eGeom == epullgDIRPBC)
517 /* Select the component along vec */
519 for (m = 0; m < DIM; m++)
521 a += pull->grp[g].vec[m]*r_ij[g][m];
523 for (m = 0; m < DIM; m++)
525 r_ij[g][m] = a*pull->grp[g].vec[m];
530 bConverged_all = FALSE;
531 while (!bConverged_all && niter < max_iter)
533 bConverged_all = TRUE;
535 /* loop over all constraints */
536 for (g = 1; g < 1+pull->ngrp; g++)
538 pgrp = &pull->grp[g];
541 pref = &pull->dyna[g];
545 pref = &pull->grp[0];
548 /* Get the current difference vector */
549 get_pullgrps_dr(pull, pbc, g, t, rinew[g], rjnew[PULL_CYL(pull) ? g : 0],
552 if (pull->eGeom == epullgPOS)
554 for (m = 0; m < DIM; m++)
556 ref[m] = pgrp->init[m] + pgrp->rate*t*pgrp->vec[m];
561 ref[0] = pgrp->init[0] + pgrp->rate*t;
562 /* Keep the compiler happy */
569 fprintf(debug, "Pull group %d, iteration %d\n", g, niter);
572 rm = 1.0/(pull->grp[g].invtm + pref->invtm);
579 gmx_fatal(FARGS, "The pull constraint reference distance for group %d is <= 0 (%f)", g, ref[0]);
582 a = diprod(r_ij[g], r_ij[g]);
583 b = diprod(unc_ij, r_ij[g])*2;
584 c = diprod(unc_ij, unc_ij) - dsqr(ref[0]);
588 q = -0.5*(b - sqrt(b*b - 4*a*c));
593 q = -0.5*(b + sqrt(b*b - 4*a*c));
600 "Pull ax^2+bx+c=0: a=%e b=%e c=%e lambda=%e\n",
604 /* The position corrections dr due to the constraints */
605 dsvmul(-lambda*rm*pgrp->invtm, r_ij[g], dr[g]);
606 dsvmul( lambda*rm*pref->invtm, r_ij[g], ref_dr);
611 /* A 1-dimensional constraint along a vector */
613 for (m = 0; m < DIM; m++)
615 vec[m] = pgrp->vec[m];
616 a += unc_ij[m]*vec[m];
618 /* Select only the component along the vector */
619 dsvmul(a, vec, unc_ij);
623 fprintf(debug, "Pull inpr %e lambda: %e\n", a, lambda);
626 /* The position corrections dr due to the constraints */
627 dsvmul(-lambda*rm*pull->grp[g].invtm, vec, dr[g]);
628 dsvmul( lambda*rm* pref->invtm, vec, ref_dr);
631 for (m = 0; m < DIM; m++)
635 lambda = r_ij[g][m] - ref[m];
636 /* The position corrections dr due to the constraints */
637 dr[g][m] = -lambda*rm*pull->grp[g].invtm;
638 ref_dr[m] = lambda*rm*pref->invtm;
652 j = (PULL_CYL(pull) ? g : 0);
653 get_pullgrps_dr(pull, pbc, g, t, rinew[g], rjnew[j], -1, tmp);
654 get_pullgrps_dr(pull, pbc, g, t, dr[g], ref_dr, -1, tmp3);
656 "Pull cur %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
657 rinew[g][0], rinew[g][1], rinew[g][2],
658 rjnew[j][0], rjnew[j][1], rjnew[j][2], dnorm(tmp));
659 if (pull->eGeom == epullgPOS)
662 "Pull ref %8.5f %8.5f %8.5f\n",
663 pgrp->vec[0], pgrp->vec[1], pgrp->vec[2]);
668 "Pull ref %8s %8s %8s %8s %8s %8s d: %8.5f %8.5f %8.5f\n",
669 "", "", "", "", "", "", ref[0], ref[1], ref[2]);
672 "Pull cor %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
673 dr[g][0], dr[g][1], dr[g][2],
674 ref_dr[0], ref_dr[1], ref_dr[2],
677 "Pull cor %10.7f %10.7f %10.7f\n",
678 dr[g][0], dr[g][1], dr[g][2]);
681 /* Update the COMs with dr */
682 dvec_inc(rinew[g], dr[g]);
683 dvec_inc(rjnew[PULL_CYL(pull) ? g : 0], ref_dr);
686 /* Check if all constraints are fullfilled now */
687 for (g = 1; g < 1+pull->ngrp; g++)
689 pgrp = &pull->grp[g];
691 if (pull->eGeom == epullgPOS)
693 for (m = 0; m < DIM; m++)
695 ref[m] = pgrp->init[m] + pgrp->rate*t*pgrp->vec[m];
700 ref[0] = pgrp->init[0] + pgrp->rate*t;
701 /* Keep the compiler happy */
706 get_pullgrps_dr(pull, pbc, g, t, rinew[g], rjnew[PULL_CYL(pull) ? g : 0],
712 bConverged = fabs(dnorm(unc_ij) - ref[0]) < pull->constr_tol;
717 for (m = 0; m < DIM; m++)
719 vec[m] = pgrp->vec[m];
721 inpr = diprod(unc_ij, vec);
722 dsvmul(inpr, vec, unc_ij);
724 fabs(diprod(unc_ij, vec) - ref[0]) < pull->constr_tol;
728 for (m = 0; m < DIM; m++)
731 fabs(unc_ij[m] - ref[m]) >= pull->constr_tol)
743 fprintf(debug, "NOT CONVERGED YET: Group %d:"
744 "d_ref = %f %f %f, current d = %f\n",
745 g, ref[0], ref[1], ref[2], dnorm(unc_ij));
748 bConverged_all = FALSE;
753 /* if after all constraints are dealt with and bConverged is still TRUE
754 we're finished, if not we do another iteration */
756 if (niter > max_iter)
758 gmx_fatal(FARGS, "Too many iterations for constraint run: %d", niter);
761 /* DONE ITERATING, NOW UPDATE COORDINATES AND CALC. CONSTRAINT FORCES */
768 /* update the normal groups */
769 for (g = 1; g < 1+pull->ngrp; g++)
771 pgrp = &pull->grp[g];
772 /* get the final dr and constraint force for group i */
773 dvec_sub(rinew[g], pgrp->xp, dr[g]);
774 /* select components of dr */
775 for (m = 0; m < DIM; m++)
777 dr[g][m] *= pull->dim[m];
779 dsvmul(1.0/(pgrp->invtm*dt*dt), dr[g], f);
780 dvec_inc(pgrp->f, f);
784 for (m = 0; m < DIM; m++)
786 pgrp->f_scal += r_ij[g][m]*f[m]/dnorm(r_ij[g]);
792 for (m = 0; m < DIM; m++)
794 pgrp->f_scal += pgrp->vec[m]*f[m];
803 /* Add the pull contribution to the virial */
804 for (j = 0; j < DIM; j++)
806 for (m = 0; m < DIM; m++)
808 vir[j][m] -= 0.5*f[j]*r_ij[g][m];
813 /* update the atom positions */
814 copy_dvec(dr[g], tmp);
815 for (j = 0; j < pgrp->nat_loc; j++)
817 ii = pgrp->ind_loc[j];
818 if (pgrp->weight_loc)
820 dsvmul(pgrp->wscale*pgrp->weight_loc[j], dr[g], tmp);
822 for (m = 0; m < DIM; m++)
828 for (m = 0; m < DIM; m++)
830 v[ii][m] += invdt*tmp[m];
836 /* update the reference groups */
839 /* update the dynamic reference groups */
840 for (g = 1; g < 1+pull->ngrp; g++)
842 pdyna = &pull->dyna[g];
843 dvec_sub(rjnew[g], pdyna->xp, ref_dr);
844 /* select components of ref_dr */
845 for (m = 0; m < DIM; m++)
847 ref_dr[m] *= pull->dim[m];
850 for (j = 0; j < pdyna->nat_loc; j++)
852 /* reset the atoms with dr, weighted by w_i */
853 dsvmul(pdyna->wscale*pdyna->weight_loc[j], ref_dr, tmp);
854 ii = pdyna->ind_loc[j];
855 for (m = 0; m < DIM; m++)
861 for (m = 0; m < DIM; m++)
863 v[ii][m] += invdt*tmp[m];
871 pgrp = &pull->grp[0];
872 /* update the reference group */
873 dvec_sub(rjnew[0], pgrp->xp, ref_dr);
874 /* select components of ref_dr */
875 for (m = 0; m < DIM; m++)
877 ref_dr[m] *= pull->dim[m];
880 copy_dvec(ref_dr, tmp);
881 for (j = 0; j < pgrp->nat_loc; j++)
883 ii = pgrp->ind_loc[j];
884 if (pgrp->weight_loc)
886 dsvmul(pgrp->wscale*pgrp->weight_loc[j], ref_dr, tmp);
888 for (m = 0; m < DIM; m++)
894 for (m = 0; m < DIM; m++)
896 v[ii][m] += invdt*tmp[m];
902 /* finished! I hope. Give back some memory */
909 /* Pulling with a harmonic umbrella potential or constant force */
910 static void do_pull_pot(int ePull,
911 t_pull *pull, t_pbc *pbc, double t, real lambda,
912 real *V, tensor vir, real *dVdl)
920 /* loop over the groups that are being pulled */
923 for (g = 1; g < 1+pull->ngrp; g++)
925 pgrp = &pull->grp[g];
926 get_pullgrp_distance(pull, pbc, g, t, pgrp->dr, dev);
928 k = (1.0 - lambda)*pgrp->k + lambda*pgrp->kB;
929 dkdl = pgrp->kB - pgrp->k;
934 ndr = dnorm(pgrp->dr);
936 if (ePull == epullUMBRELLA)
938 pgrp->f_scal = -k*dev[0];
939 *V += 0.5* k*dsqr(dev[0]);
940 *dVdl += 0.5*dkdl*dsqr(dev[0]);
948 for (m = 0; m < DIM; m++)
950 pgrp->f[m] = pgrp->f_scal*pgrp->dr[m]*invdr;
956 if (ePull == epullUMBRELLA)
958 pgrp->f_scal = -k*dev[0];
959 *V += 0.5* k*dsqr(dev[0]);
960 *dVdl += 0.5*dkdl*dsqr(dev[0]);
965 for (m = 0; m < DIM; m++)
967 ndr += pgrp->vec[m]*pgrp->dr[m];
973 for (m = 0; m < DIM; m++)
975 pgrp->f[m] = pgrp->f_scal*pgrp->vec[m];
979 for (m = 0; m < DIM; m++)
981 if (ePull == epullUMBRELLA)
983 pgrp->f[m] = -k*dev[m];
984 *V += 0.5* k*dsqr(dev[m]);
985 *dVdl += 0.5*dkdl*dsqr(dev[m]);
989 pgrp->f[m] = -k*pull->dim[m];
990 *V += k*pgrp->dr[m]*pull->dim[m];
991 *dVdl += dkdl*pgrp->dr[m]*pull->dim[m];
999 /* Add the pull contribution to the virial */
1000 for (j = 0; j < DIM; j++)
1002 for (m = 0; m < DIM; m++)
1004 vir[j][m] -= 0.5*pgrp->f[j]*pgrp->dr[m];
1011 real pull_potential(int ePull, t_pull *pull, t_mdatoms *md, t_pbc *pbc,
1012 t_commrec *cr, double t, real lambda,
1013 rvec *x, rvec *f, tensor vir, real *dvdlambda)
1017 pull_calc_coms(cr, pull, md, pbc, t, x, NULL);
1019 do_pull_pot(ePull, pull, pbc, t, lambda,
1020 &V, pull->bVirial && MASTER(cr) ? vir : NULL, &dVdl);
1022 /* Distribute forces over pulled groups */
1023 apply_forces(pull, md, DOMAINDECOMP(cr) ? cr->dd->ga2la : NULL, f);
1030 return (MASTER(cr) ? V : 0.0);
1033 void pull_constraint(t_pull *pull, t_mdatoms *md, t_pbc *pbc,
1034 t_commrec *cr, double dt, double t,
1035 rvec *x, rvec *xp, rvec *v, tensor vir)
1037 pull_calc_coms(cr, pull, md, pbc, t, x, xp);
1039 do_constraint(pull, md, pbc, xp, v, pull->bVirial && MASTER(cr), vir, dt, t);
1042 static void make_local_pull_group(gmx_ga2la_t ga2la,
1043 t_pullgrp *pg, int start, int end)
1048 for (i = 0; i < pg->nat; i++)
1053 if (!ga2la_get_home(ga2la, ii, &ii))
1058 if (ii >= start && ii < end)
1060 /* This is a home atom, add it to the local pull group */
1061 if (pg->nat_loc >= pg->nalloc_loc)
1063 pg->nalloc_loc = over_alloc_dd(pg->nat_loc+1);
1064 srenew(pg->ind_loc, pg->nalloc_loc);
1065 if (pg->epgrppbc == epgrppbcCOS || pg->weight)
1067 srenew(pg->weight_loc, pg->nalloc_loc);
1070 pg->ind_loc[pg->nat_loc] = ii;
1073 pg->weight_loc[pg->nat_loc] = pg->weight[i];
1080 void dd_make_local_pull_groups(gmx_domdec_t *dd, t_pull *pull, t_mdatoms *md)
1094 if (pull->grp[0].nat > 0)
1096 make_local_pull_group(ga2la, &pull->grp[0], md->start, md->start+md->homenr);
1098 for (g = 1; g < 1+pull->ngrp; g++)
1100 make_local_pull_group(ga2la, &pull->grp[g], md->start, md->start+md->homenr);
1104 static void init_pull_group_index(FILE *fplog, t_commrec *cr,
1106 int g, t_pullgrp *pg, ivec pulldims,
1107 gmx_mtop_t *mtop, t_inputrec *ir, real lambda)
1109 int i, ii, d, nfrozen, ndim;
1111 double tmass, wmass, wwmass;
1113 gmx_ga2la_t ga2la = NULL;
1114 gmx_groups_t *groups;
1115 gmx_mtop_atomlookup_t alook;
1118 bDomDec = (cr && DOMAINDECOMP(cr));
1121 ga2la = cr->dd->ga2la;
1124 if (EI_ENERGY_MINIMIZATION(ir->eI) || ir->eI == eiBD)
1126 /* There are no masses in the integrator.
1127 * But we still want to have the correct mass-weighted COMs.
1128 * So we store the real masses in the weights.
1129 * We do not set nweight, so these weights do not end up in the tpx file.
1131 if (pg->nweight == 0)
1133 snew(pg->weight, pg->nat);
1142 pg->weight_loc = NULL;
1146 pg->nat_loc = pg->nat;
1147 pg->ind_loc = pg->ind;
1148 if (pg->epgrppbc == epgrppbcCOS)
1150 snew(pg->weight_loc, pg->nat);
1154 pg->weight_loc = pg->weight;
1158 groups = &mtop->groups;
1160 alook = gmx_mtop_atomlookup_init(mtop);
1166 for (i = 0; i < pg->nat; i++)
1169 gmx_mtop_atomnr_to_atom(alook, ii, &atom);
1170 if (cr && PAR(cr) && !bDomDec && ii >= start && ii < end)
1172 pg->ind_loc[pg->nat_loc++] = ii;
1174 if (ir->opts.nFreeze)
1176 for (d = 0; d < DIM; d++)
1178 if (pulldims[d] && ir->opts.nFreeze[ggrpnr(groups, egcFREEZE, ii)][d])
1184 if (ir->efep == efepNO)
1190 m = (1 - lambda)*atom->m + lambda*atom->mB;
1192 if (pg->nweight > 0)
1200 if (EI_ENERGY_MINIMIZATION(ir->eI))
1202 /* Move the mass to the weight */
1207 else if (ir->eI == eiBD)
1211 mbd = ir->bd_fric*ir->delta_t;
1215 if (groups->grpnr[egcTC] == NULL)
1217 mbd = ir->delta_t/ir->opts.tau_t[0];
1221 mbd = ir->delta_t/ir->opts.tau_t[groups->grpnr[egcTC][ii]];
1233 gmx_mtop_atomlookup_destroy(alook);
1237 gmx_fatal(FARGS, "The total%s mass of pull group %d is zero",
1238 pg->weight ? " weighted" : "", g);
1243 "Pull group %d: %5d atoms, mass %9.3f", g, pg->nat, tmass);
1244 if (pg->weight || EI_ENERGY_MINIMIZATION(ir->eI) || ir->eI == eiBD)
1246 fprintf(fplog, ", weighted mass %9.3f", wmass*wmass/wwmass);
1248 if (pg->epgrppbc == epgrppbcCOS)
1250 fprintf(fplog, ", cosine weighting will be used");
1252 fprintf(fplog, "\n");
1257 /* A value > 0 signals not frozen, it is updated later */
1263 for (d = 0; d < DIM; d++)
1265 ndim += pulldims[d]*pg->nat;
1267 if (fplog && nfrozen > 0 && nfrozen < ndim)
1270 "\nWARNING: In pull group %d some, but not all of the degrees of freedom\n"
1271 " that are subject to pulling are frozen.\n"
1272 " For pulling the whole group will be frozen.\n\n",
1280 void init_pull(FILE *fplog, t_inputrec *ir, int nfile, const t_filenm fnm[],
1281 gmx_mtop_t *mtop, t_commrec *cr, const output_env_t oenv, real lambda,
1282 gmx_bool bOutFile, unsigned long Flags)
1286 int g, start = 0, end = 0, m;
1291 pull->ePBC = ir->ePBC;
1294 case epbcNONE: pull->npbcdim = 0; break;
1295 case epbcXY: pull->npbcdim = 2; break;
1296 default: pull->npbcdim = 3; break;
1301 fprintf(fplog, "\nWill apply %s COM pulling in geometry '%s'\n",
1302 EPULLTYPE(ir->ePull), EPULLGEOM(pull->eGeom));
1303 if (pull->grp[0].nat > 0)
1305 fprintf(fplog, "between a reference group and %d group%s\n",
1306 pull->ngrp, pull->ngrp == 1 ? "" : "s");
1310 fprintf(fplog, "with an absolute reference on %d group%s\n",
1311 pull->ngrp, pull->ngrp == 1 ? "" : "s");
1314 for (g = 0; g < pull->ngrp+1; g++)
1316 if (pull->grp[g].nat > 1 &&
1317 pull->grp[g].pbcatom < 0)
1319 /* We are using cosine weighting */
1320 fprintf(fplog, "Cosine weighting is used for group %d\n", g);
1326 please_cite(fplog, "Engin2010");
1330 /* We always add the virial contribution,
1331 * except for geometry = direction_periodic where this is impossible.
1333 pull->bVirial = (pull->eGeom != epullgDIRPBC);
1334 if (getenv("GMX_NO_PULLVIR") != NULL)
1338 fprintf(fplog, "Found env. var., will not add the virial contribution of the COM pull forces\n");
1340 pull->bVirial = FALSE;
1343 if (cr && PARTDECOMP(cr))
1345 pd_at_range(cr, &start, &end);
1349 pull->dbuf_cyl = NULL;
1350 pull->bRefAt = FALSE;
1352 for (g = 0; g < pull->ngrp+1; g++)
1354 pgrp = &pull->grp[g];
1355 pgrp->epgrppbc = epgrppbcNONE;
1358 /* Determine if we need to take PBC into account for calculating
1359 * the COM's of the pull groups.
1361 for (m = 0; m < pull->npbcdim; m++)
1363 if (pull->dim[m] && pgrp->nat > 1)
1365 if (pgrp->pbcatom >= 0)
1367 pgrp->epgrppbc = epgrppbcREFAT;
1368 pull->bRefAt = TRUE;
1374 gmx_fatal(FARGS, "Pull groups can not have relative weights and cosine weighting at same time");
1376 pgrp->epgrppbc = epgrppbcCOS;
1377 if (pull->cosdim >= 0 && pull->cosdim != m)
1379 gmx_fatal(FARGS, "Can only use cosine weighting with pulling in one dimension (use mdp option pull_dim)");
1385 /* Set the indices */
1386 init_pull_group_index(fplog, cr, start, end, g, pgrp, pull->dim, mtop, ir, lambda);
1387 if (PULL_CYL(pull) && pgrp->invtm == 0)
1389 gmx_fatal(FARGS, "Can not have frozen atoms in a cylinder pull group");
1394 /* Absolute reference, set the inverse mass to zero */
1400 /* if we use dynamic reference groups, do some initialising for them */
1403 if (pull->grp[0].nat == 0)
1405 gmx_fatal(FARGS, "Dynamic reference groups are not supported when using absolute reference!\n");
1407 snew(pull->dyna, pull->ngrp+1);
1410 /* Only do I/O when we are doing dynamics and if we are the MASTER */
1415 if (pull->nstxout > 0)
1417 pull->out_x = open_pull_out(opt2fn("-px", nfile, fnm), pull, oenv, TRUE, Flags);
1419 if (pull->nstfout > 0)
1421 pull->out_f = open_pull_out(opt2fn("-pf", nfile, fnm), pull, oenv,
1427 void finish_pull(FILE *fplog, t_pull *pull)
1431 gmx_fio_fclose(pull->out_x);
1435 gmx_fio_fclose(pull->out_f);