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