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