Use full path for legacyheaders
[alexxy/gromacs.git] / src / gromacs / pulling / pull.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 #include "config.h"
38
39 #include <math.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "gromacs/utility/futil.h"
45 #include "gromacs/legacyheaders/typedefs.h"
46 #include "gromacs/legacyheaders/types/commrec.h"
47 #include "gromacs/legacyheaders/network.h"
48 #include "pull.h"
49 #include "gromacs/legacyheaders/names.h"
50 #include "gromacs/pbcutil/pbc.h"
51 #include "gromacs/topology/mtop_util.h"
52 #include "gromacs/legacyheaders/mdrun.h"
53 #include "gromacs/legacyheaders/gmx_ga2la.h"
54 #include "gromacs/legacyheaders/copyrite.h"
55 #include "gromacs/legacyheaders/macros.h"
56
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"
62
63 static void pull_print_group_x(FILE *out, ivec dim, const t_pull_group *pgrp)
64 {
65     int m;
66
67     for (m = 0; m < DIM; m++)
68     {
69         if (dim[m])
70         {
71             fprintf(out, "\t%g", pgrp->x[m]);
72         }
73     }
74 }
75
76 static void pull_print_coord_dr(FILE *out, ivec dim, const t_pull_coord *pcrd)
77 {
78     int m;
79
80     for (m = 0; m < DIM; m++)
81     {
82         if (dim[m])
83         {
84             fprintf(out, "\t%g", pcrd->dr[m]);
85         }
86     }
87 }
88
89 static void pull_print_x(FILE *out, t_pull *pull, double t)
90 {
91     int                 c;
92     const t_pull_coord *pcrd;
93
94     fprintf(out, "%.4f", t);
95
96     for (c = 0; c < pull->ncoord; c++)
97     {
98         pcrd = &pull->coord[c];
99
100         if (pull->bPrintRef)
101         {
102             if (PULL_CYL(pull))
103             {
104                 pull_print_group_x(out, pull->dim, &pull->dyna[c]);
105             }
106             else
107             {
108                 pull_print_group_x(out, pull->dim, &pull->group[pcrd->group[0]]);
109             }
110         }
111         pull_print_coord_dr(out, pull->dim, pcrd);
112     }
113     fprintf(out, "\n");
114 }
115
116 static void pull_print_f(FILE *out, t_pull *pull, double t)
117 {
118     int c, d;
119
120     fprintf(out, "%.4f", t);
121
122     for (c = 0; c < pull->ncoord; c++)
123     {
124         fprintf(out, "\t%g", pull->coord[c].f_scal);
125     }
126     fprintf(out, "\n");
127 }
128
129 void pull_print_output(t_pull *pull, gmx_int64_t step, double time)
130 {
131     if ((pull->nstxout != 0) && (step % pull->nstxout == 0))
132     {
133         pull_print_x(pull->out_x, pull, time);
134     }
135
136     if ((pull->nstfout != 0) && (step % pull->nstfout == 0))
137     {
138         pull_print_f(pull->out_f, pull, time);
139     }
140 }
141
142 static FILE *open_pull_out(const char *fn, t_pull *pull, const output_env_t oenv,
143                            gmx_bool bCoord, unsigned long Flags)
144 {
145     FILE  *fp;
146     int    nsets, c, m;
147     char **setname, buf[10];
148
149     if (Flags & MD_APPENDFILES)
150     {
151         fp = gmx_fio_fopen(fn, "a+");
152     }
153     else
154     {
155         fp = gmx_fio_fopen(fn, "w+");
156         if (bCoord)
157         {
158             xvgr_header(fp, "Pull COM",  "Time (ps)", "Position (nm)",
159                         exvggtXNY, oenv);
160         }
161         else
162         {
163             xvgr_header(fp, "Pull force", "Time (ps)", "Force (kJ/mol/nm)",
164                         exvggtXNY, oenv);
165         }
166
167         snew(setname, 2*pull->ncoord*DIM);
168         nsets = 0;
169         for (c = 0; c < pull->ncoord; c++)
170         {
171             if (bCoord)
172             {
173                 if (pull->bPrintRef)
174                 {
175                     for (m = 0; m < DIM; m++)
176                     {
177                         if (pull->dim[m])
178                         {
179                             sprintf(buf, "%d %s%c", c+1, "c", 'X'+m);
180                             setname[nsets] = gmx_strdup(buf);
181                             nsets++;
182                         }
183                     }
184                 }
185                 for (m = 0; m < DIM; m++)
186                 {
187                     if (pull->dim[m])
188                     {
189                         sprintf(buf, "%d %s%c", c+1, "d", 'X'+m);
190                         setname[nsets] = gmx_strdup(buf);
191                         nsets++;
192                     }
193                 }
194             }
195             else
196             {
197                 sprintf(buf, "%d", c+1);
198                 setname[nsets] = gmx_strdup(buf);
199                 nsets++;
200             }
201         }
202         if (nsets > 1)
203         {
204             xvgr_legend(fp, nsets, (const char**)setname, oenv);
205         }
206         for (c = 0; c < nsets; c++)
207         {
208             sfree(setname[c]);
209         }
210         sfree(setname);
211     }
212
213     return fp;
214 }
215
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)
219 {
220     int    i, ii, m;
221     double wmass, inv_wm;
222
223     inv_wm = pgrp->wscale*pgrp->invtm;
224
225     for (i = 0; i < pgrp->nat_loc; i++)
226     {
227         ii    = pgrp->ind_loc[i];
228         wmass = md->massT[ii];
229         if (pgrp->weight_loc)
230         {
231             wmass *= pgrp->weight_loc[i];
232         }
233
234         for (m = 0; m < DIM; m++)
235         {
236             f[ii][m] += sign * wmass * f_pull[m] * inv_wm;
237         }
238     }
239 }
240
241 /* Apply forces in a mass weighted fashion */
242 static void apply_forces(t_pull * pull, t_mdatoms * md, rvec *f)
243 {
244     int                 c;
245     const t_pull_coord *pcrd;
246
247     for (c = 0; c < pull->ncoord; c++)
248     {
249         pcrd = &pull->coord[c];
250
251         if (PULL_CYL(pull))
252         {
253             apply_forces_grp(&pull->dyna[c], md, pcrd->f, -1, f);
254         }
255         else
256         {
257             if (pull->group[pcrd->group[0]].nat > 0)
258             {
259                 apply_forces_grp(&pull->group[pcrd->group[0]], md, pcrd->f, -1, f);
260             }
261         }
262         apply_forces_grp(&pull->group[pcrd->group[1]], md, pcrd->f, 1, f);
263     }
264 }
265
266 static double max_pull_distance2(const t_pull *pull, const t_pbc *pbc)
267 {
268     double max_d2;
269     int    m;
270
271     max_d2 = GMX_DOUBLE_MAX;
272
273     if (pull->eGeom != epullgDIRPBC)
274     {
275         for (m = 0; m < pbc->ndim_ePBC; m++)
276         {
277             if (pull->dim[m] != 0)
278             {
279                 max_d2 = min(max_d2, norm2(pbc->box[m]));
280             }
281         }
282     }
283
284     return 0.25*max_d2;
285 }
286
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,
291                                   dvec dr)
292 {
293     const t_pull_group *pgrp0, *pgrp1;
294     int                 m;
295     dvec                xrefr, dref = {0, 0, 0};
296     double              dr2;
297
298     pgrp0 = &pull->group[pcrd->group[0]];
299     pgrp1 = &pull->group[pcrd->group[1]];
300
301     /* Only the first group can be an absolute reference, in that case nat=0 */
302     if (pgrp0->nat == 0)
303     {
304         for (m = 0; m < DIM; m++)
305         {
306             xref[m] = pcrd->origin[m];
307         }
308     }
309
310     copy_dvec(xref, xrefr);
311
312     if (pull->eGeom == epullgDIRPBC)
313     {
314         for (m = 0; m < DIM; m++)
315         {
316             dref[m] = (pcrd->init + pcrd->rate*t)*pcrd->vec[m];
317         }
318         /* Add the reference position, so we use the correct periodic image */
319         dvec_inc(xrefr, dref);
320     }
321
322     pbc_dx_d(pbc, xg, xrefr, dr);
323     dr2 = 0;
324     for (m = 0; m < DIM; m++)
325     {
326         dr[m] *= pull->dim[m];
327         dr2   += dr[m]*dr[m];
328     }
329     if (max_dist2 >= 0 && dr2 > 0.98*0.98*max_dist2)
330     {
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));
333     }
334
335     if (pull->eGeom == epullgDIRPBC)
336     {
337         dvec_inc(dr, dref);
338     }
339 }
340
341 static void get_pull_coord_dr(const t_pull *pull,
342                               int coord_ind,
343                               const t_pbc *pbc, double t,
344                               dvec dr)
345 {
346     double              md2;
347     const t_pull_coord *pcrd;
348
349     if (pull->eGeom == epullgDIRPBC)
350     {
351         md2 = -1;
352     }
353     else
354     {
355         md2 = max_pull_distance2(pull, pbc);
356     }
357
358     pcrd = &pull->coord[coord_ind];
359
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,
363                           md2,
364                           dr);
365 }
366
367 void get_pull_coord_distance(const t_pull *pull,
368                              int coord_ind,
369                              const t_pbc *pbc, double t,
370                              dvec dr, double *dev)
371 {
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;
375     int                 m;
376     double              ref, drs, inpr;
377
378     pcrd = &pull->coord[coord_ind];
379
380     get_pull_coord_dr(pull, coord_ind, pbc, t, dr);
381
382     ref = pcrd->init + pcrd->rate*t;
383
384     switch (pull->eGeom)
385     {
386         case epullgDIST:
387             /* Pull along the vector between the com's */
388             if (ref < 0 && !bWarned)
389             {
390                 fprintf(stderr, "\nPull reference distance for coordinate %d is negative (%f)\n", coord_ind+1, ref);
391                 bWarned = TRUE;
392             }
393             drs = dnorm(dr);
394             if (drs == 0)
395             {
396                 /* With no vector we can not determine the direction for the force,
397                  * so we set the force to zero.
398                  */
399                 *dev = 0;
400             }
401             else
402             {
403                 /* Determine the deviation */
404                 *dev = drs - ref;
405             }
406             break;
407         case epullgDIR:
408         case epullgDIRPBC:
409         case epullgCYL:
410             /* Pull along vec */
411             inpr = 0;
412             for (m = 0; m < DIM; m++)
413             {
414                 inpr += pcrd->vec[m]*dr[m];
415             }
416             *dev = inpr - ref;
417             break;
418     }
419 }
420
421 void clear_pull_forces(t_pull *pull)
422 {
423     int i;
424
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.
428      */
429     for (i = 0; i < pull->ncoord; i++)
430     {
431         clear_dvec(pull->coord[i].f);
432         pull->coord[i].f_scal = 0;
433     }
434 }
435
436 /* Apply constraint using SHAKE */
437 static void do_constraint(t_pull *pull, t_pbc *pbc,
438                           rvec *x, rvec *v,
439                           gmx_bool bMaster, tensor vir,
440                           double dt, double t)
441 {
442
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 */
447     double        ref;
448     dvec          vec;
449     double        d0, inpr;
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;
453     double        a;
454     dvec          f;       /* the pull force */
455     dvec          tmp, tmp3;
456     t_pull_group *pdyna, *pgrp0, *pgrp1;
457     t_pull_coord *pcrd;
458
459     snew(r_ij,   pull->ncoord);
460     snew(dr_tot, pull->ncoord);
461
462     snew(rnew, pull->ngroup);
463
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++)
468     {
469         copy_dvec(pull->group[g].xp, rnew[g]);
470     }
471     if (PULL_CYL(pull))
472     {
473         /* There is only one pull coordinate and reference group */
474         copy_dvec(pull->dyna[0].xp, rnew[pull->coord[0].group[0]]);
475     }
476
477     /* Determine the constraint directions from the old positions */
478     for (c = 0; c < pull->ncoord; c++)
479     {
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);
483         if (debug)
484         {
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]);
487         }
488
489         if (pull->eGeom == epullgDIR || pull->eGeom == epullgDIRPBC)
490         {
491             /* Select the component along vec */
492             a = 0;
493             for (m = 0; m < DIM; m++)
494             {
495                 a += pull->coord[c].vec[m]*r_ij[c][m];
496             }
497             for (m = 0; m < DIM; m++)
498             {
499                 r_ij[c][m] = a*pull->coord[c].vec[m];
500             }
501         }
502     }
503
504     bConverged_all = FALSE;
505     while (!bConverged_all && niter < max_iter)
506     {
507         bConverged_all = TRUE;
508
509         /* loop over all constraints */
510         for (c = 0; c < pull->ncoord; c++)
511         {
512             dvec dr0, dr1;
513
514             pcrd  = &pull->coord[c];
515             pgrp0 = &pull->group[pcrd->group[0]];
516             pgrp1 = &pull->group[pcrd->group[1]];
517
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]],
522                                   -1, unc_ij);
523
524             ref = pcrd->init + pcrd->rate*t;
525
526             if (debug)
527             {
528                 fprintf(debug, "Pull coord %d, iteration %d\n", c, niter);
529             }
530
531             rm = 1.0/(pgrp0->invtm + pgrp1->invtm);
532
533             switch (pull->eGeom)
534             {
535                 case epullgDIST:
536                     if (ref <= 0)
537                     {
538                         gmx_fatal(FARGS, "The pull constraint reference distance for group %d is <= 0 (%f)", c, ref);
539                     }
540
541                     {
542                         double q, c_a, c_b, c_c;
543
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);
547
548                         if (c_b < 0)
549                         {
550                             q      = -0.5*(c_b - sqrt(c_b*c_b - 4*c_a*c_c));
551                             lambda = -q/c_a;
552                         }
553                         else
554                         {
555                             q      = -0.5*(c_b + sqrt(c_b*c_b - 4*c_a*c_c));
556                             lambda = -c_c/q;
557                         }
558
559                         if (debug)
560                         {
561                             fprintf(debug,
562                                     "Pull ax^2+bx+c=0: a=%e b=%e c=%e lambda=%e\n",
563                                     c_a, c_b, c_c, lambda);
564                         }
565                     }
566
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]);
571                     break;
572                 case epullgDIR:
573                 case epullgDIRPBC:
574                 case epullgCYL:
575                     /* A 1-dimensional constraint along a vector */
576                     a = 0;
577                     for (m = 0; m < DIM; m++)
578                     {
579                         vec[m] = pcrd->vec[m];
580                         a     += unc_ij[m]*vec[m];
581                     }
582                     /* Select only the component along the vector */
583                     dsvmul(a, vec, unc_ij);
584                     lambda = a - ref;
585                     if (debug)
586                     {
587                         fprintf(debug, "Pull inpr %e lambda: %e\n", a, lambda);
588                     }
589
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;
594                     break;
595             }
596
597             /* DEBUG */
598             if (debug)
599             {
600                 int g0, g1;
601
602                 g0 = pcrd->group[0];
603                 g1 = pcrd->group[1];
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);
606                 fprintf(debug,
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));
610                 fprintf(debug,
611                         "Pull ref %8s %8s %8s   %8s %8s %8s d: %8.5f\n",
612                         "", "", "", "", "", "", ref);
613                 fprintf(debug,
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],
617                         dnorm(tmp3));
618             } /* END DEBUG */
619
620             /* Update the COMs with dr */
621             dvec_inc(rnew[pcrd->group[1]], dr1);
622             dvec_inc(rnew[pcrd->group[0]], dr0);
623         }
624
625         /* Check if all constraints are fullfilled now */
626         for (c = 0; c < pull->ncoord; c++)
627         {
628             pcrd = &pull->coord[c];
629             ref  = pcrd->init + pcrd->rate*t;
630
631             low_get_pull_coord_dr(pull, pcrd, pbc, t,
632                                   rnew[pcrd->group[1]],
633                                   rnew[pcrd->group[0]],
634                                   -1, unc_ij);
635
636             switch (pull->eGeom)
637             {
638                 case epullgDIST:
639                     bConverged = fabs(dnorm(unc_ij) - ref) < pull->constr_tol;
640                     break;
641                 case epullgDIR:
642                 case epullgDIRPBC:
643                 case epullgCYL:
644                     for (m = 0; m < DIM; m++)
645                     {
646                         vec[m] = pcrd->vec[m];
647                     }
648                     inpr = diprod(unc_ij, vec);
649                     dsvmul(inpr, vec, unc_ij);
650                     bConverged =
651                         fabs(diprod(unc_ij, vec) - ref) < pull->constr_tol;
652                     break;
653             }
654
655             if (!bConverged)
656             {
657                 if (debug)
658                 {
659                     fprintf(debug, "NOT CONVERGED YET: Group %d:"
660                             "d_ref = %f, current d = %f\n",
661                             g, ref, dnorm(unc_ij));
662                 }
663
664                 bConverged_all = FALSE;
665             }
666         }
667
668         niter++;
669         /* if after all constraints are dealt with and bConverged is still TRUE
670            we're finished, if not we do another iteration */
671     }
672     if (niter > max_iter)
673     {
674         gmx_fatal(FARGS, "Too many iterations for constraint run: %d", niter);
675     }
676
677     /* DONE ITERATING, NOW UPDATE COORDINATES AND CALC. CONSTRAINT FORCES */
678
679     if (v)
680     {
681         invdt = 1/dt;
682     }
683
684     /* update atoms in the groups */
685     for (g = 0; g < pull->ngroup; g++)
686     {
687         const t_pull_group *pgrp;
688         dvec                dr;
689
690         if (PULL_CYL(pull) && g == pull->coord[0].group[0])
691         {
692             pgrp = &pull->dyna[0];
693         }
694         else
695         {
696             pgrp = &pull->group[g];
697         }
698
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++)
703         {
704             dr[m] *= pull->dim[m];
705         }
706
707         /* update the atom positions */
708         copy_dvec(dr, tmp);
709         for (j = 0; j < pgrp->nat_loc; j++)
710         {
711             ii = pgrp->ind_loc[j];
712             if (pgrp->weight_loc)
713             {
714                 dsvmul(pgrp->wscale*pgrp->weight_loc[j], dr, tmp);
715             }
716             for (m = 0; m < DIM; m++)
717             {
718                 x[ii][m] += tmp[m];
719             }
720             if (v)
721             {
722                 for (m = 0; m < DIM; m++)
723                 {
724                     v[ii][m] += invdt*tmp[m];
725                 }
726             }
727         }
728     }
729
730     /* calculate the constraint forces, used for output and virial only */
731     for (c = 0; c < pull->ncoord; c++)
732     {
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);
735
736         if (vir && bMaster)
737         {
738             double f_invr;
739
740             /* Add the pull contribution to the virial */
741             f_invr = pcrd->f_scal/dnorm(r_ij[c]);
742
743             for (j = 0; j < DIM; j++)
744             {
745                 for (m = 0; m < DIM; m++)
746                 {
747                     vir[j][m] -= 0.5*f_invr*r_ij[c][j]*r_ij[c][m];
748                 }
749             }
750         }
751     }
752
753     /* finished! I hope. Give back some memory */
754     sfree(r_ij);
755     sfree(dr_tot);
756     sfree(rnew);
757 }
758
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)
763 {
764     int           c, j, m;
765     double        dev, ndr, invdr;
766     real          k, dkdl;
767     t_pull_coord *pcrd;
768
769     /* loop over the pull coordinates */
770     *V    = 0;
771     *dVdl = 0;
772     for (c = 0; c < pull->ncoord; c++)
773     {
774         pcrd = &pull->coord[c];
775
776         get_pull_coord_distance(pull, c, pbc, t, pcrd->dr, &dev);
777
778         k    = (1.0 - lambda)*pcrd->k + lambda*pcrd->kB;
779         dkdl = pcrd->kB - pcrd->k;
780
781         switch (pull->eGeom)
782         {
783             case epullgDIST:
784                 ndr   = dnorm(pcrd->dr);
785                 invdr = 1/ndr;
786                 if (ePull == epullUMBRELLA)
787                 {
788                     pcrd->f_scal  =       -k*dev;
789                     *V           += 0.5*   k*dsqr(dev);
790                     *dVdl        += 0.5*dkdl*dsqr(dev);
791                 }
792                 else
793                 {
794                     pcrd->f_scal  =   -k;
795                     *V           +=    k*ndr;
796                     *dVdl        += dkdl*ndr;
797                 }
798                 for (m = 0; m < DIM; m++)
799                 {
800                     pcrd->f[m]    = pcrd->f_scal*pcrd->dr[m]*invdr;
801                 }
802                 break;
803             case epullgDIR:
804             case epullgDIRPBC:
805             case epullgCYL:
806                 if (ePull == epullUMBRELLA)
807                 {
808                     pcrd->f_scal  =       -k*dev;
809                     *V           += 0.5*   k*dsqr(dev);
810                     *dVdl        += 0.5*dkdl*dsqr(dev);
811                 }
812                 else
813                 {
814                     ndr = 0;
815                     for (m = 0; m < DIM; m++)
816                     {
817                         ndr += pcrd->vec[m]*pcrd->dr[m];
818                     }
819                     pcrd->f_scal  =   -k;
820                     *V           +=    k*ndr;
821                     *dVdl        += dkdl*ndr;
822                 }
823                 for (m = 0; m < DIM; m++)
824                 {
825                     pcrd->f[m]    = pcrd->f_scal*pcrd->vec[m];
826                 }
827                 break;
828         }
829
830         if (vir)
831         {
832             /* Add the pull contribution to the virial */
833             for (j = 0; j < DIM; j++)
834             {
835                 for (m = 0; m < DIM; m++)
836                 {
837                     vir[j][m] -= 0.5*pcrd->f[j]*pcrd->dr[m];
838                 }
839             }
840         }
841     }
842 }
843
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)
847 {
848     real V, dVdl;
849
850     pull_calc_coms(cr, pull, md, pbc, t, x, NULL);
851
852     do_pull_pot(ePull, pull, pbc, t, lambda,
853                 &V, pull->bVirial && MASTER(cr) ? vir : NULL, &dVdl);
854
855     /* Distribute forces over pulled groups */
856     apply_forces(pull, md, f);
857
858     if (MASTER(cr))
859     {
860         *dvdlambda += dVdl;
861     }
862
863     return (MASTER(cr) ? V : 0.0);
864 }
865
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)
869 {
870     pull_calc_coms(cr, pull, md, pbc, t, x, xp);
871
872     do_constraint(pull, pbc, xp, v, pull->bVirial && MASTER(cr), vir, dt, t);
873 }
874
875 static void make_local_pull_group(gmx_ga2la_t ga2la,
876                                   t_pull_group *pg, int start, int end)
877 {
878     int i, ii;
879
880     pg->nat_loc = 0;
881     for (i = 0; i < pg->nat; i++)
882     {
883         ii = pg->ind[i];
884         if (ga2la)
885         {
886             if (!ga2la_get_home(ga2la, ii, &ii))
887             {
888                 ii = -1;
889             }
890         }
891         if (ii >= start && ii < end)
892         {
893             /* This is a home atom, add it to the local pull group */
894             if (pg->nat_loc >= pg->nalloc_loc)
895             {
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)
899                 {
900                     srenew(pg->weight_loc, pg->nalloc_loc);
901                 }
902             }
903             pg->ind_loc[pg->nat_loc] = ii;
904             if (pg->weight)
905             {
906                 pg->weight_loc[pg->nat_loc] = pg->weight[i];
907             }
908             pg->nat_loc++;
909         }
910     }
911 }
912
913 void dd_make_local_pull_groups(gmx_domdec_t *dd, t_pull *pull, t_mdatoms *md)
914 {
915     gmx_ga2la_t ga2la;
916     int         g;
917
918     if (dd)
919     {
920         ga2la = dd->ga2la;
921     }
922     else
923     {
924         ga2la = NULL;
925     }
926
927     for (g = 0; g < pull->ngroup; g++)
928     {
929         make_local_pull_group(ga2la, &pull->group[g],
930                               0, md->homenr);
931     }
932 }
933
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)
937 {
938     int                   i, ii, d, nfrozen, ndim;
939     real                  m, w, mbd;
940     double                tmass, wmass, wwmass;
941     gmx_groups_t         *groups;
942     gmx_mtop_atomlookup_t alook;
943     t_atom               *atom;
944
945     if (EI_ENERGY_MINIMIZATION(ir->eI) || ir->eI == eiBD)
946     {
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.
951          */
952         if (pg->nweight == 0)
953         {
954             snew(pg->weight, pg->nat);
955         }
956     }
957
958     if (cr && PAR(cr))
959     {
960         pg->nat_loc    = 0;
961         pg->nalloc_loc = 0;
962         pg->ind_loc    = NULL;
963         pg->weight_loc = NULL;
964     }
965     else
966     {
967         pg->nat_loc = pg->nat;
968         pg->ind_loc = pg->ind;
969         if (pg->epgrppbc == epgrppbcCOS)
970         {
971             snew(pg->weight_loc, pg->nat);
972         }
973         else
974         {
975             pg->weight_loc = pg->weight;
976         }
977     }
978
979     groups = &mtop->groups;
980
981     alook = gmx_mtop_atomlookup_init(mtop);
982
983     nfrozen = 0;
984     tmass   = 0;
985     wmass   = 0;
986     wwmass  = 0;
987     for (i = 0; i < pg->nat; i++)
988     {
989         ii = pg->ind[i];
990         gmx_mtop_atomnr_to_atom(alook, ii, &atom);
991         if (ir->opts.nFreeze)
992         {
993             for (d = 0; d < DIM; d++)
994             {
995                 if (pulldims[d] && ir->opts.nFreeze[ggrpnr(groups, egcFREEZE, ii)][d])
996                 {
997                     nfrozen++;
998                 }
999             }
1000         }
1001         if (ir->efep == efepNO)
1002         {
1003             m = atom->m;
1004         }
1005         else
1006         {
1007             m = (1 - lambda)*atom->m + lambda*atom->mB;
1008         }
1009         if (pg->nweight > 0)
1010         {
1011             w = pg->weight[i];
1012         }
1013         else
1014         {
1015             w = 1;
1016         }
1017         if (EI_ENERGY_MINIMIZATION(ir->eI))
1018         {
1019             /* Move the mass to the weight */
1020             w            *= m;
1021             m             = 1;
1022             pg->weight[i] = w;
1023         }
1024         else if (ir->eI == eiBD)
1025         {
1026             if (ir->bd_fric)
1027             {
1028                 mbd = ir->bd_fric*ir->delta_t;
1029             }
1030             else
1031             {
1032                 if (groups->grpnr[egcTC] == NULL)
1033                 {
1034                     mbd = ir->delta_t/ir->opts.tau_t[0];
1035                 }
1036                 else
1037                 {
1038                     mbd = ir->delta_t/ir->opts.tau_t[groups->grpnr[egcTC][ii]];
1039                 }
1040             }
1041             w            *= m/mbd;
1042             m             = mbd;
1043             pg->weight[i] = w;
1044         }
1045         tmass  += m;
1046         wmass  += m*w;
1047         wwmass += m*w*w;
1048     }
1049
1050     gmx_mtop_atomlookup_destroy(alook);
1051
1052     if (wmass == 0)
1053     {
1054         gmx_fatal(FARGS, "The total%s mass of pull group %d is zero",
1055                   pg->weight ? " weighted" : "", g);
1056     }
1057     if (fplog)
1058     {
1059         fprintf(fplog,
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)
1062         {
1063             fprintf(fplog, ", weighted mass %9.3f", wmass*wmass/wwmass);
1064         }
1065         if (pg->epgrppbc == epgrppbcCOS)
1066         {
1067             fprintf(fplog, ", cosine weighting will be used");
1068         }
1069         fprintf(fplog, "\n");
1070     }
1071
1072     if (nfrozen == 0)
1073     {
1074         /* A value > 0 signals not frozen, it is updated later */
1075         pg->invtm  = 1.0;
1076     }
1077     else
1078     {
1079         ndim = 0;
1080         for (d = 0; d < DIM; d++)
1081         {
1082             ndim += pulldims[d]*pg->nat;
1083         }
1084         if (fplog && nfrozen > 0 && nfrozen < ndim)
1085         {
1086             fprintf(fplog,
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",
1090                     g);
1091         }
1092         pg->invtm  = 0.0;
1093         pg->wscale = 1.0;
1094     }
1095 }
1096
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)
1100 {
1101     t_pull       *pull;
1102     t_pull_group *pgrp;
1103     int           c, g, start = 0, end = 0, m;
1104
1105     pull = ir->pull;
1106
1107     pull->ePBC = ir->ePBC;
1108     switch (pull->ePBC)
1109     {
1110         case epbcNONE: pull->npbcdim = 0; break;
1111         case epbcXY:   pull->npbcdim = 2; break;
1112         default:       pull->npbcdim = 3; break;
1113     }
1114
1115     if (fplog)
1116     {
1117         gmx_bool bAbs, bCos;
1118
1119         bAbs = FALSE;
1120         for (c = 0; c < pull->ncoord; c++)
1121         {
1122             if (pull->group[pull->coord[c].group[0]].nat == 0 ||
1123                 pull->group[pull->coord[c].group[1]].nat == 0)
1124             {
1125                 bAbs = TRUE;
1126             }
1127         }
1128
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");
1134         if (bAbs)
1135         {
1136             fprintf(fplog, "with an absolute reference\n");
1137         }
1138         bCos = FALSE;
1139         for (g = 0; g < pull->ngroup; g++)
1140         {
1141             if (pull->group[g].nat > 1 &&
1142                 pull->group[g].pbcatom < 0)
1143             {
1144                 /* We are using cosine weighting */
1145                 fprintf(fplog, "Cosine weighting is used for group %d\n", g);
1146                 bCos = TRUE;
1147             }
1148         }
1149         if (bCos)
1150         {
1151             please_cite(fplog, "Engin2010");
1152         }
1153     }
1154
1155     /* We always add the virial contribution,
1156      * except for geometry = direction_periodic where this is impossible.
1157      */
1158     pull->bVirial = (pull->eGeom != epullgDIRPBC);
1159     if (getenv("GMX_NO_PULLVIR") != NULL)
1160     {
1161         if (fplog)
1162         {
1163             fprintf(fplog, "Found env. var., will not add the virial contribution of the COM pull forces\n");
1164         }
1165         pull->bVirial = FALSE;
1166     }
1167
1168     pull->rbuf     = NULL;
1169     pull->dbuf     = NULL;
1170     pull->dbuf_cyl = NULL;
1171     pull->bRefAt   = FALSE;
1172     pull->cosdim   = -1;
1173     for (g = 0; g < pull->ngroup; g++)
1174     {
1175         pgrp           = &pull->group[g];
1176         pgrp->epgrppbc = epgrppbcNONE;
1177         if (pgrp->nat > 0)
1178         {
1179             /* Determine if we need to take PBC into account for calculating
1180              * the COM's of the pull groups.
1181              */
1182             for (m = 0; m < pull->npbcdim; m++)
1183             {
1184                 if (pull->dim[m] && pgrp->nat > 1)
1185                 {
1186                     if (pgrp->pbcatom >= 0)
1187                     {
1188                         pgrp->epgrppbc = epgrppbcREFAT;
1189                         pull->bRefAt   = TRUE;
1190                     }
1191                     else
1192                     {
1193                         if (pgrp->weight)
1194                         {
1195                             gmx_fatal(FARGS, "Pull groups can not have relative weights and cosine weighting at same time");
1196                         }
1197                         pgrp->epgrppbc = epgrppbcCOS;
1198                         if (pull->cosdim >= 0 && pull->cosdim != m)
1199                         {
1200                             gmx_fatal(FARGS, "Can only use cosine weighting with pulling in one dimension (use mdp option pull_dim)");
1201                         }
1202                         pull->cosdim = m;
1203                     }
1204                 }
1205             }
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)
1209             {
1210                 gmx_fatal(FARGS, "Can not have frozen atoms in a cylinder pull group");
1211             }
1212         }
1213         else
1214         {
1215             /* Absolute reference, set the inverse mass to zero */
1216             pgrp->invtm  = 0;
1217             pgrp->wscale = 1;
1218         }
1219     }
1220
1221     /* if we use dynamic reference groups, do some initialising for them */
1222     if (PULL_CYL(pull))
1223     {
1224         if (ir->ePull == epullCONSTRAINT && pull->ncoord > 1)
1225         {
1226             /* We can't easily update the single reference group with multiple
1227              * constraints. This would require recalculating COMs.
1228              */
1229             gmx_fatal(FARGS, "Constraint COM pulling supports only one coordinate with geometry=cylinder, you can use umbrella pulling with multiple coordinates");
1230         }
1231
1232         for (c = 0; c < pull->ncoord; c++)
1233         {
1234             if (pull->group[pull->coord[c].group[0]].nat == 0)
1235             {
1236                 gmx_fatal(FARGS, "Dynamic reference groups are not supported when using absolute reference!\n");
1237             }
1238         }
1239
1240         snew(pull->dyna, pull->ncoord);
1241     }
1242
1243     /* Only do I/O when we are doing dynamics and if we are the MASTER */
1244     pull->out_x = NULL;
1245     pull->out_f = NULL;
1246     if (bOutFile)
1247     {
1248         if (pull->nstxout > 0)
1249         {
1250             pull->out_x = open_pull_out(opt2fn("-px", nfile, fnm), pull, oenv, TRUE, Flags);
1251         }
1252         if (pull->nstfout > 0)
1253         {
1254             pull->out_f = open_pull_out(opt2fn("-pf", nfile, fnm), pull, oenv,
1255                                         FALSE, Flags);
1256         }
1257     }
1258 }
1259
1260 void finish_pull(t_pull *pull)
1261 {
1262     if (pull->out_x)
1263     {
1264         gmx_fio_fclose(pull->out_x);
1265     }
1266     if (pull->out_f)
1267     {
1268         gmx_fio_fclose(pull->out_f);
1269     }
1270 }