Fix center of mass motion removal with frozen atoms
[alexxy/gromacs.git] / src / gromacs / gmxpreprocess / readir.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-2004, The GROMACS development team.
6  * Copyright (c) 2013-2020, 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 "readir.h"
40
41 #include <cctype>
42 #include <climits>
43 #include <cmath>
44 #include <cstdlib>
45
46 #include <algorithm>
47 #include <string>
48
49 #include "gromacs/awh/read_params.h"
50 #include "gromacs/fileio/readinp.h"
51 #include "gromacs/fileio/warninp.h"
52 #include "gromacs/gmxlib/network.h"
53 #include "gromacs/gmxpreprocess/toputil.h"
54 #include "gromacs/math/functions.h"
55 #include "gromacs/math/units.h"
56 #include "gromacs/math/vec.h"
57 #include "gromacs/mdlib/calc_verletbuf.h"
58 #include "gromacs/mdrun/mdmodules.h"
59 #include "gromacs/mdtypes/inputrec.h"
60 #include "gromacs/mdtypes/md_enums.h"
61 #include "gromacs/mdtypes/pull_params.h"
62 #include "gromacs/options/options.h"
63 #include "gromacs/options/treesupport.h"
64 #include "gromacs/pbcutil/pbc.h"
65 #include "gromacs/selection/indexutil.h"
66 #include "gromacs/topology/block.h"
67 #include "gromacs/topology/ifunc.h"
68 #include "gromacs/topology/index.h"
69 #include "gromacs/topology/mtop_util.h"
70 #include "gromacs/topology/symtab.h"
71 #include "gromacs/topology/topology.h"
72 #include "gromacs/utility/cstringutil.h"
73 #include "gromacs/utility/exceptions.h"
74 #include "gromacs/utility/fatalerror.h"
75 #include "gromacs/utility/filestream.h"
76 #include "gromacs/utility/gmxassert.h"
77 #include "gromacs/utility/ikeyvaluetreeerror.h"
78 #include "gromacs/utility/keyvaluetree.h"
79 #include "gromacs/utility/keyvaluetreebuilder.h"
80 #include "gromacs/utility/keyvaluetreemdpwriter.h"
81 #include "gromacs/utility/keyvaluetreetransform.h"
82 #include "gromacs/utility/mdmodulenotification.h"
83 #include "gromacs/utility/smalloc.h"
84 #include "gromacs/utility/strconvert.h"
85 #include "gromacs/utility/stringcompare.h"
86 #include "gromacs/utility/stringutil.h"
87 #include "gromacs/utility/textwriter.h"
88
89 #define MAXPTR 254
90 #define NOGID 255
91
92 /* Resource parameters
93  * Do not change any of these until you read the instruction
94  * in readinp.h. Some cpp's do not take spaces after the backslash
95  * (like the c-shell), which will give you a very weird compiler
96  * message.
97  */
98
99 typedef struct t_inputrec_strings
100 {
101     char tcgrps[STRLEN], tau_t[STRLEN], ref_t[STRLEN], acc[STRLEN], accgrps[STRLEN], freeze[STRLEN],
102             frdim[STRLEN], energy[STRLEN], user1[STRLEN], user2[STRLEN], vcm[STRLEN],
103             x_compressed_groups[STRLEN], couple_moltype[STRLEN], orirefitgrp[STRLEN],
104             egptable[STRLEN], egpexcl[STRLEN], wall_atomtype[STRLEN], wall_density[STRLEN],
105             deform[STRLEN], QMMM[STRLEN], imd_grp[STRLEN];
106     char   fep_lambda[efptNR][STRLEN];
107     char   lambda_weights[STRLEN];
108     char** pull_grp;
109     char** rot_grp;
110     char   anneal[STRLEN], anneal_npoints[STRLEN], anneal_time[STRLEN], anneal_temp[STRLEN];
111     char   QMmethod[STRLEN], QMbasis[STRLEN], QMcharge[STRLEN], QMmult[STRLEN], bSH[STRLEN],
112             CASorbitals[STRLEN], CASelectrons[STRLEN], SAon[STRLEN], SAoff[STRLEN], SAsteps[STRLEN];
113
114 } gmx_inputrec_strings;
115
116 static gmx_inputrec_strings* is = nullptr;
117
118 void init_inputrec_strings()
119 {
120     if (is)
121     {
122         gmx_incons(
123                 "Attempted to call init_inputrec_strings before calling done_inputrec_strings. "
124                 "Only one inputrec (i.e. .mdp file) can be parsed at a time.");
125     }
126     snew(is, 1);
127 }
128
129 void done_inputrec_strings()
130 {
131     sfree(is);
132     is = nullptr;
133 }
134
135
136 enum
137 {
138     egrptpALL,         /* All particles have to be a member of a group.     */
139     egrptpALL_GENREST, /* A rest group with name is generated for particles *
140                         * that are not part of any group.                   */
141     egrptpPART,        /* As egrptpALL_GENREST, but no name is generated    *
142                         * for the rest group.                               */
143     egrptpONE          /* Merge all selected groups into one group,         *
144                         * make a rest group for the remaining particles.    */
145 };
146
147 static const char* constraints[eshNR + 1] = { "none",     "h-bonds",    "all-bonds",
148                                               "h-angles", "all-angles", nullptr };
149
150 static const char* couple_lam[ecouplamNR + 1] = { "vdw-q", "vdw", "q", "none", nullptr };
151
152 static void GetSimTemps(int ntemps, t_simtemp* simtemp, double* temperature_lambdas)
153 {
154
155     int i;
156
157     for (i = 0; i < ntemps; i++)
158     {
159         /* simple linear scaling -- allows more control */
160         if (simtemp->eSimTempScale == esimtempLINEAR)
161         {
162             simtemp->temperatures[i] =
163                     simtemp->simtemp_low
164                     + (simtemp->simtemp_high - simtemp->simtemp_low) * temperature_lambdas[i];
165         }
166         else if (simtemp->eSimTempScale
167                  == esimtempGEOMETRIC) /* should give roughly equal acceptance for constant heat capacity . . . */
168         {
169             simtemp->temperatures[i] = simtemp->simtemp_low
170                                        * std::pow(simtemp->simtemp_high / simtemp->simtemp_low,
171                                                   static_cast<real>((1.0 * i) / (ntemps - 1)));
172         }
173         else if (simtemp->eSimTempScale == esimtempEXPONENTIAL)
174         {
175             simtemp->temperatures[i] = simtemp->simtemp_low
176                                        + (simtemp->simtemp_high - simtemp->simtemp_low)
177                                                  * (std::expm1(temperature_lambdas[i]) / std::expm1(1.0));
178         }
179         else
180         {
181             char errorstr[128];
182             sprintf(errorstr, "eSimTempScale=%d not defined", simtemp->eSimTempScale);
183             gmx_fatal(FARGS, "%s", errorstr);
184         }
185     }
186 }
187
188
189 static void _low_check(bool b, const char* s, warninp_t wi)
190 {
191     if (b)
192     {
193         warning_error(wi, s);
194     }
195 }
196
197 static void check_nst(const char* desc_nst, int nst, const char* desc_p, int* p, warninp_t wi)
198 {
199     char buf[STRLEN];
200
201     if (*p > 0 && *p % nst != 0)
202     {
203         /* Round up to the next multiple of nst */
204         *p = ((*p) / nst + 1) * nst;
205         sprintf(buf, "%s should be a multiple of %s, changing %s to %d\n", desc_p, desc_nst, desc_p, *p);
206         warning(wi, buf);
207     }
208 }
209
210 static int lcd(int n1, int n2)
211 {
212     int d, i;
213
214     d = 1;
215     for (i = 2; (i <= n1 && i <= n2); i++)
216     {
217         if (n1 % i == 0 && n2 % i == 0)
218         {
219             d = i;
220         }
221     }
222
223     return d;
224 }
225
226 //! Convert legacy mdp entries to modern ones.
227 static void process_interaction_modifier(int* eintmod)
228 {
229     if (*eintmod == eintmodPOTSHIFT_VERLET_UNSUPPORTED)
230     {
231         *eintmod = eintmodPOTSHIFT;
232     }
233 }
234
235 void check_ir(const char*                   mdparin,
236               const gmx::MdModulesNotifier& mdModulesNotifier,
237               t_inputrec*                   ir,
238               t_gromppopts*                 opts,
239               warninp_t                     wi)
240 /* Check internal consistency.
241  * NOTE: index groups are not set here yet, don't check things
242  * like temperature coupling group options here, but in triple_check
243  */
244 {
245     /* Strange macro: first one fills the err_buf, and then one can check
246      * the condition, which will print the message and increase the error
247      * counter.
248      */
249 #define CHECK(b) _low_check(b, err_buf, wi)
250     char        err_buf[256], warn_buf[STRLEN];
251     int         i, j;
252     real        dt_pcoupl;
253     t_lambda*   fep    = ir->fepvals;
254     t_expanded* expand = ir->expandedvals;
255
256     set_warning_line(wi, mdparin, -1);
257
258     if (ir->coulombtype == eelRF_NEC_UNSUPPORTED)
259     {
260         sprintf(warn_buf, "%s electrostatics is no longer supported", eel_names[eelRF_NEC_UNSUPPORTED]);
261         warning_error(wi, warn_buf);
262     }
263
264     /* BASIC CUT-OFF STUFF */
265     if (ir->rcoulomb < 0)
266     {
267         warning_error(wi, "rcoulomb should be >= 0");
268     }
269     if (ir->rvdw < 0)
270     {
271         warning_error(wi, "rvdw should be >= 0");
272     }
273     if (ir->rlist < 0 && !(ir->cutoff_scheme == ecutsVERLET && ir->verletbuf_tol > 0))
274     {
275         warning_error(wi, "rlist should be >= 0");
276     }
277     sprintf(err_buf,
278             "nstlist can not be smaller than 0. (If you were trying to use the heuristic "
279             "neighbour-list update scheme for efficient buffering for improved energy "
280             "conservation, please use the Verlet cut-off scheme instead.)");
281     CHECK(ir->nstlist < 0);
282
283     process_interaction_modifier(&ir->coulomb_modifier);
284     process_interaction_modifier(&ir->vdw_modifier);
285
286     if (ir->cutoff_scheme == ecutsGROUP)
287     {
288         gmx_fatal(FARGS,
289                   "The group cutoff scheme has been removed since GROMACS 2020. "
290                   "Please use the Verlet cutoff scheme.");
291     }
292     if (ir->cutoff_scheme == ecutsVERLET)
293     {
294         real rc_max;
295
296         /* Normal Verlet type neighbor-list, currently only limited feature support */
297         if (inputrec2nboundeddim(ir) < 3)
298         {
299             warning_error(wi, "With Verlet lists only full pbc or pbc=xy with walls is supported");
300         }
301
302         // We don't (yet) have general Verlet kernels for rcoulomb!=rvdw
303         if (ir->rcoulomb != ir->rvdw)
304         {
305             // Since we have PME coulomb + LJ cut-off kernels with rcoulomb>rvdw
306             // for PME load balancing, we can support this exception.
307             bool bUsesPmeTwinRangeKernel = (EEL_PME_EWALD(ir->coulombtype) && ir->vdwtype == evdwCUT
308                                             && ir->rcoulomb > ir->rvdw);
309             if (!bUsesPmeTwinRangeKernel)
310             {
311                 warning_error(wi,
312                               "With Verlet lists rcoulomb!=rvdw is not supported (except for "
313                               "rcoulomb>rvdw with PME electrostatics)");
314             }
315         }
316
317         if (ir->vdwtype == evdwSHIFT || ir->vdwtype == evdwSWITCH)
318         {
319             if (ir->vdw_modifier == eintmodNONE || ir->vdw_modifier == eintmodPOTSHIFT)
320             {
321                 ir->vdw_modifier = (ir->vdwtype == evdwSHIFT ? eintmodFORCESWITCH : eintmodPOTSWITCH);
322
323                 sprintf(warn_buf,
324                         "Replacing vdwtype=%s by the equivalent combination of vdwtype=%s and "
325                         "vdw_modifier=%s",
326                         evdw_names[ir->vdwtype], evdw_names[evdwCUT], eintmod_names[ir->vdw_modifier]);
327                 warning_note(wi, warn_buf);
328
329                 ir->vdwtype = evdwCUT;
330             }
331             else
332             {
333                 sprintf(warn_buf, "Unsupported combination of vdwtype=%s and vdw_modifier=%s",
334                         evdw_names[ir->vdwtype], eintmod_names[ir->vdw_modifier]);
335                 warning_error(wi, warn_buf);
336             }
337         }
338
339         if (!(ir->vdwtype == evdwCUT || ir->vdwtype == evdwPME))
340         {
341             warning_error(wi,
342                           "With Verlet lists only cut-off and PME LJ interactions are supported");
343         }
344         if (!(ir->coulombtype == eelCUT || EEL_RF(ir->coulombtype) || EEL_PME(ir->coulombtype)
345               || ir->coulombtype == eelEWALD))
346         {
347             warning_error(wi,
348                           "With Verlet lists only cut-off, reaction-field, PME and Ewald "
349                           "electrostatics are supported");
350         }
351         if (!(ir->coulomb_modifier == eintmodNONE || ir->coulomb_modifier == eintmodPOTSHIFT))
352         {
353             sprintf(warn_buf, "coulomb_modifier=%s is not supported", eintmod_names[ir->coulomb_modifier]);
354             warning_error(wi, warn_buf);
355         }
356
357         if (EEL_USER(ir->coulombtype))
358         {
359             sprintf(warn_buf, "Coulomb type %s is not supported with the verlet scheme",
360                     eel_names[ir->coulombtype]);
361             warning_error(wi, warn_buf);
362         }
363
364         if (ir->nstlist <= 0)
365         {
366             warning_error(wi, "With Verlet lists nstlist should be larger than 0");
367         }
368
369         if (ir->nstlist < 10)
370         {
371             warning_note(wi,
372                          "With Verlet lists the optimal nstlist is >= 10, with GPUs >= 20. Note "
373                          "that with the Verlet scheme, nstlist has no effect on the accuracy of "
374                          "your simulation.");
375         }
376
377         rc_max = std::max(ir->rvdw, ir->rcoulomb);
378
379         if (EI_TPI(ir->eI))
380         {
381             /* With TPI we set the pairlist cut-off later using the radius of the insterted molecule */
382             ir->verletbuf_tol = 0;
383             ir->rlist         = rc_max;
384         }
385         else if (ir->verletbuf_tol <= 0)
386         {
387             if (ir->verletbuf_tol == 0)
388             {
389                 warning_error(wi, "Can not have Verlet buffer tolerance of exactly 0");
390             }
391
392             if (ir->rlist < rc_max)
393             {
394                 warning_error(wi,
395                               "With verlet lists rlist can not be smaller than rvdw or rcoulomb");
396             }
397
398             if (ir->rlist == rc_max && ir->nstlist > 1)
399             {
400                 warning_note(
401                         wi,
402                         "rlist is equal to rvdw and/or rcoulomb: there is no explicit Verlet "
403                         "buffer. The cluster pair list does have a buffering effect, but choosing "
404                         "a larger rlist might be necessary for good energy conservation.");
405             }
406         }
407         else
408         {
409             if (ir->rlist > rc_max)
410             {
411                 warning_note(wi,
412                              "You have set rlist larger than the interaction cut-off, but you also "
413                              "have verlet-buffer-tolerance > 0. Will set rlist using "
414                              "verlet-buffer-tolerance.");
415             }
416
417             if (ir->nstlist == 1)
418             {
419                 /* No buffer required */
420                 ir->rlist = rc_max;
421             }
422             else
423             {
424                 if (EI_DYNAMICS(ir->eI))
425                 {
426                     if (inputrec2nboundeddim(ir) < 3)
427                     {
428                         warning_error(wi,
429                                       "The box volume is required for calculating rlist from the "
430                                       "energy drift with verlet-buffer-tolerance > 0. You are "
431                                       "using at least one unbounded dimension, so no volume can be "
432                                       "computed. Either use a finite box, or set rlist yourself "
433                                       "together with verlet-buffer-tolerance = -1.");
434                     }
435                     /* Set rlist temporarily so we can continue processing */
436                     ir->rlist = rc_max;
437                 }
438                 else
439                 {
440                     /* Set the buffer to 5% of the cut-off */
441                     ir->rlist = (1.0 + verlet_buffer_ratio_nodynamics) * rc_max;
442                 }
443             }
444         }
445     }
446
447     /* GENERAL INTEGRATOR STUFF */
448     if (!EI_MD(ir->eI))
449     {
450         if (ir->etc != etcNO)
451         {
452             if (EI_RANDOM(ir->eI))
453             {
454                 sprintf(warn_buf,
455                         "Setting tcoupl from '%s' to 'no'. %s handles temperature coupling "
456                         "implicitly. See the documentation for more information on which "
457                         "parameters affect temperature for %s.",
458                         etcoupl_names[ir->etc], ei_names[ir->eI], ei_names[ir->eI]);
459             }
460             else
461             {
462                 sprintf(warn_buf,
463                         "Setting tcoupl from '%s' to 'no'. Temperature coupling does not apply to "
464                         "%s.",
465                         etcoupl_names[ir->etc], ei_names[ir->eI]);
466             }
467             warning_note(wi, warn_buf);
468         }
469         ir->etc = etcNO;
470     }
471     if (ir->eI == eiVVAK)
472     {
473         sprintf(warn_buf,
474                 "Integrator method %s is implemented primarily for validation purposes; for "
475                 "molecular dynamics, you should probably be using %s or %s",
476                 ei_names[eiVVAK], ei_names[eiMD], ei_names[eiVV]);
477         warning_note(wi, warn_buf);
478     }
479     if (!EI_DYNAMICS(ir->eI))
480     {
481         if (ir->epc != epcNO)
482         {
483             sprintf(warn_buf,
484                     "Setting pcoupl from '%s' to 'no'. Pressure coupling does not apply to %s.",
485                     epcoupl_names[ir->epc], ei_names[ir->eI]);
486             warning_note(wi, warn_buf);
487         }
488         ir->epc = epcNO;
489     }
490     if (EI_DYNAMICS(ir->eI))
491     {
492         if (ir->nstcalcenergy < 0)
493         {
494             ir->nstcalcenergy = ir_optimal_nstcalcenergy(ir);
495             if (ir->nstenergy != 0 && ir->nstenergy < ir->nstcalcenergy)
496             {
497                 /* nstcalcenergy larger than nstener does not make sense.
498                  * We ideally want nstcalcenergy=nstener.
499                  */
500                 if (ir->nstlist > 0)
501                 {
502                     ir->nstcalcenergy = lcd(ir->nstenergy, ir->nstlist);
503                 }
504                 else
505                 {
506                     ir->nstcalcenergy = ir->nstenergy;
507                 }
508             }
509         }
510         else if ((ir->nstenergy > 0 && ir->nstcalcenergy > ir->nstenergy)
511                  || (ir->efep != efepNO && ir->fepvals->nstdhdl > 0
512                      && (ir->nstcalcenergy > ir->fepvals->nstdhdl)))
513
514         {
515             const char* nsten    = "nstenergy";
516             const char* nstdh    = "nstdhdl";
517             const char* min_name = nsten;
518             int         min_nst  = ir->nstenergy;
519
520             /* find the smallest of ( nstenergy, nstdhdl ) */
521             if (ir->efep != efepNO && ir->fepvals->nstdhdl > 0
522                 && (ir->nstenergy == 0 || ir->fepvals->nstdhdl < ir->nstenergy))
523             {
524                 min_nst  = ir->fepvals->nstdhdl;
525                 min_name = nstdh;
526             }
527             /* If the user sets nstenergy small, we should respect that */
528             sprintf(warn_buf, "Setting nstcalcenergy (%d) equal to %s (%d)", ir->nstcalcenergy,
529                     min_name, min_nst);
530             warning_note(wi, warn_buf);
531             ir->nstcalcenergy = min_nst;
532         }
533
534         if (ir->epc != epcNO)
535         {
536             if (ir->nstpcouple < 0)
537             {
538                 ir->nstpcouple = ir_optimal_nstpcouple(ir);
539             }
540         }
541
542         if (ir->nstcalcenergy > 0)
543         {
544             if (ir->efep != efepNO)
545             {
546                 /* nstdhdl should be a multiple of nstcalcenergy */
547                 check_nst("nstcalcenergy", ir->nstcalcenergy, "nstdhdl", &ir->fepvals->nstdhdl, wi);
548             }
549             if (ir->bExpanded)
550             {
551                 /* nstexpanded should be a multiple of nstcalcenergy */
552                 check_nst("nstcalcenergy", ir->nstcalcenergy, "nstexpanded",
553                           &ir->expandedvals->nstexpanded, wi);
554             }
555             /* for storing exact averages nstenergy should be
556              * a multiple of nstcalcenergy
557              */
558             check_nst("nstcalcenergy", ir->nstcalcenergy, "nstenergy", &ir->nstenergy, wi);
559         }
560
561         // Inquire all MdModules, if their parameters match with the energy
562         // calculation frequency
563         gmx::EnergyCalculationFrequencyErrors energyCalculationFrequencyErrors(ir->nstcalcenergy);
564         mdModulesNotifier.notifier_.notify(&energyCalculationFrequencyErrors);
565
566         // Emit all errors from the energy calculation frequency checks
567         for (const std::string& energyFrequencyErrorMessage :
568              energyCalculationFrequencyErrors.errorMessages())
569         {
570             warning_error(wi, energyFrequencyErrorMessage);
571         }
572     }
573
574     if (ir->nsteps == 0 && !ir->bContinuation)
575     {
576         warning_note(wi,
577                      "For a correct single-point energy evaluation with nsteps = 0, use "
578                      "continuation = yes to avoid constraining the input coordinates.");
579     }
580
581     /* LD STUFF */
582     if ((EI_SD(ir->eI) || ir->eI == eiBD) && ir->bContinuation && ir->ld_seed != -1)
583     {
584         warning_note(wi,
585                      "You are doing a continuation with SD or BD, make sure that ld_seed is "
586                      "different from the previous run (using ld_seed=-1 will ensure this)");
587     }
588
589     /* TPI STUFF */
590     if (EI_TPI(ir->eI))
591     {
592         sprintf(err_buf, "TPI only works with pbc = %s", epbc_names[epbcXYZ]);
593         CHECK(ir->ePBC != epbcXYZ);
594         sprintf(err_buf, "with TPI nstlist should be larger than zero");
595         CHECK(ir->nstlist <= 0);
596         sprintf(err_buf, "TPI does not work with full electrostatics other than PME");
597         CHECK(EEL_FULL(ir->coulombtype) && !EEL_PME(ir->coulombtype));
598     }
599
600     /* SHAKE / LINCS */
601     if ((opts->nshake > 0) && (opts->bMorse))
602     {
603         sprintf(warn_buf, "Using morse bond-potentials while constraining bonds is useless");
604         warning(wi, warn_buf);
605     }
606
607     if ((EI_SD(ir->eI) || ir->eI == eiBD) && ir->bContinuation && ir->ld_seed != -1)
608     {
609         warning_note(wi,
610                      "You are doing a continuation with SD or BD, make sure that ld_seed is "
611                      "different from the previous run (using ld_seed=-1 will ensure this)");
612     }
613     /* verify simulated tempering options */
614
615     if (ir->bSimTemp)
616     {
617         bool bAllTempZero = TRUE;
618         for (i = 0; i < fep->n_lambda; i++)
619         {
620             sprintf(err_buf, "Entry %d for %s must be between 0 and 1, instead is %g", i,
621                     efpt_names[efptTEMPERATURE], fep->all_lambda[efptTEMPERATURE][i]);
622             CHECK((fep->all_lambda[efptTEMPERATURE][i] < 0) || (fep->all_lambda[efptTEMPERATURE][i] > 1));
623             if (fep->all_lambda[efptTEMPERATURE][i] > 0)
624             {
625                 bAllTempZero = FALSE;
626             }
627         }
628         sprintf(err_buf, "if simulated tempering is on, temperature-lambdas may not be all zero");
629         CHECK(bAllTempZero == TRUE);
630
631         sprintf(err_buf, "Simulated tempering is currently only compatible with md-vv");
632         CHECK(ir->eI != eiVV);
633
634         /* check compatability of the temperature coupling with simulated tempering */
635
636         if (ir->etc == etcNOSEHOOVER)
637         {
638             sprintf(warn_buf,
639                     "Nose-Hoover based temperature control such as [%s] my not be "
640                     "entirelyconsistent with simulated tempering",
641                     etcoupl_names[ir->etc]);
642             warning_note(wi, warn_buf);
643         }
644
645         /* check that the temperatures make sense */
646
647         sprintf(err_buf,
648                 "Higher simulated tempering temperature (%g) must be >= than the simulated "
649                 "tempering lower temperature (%g)",
650                 ir->simtempvals->simtemp_high, ir->simtempvals->simtemp_low);
651         CHECK(ir->simtempvals->simtemp_high <= ir->simtempvals->simtemp_low);
652
653         sprintf(err_buf, "Higher simulated tempering temperature (%g) must be >= zero",
654                 ir->simtempvals->simtemp_high);
655         CHECK(ir->simtempvals->simtemp_high <= 0);
656
657         sprintf(err_buf, "Lower simulated tempering temperature (%g) must be >= zero",
658                 ir->simtempvals->simtemp_low);
659         CHECK(ir->simtempvals->simtemp_low <= 0);
660     }
661
662     /* verify free energy options */
663
664     if (ir->efep != efepNO)
665     {
666         fep = ir->fepvals;
667         sprintf(err_buf, "The soft-core power is %d and can only be 1 or 2", fep->sc_power);
668         CHECK(fep->sc_alpha != 0 && fep->sc_power != 1 && fep->sc_power != 2);
669
670         sprintf(err_buf, "The soft-core sc-r-power is %d and can only be 6 or 48",
671                 static_cast<int>(fep->sc_r_power));
672         CHECK(fep->sc_alpha != 0 && fep->sc_r_power != 6.0 && fep->sc_r_power != 48.0);
673
674         sprintf(err_buf,
675                 "Can't use positive delta-lambda (%g) if initial state/lambda does not start at "
676                 "zero",
677                 fep->delta_lambda);
678         CHECK(fep->delta_lambda > 0 && ((fep->init_fep_state > 0) || (fep->init_lambda > 0)));
679
680         sprintf(err_buf, "Can't use positive delta-lambda (%g) with expanded ensemble simulations",
681                 fep->delta_lambda);
682         CHECK(fep->delta_lambda > 0 && (ir->efep == efepEXPANDED));
683
684         sprintf(err_buf, "Can only use expanded ensemble with md-vv (for now)");
685         CHECK(!(EI_VV(ir->eI)) && (ir->efep == efepEXPANDED));
686
687         sprintf(err_buf, "Free-energy not implemented for Ewald");
688         CHECK(ir->coulombtype == eelEWALD);
689
690         /* check validty of lambda inputs */
691         if (fep->n_lambda == 0)
692         {
693             /* Clear output in case of no states:*/
694             sprintf(err_buf, "init-lambda-state set to %d: no lambda states are defined.",
695                     fep->init_fep_state);
696             CHECK((fep->init_fep_state >= 0) && (fep->n_lambda == 0));
697         }
698         else
699         {
700             sprintf(err_buf, "initial thermodynamic state %d does not exist, only goes to %d",
701                     fep->init_fep_state, fep->n_lambda - 1);
702             CHECK((fep->init_fep_state >= fep->n_lambda));
703         }
704
705         sprintf(err_buf,
706                 "Lambda state must be set, either with init-lambda-state or with init-lambda");
707         CHECK((fep->init_fep_state < 0) && (fep->init_lambda < 0));
708
709         sprintf(err_buf,
710                 "init-lambda=%g while init-lambda-state=%d. Lambda state must be set either with "
711                 "init-lambda-state or with init-lambda, but not both",
712                 fep->init_lambda, fep->init_fep_state);
713         CHECK((fep->init_fep_state >= 0) && (fep->init_lambda >= 0));
714
715
716         if ((fep->init_lambda >= 0) && (fep->delta_lambda == 0))
717         {
718             int n_lambda_terms;
719             n_lambda_terms = 0;
720             for (i = 0; i < efptNR; i++)
721             {
722                 if (fep->separate_dvdl[i])
723                 {
724                     n_lambda_terms++;
725                 }
726             }
727             if (n_lambda_terms > 1)
728             {
729                 sprintf(warn_buf,
730                         "If lambda vector states (fep-lambdas, coul-lambdas etc.) are set, don't "
731                         "use init-lambda to set lambda state (except for slow growth). Use "
732                         "init-lambda-state instead.");
733                 warning(wi, warn_buf);
734             }
735
736             if (n_lambda_terms < 2 && fep->n_lambda > 0)
737             {
738                 warning_note(wi,
739                              "init-lambda is deprecated for setting lambda state (except for slow "
740                              "growth). Use init-lambda-state instead.");
741             }
742         }
743
744         for (j = 0; j < efptNR; j++)
745         {
746             for (i = 0; i < fep->n_lambda; i++)
747             {
748                 sprintf(err_buf, "Entry %d for %s must be between 0 and 1, instead is %g", i,
749                         efpt_names[j], fep->all_lambda[j][i]);
750                 CHECK((fep->all_lambda[j][i] < 0) || (fep->all_lambda[j][i] > 1));
751             }
752         }
753
754         if ((fep->sc_alpha > 0) && (!fep->bScCoul))
755         {
756             for (i = 0; i < fep->n_lambda; i++)
757             {
758                 sprintf(err_buf,
759                         "For state %d, vdw-lambdas (%f) is changing with vdw softcore, while "
760                         "coul-lambdas (%f) is nonzero without coulomb softcore: this will lead to "
761                         "crashes, and is not supported.",
762                         i, fep->all_lambda[efptVDW][i], fep->all_lambda[efptCOUL][i]);
763                 CHECK((fep->sc_alpha > 0)
764                       && (((fep->all_lambda[efptCOUL][i] > 0.0) && (fep->all_lambda[efptCOUL][i] < 1.0))
765                           && ((fep->all_lambda[efptVDW][i] > 0.0) && (fep->all_lambda[efptVDW][i] < 1.0))));
766             }
767         }
768
769         if ((fep->bScCoul) && (EEL_PME(ir->coulombtype)))
770         {
771             real sigma, lambda, r_sc;
772
773             sigma = 0.34;
774             /* Maximum estimate for A and B charges equal with lambda power 1 */
775             lambda = 0.5;
776             r_sc = std::pow(lambda * fep->sc_alpha * std::pow(sigma / ir->rcoulomb, fep->sc_r_power) + 1.0,
777                             1.0 / fep->sc_r_power);
778             sprintf(warn_buf,
779                     "With PME there is a minor soft core effect present at the cut-off, "
780                     "proportional to (LJsigma/rcoulomb)^%g. This could have a minor effect on "
781                     "energy conservation, but usually other effects dominate. With a common sigma "
782                     "value of %g nm the fraction of the particle-particle potential at the cut-off "
783                     "at lambda=%g is around %.1e, while ewald-rtol is %.1e.",
784                     fep->sc_r_power, sigma, lambda, r_sc - 1.0, ir->ewald_rtol);
785             warning_note(wi, warn_buf);
786         }
787
788         /*  Free Energy Checks -- In an ideal world, slow growth and FEP would
789             be treated differently, but that's the next step */
790
791         for (i = 0; i < efptNR; i++)
792         {
793             for (j = 0; j < fep->n_lambda; j++)
794             {
795                 sprintf(err_buf, "%s[%d] must be between 0 and 1", efpt_names[i], j);
796                 CHECK((fep->all_lambda[i][j] < 0) || (fep->all_lambda[i][j] > 1));
797             }
798         }
799     }
800
801     if ((ir->bSimTemp) || (ir->efep == efepEXPANDED))
802     {
803         fep = ir->fepvals;
804
805         /* checking equilibration of weights inputs for validity */
806
807         sprintf(err_buf,
808                 "weight-equil-number-all-lambda (%d) is ignored if lmc-weights-equil is not equal "
809                 "to %s",
810                 expand->equil_n_at_lam, elmceq_names[elmceqNUMATLAM]);
811         CHECK((expand->equil_n_at_lam > 0) && (expand->elmceq != elmceqNUMATLAM));
812
813         sprintf(err_buf,
814                 "weight-equil-number-samples (%d) is ignored if lmc-weights-equil is not equal to "
815                 "%s",
816                 expand->equil_samples, elmceq_names[elmceqSAMPLES]);
817         CHECK((expand->equil_samples > 0) && (expand->elmceq != elmceqSAMPLES));
818
819         sprintf(err_buf,
820                 "weight-equil-number-steps (%d) is ignored if lmc-weights-equil is not equal to %s",
821                 expand->equil_steps, elmceq_names[elmceqSTEPS]);
822         CHECK((expand->equil_steps > 0) && (expand->elmceq != elmceqSTEPS));
823
824         sprintf(err_buf,
825                 "weight-equil-wl-delta (%d) is ignored if lmc-weights-equil is not equal to %s",
826                 expand->equil_samples, elmceq_names[elmceqWLDELTA]);
827         CHECK((expand->equil_wl_delta > 0) && (expand->elmceq != elmceqWLDELTA));
828
829         sprintf(err_buf,
830                 "weight-equil-count-ratio (%f) is ignored if lmc-weights-equil is not equal to %s",
831                 expand->equil_ratio, elmceq_names[elmceqRATIO]);
832         CHECK((expand->equil_ratio > 0) && (expand->elmceq != elmceqRATIO));
833
834         sprintf(err_buf,
835                 "weight-equil-number-all-lambda (%d) must be a positive integer if "
836                 "lmc-weights-equil=%s",
837                 expand->equil_n_at_lam, elmceq_names[elmceqNUMATLAM]);
838         CHECK((expand->equil_n_at_lam <= 0) && (expand->elmceq == elmceqNUMATLAM));
839
840         sprintf(err_buf,
841                 "weight-equil-number-samples (%d) must be a positive integer if "
842                 "lmc-weights-equil=%s",
843                 expand->equil_samples, elmceq_names[elmceqSAMPLES]);
844         CHECK((expand->equil_samples <= 0) && (expand->elmceq == elmceqSAMPLES));
845
846         sprintf(err_buf,
847                 "weight-equil-number-steps (%d) must be a positive integer if lmc-weights-equil=%s",
848                 expand->equil_steps, elmceq_names[elmceqSTEPS]);
849         CHECK((expand->equil_steps <= 0) && (expand->elmceq == elmceqSTEPS));
850
851         sprintf(err_buf, "weight-equil-wl-delta (%f) must be > 0 if lmc-weights-equil=%s",
852                 expand->equil_wl_delta, elmceq_names[elmceqWLDELTA]);
853         CHECK((expand->equil_wl_delta <= 0) && (expand->elmceq == elmceqWLDELTA));
854
855         sprintf(err_buf, "weight-equil-count-ratio (%f) must be > 0 if lmc-weights-equil=%s",
856                 expand->equil_ratio, elmceq_names[elmceqRATIO]);
857         CHECK((expand->equil_ratio <= 0) && (expand->elmceq == elmceqRATIO));
858
859         sprintf(err_buf, "lmc-weights-equil=%s only possible when lmc-stats = %s or lmc-stats %s",
860                 elmceq_names[elmceqWLDELTA], elamstats_names[elamstatsWL], elamstats_names[elamstatsWWL]);
861         CHECK((expand->elmceq == elmceqWLDELTA) && (!EWL(expand->elamstats)));
862
863         sprintf(err_buf, "lmc-repeats (%d) must be greater than 0", expand->lmc_repeats);
864         CHECK((expand->lmc_repeats <= 0));
865         sprintf(err_buf, "minimum-var-min (%d) must be greater than 0", expand->minvarmin);
866         CHECK((expand->minvarmin <= 0));
867         sprintf(err_buf, "weight-c-range (%d) must be greater or equal to 0", expand->c_range);
868         CHECK((expand->c_range < 0));
869         sprintf(err_buf,
870                 "init-lambda-state (%d) must be zero if lmc-forced-nstart (%d)> 0 and lmc-move != "
871                 "'no'",
872                 fep->init_fep_state, expand->lmc_forced_nstart);
873         CHECK((fep->init_fep_state != 0) && (expand->lmc_forced_nstart > 0)
874               && (expand->elmcmove != elmcmoveNO));
875         sprintf(err_buf, "lmc-forced-nstart (%d) must not be negative", expand->lmc_forced_nstart);
876         CHECK((expand->lmc_forced_nstart < 0));
877         sprintf(err_buf, "init-lambda-state (%d) must be in the interval [0,number of lambdas)",
878                 fep->init_fep_state);
879         CHECK((fep->init_fep_state < 0) || (fep->init_fep_state >= fep->n_lambda));
880
881         sprintf(err_buf, "init-wl-delta (%f) must be greater than or equal to 0", expand->init_wl_delta);
882         CHECK((expand->init_wl_delta < 0));
883         sprintf(err_buf, "wl-ratio (%f) must be between 0 and 1", expand->wl_ratio);
884         CHECK((expand->wl_ratio <= 0) || (expand->wl_ratio >= 1));
885         sprintf(err_buf, "wl-scale (%f) must be between 0 and 1", expand->wl_scale);
886         CHECK((expand->wl_scale <= 0) || (expand->wl_scale >= 1));
887
888         /* if there is no temperature control, we need to specify an MC temperature */
889         if (!integratorHasReferenceTemperature(ir) && (expand->elmcmove != elmcmoveNO)
890             && (expand->mc_temp <= 0.0))
891         {
892             sprintf(err_buf,
893                     "If there is no temperature control, and lmc-mcmove!='no', mc_temp must be set "
894                     "to a positive number");
895             warning_error(wi, err_buf);
896         }
897         if (expand->nstTij > 0)
898         {
899             sprintf(err_buf, "nstlog must be non-zero");
900             CHECK(ir->nstlog == 0);
901             // Avoid modulus by zero in the case that already triggered an error exit.
902             if (ir->nstlog != 0)
903             {
904                 sprintf(err_buf,
905                         "nst-transition-matrix (%d) must be an integer multiple of nstlog (%d)",
906                         expand->nstTij, ir->nstlog);
907                 CHECK((expand->nstTij % ir->nstlog) != 0);
908             }
909         }
910     }
911
912     /* PBC/WALLS */
913     sprintf(err_buf, "walls only work with pbc=%s", epbc_names[epbcXY]);
914     CHECK(ir->nwall && ir->ePBC != epbcXY);
915
916     /* VACUUM STUFF */
917     if (ir->ePBC != epbcXYZ && ir->nwall != 2)
918     {
919         if (ir->ePBC == epbcNONE)
920         {
921             if (ir->epc != epcNO)
922             {
923                 warning(wi, "Turning off pressure coupling for vacuum system");
924                 ir->epc = epcNO;
925             }
926         }
927         else
928         {
929             sprintf(err_buf, "Can not have pressure coupling with pbc=%s", epbc_names[ir->ePBC]);
930             CHECK(ir->epc != epcNO);
931         }
932         sprintf(err_buf, "Can not have Ewald with pbc=%s", epbc_names[ir->ePBC]);
933         CHECK(EEL_FULL(ir->coulombtype));
934
935         sprintf(err_buf, "Can not have dispersion correction with pbc=%s", epbc_names[ir->ePBC]);
936         CHECK(ir->eDispCorr != edispcNO);
937     }
938
939     if (ir->rlist == 0.0)
940     {
941         sprintf(err_buf,
942                 "can only have neighborlist cut-off zero (=infinite)\n"
943                 "with coulombtype = %s or coulombtype = %s\n"
944                 "without periodic boundary conditions (pbc = %s) and\n"
945                 "rcoulomb and rvdw set to zero",
946                 eel_names[eelCUT], eel_names[eelUSER], epbc_names[epbcNONE]);
947         CHECK(((ir->coulombtype != eelCUT) && (ir->coulombtype != eelUSER))
948               || (ir->ePBC != epbcNONE) || (ir->rcoulomb != 0.0) || (ir->rvdw != 0.0));
949
950         if (ir->nstlist > 0)
951         {
952             warning_note(wi,
953                          "Simulating without cut-offs can be (slightly) faster with nstlist=0, "
954                          "nstype=simple and only one MPI rank");
955         }
956     }
957
958     /* COMM STUFF */
959     if (ir->nstcomm == 0)
960     {
961         // TODO Change this behaviour. There should be exactly one way
962         // to turn off an algorithm.
963         ir->comm_mode = ecmNO;
964     }
965     if (ir->comm_mode != ecmNO)
966     {
967         if (ir->nstcomm < 0)
968         {
969             // TODO Such input was once valid. Now that we've been
970             // helpful for a few years, we should reject such input,
971             // lest we have to support every historical decision
972             // forever.
973             warning(wi,
974                     "If you want to remove the rotation around the center of mass, you should set "
975                     "comm_mode = Angular instead of setting nstcomm < 0. nstcomm is modified to "
976                     "its absolute value");
977             ir->nstcomm = abs(ir->nstcomm);
978         }
979
980         if (ir->nstcalcenergy > 0 && ir->nstcomm < ir->nstcalcenergy)
981         {
982             warning_note(wi,
983                          "nstcomm < nstcalcenergy defeats the purpose of nstcalcenergy, setting "
984                          "nstcomm to nstcalcenergy");
985             ir->nstcomm = ir->nstcalcenergy;
986         }
987
988         if (ir->comm_mode == ecmANGULAR)
989         {
990             sprintf(err_buf,
991                     "Can not remove the rotation around the center of mass with periodic "
992                     "molecules");
993             CHECK(ir->bPeriodicMols);
994             if (ir->ePBC != epbcNONE)
995             {
996                 warning(wi,
997                         "Removing the rotation around the center of mass in a periodic system, "
998                         "this can lead to artifacts. Only use this on a single (cluster of) "
999                         "molecules. This cluster should not cross periodic boundaries.");
1000             }
1001         }
1002     }
1003
1004     if (EI_STATE_VELOCITY(ir->eI) && !EI_SD(ir->eI) && ir->ePBC == epbcNONE && ir->comm_mode != ecmANGULAR)
1005     {
1006         sprintf(warn_buf,
1007                 "Tumbling and flying ice-cubes: We are not removing rotation around center of mass "
1008                 "in a non-periodic system. You should probably set comm_mode = ANGULAR or use "
1009                 "integrator = %s.",
1010                 ei_names[eiSD1]);
1011         warning_note(wi, warn_buf);
1012     }
1013
1014     /* TEMPERATURE COUPLING */
1015     if (ir->etc == etcYES)
1016     {
1017         ir->etc = etcBERENDSEN;
1018         warning_note(wi,
1019                      "Old option for temperature coupling given: "
1020                      "changing \"yes\" to \"Berendsen\"\n");
1021     }
1022
1023     if ((ir->etc == etcNOSEHOOVER) || (ir->epc == epcMTTK))
1024     {
1025         if (ir->opts.nhchainlength < 1)
1026         {
1027             sprintf(warn_buf,
1028                     "number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to "
1029                     "1\n",
1030                     ir->opts.nhchainlength);
1031             ir->opts.nhchainlength = 1;
1032             warning(wi, warn_buf);
1033         }
1034
1035         if (ir->etc == etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
1036         {
1037             warning_note(
1038                     wi,
1039                     "leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
1040             ir->opts.nhchainlength = 1;
1041         }
1042     }
1043     else
1044     {
1045         ir->opts.nhchainlength = 0;
1046     }
1047
1048     if (ir->eI == eiVVAK)
1049     {
1050         sprintf(err_buf,
1051                 "%s implemented primarily for validation, and requires nsttcouple = 1 and "
1052                 "nstpcouple = 1.",
1053                 ei_names[eiVVAK]);
1054         CHECK((ir->nsttcouple != 1) || (ir->nstpcouple != 1));
1055     }
1056
1057     if (ETC_ANDERSEN(ir->etc))
1058     {
1059         sprintf(err_buf, "%s temperature control not supported for integrator %s.",
1060                 etcoupl_names[ir->etc], ei_names[ir->eI]);
1061         CHECK(!(EI_VV(ir->eI)));
1062
1063         if (ir->nstcomm > 0 && (ir->etc == etcANDERSEN))
1064         {
1065             sprintf(warn_buf,
1066                     "Center of mass removal not necessary for %s.  All velocities of coupled "
1067                     "groups are rerandomized periodically, so flying ice cube errors will not "
1068                     "occur.",
1069                     etcoupl_names[ir->etc]);
1070             warning_note(wi, warn_buf);
1071         }
1072
1073         sprintf(err_buf,
1074                 "nstcomm must be 1, not %d for %s, as velocities of atoms in coupled groups are "
1075                 "randomized every time step",
1076                 ir->nstcomm, etcoupl_names[ir->etc]);
1077         CHECK(ir->nstcomm > 1 && (ir->etc == etcANDERSEN));
1078     }
1079
1080     if (ir->etc == etcBERENDSEN)
1081     {
1082         sprintf(warn_buf,
1083                 "The %s thermostat does not generate the correct kinetic energy distribution. You "
1084                 "might want to consider using the %s thermostat.",
1085                 ETCOUPLTYPE(ir->etc), ETCOUPLTYPE(etcVRESCALE));
1086         warning_note(wi, warn_buf);
1087     }
1088
1089     if ((ir->etc == etcNOSEHOOVER || ETC_ANDERSEN(ir->etc)) && ir->epc == epcBERENDSEN)
1090     {
1091         sprintf(warn_buf,
1092                 "Using Berendsen pressure coupling invalidates the "
1093                 "true ensemble for the thermostat");
1094         warning(wi, warn_buf);
1095     }
1096
1097     /* PRESSURE COUPLING */
1098     if (ir->epc == epcISOTROPIC)
1099     {
1100         ir->epc = epcBERENDSEN;
1101         warning_note(wi,
1102                      "Old option for pressure coupling given: "
1103                      "changing \"Isotropic\" to \"Berendsen\"\n");
1104     }
1105
1106     if (ir->epc != epcNO)
1107     {
1108         dt_pcoupl = ir->nstpcouple * ir->delta_t;
1109
1110         sprintf(err_buf, "tau-p must be > 0 instead of %g\n", ir->tau_p);
1111         CHECK(ir->tau_p <= 0);
1112
1113         if (ir->tau_p / dt_pcoupl < pcouple_min_integration_steps(ir->epc) - 10 * GMX_REAL_EPS)
1114         {
1115             sprintf(warn_buf,
1116                     "For proper integration of the %s barostat, tau-p (%g) should be at least %d "
1117                     "times larger than nstpcouple*dt (%g)",
1118                     EPCOUPLTYPE(ir->epc), ir->tau_p, pcouple_min_integration_steps(ir->epc), dt_pcoupl);
1119             warning(wi, warn_buf);
1120         }
1121
1122         sprintf(err_buf,
1123                 "compressibility must be > 0 when using pressure"
1124                 " coupling %s\n",
1125                 EPCOUPLTYPE(ir->epc));
1126         CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || ir->compress[ZZ][ZZ] < 0
1127               || (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 && ir->compress[ZZ][XX] <= 0
1128                   && ir->compress[ZZ][YY] <= 0));
1129
1130         if (epcPARRINELLORAHMAN == ir->epc && opts->bGenVel)
1131         {
1132             sprintf(warn_buf,
1133                     "You are generating velocities so I am assuming you "
1134                     "are equilibrating a system. You are using "
1135                     "%s pressure coupling, but this can be "
1136                     "unstable for equilibration. If your system crashes, try "
1137                     "equilibrating first with Berendsen pressure coupling. If "
1138                     "you are not equilibrating the system, you can probably "
1139                     "ignore this warning.",
1140                     epcoupl_names[ir->epc]);
1141             warning(wi, warn_buf);
1142         }
1143     }
1144
1145     if (!EI_VV(ir->eI))
1146     {
1147         if (ir->epc == epcMTTK)
1148         {
1149             warning_error(wi, "MTTK pressure coupling requires a Velocity-verlet integrator");
1150         }
1151     }
1152
1153     /* ELECTROSTATICS */
1154     /* More checks are in triple check (grompp.c) */
1155
1156     if (ir->coulombtype == eelSWITCH)
1157     {
1158         sprintf(warn_buf,
1159                 "coulombtype = %s is only for testing purposes and can lead to serious "
1160                 "artifacts, advice: use coulombtype = %s",
1161                 eel_names[ir->coulombtype], eel_names[eelRF_ZERO]);
1162         warning(wi, warn_buf);
1163     }
1164
1165     if (EEL_RF(ir->coulombtype) && ir->epsilon_rf == 1 && ir->epsilon_r != 1)
1166     {
1167         sprintf(warn_buf,
1168                 "epsilon-r = %g and epsilon-rf = 1 with reaction field, proceeding assuming old "
1169                 "format and exchanging epsilon-r and epsilon-rf",
1170                 ir->epsilon_r);
1171         warning(wi, warn_buf);
1172         ir->epsilon_rf = ir->epsilon_r;
1173         ir->epsilon_r  = 1.0;
1174     }
1175
1176     if (ir->epsilon_r == 0)
1177     {
1178         sprintf(err_buf,
1179                 "It is pointless to use long-range electrostatics with infinite relative "
1180                 "permittivity."
1181                 "Since you are effectively turning of electrostatics, a plain cutoff will be much "
1182                 "faster.");
1183         CHECK(EEL_FULL(ir->coulombtype));
1184     }
1185
1186     if (getenv("GMX_DO_GALACTIC_DYNAMICS") == nullptr)
1187     {
1188         sprintf(err_buf, "epsilon-r must be >= 0 instead of %g\n", ir->epsilon_r);
1189         CHECK(ir->epsilon_r < 0);
1190     }
1191
1192     if (EEL_RF(ir->coulombtype))
1193     {
1194         /* reaction field (at the cut-off) */
1195
1196         if (ir->coulombtype == eelRF_ZERO && ir->epsilon_rf != 0)
1197         {
1198             sprintf(warn_buf,
1199                     "With coulombtype = %s, epsilon-rf must be 0, assuming you meant epsilon_rf=0",
1200                     eel_names[ir->coulombtype]);
1201             warning(wi, warn_buf);
1202             ir->epsilon_rf = 0.0;
1203         }
1204
1205         sprintf(err_buf, "epsilon-rf must be >= epsilon-r");
1206         CHECK((ir->epsilon_rf < ir->epsilon_r && ir->epsilon_rf != 0) || (ir->epsilon_r == 0));
1207         if (ir->epsilon_rf == ir->epsilon_r)
1208         {
1209             sprintf(warn_buf, "Using epsilon-rf = epsilon-r with %s does not make sense",
1210                     eel_names[ir->coulombtype]);
1211             warning(wi, warn_buf);
1212         }
1213     }
1214     /* Allow rlist>rcoulomb for tabulated long range stuff. This just
1215      * means the interaction is zero outside rcoulomb, but it helps to
1216      * provide accurate energy conservation.
1217      */
1218     if (ir_coulomb_might_be_zero_at_cutoff(ir))
1219     {
1220         if (ir_coulomb_switched(ir))
1221         {
1222             sprintf(err_buf,
1223                     "With coulombtype = %s rcoulomb_switch must be < rcoulomb. Or, better: Use the "
1224                     "potential modifier options!",
1225                     eel_names[ir->coulombtype]);
1226             CHECK(ir->rcoulomb_switch >= ir->rcoulomb);
1227         }
1228     }
1229
1230     if (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT)
1231     {
1232         sprintf(err_buf,
1233                 "Explicit switch/shift coulomb interactions cannot be used in combination with a "
1234                 "secondary coulomb-modifier.");
1235         CHECK(ir->coulomb_modifier != eintmodNONE);
1236     }
1237     if (ir->vdwtype == evdwSWITCH || ir->vdwtype == evdwSHIFT)
1238     {
1239         sprintf(err_buf,
1240                 "Explicit switch/shift vdw interactions cannot be used in combination with a "
1241                 "secondary vdw-modifier.");
1242         CHECK(ir->vdw_modifier != eintmodNONE);
1243     }
1244
1245     if (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT || ir->vdwtype == evdwSWITCH
1246         || ir->vdwtype == evdwSHIFT)
1247     {
1248         sprintf(warn_buf,
1249                 "The switch/shift interaction settings are just for compatibility; you will get "
1250                 "better "
1251                 "performance from applying potential modifiers to your interactions!\n");
1252         warning_note(wi, warn_buf);
1253     }
1254
1255     if (ir->coulombtype == eelPMESWITCH || ir->coulomb_modifier == eintmodPOTSWITCH)
1256     {
1257         if (ir->rcoulomb_switch / ir->rcoulomb < 0.9499)
1258         {
1259             real percentage = 100 * (ir->rcoulomb - ir->rcoulomb_switch) / ir->rcoulomb;
1260             sprintf(warn_buf,
1261                     "The switching range should be 5%% or less (currently %.2f%% using a switching "
1262                     "range of %4f-%4f) for accurate electrostatic energies, energy conservation "
1263                     "will be good regardless, since ewald_rtol = %g.",
1264                     percentage, ir->rcoulomb_switch, ir->rcoulomb, ir->ewald_rtol);
1265             warning(wi, warn_buf);
1266         }
1267     }
1268
1269     if (ir->vdwtype == evdwSWITCH || ir->vdw_modifier == eintmodPOTSWITCH)
1270     {
1271         if (ir->rvdw_switch == 0)
1272         {
1273             sprintf(warn_buf,
1274                     "rvdw-switch is equal 0 even though you are using a switched Lennard-Jones "
1275                     "potential.  This suggests it was not set in the mdp, which can lead to large "
1276                     "energy errors.  In GROMACS, 0.05 to 0.1 nm is often a reasonable vdw "
1277                     "switching range.");
1278             warning(wi, warn_buf);
1279         }
1280     }
1281
1282     if (EEL_FULL(ir->coulombtype))
1283     {
1284         if (ir->coulombtype == eelPMESWITCH || ir->coulombtype == eelPMEUSER
1285             || ir->coulombtype == eelPMEUSERSWITCH)
1286         {
1287             sprintf(err_buf, "With coulombtype = %s, rcoulomb must be <= rlist",
1288                     eel_names[ir->coulombtype]);
1289             CHECK(ir->rcoulomb > ir->rlist);
1290         }
1291     }
1292
1293     if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
1294     {
1295         // TODO: Move these checks into the ewald module with the options class
1296         int orderMin = 3;
1297         int orderMax = (ir->coulombtype == eelP3M_AD ? 8 : 12);
1298
1299         if (ir->pme_order < orderMin || ir->pme_order > orderMax)
1300         {
1301             sprintf(warn_buf, "With coulombtype = %s, you should have %d <= pme-order <= %d",
1302                     eel_names[ir->coulombtype], orderMin, orderMax);
1303             warning_error(wi, warn_buf);
1304         }
1305     }
1306
1307     if (ir->nwall == 2 && EEL_FULL(ir->coulombtype))
1308     {
1309         if (ir->ewald_geometry == eewg3D)
1310         {
1311             sprintf(warn_buf, "With pbc=%s you should use ewald-geometry=%s", epbc_names[ir->ePBC],
1312                     eewg_names[eewg3DC]);
1313             warning(wi, warn_buf);
1314         }
1315         /* This check avoids extra pbc coding for exclusion corrections */
1316         sprintf(err_buf, "wall-ewald-zfac should be >= 2");
1317         CHECK(ir->wall_ewald_zfac < 2);
1318     }
1319     if ((ir->ewald_geometry == eewg3DC) && (ir->ePBC != epbcXY) && EEL_FULL(ir->coulombtype))
1320     {
1321         sprintf(warn_buf, "With %s and ewald_geometry = %s you should use pbc = %s",
1322                 eel_names[ir->coulombtype], eewg_names[eewg3DC], epbc_names[epbcXY]);
1323         warning(wi, warn_buf);
1324     }
1325     if ((ir->epsilon_surface != 0) && EEL_FULL(ir->coulombtype))
1326     {
1327         sprintf(err_buf, "Cannot have periodic molecules with epsilon_surface > 0");
1328         CHECK(ir->bPeriodicMols);
1329         sprintf(warn_buf, "With epsilon_surface > 0 all molecules should be neutral.");
1330         warning_note(wi, warn_buf);
1331         sprintf(warn_buf,
1332                 "With epsilon_surface > 0 you can only use domain decomposition "
1333                 "when there are only small molecules with all bonds constrained (mdrun will check "
1334                 "for this).");
1335         warning_note(wi, warn_buf);
1336     }
1337
1338     if (ir_vdw_switched(ir))
1339     {
1340         sprintf(err_buf, "With switched vdw forces or potentials, rvdw-switch must be < rvdw");
1341         CHECK(ir->rvdw_switch >= ir->rvdw);
1342
1343         if (ir->rvdw_switch < 0.5 * ir->rvdw)
1344         {
1345             sprintf(warn_buf,
1346                     "You are applying a switch function to vdw forces or potentials from %g to %g "
1347                     "nm, which is more than half the interaction range, whereas switch functions "
1348                     "are intended to act only close to the cut-off.",
1349                     ir->rvdw_switch, ir->rvdw);
1350             warning_note(wi, warn_buf);
1351         }
1352     }
1353
1354     if (ir->vdwtype == evdwPME)
1355     {
1356         if (!(ir->vdw_modifier == eintmodNONE || ir->vdw_modifier == eintmodPOTSHIFT))
1357         {
1358             sprintf(err_buf, "With vdwtype = %s, the only supported modifiers are %s and %s",
1359                     evdw_names[ir->vdwtype], eintmod_names[eintmodPOTSHIFT], eintmod_names[eintmodNONE]);
1360             warning_error(wi, err_buf);
1361         }
1362     }
1363
1364     if (ir->vdwtype == evdwUSER && ir->eDispCorr != edispcNO)
1365     {
1366         warning_note(wi,
1367                      "You have selected user tables with dispersion correction, the dispersion "
1368                      "will be corrected to -C6/r^6 beyond rvdw_switch (the tabulated interaction "
1369                      "between rvdw_switch and rvdw will not be double counted). Make sure that you "
1370                      "really want dispersion correction to -C6/r^6.");
1371     }
1372
1373     if (ir->eI == eiLBFGS && (ir->coulombtype == eelCUT || ir->vdwtype == evdwCUT) && ir->rvdw != 0)
1374     {
1375         warning(wi, "For efficient BFGS minimization, use switch/shift/pme instead of cut-off.");
1376     }
1377
1378     if (ir->eI == eiLBFGS && ir->nbfgscorr <= 0)
1379     {
1380         warning(wi, "Using L-BFGS with nbfgscorr<=0 just gets you steepest descent.");
1381     }
1382
1383     /* IMPLICIT SOLVENT */
1384     if (ir->coulombtype == eelGB_NOTUSED)
1385     {
1386         sprintf(warn_buf, "Invalid option %s for coulombtype", eel_names[ir->coulombtype]);
1387         warning_error(wi, warn_buf);
1388     }
1389
1390     if (ir->bQMMM)
1391     {
1392         warning_error(wi, "QMMM is currently not supported");
1393         if (!EI_DYNAMICS(ir->eI))
1394         {
1395             char buf[STRLEN];
1396             sprintf(buf, "QMMM is only supported with dynamics, not with integrator %s", ei_names[ir->eI]);
1397             warning_error(wi, buf);
1398         }
1399     }
1400
1401     if (ir->bAdress)
1402     {
1403         gmx_fatal(FARGS, "AdResS simulations are no longer supported");
1404     }
1405 }
1406
1407 /* interpret a number of doubles from a string and put them in an array,
1408    after allocating space for them.
1409    str = the input string
1410    n = the (pre-allocated) number of doubles read
1411    r = the output array of doubles. */
1412 static void parse_n_real(char* str, int* n, real** r, warninp_t wi)
1413 {
1414     auto values = gmx::splitString(str);
1415     *n          = values.size();
1416
1417     snew(*r, *n);
1418     for (int i = 0; i < *n; i++)
1419     {
1420         try
1421         {
1422             (*r)[i] = gmx::fromString<real>(values[i]);
1423         }
1424         catch (gmx::GromacsException&)
1425         {
1426             warning_error(wi, "Invalid value " + values[i]
1427                                       + " in string in mdp file. Expected a real number.");
1428         }
1429     }
1430 }
1431
1432
1433 static void do_fep_params(t_inputrec* ir, char fep_lambda[][STRLEN], char weights[STRLEN], warninp_t wi)
1434 {
1435
1436     int         i, j, max_n_lambda, nweights, nfep[efptNR];
1437     t_lambda*   fep    = ir->fepvals;
1438     t_expanded* expand = ir->expandedvals;
1439     real**      count_fep_lambdas;
1440     bool        bOneLambda = TRUE;
1441
1442     snew(count_fep_lambdas, efptNR);
1443
1444     /* FEP input processing */
1445     /* first, identify the number of lambda values for each type.
1446        All that are nonzero must have the same number */
1447
1448     for (i = 0; i < efptNR; i++)
1449     {
1450         parse_n_real(fep_lambda[i], &(nfep[i]), &(count_fep_lambdas[i]), wi);
1451     }
1452
1453     /* now, determine the number of components.  All must be either zero, or equal. */
1454
1455     max_n_lambda = 0;
1456     for (i = 0; i < efptNR; i++)
1457     {
1458         if (nfep[i] > max_n_lambda)
1459         {
1460             max_n_lambda = nfep[i]; /* here's a nonzero one.  All of them
1461                                        must have the same number if its not zero.*/
1462             break;
1463         }
1464     }
1465
1466     for (i = 0; i < efptNR; i++)
1467     {
1468         if (nfep[i] == 0)
1469         {
1470             ir->fepvals->separate_dvdl[i] = FALSE;
1471         }
1472         else if (nfep[i] == max_n_lambda)
1473         {
1474             if (i != efptTEMPERATURE) /* we treat this differently -- not really a reason to compute
1475                                          the derivative with respect to the temperature currently */
1476             {
1477                 ir->fepvals->separate_dvdl[i] = TRUE;
1478             }
1479         }
1480         else
1481         {
1482             gmx_fatal(FARGS,
1483                       "Number of lambdas (%d) for FEP type %s not equal to number of other types "
1484                       "(%d)",
1485                       nfep[i], efpt_names[i], max_n_lambda);
1486         }
1487     }
1488     /* we don't print out dhdl if the temperature is changing, since we can't correctly define dhdl in this case */
1489     ir->fepvals->separate_dvdl[efptTEMPERATURE] = FALSE;
1490
1491     /* the number of lambdas is the number we've read in, which is either zero
1492        or the same for all */
1493     fep->n_lambda = max_n_lambda;
1494
1495     /* allocate space for the array of lambda values */
1496     snew(fep->all_lambda, efptNR);
1497     /* if init_lambda is defined, we need to set lambda */
1498     if ((fep->init_lambda > 0) && (fep->n_lambda == 0))
1499     {
1500         ir->fepvals->separate_dvdl[efptFEP] = TRUE;
1501     }
1502     /* otherwise allocate the space for all of the lambdas, and transfer the data */
1503     for (i = 0; i < efptNR; i++)
1504     {
1505         snew(fep->all_lambda[i], fep->n_lambda);
1506         if (nfep[i] > 0) /* if it's zero, then the count_fep_lambda arrays
1507                             are zero */
1508         {
1509             for (j = 0; j < fep->n_lambda; j++)
1510             {
1511                 fep->all_lambda[i][j] = static_cast<double>(count_fep_lambdas[i][j]);
1512             }
1513             sfree(count_fep_lambdas[i]);
1514         }
1515     }
1516     sfree(count_fep_lambdas);
1517
1518     /* "fep-vals" is either zero or the full number. If zero, we'll need to define fep-lambdas for
1519        internal bookkeeping -- for now, init_lambda */
1520
1521     if ((nfep[efptFEP] == 0) && (fep->init_lambda >= 0))
1522     {
1523         for (i = 0; i < fep->n_lambda; i++)
1524         {
1525             fep->all_lambda[efptFEP][i] = fep->init_lambda;
1526         }
1527     }
1528
1529     /* check to see if only a single component lambda is defined, and soft core is defined.
1530        In this case, turn on coulomb soft core */
1531
1532     if (max_n_lambda == 0)
1533     {
1534         bOneLambda = TRUE;
1535     }
1536     else
1537     {
1538         for (i = 0; i < efptNR; i++)
1539         {
1540             if ((nfep[i] != 0) && (i != efptFEP))
1541             {
1542                 bOneLambda = FALSE;
1543             }
1544         }
1545     }
1546     if ((bOneLambda) && (fep->sc_alpha > 0))
1547     {
1548         fep->bScCoul = TRUE;
1549     }
1550
1551     /* Fill in the others with the efptFEP if they are not explicitly
1552        specified (i.e. nfep[i] == 0).  This means if fep is not defined,
1553        they are all zero. */
1554
1555     for (i = 0; i < efptNR; i++)
1556     {
1557         if ((nfep[i] == 0) && (i != efptFEP))
1558         {
1559             for (j = 0; j < fep->n_lambda; j++)
1560             {
1561                 fep->all_lambda[i][j] = fep->all_lambda[efptFEP][j];
1562             }
1563         }
1564     }
1565
1566
1567     /* make it easier if sc_r_power = 48 by increasing it to the 4th power, to be in the right scale. */
1568     if (fep->sc_r_power == 48)
1569     {
1570         if (fep->sc_alpha > 0.1)
1571         {
1572             gmx_fatal(FARGS,
1573                       "sc_alpha (%f) for sc_r_power = 48 should usually be between 0.001 and 0.004",
1574                       fep->sc_alpha);
1575         }
1576     }
1577
1578     /* now read in the weights */
1579     parse_n_real(weights, &nweights, &(expand->init_lambda_weights), wi);
1580     if (nweights == 0)
1581     {
1582         snew(expand->init_lambda_weights, fep->n_lambda); /* initialize to zero */
1583     }
1584     else if (nweights != fep->n_lambda)
1585     {
1586         gmx_fatal(FARGS, "Number of weights (%d) is not equal to number of lambda values (%d)",
1587                   nweights, fep->n_lambda);
1588     }
1589     if ((expand->nstexpanded < 0) && (ir->efep != efepNO))
1590     {
1591         expand->nstexpanded = fep->nstdhdl;
1592         /* if you don't specify nstexpanded when doing expanded ensemble free energy calcs, it is set to nstdhdl */
1593     }
1594 }
1595
1596
1597 static void do_simtemp_params(t_inputrec* ir)
1598 {
1599
1600     snew(ir->simtempvals->temperatures, ir->fepvals->n_lambda);
1601     GetSimTemps(ir->fepvals->n_lambda, ir->simtempvals, ir->fepvals->all_lambda[efptTEMPERATURE]);
1602 }
1603
1604 static void convertYesNos(warninp_t /*wi*/,
1605                           gmx::ArrayRef<const std::string> inputs,
1606                           const char* /*name*/,
1607                           gmx_bool* outputs)
1608 {
1609     int i = 0;
1610     for (const auto& input : inputs)
1611     {
1612         outputs[i] = gmx::equalCaseInsensitive(input, "Y", 1);
1613         ++i;
1614     }
1615 }
1616
1617 template<typename T>
1618 void convertInts(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, T* outputs)
1619 {
1620     int i = 0;
1621     for (const auto& input : inputs)
1622     {
1623         try
1624         {
1625             outputs[i] = gmx::fromStdString<T>(input);
1626         }
1627         catch (gmx::GromacsException&)
1628         {
1629             auto message = gmx::formatString(
1630                     "Invalid value for mdp option %s. %s should only consist of integers separated "
1631                     "by spaces.",
1632                     name, name);
1633             warning_error(wi, message);
1634         }
1635         ++i;
1636     }
1637 }
1638
1639 static void convertReals(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, real* outputs)
1640 {
1641     int i = 0;
1642     for (const auto& input : inputs)
1643     {
1644         try
1645         {
1646             outputs[i] = gmx::fromString<real>(input);
1647         }
1648         catch (gmx::GromacsException&)
1649         {
1650             auto message = gmx::formatString(
1651                     "Invalid value for mdp option %s. %s should only consist of real numbers "
1652                     "separated by spaces.",
1653                     name, name);
1654             warning_error(wi, message);
1655         }
1656         ++i;
1657     }
1658 }
1659
1660 static void convertRvecs(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, rvec* outputs)
1661 {
1662     int i = 0, d = 0;
1663     for (const auto& input : inputs)
1664     {
1665         try
1666         {
1667             outputs[i][d] = gmx::fromString<real>(input);
1668         }
1669         catch (gmx::GromacsException&)
1670         {
1671             auto message = gmx::formatString(
1672                     "Invalid value for mdp option %s. %s should only consist of real numbers "
1673                     "separated by spaces.",
1674                     name, name);
1675             warning_error(wi, message);
1676         }
1677         ++d;
1678         if (d == DIM)
1679         {
1680             d = 0;
1681             ++i;
1682         }
1683     }
1684 }
1685
1686 static void do_wall_params(t_inputrec* ir, char* wall_atomtype, char* wall_density, t_gromppopts* opts, warninp_t wi)
1687 {
1688     opts->wall_atomtype[0] = nullptr;
1689     opts->wall_atomtype[1] = nullptr;
1690
1691     ir->wall_atomtype[0] = -1;
1692     ir->wall_atomtype[1] = -1;
1693     ir->wall_density[0]  = 0;
1694     ir->wall_density[1]  = 0;
1695
1696     if (ir->nwall > 0)
1697     {
1698         auto wallAtomTypes = gmx::splitString(wall_atomtype);
1699         if (wallAtomTypes.size() != size_t(ir->nwall))
1700         {
1701             gmx_fatal(FARGS, "Expected %d elements for wall_atomtype, found %zu", ir->nwall,
1702                       wallAtomTypes.size());
1703         }
1704         for (int i = 0; i < ir->nwall; i++)
1705         {
1706             opts->wall_atomtype[i] = gmx_strdup(wallAtomTypes[i].c_str());
1707         }
1708
1709         if (ir->wall_type == ewt93 || ir->wall_type == ewt104)
1710         {
1711             auto wallDensity = gmx::splitString(wall_density);
1712             if (wallDensity.size() != size_t(ir->nwall))
1713             {
1714                 gmx_fatal(FARGS, "Expected %d elements for wall-density, found %zu", ir->nwall,
1715                           wallDensity.size());
1716             }
1717             convertReals(wi, wallDensity, "wall-density", ir->wall_density);
1718             for (int i = 0; i < ir->nwall; i++)
1719             {
1720                 if (ir->wall_density[i] <= 0)
1721                 {
1722                     gmx_fatal(FARGS, "wall-density[%d] = %f\n", i, ir->wall_density[i]);
1723                 }
1724             }
1725         }
1726     }
1727 }
1728
1729 static void add_wall_energrps(SimulationGroups* groups, int nwall, t_symtab* symtab)
1730 {
1731     if (nwall > 0)
1732     {
1733         AtomGroupIndices* grps = &(groups->groups[SimulationAtomGroupType::EnergyOutput]);
1734         for (int i = 0; i < nwall; i++)
1735         {
1736             groups->groupNames.emplace_back(put_symtab(symtab, gmx::formatString("wall%d", i).c_str()));
1737             grps->emplace_back(groups->groupNames.size() - 1);
1738         }
1739     }
1740 }
1741
1742 static void read_expandedparams(std::vector<t_inpfile>* inp, t_expanded* expand, warninp_t wi)
1743 {
1744     /* read expanded ensemble parameters */
1745     printStringNewline(inp, "expanded ensemble variables");
1746     expand->nstexpanded    = get_eint(inp, "nstexpanded", -1, wi);
1747     expand->elamstats      = get_eeenum(inp, "lmc-stats", elamstats_names, wi);
1748     expand->elmcmove       = get_eeenum(inp, "lmc-move", elmcmove_names, wi);
1749     expand->elmceq         = get_eeenum(inp, "lmc-weights-equil", elmceq_names, wi);
1750     expand->equil_n_at_lam = get_eint(inp, "weight-equil-number-all-lambda", -1, wi);
1751     expand->equil_samples  = get_eint(inp, "weight-equil-number-samples", -1, wi);
1752     expand->equil_steps    = get_eint(inp, "weight-equil-number-steps", -1, wi);
1753     expand->equil_wl_delta = get_ereal(inp, "weight-equil-wl-delta", -1, wi);
1754     expand->equil_ratio    = get_ereal(inp, "weight-equil-count-ratio", -1, wi);
1755     printStringNewline(inp, "Seed for Monte Carlo in lambda space");
1756     expand->lmc_seed          = get_eint(inp, "lmc-seed", -1, wi);
1757     expand->mc_temp           = get_ereal(inp, "mc-temperature", -1, wi);
1758     expand->lmc_repeats       = get_eint(inp, "lmc-repeats", 1, wi);
1759     expand->gibbsdeltalam     = get_eint(inp, "lmc-gibbsdelta", -1, wi);
1760     expand->lmc_forced_nstart = get_eint(inp, "lmc-forced-nstart", 0, wi);
1761     expand->bSymmetrizedTMatrix =
1762             (get_eeenum(inp, "symmetrized-transition-matrix", yesno_names, wi) != 0);
1763     expand->nstTij        = get_eint(inp, "nst-transition-matrix", -1, wi);
1764     expand->minvarmin     = get_eint(inp, "mininum-var-min", 100, wi); /*default is reasonable */
1765     expand->c_range       = get_eint(inp, "weight-c-range", 0, wi);    /* default is just C=0 */
1766     expand->wl_scale      = get_ereal(inp, "wl-scale", 0.8, wi);
1767     expand->wl_ratio      = get_ereal(inp, "wl-ratio", 0.8, wi);
1768     expand->init_wl_delta = get_ereal(inp, "init-wl-delta", 1.0, wi);
1769     expand->bWLoneovert   = (get_eeenum(inp, "wl-oneovert", yesno_names, wi) != 0);
1770 }
1771
1772 /*! \brief Return whether an end state with the given coupling-lambda
1773  * value describes fully-interacting VDW.
1774  *
1775  * \param[in]  couple_lambda_value  Enumeration ecouplam value describing the end state
1776  * \return                          Whether VDW is on (i.e. the user chose vdw or vdw-q in the .mdp file)
1777  */
1778 static bool couple_lambda_has_vdw_on(int couple_lambda_value)
1779 {
1780     return (couple_lambda_value == ecouplamVDW || couple_lambda_value == ecouplamVDWQ);
1781 }
1782
1783 namespace
1784 {
1785
1786 class MdpErrorHandler : public gmx::IKeyValueTreeErrorHandler
1787 {
1788 public:
1789     explicit MdpErrorHandler(warninp_t wi) : wi_(wi), mapping_(nullptr) {}
1790
1791     void setBackMapping(const gmx::IKeyValueTreeBackMapping& mapping) { mapping_ = &mapping; }
1792
1793     bool onError(gmx::UserInputError* ex, const gmx::KeyValueTreePath& context) override
1794     {
1795         ex->prependContext(
1796                 gmx::formatString("Error in mdp option \"%s\":", getOptionName(context).c_str()));
1797         std::string message = gmx::formatExceptionMessageToString(*ex);
1798         warning_error(wi_, message.c_str());
1799         return true;
1800     }
1801
1802 private:
1803     std::string getOptionName(const gmx::KeyValueTreePath& context)
1804     {
1805         if (mapping_ != nullptr)
1806         {
1807             gmx::KeyValueTreePath path = mapping_->originalPath(context);
1808             GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
1809             return path[0];
1810         }
1811         GMX_ASSERT(context.size() == 1, "Inconsistent context for mdp option parsing");
1812         return context[0];
1813     }
1814
1815     warninp_t                            wi_;
1816     const gmx::IKeyValueTreeBackMapping* mapping_;
1817 };
1818
1819 } // namespace
1820
1821 void get_ir(const char*     mdparin,
1822             const char*     mdparout,
1823             gmx::MDModules* mdModules,
1824             t_inputrec*     ir,
1825             t_gromppopts*   opts,
1826             WriteMdpHeader  writeMdpHeader,
1827             warninp_t       wi)
1828 {
1829     char*       dumstr[2];
1830     double      dumdub[2][6];
1831     int         i, j, m;
1832     char        warn_buf[STRLEN];
1833     t_lambda*   fep    = ir->fepvals;
1834     t_expanded* expand = ir->expandedvals;
1835
1836     const char* no_names[] = { "no", nullptr };
1837
1838     init_inputrec_strings();
1839     gmx::TextInputFile     stream(mdparin);
1840     std::vector<t_inpfile> inp = read_inpfile(&stream, mdparin, wi);
1841
1842     snew(dumstr[0], STRLEN);
1843     snew(dumstr[1], STRLEN);
1844
1845     /* ignore the following deprecated commands */
1846     replace_inp_entry(inp, "title", nullptr);
1847     replace_inp_entry(inp, "cpp", nullptr);
1848     replace_inp_entry(inp, "domain-decomposition", nullptr);
1849     replace_inp_entry(inp, "andersen-seed", nullptr);
1850     replace_inp_entry(inp, "dihre", nullptr);
1851     replace_inp_entry(inp, "dihre-fc", nullptr);
1852     replace_inp_entry(inp, "dihre-tau", nullptr);
1853     replace_inp_entry(inp, "nstdihreout", nullptr);
1854     replace_inp_entry(inp, "nstcheckpoint", nullptr);
1855     replace_inp_entry(inp, "optimize-fft", nullptr);
1856     replace_inp_entry(inp, "adress_type", nullptr);
1857     replace_inp_entry(inp, "adress_const_wf", nullptr);
1858     replace_inp_entry(inp, "adress_ex_width", nullptr);
1859     replace_inp_entry(inp, "adress_hy_width", nullptr);
1860     replace_inp_entry(inp, "adress_ex_forcecap", nullptr);
1861     replace_inp_entry(inp, "adress_interface_correction", nullptr);
1862     replace_inp_entry(inp, "adress_site", nullptr);
1863     replace_inp_entry(inp, "adress_reference_coords", nullptr);
1864     replace_inp_entry(inp, "adress_tf_grp_names", nullptr);
1865     replace_inp_entry(inp, "adress_cg_grp_names", nullptr);
1866     replace_inp_entry(inp, "adress_do_hybridpairs", nullptr);
1867     replace_inp_entry(inp, "rlistlong", nullptr);
1868     replace_inp_entry(inp, "nstcalclr", nullptr);
1869     replace_inp_entry(inp, "pull-print-com2", nullptr);
1870     replace_inp_entry(inp, "gb-algorithm", nullptr);
1871     replace_inp_entry(inp, "nstgbradii", nullptr);
1872     replace_inp_entry(inp, "rgbradii", nullptr);
1873     replace_inp_entry(inp, "gb-epsilon-solvent", nullptr);
1874     replace_inp_entry(inp, "gb-saltconc", nullptr);
1875     replace_inp_entry(inp, "gb-obc-alpha", nullptr);
1876     replace_inp_entry(inp, "gb-obc-beta", nullptr);
1877     replace_inp_entry(inp, "gb-obc-gamma", nullptr);
1878     replace_inp_entry(inp, "gb-dielectric-offset", nullptr);
1879     replace_inp_entry(inp, "sa-algorithm", nullptr);
1880     replace_inp_entry(inp, "sa-surface-tension", nullptr);
1881     replace_inp_entry(inp, "ns-type", nullptr);
1882
1883     /* replace the following commands with the clearer new versions*/
1884     replace_inp_entry(inp, "unconstrained-start", "continuation");
1885     replace_inp_entry(inp, "foreign-lambda", "fep-lambdas");
1886     replace_inp_entry(inp, "verlet-buffer-drift", "verlet-buffer-tolerance");
1887     replace_inp_entry(inp, "nstxtcout", "nstxout-compressed");
1888     replace_inp_entry(inp, "xtc-grps", "compressed-x-grps");
1889     replace_inp_entry(inp, "xtc-precision", "compressed-x-precision");
1890     replace_inp_entry(inp, "pull-print-com1", "pull-print-com");
1891
1892     printStringNewline(&inp, "VARIOUS PREPROCESSING OPTIONS");
1893     printStringNoNewline(&inp, "Preprocessor information: use cpp syntax.");
1894     printStringNoNewline(&inp, "e.g.: -I/home/joe/doe -I/home/mary/roe");
1895     setStringEntry(&inp, "include", opts->include, nullptr);
1896     printStringNoNewline(
1897             &inp, "e.g.: -DPOSRES -DFLEXIBLE (note these variable names are case sensitive)");
1898     setStringEntry(&inp, "define", opts->define, nullptr);
1899
1900     printStringNewline(&inp, "RUN CONTROL PARAMETERS");
1901     ir->eI = get_eeenum(&inp, "integrator", ei_names, wi);
1902     printStringNoNewline(&inp, "Start time and timestep in ps");
1903     ir->init_t  = get_ereal(&inp, "tinit", 0.0, wi);
1904     ir->delta_t = get_ereal(&inp, "dt", 0.001, wi);
1905     ir->nsteps  = get_eint64(&inp, "nsteps", 0, wi);
1906     printStringNoNewline(&inp, "For exact run continuation or redoing part of a run");
1907     ir->init_step = get_eint64(&inp, "init-step", 0, wi);
1908     printStringNoNewline(
1909             &inp, "Part index is updated automatically on checkpointing (keeps files separate)");
1910     ir->simulation_part = get_eint(&inp, "simulation-part", 1, wi);
1911     printStringNoNewline(&inp, "mode for center of mass motion removal");
1912     ir->comm_mode = get_eeenum(&inp, "comm-mode", ecm_names, wi);
1913     printStringNoNewline(&inp, "number of steps for center of mass motion removal");
1914     ir->nstcomm = get_eint(&inp, "nstcomm", 100, wi);
1915     printStringNoNewline(&inp, "group(s) for center of mass motion removal");
1916     setStringEntry(&inp, "comm-grps", is->vcm, nullptr);
1917
1918     printStringNewline(&inp, "LANGEVIN DYNAMICS OPTIONS");
1919     printStringNoNewline(&inp, "Friction coefficient (amu/ps) and random seed");
1920     ir->bd_fric = get_ereal(&inp, "bd-fric", 0.0, wi);
1921     ir->ld_seed = get_eint64(&inp, "ld-seed", -1, wi);
1922
1923     /* Em stuff */
1924     printStringNewline(&inp, "ENERGY MINIMIZATION OPTIONS");
1925     printStringNoNewline(&inp, "Force tolerance and initial step-size");
1926     ir->em_tol      = get_ereal(&inp, "emtol", 10.0, wi);
1927     ir->em_stepsize = get_ereal(&inp, "emstep", 0.01, wi);
1928     printStringNoNewline(&inp, "Max number of iterations in relax-shells");
1929     ir->niter = get_eint(&inp, "niter", 20, wi);
1930     printStringNoNewline(&inp, "Step size (ps^2) for minimization of flexible constraints");
1931     ir->fc_stepsize = get_ereal(&inp, "fcstep", 0, wi);
1932     printStringNoNewline(&inp, "Frequency of steepest descents steps when doing CG");
1933     ir->nstcgsteep = get_eint(&inp, "nstcgsteep", 1000, wi);
1934     ir->nbfgscorr  = get_eint(&inp, "nbfgscorr", 10, wi);
1935
1936     printStringNewline(&inp, "TEST PARTICLE INSERTION OPTIONS");
1937     ir->rtpi = get_ereal(&inp, "rtpi", 0.05, wi);
1938
1939     /* Output options */
1940     printStringNewline(&inp, "OUTPUT CONTROL OPTIONS");
1941     printStringNoNewline(&inp, "Output frequency for coords (x), velocities (v) and forces (f)");
1942     ir->nstxout = get_eint(&inp, "nstxout", 0, wi);
1943     ir->nstvout = get_eint(&inp, "nstvout", 0, wi);
1944     ir->nstfout = get_eint(&inp, "nstfout", 0, wi);
1945     printStringNoNewline(&inp, "Output frequency for energies to log file and energy file");
1946     ir->nstlog        = get_eint(&inp, "nstlog", 1000, wi);
1947     ir->nstcalcenergy = get_eint(&inp, "nstcalcenergy", 100, wi);
1948     ir->nstenergy     = get_eint(&inp, "nstenergy", 1000, wi);
1949     printStringNoNewline(&inp, "Output frequency and precision for .xtc file");
1950     ir->nstxout_compressed      = get_eint(&inp, "nstxout-compressed", 0, wi);
1951     ir->x_compression_precision = get_ereal(&inp, "compressed-x-precision", 1000.0, wi);
1952     printStringNoNewline(&inp, "This selects the subset of atoms for the compressed");
1953     printStringNoNewline(&inp, "trajectory file. You can select multiple groups. By");
1954     printStringNoNewline(&inp, "default, all atoms will be written.");
1955     setStringEntry(&inp, "compressed-x-grps", is->x_compressed_groups, nullptr);
1956     printStringNoNewline(&inp, "Selection of energy groups");
1957     setStringEntry(&inp, "energygrps", is->energy, nullptr);
1958
1959     /* Neighbor searching */
1960     printStringNewline(&inp, "NEIGHBORSEARCHING PARAMETERS");
1961     printStringNoNewline(&inp, "cut-off scheme (Verlet: particle based cut-offs)");
1962     ir->cutoff_scheme = get_eeenum(&inp, "cutoff-scheme", ecutscheme_names, wi);
1963     printStringNoNewline(&inp, "nblist update frequency");
1964     ir->nstlist = get_eint(&inp, "nstlist", 10, wi);
1965     printStringNoNewline(&inp, "Periodic boundary conditions: xyz, no, xy");
1966     ir->ePBC          = get_eeenum(&inp, "pbc", epbc_names, wi);
1967     ir->bPeriodicMols = get_eeenum(&inp, "periodic-molecules", yesno_names, wi) != 0;
1968     printStringNoNewline(&inp,
1969                          "Allowed energy error due to the Verlet buffer in kJ/mol/ps per atom,");
1970     printStringNoNewline(&inp, "a value of -1 means: use rlist");
1971     ir->verletbuf_tol = get_ereal(&inp, "verlet-buffer-tolerance", 0.005, wi);
1972     printStringNoNewline(&inp, "nblist cut-off");
1973     ir->rlist = get_ereal(&inp, "rlist", 1.0, wi);
1974     printStringNoNewline(&inp, "long-range cut-off for switched potentials");
1975
1976     /* Electrostatics */
1977     printStringNewline(&inp, "OPTIONS FOR ELECTROSTATICS AND VDW");
1978     printStringNoNewline(&inp, "Method for doing electrostatics");
1979     ir->coulombtype      = get_eeenum(&inp, "coulombtype", eel_names, wi);
1980     ir->coulomb_modifier = get_eeenum(&inp, "coulomb-modifier", eintmod_names, wi);
1981     printStringNoNewline(&inp, "cut-off lengths");
1982     ir->rcoulomb_switch = get_ereal(&inp, "rcoulomb-switch", 0.0, wi);
1983     ir->rcoulomb        = get_ereal(&inp, "rcoulomb", 1.0, wi);
1984     printStringNoNewline(&inp,
1985                          "Relative dielectric constant for the medium and the reaction field");
1986     ir->epsilon_r  = get_ereal(&inp, "epsilon-r", 1.0, wi);
1987     ir->epsilon_rf = get_ereal(&inp, "epsilon-rf", 0.0, wi);
1988     printStringNoNewline(&inp, "Method for doing Van der Waals");
1989     ir->vdwtype      = get_eeenum(&inp, "vdw-type", evdw_names, wi);
1990     ir->vdw_modifier = get_eeenum(&inp, "vdw-modifier", eintmod_names, wi);
1991     printStringNoNewline(&inp, "cut-off lengths");
1992     ir->rvdw_switch = get_ereal(&inp, "rvdw-switch", 0.0, wi);
1993     ir->rvdw        = get_ereal(&inp, "rvdw", 1.0, wi);
1994     printStringNoNewline(&inp, "Apply long range dispersion corrections for Energy and Pressure");
1995     ir->eDispCorr = get_eeenum(&inp, "DispCorr", edispc_names, wi);
1996     printStringNoNewline(&inp, "Extension of the potential lookup tables beyond the cut-off");
1997     ir->tabext = get_ereal(&inp, "table-extension", 1.0, wi);
1998     printStringNoNewline(&inp, "Separate tables between energy group pairs");
1999     setStringEntry(&inp, "energygrp-table", is->egptable, nullptr);
2000     printStringNoNewline(&inp, "Spacing for the PME/PPPM FFT grid");
2001     ir->fourier_spacing = get_ereal(&inp, "fourierspacing", 0.12, wi);
2002     printStringNoNewline(&inp, "FFT grid size, when a value is 0 fourierspacing will be used");
2003     ir->nkx = get_eint(&inp, "fourier-nx", 0, wi);
2004     ir->nky = get_eint(&inp, "fourier-ny", 0, wi);
2005     ir->nkz = get_eint(&inp, "fourier-nz", 0, wi);
2006     printStringNoNewline(&inp, "EWALD/PME/PPPM parameters");
2007     ir->pme_order              = get_eint(&inp, "pme-order", 4, wi);
2008     ir->ewald_rtol             = get_ereal(&inp, "ewald-rtol", 0.00001, wi);
2009     ir->ewald_rtol_lj          = get_ereal(&inp, "ewald-rtol-lj", 0.001, wi);
2010     ir->ljpme_combination_rule = get_eeenum(&inp, "lj-pme-comb-rule", eljpme_names, wi);
2011     ir->ewald_geometry         = get_eeenum(&inp, "ewald-geometry", eewg_names, wi);
2012     ir->epsilon_surface        = get_ereal(&inp, "epsilon-surface", 0.0, wi);
2013
2014     /* Implicit solvation is no longer supported, but we need grompp
2015        to be able to refuse old .mdp files that would have built a tpr
2016        to run it. Thus, only "no" is accepted. */
2017     ir->implicit_solvent = (get_eeenum(&inp, "implicit-solvent", no_names, wi) != 0);
2018
2019     /* Coupling stuff */
2020     printStringNewline(&inp, "OPTIONS FOR WEAK COUPLING ALGORITHMS");
2021     printStringNoNewline(&inp, "Temperature coupling");
2022     ir->etc                = get_eeenum(&inp, "tcoupl", etcoupl_names, wi);
2023     ir->nsttcouple         = get_eint(&inp, "nsttcouple", -1, wi);
2024     ir->opts.nhchainlength = get_eint(&inp, "nh-chain-length", 10, wi);
2025     ir->bPrintNHChains = (get_eeenum(&inp, "print-nose-hoover-chain-variables", yesno_names, wi) != 0);
2026     printStringNoNewline(&inp, "Groups to couple separately");
2027     setStringEntry(&inp, "tc-grps", is->tcgrps, nullptr);
2028     printStringNoNewline(&inp, "Time constant (ps) and reference temperature (K)");
2029     setStringEntry(&inp, "tau-t", is->tau_t, nullptr);
2030     setStringEntry(&inp, "ref-t", is->ref_t, nullptr);
2031     printStringNoNewline(&inp, "pressure coupling");
2032     ir->epc        = get_eeenum(&inp, "pcoupl", epcoupl_names, wi);
2033     ir->epct       = get_eeenum(&inp, "pcoupltype", epcoupltype_names, wi);
2034     ir->nstpcouple = get_eint(&inp, "nstpcouple", -1, wi);
2035     printStringNoNewline(&inp, "Time constant (ps), compressibility (1/bar) and reference P (bar)");
2036     ir->tau_p = get_ereal(&inp, "tau-p", 1.0, wi);
2037     setStringEntry(&inp, "compressibility", dumstr[0], nullptr);
2038     setStringEntry(&inp, "ref-p", dumstr[1], nullptr);
2039     printStringNoNewline(&inp, "Scaling of reference coordinates, No, All or COM");
2040     ir->refcoord_scaling = get_eeenum(&inp, "refcoord-scaling", erefscaling_names, wi);
2041
2042     /* QMMM */
2043     printStringNewline(&inp, "OPTIONS FOR QMMM calculations");
2044     ir->bQMMM = (get_eeenum(&inp, "QMMM", yesno_names, wi) != 0);
2045     printStringNoNewline(&inp, "Groups treated Quantum Mechanically");
2046     setStringEntry(&inp, "QMMM-grps", is->QMMM, nullptr);
2047     printStringNoNewline(&inp, "QM method");
2048     setStringEntry(&inp, "QMmethod", is->QMmethod, nullptr);
2049     printStringNoNewline(&inp, "QMMM scheme");
2050     ir->QMMMscheme = get_eeenum(&inp, "QMMMscheme", eQMMMscheme_names, wi);
2051     printStringNoNewline(&inp, "QM basisset");
2052     setStringEntry(&inp, "QMbasis", is->QMbasis, nullptr);
2053     printStringNoNewline(&inp, "QM charge");
2054     setStringEntry(&inp, "QMcharge", is->QMcharge, nullptr);
2055     printStringNoNewline(&inp, "QM multiplicity");
2056     setStringEntry(&inp, "QMmult", is->QMmult, nullptr);
2057     printStringNoNewline(&inp, "Surface Hopping");
2058     setStringEntry(&inp, "SH", is->bSH, nullptr);
2059     printStringNoNewline(&inp, "CAS space options");
2060     setStringEntry(&inp, "CASorbitals", is->CASorbitals, nullptr);
2061     setStringEntry(&inp, "CASelectrons", is->CASelectrons, nullptr);
2062     setStringEntry(&inp, "SAon", is->SAon, nullptr);
2063     setStringEntry(&inp, "SAoff", is->SAoff, nullptr);
2064     setStringEntry(&inp, "SAsteps", is->SAsteps, nullptr);
2065     printStringNoNewline(&inp, "Scale factor for MM charges");
2066     ir->scalefactor = get_ereal(&inp, "MMChargeScaleFactor", 1.0, wi);
2067
2068     /* Simulated annealing */
2069     printStringNewline(&inp, "SIMULATED ANNEALING");
2070     printStringNoNewline(&inp, "Type of annealing for each temperature group (no/single/periodic)");
2071     setStringEntry(&inp, "annealing", is->anneal, nullptr);
2072     printStringNoNewline(&inp,
2073                          "Number of time points to use for specifying annealing in each group");
2074     setStringEntry(&inp, "annealing-npoints", is->anneal_npoints, nullptr);
2075     printStringNoNewline(&inp, "List of times at the annealing points for each group");
2076     setStringEntry(&inp, "annealing-time", is->anneal_time, nullptr);
2077     printStringNoNewline(&inp, "Temp. at each annealing point, for each group.");
2078     setStringEntry(&inp, "annealing-temp", is->anneal_temp, nullptr);
2079
2080     /* Startup run */
2081     printStringNewline(&inp, "GENERATE VELOCITIES FOR STARTUP RUN");
2082     opts->bGenVel = (get_eeenum(&inp, "gen-vel", yesno_names, wi) != 0);
2083     opts->tempi   = get_ereal(&inp, "gen-temp", 300.0, wi);
2084     opts->seed    = get_eint(&inp, "gen-seed", -1, wi);
2085
2086     /* Shake stuff */
2087     printStringNewline(&inp, "OPTIONS FOR BONDS");
2088     opts->nshake = get_eeenum(&inp, "constraints", constraints, wi);
2089     printStringNoNewline(&inp, "Type of constraint algorithm");
2090     ir->eConstrAlg = get_eeenum(&inp, "constraint-algorithm", econstr_names, wi);
2091     printStringNoNewline(&inp, "Do not constrain the start configuration");
2092     ir->bContinuation = (get_eeenum(&inp, "continuation", yesno_names, wi) != 0);
2093     printStringNoNewline(&inp,
2094                          "Use successive overrelaxation to reduce the number of shake iterations");
2095     ir->bShakeSOR = (get_eeenum(&inp, "Shake-SOR", yesno_names, wi) != 0);
2096     printStringNoNewline(&inp, "Relative tolerance of shake");
2097     ir->shake_tol = get_ereal(&inp, "shake-tol", 0.0001, wi);
2098     printStringNoNewline(&inp, "Highest order in the expansion of the constraint coupling matrix");
2099     ir->nProjOrder = get_eint(&inp, "lincs-order", 4, wi);
2100     printStringNoNewline(&inp, "Number of iterations in the final step of LINCS. 1 is fine for");
2101     printStringNoNewline(&inp, "normal simulations, but use 2 to conserve energy in NVE runs.");
2102     printStringNoNewline(&inp, "For energy minimization with constraints it should be 4 to 8.");
2103     ir->nLincsIter = get_eint(&inp, "lincs-iter", 1, wi);
2104     printStringNoNewline(&inp, "Lincs will write a warning to the stderr if in one step a bond");
2105     printStringNoNewline(&inp, "rotates over more degrees than");
2106     ir->LincsWarnAngle = get_ereal(&inp, "lincs-warnangle", 30.0, wi);
2107     printStringNoNewline(&inp, "Convert harmonic bonds to morse potentials");
2108     opts->bMorse = (get_eeenum(&inp, "morse", yesno_names, wi) != 0);
2109
2110     /* Energy group exclusions */
2111     printStringNewline(&inp, "ENERGY GROUP EXCLUSIONS");
2112     printStringNoNewline(
2113             &inp, "Pairs of energy groups for which all non-bonded interactions are excluded");
2114     setStringEntry(&inp, "energygrp-excl", is->egpexcl, nullptr);
2115
2116     /* Walls */
2117     printStringNewline(&inp, "WALLS");
2118     printStringNoNewline(
2119             &inp, "Number of walls, type, atom types, densities and box-z scale factor for Ewald");
2120     ir->nwall         = get_eint(&inp, "nwall", 0, wi);
2121     ir->wall_type     = get_eeenum(&inp, "wall-type", ewt_names, wi);
2122     ir->wall_r_linpot = get_ereal(&inp, "wall-r-linpot", -1, wi);
2123     setStringEntry(&inp, "wall-atomtype", is->wall_atomtype, nullptr);
2124     setStringEntry(&inp, "wall-density", is->wall_density, nullptr);
2125     ir->wall_ewald_zfac = get_ereal(&inp, "wall-ewald-zfac", 3, wi);
2126
2127     /* COM pulling */
2128     printStringNewline(&inp, "COM PULLING");
2129     ir->bPull = (get_eeenum(&inp, "pull", yesno_names, wi) != 0);
2130     if (ir->bPull)
2131     {
2132         snew(ir->pull, 1);
2133         is->pull_grp = read_pullparams(&inp, ir->pull, wi);
2134     }
2135
2136     /* AWH biasing
2137        NOTE: needs COM pulling input */
2138     printStringNewline(&inp, "AWH biasing");
2139     ir->bDoAwh = (get_eeenum(&inp, "awh", yesno_names, wi) != 0);
2140     if (ir->bDoAwh)
2141     {
2142         if (ir->bPull)
2143         {
2144             ir->awhParams = gmx::readAndCheckAwhParams(&inp, ir, wi);
2145         }
2146         else
2147         {
2148             gmx_fatal(FARGS, "AWH biasing is only compatible with COM pulling turned on");
2149         }
2150     }
2151
2152     /* Enforced rotation */
2153     printStringNewline(&inp, "ENFORCED ROTATION");
2154     printStringNoNewline(&inp, "Enforced rotation: No or Yes");
2155     ir->bRot = (get_eeenum(&inp, "rotation", yesno_names, wi) != 0);
2156     if (ir->bRot)
2157     {
2158         snew(ir->rot, 1);
2159         is->rot_grp = read_rotparams(&inp, ir->rot, wi);
2160     }
2161
2162     /* Interactive MD */
2163     ir->bIMD = FALSE;
2164     printStringNewline(&inp, "Group to display and/or manipulate in interactive MD session");
2165     setStringEntry(&inp, "IMD-group", is->imd_grp, nullptr);
2166     if (is->imd_grp[0] != '\0')
2167     {
2168         snew(ir->imd, 1);
2169         ir->bIMD = TRUE;
2170     }
2171
2172     /* Refinement */
2173     printStringNewline(&inp, "NMR refinement stuff");
2174     printStringNoNewline(&inp, "Distance restraints type: No, Simple or Ensemble");
2175     ir->eDisre = get_eeenum(&inp, "disre", edisre_names, wi);
2176     printStringNoNewline(
2177             &inp, "Force weighting of pairs in one distance restraint: Conservative or Equal");
2178     ir->eDisreWeighting = get_eeenum(&inp, "disre-weighting", edisreweighting_names, wi);
2179     printStringNoNewline(&inp, "Use sqrt of the time averaged times the instantaneous violation");
2180     ir->bDisreMixed = (get_eeenum(&inp, "disre-mixed", yesno_names, wi) != 0);
2181     ir->dr_fc       = get_ereal(&inp, "disre-fc", 1000.0, wi);
2182     ir->dr_tau      = get_ereal(&inp, "disre-tau", 0.0, wi);
2183     printStringNoNewline(&inp, "Output frequency for pair distances to energy file");
2184     ir->nstdisreout = get_eint(&inp, "nstdisreout", 100, wi);
2185     printStringNoNewline(&inp, "Orientation restraints: No or Yes");
2186     opts->bOrire = (get_eeenum(&inp, "orire", yesno_names, wi) != 0);
2187     printStringNoNewline(&inp, "Orientation restraints force constant and tau for time averaging");
2188     ir->orires_fc  = get_ereal(&inp, "orire-fc", 0.0, wi);
2189     ir->orires_tau = get_ereal(&inp, "orire-tau", 0.0, wi);
2190     setStringEntry(&inp, "orire-fitgrp", is->orirefitgrp, nullptr);
2191     printStringNoNewline(&inp, "Output frequency for trace(SD) and S to energy file");
2192     ir->nstorireout = get_eint(&inp, "nstorireout", 100, wi);
2193
2194     /* free energy variables */
2195     printStringNewline(&inp, "Free energy variables");
2196     ir->efep = get_eeenum(&inp, "free-energy", efep_names, wi);
2197     setStringEntry(&inp, "couple-moltype", is->couple_moltype, nullptr);
2198     opts->couple_lam0  = get_eeenum(&inp, "couple-lambda0", couple_lam, wi);
2199     opts->couple_lam1  = get_eeenum(&inp, "couple-lambda1", couple_lam, wi);
2200     opts->bCoupleIntra = (get_eeenum(&inp, "couple-intramol", yesno_names, wi) != 0);
2201
2202     fep->init_lambda = get_ereal(&inp, "init-lambda", -1, wi); /* start with -1 so
2203                                                                          we can recognize if
2204                                                                          it was not entered */
2205     fep->init_fep_state = get_eint(&inp, "init-lambda-state", -1, wi);
2206     fep->delta_lambda   = get_ereal(&inp, "delta-lambda", 0.0, wi);
2207     fep->nstdhdl        = get_eint(&inp, "nstdhdl", 50, wi);
2208     setStringEntry(&inp, "fep-lambdas", is->fep_lambda[efptFEP], nullptr);
2209     setStringEntry(&inp, "mass-lambdas", is->fep_lambda[efptMASS], nullptr);
2210     setStringEntry(&inp, "coul-lambdas", is->fep_lambda[efptCOUL], nullptr);
2211     setStringEntry(&inp, "vdw-lambdas", is->fep_lambda[efptVDW], nullptr);
2212     setStringEntry(&inp, "bonded-lambdas", is->fep_lambda[efptBONDED], nullptr);
2213     setStringEntry(&inp, "restraint-lambdas", is->fep_lambda[efptRESTRAINT], nullptr);
2214     setStringEntry(&inp, "temperature-lambdas", is->fep_lambda[efptTEMPERATURE], nullptr);
2215     fep->lambda_neighbors = get_eint(&inp, "calc-lambda-neighbors", 1, wi);
2216     setStringEntry(&inp, "init-lambda-weights", is->lambda_weights, nullptr);
2217     fep->edHdLPrintEnergy   = get_eeenum(&inp, "dhdl-print-energy", edHdLPrintEnergy_names, wi);
2218     fep->sc_alpha           = get_ereal(&inp, "sc-alpha", 0.0, wi);
2219     fep->sc_power           = get_eint(&inp, "sc-power", 1, wi);
2220     fep->sc_r_power         = get_ereal(&inp, "sc-r-power", 6.0, wi);
2221     fep->sc_sigma           = get_ereal(&inp, "sc-sigma", 0.3, wi);
2222     fep->bScCoul            = (get_eeenum(&inp, "sc-coul", yesno_names, wi) != 0);
2223     fep->dh_hist_size       = get_eint(&inp, "dh_hist_size", 0, wi);
2224     fep->dh_hist_spacing    = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
2225     fep->separate_dhdl_file = get_eeenum(&inp, "separate-dhdl-file", separate_dhdl_file_names, wi);
2226     fep->dhdl_derivatives   = get_eeenum(&inp, "dhdl-derivatives", dhdl_derivatives_names, wi);
2227     fep->dh_hist_size       = get_eint(&inp, "dh_hist_size", 0, wi);
2228     fep->dh_hist_spacing    = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
2229
2230     /* Non-equilibrium MD stuff */
2231     printStringNewline(&inp, "Non-equilibrium MD stuff");
2232     setStringEntry(&inp, "acc-grps", is->accgrps, nullptr);
2233     setStringEntry(&inp, "accelerate", is->acc, nullptr);
2234     setStringEntry(&inp, "freezegrps", is->freeze, nullptr);
2235     setStringEntry(&inp, "freezedim", is->frdim, nullptr);
2236     ir->cos_accel = get_ereal(&inp, "cos-acceleration", 0, wi);
2237     setStringEntry(&inp, "deform", is->deform, nullptr);
2238
2239     /* simulated tempering variables */
2240     printStringNewline(&inp, "simulated tempering variables");
2241     ir->bSimTemp = (get_eeenum(&inp, "simulated-tempering", yesno_names, wi) != 0);
2242     ir->simtempvals->eSimTempScale = get_eeenum(&inp, "simulated-tempering-scaling", esimtemp_names, wi);
2243     ir->simtempvals->simtemp_low  = get_ereal(&inp, "sim-temp-low", 300.0, wi);
2244     ir->simtempvals->simtemp_high = get_ereal(&inp, "sim-temp-high", 300.0, wi);
2245
2246     /* expanded ensemble variables */
2247     if (ir->efep == efepEXPANDED || ir->bSimTemp)
2248     {
2249         read_expandedparams(&inp, expand, wi);
2250     }
2251
2252     /* Electric fields */
2253     {
2254         gmx::KeyValueTreeObject      convertedValues = flatKeyValueTreeFromInpFile(inp);
2255         gmx::KeyValueTreeTransformer transform;
2256         transform.rules()->addRule().keyMatchType("/", gmx::StringCompareType::CaseAndDashInsensitive);
2257         mdModules->initMdpTransform(transform.rules());
2258         for (const auto& path : transform.mappedPaths())
2259         {
2260             GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
2261             mark_einp_set(inp, path[0].c_str());
2262         }
2263         MdpErrorHandler errorHandler(wi);
2264         auto            result = transform.transform(convertedValues, &errorHandler);
2265         ir->params             = new gmx::KeyValueTreeObject(result.object());
2266         mdModules->adjustInputrecBasedOnModules(ir);
2267         errorHandler.setBackMapping(result.backMapping());
2268         mdModules->assignOptionsToModules(*ir->params, &errorHandler);
2269     }
2270
2271     /* Ion/water position swapping ("computational electrophysiology") */
2272     printStringNewline(&inp,
2273                        "Ion/water position swapping for computational electrophysiology setups");
2274     printStringNoNewline(&inp, "Swap positions along direction: no, X, Y, Z");
2275     ir->eSwapCoords = get_eeenum(&inp, "swapcoords", eSwapTypes_names, wi);
2276     if (ir->eSwapCoords != eswapNO)
2277     {
2278         char buf[STRLEN];
2279         int  nIonTypes;
2280
2281
2282         snew(ir->swap, 1);
2283         printStringNoNewline(&inp, "Swap attempt frequency");
2284         ir->swap->nstswap = get_eint(&inp, "swap-frequency", 1, wi);
2285         printStringNoNewline(&inp, "Number of ion types to be controlled");
2286         nIonTypes = get_eint(&inp, "iontypes", 1, wi);
2287         if (nIonTypes < 1)
2288         {
2289             warning_error(wi, "You need to provide at least one ion type for position exchanges.");
2290         }
2291         ir->swap->ngrp = nIonTypes + eSwapFixedGrpNR;
2292         snew(ir->swap->grp, ir->swap->ngrp);
2293         for (i = 0; i < ir->swap->ngrp; i++)
2294         {
2295             snew(ir->swap->grp[i].molname, STRLEN);
2296         }
2297         printStringNoNewline(&inp,
2298                              "Two index groups that contain the compartment-partitioning atoms");
2299         setStringEntry(&inp, "split-group0", ir->swap->grp[eGrpSplit0].molname, nullptr);
2300         setStringEntry(&inp, "split-group1", ir->swap->grp[eGrpSplit1].molname, nullptr);
2301         printStringNoNewline(&inp,
2302                              "Use center of mass of split groups (yes/no), otherwise center of "
2303                              "geometry is used");
2304         ir->swap->massw_split[0] = (get_eeenum(&inp, "massw-split0", yesno_names, wi) != 0);
2305         ir->swap->massw_split[1] = (get_eeenum(&inp, "massw-split1", yesno_names, wi) != 0);
2306
2307         printStringNoNewline(&inp, "Name of solvent molecules");
2308         setStringEntry(&inp, "solvent-group", ir->swap->grp[eGrpSolvent].molname, nullptr);
2309
2310         printStringNoNewline(&inp,
2311                              "Split cylinder: radius, upper and lower extension (nm) (this will "
2312                              "define the channels)");
2313         printStringNoNewline(&inp,
2314                              "Note that the split cylinder settings do not have an influence on "
2315                              "the swapping protocol,");
2316         printStringNoNewline(
2317                 &inp,
2318                 "however, if correctly defined, the permeation events are recorded per channel");
2319         ir->swap->cyl0r = get_ereal(&inp, "cyl0-r", 2.0, wi);
2320         ir->swap->cyl0u = get_ereal(&inp, "cyl0-up", 1.0, wi);
2321         ir->swap->cyl0l = get_ereal(&inp, "cyl0-down", 1.0, wi);
2322         ir->swap->cyl1r = get_ereal(&inp, "cyl1-r", 2.0, wi);
2323         ir->swap->cyl1u = get_ereal(&inp, "cyl1-up", 1.0, wi);
2324         ir->swap->cyl1l = get_ereal(&inp, "cyl1-down", 1.0, wi);
2325
2326         printStringNoNewline(
2327                 &inp,
2328                 "Average the number of ions per compartment over these many swap attempt steps");
2329         ir->swap->nAverage = get_eint(&inp, "coupl-steps", 10, wi);
2330
2331         printStringNoNewline(
2332                 &inp, "Names of the ion types that can be exchanged with solvent molecules,");
2333         printStringNoNewline(
2334                 &inp, "and the requested number of ions of this type in compartments A and B");
2335         printStringNoNewline(&inp, "-1 means fix the numbers as found in step 0");
2336         for (i = 0; i < nIonTypes; i++)
2337         {
2338             int ig = eSwapFixedGrpNR + i;
2339
2340             sprintf(buf, "iontype%d-name", i);
2341             setStringEntry(&inp, buf, ir->swap->grp[ig].molname, nullptr);
2342             sprintf(buf, "iontype%d-in-A", i);
2343             ir->swap->grp[ig].nmolReq[0] = get_eint(&inp, buf, -1, wi);
2344             sprintf(buf, "iontype%d-in-B", i);
2345             ir->swap->grp[ig].nmolReq[1] = get_eint(&inp, buf, -1, wi);
2346         }
2347
2348         printStringNoNewline(
2349                 &inp,
2350                 "By default (i.e. bulk offset = 0.0), ion/water exchanges happen between layers");
2351         printStringNoNewline(
2352                 &inp,
2353                 "at maximum distance (= bulk concentration) to the split group layers. However,");
2354         printStringNoNewline(&inp,
2355                              "an offset b (-1.0 < b < +1.0) can be specified to offset the bulk "
2356                              "layer from the middle at 0.0");
2357         printStringNoNewline(&inp,
2358                              "towards one of the compartment-partitioning layers (at +/- 1.0).");
2359         ir->swap->bulkOffset[0] = get_ereal(&inp, "bulk-offsetA", 0.0, wi);
2360         ir->swap->bulkOffset[1] = get_ereal(&inp, "bulk-offsetB", 0.0, wi);
2361         if (!(ir->swap->bulkOffset[0] > -1.0 && ir->swap->bulkOffset[0] < 1.0)
2362             || !(ir->swap->bulkOffset[1] > -1.0 && ir->swap->bulkOffset[1] < 1.0))
2363         {
2364             warning_error(wi, "Bulk layer offsets must be > -1.0 and < 1.0 !");
2365         }
2366
2367         printStringNoNewline(
2368                 &inp, "Start to swap ions if threshold difference to requested count is reached");
2369         ir->swap->threshold = get_ereal(&inp, "threshold", 1.0, wi);
2370     }
2371
2372     /* AdResS is no longer supported, but we need grompp to be able to
2373        refuse to process old .mdp files that used it. */
2374     ir->bAdress = (get_eeenum(&inp, "adress", no_names, wi) != 0);
2375
2376     /* User defined thingies */
2377     printStringNewline(&inp, "User defined thingies");
2378     setStringEntry(&inp, "user1-grps", is->user1, nullptr);
2379     setStringEntry(&inp, "user2-grps", is->user2, nullptr);
2380     ir->userint1  = get_eint(&inp, "userint1", 0, wi);
2381     ir->userint2  = get_eint(&inp, "userint2", 0, wi);
2382     ir->userint3  = get_eint(&inp, "userint3", 0, wi);
2383     ir->userint4  = get_eint(&inp, "userint4", 0, wi);
2384     ir->userreal1 = get_ereal(&inp, "userreal1", 0, wi);
2385     ir->userreal2 = get_ereal(&inp, "userreal2", 0, wi);
2386     ir->userreal3 = get_ereal(&inp, "userreal3", 0, wi);
2387     ir->userreal4 = get_ereal(&inp, "userreal4", 0, wi);
2388 #undef CTYPE
2389
2390     {
2391         gmx::TextOutputFile stream(mdparout);
2392         write_inpfile(&stream, mdparout, &inp, FALSE, writeMdpHeader, wi);
2393
2394         // Transform module data into a flat key-value tree for output.
2395         gmx::KeyValueTreeBuilder       builder;
2396         gmx::KeyValueTreeObjectBuilder builderObject = builder.rootObject();
2397         mdModules->buildMdpOutput(&builderObject);
2398         {
2399             gmx::TextWriter writer(&stream);
2400             writeKeyValueTreeAsMdp(&writer, builder.build());
2401         }
2402         stream.close();
2403     }
2404
2405     /* Process options if necessary */
2406     for (m = 0; m < 2; m++)
2407     {
2408         for (i = 0; i < 2 * DIM; i++)
2409         {
2410             dumdub[m][i] = 0.0;
2411         }
2412         if (ir->epc)
2413         {
2414             switch (ir->epct)
2415             {
2416                 case epctISOTROPIC:
2417                     if (sscanf(dumstr[m], "%lf", &(dumdub[m][XX])) != 1)
2418                     {
2419                         warning_error(
2420                                 wi,
2421                                 "Pressure coupling incorrect number of values (I need exactly 1)");
2422                     }
2423                     dumdub[m][YY] = dumdub[m][ZZ] = dumdub[m][XX];
2424                     break;
2425                 case epctSEMIISOTROPIC:
2426                 case epctSURFACETENSION:
2427                     if (sscanf(dumstr[m], "%lf%lf", &(dumdub[m][XX]), &(dumdub[m][ZZ])) != 2)
2428                     {
2429                         warning_error(
2430                                 wi,
2431                                 "Pressure coupling incorrect number of values (I need exactly 2)");
2432                     }
2433                     dumdub[m][YY] = dumdub[m][XX];
2434                     break;
2435                 case epctANISOTROPIC:
2436                     if (sscanf(dumstr[m], "%lf%lf%lf%lf%lf%lf", &(dumdub[m][XX]), &(dumdub[m][YY]),
2437                                &(dumdub[m][ZZ]), &(dumdub[m][3]), &(dumdub[m][4]), &(dumdub[m][5]))
2438                         != 6)
2439                     {
2440                         warning_error(
2441                                 wi,
2442                                 "Pressure coupling incorrect number of values (I need exactly 6)");
2443                     }
2444                     break;
2445                 default:
2446                     gmx_fatal(FARGS, "Pressure coupling type %s not implemented yet",
2447                               epcoupltype_names[ir->epct]);
2448             }
2449         }
2450     }
2451     clear_mat(ir->ref_p);
2452     clear_mat(ir->compress);
2453     for (i = 0; i < DIM; i++)
2454     {
2455         ir->ref_p[i][i]    = dumdub[1][i];
2456         ir->compress[i][i] = dumdub[0][i];
2457     }
2458     if (ir->epct == epctANISOTROPIC)
2459     {
2460         ir->ref_p[XX][YY] = dumdub[1][3];
2461         ir->ref_p[XX][ZZ] = dumdub[1][4];
2462         ir->ref_p[YY][ZZ] = dumdub[1][5];
2463         if (ir->ref_p[XX][YY] != 0 && ir->ref_p[XX][ZZ] != 0 && ir->ref_p[YY][ZZ] != 0)
2464         {
2465             warning(wi,
2466                     "All off-diagonal reference pressures are non-zero. Are you sure you want to "
2467                     "apply a threefold shear stress?\n");
2468         }
2469         ir->compress[XX][YY] = dumdub[0][3];
2470         ir->compress[XX][ZZ] = dumdub[0][4];
2471         ir->compress[YY][ZZ] = dumdub[0][5];
2472         for (i = 0; i < DIM; i++)
2473         {
2474             for (m = 0; m < i; m++)
2475             {
2476                 ir->ref_p[i][m]    = ir->ref_p[m][i];
2477                 ir->compress[i][m] = ir->compress[m][i];
2478             }
2479         }
2480     }
2481
2482     if (ir->comm_mode == ecmNO)
2483     {
2484         ir->nstcomm = 0;
2485     }
2486
2487     opts->couple_moltype = nullptr;
2488     if (strlen(is->couple_moltype) > 0)
2489     {
2490         if (ir->efep != efepNO)
2491         {
2492             opts->couple_moltype = gmx_strdup(is->couple_moltype);
2493             if (opts->couple_lam0 == opts->couple_lam1)
2494             {
2495                 warning(wi, "The lambda=0 and lambda=1 states for coupling are identical");
2496             }
2497             if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE || opts->couple_lam1 == ecouplamNONE))
2498             {
2499                 warning_note(
2500                         wi,
2501                         "For proper sampling of the (nearly) decoupled state, stochastic dynamics "
2502                         "should be used");
2503             }
2504         }
2505         else
2506         {
2507             warning_note(wi,
2508                          "Free energy is turned off, so we will not decouple the molecule listed "
2509                          "in your input.");
2510         }
2511     }
2512     /* FREE ENERGY AND EXPANDED ENSEMBLE OPTIONS */
2513     if (ir->efep != efepNO)
2514     {
2515         if (fep->delta_lambda > 0)
2516         {
2517             ir->efep = efepSLOWGROWTH;
2518         }
2519     }
2520
2521     if (fep->edHdLPrintEnergy == edHdLPrintEnergyYES)
2522     {
2523         fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
2524         warning_note(wi,
2525                      "Old option for dhdl-print-energy given: "
2526                      "changing \"yes\" to \"total\"\n");
2527     }
2528
2529     if (ir->bSimTemp && (fep->edHdLPrintEnergy == edHdLPrintEnergyNO))
2530     {
2531         /* always print out the energy to dhdl if we are doing
2532            expanded ensemble, since we need the total energy for
2533            analysis if the temperature is changing. In some
2534            conditions one may only want the potential energy, so
2535            we will allow that if the appropriate mdp setting has
2536            been enabled. Otherwise, total it is:
2537          */
2538         fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
2539     }
2540
2541     if ((ir->efep != efepNO) || ir->bSimTemp)
2542     {
2543         ir->bExpanded = FALSE;
2544         if ((ir->efep == efepEXPANDED) || ir->bSimTemp)
2545         {
2546             ir->bExpanded = TRUE;
2547         }
2548         do_fep_params(ir, is->fep_lambda, is->lambda_weights, wi);
2549         if (ir->bSimTemp) /* done after fep params */
2550         {
2551             do_simtemp_params(ir);
2552         }
2553
2554         /* Because sc-coul (=FALSE by default) only acts on the lambda state
2555          * setup and not on the old way of specifying the free-energy setup,
2556          * we should check for using soft-core when not needed, since that
2557          * can complicate the sampling significantly.
2558          * Note that we only check for the automated coupling setup.
2559          * If the (advanced) user does FEP through manual topology changes,
2560          * this check will not be triggered.
2561          */
2562         if (ir->efep != efepNO && ir->fepvals->n_lambda == 0 && ir->fepvals->sc_alpha != 0
2563             && (couple_lambda_has_vdw_on(opts->couple_lam0) && couple_lambda_has_vdw_on(opts->couple_lam1)))
2564         {
2565             warning(wi,
2566                     "You are using soft-core interactions while the Van der Waals interactions are "
2567                     "not decoupled (note that the sc-coul option is only active when using lambda "
2568                     "states). Although this will not lead to errors, you will need much more "
2569                     "sampling than without soft-core interactions. Consider using sc-alpha=0.");
2570         }
2571     }
2572     else
2573     {
2574         ir->fepvals->n_lambda = 0;
2575     }
2576
2577     /* WALL PARAMETERS */
2578
2579     do_wall_params(ir, is->wall_atomtype, is->wall_density, opts, wi);
2580
2581     /* ORIENTATION RESTRAINT PARAMETERS */
2582
2583     if (opts->bOrire && gmx::splitString(is->orirefitgrp).size() != 1)
2584     {
2585         warning_error(wi, "ERROR: Need one orientation restraint fit group\n");
2586     }
2587
2588     /* DEFORMATION PARAMETERS */
2589
2590     clear_mat(ir->deform);
2591     for (i = 0; i < 6; i++)
2592     {
2593         dumdub[0][i] = 0;
2594     }
2595
2596     double gmx_unused canary;
2597     int ndeform = sscanf(is->deform, "%lf %lf %lf %lf %lf %lf %lf", &(dumdub[0][0]), &(dumdub[0][1]),
2598                          &(dumdub[0][2]), &(dumdub[0][3]), &(dumdub[0][4]), &(dumdub[0][5]), &canary);
2599
2600     if (strlen(is->deform) > 0 && ndeform != 6)
2601     {
2602         warning_error(
2603                 wi, gmx::formatString(
2604                             "Cannot parse exactly 6 box deformation velocities from string '%s'", is->deform)
2605                             .c_str());
2606     }
2607     for (i = 0; i < 3; i++)
2608     {
2609         ir->deform[i][i] = dumdub[0][i];
2610     }
2611     ir->deform[YY][XX] = dumdub[0][3];
2612     ir->deform[ZZ][XX] = dumdub[0][4];
2613     ir->deform[ZZ][YY] = dumdub[0][5];
2614     if (ir->epc != epcNO)
2615     {
2616         for (i = 0; i < 3; i++)
2617         {
2618             for (j = 0; j <= i; j++)
2619             {
2620                 if (ir->deform[i][j] != 0 && ir->compress[i][j] != 0)
2621                 {
2622                     warning_error(wi, "A box element has deform set and compressibility > 0");
2623                 }
2624             }
2625         }
2626         for (i = 0; i < 3; i++)
2627         {
2628             for (j = 0; j < i; j++)
2629             {
2630                 if (ir->deform[i][j] != 0)
2631                 {
2632                     for (m = j; m < DIM; m++)
2633                     {
2634                         if (ir->compress[m][j] != 0)
2635                         {
2636                             sprintf(warn_buf,
2637                                     "An off-diagonal box element has deform set while "
2638                                     "compressibility > 0 for the same component of another box "
2639                                     "vector, this might lead to spurious periodicity effects.");
2640                             warning(wi, warn_buf);
2641                         }
2642                     }
2643                 }
2644             }
2645         }
2646     }
2647
2648     /* Ion/water position swapping checks */
2649     if (ir->eSwapCoords != eswapNO)
2650     {
2651         if (ir->swap->nstswap < 1)
2652         {
2653             warning_error(wi, "swap_frequency must be 1 or larger when ion swapping is requested");
2654         }
2655         if (ir->swap->nAverage < 1)
2656         {
2657             warning_error(wi, "coupl_steps must be 1 or larger.\n");
2658         }
2659         if (ir->swap->threshold < 1.0)
2660         {
2661             warning_error(wi, "Ion count threshold must be at least 1.\n");
2662         }
2663     }
2664
2665     sfree(dumstr[0]);
2666     sfree(dumstr[1]);
2667 }
2668
2669 static int search_QMstring(const char* s, int ng, const char* gn[])
2670 {
2671     /* same as normal search_string, but this one searches QM strings */
2672     int i;
2673
2674     for (i = 0; (i < ng); i++)
2675     {
2676         if (gmx_strcasecmp(s, gn[i]) == 0)
2677         {
2678             return i;
2679         }
2680     }
2681
2682     gmx_fatal(FARGS, "this QM method or basisset (%s) is not implemented\n!", s);
2683 } /* search_QMstring */
2684
2685 /* We would like gn to be const as well, but C doesn't allow this */
2686 /* TODO this is utility functionality (search for the index of a
2687    string in a collection), so should be refactored and located more
2688    centrally. */
2689 int search_string(const char* s, int ng, char* gn[])
2690 {
2691     int i;
2692
2693     for (i = 0; (i < ng); i++)
2694     {
2695         if (gmx_strcasecmp(s, gn[i]) == 0)
2696         {
2697             return i;
2698         }
2699     }
2700
2701     gmx_fatal(FARGS,
2702               "Group %s referenced in the .mdp file was not found in the index file.\n"
2703               "Group names must match either [moleculetype] names or custom index group\n"
2704               "names, in which case you must supply an index file to the '-n' option\n"
2705               "of grompp.",
2706               s);
2707 }
2708
2709 static void do_numbering(int                        natoms,
2710                          SimulationGroups*          groups,
2711                          gmx::ArrayRef<std::string> groupsFromMdpFile,
2712                          t_blocka*                  block,
2713                          char*                      gnames[],
2714                          SimulationAtomGroupType    gtype,
2715                          int                        restnm,
2716                          int                        grptp,
2717                          bool                       bVerbose,
2718                          warninp_t                  wi)
2719 {
2720     unsigned short*   cbuf;
2721     AtomGroupIndices* grps = &(groups->groups[gtype]);
2722     int               j, gid, aj, ognr, ntot = 0;
2723     const char*       title;
2724     char              warn_buf[STRLEN];
2725
2726     title = shortName(gtype);
2727
2728     snew(cbuf, natoms);
2729     /* Mark all id's as not set */
2730     for (int i = 0; (i < natoms); i++)
2731     {
2732         cbuf[i] = NOGID;
2733     }
2734
2735     for (int i = 0; i != groupsFromMdpFile.ssize(); ++i)
2736     {
2737         /* Lookup the group name in the block structure */
2738         gid = search_string(groupsFromMdpFile[i].c_str(), block->nr, gnames);
2739         if ((grptp != egrptpONE) || (i == 0))
2740         {
2741             grps->emplace_back(gid);
2742         }
2743
2744         /* Now go over the atoms in the group */
2745         for (j = block->index[gid]; (j < block->index[gid + 1]); j++)
2746         {
2747
2748             aj = block->a[j];
2749
2750             /* Range checking */
2751             if ((aj < 0) || (aj >= natoms))
2752             {
2753                 gmx_fatal(FARGS, "Invalid atom number %d in indexfile", aj + 1);
2754             }
2755             /* Lookup up the old group number */
2756             ognr = cbuf[aj];
2757             if (ognr != NOGID)
2758             {
2759                 gmx_fatal(FARGS, "Atom %d in multiple %s groups (%d and %d)", aj + 1, title,
2760                           ognr + 1, i + 1);
2761             }
2762             else
2763             {
2764                 /* Store the group number in buffer */
2765                 if (grptp == egrptpONE)
2766                 {
2767                     cbuf[aj] = 0;
2768                 }
2769                 else
2770                 {
2771                     cbuf[aj] = i;
2772                 }
2773                 ntot++;
2774             }
2775         }
2776     }
2777
2778     /* Now check whether we have done all atoms */
2779     if (ntot != natoms)
2780     {
2781         if (grptp == egrptpALL)
2782         {
2783             gmx_fatal(FARGS, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
2784         }
2785         else if (grptp == egrptpPART)
2786         {
2787             sprintf(warn_buf, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
2788             warning_note(wi, warn_buf);
2789         }
2790         /* Assign all atoms currently unassigned to a rest group */
2791         for (j = 0; (j < natoms); j++)
2792         {
2793             if (cbuf[j] == NOGID)
2794             {
2795                 cbuf[j] = grps->size();
2796             }
2797         }
2798         if (grptp != egrptpPART)
2799         {
2800             if (bVerbose)
2801             {
2802                 fprintf(stderr, "Making dummy/rest group for %s containing %d elements\n", title,
2803                         natoms - ntot);
2804             }
2805             /* Add group name "rest" */
2806             grps->emplace_back(restnm);
2807
2808             /* Assign the rest name to all atoms not currently assigned to a group */
2809             for (j = 0; (j < natoms); j++)
2810             {
2811                 if (cbuf[j] == NOGID)
2812                 {
2813                     // group size was not updated before this here, so need to use -1.
2814                     cbuf[j] = grps->size() - 1;
2815                 }
2816             }
2817         }
2818     }
2819
2820     if (grps->size() == 1 && (ntot == 0 || ntot == natoms))
2821     {
2822         /* All atoms are part of one (or no) group, no index required */
2823         groups->groupNumbers[gtype].clear();
2824     }
2825     else
2826     {
2827         for (int j = 0; (j < natoms); j++)
2828         {
2829             groups->groupNumbers[gtype].emplace_back(cbuf[j]);
2830         }
2831     }
2832
2833     sfree(cbuf);
2834 }
2835
2836 static void calc_nrdf(const gmx_mtop_t* mtop, t_inputrec* ir, char** gnames)
2837 {
2838     t_grpopts*     opts;
2839     pull_params_t* pull;
2840     int            natoms, imin, jmin;
2841     int *          nrdf2, *na_vcm, na_tot;
2842     double *       nrdf_tc, *nrdf_vcm, nrdf_uc, *nrdf_vcm_sub;
2843     ivec*          dof_vcm;
2844     int            as;
2845
2846     /* Calculate nrdf.
2847      * First calc 3xnr-atoms for each group
2848      * then subtract half a degree of freedom for each constraint
2849      *
2850      * Only atoms and nuclei contribute to the degrees of freedom...
2851      */
2852
2853     opts = &ir->opts;
2854
2855     const SimulationGroups& groups = mtop->groups;
2856     natoms                         = mtop->natoms;
2857
2858     /* Allocate one more for a possible rest group */
2859     /* We need to sum degrees of freedom into doubles,
2860      * since floats give too low nrdf's above 3 million atoms.
2861      */
2862     snew(nrdf_tc, groups.groups[SimulationAtomGroupType::TemperatureCoupling].size() + 1);
2863     snew(nrdf_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2864     snew(dof_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2865     snew(na_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2866     snew(nrdf_vcm_sub, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2867
2868     for (gmx::index i = 0; i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
2869     {
2870         nrdf_tc[i] = 0;
2871     }
2872     for (gmx::index i = 0;
2873          i < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; i++)
2874     {
2875         nrdf_vcm[i] = 0;
2876         clear_ivec(dof_vcm[i]);
2877         na_vcm[i]       = 0;
2878         nrdf_vcm_sub[i] = 0;
2879     }
2880     snew(nrdf2, natoms);
2881     for (const AtomProxy atomP : AtomRange(*mtop))
2882     {
2883         const t_atom& local = atomP.atom();
2884         int           i     = atomP.globalAtomNumber();
2885         nrdf2[i]            = 0;
2886         if (local.ptype == eptAtom || local.ptype == eptNucleus)
2887         {
2888             int g = getGroupType(groups, SimulationAtomGroupType::Freeze, i);
2889             for (int d = 0; d < DIM; d++)
2890             {
2891                 if (opts->nFreeze[g][d] == 0)
2892                 {
2893                     /* Add one DOF for particle i (counted as 2*1) */
2894                     nrdf2[i] += 2;
2895                     /* VCM group i has dim d as a DOF */
2896                     dof_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)][d] =
2897                             1;
2898                 }
2899             }
2900             nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, i)] +=
2901                     0.5 * nrdf2[i];
2902             nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)] +=
2903                     0.5 * nrdf2[i];
2904         }
2905     }
2906
2907     as = 0;
2908     for (const gmx_molblock_t& molb : mtop->molblock)
2909     {
2910         const gmx_moltype_t& molt = mtop->moltype[molb.type];
2911         const t_atom*        atom = molt.atoms.atom;
2912         for (int mol = 0; mol < molb.nmol; mol++)
2913         {
2914             for (int ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
2915             {
2916                 gmx::ArrayRef<const int> ia = molt.ilist[ftype].iatoms;
2917                 for (int i = 0; i < molt.ilist[ftype].size();)
2918                 {
2919                     /* Subtract degrees of freedom for the constraints,
2920                      * if the particles still have degrees of freedom left.
2921                      * If one of the particles is a vsite or a shell, then all
2922                      * constraint motion will go there, but since they do not
2923                      * contribute to the constraints the degrees of freedom do not
2924                      * change.
2925                      */
2926                     int ai = as + ia[i + 1];
2927                     int aj = as + ia[i + 2];
2928                     if (((atom[ia[i + 1]].ptype == eptNucleus) || (atom[ia[i + 1]].ptype == eptAtom))
2929                         && ((atom[ia[i + 2]].ptype == eptNucleus) || (atom[ia[i + 2]].ptype == eptAtom)))
2930                     {
2931                         if (nrdf2[ai] > 0)
2932                         {
2933                             jmin = 1;
2934                         }
2935                         else
2936                         {
2937                             jmin = 2;
2938                         }
2939                         if (nrdf2[aj] > 0)
2940                         {
2941                             imin = 1;
2942                         }
2943                         else
2944                         {
2945                             imin = 2;
2946                         }
2947                         imin = std::min(imin, nrdf2[ai]);
2948                         jmin = std::min(jmin, nrdf2[aj]);
2949                         nrdf2[ai] -= imin;
2950                         nrdf2[aj] -= jmin;
2951                         nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
2952                                 0.5 * imin;
2953                         nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, aj)] -=
2954                                 0.5 * jmin;
2955                         nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
2956                                 0.5 * imin;
2957                         nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, aj)] -=
2958                                 0.5 * jmin;
2959                     }
2960                     i += interaction_function[ftype].nratoms + 1;
2961                 }
2962             }
2963             gmx::ArrayRef<const int> ia = molt.ilist[F_SETTLE].iatoms;
2964             for (int i = 0; i < molt.ilist[F_SETTLE].size();)
2965             {
2966                 /* Subtract 1 dof from every atom in the SETTLE */
2967                 for (int j = 0; j < 3; j++)
2968                 {
2969                     int ai = as + ia[i + 1 + j];
2970                     imin   = std::min(2, nrdf2[ai]);
2971                     nrdf2[ai] -= imin;
2972                     nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
2973                             0.5 * imin;
2974                     nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
2975                             0.5 * imin;
2976                 }
2977                 i += 4;
2978             }
2979             as += molt.atoms.nr;
2980         }
2981     }
2982
2983     if (ir->bPull)
2984     {
2985         /* Correct nrdf for the COM constraints.
2986          * We correct using the TC and VCM group of the first atom
2987          * in the reference and pull group. If atoms in one pull group
2988          * belong to different TC or VCM groups it is anyhow difficult
2989          * to determine the optimal nrdf assignment.
2990          */
2991         pull = ir->pull;
2992
2993         for (int i = 0; i < pull->ncoord; i++)
2994         {
2995             if (pull->coord[i].eType != epullCONSTRAINT)
2996             {
2997                 continue;
2998             }
2999
3000             imin = 1;
3001
3002             for (int j = 0; j < 2; j++)
3003             {
3004                 const t_pull_group* pgrp;
3005
3006                 pgrp = &pull->group[pull->coord[i].group[j]];
3007
3008                 if (pgrp->nat > 0)
3009                 {
3010                     /* Subtract 1/2 dof from each group */
3011                     int ai = pgrp->ind[0];
3012                     nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
3013                             0.5 * imin;
3014                     nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
3015                             0.5 * imin;
3016                     if (nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] < 0)
3017                     {
3018                         gmx_fatal(FARGS,
3019                                   "Center of mass pulling constraints caused the number of degrees "
3020                                   "of freedom for temperature coupling group %s to be negative",
3021                                   gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][getGroupType(
3022                                           groups, SimulationAtomGroupType::TemperatureCoupling, ai)]]);
3023                     }
3024                 }
3025                 else
3026                 {
3027                     /* We need to subtract the whole DOF from group j=1 */
3028                     imin += 1;
3029                 }
3030             }
3031         }
3032     }
3033
3034     if (ir->nstcomm != 0)
3035     {
3036         GMX_RELEASE_ASSERT(!groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].empty(),
3037                            "Expect at least one group when removing COM motion");
3038
3039         /* We remove COM motion up to dim ndof_com() */
3040         const int ndim_rm_vcm = ndof_com(ir);
3041
3042         /* Subtract ndim_rm_vcm (or less with frozen dimensions) from
3043          * the number of degrees of freedom in each vcm group when COM
3044          * translation is removed and 6 when rotation is removed as well.
3045          * Note that we do not and should not include the rest group here.
3046          */
3047         for (gmx::index j = 0;
3048              j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]); j++)
3049         {
3050             switch (ir->comm_mode)
3051             {
3052                 case ecmLINEAR:
3053                 case ecmLINEAR_ACCELERATION_CORRECTION:
3054                     nrdf_vcm_sub[j] = 0;
3055                     for (int d = 0; d < ndim_rm_vcm; d++)
3056                     {
3057                         if (dof_vcm[j][d])
3058                         {
3059                             nrdf_vcm_sub[j]++;
3060                         }
3061                     }
3062                     break;
3063                 case ecmANGULAR: nrdf_vcm_sub[j] = 6; break;
3064                 default: gmx_incons("Checking comm_mode");
3065             }
3066         }
3067
3068         for (gmx::index i = 0;
3069              i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
3070         {
3071             /* Count the number of atoms of TC group i for every VCM group */
3072             for (gmx::index j = 0;
3073                  j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; j++)
3074             {
3075                 na_vcm[j] = 0;
3076             }
3077             na_tot = 0;
3078             for (int ai = 0; ai < natoms; ai++)
3079             {
3080                 if (getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai) == i)
3081                 {
3082                     na_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)]++;
3083                     na_tot++;
3084                 }
3085             }
3086             /* Correct for VCM removal according to the fraction of each VCM
3087              * group present in this TC group.
3088              */
3089             nrdf_uc    = nrdf_tc[i];
3090             nrdf_tc[i] = 0;
3091             for (gmx::index j = 0;
3092                  j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; j++)
3093             {
3094                 if (nrdf_vcm[j] > nrdf_vcm_sub[j])
3095                 {
3096                     nrdf_tc[i] += nrdf_uc * (static_cast<double>(na_vcm[j]) / static_cast<double>(na_tot))
3097                                   * (nrdf_vcm[j] - nrdf_vcm_sub[j]) / nrdf_vcm[j];
3098                 }
3099             }
3100         }
3101     }
3102     for (int i = 0; (i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling])); i++)
3103     {
3104         opts->nrdf[i] = nrdf_tc[i];
3105         if (opts->nrdf[i] < 0)
3106         {
3107             opts->nrdf[i] = 0;
3108         }
3109         fprintf(stderr, "Number of degrees of freedom in T-Coupling group %s is %.2f\n",
3110                 gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][i]], opts->nrdf[i]);
3111     }
3112
3113     sfree(nrdf2);
3114     sfree(nrdf_tc);
3115     sfree(nrdf_vcm);
3116     sfree(dof_vcm);
3117     sfree(na_vcm);
3118     sfree(nrdf_vcm_sub);
3119 }
3120
3121 static bool do_egp_flag(t_inputrec* ir, SimulationGroups* groups, const char* option, const char* val, int flag)
3122 {
3123     /* The maximum number of energy group pairs would be MAXPTR*(MAXPTR+1)/2.
3124      * But since this is much larger than STRLEN, such a line can not be parsed.
3125      * The real maximum is the number of names that fit in a string: STRLEN/2.
3126      */
3127 #define EGP_MAX (STRLEN / 2)
3128     int  j, k, nr;
3129     bool bSet;
3130
3131     auto names = gmx::splitString(val);
3132     if (names.size() % 2 != 0)
3133     {
3134         gmx_fatal(FARGS, "The number of groups for %s is odd", option);
3135     }
3136     nr   = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3137     bSet = FALSE;
3138     for (size_t i = 0; i < names.size() / 2; i++)
3139     {
3140         // TODO this needs to be replaced by a solution using std::find_if
3141         j = 0;
3142         while ((j < nr)
3143                && gmx_strcasecmp(
3144                           names[2 * i].c_str(),
3145                           *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][j]])))
3146         {
3147             j++;
3148         }
3149         if (j == nr)
3150         {
3151             gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i].c_str(), option);
3152         }
3153         k = 0;
3154         while ((k < nr)
3155                && gmx_strcasecmp(
3156                           names[2 * i + 1].c_str(),
3157                           *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][k]])))
3158         {
3159             k++;
3160         }
3161         if (k == nr)
3162         {
3163             gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i + 1].c_str(), option);
3164         }
3165         if ((j < nr) && (k < nr))
3166         {
3167             ir->opts.egp_flags[nr * j + k] |= flag;
3168             ir->opts.egp_flags[nr * k + j] |= flag;
3169             bSet = TRUE;
3170         }
3171     }
3172
3173     return bSet;
3174 }
3175
3176
3177 static void make_swap_groups(t_swapcoords* swap, t_blocka* grps, char** gnames)
3178 {
3179     int          ig = -1, i = 0, gind;
3180     t_swapGroup* swapg;
3181
3182
3183     /* Just a quick check here, more thorough checks are in mdrun */
3184     if (strcmp(swap->grp[eGrpSplit0].molname, swap->grp[eGrpSplit1].molname) == 0)
3185     {
3186         gmx_fatal(FARGS, "The split groups can not both be '%s'.", swap->grp[eGrpSplit0].molname);
3187     }
3188
3189     /* Get the index atoms of the split0, split1, solvent, and swap groups */
3190     for (ig = 0; ig < swap->ngrp; ig++)
3191     {
3192         swapg      = &swap->grp[ig];
3193         gind       = search_string(swap->grp[ig].molname, grps->nr, gnames);
3194         swapg->nat = grps->index[gind + 1] - grps->index[gind];
3195
3196         if (swapg->nat > 0)
3197         {
3198             fprintf(stderr, "%s group '%s' contains %d atoms.\n",
3199                     ig < 3 ? eSwapFixedGrp_names[ig] : "Swap", swap->grp[ig].molname, swapg->nat);
3200             snew(swapg->ind, swapg->nat);
3201             for (i = 0; i < swapg->nat; i++)
3202             {
3203                 swapg->ind[i] = grps->a[grps->index[gind] + i];
3204             }
3205         }
3206         else
3207         {
3208             gmx_fatal(FARGS, "Swap group %s does not contain any atoms.", swap->grp[ig].molname);
3209         }
3210     }
3211 }
3212
3213
3214 static void make_IMD_group(t_IMD* IMDgroup, char* IMDgname, t_blocka* grps, char** gnames)
3215 {
3216     int ig, i;
3217
3218
3219     ig            = search_string(IMDgname, grps->nr, gnames);
3220     IMDgroup->nat = grps->index[ig + 1] - grps->index[ig];
3221
3222     if (IMDgroup->nat > 0)
3223     {
3224         fprintf(stderr,
3225                 "Group '%s' with %d atoms can be activated for interactive molecular dynamics "
3226                 "(IMD).\n",
3227                 IMDgname, IMDgroup->nat);
3228         snew(IMDgroup->ind, IMDgroup->nat);
3229         for (i = 0; i < IMDgroup->nat; i++)
3230         {
3231             IMDgroup->ind[i] = grps->a[grps->index[ig] + i];
3232         }
3233     }
3234 }
3235
3236 /* Checks whether atoms are both part of a COM removal group and frozen.
3237  * If a fully frozen atom is part of a COM removal group, it is removed
3238  * from the COM removal group. A note is issued if such atoms are present.
3239  * A warning is issued for atom with one or two dimensions frozen that
3240  * are part of a COM removal group (mdrun would need to compute COM mass
3241  * per dimension to handle this correctly).
3242  * Also issues a warning when non-frozen atoms are not part of a COM
3243  * removal group while COM removal is active.
3244  */
3245 static void checkAndUpdateVcmFreezeGroupConsistency(SimulationGroups* groups,
3246                                                     const int         numAtoms,
3247                                                     const t_grpopts&  opts,
3248                                                     warninp_t         wi)
3249 {
3250     const int vcmRestGroup =
3251             std::max(int(groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size()), 1);
3252
3253     int numFullyFrozenVcmAtoms     = 0;
3254     int numPartiallyFrozenVcmAtoms = 0;
3255     int numNonVcmAtoms             = 0;
3256     for (int a = 0; a < numAtoms; a++)
3257     {
3258         const int freezeGroup   = getGroupType(*groups, SimulationAtomGroupType::Freeze, a);
3259         int       numFrozenDims = 0;
3260         for (int d = 0; d < DIM; d++)
3261         {
3262             numFrozenDims += opts.nFreeze[freezeGroup][d];
3263         }
3264
3265         const int vcmGroup = getGroupType(*groups, SimulationAtomGroupType::MassCenterVelocityRemoval, a);
3266         if (vcmGroup < vcmRestGroup)
3267         {
3268             if (numFrozenDims == DIM)
3269             {
3270                 /* Do not remove COM motion for this fully frozen atom */
3271                 if (groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval].empty())
3272                 {
3273                     groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval].resize(numAtoms, 0);
3274                 }
3275                 groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval][a] = vcmRestGroup;
3276                 numFullyFrozenVcmAtoms++;
3277             }
3278             else if (numFrozenDims > 0)
3279             {
3280                 numPartiallyFrozenVcmAtoms++;
3281             }
3282         }
3283         else if (numFrozenDims < DIM)
3284         {
3285             numNonVcmAtoms++;
3286         }
3287     }
3288
3289     if (numFullyFrozenVcmAtoms > 0)
3290     {
3291         std::string warningText = gmx::formatString(
3292                 "There are %d atoms that are fully frozen and part of COMM removal group(s), "
3293                 "removing these atoms from the COMM removal group(s)",
3294                 numFullyFrozenVcmAtoms);
3295         warning_note(wi, warningText.c_str());
3296     }
3297     if (numPartiallyFrozenVcmAtoms > 0 && numPartiallyFrozenVcmAtoms < numAtoms)
3298     {
3299         std::string warningText = gmx::formatString(
3300                 "There are %d atoms that are frozen along less then %d dimensions and part of COMM "
3301                 "removal group(s), due to limitations in the code these still contribute to the "
3302                 "mass of the COM along frozen dimensions and therefore the COMM correction will be "
3303                 "too small.",
3304                 numPartiallyFrozenVcmAtoms, DIM);
3305         warning(wi, warningText.c_str());
3306     }
3307     if (numNonVcmAtoms > 0)
3308     {
3309         std::string warningText = gmx::formatString(
3310                 "%d atoms are not part of any center of mass motion removal group.\n"
3311                 "This may lead to artifacts.\n"
3312                 "In most cases one should use one group for the whole system.",
3313                 numNonVcmAtoms);
3314         warning(wi, warningText.c_str());
3315     }
3316 }
3317
3318 void do_index(const char*                   mdparin,
3319               const char*                   ndx,
3320               gmx_mtop_t*                   mtop,
3321               bool                          bVerbose,
3322               const gmx::MdModulesNotifier& notifier,
3323               t_inputrec*                   ir,
3324               warninp_t                     wi)
3325 {
3326     t_blocka* defaultIndexGroups;
3327     int       natoms;
3328     t_symtab* symtab;
3329     t_atoms   atoms_all;
3330     char**    gnames;
3331     int       nr;
3332     real      tau_min;
3333     int       nstcmin;
3334     int       i, j, k, restnm;
3335     bool      bExcl, bTable, bAnneal;
3336     char      warn_buf[STRLEN];
3337
3338     if (bVerbose)
3339     {
3340         fprintf(stderr, "processing index file...\n");
3341     }
3342     if (ndx == nullptr)
3343     {
3344         snew(defaultIndexGroups, 1);
3345         snew(defaultIndexGroups->index, 1);
3346         snew(gnames, 1);
3347         atoms_all = gmx_mtop_global_atoms(mtop);
3348         analyse(&atoms_all, defaultIndexGroups, &gnames, FALSE, TRUE);
3349         done_atom(&atoms_all);
3350     }
3351     else
3352     {
3353         defaultIndexGroups = init_index(ndx, &gnames);
3354     }
3355
3356     SimulationGroups* groups = &mtop->groups;
3357     natoms                   = mtop->natoms;
3358     symtab                   = &mtop->symtab;
3359
3360     for (int i = 0; (i < defaultIndexGroups->nr); i++)
3361     {
3362         groups->groupNames.emplace_back(put_symtab(symtab, gnames[i]));
3363     }
3364     groups->groupNames.emplace_back(put_symtab(symtab, "rest"));
3365     restnm = groups->groupNames.size() - 1;
3366     GMX_RELEASE_ASSERT(restnm == defaultIndexGroups->nr, "Size of allocations must match");
3367     srenew(gnames, defaultIndexGroups->nr + 1);
3368     gnames[restnm] = *(groups->groupNames.back());
3369
3370     set_warning_line(wi, mdparin, -1);
3371
3372     auto temperatureCouplingTauValues       = gmx::splitString(is->tau_t);
3373     auto temperatureCouplingReferenceValues = gmx::splitString(is->ref_t);
3374     auto temperatureCouplingGroupNames      = gmx::splitString(is->tcgrps);
3375     if (temperatureCouplingTauValues.size() != temperatureCouplingGroupNames.size()
3376         || temperatureCouplingReferenceValues.size() != temperatureCouplingGroupNames.size())
3377     {
3378         gmx_fatal(FARGS,
3379                   "Invalid T coupling input: %zu groups, %zu ref-t values and "
3380                   "%zu tau-t values",
3381                   temperatureCouplingGroupNames.size(), temperatureCouplingReferenceValues.size(),
3382                   temperatureCouplingTauValues.size());
3383     }
3384
3385     const bool useReferenceTemperature = integratorHasReferenceTemperature(ir);
3386     do_numbering(natoms, groups, temperatureCouplingGroupNames, defaultIndexGroups, gnames,
3387                  SimulationAtomGroupType::TemperatureCoupling, restnm,
3388                  useReferenceTemperature ? egrptpALL : egrptpALL_GENREST, bVerbose, wi);
3389     nr            = groups->groups[SimulationAtomGroupType::TemperatureCoupling].size();
3390     ir->opts.ngtc = nr;
3391     snew(ir->opts.nrdf, nr);
3392     snew(ir->opts.tau_t, nr);
3393     snew(ir->opts.ref_t, nr);
3394     if (ir->eI == eiBD && ir->bd_fric == 0)
3395     {
3396         fprintf(stderr, "bd-fric=0, so tau-t will be used as the inverse friction constant(s)\n");
3397     }
3398
3399     if (useReferenceTemperature)
3400     {
3401         if (size_t(nr) != temperatureCouplingReferenceValues.size())
3402         {
3403             gmx_fatal(FARGS, "Not enough ref-t and tau-t values!");
3404         }
3405
3406         tau_min = 1e20;
3407         convertReals(wi, temperatureCouplingTauValues, "tau-t", ir->opts.tau_t);
3408         for (i = 0; (i < nr); i++)
3409         {
3410             if ((ir->eI == eiBD) && ir->opts.tau_t[i] <= 0)
3411             {
3412                 sprintf(warn_buf, "With integrator %s tau-t should be larger than 0", ei_names[ir->eI]);
3413                 warning_error(wi, warn_buf);
3414             }
3415
3416             if (ir->etc != etcVRESCALE && ir->opts.tau_t[i] == 0)
3417             {
3418                 warning_note(
3419                         wi,
3420                         "tau-t = -1 is the value to signal that a group should not have "
3421                         "temperature coupling. Treating your use of tau-t = 0 as if you used -1.");
3422             }
3423
3424             if (ir->opts.tau_t[i] >= 0)
3425             {
3426                 tau_min = std::min(tau_min, ir->opts.tau_t[i]);
3427             }
3428         }
3429         if (ir->etc != etcNO && ir->nsttcouple == -1)
3430         {
3431             ir->nsttcouple = ir_optimal_nsttcouple(ir);
3432         }
3433
3434         if (EI_VV(ir->eI))
3435         {
3436             if ((ir->etc == etcNOSEHOOVER) && (ir->epc == epcBERENDSEN))
3437             {
3438                 gmx_fatal(FARGS,
3439                           "Cannot do Nose-Hoover temperature with Berendsen pressure control with "
3440                           "md-vv; use either vrescale temperature with berendsen pressure or "
3441                           "Nose-Hoover temperature with MTTK pressure");
3442             }
3443             if (ir->epc == epcMTTK)
3444             {
3445                 if (ir->etc != etcNOSEHOOVER)
3446                 {
3447                     gmx_fatal(FARGS,
3448                               "Cannot do MTTK pressure coupling without Nose-Hoover temperature "
3449                               "control");
3450                 }
3451                 else
3452                 {
3453                     if (ir->nstpcouple != ir->nsttcouple)
3454                     {
3455                         int mincouple  = std::min(ir->nstpcouple, ir->nsttcouple);
3456                         ir->nstpcouple = ir->nsttcouple = mincouple;
3457                         sprintf(warn_buf,
3458                                 "for current Trotter decomposition methods with vv, nsttcouple and "
3459                                 "nstpcouple must be equal.  Both have been reset to "
3460                                 "min(nsttcouple,nstpcouple) = %d",
3461                                 mincouple);
3462                         warning_note(wi, warn_buf);
3463                     }
3464                 }
3465             }
3466         }
3467         /* velocity verlet with averaged kinetic energy KE = 0.5*(v(t+1/2) - v(t-1/2)) is implemented
3468            primarily for testing purposes, and does not work with temperature coupling other than 1 */
3469
3470         if (ETC_ANDERSEN(ir->etc))
3471         {
3472             if (ir->nsttcouple != 1)
3473             {
3474                 ir->nsttcouple = 1;
3475                 sprintf(warn_buf,
3476                         "Andersen temperature control methods assume nsttcouple = 1; there is no "
3477                         "need for larger nsttcouple > 1, since no global parameters are computed. "
3478                         "nsttcouple has been reset to 1");
3479                 warning_note(wi, warn_buf);
3480             }
3481         }
3482         nstcmin = tcouple_min_integration_steps(ir->etc);
3483         if (nstcmin > 1)
3484         {
3485             if (tau_min / (ir->delta_t * ir->nsttcouple) < nstcmin - 10 * GMX_REAL_EPS)
3486             {
3487                 sprintf(warn_buf,
3488                         "For proper integration of the %s thermostat, tau-t (%g) should be at "
3489                         "least %d times larger than nsttcouple*dt (%g)",
3490                         ETCOUPLTYPE(ir->etc), tau_min, nstcmin, ir->nsttcouple * ir->delta_t);
3491                 warning(wi, warn_buf);
3492             }
3493         }
3494         convertReals(wi, temperatureCouplingReferenceValues, "ref-t", ir->opts.ref_t);
3495         for (i = 0; (i < nr); i++)
3496         {
3497             if (ir->opts.ref_t[i] < 0)
3498             {
3499                 gmx_fatal(FARGS, "ref-t for group %d negative", i);
3500             }
3501         }
3502         /* set the lambda mc temperature to the md integrator temperature (which should be defined
3503            if we are in this conditional) if mc_temp is negative */
3504         if (ir->expandedvals->mc_temp < 0)
3505         {
3506             ir->expandedvals->mc_temp = ir->opts.ref_t[0]; /*for now, set to the first reft */
3507         }
3508     }
3509
3510     /* Simulated annealing for each group. There are nr groups */
3511     auto simulatedAnnealingGroupNames = gmx::splitString(is->anneal);
3512     if (simulatedAnnealingGroupNames.size() == 1
3513         && gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[0], "N", 1))
3514     {
3515         simulatedAnnealingGroupNames.resize(0);
3516     }
3517     if (!simulatedAnnealingGroupNames.empty() && gmx::ssize(simulatedAnnealingGroupNames) != nr)
3518     {
3519         gmx_fatal(FARGS, "Wrong number of annealing values: %zu (for %d groups)\n",
3520                   simulatedAnnealingGroupNames.size(), nr);
3521     }
3522     else
3523     {
3524         snew(ir->opts.annealing, nr);
3525         snew(ir->opts.anneal_npoints, nr);
3526         snew(ir->opts.anneal_time, nr);
3527         snew(ir->opts.anneal_temp, nr);
3528         for (i = 0; i < nr; i++)
3529         {
3530             ir->opts.annealing[i]      = eannNO;
3531             ir->opts.anneal_npoints[i] = 0;
3532             ir->opts.anneal_time[i]    = nullptr;
3533             ir->opts.anneal_temp[i]    = nullptr;
3534         }
3535         if (!simulatedAnnealingGroupNames.empty())
3536         {
3537             bAnneal = FALSE;
3538             for (i = 0; i < nr; i++)
3539             {
3540                 if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "N", 1))
3541                 {
3542                     ir->opts.annealing[i] = eannNO;
3543                 }
3544                 else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "S", 1))
3545                 {
3546                     ir->opts.annealing[i] = eannSINGLE;
3547                     bAnneal               = TRUE;
3548                 }
3549                 else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "P", 1))
3550                 {
3551                     ir->opts.annealing[i] = eannPERIODIC;
3552                     bAnneal               = TRUE;
3553                 }
3554             }
3555             if (bAnneal)
3556             {
3557                 /* Read the other fields too */
3558                 auto simulatedAnnealingPoints = gmx::splitString(is->anneal_npoints);
3559                 if (simulatedAnnealingPoints.size() != simulatedAnnealingGroupNames.size())
3560                 {
3561                     gmx_fatal(FARGS, "Found %zu annealing-npoints values for %zu groups\n",
3562                               simulatedAnnealingPoints.size(), simulatedAnnealingGroupNames.size());
3563                 }
3564                 convertInts(wi, simulatedAnnealingPoints, "annealing points", ir->opts.anneal_npoints);
3565                 size_t numSimulatedAnnealingFields = 0;
3566                 for (i = 0; i < nr; i++)
3567                 {
3568                     if (ir->opts.anneal_npoints[i] == 1)
3569                     {
3570                         gmx_fatal(
3571                                 FARGS,
3572                                 "Please specify at least a start and an end point for annealing\n");
3573                     }
3574                     snew(ir->opts.anneal_time[i], ir->opts.anneal_npoints[i]);
3575                     snew(ir->opts.anneal_temp[i], ir->opts.anneal_npoints[i]);
3576                     numSimulatedAnnealingFields += ir->opts.anneal_npoints[i];
3577                 }
3578
3579                 auto simulatedAnnealingTimes = gmx::splitString(is->anneal_time);
3580
3581                 if (simulatedAnnealingTimes.size() != numSimulatedAnnealingFields)
3582                 {
3583                     gmx_fatal(FARGS, "Found %zu annealing-time values, wanted %zu\n",
3584                               simulatedAnnealingTimes.size(), numSimulatedAnnealingFields);
3585                 }
3586                 auto simulatedAnnealingTemperatures = gmx::splitString(is->anneal_temp);
3587                 if (simulatedAnnealingTemperatures.size() != numSimulatedAnnealingFields)
3588                 {
3589                     gmx_fatal(FARGS, "Found %zu annealing-temp values, wanted %zu\n",
3590                               simulatedAnnealingTemperatures.size(), numSimulatedAnnealingFields);
3591                 }
3592
3593                 std::vector<real> allSimulatedAnnealingTimes(numSimulatedAnnealingFields);
3594                 std::vector<real> allSimulatedAnnealingTemperatures(numSimulatedAnnealingFields);
3595                 convertReals(wi, simulatedAnnealingTimes, "anneal-time",
3596                              allSimulatedAnnealingTimes.data());
3597                 convertReals(wi, simulatedAnnealingTemperatures, "anneal-temp",
3598                              allSimulatedAnnealingTemperatures.data());
3599                 for (i = 0, k = 0; i < nr; i++)
3600                 {
3601                     for (j = 0; j < ir->opts.anneal_npoints[i]; j++)
3602                     {
3603                         ir->opts.anneal_time[i][j] = allSimulatedAnnealingTimes[k];
3604                         ir->opts.anneal_temp[i][j] = allSimulatedAnnealingTemperatures[k];
3605                         if (j == 0)
3606                         {
3607                             if (ir->opts.anneal_time[i][0] > (ir->init_t + GMX_REAL_EPS))
3608                             {
3609                                 gmx_fatal(FARGS, "First time point for annealing > init_t.\n");
3610                             }
3611                         }
3612                         else
3613                         {
3614                             /* j>0 */
3615                             if (ir->opts.anneal_time[i][j] < ir->opts.anneal_time[i][j - 1])
3616                             {
3617                                 gmx_fatal(FARGS,
3618                                           "Annealing timepoints out of order: t=%f comes after "
3619                                           "t=%f\n",
3620                                           ir->opts.anneal_time[i][j], ir->opts.anneal_time[i][j - 1]);
3621                             }
3622                         }
3623                         if (ir->opts.anneal_temp[i][j] < 0)
3624                         {
3625                             gmx_fatal(FARGS, "Found negative temperature in annealing: %f\n",
3626                                       ir->opts.anneal_temp[i][j]);
3627                         }
3628                         k++;
3629                     }
3630                 }
3631                 /* Print out some summary information, to make sure we got it right */
3632                 for (i = 0; i < nr; i++)
3633                 {
3634                     if (ir->opts.annealing[i] != eannNO)
3635                     {
3636                         j = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
3637                         fprintf(stderr, "Simulated annealing for group %s: %s, %d timepoints\n",
3638                                 *(groups->groupNames[j]), eann_names[ir->opts.annealing[i]],
3639                                 ir->opts.anneal_npoints[i]);
3640                         fprintf(stderr, "Time (ps)   Temperature (K)\n");
3641                         /* All terms except the last one */
3642                         for (j = 0; j < (ir->opts.anneal_npoints[i] - 1); j++)
3643                         {
3644                             fprintf(stderr, "%9.1f      %5.1f\n", ir->opts.anneal_time[i][j],
3645                                     ir->opts.anneal_temp[i][j]);
3646                         }
3647
3648                         /* Finally the last one */
3649                         j = ir->opts.anneal_npoints[i] - 1;
3650                         if (ir->opts.annealing[i] == eannSINGLE)
3651                         {
3652                             fprintf(stderr, "%9.1f-     %5.1f\n", ir->opts.anneal_time[i][j],
3653                                     ir->opts.anneal_temp[i][j]);
3654                         }
3655                         else
3656                         {
3657                             fprintf(stderr, "%9.1f      %5.1f\n", ir->opts.anneal_time[i][j],
3658                                     ir->opts.anneal_temp[i][j]);
3659                             if (std::fabs(ir->opts.anneal_temp[i][j] - ir->opts.anneal_temp[i][0]) > GMX_REAL_EPS)
3660                             {
3661                                 warning_note(wi,
3662                                              "There is a temperature jump when your annealing "
3663                                              "loops back.\n");
3664                             }
3665                         }
3666                     }
3667                 }
3668             }
3669         }
3670     }
3671
3672     if (ir->bPull)
3673     {
3674         make_pull_groups(ir->pull, is->pull_grp, defaultIndexGroups, gnames);
3675
3676         make_pull_coords(ir->pull);
3677     }
3678
3679     if (ir->bRot)
3680     {
3681         make_rotation_groups(ir->rot, is->rot_grp, defaultIndexGroups, gnames);
3682     }
3683
3684     if (ir->eSwapCoords != eswapNO)
3685     {
3686         make_swap_groups(ir->swap, defaultIndexGroups, gnames);
3687     }
3688
3689     /* Make indices for IMD session */
3690     if (ir->bIMD)
3691     {
3692         make_IMD_group(ir->imd, is->imd_grp, defaultIndexGroups, gnames);
3693     }
3694
3695     gmx::IndexGroupsAndNames defaultIndexGroupsAndNames(
3696             *defaultIndexGroups, gmx::arrayRefFromArray(gnames, defaultIndexGroups->nr));
3697     notifier.notifier_.notify(defaultIndexGroupsAndNames);
3698
3699     auto accelerations          = gmx::splitString(is->acc);
3700     auto accelerationGroupNames = gmx::splitString(is->accgrps);
3701     if (accelerationGroupNames.size() * DIM != accelerations.size())
3702     {
3703         gmx_fatal(FARGS, "Invalid Acceleration input: %zu groups and %zu acc. values",
3704                   accelerationGroupNames.size(), accelerations.size());
3705     }
3706     do_numbering(natoms, groups, accelerationGroupNames, defaultIndexGroups, gnames,
3707                  SimulationAtomGroupType::Acceleration, restnm, egrptpALL_GENREST, bVerbose, wi);
3708     nr = groups->groups[SimulationAtomGroupType::Acceleration].size();
3709     snew(ir->opts.acc, nr);
3710     ir->opts.ngacc = nr;
3711
3712     convertRvecs(wi, accelerations, "anneal-time", ir->opts.acc);
3713
3714     auto freezeDims       = gmx::splitString(is->frdim);
3715     auto freezeGroupNames = gmx::splitString(is->freeze);
3716     if (freezeDims.size() != DIM * freezeGroupNames.size())
3717     {
3718         gmx_fatal(FARGS, "Invalid Freezing input: %zu groups and %zu freeze values",
3719                   freezeGroupNames.size(), freezeDims.size());
3720     }
3721     do_numbering(natoms, groups, freezeGroupNames, defaultIndexGroups, gnames,
3722                  SimulationAtomGroupType::Freeze, restnm, egrptpALL_GENREST, bVerbose, wi);
3723     nr             = groups->groups[SimulationAtomGroupType::Freeze].size();
3724     ir->opts.ngfrz = nr;
3725     snew(ir->opts.nFreeze, nr);
3726     for (i = k = 0; (size_t(i) < freezeGroupNames.size()); i++)
3727     {
3728         for (j = 0; (j < DIM); j++, k++)
3729         {
3730             ir->opts.nFreeze[i][j] = static_cast<int>(gmx::equalCaseInsensitive(freezeDims[k], "Y", 1));
3731             if (!ir->opts.nFreeze[i][j])
3732             {
3733                 if (!gmx::equalCaseInsensitive(freezeDims[k], "N", 1))
3734                 {
3735                     sprintf(warn_buf,
3736                             "Please use Y(ES) or N(O) for freezedim only "
3737                             "(not %s)",
3738                             freezeDims[k].c_str());
3739                     warning(wi, warn_buf);
3740                 }
3741             }
3742         }
3743     }
3744     for (; (i < nr); i++)
3745     {
3746         for (j = 0; (j < DIM); j++)
3747         {
3748             ir->opts.nFreeze[i][j] = 0;
3749         }
3750     }
3751
3752     auto energyGroupNames = gmx::splitString(is->energy);
3753     do_numbering(natoms, groups, energyGroupNames, defaultIndexGroups, gnames,
3754                  SimulationAtomGroupType::EnergyOutput, restnm, egrptpALL_GENREST, bVerbose, wi);
3755     add_wall_energrps(groups, ir->nwall, symtab);
3756     ir->opts.ngener    = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3757     auto vcmGroupNames = gmx::splitString(is->vcm);
3758     do_numbering(natoms, groups, vcmGroupNames, defaultIndexGroups, gnames,
3759                  SimulationAtomGroupType::MassCenterVelocityRemoval, restnm,
3760                  vcmGroupNames.empty() ? egrptpALL_GENREST : egrptpPART, bVerbose, wi);
3761
3762     if (ir->comm_mode != ecmNO)
3763     {
3764         checkAndUpdateVcmFreezeGroupConsistency(groups, natoms, ir->opts, wi);
3765     }
3766
3767     /* Now we have filled the freeze struct, so we can calculate NRDF */
3768     calc_nrdf(mtop, ir, gnames);
3769
3770     auto user1GroupNames = gmx::splitString(is->user1);
3771     do_numbering(natoms, groups, user1GroupNames, defaultIndexGroups, gnames,
3772                  SimulationAtomGroupType::User1, restnm, egrptpALL_GENREST, bVerbose, wi);
3773     auto user2GroupNames = gmx::splitString(is->user2);
3774     do_numbering(natoms, groups, user2GroupNames, defaultIndexGroups, gnames,
3775                  SimulationAtomGroupType::User2, restnm, egrptpALL_GENREST, bVerbose, wi);
3776     auto compressedXGroupNames = gmx::splitString(is->x_compressed_groups);
3777     do_numbering(natoms, groups, compressedXGroupNames, defaultIndexGroups, gnames,
3778                  SimulationAtomGroupType::CompressedPositionOutput, restnm, egrptpONE, bVerbose, wi);
3779     auto orirefFitGroupNames = gmx::splitString(is->orirefitgrp);
3780     do_numbering(natoms, groups, orirefFitGroupNames, defaultIndexGroups, gnames,
3781                  SimulationAtomGroupType::OrientationRestraintsFit, restnm, egrptpALL_GENREST,
3782                  bVerbose, wi);
3783
3784     /* QMMM input processing */
3785     auto qmGroupNames = gmx::splitString(is->QMMM);
3786     auto qmMethods    = gmx::splitString(is->QMmethod);
3787     auto qmBasisSets  = gmx::splitString(is->QMbasis);
3788     if (ir->eI != eiMimic)
3789     {
3790         if (qmMethods.size() != qmGroupNames.size() || qmBasisSets.size() != qmGroupNames.size())
3791         {
3792             gmx_fatal(FARGS,
3793                       "Invalid QMMM input: %zu groups %zu basissets"
3794                       " and %zu methods\n",
3795                       qmGroupNames.size(), qmBasisSets.size(), qmMethods.size());
3796         }
3797         /* group rest, if any, is always MM! */
3798         do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
3799                      SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
3800         nr            = qmGroupNames.size(); /*atoms->grps[egcQMMM].nr;*/
3801         ir->opts.ngQM = qmGroupNames.size();
3802         snew(ir->opts.QMmethod, nr);
3803         snew(ir->opts.QMbasis, nr);
3804         for (i = 0; i < nr; i++)
3805         {
3806             /* input consists of strings: RHF CASSCF PM3 .. These need to be
3807              * converted to the corresponding enum in names.c
3808              */
3809             ir->opts.QMmethod[i] = search_QMstring(qmMethods[i].c_str(), eQMmethodNR, eQMmethod_names);
3810             ir->opts.QMbasis[i] = search_QMstring(qmBasisSets[i].c_str(), eQMbasisNR, eQMbasis_names);
3811         }
3812         auto qmMultiplicities = gmx::splitString(is->QMmult);
3813         auto qmCharges        = gmx::splitString(is->QMcharge);
3814         auto qmbSH            = gmx::splitString(is->bSH);
3815         snew(ir->opts.QMmult, nr);
3816         snew(ir->opts.QMcharge, nr);
3817         snew(ir->opts.bSH, nr);
3818         convertInts(wi, qmMultiplicities, "QMmult", ir->opts.QMmult);
3819         convertInts(wi, qmCharges, "QMcharge", ir->opts.QMcharge);
3820         convertYesNos(wi, qmbSH, "bSH", ir->opts.bSH);
3821
3822         auto CASelectrons = gmx::splitString(is->CASelectrons);
3823         auto CASorbitals  = gmx::splitString(is->CASorbitals);
3824         snew(ir->opts.CASelectrons, nr);
3825         snew(ir->opts.CASorbitals, nr);
3826         convertInts(wi, CASelectrons, "CASelectrons", ir->opts.CASelectrons);
3827         convertInts(wi, CASorbitals, "CASOrbitals", ir->opts.CASorbitals);
3828
3829         auto SAon    = gmx::splitString(is->SAon);
3830         auto SAoff   = gmx::splitString(is->SAoff);
3831         auto SAsteps = gmx::splitString(is->SAsteps);
3832         snew(ir->opts.SAon, nr);
3833         snew(ir->opts.SAoff, nr);
3834         snew(ir->opts.SAsteps, nr);
3835         convertInts(wi, SAon, "SAon", ir->opts.SAon);
3836         convertInts(wi, SAoff, "SAoff", ir->opts.SAoff);
3837         convertInts(wi, SAsteps, "SAsteps", ir->opts.SAsteps);
3838     }
3839     else
3840     {
3841         /* MiMiC */
3842         if (qmGroupNames.size() > 1)
3843         {
3844             gmx_fatal(FARGS, "Currently, having more than one QM group in MiMiC is not supported");
3845         }
3846         /* group rest, if any, is always MM! */
3847         do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
3848                      SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
3849
3850         ir->opts.ngQM = qmGroupNames.size();
3851     }
3852
3853     /* end of QMMM input */
3854
3855     if (bVerbose)
3856     {
3857         for (auto group : gmx::keysOf(groups->groups))
3858         {
3859             fprintf(stderr, "%-16s has %zu element(s):", shortName(group), groups->groups[group].size());
3860             for (const auto& entry : groups->groups[group])
3861             {
3862                 fprintf(stderr, " %s", *(groups->groupNames[entry]));
3863             }
3864             fprintf(stderr, "\n");
3865         }
3866     }
3867
3868     nr = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3869     snew(ir->opts.egp_flags, nr * nr);
3870
3871     bExcl = do_egp_flag(ir, groups, "energygrp-excl", is->egpexcl, EGP_EXCL);
3872     if (bExcl && ir->cutoff_scheme == ecutsVERLET)
3873     {
3874         warning_error(wi, "Energy group exclusions are currently not supported");
3875     }
3876     if (bExcl && EEL_FULL(ir->coulombtype))
3877     {
3878         warning(wi, "Can not exclude the lattice Coulomb energy between energy groups");
3879     }
3880
3881     bTable = do_egp_flag(ir, groups, "energygrp-table", is->egptable, EGP_TABLE);
3882     if (bTable && !(ir->vdwtype == evdwUSER) && !(ir->coulombtype == eelUSER)
3883         && !(ir->coulombtype == eelPMEUSER) && !(ir->coulombtype == eelPMEUSERSWITCH))
3884     {
3885         gmx_fatal(FARGS,
3886                   "Can only have energy group pair tables in combination with user tables for VdW "
3887                   "and/or Coulomb");
3888     }
3889
3890     /* final check before going out of scope if simulated tempering variables
3891      * need to be set to default values.
3892      */
3893     if ((ir->expandedvals->nstexpanded < 0) && ir->bSimTemp)
3894     {
3895         ir->expandedvals->nstexpanded = 2 * static_cast<int>(ir->opts.tau_t[0] / ir->delta_t);
3896         warning(wi, gmx::formatString(
3897                             "the value for nstexpanded was not specified for "
3898                             " expanded ensemble simulated tempering. It is set to 2*tau_t (%d) "
3899                             "by default, but it is recommended to set it to an explicit value!",
3900                             ir->expandedvals->nstexpanded));
3901     }
3902     for (i = 0; (i < defaultIndexGroups->nr); i++)
3903     {
3904         sfree(gnames[i]);
3905     }
3906     sfree(gnames);
3907     done_blocka(defaultIndexGroups);
3908     sfree(defaultIndexGroups);
3909 }
3910
3911
3912 static void check_disre(const gmx_mtop_t* mtop)
3913 {
3914     if (gmx_mtop_ftype_count(mtop, F_DISRES) > 0)
3915     {
3916         const gmx_ffparams_t& ffparams  = mtop->ffparams;
3917         int                   ndouble   = 0;
3918         int                   old_label = -1;
3919         for (int i = 0; i < ffparams.numTypes(); i++)
3920         {
3921             int ftype = ffparams.functype[i];
3922             if (ftype == F_DISRES)
3923             {
3924                 int label = ffparams.iparams[i].disres.label;
3925                 if (label == old_label)
3926                 {
3927                     fprintf(stderr, "Distance restraint index %d occurs twice\n", label);
3928                     ndouble++;
3929                 }
3930                 old_label = label;
3931             }
3932         }
3933         if (ndouble > 0)
3934         {
3935             gmx_fatal(FARGS,
3936                       "Found %d double distance restraint indices,\n"
3937                       "probably the parameters for multiple pairs in one restraint "
3938                       "are not identical\n",
3939                       ndouble);
3940         }
3941     }
3942 }
3943
3944 static bool absolute_reference(const t_inputrec* ir, const gmx_mtop_t* sys, const bool posres_only, ivec AbsRef)
3945 {
3946     int                  d, g, i;
3947     gmx_mtop_ilistloop_t iloop;
3948     int                  nmol;
3949     const t_iparams*     pr;
3950
3951     clear_ivec(AbsRef);
3952
3953     if (!posres_only)
3954     {
3955         /* Check the COM */
3956         for (d = 0; d < DIM; d++)
3957         {
3958             AbsRef[d] = (d < ndof_com(ir) ? 0 : 1);
3959         }
3960         /* Check for freeze groups */
3961         for (g = 0; g < ir->opts.ngfrz; g++)
3962         {
3963             for (d = 0; d < DIM; d++)
3964             {
3965                 if (ir->opts.nFreeze[g][d] != 0)
3966                 {
3967                     AbsRef[d] = 1;
3968                 }
3969             }
3970         }
3971     }
3972
3973     /* Check for position restraints */
3974     iloop = gmx_mtop_ilistloop_init(sys);
3975     while (const InteractionLists* ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
3976     {
3977         if (nmol > 0 && (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
3978         {
3979             for (i = 0; i < (*ilist)[F_POSRES].size(); i += 2)
3980             {
3981                 pr = &sys->ffparams.iparams[(*ilist)[F_POSRES].iatoms[i]];
3982                 for (d = 0; d < DIM; d++)
3983                 {
3984                     if (pr->posres.fcA[d] != 0)
3985                     {
3986                         AbsRef[d] = 1;
3987                     }
3988                 }
3989             }
3990             for (i = 0; i < (*ilist)[F_FBPOSRES].size(); i += 2)
3991             {
3992                 /* Check for flat-bottom posres */
3993                 pr = &sys->ffparams.iparams[(*ilist)[F_FBPOSRES].iatoms[i]];
3994                 if (pr->fbposres.k != 0)
3995                 {
3996                     switch (pr->fbposres.geom)
3997                     {
3998                         case efbposresSPHERE: AbsRef[XX] = AbsRef[YY] = AbsRef[ZZ] = 1; break;
3999                         case efbposresCYLINDERX: AbsRef[YY] = AbsRef[ZZ] = 1; break;
4000                         case efbposresCYLINDERY: AbsRef[XX] = AbsRef[ZZ] = 1; break;
4001                         case efbposresCYLINDER:
4002                         /* efbposres is a synonym for efbposresCYLINDERZ for backwards compatibility */
4003                         case efbposresCYLINDERZ: AbsRef[XX] = AbsRef[YY] = 1; break;
4004                         case efbposresX: /* d=XX */
4005                         case efbposresY: /* d=YY */
4006                         case efbposresZ: /* d=ZZ */
4007                             d         = pr->fbposres.geom - efbposresX;
4008                             AbsRef[d] = 1;
4009                             break;
4010                         default:
4011                             gmx_fatal(FARGS,
4012                                       " Invalid geometry for flat-bottom position restraint.\n"
4013                                       "Expected nr between 1 and %d. Found %d\n",
4014                                       efbposresNR - 1, pr->fbposres.geom);
4015                     }
4016                 }
4017             }
4018         }
4019     }
4020
4021     return (AbsRef[XX] != 0 && AbsRef[YY] != 0 && AbsRef[ZZ] != 0);
4022 }
4023
4024 static void check_combination_rule_differences(const gmx_mtop_t* mtop,
4025                                                int               state,
4026                                                bool* bC6ParametersWorkWithGeometricRules,
4027                                                bool* bC6ParametersWorkWithLBRules,
4028                                                bool* bLBRulesPossible)
4029 {
4030     int         ntypes, tpi, tpj;
4031     int*        typecount;
4032     real        tol;
4033     double      c6i, c6j, c12i, c12j;
4034     double      c6, c6_geometric, c6_LB;
4035     double      sigmai, sigmaj, epsi, epsj;
4036     bool        bCanDoLBRules, bCanDoGeometricRules;
4037     const char* ptr;
4038
4039     /* A tolerance of 1e-5 seems reasonable for (possibly hand-typed)
4040      * force-field floating point parameters.
4041      */
4042     tol = 1e-5;
4043     ptr = getenv("GMX_LJCOMB_TOL");
4044     if (ptr != nullptr)
4045     {
4046         double dbl;
4047         double gmx_unused canary;
4048
4049         if (sscanf(ptr, "%lf%lf", &dbl, &canary) != 1)
4050         {
4051             gmx_fatal(FARGS,
4052                       "Could not parse a single floating-point number from GMX_LJCOMB_TOL (%s)", ptr);
4053         }
4054         tol = dbl;
4055     }
4056
4057     *bC6ParametersWorkWithLBRules        = TRUE;
4058     *bC6ParametersWorkWithGeometricRules = TRUE;
4059     bCanDoLBRules                        = TRUE;
4060     ntypes                               = mtop->ffparams.atnr;
4061     snew(typecount, ntypes);
4062     gmx_mtop_count_atomtypes(mtop, state, typecount);
4063     *bLBRulesPossible = TRUE;
4064     for (tpi = 0; tpi < ntypes; ++tpi)
4065     {
4066         c6i  = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c6;
4067         c12i = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c12;
4068         for (tpj = tpi; tpj < ntypes; ++tpj)
4069         {
4070             c6j          = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c6;
4071             c12j         = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c12;
4072             c6           = mtop->ffparams.iparams[ntypes * tpi + tpj].lj.c6;
4073             c6_geometric = std::sqrt(c6i * c6j);
4074             if (!gmx_numzero(c6_geometric))
4075             {
4076                 if (!gmx_numzero(c12i) && !gmx_numzero(c12j))
4077                 {
4078                     sigmai = gmx::sixthroot(c12i / c6i);
4079                     sigmaj = gmx::sixthroot(c12j / c6j);
4080                     epsi   = c6i * c6i / (4.0 * c12i);
4081                     epsj   = c6j * c6j / (4.0 * c12j);
4082                     c6_LB  = 4.0 * std::sqrt(epsi * epsj) * gmx::power6(0.5 * (sigmai + sigmaj));
4083                 }
4084                 else
4085                 {
4086                     *bLBRulesPossible = FALSE;
4087                     c6_LB             = c6_geometric;
4088                 }
4089                 bCanDoLBRules = gmx_within_tol(c6_LB, c6, tol);
4090             }
4091
4092             if (!bCanDoLBRules)
4093             {
4094                 *bC6ParametersWorkWithLBRules = FALSE;
4095             }
4096
4097             bCanDoGeometricRules = gmx_within_tol(c6_geometric, c6, tol);
4098
4099             if (!bCanDoGeometricRules)
4100             {
4101                 *bC6ParametersWorkWithGeometricRules = FALSE;
4102             }
4103         }
4104     }
4105     sfree(typecount);
4106 }
4107
4108 static void check_combination_rules(const t_inputrec* ir, const gmx_mtop_t* mtop, warninp_t wi)
4109 {
4110     bool bLBRulesPossible, bC6ParametersWorkWithGeometricRules, bC6ParametersWorkWithLBRules;
4111
4112     check_combination_rule_differences(mtop, 0, &bC6ParametersWorkWithGeometricRules,
4113                                        &bC6ParametersWorkWithLBRules, &bLBRulesPossible);
4114     if (ir->ljpme_combination_rule == eljpmeLB)
4115     {
4116         if (!bC6ParametersWorkWithLBRules || !bLBRulesPossible)
4117         {
4118             warning(wi,
4119                     "You are using arithmetic-geometric combination rules "
4120                     "in LJ-PME, but your non-bonded C6 parameters do not "
4121                     "follow these rules.");
4122         }
4123     }
4124     else
4125     {
4126         if (!bC6ParametersWorkWithGeometricRules)
4127         {
4128             if (ir->eDispCorr != edispcNO)
4129             {
4130                 warning_note(wi,
4131                              "You are using geometric combination rules in "
4132                              "LJ-PME, but your non-bonded C6 parameters do "
4133                              "not follow these rules. "
4134                              "This will introduce very small errors in the forces and energies in "
4135                              "your simulations. Dispersion correction will correct total energy "
4136                              "and/or pressure for isotropic systems, but not forces or surface "
4137                              "tensions.");
4138             }
4139             else
4140             {
4141                 warning_note(wi,
4142                              "You are using geometric combination rules in "
4143                              "LJ-PME, but your non-bonded C6 parameters do "
4144                              "not follow these rules. "
4145                              "This will introduce very small errors in the forces and energies in "
4146                              "your simulations. If your system is homogeneous, consider using "
4147                              "dispersion correction "
4148                              "for the total energy and pressure.");
4149             }
4150         }
4151     }
4152 }
4153
4154 void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_t wi)
4155 {
4156     char                      err_buf[STRLEN];
4157     int                       i, m, c, nmol;
4158     bool                      bCharge, bAcc;
4159     real *                    mgrp, mt;
4160     rvec                      acc;
4161     gmx_mtop_atomloop_block_t aloopb;
4162     ivec                      AbsRef;
4163     char                      warn_buf[STRLEN];
4164
4165     set_warning_line(wi, mdparin, -1);
4166
4167     if (absolute_reference(ir, sys, false, AbsRef))
4168     {
4169         warning_note(wi,
4170                      "Removing center of mass motion in the presence of position restraints might "
4171                      "cause artifacts. When you are using position restraints to equilibrate a "
4172                      "macro-molecule, the artifacts are usually negligible.");
4173     }
4174
4175     if (ir->cutoff_scheme == ecutsVERLET && ir->verletbuf_tol > 0 && ir->nstlist > 1
4176         && ((EI_MD(ir->eI) || EI_SD(ir->eI)) && (ir->etc == etcVRESCALE || ir->etc == etcBERENDSEN)))
4177     {
4178         /* Check if a too small Verlet buffer might potentially
4179          * cause more drift than the thermostat can couple off.
4180          */
4181         /* Temperature error fraction for warning and suggestion */
4182         const real T_error_warn    = 0.002;
4183         const real T_error_suggest = 0.001;
4184         /* For safety: 2 DOF per atom (typical with constraints) */
4185         const real nrdf_at = 2;
4186         real       T, tau, max_T_error;
4187         int        i;
4188
4189         T   = 0;
4190         tau = 0;
4191         for (i = 0; i < ir->opts.ngtc; i++)
4192         {
4193             T   = std::max(T, ir->opts.ref_t[i]);
4194             tau = std::max(tau, ir->opts.tau_t[i]);
4195         }
4196         if (T > 0)
4197         {
4198             /* This is a worst case estimate of the temperature error,
4199              * assuming perfect buffer estimation and no cancelation
4200              * of errors. The factor 0.5 is because energy distributes
4201              * equally over Ekin and Epot.
4202              */
4203             max_T_error = 0.5 * tau * ir->verletbuf_tol / (nrdf_at * BOLTZ * T);
4204             if (max_T_error > T_error_warn)
4205             {
4206                 sprintf(warn_buf,
4207                         "With a verlet-buffer-tolerance of %g kJ/mol/ps, a reference temperature "
4208                         "of %g and a tau_t of %g, your temperature might be off by up to %.1f%%. "
4209                         "To ensure the error is below %.1f%%, decrease verlet-buffer-tolerance to "
4210                         "%.0e or decrease tau_t.",
4211                         ir->verletbuf_tol, T, tau, 100 * max_T_error, 100 * T_error_suggest,
4212                         ir->verletbuf_tol * T_error_suggest / max_T_error);
4213                 warning(wi, warn_buf);
4214             }
4215         }
4216     }
4217
4218     if (ETC_ANDERSEN(ir->etc))
4219     {
4220         int i;
4221
4222         for (i = 0; i < ir->opts.ngtc; i++)
4223         {
4224             sprintf(err_buf,
4225                     "all tau_t must currently be equal using Andersen temperature control, "
4226                     "violated for group %d",
4227                     i);
4228             CHECK(ir->opts.tau_t[0] != ir->opts.tau_t[i]);
4229             sprintf(err_buf,
4230                     "all tau_t must be positive using Andersen temperature control, "
4231                     "tau_t[%d]=%10.6f",
4232                     i, ir->opts.tau_t[i]);
4233             CHECK(ir->opts.tau_t[i] < 0);
4234         }
4235
4236         if (ir->etc == etcANDERSENMASSIVE && ir->comm_mode != ecmNO)
4237         {
4238             for (i = 0; i < ir->opts.ngtc; i++)
4239             {
4240                 int nsteps = gmx::roundToInt(ir->opts.tau_t[i] / ir->delta_t);
4241                 sprintf(err_buf,
4242                         "tau_t/delta_t for group %d for temperature control method %s must be a "
4243                         "multiple of nstcomm (%d), as velocities of atoms in coupled groups are "
4244                         "randomized every time step. The input tau_t (%8.3f) leads to %d steps per "
4245                         "randomization",
4246                         i, etcoupl_names[ir->etc], ir->nstcomm, ir->opts.tau_t[i], nsteps);
4247                 CHECK(nsteps % ir->nstcomm != 0);
4248             }
4249         }
4250     }
4251
4252     if (EI_DYNAMICS(ir->eI) && !EI_SD(ir->eI) && ir->eI != eiBD && ir->comm_mode == ecmNO
4253         && !(absolute_reference(ir, sys, FALSE, AbsRef) || ir->nsteps <= 10) && !ETC_ANDERSEN(ir->etc))
4254     {
4255         warning(wi,
4256                 "You are not using center of mass motion removal (mdp option comm-mode), numerical "
4257                 "rounding errors can lead to build up of kinetic energy of the center of mass");
4258     }
4259
4260     if (ir->epc == epcPARRINELLORAHMAN && ir->etc == etcNOSEHOOVER)
4261     {
4262         real tau_t_max = 0;
4263         for (int g = 0; g < ir->opts.ngtc; g++)
4264         {
4265             tau_t_max = std::max(tau_t_max, ir->opts.tau_t[g]);
4266         }
4267         if (ir->tau_p < 1.9 * tau_t_max)
4268         {
4269             std::string message = gmx::formatString(
4270                     "With %s T-coupling and %s p-coupling, "
4271                     "%s (%g) should be at least twice as large as %s (%g) to avoid resonances",
4272                     etcoupl_names[ir->etc], epcoupl_names[ir->epc], "tau-p", ir->tau_p, "tau-t",
4273                     tau_t_max);
4274             warning(wi, message.c_str());
4275         }
4276     }
4277
4278     /* Check for pressure coupling with absolute position restraints */
4279     if (ir->epc != epcNO && ir->refcoord_scaling == erscNO)
4280     {
4281         absolute_reference(ir, sys, TRUE, AbsRef);
4282         {
4283             for (m = 0; m < DIM; m++)
4284             {
4285                 if (AbsRef[m] && norm2(ir->compress[m]) > 0)
4286                 {
4287                     warning(wi,
4288                             "You are using pressure coupling with absolute position restraints, "
4289                             "this will give artifacts. Use the refcoord_scaling option.");
4290                     break;
4291                 }
4292             }
4293         }
4294     }
4295
4296     bCharge = FALSE;
4297     aloopb  = gmx_mtop_atomloop_block_init(sys);
4298     const t_atom* atom;
4299     while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
4300     {
4301         if (atom->q != 0 || atom->qB != 0)
4302         {
4303             bCharge = TRUE;
4304         }
4305     }
4306
4307     if (!bCharge)
4308     {
4309         if (EEL_FULL(ir->coulombtype))
4310         {
4311             sprintf(err_buf,
4312                     "You are using full electrostatics treatment %s for a system without charges.\n"
4313                     "This costs a lot of performance for just processing zeros, consider using %s "
4314                     "instead.\n",
4315                     EELTYPE(ir->coulombtype), EELTYPE(eelCUT));
4316             warning(wi, err_buf);
4317         }
4318     }
4319     else
4320     {
4321         if (ir->coulombtype == eelCUT && ir->rcoulomb > 0)
4322         {
4323             sprintf(err_buf,
4324                     "You are using a plain Coulomb cut-off, which might produce artifacts.\n"
4325                     "You might want to consider using %s electrostatics.\n",
4326                     EELTYPE(eelPME));
4327             warning_note(wi, err_buf);
4328         }
4329     }
4330
4331     /* Check if combination rules used in LJ-PME are the same as in the force field */
4332     if (EVDW_PME(ir->vdwtype))
4333     {
4334         check_combination_rules(ir, sys, wi);
4335     }
4336
4337     /* Generalized reaction field */
4338     if (ir->coulombtype == eelGRF_NOTUSED)
4339     {
4340         warning_error(wi,
4341                       "Generalized reaction-field electrostatics is no longer supported. "
4342                       "You can use normal reaction-field instead and compute the reaction-field "
4343                       "constant by hand.");
4344     }
4345
4346     bAcc = FALSE;
4347     for (int i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4348     {
4349         for (m = 0; (m < DIM); m++)
4350         {
4351             if (fabs(ir->opts.acc[i][m]) > 1e-6)
4352             {
4353                 bAcc = TRUE;
4354             }
4355         }
4356     }
4357     if (bAcc)
4358     {
4359         clear_rvec(acc);
4360         snew(mgrp, sys->groups.groups[SimulationAtomGroupType::Acceleration].size());
4361         for (const AtomProxy atomP : AtomRange(*sys))
4362         {
4363             const t_atom& local = atomP.atom();
4364             int           i     = atomP.globalAtomNumber();
4365             mgrp[getGroupType(sys->groups, SimulationAtomGroupType::Acceleration, i)] += local.m;
4366         }
4367         mt = 0.0;
4368         for (i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4369         {
4370             for (m = 0; (m < DIM); m++)
4371             {
4372                 acc[m] += ir->opts.acc[i][m] * mgrp[i];
4373             }
4374             mt += mgrp[i];
4375         }
4376         for (m = 0; (m < DIM); m++)
4377         {
4378             if (fabs(acc[m]) > 1e-6)
4379             {
4380                 const char* dim[DIM] = { "X", "Y", "Z" };
4381                 fprintf(stderr, "Net Acceleration in %s direction, will %s be corrected\n", dim[m],
4382                         ir->nstcomm != 0 ? "" : "not");
4383                 if (ir->nstcomm != 0 && m < ndof_com(ir))
4384                 {
4385                     acc[m] /= mt;
4386                     for (i = 0;
4387                          (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4388                     {
4389                         ir->opts.acc[i][m] -= acc[m];
4390                     }
4391                 }
4392             }
4393         }
4394         sfree(mgrp);
4395     }
4396
4397     if (ir->efep != efepNO && ir->fepvals->sc_alpha != 0
4398         && !gmx_within_tol(sys->ffparams.reppow, 12.0, 10 * GMX_DOUBLE_EPS))
4399     {
4400         gmx_fatal(FARGS, "Soft-core interactions are only supported with VdW repulsion power 12");
4401     }
4402
4403     if (ir->bPull)
4404     {
4405         bool bWarned;
4406
4407         bWarned = FALSE;
4408         for (i = 0; i < ir->pull->ncoord && !bWarned; i++)
4409         {
4410             if (ir->pull->coord[i].group[0] == 0 || ir->pull->coord[i].group[1] == 0)
4411             {
4412                 absolute_reference(ir, sys, FALSE, AbsRef);
4413                 for (m = 0; m < DIM; m++)
4414                 {
4415                     if (ir->pull->coord[i].dim[m] && !AbsRef[m])
4416                     {
4417                         warning(wi,
4418                                 "You are using an absolute reference for pulling, but the rest of "
4419                                 "the system does not have an absolute reference. This will lead to "
4420                                 "artifacts.");
4421                         bWarned = TRUE;
4422                         break;
4423                     }
4424                 }
4425             }
4426         }
4427
4428         for (i = 0; i < 3; i++)
4429         {
4430             for (m = 0; m <= i; m++)
4431             {
4432                 if ((ir->epc != epcNO && ir->compress[i][m] != 0) || ir->deform[i][m] != 0)
4433                 {
4434                     for (c = 0; c < ir->pull->ncoord; c++)
4435                     {
4436                         if (ir->pull->coord[c].eGeom == epullgDIRPBC && ir->pull->coord[c].vec[m] != 0)
4437                         {
4438                             gmx_fatal(FARGS,
4439                                       "Can not have dynamic box while using pull geometry '%s' "
4440                                       "(dim %c)",
4441                                       EPULLGEOM(ir->pull->coord[c].eGeom), 'x' + m);
4442                         }
4443                     }
4444                 }
4445             }
4446         }
4447     }
4448
4449     check_disre(sys);
4450 }
4451
4452 void double_check(t_inputrec* ir, matrix box, bool bHasNormalConstraints, bool bHasAnyConstraints, warninp_t wi)
4453 {
4454     char        warn_buf[STRLEN];
4455     const char* ptr;
4456
4457     ptr = check_box(ir->ePBC, box);
4458     if (ptr)
4459     {
4460         warning_error(wi, ptr);
4461     }
4462
4463     if (bHasNormalConstraints && ir->eConstrAlg == econtSHAKE)
4464     {
4465         if (ir->shake_tol <= 0.0)
4466         {
4467             sprintf(warn_buf, "ERROR: shake-tol must be > 0 instead of %g\n", ir->shake_tol);
4468             warning_error(wi, warn_buf);
4469         }
4470     }
4471
4472     if ((ir->eConstrAlg == econtLINCS) && bHasNormalConstraints)
4473     {
4474         /* If we have Lincs constraints: */
4475         if (ir->eI == eiMD && ir->etc == etcNO && ir->eConstrAlg == econtLINCS && ir->nLincsIter == 1)
4476         {
4477             sprintf(warn_buf,
4478                     "For energy conservation with LINCS, lincs_iter should be 2 or larger.\n");
4479             warning_note(wi, warn_buf);
4480         }
4481
4482         if ((ir->eI == eiCG || ir->eI == eiLBFGS) && (ir->nProjOrder < 8))
4483         {
4484             sprintf(warn_buf,
4485                     "For accurate %s with LINCS constraints, lincs-order should be 8 or more.",
4486                     ei_names[ir->eI]);
4487             warning_note(wi, warn_buf);
4488         }
4489         if (ir->epc == epcMTTK)
4490         {
4491             warning_error(wi, "MTTK not compatible with lincs -- use shake instead.");
4492         }
4493     }
4494
4495     if (bHasAnyConstraints && ir->epc == epcMTTK)
4496     {
4497         warning_error(wi, "Constraints are not implemented with MTTK pressure control.");
4498     }
4499
4500     if (ir->LincsWarnAngle > 90.0)
4501     {
4502         sprintf(warn_buf, "lincs-warnangle can not be larger than 90 degrees, setting it to 90.\n");
4503         warning(wi, warn_buf);
4504         ir->LincsWarnAngle = 90.0;
4505     }
4506
4507     if (ir->ePBC != epbcNONE)
4508     {
4509         if (ir->nstlist == 0)
4510         {
4511             warning(wi,
4512                     "With nstlist=0 atoms are only put into the box at step 0, therefore drifting "
4513                     "atoms might cause the simulation to crash.");
4514         }
4515         if (gmx::square(ir->rlist) >= max_cutoff2(ir->ePBC, box))
4516         {
4517             sprintf(warn_buf,
4518                     "ERROR: The cut-off length is longer than half the shortest box vector or "
4519                     "longer than the smallest box diagonal element. Increase the box size or "
4520                     "decrease rlist.\n");
4521             warning_error(wi, warn_buf);
4522         }
4523     }
4524 }