Fix issues for clang-analyzer-8
[alexxy/gromacs.git] / src / gromacs / mdrun / shellfc.cpp
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-2008, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, 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 "gmxpre.h"
38
39 #include "shellfc.h"
40
41 #include <cmath>
42 #include <cstdint>
43 #include <cstdlib>
44 #include <cstring>
45
46 #include <algorithm>
47 #include <array>
48
49 #include "gromacs/domdec/dlbtiming.h"
50 #include "gromacs/domdec/domdec.h"
51 #include "gromacs/domdec/domdec_struct.h"
52 #include "gromacs/domdec/mdsetup.h"
53 #include "gromacs/gmxlib/chargegroup.h"
54 #include "gromacs/gmxlib/network.h"
55 #include "gromacs/math/functions.h"
56 #include "gromacs/math/units.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/math/vecdump.h"
59 #include "gromacs/mdlib/constr.h"
60 #include "gromacs/mdlib/enerdata_utils.h"
61 #include "gromacs/mdlib/force.h"
62 #include "gromacs/mdlib/force_flags.h"
63 #include "gromacs/mdlib/gmx_omp_nthreads.h"
64 #include "gromacs/mdlib/mdatoms.h"
65 #include "gromacs/mdlib/vsite.h"
66 #include "gromacs/mdtypes/commrec.h"
67 #include "gromacs/mdtypes/enerdata.h"
68 #include "gromacs/mdtypes/forcerec.h"
69 #include "gromacs/mdtypes/inputrec.h"
70 #include "gromacs/mdtypes/md_enums.h"
71 #include "gromacs/mdtypes/state.h"
72 #include "gromacs/pbcutil/mshift.h"
73 #include "gromacs/pbcutil/pbc.h"
74 #include "gromacs/topology/ifunc.h"
75 #include "gromacs/topology/mtop_lookup.h"
76 #include "gromacs/topology/mtop_util.h"
77 #include "gromacs/utility/arrayref.h"
78 #include "gromacs/utility/arraysize.h"
79 #include "gromacs/utility/cstringutil.h"
80 #include "gromacs/utility/fatalerror.h"
81 #include "gromacs/utility/gmxassert.h"
82 #include "gromacs/utility/smalloc.h"
83
84 typedef struct {
85     int     nnucl;
86     int     shell;               /* The shell id                                */
87     int     nucl1, nucl2, nucl3; /* The nuclei connected to the shell   */
88     /* gmx_bool    bInterCG; */       /* Coupled to nuclei outside cg?        */
89     real    k;                   /* force constant                      */
90     real    k_1;                 /* 1 over force constant               */
91     rvec    xold;
92     rvec    fold;
93     rvec    step;
94 } t_shell;
95
96 struct gmx_shellfc_t {
97     /* Shell counts, indices, parameters and working data */
98     int          nshell_gl;              /* The number of shells in the system        */
99     t_shell     *shell_gl;               /* All the shells (for DD only)              */
100     int         *shell_index_gl;         /* Global shell index (for DD only)          */
101     gmx_bool     bInterCG;               /* Are there inter charge-group shells?      */
102     int          nshell;                 /* The number of local shells                */
103     t_shell     *shell;                  /* The local shells                          */
104     int          shell_nalloc;           /* The allocation size of shell              */
105     gmx_bool     bPredict;               /* Predict shell positions                   */
106     gmx_bool     bRequireInit;           /* Require initialization of shell positions */
107     int          nflexcon;               /* The number of flexible constraints        */
108
109     /* Temporary arrays, should be fixed size 2 when fully converted to C++ */
110     PaddedVector<gmx::RVec> *x;          /* Array for iterative minimization          */
111     PaddedVector<gmx::RVec> *f;          /* Array for iterative minimization          */
112
113     /* Flexible constraint working data */
114     rvec        *acc_dir;                /* Acceleration direction for flexcon        */
115     rvec        *x_old;                  /* Old coordinates for flexcon               */
116     int          flex_nalloc;            /* The allocation size of acc_dir and x_old  */
117     rvec        *adir_xnold;             /* Work space for init_adir                  */
118     rvec        *adir_xnew;              /* Work space for init_adir                  */
119     int          adir_nalloc;            /* Work space for init_adir                  */
120     std::int64_t numForceEvaluations;    /* Total number of force evaluations         */
121     int          numConvergedIterations; /* Total number of iterations that converged */
122 };
123
124
125 static void pr_shell(FILE *fplog, int ns, t_shell s[])
126 {
127     int i;
128
129     fprintf(fplog, "SHELL DATA\n");
130     fprintf(fplog, "%5s  %8s  %5s  %5s  %5s\n",
131             "Shell", "Force k", "Nucl1", "Nucl2", "Nucl3");
132     for (i = 0; (i < ns); i++)
133     {
134         fprintf(fplog, "%5d  %8.3f  %5d", s[i].shell, 1.0/s[i].k_1, s[i].nucl1);
135         if (s[i].nnucl == 2)
136         {
137             fprintf(fplog, "  %5d\n", s[i].nucl2);
138         }
139         else if (s[i].nnucl == 3)
140         {
141             fprintf(fplog, "  %5d  %5d\n", s[i].nucl2, s[i].nucl3);
142         }
143         else
144         {
145             fprintf(fplog, "\n");
146         }
147     }
148 }
149
150 /* TODO The remain call of this function passes non-NULL mass and NULL
151  * mtop, so this routine can be simplified.
152  *
153  * The other code path supported doing prediction before the MD loop
154  * started, but even when called, the prediction was always
155  * over-written by a subsequent call in the MD loop, so has been
156  * removed. */
157 static void predict_shells(FILE *fplog, rvec x[], rvec v[], real dt,
158                            int ns, t_shell s[],
159                            const real mass[], gmx_mtop_t *mtop, gmx_bool bInit)
160 {
161     int                   i, m, s1, n1, n2, n3;
162     real                  dt_1, fudge, tm, m1, m2, m3;
163     rvec                 *ptr;
164
165     GMX_RELEASE_ASSERT(mass || mtop, "Must have masses or a way to look them up");
166
167     /* We introduce a fudge factor for performance reasons: with this choice
168      * the initial force on the shells is about a factor of two lower than
169      * without
170      */
171     fudge = 1.0;
172
173     if (bInit)
174     {
175         if (fplog)
176         {
177             fprintf(fplog, "RELAX: Using prediction for initial shell placement\n");
178         }
179         ptr  = x;
180         dt_1 = 1;
181     }
182     else
183     {
184         ptr  = v;
185         dt_1 = fudge*dt;
186     }
187
188     int molb = 0;
189     for (i = 0; (i < ns); i++)
190     {
191         s1 = s[i].shell;
192         if (bInit)
193         {
194             clear_rvec(x[s1]);
195         }
196         switch (s[i].nnucl)
197         {
198             case 1:
199                 n1 = s[i].nucl1;
200                 for (m = 0; (m < DIM); m++)
201                 {
202                     x[s1][m] += ptr[n1][m]*dt_1;
203                 }
204                 break;
205             case 2:
206                 n1 = s[i].nucl1;
207                 n2 = s[i].nucl2;
208                 if (mass)
209                 {
210                     m1 = mass[n1];
211                     m2 = mass[n2];
212                 }
213                 else
214                 {
215                     /* Not the correct masses with FE, but it is just a prediction... */
216                     m1 = mtopGetAtomMass(mtop, n1, &molb);
217                     m2 = mtopGetAtomMass(mtop, n2, &molb);
218                 }
219                 tm = dt_1/(m1+m2);
220                 for (m = 0; (m < DIM); m++)
221                 {
222                     x[s1][m] += (m1*ptr[n1][m]+m2*ptr[n2][m])*tm;
223                 }
224                 break;
225             case 3:
226                 n1 = s[i].nucl1;
227                 n2 = s[i].nucl2;
228                 n3 = s[i].nucl3;
229                 if (mass)
230                 {
231                     m1 = mass[n1];
232                     m2 = mass[n2];
233                     m3 = mass[n3];
234                 }
235                 else
236                 {
237                     /* Not the correct masses with FE, but it is just a prediction... */
238                     m1 = mtopGetAtomMass(mtop, n1, &molb);
239                     m2 = mtopGetAtomMass(mtop, n2, &molb);
240                     m3 = mtopGetAtomMass(mtop, n3, &molb);
241                 }
242                 tm = dt_1/(m1+m2+m3);
243                 for (m = 0; (m < DIM); m++)
244                 {
245                     x[s1][m] += (m1*ptr[n1][m]+m2*ptr[n2][m]+m3*ptr[n3][m])*tm;
246                 }
247                 break;
248             default:
249                 gmx_fatal(FARGS, "Shell %d has %d nuclei!", i, s[i].nnucl);
250         }
251     }
252 }
253
254 /*! \brief Count the different particle types in a system
255  *
256  * Routine prints a warning to stderr in case an unknown particle type
257  * is encountered.
258  * \param[in]  fplog Print what we have found if not NULL
259  * \param[in]  mtop  Molecular topology.
260  * \returns Array holding the number of particles of a type
261  */
262 static std::array<int, eptNR> countPtypes(FILE             *fplog,
263                                           const gmx_mtop_t *mtop)
264 {
265     std::array<int, eptNR> nptype = { { 0 } };
266     /* Count number of shells, and find their indices */
267     for (int i = 0; (i < eptNR); i++)
268     {
269         nptype[i] = 0;
270     }
271
272     gmx_mtop_atomloop_block_t  aloopb = gmx_mtop_atomloop_block_init(mtop);
273     int                        nmol;
274     const t_atom              *atom;
275     while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
276     {
277         switch (atom->ptype)
278         {
279             case eptAtom:
280             case eptVSite:
281             case eptShell:
282                 nptype[atom->ptype] += nmol;
283                 break;
284             default:
285                 fprintf(stderr, "Warning unsupported particle type %d in countPtypes",
286                         static_cast<int>(atom->ptype));
287         }
288     }
289     if (fplog)
290     {
291         /* Print the number of each particle type */
292         int n = 0;
293         for (const auto &i : nptype)
294         {
295             if (i != 0)
296             {
297                 fprintf(fplog, "There are: %d %ss\n", i, ptype_str[n]);
298             }
299             n++;
300         }
301     }
302     return nptype;
303 }
304
305 gmx_shellfc_t *init_shell_flexcon(FILE *fplog,
306                                   const gmx_mtop_t *mtop, int nflexcon,
307                                   int nstcalcenergy,
308                                   bool usingDomainDecomposition)
309 {
310     gmx_shellfc_t            *shfc;
311     t_shell                  *shell;
312     int                      *shell_index = nullptr, *at2cg;
313
314     int                       ns, nshell, nsi;
315     int                       i, j, type, a_offset, cg, mol, ftype, nra;
316     real                      qS, alpha;
317     int                       aS, aN = 0; /* Shell and nucleus */
318     int                       bondtypes[] = { F_BONDS, F_HARMONIC, F_CUBICBONDS, F_POLARIZATION, F_ANHARM_POL, F_WATER_POL };
319 #define NBT asize(bondtypes)
320     const gmx_ffparams_t     *ffparams;
321
322     std::array<int, eptNR>    n = countPtypes(fplog, mtop);
323     nshell = n[eptShell];
324
325     if (nshell == 0 && nflexcon == 0)
326     {
327         /* We're not doing shells or flexible constraints */
328         return nullptr;
329     }
330
331     snew(shfc, 1);
332     shfc->x        = new PaddedVector<gmx::RVec>[2] {};
333     shfc->f        = new PaddedVector<gmx::RVec>[2] {};
334     shfc->nflexcon = nflexcon;
335
336     if (nshell == 0)
337     {
338         /* Only flexible constraints, no shells.
339          * Note that make_local_shells() does not need to be called.
340          */
341         shfc->nshell   = 0;
342         shfc->bPredict = FALSE;
343
344         return shfc;
345     }
346
347     if (nstcalcenergy != 1)
348     {
349         gmx_fatal(FARGS, "You have nstcalcenergy set to a value (%d) that is different from 1.\nThis is not supported in combination with shell particles.\nPlease make a new tpr file.", nstcalcenergy);
350     }
351     if (usingDomainDecomposition)
352     {
353         gmx_fatal(FARGS, "Shell particles are not implemented with domain decomposition, use a single rank");
354     }
355
356     /* We have shells: fill the shell data structure */
357
358     /* Global system sized array, this should be avoided */
359     snew(shell_index, mtop->natoms);
360
361     nshell = 0;
362     for (const AtomProxy atomP : AtomRange(*mtop))
363     {
364         const t_atom &local = atomP.atom();
365         int           i     = atomP.globalAtomNumber();
366         if (local.ptype == eptShell)
367         {
368             shell_index[i] = nshell++;
369         }
370     }
371
372     snew(shell, nshell);
373
374     /* Initiate the shell structures */
375     for (i = 0; (i < nshell); i++)
376     {
377         shell[i].shell = -1;
378         shell[i].nnucl = 0;
379         shell[i].nucl1 = -1;
380         shell[i].nucl2 = -1;
381         shell[i].nucl3 = -1;
382         /* shell[i].bInterCG=FALSE; */
383         shell[i].k_1   = 0;
384         shell[i].k     = 0;
385     }
386
387     ffparams = &mtop->ffparams;
388
389     /* Now fill the structures */
390     shfc->bInterCG = FALSE;
391     ns             = 0;
392     a_offset       = 0;
393     for (size_t mb = 0; mb < mtop->molblock.size(); mb++)
394     {
395         const gmx_molblock_t *molb = &mtop->molblock[mb];
396         const gmx_moltype_t  *molt = &mtop->moltype[molb->type];
397         const t_block        *cgs  = &molt->cgs;
398
399         snew(at2cg, molt->atoms.nr);
400         for (cg = 0; cg < cgs->nr; cg++)
401         {
402             for (i = cgs->index[cg]; i < cgs->index[cg+1]; i++)
403             {
404                 at2cg[i] = cg;
405             }
406         }
407
408         const t_atom *atom = molt->atoms.atom;
409         for (mol = 0; mol < molb->nmol; mol++)
410         {
411             for (j = 0; (j < NBT); j++)
412             {
413                 const int *ia = molt->ilist[bondtypes[j]].iatoms.data();
414                 for (i = 0; (i < molt->ilist[bondtypes[j]].size()); )
415                 {
416                     type  = ia[0];
417                     ftype = ffparams->functype[type];
418                     nra   = interaction_function[ftype].nratoms;
419
420                     /* Check whether we have a bond with a shell */
421                     aS = -1;
422
423                     switch (bondtypes[j])
424                     {
425                         case F_BONDS:
426                         case F_HARMONIC:
427                         case F_CUBICBONDS:
428                         case F_POLARIZATION:
429                         case F_ANHARM_POL:
430                             if (atom[ia[1]].ptype == eptShell)
431                             {
432                                 aS = ia[1];
433                                 aN = ia[2];
434                             }
435                             else if (atom[ia[2]].ptype == eptShell)
436                             {
437                                 aS = ia[2];
438                                 aN = ia[1];
439                             }
440                             break;
441                         case F_WATER_POL:
442                             aN    = ia[4]; /* Dummy */
443                             aS    = ia[5]; /* Shell */
444                             break;
445                         default:
446                             gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__);
447                     }
448
449                     if (aS != -1)
450                     {
451                         qS = atom[aS].q;
452
453                         /* Check whether one of the particles is a shell... */
454                         nsi = shell_index[a_offset+aS];
455                         if ((nsi < 0) || (nsi >= nshell))
456                         {
457                             gmx_fatal(FARGS, "nsi is %d should be within 0 - %d. aS = %d",
458                                       nsi, nshell, aS);
459                         }
460                         if (shell[nsi].shell == -1)
461                         {
462                             shell[nsi].shell = a_offset + aS;
463                             ns++;
464                         }
465                         else if (shell[nsi].shell != a_offset+aS)
466                         {
467                             gmx_fatal(FARGS, "Weird stuff in %s, %d", __FILE__, __LINE__);
468                         }
469
470                         if      (shell[nsi].nucl1 == -1)
471                         {
472                             shell[nsi].nucl1 = a_offset + aN;
473                         }
474                         else if (shell[nsi].nucl2 == -1)
475                         {
476                             shell[nsi].nucl2 = a_offset + aN;
477                         }
478                         else if (shell[nsi].nucl3 == -1)
479                         {
480                             shell[nsi].nucl3 = a_offset + aN;
481                         }
482                         else
483                         {
484                             if (fplog)
485                             {
486                                 pr_shell(fplog, ns, shell);
487                             }
488                             gmx_fatal(FARGS, "Can not handle more than three bonds per shell\n");
489                         }
490                         if (at2cg[aS] != at2cg[aN])
491                         {
492                             /* shell[nsi].bInterCG = TRUE; */
493                             shfc->bInterCG = TRUE;
494                         }
495
496                         switch (bondtypes[j])
497                         {
498                             case F_BONDS:
499                             case F_HARMONIC:
500                                 shell[nsi].k    += ffparams->iparams[type].harmonic.krA;
501                                 break;
502                             case F_CUBICBONDS:
503                                 shell[nsi].k    += ffparams->iparams[type].cubic.kb;
504                                 break;
505                             case F_POLARIZATION:
506                             case F_ANHARM_POL:
507                                 if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10))
508                                 {
509                                     gmx_fatal(FARGS, "polarize can not be used with qA(%e) != qB(%e) for atom %d of molecule block %zu", qS, atom[aS].qB, aS+1, mb+1);
510                                 }
511                                 shell[nsi].k    += gmx::square(qS)*ONE_4PI_EPS0/
512                                     ffparams->iparams[type].polarize.alpha;
513                                 break;
514                             case F_WATER_POL:
515                                 if (!gmx_within_tol(qS, atom[aS].qB, GMX_REAL_EPS*10))
516                                 {
517                                     gmx_fatal(FARGS, "water_pol can not be used with qA(%e) != qB(%e) for atom %d of molecule block %zu", qS, atom[aS].qB, aS+1, mb+1);
518                                 }
519                                 alpha          = (ffparams->iparams[type].wpol.al_x+
520                                                   ffparams->iparams[type].wpol.al_y+
521                                                   ffparams->iparams[type].wpol.al_z)/3.0;
522                                 shell[nsi].k  += gmx::square(qS)*ONE_4PI_EPS0/alpha;
523                                 break;
524                             default:
525                                 gmx_fatal(FARGS, "Death Horror: %s, %d", __FILE__, __LINE__);
526                         }
527                         shell[nsi].nnucl++;
528                     }
529                     ia += nra+1;
530                     i  += nra+1;
531                 }
532             }
533             a_offset += molt->atoms.nr;
534         }
535         /* Done with this molecule type */
536         sfree(at2cg);
537     }
538
539     /* Verify whether it's all correct */
540     if (ns != nshell)
541     {
542         gmx_fatal(FARGS, "Something weird with shells. They may not be bonded to something");
543     }
544
545     for (i = 0; (i < ns); i++)
546     {
547         shell[i].k_1 = 1.0/shell[i].k;
548     }
549
550     if (debug)
551     {
552         pr_shell(debug, ns, shell);
553     }
554
555
556     shfc->nshell_gl      = ns;
557     shfc->shell_gl       = shell;
558     shfc->shell_index_gl = shell_index;
559
560     shfc->bPredict     = (getenv("GMX_NOPREDICT") == nullptr);
561     shfc->bRequireInit = FALSE;
562     if (!shfc->bPredict)
563     {
564         if (fplog)
565         {
566             fprintf(fplog, "\nWill never predict shell positions\n");
567         }
568     }
569     else
570     {
571         shfc->bRequireInit = (getenv("GMX_REQUIRE_SHELL_INIT") != nullptr);
572         if (shfc->bRequireInit && fplog)
573         {
574             fprintf(fplog, "\nWill always initiate shell positions\n");
575         }
576     }
577
578     if (shfc->bPredict)
579     {
580         if (shfc->bInterCG)
581         {
582             if (fplog)
583             {
584                 fprintf(fplog, "\nNOTE: there are shells that are connected to particles outside their own charge group, will not predict shells positions during the run\n\n");
585             }
586             /* Prediction improves performance, so we should implement either:
587              * 1. communication for the atoms needed for prediction
588              * 2. prediction using the velocities of shells; currently the
589              *    shell velocities are zeroed, it's a bit tricky to keep
590              *    track of the shell displacements and thus the velocity.
591              */
592             shfc->bPredict = FALSE;
593         }
594     }
595
596     return shfc;
597 }
598
599 void make_local_shells(const t_commrec *cr,
600                        const t_mdatoms *md,
601                        gmx_shellfc_t   *shfc)
602 {
603     t_shell      *shell;
604     int           a0, a1, *ind, nshell, i;
605     gmx_domdec_t *dd = nullptr;
606
607     if (DOMAINDECOMP(cr))
608     {
609         dd = cr->dd;
610         a0 = 0;
611         a1 = dd_numHomeAtoms(*dd);
612     }
613     else
614     {
615         /* Single node: we need all shells, just copy the pointer */
616         shfc->nshell = shfc->nshell_gl;
617         shfc->shell  = shfc->shell_gl;
618
619         return;
620     }
621
622     ind = shfc->shell_index_gl;
623
624     nshell = 0;
625     shell  = shfc->shell;
626     for (i = a0; i < a1; i++)
627     {
628         if (md->ptype[i] == eptShell)
629         {
630             if (nshell+1 > shfc->shell_nalloc)
631             {
632                 shfc->shell_nalloc = over_alloc_dd(nshell+1);
633                 srenew(shell, shfc->shell_nalloc);
634             }
635             if (dd)
636             {
637                 shell[nshell] = shfc->shell_gl[ind[dd->globalAtomIndices[i]]];
638             }
639             else
640             {
641                 shell[nshell] = shfc->shell_gl[ind[i]];
642             }
643
644             /* With inter-cg shells we can no do shell prediction,
645              * so we do not need the nuclei numbers.
646              */
647             if (!shfc->bInterCG)
648             {
649                 shell[nshell].nucl1   = i + shell[nshell].nucl1 - shell[nshell].shell;
650                 if (shell[nshell].nnucl > 1)
651                 {
652                     shell[nshell].nucl2 = i + shell[nshell].nucl2 - shell[nshell].shell;
653                 }
654                 if (shell[nshell].nnucl > 2)
655                 {
656                     shell[nshell].nucl3 = i + shell[nshell].nucl3 - shell[nshell].shell;
657                 }
658             }
659             shell[nshell].shell = i;
660             nshell++;
661         }
662     }
663
664     shfc->nshell = nshell;
665     shfc->shell  = shell;
666 }
667
668 static void do_1pos(rvec xnew, const rvec xold, const rvec f, real step)
669 {
670     real xo, yo, zo;
671     real dx, dy, dz;
672
673     xo = xold[XX];
674     yo = xold[YY];
675     zo = xold[ZZ];
676
677     dx = f[XX]*step;
678     dy = f[YY]*step;
679     dz = f[ZZ]*step;
680
681     xnew[XX] = xo+dx;
682     xnew[YY] = yo+dy;
683     xnew[ZZ] = zo+dz;
684 }
685
686 static void do_1pos3(rvec xnew, const rvec xold, const rvec f, const rvec step)
687 {
688     real xo, yo, zo;
689     real dx, dy, dz;
690
691     xo = xold[XX];
692     yo = xold[YY];
693     zo = xold[ZZ];
694
695     dx = f[XX]*step[XX];
696     dy = f[YY]*step[YY];
697     dz = f[ZZ]*step[ZZ];
698
699     xnew[XX] = xo+dx;
700     xnew[YY] = yo+dy;
701     xnew[ZZ] = zo+dz;
702 }
703
704 static void directional_sd(gmx::ArrayRef<const gmx::RVec> xold,
705                            gmx::ArrayRef<gmx::RVec> xnew,
706                            const rvec acc_dir[], int homenr, real step)
707 {
708     const rvec *xo = as_rvec_array(xold.data());
709     rvec       *xn = as_rvec_array(xnew.data());
710
711     for (int i = 0; i < homenr; i++)
712     {
713         do_1pos(xn[i], xo[i], acc_dir[i], step);
714     }
715 }
716
717 static void shell_pos_sd(gmx::ArrayRef<const gmx::RVec> xcur,
718                          gmx::ArrayRef<gmx::RVec> xnew,
719                          gmx::ArrayRef<const gmx::RVec> f,
720                          int ns, t_shell s[], int count)
721 {
722     const real step_scale_min       = 0.8,
723                step_scale_increment = 0.2,
724                step_scale_max       = 1.2,
725                step_scale_multiple  = (step_scale_max - step_scale_min) / step_scale_increment;
726     int        i, shell, d;
727     real       dx, df, k_est;
728     const real zero = 0;
729 #ifdef PRINT_STEP
730     real       step_min, step_max;
731
732     step_min = 1e30;
733     step_max = 0;
734 #endif
735     for (i = 0; (i < ns); i++)
736     {
737         shell = s[i].shell;
738         if (count == 1)
739         {
740             for (d = 0; d < DIM; d++)
741             {
742                 s[i].step[d] = s[i].k_1;
743 #ifdef PRINT_STEP
744                 step_min = std::min(step_min, s[i].step[d]);
745                 step_max = std::max(step_max, s[i].step[d]);
746 #endif
747             }
748         }
749         else
750         {
751             for (d = 0; d < DIM; d++)
752             {
753                 dx = xcur[shell][d] - s[i].xold[d];
754                 df =    f[shell][d] - s[i].fold[d];
755                 /* -dx/df gets used to generate an interpolated value, but would
756                  * cause a NaN if df were binary-equal to zero. Values close to
757                  * zero won't cause problems (because of the min() and max()), so
758                  * just testing for binary inequality is OK. */
759                 if (zero != df)
760                 {
761                     k_est = -dx/df;
762                     /* Scale the step size by a factor interpolated from
763                      * step_scale_min to step_scale_max, as k_est goes from 0 to
764                      * step_scale_multiple * s[i].step[d] */
765                     s[i].step[d] =
766                         step_scale_min * s[i].step[d] +
767                         step_scale_increment * std::min(step_scale_multiple * s[i].step[d], std::max(k_est, zero));
768                 }
769                 else
770                 {
771                     /* Here 0 == df */
772                     if (gmx_numzero(dx)) /* 0 == dx */
773                     {
774                         /* Likely this will never happen, but if it does just
775                          * don't scale the step. */
776                     }
777                     else /* 0 != dx */
778                     {
779                         s[i].step[d] *= step_scale_max;
780                     }
781                 }
782 #ifdef PRINT_STEP
783                 step_min = std::min(step_min, s[i].step[d]);
784                 step_max = std::max(step_max, s[i].step[d]);
785 #endif
786             }
787         }
788         copy_rvec(xcur [shell], s[i].xold);
789         copy_rvec(f[shell],   s[i].fold);
790
791         do_1pos3(xnew[shell], xcur[shell], f[shell], s[i].step);
792
793         if (gmx_debug_at)
794         {
795             fprintf(debug, "shell[%d] = %d\n", i, shell);
796             pr_rvec(debug, 0, "fshell", f[shell], DIM, TRUE);
797             pr_rvec(debug, 0, "xold", xcur[shell], DIM, TRUE);
798             pr_rvec(debug, 0, "step", s[i].step, DIM, TRUE);
799             pr_rvec(debug, 0, "xnew", xnew[shell], DIM, TRUE);
800         }
801     }
802 #ifdef PRINT_STEP
803     printf("step %.3e %.3e\n", step_min, step_max);
804 #endif
805 }
806
807 static void decrease_step_size(int nshell, t_shell s[])
808 {
809     int i;
810
811     for (i = 0; i < nshell; i++)
812     {
813         svmul(0.8, s[i].step, s[i].step);
814     }
815 }
816
817 static void print_epot(FILE *fp, int64_t mdstep, int count, real epot, real df,
818                        int ndir, real sf_dir)
819 {
820     char buf[22];
821
822     fprintf(fp, "MDStep=%5s/%2d EPot: %12.8e, rmsF: %6.2e",
823             gmx_step_str(mdstep, buf), count, epot, df);
824     if (ndir)
825     {
826         fprintf(fp, ", dir. rmsF: %6.2e\n", std::sqrt(sf_dir/ndir));
827     }
828     else
829     {
830         fprintf(fp, "\n");
831     }
832 }
833
834
835 static real rms_force(const t_commrec *cr, gmx::ArrayRef<const gmx::RVec> force, int ns, t_shell s[],
836                       int ndir, real *sf_dir, real *Epot)
837 {
838     double      buf[4];
839     const rvec *f = as_rvec_array(force.data());
840
841     buf[0] = *sf_dir;
842     for (int i = 0; i < ns; i++)
843     {
844         int shell  = s[i].shell;
845         buf[0]    += norm2(f[shell]);
846     }
847     int ntot = ns;
848
849     if (PAR(cr))
850     {
851         buf[1] = ntot;
852         buf[2] = *sf_dir;
853         buf[3] = *Epot;
854         gmx_sumd(4, buf, cr);
855         ntot    = gmx::roundToInt(buf[1]);
856         *sf_dir = buf[2];
857         *Epot   = buf[3];
858     }
859     ntot += ndir;
860
861     return (ntot ? std::sqrt(buf[0]/ntot) : 0);
862 }
863
864 static void dump_shells(FILE *fp, gmx::ArrayRef<gmx::RVec> f, real ftol, int ns, t_shell s[])
865 {
866     int  i, shell;
867     real ft2, ff2;
868
869     ft2 = gmx::square(ftol);
870
871     for (i = 0; (i < ns); i++)
872     {
873         shell = s[i].shell;
874         ff2   = iprod(f[shell], f[shell]);
875         if (ff2 > ft2)
876         {
877             fprintf(fp, "SHELL %5d, force %10.5f  %10.5f  %10.5f, |f| %10.5f\n",
878                     shell, f[shell][XX], f[shell][YY], f[shell][ZZ], std::sqrt(ff2));
879         }
880     }
881 }
882
883 static void init_adir(gmx_shellfc_t            *shfc,
884                       gmx::Constraints         *constr,
885                       const t_inputrec         *ir,
886                       const t_commrec          *cr,
887                       int                       dd_ac1,
888                       int64_t                   step,
889                       const t_mdatoms          *md,
890                       int                       end,
891                       rvec                     *x_old,
892                       rvec                     *x_init,
893                       rvec                     *x,
894                       rvec                     *f,
895                       rvec                     *acc_dir,
896                       matrix                    box,
897                       gmx::ArrayRef<const real> lambda,
898                       real                     *dvdlambda)
899 {
900     rvec           *xnold, *xnew;
901     double          dt, w_dt;
902     int             n, d;
903     unsigned short *ptype;
904
905     if (DOMAINDECOMP(cr))
906     {
907         n = dd_ac1;
908     }
909     else
910     {
911         n = end;
912     }
913     if (n > shfc->adir_nalloc)
914     {
915         shfc->adir_nalloc = over_alloc_dd(n);
916         srenew(shfc->adir_xnold, shfc->adir_nalloc);
917         srenew(shfc->adir_xnew, shfc->adir_nalloc);
918     }
919     xnold = shfc->adir_xnold;
920     xnew  = shfc->adir_xnew;
921
922     ptype = md->ptype;
923
924     dt = ir->delta_t;
925
926     /* Does NOT work with freeze or acceleration groups (yet) */
927     for (n = 0; n < end; n++)
928     {
929         w_dt = md->invmass[n]*dt;
930
931         for (d = 0; d < DIM; d++)
932         {
933             if ((ptype[n] != eptVSite) && (ptype[n] != eptShell))
934             {
935                 xnold[n][d] = x[n][d] - (x_init[n][d] - x_old[n][d]);
936                 xnew[n][d]  = 2*x[n][d] - x_old[n][d] + f[n][d]*w_dt*dt;
937             }
938             else
939             {
940                 xnold[n][d] = x[n][d];
941                 xnew[n][d]  = x[n][d];
942             }
943         }
944     }
945     constr->apply(FALSE, FALSE, step, 0, 1.0,
946                   x, xnold, nullptr, box,
947                   lambda[efptBONDED], &(dvdlambda[efptBONDED]),
948                   nullptr, nullptr, gmx::ConstraintVariable::Positions);
949     constr->apply(FALSE, FALSE, step, 0, 1.0,
950                   x, xnew, nullptr, box,
951                   lambda[efptBONDED], &(dvdlambda[efptBONDED]),
952                   nullptr, nullptr, gmx::ConstraintVariable::Positions);
953
954     for (n = 0; n < end; n++)
955     {
956         for (d = 0; d < DIM; d++)
957         {
958             xnew[n][d] =
959                 -(2*x[n][d]-xnold[n][d]-xnew[n][d])/gmx::square(dt)
960                 - f[n][d]*md->invmass[n];
961         }
962         clear_rvec(acc_dir[n]);
963     }
964
965     /* Project the acceleration on the old bond directions */
966     constr->apply(FALSE, FALSE, step, 0, 1.0,
967                   x_old, xnew, acc_dir, box,
968                   lambda[efptBONDED], &(dvdlambda[efptBONDED]),
969                   nullptr, nullptr, gmx::ConstraintVariable::Deriv_FlexCon);
970 }
971
972 void relax_shell_flexcon(FILE                                     *fplog,
973                          const t_commrec                          *cr,
974                          const gmx_multisim_t                     *ms,
975                          gmx_bool                                  bVerbose,
976                          gmx_enfrot                               *enforcedRotation,
977                          int64_t                                   mdstep,
978                          const t_inputrec                         *inputrec,
979                          gmx::ImdSession                          *imdSession,
980                          pull_t                                   *pull_work,
981                          gmx_bool                                  bDoNS,
982                          int                                       force_flags,
983                          const gmx_localtop_t                     *top,
984                          gmx::Constraints                         *constr,
985                          gmx_enerdata_t                           *enerd,
986                          t_fcdata                                 *fcd,
987                          int                                       natoms,
988                          gmx::ArrayRefWithPadding<gmx::RVec>       x,
989                          gmx::ArrayRefWithPadding<gmx::RVec>       v,
990                          matrix                                    box,
991                          gmx::ArrayRef<real>                       lambda,
992                          history_t                                *hist,
993                          gmx::ArrayRefWithPadding<gmx::RVec>       f,
994                          tensor                                    force_vir,
995                          const t_mdatoms                          *md,
996                          t_nrnb                                   *nrnb,
997                          gmx_wallcycle_t                           wcycle,
998                          t_graph                                  *graph,
999                          gmx_shellfc_t                            *shfc,
1000                          t_forcerec                               *fr,
1001                          gmx::PpForceWorkload                     *ppForceWorkload,
1002                          double                                    t,
1003                          rvec                                      mu_tot,
1004                          const gmx_vsite_t                        *vsite,
1005                          const DDBalanceRegionHandler             &ddBalanceRegionHandler)
1006 {
1007     auto          xRvec = as_rvec_array(x.paddedArrayRef().data());
1008     auto          vRvec = as_rvec_array(v.paddedArrayRef().data());
1009
1010     int           nshell;
1011     t_shell      *shell;
1012     const t_idef *idef;
1013     rvec         *acc_dir = nullptr, *x_old = nullptr;
1014     real          Epot[2], df[2];
1015     real          sf_dir, invdt;
1016     real          ftol, dum = 0;
1017     char          sbuf[22];
1018     gmx_bool      bCont, bInit, bConverged;
1019     int           nat, dd_ac0, dd_ac1 = 0, i;
1020     int           homenr = md->homenr, end = homenr;
1021     int           nflexcon, number_steps, d, Min = 0, count = 0;
1022 #define  Try (1-Min)             /* At start Try = 1 */
1023
1024     bCont        = (mdstep == inputrec->init_step) && inputrec->bContinuation;
1025     bInit        = (mdstep == inputrec->init_step) || shfc->bRequireInit;
1026     ftol         = inputrec->em_tol;
1027     number_steps = inputrec->niter;
1028     nshell       = shfc->nshell;
1029     shell        = shfc->shell;
1030     nflexcon     = shfc->nflexcon;
1031
1032     idef = &top->idef;
1033
1034     if (DOMAINDECOMP(cr))
1035     {
1036         nat = dd_natoms_vsite(cr->dd);
1037         if (nflexcon > 0)
1038         {
1039             dd_get_constraint_range(cr->dd, &dd_ac0, &dd_ac1);
1040             nat = std::max(nat, dd_ac1);
1041         }
1042     }
1043     else
1044     {
1045         nat = natoms;
1046     }
1047
1048     for (i = 0; (i < 2); i++)
1049     {
1050         shfc->x[i].resizeWithPadding(nat);
1051         shfc->f[i].resizeWithPadding(nat);
1052     }
1053
1054     /* Create views that we can swap */
1055     gmx::ArrayRefWithPadding<gmx::RVec> posWithPadding[2];
1056     gmx::ArrayRefWithPadding<gmx::RVec> forceWithPadding[2];
1057     gmx::ArrayRef<gmx::RVec>            pos[2];
1058     gmx::ArrayRef<gmx::RVec>            force[2];
1059     for (i = 0; (i < 2); i++)
1060     {
1061         posWithPadding[i]   = shfc->x[i].arrayRefWithPadding();
1062         pos[i]              = posWithPadding[i].paddedArrayRef();
1063         forceWithPadding[i] = shfc->f[i].arrayRefWithPadding();
1064         force[i]            = forceWithPadding[i].paddedArrayRef();
1065     }
1066
1067     if (bDoNS && inputrec->ePBC != epbcNONE && !DOMAINDECOMP(cr))
1068     {
1069         /* This is the only time where the coordinates are used
1070          * before do_force is called, which normally puts all
1071          * charge groups in the box.
1072          */
1073         auto xRef = x.paddedArrayRef();
1074         put_atoms_in_box_omp(fr->ePBC, box, xRef.subArray(0, md->homenr), gmx_omp_nthreads_get(emntDefault));
1075
1076         if (graph)
1077         {
1078             mk_mshift(fplog, graph, fr->ePBC, box, xRvec);
1079         }
1080     }
1081
1082     /* After this all coordinate arrays will contain whole charge groups */
1083     if (graph)
1084     {
1085         shift_self(graph, box, xRvec);
1086     }
1087
1088     if (nflexcon)
1089     {
1090         if (nat > shfc->flex_nalloc)
1091         {
1092             shfc->flex_nalloc = over_alloc_dd(nat);
1093             srenew(shfc->acc_dir, shfc->flex_nalloc);
1094             srenew(shfc->x_old, shfc->flex_nalloc);
1095         }
1096         acc_dir = shfc->acc_dir;
1097         x_old   = shfc->x_old;
1098         auto xArrayRef = x.paddedArrayRef();
1099         auto vArrayRef = v.paddedArrayRef();
1100         for (i = 0; i < homenr; i++)
1101         {
1102             for (d = 0; d < DIM; d++)
1103             {
1104                 shfc->x_old[i][d] =
1105                     xArrayRef[i][d] - vArrayRef[i][d]*inputrec->delta_t;
1106             }
1107         }
1108     }
1109
1110     /* Do a prediction of the shell positions, when appropriate.
1111      * Without velocities (EM, NM, BD) we only do initial prediction.
1112      */
1113     if (shfc->bPredict && !bCont && (EI_STATE_VELOCITY(inputrec->eI) || bInit))
1114     {
1115         predict_shells(fplog, xRvec, vRvec, inputrec->delta_t, nshell, shell,
1116                        md->massT, nullptr, bInit);
1117     }
1118
1119     /* do_force expected the charge groups to be in the box */
1120     if (graph)
1121     {
1122         unshift_self(graph, box, xRvec);
1123     }
1124
1125     /* Calculate the forces first time around */
1126     if (gmx_debug_at)
1127     {
1128         pr_rvecs(debug, 0, "x b4 do_force", xRvec, homenr);
1129     }
1130     int shellfc_flags = force_flags | (bVerbose ? GMX_FORCE_ENERGY : 0);
1131     do_force(fplog, cr, ms, inputrec, nullptr, enforcedRotation, imdSession,
1132              pull_work,
1133              mdstep, nrnb, wcycle, top,
1134              box, x, hist,
1135              forceWithPadding[Min], force_vir, md, enerd, fcd,
1136              lambda, graph,
1137              fr, ppForceWorkload, vsite, mu_tot, t, nullptr,
1138              (bDoNS ? GMX_FORCE_NS : 0) | shellfc_flags,
1139              ddBalanceRegionHandler);
1140
1141     sf_dir = 0;
1142     if (nflexcon)
1143     {
1144         init_adir(shfc,
1145                   constr, inputrec, cr, dd_ac1, mdstep, md, end,
1146                   shfc->x_old, xRvec, xRvec, as_rvec_array(force[Min].data()),
1147                   shfc->acc_dir,
1148                   box, lambda, &dum);
1149
1150         for (i = 0; i < end; i++)
1151         {
1152             sf_dir += md->massT[i]*norm2(shfc->acc_dir[i]);
1153         }
1154     }
1155     sum_epot(&(enerd->grpp), enerd->term);
1156     Epot[Min] = enerd->term[F_EPOT];
1157
1158     df[Min] = rms_force(cr, forceWithPadding[Min].paddedArrayRef(), nshell, shell, nflexcon, &sf_dir, &Epot[Min]);
1159     df[Try] = 0;
1160     if (debug)
1161     {
1162         fprintf(debug, "df = %g  %g\n", df[Min], df[Try]);
1163     }
1164
1165     if (gmx_debug_at)
1166     {
1167         pr_rvecs(debug, 0, "force0", as_rvec_array(force[Min].data()), md->nr);
1168     }
1169
1170     if (nshell+nflexcon > 0)
1171     {
1172         /* Copy x to pos[Min] & pos[Try]: during minimization only the
1173          * shell positions are updated, therefore the other particles must
1174          * be set here, in advance.
1175          */
1176         std::copy(x.paddedArrayRef().begin(),
1177                   x.paddedArrayRef().end(),
1178                   posWithPadding[Min].paddedArrayRef().begin());
1179         std::copy(x.paddedArrayRef().begin(),
1180                   x.paddedArrayRef().end(),
1181                   posWithPadding[Try].paddedArrayRef().begin());
1182     }
1183
1184     if (bVerbose && MASTER(cr))
1185     {
1186         print_epot(stdout, mdstep, 0, Epot[Min], df[Min], nflexcon, sf_dir);
1187     }
1188
1189     if (debug)
1190     {
1191         fprintf(debug, "%17s: %14.10e\n",
1192                 interaction_function[F_EKIN].longname, enerd->term[F_EKIN]);
1193         fprintf(debug, "%17s: %14.10e\n",
1194                 interaction_function[F_EPOT].longname, enerd->term[F_EPOT]);
1195         fprintf(debug, "%17s: %14.10e\n",
1196                 interaction_function[F_ETOT].longname, enerd->term[F_ETOT]);
1197         fprintf(debug, "SHELLSTEP %s\n", gmx_step_str(mdstep, sbuf));
1198     }
1199
1200     /* First check whether we should do shells, or whether the force is
1201      * low enough even without minimization.
1202      */
1203     bConverged = (df[Min] < ftol);
1204
1205     for (count = 1; (!(bConverged) && (count < number_steps)); count++)
1206     {
1207         if (vsite)
1208         {
1209             construct_vsites(vsite, as_rvec_array(pos[Min].data()),
1210                              inputrec->delta_t, vRvec,
1211                              idef->iparams, idef->il,
1212                              fr->ePBC, fr->bMolPBC, cr, box);
1213         }
1214
1215         if (nflexcon)
1216         {
1217             init_adir(shfc,
1218                       constr, inputrec, cr, dd_ac1, mdstep, md, end,
1219                       x_old, xRvec,
1220                       as_rvec_array(pos[Min].data()),
1221                       as_rvec_array(force[Min].data()), acc_dir,
1222                       box, lambda, &dum);
1223
1224             directional_sd(pos[Min], pos[Try], acc_dir, end, fr->fc_stepsize);
1225         }
1226
1227         /* New positions, Steepest descent */
1228         shell_pos_sd(pos[Min], pos[Try], force[Min], nshell, shell, count);
1229
1230         /* do_force expected the charge groups to be in the box */
1231         if (graph)
1232         {
1233             unshift_self(graph, box, as_rvec_array(pos[Try].data()));
1234         }
1235
1236         if (gmx_debug_at)
1237         {
1238             pr_rvecs(debug, 0, "RELAX: pos[Min]  ", as_rvec_array(pos[Min].data()), homenr);
1239             pr_rvecs(debug, 0, "RELAX: pos[Try]  ", as_rvec_array(pos[Try].data()), homenr);
1240         }
1241         /* Try the new positions */
1242         do_force(fplog, cr, ms, inputrec, nullptr, enforcedRotation, imdSession,
1243                  pull_work,
1244                  1, nrnb, wcycle,
1245                  top, box, posWithPadding[Try], hist,
1246                  forceWithPadding[Try], force_vir,
1247                  md, enerd, fcd, lambda, graph,
1248                  fr, ppForceWorkload, vsite, mu_tot, t, nullptr,
1249                  shellfc_flags,
1250                  ddBalanceRegionHandler);
1251         sum_epot(&(enerd->grpp), enerd->term);
1252         if (gmx_debug_at)
1253         {
1254             pr_rvecs(debug, 0, "RELAX: force[Min]", as_rvec_array(force[Min].data()), homenr);
1255             pr_rvecs(debug, 0, "RELAX: force[Try]", as_rvec_array(force[Try].data()), homenr);
1256         }
1257         sf_dir = 0;
1258         if (nflexcon)
1259         {
1260             init_adir(shfc,
1261                       constr, inputrec, cr, dd_ac1, mdstep, md, end,
1262                       x_old, xRvec,
1263                       as_rvec_array(pos[Try].data()),
1264                       as_rvec_array(force[Try].data()),
1265                       acc_dir, box, lambda, &dum);
1266
1267             for (i = 0; i < end; i++)
1268             {
1269                 sf_dir += md->massT[i]*norm2(acc_dir[i]);
1270             }
1271         }
1272
1273         Epot[Try] = enerd->term[F_EPOT];
1274
1275         df[Try] = rms_force(cr, force[Try], nshell, shell, nflexcon, &sf_dir, &Epot[Try]);
1276
1277         if (debug)
1278         {
1279             fprintf(debug, "df = %g  %g\n", df[Min], df[Try]);
1280         }
1281
1282         if (debug)
1283         {
1284             if (gmx_debug_at)
1285             {
1286                 pr_rvecs(debug, 0, "F na do_force", as_rvec_array(force[Try].data()), homenr);
1287             }
1288             if (gmx_debug_at)
1289             {
1290                 fprintf(debug, "SHELL ITER %d\n", count);
1291                 dump_shells(debug, force[Try], ftol, nshell, shell);
1292             }
1293         }
1294
1295         if (bVerbose && MASTER(cr))
1296         {
1297             print_epot(stdout, mdstep, count, Epot[Try], df[Try], nflexcon, sf_dir);
1298         }
1299
1300         bConverged = (df[Try] < ftol);
1301
1302         if ((df[Try] < df[Min]))
1303         {
1304             if (debug)
1305             {
1306                 fprintf(debug, "Swapping Min and Try\n");
1307             }
1308             if (nflexcon)
1309             {
1310                 /* Correct the velocities for the flexible constraints */
1311                 invdt = 1/inputrec->delta_t;
1312                 auto vArrayRef = v.paddedArrayRef();
1313                 for (i = 0; i < end; i++)
1314                 {
1315                     for (d = 0; d < DIM; d++)
1316                     {
1317                         vArrayRef[i][d] += (pos[Try][i][d] - pos[Min][i][d])*invdt;
1318                     }
1319                 }
1320             }
1321             Min  = Try;
1322         }
1323         else
1324         {
1325             decrease_step_size(nshell, shell);
1326         }
1327     }
1328     shfc->numForceEvaluations += count;
1329     if (bConverged)
1330     {
1331         shfc->numConvergedIterations++;
1332     }
1333     if (MASTER(cr) && !(bConverged))
1334     {
1335         /* Note that the energies and virial are incorrect when not converged */
1336         if (fplog)
1337         {
1338             fprintf(fplog,
1339                     "step %s: EM did not converge in %d iterations, RMS force %6.2e\n",
1340                     gmx_step_str(mdstep, sbuf), number_steps, df[Min]);
1341         }
1342         fprintf(stderr,
1343                 "step %s: EM did not converge in %d iterations, RMS force %6.2e\n",
1344                 gmx_step_str(mdstep, sbuf), number_steps, df[Min]);
1345     }
1346
1347     /* Copy back the coordinates and the forces */
1348     std::copy(pos[Min].begin(), pos[Min].end(), x.paddedArrayRef().data());
1349     std::copy(force[Min].begin(), force[Min].end(), f.unpaddedArrayRef().begin());
1350 }
1351
1352 void done_shellfc(FILE *fplog, gmx_shellfc_t *shfc, int64_t numSteps)
1353 {
1354     if (shfc && fplog && numSteps > 0)
1355     {
1356         double numStepsAsDouble = static_cast<double>(numSteps);
1357         fprintf(fplog, "Fraction of iterations that converged:           %.2f %%\n",
1358                 (shfc->numConvergedIterations*100.0)/numStepsAsDouble);
1359         fprintf(fplog, "Average number of force evaluations per MD step: %.2f\n\n",
1360                 shfc->numForceEvaluations/numStepsAsDouble);
1361     }
1362
1363     // TODO Deallocate memory in shfc
1364 }