Separate AWH parameter reading and checking
[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, "QMMM is currently not supported");
1398         if (!EI_DYNAMICS(ir->eI))
1399         {
1400             char buf[STRLEN];
1401             sprintf(buf, "QMMM is only supported with dynamics, not with integrator %s", ei_names[ir->eI]);
1402             warning_error(wi, buf);
1403         }
1404     }
1405
1406     if (ir->bAdress)
1407     {
1408         gmx_fatal(FARGS, "AdResS simulations are no longer supported");
1409     }
1410 }
1411
1412 /* interpret a number of doubles from a string and put them in an array,
1413    after allocating space for them.
1414    str = the input string
1415    n = the (pre-allocated) number of doubles read
1416    r = the output array of doubles. */
1417 static void parse_n_real(char* str, int* n, real** r, warninp_t wi)
1418 {
1419     auto values = gmx::splitString(str);
1420     *n          = values.size();
1421
1422     snew(*r, *n);
1423     for (int i = 0; i < *n; i++)
1424     {
1425         try
1426         {
1427             (*r)[i] = gmx::fromString<real>(values[i]);
1428         }
1429         catch (gmx::GromacsException&)
1430         {
1431             warning_error(wi, "Invalid value " + values[i]
1432                                       + " in string in mdp file. Expected a real number.");
1433         }
1434     }
1435 }
1436
1437
1438 static void do_fep_params(t_inputrec* ir, char fep_lambda[][STRLEN], char weights[STRLEN], warninp_t wi)
1439 {
1440
1441     int         i, j, max_n_lambda, nweights, nfep[efptNR];
1442     t_lambda*   fep    = ir->fepvals;
1443     t_expanded* expand = ir->expandedvals;
1444     real**      count_fep_lambdas;
1445     bool        bOneLambda = TRUE;
1446
1447     snew(count_fep_lambdas, efptNR);
1448
1449     /* FEP input processing */
1450     /* first, identify the number of lambda values for each type.
1451        All that are nonzero must have the same number */
1452
1453     for (i = 0; i < efptNR; i++)
1454     {
1455         parse_n_real(fep_lambda[i], &(nfep[i]), &(count_fep_lambdas[i]), wi);
1456     }
1457
1458     /* now, determine the number of components.  All must be either zero, or equal. */
1459
1460     max_n_lambda = 0;
1461     for (i = 0; i < efptNR; i++)
1462     {
1463         if (nfep[i] > max_n_lambda)
1464         {
1465             max_n_lambda = nfep[i]; /* here's a nonzero one.  All of them
1466                                        must have the same number if its not zero.*/
1467             break;
1468         }
1469     }
1470
1471     for (i = 0; i < efptNR; i++)
1472     {
1473         if (nfep[i] == 0)
1474         {
1475             ir->fepvals->separate_dvdl[i] = FALSE;
1476         }
1477         else if (nfep[i] == max_n_lambda)
1478         {
1479             if (i != efptTEMPERATURE) /* we treat this differently -- not really a reason to compute
1480                                          the derivative with respect to the temperature currently */
1481             {
1482                 ir->fepvals->separate_dvdl[i] = TRUE;
1483             }
1484         }
1485         else
1486         {
1487             gmx_fatal(FARGS,
1488                       "Number of lambdas (%d) for FEP type %s not equal to number of other types "
1489                       "(%d)",
1490                       nfep[i], efpt_names[i], max_n_lambda);
1491         }
1492     }
1493     /* we don't print out dhdl if the temperature is changing, since we can't correctly define dhdl in this case */
1494     ir->fepvals->separate_dvdl[efptTEMPERATURE] = FALSE;
1495
1496     /* the number of lambdas is the number we've read in, which is either zero
1497        or the same for all */
1498     fep->n_lambda = max_n_lambda;
1499
1500     /* allocate space for the array of lambda values */
1501     snew(fep->all_lambda, efptNR);
1502     /* if init_lambda is defined, we need to set lambda */
1503     if ((fep->init_lambda > 0) && (fep->n_lambda == 0))
1504     {
1505         ir->fepvals->separate_dvdl[efptFEP] = TRUE;
1506     }
1507     /* otherwise allocate the space for all of the lambdas, and transfer the data */
1508     for (i = 0; i < efptNR; i++)
1509     {
1510         snew(fep->all_lambda[i], fep->n_lambda);
1511         if (nfep[i] > 0) /* if it's zero, then the count_fep_lambda arrays
1512                             are zero */
1513         {
1514             for (j = 0; j < fep->n_lambda; j++)
1515             {
1516                 fep->all_lambda[i][j] = static_cast<double>(count_fep_lambdas[i][j]);
1517             }
1518             sfree(count_fep_lambdas[i]);
1519         }
1520     }
1521     sfree(count_fep_lambdas);
1522
1523     /* "fep-vals" is either zero or the full number. If zero, we'll need to define fep-lambdas for
1524        internal bookkeeping -- for now, init_lambda */
1525
1526     if ((nfep[efptFEP] == 0) && (fep->init_lambda >= 0))
1527     {
1528         for (i = 0; i < fep->n_lambda; i++)
1529         {
1530             fep->all_lambda[efptFEP][i] = fep->init_lambda;
1531         }
1532     }
1533
1534     /* check to see if only a single component lambda is defined, and soft core is defined.
1535        In this case, turn on coulomb soft core */
1536
1537     if (max_n_lambda == 0)
1538     {
1539         bOneLambda = TRUE;
1540     }
1541     else
1542     {
1543         for (i = 0; i < efptNR; i++)
1544         {
1545             if ((nfep[i] != 0) && (i != efptFEP))
1546             {
1547                 bOneLambda = FALSE;
1548             }
1549         }
1550     }
1551     if ((bOneLambda) && (fep->sc_alpha > 0))
1552     {
1553         fep->bScCoul = TRUE;
1554     }
1555
1556     /* Fill in the others with the efptFEP if they are not explicitly
1557        specified (i.e. nfep[i] == 0).  This means if fep is not defined,
1558        they are all zero. */
1559
1560     for (i = 0; i < efptNR; i++)
1561     {
1562         if ((nfep[i] == 0) && (i != efptFEP))
1563         {
1564             for (j = 0; j < fep->n_lambda; j++)
1565             {
1566                 fep->all_lambda[i][j] = fep->all_lambda[efptFEP][j];
1567             }
1568         }
1569     }
1570
1571
1572     /* now read in the weights */
1573     parse_n_real(weights, &nweights, &(expand->init_lambda_weights), wi);
1574     if (nweights == 0)
1575     {
1576         snew(expand->init_lambda_weights, fep->n_lambda); /* initialize to zero */
1577     }
1578     else if (nweights != fep->n_lambda)
1579     {
1580         gmx_fatal(FARGS, "Number of weights (%d) is not equal to number of lambda values (%d)",
1581                   nweights, fep->n_lambda);
1582     }
1583     if ((expand->nstexpanded < 0) && (ir->efep != efepNO))
1584     {
1585         expand->nstexpanded = fep->nstdhdl;
1586         /* if you don't specify nstexpanded when doing expanded ensemble free energy calcs, it is set to nstdhdl */
1587     }
1588 }
1589
1590
1591 static void do_simtemp_params(t_inputrec* ir)
1592 {
1593
1594     snew(ir->simtempvals->temperatures, ir->fepvals->n_lambda);
1595     GetSimTemps(ir->fepvals->n_lambda, ir->simtempvals, ir->fepvals->all_lambda[efptTEMPERATURE]);
1596 }
1597
1598 static void convertYesNos(warninp_t /*wi*/,
1599                           gmx::ArrayRef<const std::string> inputs,
1600                           const char* /*name*/,
1601                           gmx_bool* outputs)
1602 {
1603     int i = 0;
1604     for (const auto& input : inputs)
1605     {
1606         outputs[i] = gmx::equalCaseInsensitive(input, "Y", 1);
1607         ++i;
1608     }
1609 }
1610
1611 template<typename T>
1612 void convertInts(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, T* outputs)
1613 {
1614     int i = 0;
1615     for (const auto& input : inputs)
1616     {
1617         try
1618         {
1619             outputs[i] = gmx::fromStdString<T>(input);
1620         }
1621         catch (gmx::GromacsException&)
1622         {
1623             auto message = gmx::formatString(
1624                     "Invalid value for mdp option %s. %s should only consist of integers separated "
1625                     "by spaces.",
1626                     name, name);
1627             warning_error(wi, message);
1628         }
1629         ++i;
1630     }
1631 }
1632
1633 static void convertReals(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, real* outputs)
1634 {
1635     int i = 0;
1636     for (const auto& input : inputs)
1637     {
1638         try
1639         {
1640             outputs[i] = gmx::fromString<real>(input);
1641         }
1642         catch (gmx::GromacsException&)
1643         {
1644             auto message = gmx::formatString(
1645                     "Invalid value for mdp option %s. %s should only consist of real numbers "
1646                     "separated by spaces.",
1647                     name, name);
1648             warning_error(wi, message);
1649         }
1650         ++i;
1651     }
1652 }
1653
1654 static void convertRvecs(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, rvec* outputs)
1655 {
1656     int i = 0, d = 0;
1657     for (const auto& input : inputs)
1658     {
1659         try
1660         {
1661             outputs[i][d] = gmx::fromString<real>(input);
1662         }
1663         catch (gmx::GromacsException&)
1664         {
1665             auto message = gmx::formatString(
1666                     "Invalid value for mdp option %s. %s should only consist of real numbers "
1667                     "separated by spaces.",
1668                     name, name);
1669             warning_error(wi, message);
1670         }
1671         ++d;
1672         if (d == DIM)
1673         {
1674             d = 0;
1675             ++i;
1676         }
1677     }
1678 }
1679
1680 static void do_wall_params(t_inputrec* ir, char* wall_atomtype, char* wall_density, t_gromppopts* opts, warninp_t wi)
1681 {
1682     opts->wall_atomtype[0] = nullptr;
1683     opts->wall_atomtype[1] = nullptr;
1684
1685     ir->wall_atomtype[0] = -1;
1686     ir->wall_atomtype[1] = -1;
1687     ir->wall_density[0]  = 0;
1688     ir->wall_density[1]  = 0;
1689
1690     if (ir->nwall > 0)
1691     {
1692         auto wallAtomTypes = gmx::splitString(wall_atomtype);
1693         if (wallAtomTypes.size() != size_t(ir->nwall))
1694         {
1695             gmx_fatal(FARGS, "Expected %d elements for wall_atomtype, found %zu", ir->nwall,
1696                       wallAtomTypes.size());
1697         }
1698         for (int i = 0; i < ir->nwall; i++)
1699         {
1700             opts->wall_atomtype[i] = gmx_strdup(wallAtomTypes[i].c_str());
1701         }
1702
1703         if (ir->wall_type == ewt93 || ir->wall_type == ewt104)
1704         {
1705             auto wallDensity = gmx::splitString(wall_density);
1706             if (wallDensity.size() != size_t(ir->nwall))
1707             {
1708                 gmx_fatal(FARGS, "Expected %d elements for wall-density, found %zu", ir->nwall,
1709                           wallDensity.size());
1710             }
1711             convertReals(wi, wallDensity, "wall-density", ir->wall_density);
1712             for (int i = 0; i < ir->nwall; i++)
1713             {
1714                 if (ir->wall_density[i] <= 0)
1715                 {
1716                     gmx_fatal(FARGS, "wall-density[%d] = %f\n", i, ir->wall_density[i]);
1717                 }
1718             }
1719         }
1720     }
1721 }
1722
1723 static void add_wall_energrps(SimulationGroups* groups, int nwall, t_symtab* symtab)
1724 {
1725     if (nwall > 0)
1726     {
1727         AtomGroupIndices* grps = &(groups->groups[SimulationAtomGroupType::EnergyOutput]);
1728         for (int i = 0; i < nwall; i++)
1729         {
1730             groups->groupNames.emplace_back(put_symtab(symtab, gmx::formatString("wall%d", i).c_str()));
1731             grps->emplace_back(groups->groupNames.size() - 1);
1732         }
1733     }
1734 }
1735
1736 static void read_expandedparams(std::vector<t_inpfile>* inp, t_expanded* expand, warninp_t wi)
1737 {
1738     /* read expanded ensemble parameters */
1739     printStringNewline(inp, "expanded ensemble variables");
1740     expand->nstexpanded    = get_eint(inp, "nstexpanded", -1, wi);
1741     expand->elamstats      = get_eeenum(inp, "lmc-stats", elamstats_names, wi);
1742     expand->elmcmove       = get_eeenum(inp, "lmc-move", elmcmove_names, wi);
1743     expand->elmceq         = get_eeenum(inp, "lmc-weights-equil", elmceq_names, wi);
1744     expand->equil_n_at_lam = get_eint(inp, "weight-equil-number-all-lambda", -1, wi);
1745     expand->equil_samples  = get_eint(inp, "weight-equil-number-samples", -1, wi);
1746     expand->equil_steps    = get_eint(inp, "weight-equil-number-steps", -1, wi);
1747     expand->equil_wl_delta = get_ereal(inp, "weight-equil-wl-delta", -1, wi);
1748     expand->equil_ratio    = get_ereal(inp, "weight-equil-count-ratio", -1, wi);
1749     printStringNewline(inp, "Seed for Monte Carlo in lambda space");
1750     expand->lmc_seed          = get_eint(inp, "lmc-seed", -1, wi);
1751     expand->mc_temp           = get_ereal(inp, "mc-temperature", -1, wi);
1752     expand->lmc_repeats       = get_eint(inp, "lmc-repeats", 1, wi);
1753     expand->gibbsdeltalam     = get_eint(inp, "lmc-gibbsdelta", -1, wi);
1754     expand->lmc_forced_nstart = get_eint(inp, "lmc-forced-nstart", 0, wi);
1755     expand->bSymmetrizedTMatrix =
1756             (get_eeenum(inp, "symmetrized-transition-matrix", yesno_names, wi) != 0);
1757     expand->nstTij        = get_eint(inp, "nst-transition-matrix", -1, wi);
1758     expand->minvarmin     = get_eint(inp, "mininum-var-min", 100, wi); /*default is reasonable */
1759     expand->c_range       = get_eint(inp, "weight-c-range", 0, wi);    /* default is just C=0 */
1760     expand->wl_scale      = get_ereal(inp, "wl-scale", 0.8, wi);
1761     expand->wl_ratio      = get_ereal(inp, "wl-ratio", 0.8, wi);
1762     expand->init_wl_delta = get_ereal(inp, "init-wl-delta", 1.0, wi);
1763     expand->bWLoneovert   = (get_eeenum(inp, "wl-oneovert", yesno_names, wi) != 0);
1764 }
1765
1766 /*! \brief Return whether an end state with the given coupling-lambda
1767  * value describes fully-interacting VDW.
1768  *
1769  * \param[in]  couple_lambda_value  Enumeration ecouplam value describing the end state
1770  * \return                          Whether VDW is on (i.e. the user chose vdw or vdw-q in the .mdp file)
1771  */
1772 static bool couple_lambda_has_vdw_on(int couple_lambda_value)
1773 {
1774     return (couple_lambda_value == ecouplamVDW || couple_lambda_value == ecouplamVDWQ);
1775 }
1776
1777 namespace
1778 {
1779
1780 class MdpErrorHandler : public gmx::IKeyValueTreeErrorHandler
1781 {
1782 public:
1783     explicit MdpErrorHandler(warninp_t wi) : wi_(wi), mapping_(nullptr) {}
1784
1785     void setBackMapping(const gmx::IKeyValueTreeBackMapping& mapping) { mapping_ = &mapping; }
1786
1787     bool onError(gmx::UserInputError* ex, const gmx::KeyValueTreePath& context) override
1788     {
1789         ex->prependContext(
1790                 gmx::formatString("Error in mdp option \"%s\":", getOptionName(context).c_str()));
1791         std::string message = gmx::formatExceptionMessageToString(*ex);
1792         warning_error(wi_, message.c_str());
1793         return true;
1794     }
1795
1796 private:
1797     std::string getOptionName(const gmx::KeyValueTreePath& context)
1798     {
1799         if (mapping_ != nullptr)
1800         {
1801             gmx::KeyValueTreePath path = mapping_->originalPath(context);
1802             GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
1803             return path[0];
1804         }
1805         GMX_ASSERT(context.size() == 1, "Inconsistent context for mdp option parsing");
1806         return context[0];
1807     }
1808
1809     warninp_t                            wi_;
1810     const gmx::IKeyValueTreeBackMapping* mapping_;
1811 };
1812
1813 } // namespace
1814
1815 void get_ir(const char*     mdparin,
1816             const char*     mdparout,
1817             gmx::MDModules* mdModules,
1818             t_inputrec*     ir,
1819             t_gromppopts*   opts,
1820             WriteMdpHeader  writeMdpHeader,
1821             warninp_t       wi)
1822 {
1823     char*       dumstr[2];
1824     double      dumdub[2][6];
1825     int         i, j, m;
1826     char        warn_buf[STRLEN];
1827     t_lambda*   fep    = ir->fepvals;
1828     t_expanded* expand = ir->expandedvals;
1829
1830     const char* no_names[] = { "no", nullptr };
1831
1832     init_inputrec_strings();
1833     gmx::TextInputFile     stream(mdparin);
1834     std::vector<t_inpfile> inp = read_inpfile(&stream, mdparin, wi);
1835
1836     snew(dumstr[0], STRLEN);
1837     snew(dumstr[1], STRLEN);
1838
1839     /* ignore the following deprecated commands */
1840     replace_inp_entry(inp, "title", nullptr);
1841     replace_inp_entry(inp, "cpp", nullptr);
1842     replace_inp_entry(inp, "domain-decomposition", nullptr);
1843     replace_inp_entry(inp, "andersen-seed", nullptr);
1844     replace_inp_entry(inp, "dihre", nullptr);
1845     replace_inp_entry(inp, "dihre-fc", nullptr);
1846     replace_inp_entry(inp, "dihre-tau", nullptr);
1847     replace_inp_entry(inp, "nstdihreout", nullptr);
1848     replace_inp_entry(inp, "nstcheckpoint", nullptr);
1849     replace_inp_entry(inp, "optimize-fft", nullptr);
1850     replace_inp_entry(inp, "adress_type", nullptr);
1851     replace_inp_entry(inp, "adress_const_wf", nullptr);
1852     replace_inp_entry(inp, "adress_ex_width", nullptr);
1853     replace_inp_entry(inp, "adress_hy_width", nullptr);
1854     replace_inp_entry(inp, "adress_ex_forcecap", nullptr);
1855     replace_inp_entry(inp, "adress_interface_correction", nullptr);
1856     replace_inp_entry(inp, "adress_site", nullptr);
1857     replace_inp_entry(inp, "adress_reference_coords", nullptr);
1858     replace_inp_entry(inp, "adress_tf_grp_names", nullptr);
1859     replace_inp_entry(inp, "adress_cg_grp_names", nullptr);
1860     replace_inp_entry(inp, "adress_do_hybridpairs", nullptr);
1861     replace_inp_entry(inp, "rlistlong", nullptr);
1862     replace_inp_entry(inp, "nstcalclr", nullptr);
1863     replace_inp_entry(inp, "pull-print-com2", nullptr);
1864     replace_inp_entry(inp, "gb-algorithm", nullptr);
1865     replace_inp_entry(inp, "nstgbradii", nullptr);
1866     replace_inp_entry(inp, "rgbradii", nullptr);
1867     replace_inp_entry(inp, "gb-epsilon-solvent", nullptr);
1868     replace_inp_entry(inp, "gb-saltconc", nullptr);
1869     replace_inp_entry(inp, "gb-obc-alpha", nullptr);
1870     replace_inp_entry(inp, "gb-obc-beta", nullptr);
1871     replace_inp_entry(inp, "gb-obc-gamma", nullptr);
1872     replace_inp_entry(inp, "gb-dielectric-offset", nullptr);
1873     replace_inp_entry(inp, "sa-algorithm", nullptr);
1874     replace_inp_entry(inp, "sa-surface-tension", nullptr);
1875     replace_inp_entry(inp, "ns-type", nullptr);
1876
1877     /* replace the following commands with the clearer new versions*/
1878     replace_inp_entry(inp, "unconstrained-start", "continuation");
1879     replace_inp_entry(inp, "foreign-lambda", "fep-lambdas");
1880     replace_inp_entry(inp, "verlet-buffer-drift", "verlet-buffer-tolerance");
1881     replace_inp_entry(inp, "nstxtcout", "nstxout-compressed");
1882     replace_inp_entry(inp, "xtc-grps", "compressed-x-grps");
1883     replace_inp_entry(inp, "xtc-precision", "compressed-x-precision");
1884     replace_inp_entry(inp, "pull-print-com1", "pull-print-com");
1885
1886     printStringNewline(&inp, "VARIOUS PREPROCESSING OPTIONS");
1887     printStringNoNewline(&inp, "Preprocessor information: use cpp syntax.");
1888     printStringNoNewline(&inp, "e.g.: -I/home/joe/doe -I/home/mary/roe");
1889     setStringEntry(&inp, "include", opts->include, nullptr);
1890     printStringNoNewline(
1891             &inp, "e.g.: -DPOSRES -DFLEXIBLE (note these variable names are case sensitive)");
1892     setStringEntry(&inp, "define", opts->define, nullptr);
1893
1894     printStringNewline(&inp, "RUN CONTROL PARAMETERS");
1895     ir->eI = get_eeenum(&inp, "integrator", ei_names, wi);
1896     printStringNoNewline(&inp, "Start time and timestep in ps");
1897     ir->init_t  = get_ereal(&inp, "tinit", 0.0, wi);
1898     ir->delta_t = get_ereal(&inp, "dt", 0.001, wi);
1899     ir->nsteps  = get_eint64(&inp, "nsteps", 0, wi);
1900     printStringNoNewline(&inp, "For exact run continuation or redoing part of a run");
1901     ir->init_step = get_eint64(&inp, "init-step", 0, wi);
1902     printStringNoNewline(
1903             &inp, "Part index is updated automatically on checkpointing (keeps files separate)");
1904     ir->simulation_part = get_eint(&inp, "simulation-part", 1, wi);
1905     printStringNoNewline(&inp, "mode for center of mass motion removal");
1906     ir->comm_mode = get_eeenum(&inp, "comm-mode", ecm_names, wi);
1907     printStringNoNewline(&inp, "number of steps for center of mass motion removal");
1908     ir->nstcomm = get_eint(&inp, "nstcomm", 100, wi);
1909     printStringNoNewline(&inp, "group(s) for center of mass motion removal");
1910     setStringEntry(&inp, "comm-grps", is->vcm, nullptr);
1911
1912     printStringNewline(&inp, "LANGEVIN DYNAMICS OPTIONS");
1913     printStringNoNewline(&inp, "Friction coefficient (amu/ps) and random seed");
1914     ir->bd_fric = get_ereal(&inp, "bd-fric", 0.0, wi);
1915     ir->ld_seed = get_eint64(&inp, "ld-seed", -1, wi);
1916
1917     /* Em stuff */
1918     printStringNewline(&inp, "ENERGY MINIMIZATION OPTIONS");
1919     printStringNoNewline(&inp, "Force tolerance and initial step-size");
1920     ir->em_tol      = get_ereal(&inp, "emtol", 10.0, wi);
1921     ir->em_stepsize = get_ereal(&inp, "emstep", 0.01, wi);
1922     printStringNoNewline(&inp, "Max number of iterations in relax-shells");
1923     ir->niter = get_eint(&inp, "niter", 20, wi);
1924     printStringNoNewline(&inp, "Step size (ps^2) for minimization of flexible constraints");
1925     ir->fc_stepsize = get_ereal(&inp, "fcstep", 0, wi);
1926     printStringNoNewline(&inp, "Frequency of steepest descents steps when doing CG");
1927     ir->nstcgsteep = get_eint(&inp, "nstcgsteep", 1000, wi);
1928     ir->nbfgscorr  = get_eint(&inp, "nbfgscorr", 10, wi);
1929
1930     printStringNewline(&inp, "TEST PARTICLE INSERTION OPTIONS");
1931     ir->rtpi = get_ereal(&inp, "rtpi", 0.05, wi);
1932
1933     /* Output options */
1934     printStringNewline(&inp, "OUTPUT CONTROL OPTIONS");
1935     printStringNoNewline(&inp, "Output frequency for coords (x), velocities (v) and forces (f)");
1936     ir->nstxout = get_eint(&inp, "nstxout", 0, wi);
1937     ir->nstvout = get_eint(&inp, "nstvout", 0, wi);
1938     ir->nstfout = get_eint(&inp, "nstfout", 0, wi);
1939     printStringNoNewline(&inp, "Output frequency for energies to log file and energy file");
1940     ir->nstlog        = get_eint(&inp, "nstlog", 1000, wi);
1941     ir->nstcalcenergy = get_eint(&inp, "nstcalcenergy", 100, wi);
1942     ir->nstenergy     = get_eint(&inp, "nstenergy", 1000, wi);
1943     printStringNoNewline(&inp, "Output frequency and precision for .xtc file");
1944     ir->nstxout_compressed      = get_eint(&inp, "nstxout-compressed", 0, wi);
1945     ir->x_compression_precision = get_ereal(&inp, "compressed-x-precision", 1000.0, wi);
1946     printStringNoNewline(&inp, "This selects the subset of atoms for the compressed");
1947     printStringNoNewline(&inp, "trajectory file. You can select multiple groups. By");
1948     printStringNoNewline(&inp, "default, all atoms will be written.");
1949     setStringEntry(&inp, "compressed-x-grps", is->x_compressed_groups, nullptr);
1950     printStringNoNewline(&inp, "Selection of energy groups");
1951     setStringEntry(&inp, "energygrps", is->energy, nullptr);
1952
1953     /* Neighbor searching */
1954     printStringNewline(&inp, "NEIGHBORSEARCHING PARAMETERS");
1955     printStringNoNewline(&inp, "cut-off scheme (Verlet: particle based cut-offs)");
1956     ir->cutoff_scheme = get_eeenum(&inp, "cutoff-scheme", ecutscheme_names, wi);
1957     printStringNoNewline(&inp, "nblist update frequency");
1958     ir->nstlist = get_eint(&inp, "nstlist", 10, wi);
1959     printStringNoNewline(&inp, "Periodic boundary conditions: xyz, no, xy");
1960     // TODO This conversion should be removed when proper std:string handling will be added to get_eeenum(...), etc.
1961     std::vector<const char*> pbcTypesNamesChar;
1962     for (const auto& pbcTypeName : c_pbcTypeNames)
1963     {
1964         pbcTypesNamesChar.push_back(pbcTypeName.c_str());
1965     }
1966     ir->pbcType       = static_cast<PbcType>(get_eeenum(&inp, "pbc", pbcTypesNamesChar.data(), wi));
1967     ir->bPeriodicMols = get_eeenum(&inp, "periodic-molecules", yesno_names, wi) != 0;
1968     printStringNoNewline(&inp,
1969                          "Allowed energy error due to the Verlet buffer in kJ/mol/ps per atom,");
1970     printStringNoNewline(&inp, "a value of -1 means: use rlist");
1971     ir->verletbuf_tol = get_ereal(&inp, "verlet-buffer-tolerance", 0.005, wi);
1972     printStringNoNewline(&inp, "nblist cut-off");
1973     ir->rlist = get_ereal(&inp, "rlist", 1.0, wi);
1974     printStringNoNewline(&inp, "long-range cut-off for switched potentials");
1975
1976     /* Electrostatics */
1977     printStringNewline(&inp, "OPTIONS FOR ELECTROSTATICS AND VDW");
1978     printStringNoNewline(&inp, "Method for doing electrostatics");
1979     ir->coulombtype      = get_eeenum(&inp, "coulombtype", eel_names, wi);
1980     ir->coulomb_modifier = get_eeenum(&inp, "coulomb-modifier", eintmod_names, wi);
1981     printStringNoNewline(&inp, "cut-off lengths");
1982     ir->rcoulomb_switch = get_ereal(&inp, "rcoulomb-switch", 0.0, wi);
1983     ir->rcoulomb        = get_ereal(&inp, "rcoulomb", 1.0, wi);
1984     printStringNoNewline(&inp,
1985                          "Relative dielectric constant for the medium and the reaction field");
1986     ir->epsilon_r  = get_ereal(&inp, "epsilon-r", 1.0, wi);
1987     ir->epsilon_rf = get_ereal(&inp, "epsilon-rf", 0.0, wi);
1988     printStringNoNewline(&inp, "Method for doing Van der Waals");
1989     ir->vdwtype      = get_eeenum(&inp, "vdw-type", evdw_names, wi);
1990     ir->vdw_modifier = get_eeenum(&inp, "vdw-modifier", eintmod_names, wi);
1991     printStringNoNewline(&inp, "cut-off lengths");
1992     ir->rvdw_switch = get_ereal(&inp, "rvdw-switch", 0.0, wi);
1993     ir->rvdw        = get_ereal(&inp, "rvdw", 1.0, wi);
1994     printStringNoNewline(&inp, "Apply long range dispersion corrections for Energy and Pressure");
1995     ir->eDispCorr = get_eeenum(&inp, "DispCorr", edispc_names, wi);
1996     printStringNoNewline(&inp, "Extension of the potential lookup tables beyond the cut-off");
1997     ir->tabext = get_ereal(&inp, "table-extension", 1.0, wi);
1998     printStringNoNewline(&inp, "Separate tables between energy group pairs");
1999     setStringEntry(&inp, "energygrp-table", is->egptable, nullptr);
2000     printStringNoNewline(&inp, "Spacing for the PME/PPPM FFT grid");
2001     ir->fourier_spacing = get_ereal(&inp, "fourierspacing", 0.12, wi);
2002     printStringNoNewline(&inp, "FFT grid size, when a value is 0 fourierspacing will be used");
2003     ir->nkx = get_eint(&inp, "fourier-nx", 0, wi);
2004     ir->nky = get_eint(&inp, "fourier-ny", 0, wi);
2005     ir->nkz = get_eint(&inp, "fourier-nz", 0, wi);
2006     printStringNoNewline(&inp, "EWALD/PME/PPPM parameters");
2007     ir->pme_order              = get_eint(&inp, "pme-order", 4, wi);
2008     ir->ewald_rtol             = get_ereal(&inp, "ewald-rtol", 0.00001, wi);
2009     ir->ewald_rtol_lj          = get_ereal(&inp, "ewald-rtol-lj", 0.001, wi);
2010     ir->ljpme_combination_rule = get_eeenum(&inp, "lj-pme-comb-rule", eljpme_names, wi);
2011     ir->ewald_geometry         = get_eeenum(&inp, "ewald-geometry", eewg_names, wi);
2012     ir->epsilon_surface        = get_ereal(&inp, "epsilon-surface", 0.0, wi);
2013
2014     /* Implicit solvation is no longer supported, but we need grompp
2015        to be able to refuse old .mdp files that would have built a tpr
2016        to run it. Thus, only "no" is accepted. */
2017     ir->implicit_solvent = (get_eeenum(&inp, "implicit-solvent", no_names, wi) != 0);
2018
2019     /* Coupling stuff */
2020     printStringNewline(&inp, "OPTIONS FOR WEAK COUPLING ALGORITHMS");
2021     printStringNoNewline(&inp, "Temperature coupling");
2022     ir->etc                = get_eeenum(&inp, "tcoupl", etcoupl_names, wi);
2023     ir->nsttcouple         = get_eint(&inp, "nsttcouple", -1, wi);
2024     ir->opts.nhchainlength = get_eint(&inp, "nh-chain-length", 10, wi);
2025     ir->bPrintNHChains = (get_eeenum(&inp, "print-nose-hoover-chain-variables", yesno_names, wi) != 0);
2026     printStringNoNewline(&inp, "Groups to couple separately");
2027     setStringEntry(&inp, "tc-grps", is->tcgrps, nullptr);
2028     printStringNoNewline(&inp, "Time constant (ps) and reference temperature (K)");
2029     setStringEntry(&inp, "tau-t", is->tau_t, nullptr);
2030     setStringEntry(&inp, "ref-t", is->ref_t, nullptr);
2031     printStringNoNewline(&inp, "pressure coupling");
2032     ir->epc        = get_eeenum(&inp, "pcoupl", epcoupl_names, wi);
2033     ir->epct       = get_eeenum(&inp, "pcoupltype", epcoupltype_names, wi);
2034     ir->nstpcouple = get_eint(&inp, "nstpcouple", -1, wi);
2035     printStringNoNewline(&inp, "Time constant (ps), compressibility (1/bar) and reference P (bar)");
2036     ir->tau_p = get_ereal(&inp, "tau-p", 1.0, wi);
2037     setStringEntry(&inp, "compressibility", dumstr[0], nullptr);
2038     setStringEntry(&inp, "ref-p", dumstr[1], nullptr);
2039     printStringNoNewline(&inp, "Scaling of reference coordinates, No, All or COM");
2040     ir->refcoord_scaling = get_eeenum(&inp, "refcoord-scaling", erefscaling_names, wi);
2041
2042     /* QMMM */
2043     printStringNewline(&inp, "OPTIONS FOR QMMM calculations");
2044     ir->bQMMM = (get_eeenum(&inp, "QMMM", yesno_names, wi) != 0);
2045     printStringNoNewline(&inp, "Groups treated Quantum Mechanically");
2046     setStringEntry(&inp, "QMMM-grps", is->QMMM, nullptr);
2047     printStringNoNewline(&inp, "QM method");
2048     setStringEntry(&inp, "QMmethod", is->QMmethod, nullptr);
2049     printStringNoNewline(&inp, "QMMM scheme");
2050     ir->QMMMscheme = get_eeenum(&inp, "QMMMscheme", eQMMMscheme_names, wi);
2051     printStringNoNewline(&inp, "QM basisset");
2052     setStringEntry(&inp, "QMbasis", is->QMbasis, nullptr);
2053     printStringNoNewline(&inp, "QM charge");
2054     setStringEntry(&inp, "QMcharge", is->QMcharge, nullptr);
2055     printStringNoNewline(&inp, "QM multiplicity");
2056     setStringEntry(&inp, "QMmult", is->QMmult, nullptr);
2057     printStringNoNewline(&inp, "Surface Hopping");
2058     setStringEntry(&inp, "SH", is->bSH, nullptr);
2059     printStringNoNewline(&inp, "CAS space options");
2060     setStringEntry(&inp, "CASorbitals", is->CASorbitals, nullptr);
2061     setStringEntry(&inp, "CASelectrons", is->CASelectrons, nullptr);
2062     setStringEntry(&inp, "SAon", is->SAon, nullptr);
2063     setStringEntry(&inp, "SAoff", is->SAoff, nullptr);
2064     setStringEntry(&inp, "SAsteps", is->SAsteps, nullptr);
2065     printStringNoNewline(&inp, "Scale factor for MM charges");
2066     ir->scalefactor = get_ereal(&inp, "MMChargeScaleFactor", 1.0, wi);
2067
2068     /* Simulated annealing */
2069     printStringNewline(&inp, "SIMULATED ANNEALING");
2070     printStringNoNewline(&inp, "Type of annealing for each temperature group (no/single/periodic)");
2071     setStringEntry(&inp, "annealing", is->anneal, nullptr);
2072     printStringNoNewline(&inp,
2073                          "Number of time points to use for specifying annealing in each group");
2074     setStringEntry(&inp, "annealing-npoints", is->anneal_npoints, nullptr);
2075     printStringNoNewline(&inp, "List of times at the annealing points for each group");
2076     setStringEntry(&inp, "annealing-time", is->anneal_time, nullptr);
2077     printStringNoNewline(&inp, "Temp. at each annealing point, for each group.");
2078     setStringEntry(&inp, "annealing-temp", is->anneal_temp, nullptr);
2079
2080     /* Startup run */
2081     printStringNewline(&inp, "GENERATE VELOCITIES FOR STARTUP RUN");
2082     opts->bGenVel = (get_eeenum(&inp, "gen-vel", yesno_names, wi) != 0);
2083     opts->tempi   = get_ereal(&inp, "gen-temp", 300.0, wi);
2084     opts->seed    = get_eint(&inp, "gen-seed", -1, wi);
2085
2086     /* Shake stuff */
2087     printStringNewline(&inp, "OPTIONS FOR BONDS");
2088     opts->nshake = get_eeenum(&inp, "constraints", constraints, wi);
2089     printStringNoNewline(&inp, "Type of constraint algorithm");
2090     ir->eConstrAlg = get_eeenum(&inp, "constraint-algorithm", econstr_names, wi);
2091     printStringNoNewline(&inp, "Do not constrain the start configuration");
2092     ir->bContinuation = (get_eeenum(&inp, "continuation", yesno_names, wi) != 0);
2093     printStringNoNewline(&inp,
2094                          "Use successive overrelaxation to reduce the number of shake iterations");
2095     ir->bShakeSOR = (get_eeenum(&inp, "Shake-SOR", yesno_names, wi) != 0);
2096     printStringNoNewline(&inp, "Relative tolerance of shake");
2097     ir->shake_tol = get_ereal(&inp, "shake-tol", 0.0001, wi);
2098     printStringNoNewline(&inp, "Highest order in the expansion of the constraint coupling matrix");
2099     ir->nProjOrder = get_eint(&inp, "lincs-order", 4, wi);
2100     printStringNoNewline(&inp, "Number of iterations in the final step of LINCS. 1 is fine for");
2101     printStringNoNewline(&inp, "normal simulations, but use 2 to conserve energy in NVE runs.");
2102     printStringNoNewline(&inp, "For energy minimization with constraints it should be 4 to 8.");
2103     ir->nLincsIter = get_eint(&inp, "lincs-iter", 1, wi);
2104     printStringNoNewline(&inp, "Lincs will write a warning to the stderr if in one step a bond");
2105     printStringNoNewline(&inp, "rotates over more degrees than");
2106     ir->LincsWarnAngle = get_ereal(&inp, "lincs-warnangle", 30.0, wi);
2107     printStringNoNewline(&inp, "Convert harmonic bonds to morse potentials");
2108     opts->bMorse = (get_eeenum(&inp, "morse", yesno_names, wi) != 0);
2109
2110     /* Energy group exclusions */
2111     printStringNewline(&inp, "ENERGY GROUP EXCLUSIONS");
2112     printStringNoNewline(
2113             &inp, "Pairs of energy groups for which all non-bonded interactions are excluded");
2114     setStringEntry(&inp, "energygrp-excl", is->egpexcl, nullptr);
2115
2116     /* Walls */
2117     printStringNewline(&inp, "WALLS");
2118     printStringNoNewline(
2119             &inp, "Number of walls, type, atom types, densities and box-z scale factor for Ewald");
2120     ir->nwall         = get_eint(&inp, "nwall", 0, wi);
2121     ir->wall_type     = get_eeenum(&inp, "wall-type", ewt_names, wi);
2122     ir->wall_r_linpot = get_ereal(&inp, "wall-r-linpot", -1, wi);
2123     setStringEntry(&inp, "wall-atomtype", is->wall_atomtype, nullptr);
2124     setStringEntry(&inp, "wall-density", is->wall_density, nullptr);
2125     ir->wall_ewald_zfac = get_ereal(&inp, "wall-ewald-zfac", 3, wi);
2126
2127     /* COM pulling */
2128     printStringNewline(&inp, "COM PULLING");
2129     ir->bPull = (get_eeenum(&inp, "pull", yesno_names, wi) != 0);
2130     if (ir->bPull)
2131     {
2132         snew(ir->pull, 1);
2133         is->pull_grp = read_pullparams(&inp, ir->pull, wi);
2134     }
2135
2136     /* AWH biasing
2137        NOTE: needs COM pulling input */
2138     printStringNewline(&inp, "AWH biasing");
2139     ir->bDoAwh = (get_eeenum(&inp, "awh", yesno_names, wi) != 0);
2140     if (ir->bDoAwh)
2141     {
2142         ir->awhParams = gmx::readAwhParams(&inp, wi);
2143     }
2144
2145     /* Enforced rotation */
2146     printStringNewline(&inp, "ENFORCED ROTATION");
2147     printStringNoNewline(&inp, "Enforced rotation: No or Yes");
2148     ir->bRot = (get_eeenum(&inp, "rotation", yesno_names, wi) != 0);
2149     if (ir->bRot)
2150     {
2151         snew(ir->rot, 1);
2152         is->rot_grp = read_rotparams(&inp, ir->rot, wi);
2153     }
2154
2155     /* Interactive MD */
2156     ir->bIMD = FALSE;
2157     printStringNewline(&inp, "Group to display and/or manipulate in interactive MD session");
2158     setStringEntry(&inp, "IMD-group", is->imd_grp, nullptr);
2159     if (is->imd_grp[0] != '\0')
2160     {
2161         snew(ir->imd, 1);
2162         ir->bIMD = TRUE;
2163     }
2164
2165     /* Refinement */
2166     printStringNewline(&inp, "NMR refinement stuff");
2167     printStringNoNewline(&inp, "Distance restraints type: No, Simple or Ensemble");
2168     ir->eDisre = get_eeenum(&inp, "disre", edisre_names, wi);
2169     printStringNoNewline(
2170             &inp, "Force weighting of pairs in one distance restraint: Conservative or Equal");
2171     ir->eDisreWeighting = get_eeenum(&inp, "disre-weighting", edisreweighting_names, wi);
2172     printStringNoNewline(&inp, "Use sqrt of the time averaged times the instantaneous violation");
2173     ir->bDisreMixed = (get_eeenum(&inp, "disre-mixed", yesno_names, wi) != 0);
2174     ir->dr_fc       = get_ereal(&inp, "disre-fc", 1000.0, wi);
2175     ir->dr_tau      = get_ereal(&inp, "disre-tau", 0.0, wi);
2176     printStringNoNewline(&inp, "Output frequency for pair distances to energy file");
2177     ir->nstdisreout = get_eint(&inp, "nstdisreout", 100, wi);
2178     printStringNoNewline(&inp, "Orientation restraints: No or Yes");
2179     opts->bOrire = (get_eeenum(&inp, "orire", yesno_names, wi) != 0);
2180     printStringNoNewline(&inp, "Orientation restraints force constant and tau for time averaging");
2181     ir->orires_fc  = get_ereal(&inp, "orire-fc", 0.0, wi);
2182     ir->orires_tau = get_ereal(&inp, "orire-tau", 0.0, wi);
2183     setStringEntry(&inp, "orire-fitgrp", is->orirefitgrp, nullptr);
2184     printStringNoNewline(&inp, "Output frequency for trace(SD) and S to energy file");
2185     ir->nstorireout = get_eint(&inp, "nstorireout", 100, wi);
2186
2187     /* free energy variables */
2188     printStringNewline(&inp, "Free energy variables");
2189     ir->efep = get_eeenum(&inp, "free-energy", efep_names, wi);
2190     setStringEntry(&inp, "couple-moltype", is->couple_moltype, nullptr);
2191     opts->couple_lam0  = get_eeenum(&inp, "couple-lambda0", couple_lam, wi);
2192     opts->couple_lam1  = get_eeenum(&inp, "couple-lambda1", couple_lam, wi);
2193     opts->bCoupleIntra = (get_eeenum(&inp, "couple-intramol", yesno_names, wi) != 0);
2194
2195     fep->init_lambda = get_ereal(&inp, "init-lambda", -1, wi); /* start with -1 so
2196                                                                          we can recognize if
2197                                                                          it was not entered */
2198     fep->init_fep_state = get_eint(&inp, "init-lambda-state", -1, wi);
2199     fep->delta_lambda   = get_ereal(&inp, "delta-lambda", 0.0, wi);
2200     fep->nstdhdl        = get_eint(&inp, "nstdhdl", 50, wi);
2201     setStringEntry(&inp, "fep-lambdas", is->fep_lambda[efptFEP], nullptr);
2202     setStringEntry(&inp, "mass-lambdas", is->fep_lambda[efptMASS], nullptr);
2203     setStringEntry(&inp, "coul-lambdas", is->fep_lambda[efptCOUL], nullptr);
2204     setStringEntry(&inp, "vdw-lambdas", is->fep_lambda[efptVDW], nullptr);
2205     setStringEntry(&inp, "bonded-lambdas", is->fep_lambda[efptBONDED], nullptr);
2206     setStringEntry(&inp, "restraint-lambdas", is->fep_lambda[efptRESTRAINT], nullptr);
2207     setStringEntry(&inp, "temperature-lambdas", is->fep_lambda[efptTEMPERATURE], nullptr);
2208     fep->lambda_neighbors = get_eint(&inp, "calc-lambda-neighbors", 1, wi);
2209     setStringEntry(&inp, "init-lambda-weights", is->lambda_weights, nullptr);
2210     fep->edHdLPrintEnergy   = get_eeenum(&inp, "dhdl-print-energy", edHdLPrintEnergy_names, wi);
2211     fep->sc_alpha           = get_ereal(&inp, "sc-alpha", 0.0, wi);
2212     fep->sc_power           = get_eint(&inp, "sc-power", 1, wi);
2213     fep->sc_r_power         = get_ereal(&inp, "sc-r-power", 6.0, wi);
2214     fep->sc_sigma           = get_ereal(&inp, "sc-sigma", 0.3, wi);
2215     fep->bScCoul            = (get_eeenum(&inp, "sc-coul", yesno_names, wi) != 0);
2216     fep->dh_hist_size       = get_eint(&inp, "dh_hist_size", 0, wi);
2217     fep->dh_hist_spacing    = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
2218     fep->separate_dhdl_file = get_eeenum(&inp, "separate-dhdl-file", separate_dhdl_file_names, wi);
2219     fep->dhdl_derivatives   = get_eeenum(&inp, "dhdl-derivatives", dhdl_derivatives_names, wi);
2220     fep->dh_hist_size       = get_eint(&inp, "dh_hist_size", 0, wi);
2221     fep->dh_hist_spacing    = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
2222
2223     /* Non-equilibrium MD stuff */
2224     printStringNewline(&inp, "Non-equilibrium MD stuff");
2225     setStringEntry(&inp, "acc-grps", is->accgrps, nullptr);
2226     setStringEntry(&inp, "accelerate", is->acc, nullptr);
2227     setStringEntry(&inp, "freezegrps", is->freeze, nullptr);
2228     setStringEntry(&inp, "freezedim", is->frdim, nullptr);
2229     ir->cos_accel = get_ereal(&inp, "cos-acceleration", 0, wi);
2230     setStringEntry(&inp, "deform", is->deform, nullptr);
2231
2232     /* simulated tempering variables */
2233     printStringNewline(&inp, "simulated tempering variables");
2234     ir->bSimTemp = (get_eeenum(&inp, "simulated-tempering", yesno_names, wi) != 0);
2235     ir->simtempvals->eSimTempScale = get_eeenum(&inp, "simulated-tempering-scaling", esimtemp_names, wi);
2236     ir->simtempvals->simtemp_low  = get_ereal(&inp, "sim-temp-low", 300.0, wi);
2237     ir->simtempvals->simtemp_high = get_ereal(&inp, "sim-temp-high", 300.0, wi);
2238
2239     /* expanded ensemble variables */
2240     if (ir->efep == efepEXPANDED || ir->bSimTemp)
2241     {
2242         read_expandedparams(&inp, expand, wi);
2243     }
2244
2245     /* Electric fields */
2246     {
2247         gmx::KeyValueTreeObject      convertedValues = flatKeyValueTreeFromInpFile(inp);
2248         gmx::KeyValueTreeTransformer transform;
2249         transform.rules()->addRule().keyMatchType("/", gmx::StringCompareType::CaseAndDashInsensitive);
2250         mdModules->initMdpTransform(transform.rules());
2251         for (const auto& path : transform.mappedPaths())
2252         {
2253             GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
2254             mark_einp_set(inp, path[0].c_str());
2255         }
2256         MdpErrorHandler errorHandler(wi);
2257         auto            result = transform.transform(convertedValues, &errorHandler);
2258         ir->params             = new gmx::KeyValueTreeObject(result.object());
2259         mdModules->adjustInputrecBasedOnModules(ir);
2260         errorHandler.setBackMapping(result.backMapping());
2261         mdModules->assignOptionsToModules(*ir->params, &errorHandler);
2262     }
2263
2264     /* Ion/water position swapping ("computational electrophysiology") */
2265     printStringNewline(&inp,
2266                        "Ion/water position swapping for computational electrophysiology setups");
2267     printStringNoNewline(&inp, "Swap positions along direction: no, X, Y, Z");
2268     ir->eSwapCoords = get_eeenum(&inp, "swapcoords", eSwapTypes_names, wi);
2269     if (ir->eSwapCoords != eswapNO)
2270     {
2271         char buf[STRLEN];
2272         int  nIonTypes;
2273
2274
2275         snew(ir->swap, 1);
2276         printStringNoNewline(&inp, "Swap attempt frequency");
2277         ir->swap->nstswap = get_eint(&inp, "swap-frequency", 1, wi);
2278         printStringNoNewline(&inp, "Number of ion types to be controlled");
2279         nIonTypes = get_eint(&inp, "iontypes", 1, wi);
2280         if (nIonTypes < 1)
2281         {
2282             warning_error(wi, "You need to provide at least one ion type for position exchanges.");
2283         }
2284         ir->swap->ngrp = nIonTypes + eSwapFixedGrpNR;
2285         snew(ir->swap->grp, ir->swap->ngrp);
2286         for (i = 0; i < ir->swap->ngrp; i++)
2287         {
2288             snew(ir->swap->grp[i].molname, STRLEN);
2289         }
2290         printStringNoNewline(&inp,
2291                              "Two index groups that contain the compartment-partitioning atoms");
2292         setStringEntry(&inp, "split-group0", ir->swap->grp[eGrpSplit0].molname, nullptr);
2293         setStringEntry(&inp, "split-group1", ir->swap->grp[eGrpSplit1].molname, nullptr);
2294         printStringNoNewline(&inp,
2295                              "Use center of mass of split groups (yes/no), otherwise center of "
2296                              "geometry is used");
2297         ir->swap->massw_split[0] = (get_eeenum(&inp, "massw-split0", yesno_names, wi) != 0);
2298         ir->swap->massw_split[1] = (get_eeenum(&inp, "massw-split1", yesno_names, wi) != 0);
2299
2300         printStringNoNewline(&inp, "Name of solvent molecules");
2301         setStringEntry(&inp, "solvent-group", ir->swap->grp[eGrpSolvent].molname, nullptr);
2302
2303         printStringNoNewline(&inp,
2304                              "Split cylinder: radius, upper and lower extension (nm) (this will "
2305                              "define the channels)");
2306         printStringNoNewline(&inp,
2307                              "Note that the split cylinder settings do not have an influence on "
2308                              "the swapping protocol,");
2309         printStringNoNewline(
2310                 &inp,
2311                 "however, if correctly defined, the permeation events are recorded per channel");
2312         ir->swap->cyl0r = get_ereal(&inp, "cyl0-r", 2.0, wi);
2313         ir->swap->cyl0u = get_ereal(&inp, "cyl0-up", 1.0, wi);
2314         ir->swap->cyl0l = get_ereal(&inp, "cyl0-down", 1.0, wi);
2315         ir->swap->cyl1r = get_ereal(&inp, "cyl1-r", 2.0, wi);
2316         ir->swap->cyl1u = get_ereal(&inp, "cyl1-up", 1.0, wi);
2317         ir->swap->cyl1l = get_ereal(&inp, "cyl1-down", 1.0, wi);
2318
2319         printStringNoNewline(
2320                 &inp,
2321                 "Average the number of ions per compartment over these many swap attempt steps");
2322         ir->swap->nAverage = get_eint(&inp, "coupl-steps", 10, wi);
2323
2324         printStringNoNewline(
2325                 &inp, "Names of the ion types that can be exchanged with solvent molecules,");
2326         printStringNoNewline(
2327                 &inp, "and the requested number of ions of this type in compartments A and B");
2328         printStringNoNewline(&inp, "-1 means fix the numbers as found in step 0");
2329         for (i = 0; i < nIonTypes; i++)
2330         {
2331             int ig = eSwapFixedGrpNR + i;
2332
2333             sprintf(buf, "iontype%d-name", i);
2334             setStringEntry(&inp, buf, ir->swap->grp[ig].molname, nullptr);
2335             sprintf(buf, "iontype%d-in-A", i);
2336             ir->swap->grp[ig].nmolReq[0] = get_eint(&inp, buf, -1, wi);
2337             sprintf(buf, "iontype%d-in-B", i);
2338             ir->swap->grp[ig].nmolReq[1] = get_eint(&inp, buf, -1, wi);
2339         }
2340
2341         printStringNoNewline(
2342                 &inp,
2343                 "By default (i.e. bulk offset = 0.0), ion/water exchanges happen between layers");
2344         printStringNoNewline(
2345                 &inp,
2346                 "at maximum distance (= bulk concentration) to the split group layers. However,");
2347         printStringNoNewline(&inp,
2348                              "an offset b (-1.0 < b < +1.0) can be specified to offset the bulk "
2349                              "layer from the middle at 0.0");
2350         printStringNoNewline(&inp,
2351                              "towards one of the compartment-partitioning layers (at +/- 1.0).");
2352         ir->swap->bulkOffset[0] = get_ereal(&inp, "bulk-offsetA", 0.0, wi);
2353         ir->swap->bulkOffset[1] = get_ereal(&inp, "bulk-offsetB", 0.0, wi);
2354         if (!(ir->swap->bulkOffset[0] > -1.0 && ir->swap->bulkOffset[0] < 1.0)
2355             || !(ir->swap->bulkOffset[1] > -1.0 && ir->swap->bulkOffset[1] < 1.0))
2356         {
2357             warning_error(wi, "Bulk layer offsets must be > -1.0 and < 1.0 !");
2358         }
2359
2360         printStringNoNewline(
2361                 &inp, "Start to swap ions if threshold difference to requested count is reached");
2362         ir->swap->threshold = get_ereal(&inp, "threshold", 1.0, wi);
2363     }
2364
2365     /* AdResS is no longer supported, but we need grompp to be able to
2366        refuse to process old .mdp files that used it. */
2367     ir->bAdress = (get_eeenum(&inp, "adress", no_names, wi) != 0);
2368
2369     /* User defined thingies */
2370     printStringNewline(&inp, "User defined thingies");
2371     setStringEntry(&inp, "user1-grps", is->user1, nullptr);
2372     setStringEntry(&inp, "user2-grps", is->user2, nullptr);
2373     ir->userint1  = get_eint(&inp, "userint1", 0, wi);
2374     ir->userint2  = get_eint(&inp, "userint2", 0, wi);
2375     ir->userint3  = get_eint(&inp, "userint3", 0, wi);
2376     ir->userint4  = get_eint(&inp, "userint4", 0, wi);
2377     ir->userreal1 = get_ereal(&inp, "userreal1", 0, wi);
2378     ir->userreal2 = get_ereal(&inp, "userreal2", 0, wi);
2379     ir->userreal3 = get_ereal(&inp, "userreal3", 0, wi);
2380     ir->userreal4 = get_ereal(&inp, "userreal4", 0, wi);
2381 #undef CTYPE
2382
2383     {
2384         gmx::TextOutputFile stream(mdparout);
2385         write_inpfile(&stream, mdparout, &inp, FALSE, writeMdpHeader, wi);
2386
2387         // Transform module data into a flat key-value tree for output.
2388         gmx::KeyValueTreeBuilder       builder;
2389         gmx::KeyValueTreeObjectBuilder builderObject = builder.rootObject();
2390         mdModules->buildMdpOutput(&builderObject);
2391         {
2392             gmx::TextWriter writer(&stream);
2393             writeKeyValueTreeAsMdp(&writer, builder.build());
2394         }
2395         stream.close();
2396     }
2397
2398     /* Process options if necessary */
2399     for (m = 0; m < 2; m++)
2400     {
2401         for (i = 0; i < 2 * DIM; i++)
2402         {
2403             dumdub[m][i] = 0.0;
2404         }
2405         if (ir->epc)
2406         {
2407             switch (ir->epct)
2408             {
2409                 case epctISOTROPIC:
2410                     if (sscanf(dumstr[m], "%lf", &(dumdub[m][XX])) != 1)
2411                     {
2412                         warning_error(
2413                                 wi,
2414                                 "Pressure coupling incorrect number of values (I need exactly 1)");
2415                     }
2416                     dumdub[m][YY] = dumdub[m][ZZ] = dumdub[m][XX];
2417                     break;
2418                 case epctSEMIISOTROPIC:
2419                 case epctSURFACETENSION:
2420                     if (sscanf(dumstr[m], "%lf%lf", &(dumdub[m][XX]), &(dumdub[m][ZZ])) != 2)
2421                     {
2422                         warning_error(
2423                                 wi,
2424                                 "Pressure coupling incorrect number of values (I need exactly 2)");
2425                     }
2426                     dumdub[m][YY] = dumdub[m][XX];
2427                     break;
2428                 case epctANISOTROPIC:
2429                     if (sscanf(dumstr[m], "%lf%lf%lf%lf%lf%lf", &(dumdub[m][XX]), &(dumdub[m][YY]),
2430                                &(dumdub[m][ZZ]), &(dumdub[m][3]), &(dumdub[m][4]), &(dumdub[m][5]))
2431                         != 6)
2432                     {
2433                         warning_error(
2434                                 wi,
2435                                 "Pressure coupling incorrect number of values (I need exactly 6)");
2436                     }
2437                     break;
2438                 default:
2439                     gmx_fatal(FARGS, "Pressure coupling type %s not implemented yet",
2440                               epcoupltype_names[ir->epct]);
2441             }
2442         }
2443     }
2444     clear_mat(ir->ref_p);
2445     clear_mat(ir->compress);
2446     for (i = 0; i < DIM; i++)
2447     {
2448         ir->ref_p[i][i]    = dumdub[1][i];
2449         ir->compress[i][i] = dumdub[0][i];
2450     }
2451     if (ir->epct == epctANISOTROPIC)
2452     {
2453         ir->ref_p[XX][YY] = dumdub[1][3];
2454         ir->ref_p[XX][ZZ] = dumdub[1][4];
2455         ir->ref_p[YY][ZZ] = dumdub[1][5];
2456         if (ir->ref_p[XX][YY] != 0 && ir->ref_p[XX][ZZ] != 0 && ir->ref_p[YY][ZZ] != 0)
2457         {
2458             warning(wi,
2459                     "All off-diagonal reference pressures are non-zero. Are you sure you want to "
2460                     "apply a threefold shear stress?\n");
2461         }
2462         ir->compress[XX][YY] = dumdub[0][3];
2463         ir->compress[XX][ZZ] = dumdub[0][4];
2464         ir->compress[YY][ZZ] = dumdub[0][5];
2465         for (i = 0; i < DIM; i++)
2466         {
2467             for (m = 0; m < i; m++)
2468             {
2469                 ir->ref_p[i][m]    = ir->ref_p[m][i];
2470                 ir->compress[i][m] = ir->compress[m][i];
2471             }
2472         }
2473     }
2474
2475     if (ir->comm_mode == ecmNO)
2476     {
2477         ir->nstcomm = 0;
2478     }
2479
2480     opts->couple_moltype = nullptr;
2481     if (strlen(is->couple_moltype) > 0)
2482     {
2483         if (ir->efep != efepNO)
2484         {
2485             opts->couple_moltype = gmx_strdup(is->couple_moltype);
2486             if (opts->couple_lam0 == opts->couple_lam1)
2487             {
2488                 warning(wi, "The lambda=0 and lambda=1 states for coupling are identical");
2489             }
2490             if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE || opts->couple_lam1 == ecouplamNONE))
2491             {
2492                 warning_note(
2493                         wi,
2494                         "For proper sampling of the (nearly) decoupled state, stochastic dynamics "
2495                         "should be used");
2496             }
2497         }
2498         else
2499         {
2500             warning_note(wi,
2501                          "Free energy is turned off, so we will not decouple the molecule listed "
2502                          "in your input.");
2503         }
2504     }
2505     /* FREE ENERGY AND EXPANDED ENSEMBLE OPTIONS */
2506     if (ir->efep != efepNO)
2507     {
2508         if (fep->delta_lambda > 0)
2509         {
2510             ir->efep = efepSLOWGROWTH;
2511         }
2512     }
2513
2514     if (fep->edHdLPrintEnergy == edHdLPrintEnergyYES)
2515     {
2516         fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
2517         warning_note(wi,
2518                      "Old option for dhdl-print-energy given: "
2519                      "changing \"yes\" to \"total\"\n");
2520     }
2521
2522     if (ir->bSimTemp && (fep->edHdLPrintEnergy == edHdLPrintEnergyNO))
2523     {
2524         /* always print out the energy to dhdl if we are doing
2525            expanded ensemble, since we need the total energy for
2526            analysis if the temperature is changing. In some
2527            conditions one may only want the potential energy, so
2528            we will allow that if the appropriate mdp setting has
2529            been enabled. Otherwise, total it is:
2530          */
2531         fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
2532     }
2533
2534     if ((ir->efep != efepNO) || ir->bSimTemp)
2535     {
2536         ir->bExpanded = FALSE;
2537         if ((ir->efep == efepEXPANDED) || ir->bSimTemp)
2538         {
2539             ir->bExpanded = TRUE;
2540         }
2541         do_fep_params(ir, is->fep_lambda, is->lambda_weights, wi);
2542         if (ir->bSimTemp) /* done after fep params */
2543         {
2544             do_simtemp_params(ir);
2545         }
2546
2547         /* Because sc-coul (=FALSE by default) only acts on the lambda state
2548          * setup and not on the old way of specifying the free-energy setup,
2549          * we should check for using soft-core when not needed, since that
2550          * can complicate the sampling significantly.
2551          * Note that we only check for the automated coupling setup.
2552          * If the (advanced) user does FEP through manual topology changes,
2553          * this check will not be triggered.
2554          */
2555         if (ir->efep != efepNO && ir->fepvals->n_lambda == 0 && ir->fepvals->sc_alpha != 0
2556             && (couple_lambda_has_vdw_on(opts->couple_lam0) && couple_lambda_has_vdw_on(opts->couple_lam1)))
2557         {
2558             warning(wi,
2559                     "You are using soft-core interactions while the Van der Waals interactions are "
2560                     "not decoupled (note that the sc-coul option is only active when using lambda "
2561                     "states). Although this will not lead to errors, you will need much more "
2562                     "sampling than without soft-core interactions. Consider using sc-alpha=0.");
2563         }
2564     }
2565     else
2566     {
2567         ir->fepvals->n_lambda = 0;
2568     }
2569
2570     /* WALL PARAMETERS */
2571
2572     do_wall_params(ir, is->wall_atomtype, is->wall_density, opts, wi);
2573
2574     /* ORIENTATION RESTRAINT PARAMETERS */
2575
2576     if (opts->bOrire && gmx::splitString(is->orirefitgrp).size() != 1)
2577     {
2578         warning_error(wi, "ERROR: Need one orientation restraint fit group\n");
2579     }
2580
2581     /* DEFORMATION PARAMETERS */
2582
2583     clear_mat(ir->deform);
2584     for (i = 0; i < 6; i++)
2585     {
2586         dumdub[0][i] = 0;
2587     }
2588
2589     double gmx_unused canary;
2590     int ndeform = sscanf(is->deform, "%lf %lf %lf %lf %lf %lf %lf", &(dumdub[0][0]), &(dumdub[0][1]),
2591                          &(dumdub[0][2]), &(dumdub[0][3]), &(dumdub[0][4]), &(dumdub[0][5]), &canary);
2592
2593     if (strlen(is->deform) > 0 && ndeform != 6)
2594     {
2595         warning_error(
2596                 wi, gmx::formatString(
2597                             "Cannot parse exactly 6 box deformation velocities from string '%s'", is->deform)
2598                             .c_str());
2599     }
2600     for (i = 0; i < 3; i++)
2601     {
2602         ir->deform[i][i] = dumdub[0][i];
2603     }
2604     ir->deform[YY][XX] = dumdub[0][3];
2605     ir->deform[ZZ][XX] = dumdub[0][4];
2606     ir->deform[ZZ][YY] = dumdub[0][5];
2607     if (ir->epc != epcNO)
2608     {
2609         for (i = 0; i < 3; i++)
2610         {
2611             for (j = 0; j <= i; j++)
2612             {
2613                 if (ir->deform[i][j] != 0 && ir->compress[i][j] != 0)
2614                 {
2615                     warning_error(wi, "A box element has deform set and compressibility > 0");
2616                 }
2617             }
2618         }
2619         for (i = 0; i < 3; i++)
2620         {
2621             for (j = 0; j < i; j++)
2622             {
2623                 if (ir->deform[i][j] != 0)
2624                 {
2625                     for (m = j; m < DIM; m++)
2626                     {
2627                         if (ir->compress[m][j] != 0)
2628                         {
2629                             sprintf(warn_buf,
2630                                     "An off-diagonal box element has deform set while "
2631                                     "compressibility > 0 for the same component of another box "
2632                                     "vector, this might lead to spurious periodicity effects.");
2633                             warning(wi, warn_buf);
2634                         }
2635                     }
2636                 }
2637             }
2638         }
2639     }
2640
2641     /* Ion/water position swapping checks */
2642     if (ir->eSwapCoords != eswapNO)
2643     {
2644         if (ir->swap->nstswap < 1)
2645         {
2646             warning_error(wi, "swap_frequency must be 1 or larger when ion swapping is requested");
2647         }
2648         if (ir->swap->nAverage < 1)
2649         {
2650             warning_error(wi, "coupl_steps must be 1 or larger.\n");
2651         }
2652         if (ir->swap->threshold < 1.0)
2653         {
2654             warning_error(wi, "Ion count threshold must be at least 1.\n");
2655         }
2656     }
2657
2658     if (ir->bDoAwh)
2659     {
2660         gmx::checkAwhParams(ir->awhParams, ir, wi);
2661     }
2662
2663     sfree(dumstr[0]);
2664     sfree(dumstr[1]);
2665 }
2666
2667 static int search_QMstring(const char* s, int ng, const char* gn[])
2668 {
2669     /* same as normal search_string, but this one searches QM strings */
2670     int i;
2671
2672     for (i = 0; (i < ng); i++)
2673     {
2674         if (gmx_strcasecmp(s, gn[i]) == 0)
2675         {
2676             return i;
2677         }
2678     }
2679
2680     gmx_fatal(FARGS, "this QM method or basisset (%s) is not implemented\n!", s);
2681 } /* search_QMstring */
2682
2683 /* We would like gn to be const as well, but C doesn't allow this */
2684 /* TODO this is utility functionality (search for the index of a
2685    string in a collection), so should be refactored and located more
2686    centrally. */
2687 int search_string(const char* s, int ng, char* gn[])
2688 {
2689     int i;
2690
2691     for (i = 0; (i < ng); i++)
2692     {
2693         if (gmx_strcasecmp(s, gn[i]) == 0)
2694         {
2695             return i;
2696         }
2697     }
2698
2699     gmx_fatal(FARGS,
2700               "Group %s referenced in the .mdp file was not found in the index file.\n"
2701               "Group names must match either [moleculetype] names or custom index group\n"
2702               "names, in which case you must supply an index file to the '-n' option\n"
2703               "of grompp.",
2704               s);
2705 }
2706
2707 static void do_numbering(int                        natoms,
2708                          SimulationGroups*          groups,
2709                          gmx::ArrayRef<std::string> groupsFromMdpFile,
2710                          t_blocka*                  block,
2711                          char*                      gnames[],
2712                          SimulationAtomGroupType    gtype,
2713                          int                        restnm,
2714                          int                        grptp,
2715                          bool                       bVerbose,
2716                          warninp_t                  wi)
2717 {
2718     unsigned short*   cbuf;
2719     AtomGroupIndices* grps = &(groups->groups[gtype]);
2720     int               j, gid, aj, ognr, ntot = 0;
2721     const char*       title;
2722     char              warn_buf[STRLEN];
2723
2724     title = shortName(gtype);
2725
2726     snew(cbuf, natoms);
2727     /* Mark all id's as not set */
2728     for (int i = 0; (i < natoms); i++)
2729     {
2730         cbuf[i] = NOGID;
2731     }
2732
2733     for (int i = 0; i != groupsFromMdpFile.ssize(); ++i)
2734     {
2735         /* Lookup the group name in the block structure */
2736         gid = search_string(groupsFromMdpFile[i].c_str(), block->nr, gnames);
2737         if ((grptp != egrptpONE) || (i == 0))
2738         {
2739             grps->emplace_back(gid);
2740         }
2741
2742         /* Now go over the atoms in the group */
2743         for (j = block->index[gid]; (j < block->index[gid + 1]); j++)
2744         {
2745
2746             aj = block->a[j];
2747
2748             /* Range checking */
2749             if ((aj < 0) || (aj >= natoms))
2750             {
2751                 gmx_fatal(FARGS, "Invalid atom number %d in indexfile", aj + 1);
2752             }
2753             /* Lookup up the old group number */
2754             ognr = cbuf[aj];
2755             if (ognr != NOGID)
2756             {
2757                 gmx_fatal(FARGS, "Atom %d in multiple %s groups (%d and %d)", aj + 1, title,
2758                           ognr + 1, i + 1);
2759             }
2760             else
2761             {
2762                 /* Store the group number in buffer */
2763                 if (grptp == egrptpONE)
2764                 {
2765                     cbuf[aj] = 0;
2766                 }
2767                 else
2768                 {
2769                     cbuf[aj] = i;
2770                 }
2771                 ntot++;
2772             }
2773         }
2774     }
2775
2776     /* Now check whether we have done all atoms */
2777     if (ntot != natoms)
2778     {
2779         if (grptp == egrptpALL)
2780         {
2781             gmx_fatal(FARGS, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
2782         }
2783         else if (grptp == egrptpPART)
2784         {
2785             sprintf(warn_buf, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
2786             warning_note(wi, warn_buf);
2787         }
2788         /* Assign all atoms currently unassigned to a rest group */
2789         for (j = 0; (j < natoms); j++)
2790         {
2791             if (cbuf[j] == NOGID)
2792             {
2793                 cbuf[j] = grps->size();
2794             }
2795         }
2796         if (grptp != egrptpPART)
2797         {
2798             if (bVerbose)
2799             {
2800                 fprintf(stderr, "Making dummy/rest group for %s containing %d elements\n", title,
2801                         natoms - ntot);
2802             }
2803             /* Add group name "rest" */
2804             grps->emplace_back(restnm);
2805
2806             /* Assign the rest name to all atoms not currently assigned to a group */
2807             for (j = 0; (j < natoms); j++)
2808             {
2809                 if (cbuf[j] == NOGID)
2810                 {
2811                     // group size was not updated before this here, so need to use -1.
2812                     cbuf[j] = grps->size() - 1;
2813                 }
2814             }
2815         }
2816     }
2817
2818     if (grps->size() == 1 && (ntot == 0 || ntot == natoms))
2819     {
2820         /* All atoms are part of one (or no) group, no index required */
2821         groups->groupNumbers[gtype].clear();
2822     }
2823     else
2824     {
2825         for (int j = 0; (j < natoms); j++)
2826         {
2827             groups->groupNumbers[gtype].emplace_back(cbuf[j]);
2828         }
2829     }
2830
2831     sfree(cbuf);
2832 }
2833
2834 static void calc_nrdf(const gmx_mtop_t* mtop, t_inputrec* ir, char** gnames)
2835 {
2836     t_grpopts*     opts;
2837     pull_params_t* pull;
2838     int            natoms, imin, jmin;
2839     int *          nrdf2, *na_vcm, na_tot;
2840     double *       nrdf_tc, *nrdf_vcm, nrdf_uc, *nrdf_vcm_sub;
2841     ivec*          dof_vcm;
2842     int            as;
2843
2844     /* Calculate nrdf.
2845      * First calc 3xnr-atoms for each group
2846      * then subtract half a degree of freedom for each constraint
2847      *
2848      * Only atoms and nuclei contribute to the degrees of freedom...
2849      */
2850
2851     opts = &ir->opts;
2852
2853     const SimulationGroups& groups = mtop->groups;
2854     natoms                         = mtop->natoms;
2855
2856     /* Allocate one more for a possible rest group */
2857     /* We need to sum degrees of freedom into doubles,
2858      * since floats give too low nrdf's above 3 million atoms.
2859      */
2860     snew(nrdf_tc, groups.groups[SimulationAtomGroupType::TemperatureCoupling].size() + 1);
2861     snew(nrdf_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2862     snew(dof_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2863     snew(na_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2864     snew(nrdf_vcm_sub, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2865
2866     for (gmx::index i = 0; i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
2867     {
2868         nrdf_tc[i] = 0;
2869     }
2870     for (gmx::index i = 0;
2871          i < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; i++)
2872     {
2873         nrdf_vcm[i] = 0;
2874         clear_ivec(dof_vcm[i]);
2875         na_vcm[i]       = 0;
2876         nrdf_vcm_sub[i] = 0;
2877     }
2878     snew(nrdf2, natoms);
2879     for (const AtomProxy atomP : AtomRange(*mtop))
2880     {
2881         const t_atom& local = atomP.atom();
2882         int           i     = atomP.globalAtomNumber();
2883         nrdf2[i]            = 0;
2884         if (local.ptype == eptAtom || local.ptype == eptNucleus)
2885         {
2886             int g = getGroupType(groups, SimulationAtomGroupType::Freeze, i);
2887             for (int d = 0; d < DIM; d++)
2888             {
2889                 if (opts->nFreeze[g][d] == 0)
2890                 {
2891                     /* Add one DOF for particle i (counted as 2*1) */
2892                     nrdf2[i] += 2;
2893                     /* VCM group i has dim d as a DOF */
2894                     dof_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)][d] =
2895                             1;
2896                 }
2897             }
2898             nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, i)] +=
2899                     0.5 * nrdf2[i];
2900             nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)] +=
2901                     0.5 * nrdf2[i];
2902         }
2903     }
2904
2905     as = 0;
2906     for (const gmx_molblock_t& molb : mtop->molblock)
2907     {
2908         const gmx_moltype_t& molt = mtop->moltype[molb.type];
2909         const t_atom*        atom = molt.atoms.atom;
2910         for (int mol = 0; mol < molb.nmol; mol++)
2911         {
2912             for (int ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
2913             {
2914                 gmx::ArrayRef<const int> ia = molt.ilist[ftype].iatoms;
2915                 for (int i = 0; i < molt.ilist[ftype].size();)
2916                 {
2917                     /* Subtract degrees of freedom for the constraints,
2918                      * if the particles still have degrees of freedom left.
2919                      * If one of the particles is a vsite or a shell, then all
2920                      * constraint motion will go there, but since they do not
2921                      * contribute to the constraints the degrees of freedom do not
2922                      * change.
2923                      */
2924                     int ai = as + ia[i + 1];
2925                     int aj = as + ia[i + 2];
2926                     if (((atom[ia[i + 1]].ptype == eptNucleus) || (atom[ia[i + 1]].ptype == eptAtom))
2927                         && ((atom[ia[i + 2]].ptype == eptNucleus) || (atom[ia[i + 2]].ptype == eptAtom)))
2928                     {
2929                         if (nrdf2[ai] > 0)
2930                         {
2931                             jmin = 1;
2932                         }
2933                         else
2934                         {
2935                             jmin = 2;
2936                         }
2937                         if (nrdf2[aj] > 0)
2938                         {
2939                             imin = 1;
2940                         }
2941                         else
2942                         {
2943                             imin = 2;
2944                         }
2945                         imin = std::min(imin, nrdf2[ai]);
2946                         jmin = std::min(jmin, nrdf2[aj]);
2947                         nrdf2[ai] -= imin;
2948                         nrdf2[aj] -= jmin;
2949                         nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
2950                                 0.5 * imin;
2951                         nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, aj)] -=
2952                                 0.5 * jmin;
2953                         nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
2954                                 0.5 * imin;
2955                         nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, aj)] -=
2956                                 0.5 * jmin;
2957                     }
2958                     i += interaction_function[ftype].nratoms + 1;
2959                 }
2960             }
2961             gmx::ArrayRef<const int> ia = molt.ilist[F_SETTLE].iatoms;
2962             for (int i = 0; i < molt.ilist[F_SETTLE].size();)
2963             {
2964                 /* Subtract 1 dof from every atom in the SETTLE */
2965                 for (int j = 0; j < 3; j++)
2966                 {
2967                     int ai = as + ia[i + 1 + j];
2968                     imin   = std::min(2, nrdf2[ai]);
2969                     nrdf2[ai] -= imin;
2970                     nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
2971                             0.5 * imin;
2972                     nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
2973                             0.5 * imin;
2974                 }
2975                 i += 4;
2976             }
2977             as += molt.atoms.nr;
2978         }
2979     }
2980
2981     if (ir->bPull)
2982     {
2983         /* Correct nrdf for the COM constraints.
2984          * We correct using the TC and VCM group of the first atom
2985          * in the reference and pull group. If atoms in one pull group
2986          * belong to different TC or VCM groups it is anyhow difficult
2987          * to determine the optimal nrdf assignment.
2988          */
2989         pull = ir->pull;
2990
2991         for (int i = 0; i < pull->ncoord; i++)
2992         {
2993             if (pull->coord[i].eType != epullCONSTRAINT)
2994             {
2995                 continue;
2996             }
2997
2998             imin = 1;
2999
3000             for (int j = 0; j < 2; j++)
3001             {
3002                 const t_pull_group* pgrp;
3003
3004                 pgrp = &pull->group[pull->coord[i].group[j]];
3005
3006                 if (pgrp->nat > 0)
3007                 {
3008                     /* Subtract 1/2 dof from each group */
3009                     int ai = pgrp->ind[0];
3010                     nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
3011                             0.5 * imin;
3012                     nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
3013                             0.5 * imin;
3014                     if (nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] < 0)
3015                     {
3016                         gmx_fatal(FARGS,
3017                                   "Center of mass pulling constraints caused the number of degrees "
3018                                   "of freedom for temperature coupling group %s to be negative",
3019                                   gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][getGroupType(
3020                                           groups, SimulationAtomGroupType::TemperatureCoupling, ai)]]);
3021                     }
3022                 }
3023                 else
3024                 {
3025                     /* We need to subtract the whole DOF from group j=1 */
3026                     imin += 1;
3027                 }
3028             }
3029         }
3030     }
3031
3032     if (ir->nstcomm != 0)
3033     {
3034         GMX_RELEASE_ASSERT(!groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].empty(),
3035                            "Expect at least one group when removing COM motion");
3036
3037         /* We remove COM motion up to dim ndof_com() */
3038         const int ndim_rm_vcm = ndof_com(ir);
3039
3040         /* Subtract ndim_rm_vcm (or less with frozen dimensions) from
3041          * the number of degrees of freedom in each vcm group when COM
3042          * translation is removed and 6 when rotation is removed as well.
3043          * Note that we do not and should not include the rest group here.
3044          */
3045         for (gmx::index j = 0;
3046              j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]); j++)
3047         {
3048             switch (ir->comm_mode)
3049             {
3050                 case ecmLINEAR:
3051                 case ecmLINEAR_ACCELERATION_CORRECTION:
3052                     nrdf_vcm_sub[j] = 0;
3053                     for (int d = 0; d < ndim_rm_vcm; d++)
3054                     {
3055                         if (dof_vcm[j][d])
3056                         {
3057                             nrdf_vcm_sub[j]++;
3058                         }
3059                     }
3060                     break;
3061                 case ecmANGULAR: nrdf_vcm_sub[j] = 6; break;
3062                 default: gmx_incons("Checking comm_mode");
3063             }
3064         }
3065
3066         for (gmx::index i = 0;
3067              i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
3068         {
3069             /* Count the number of atoms of TC group i for every VCM group */
3070             for (gmx::index j = 0;
3071                  j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; j++)
3072             {
3073                 na_vcm[j] = 0;
3074             }
3075             na_tot = 0;
3076             for (int ai = 0; ai < natoms; ai++)
3077             {
3078                 if (getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai) == i)
3079                 {
3080                     na_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)]++;
3081                     na_tot++;
3082                 }
3083             }
3084             /* Correct for VCM removal according to the fraction of each VCM
3085              * group present in this TC group.
3086              */
3087             nrdf_uc    = nrdf_tc[i];
3088             nrdf_tc[i] = 0;
3089             for (gmx::index j = 0;
3090                  j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; j++)
3091             {
3092                 if (nrdf_vcm[j] > nrdf_vcm_sub[j])
3093                 {
3094                     nrdf_tc[i] += nrdf_uc * (static_cast<double>(na_vcm[j]) / static_cast<double>(na_tot))
3095                                   * (nrdf_vcm[j] - nrdf_vcm_sub[j]) / nrdf_vcm[j];
3096                 }
3097             }
3098         }
3099     }
3100     for (int i = 0; (i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling])); i++)
3101     {
3102         opts->nrdf[i] = nrdf_tc[i];
3103         if (opts->nrdf[i] < 0)
3104         {
3105             opts->nrdf[i] = 0;
3106         }
3107         fprintf(stderr, "Number of degrees of freedom in T-Coupling group %s is %.2f\n",
3108                 gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][i]], opts->nrdf[i]);
3109     }
3110
3111     sfree(nrdf2);
3112     sfree(nrdf_tc);
3113     sfree(nrdf_vcm);
3114     sfree(dof_vcm);
3115     sfree(na_vcm);
3116     sfree(nrdf_vcm_sub);
3117 }
3118
3119 static bool do_egp_flag(t_inputrec* ir, SimulationGroups* groups, const char* option, const char* val, int flag)
3120 {
3121     /* The maximum number of energy group pairs would be MAXPTR*(MAXPTR+1)/2.
3122      * But since this is much larger than STRLEN, such a line can not be parsed.
3123      * The real maximum is the number of names that fit in a string: STRLEN/2.
3124      */
3125 #define EGP_MAX (STRLEN / 2)
3126     int  j, k, nr;
3127     bool bSet;
3128
3129     auto names = gmx::splitString(val);
3130     if (names.size() % 2 != 0)
3131     {
3132         gmx_fatal(FARGS, "The number of groups for %s is odd", option);
3133     }
3134     nr   = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3135     bSet = FALSE;
3136     for (size_t i = 0; i < names.size() / 2; i++)
3137     {
3138         // TODO this needs to be replaced by a solution using std::find_if
3139         j = 0;
3140         while ((j < nr)
3141                && gmx_strcasecmp(
3142                           names[2 * i].c_str(),
3143                           *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][j]])))
3144         {
3145             j++;
3146         }
3147         if (j == nr)
3148         {
3149             gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i].c_str(), option);
3150         }
3151         k = 0;
3152         while ((k < nr)
3153                && gmx_strcasecmp(
3154                           names[2 * i + 1].c_str(),
3155                           *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][k]])))
3156         {
3157             k++;
3158         }
3159         if (k == nr)
3160         {
3161             gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i + 1].c_str(), option);
3162         }
3163         if ((j < nr) && (k < nr))
3164         {
3165             ir->opts.egp_flags[nr * j + k] |= flag;
3166             ir->opts.egp_flags[nr * k + j] |= flag;
3167             bSet = TRUE;
3168         }
3169     }
3170
3171     return bSet;
3172 }
3173
3174
3175 static void make_swap_groups(t_swapcoords* swap, t_blocka* grps, char** gnames)
3176 {
3177     int          ig = -1, i = 0, gind;
3178     t_swapGroup* swapg;
3179
3180
3181     /* Just a quick check here, more thorough checks are in mdrun */
3182     if (strcmp(swap->grp[eGrpSplit0].molname, swap->grp[eGrpSplit1].molname) == 0)
3183     {
3184         gmx_fatal(FARGS, "The split groups can not both be '%s'.", swap->grp[eGrpSplit0].molname);
3185     }
3186
3187     /* Get the index atoms of the split0, split1, solvent, and swap groups */
3188     for (ig = 0; ig < swap->ngrp; ig++)
3189     {
3190         swapg      = &swap->grp[ig];
3191         gind       = search_string(swap->grp[ig].molname, grps->nr, gnames);
3192         swapg->nat = grps->index[gind + 1] - grps->index[gind];
3193
3194         if (swapg->nat > 0)
3195         {
3196             fprintf(stderr, "%s group '%s' contains %d atoms.\n",
3197                     ig < 3 ? eSwapFixedGrp_names[ig] : "Swap", swap->grp[ig].molname, swapg->nat);
3198             snew(swapg->ind, swapg->nat);
3199             for (i = 0; i < swapg->nat; i++)
3200             {
3201                 swapg->ind[i] = grps->a[grps->index[gind] + i];
3202             }
3203         }
3204         else
3205         {
3206             gmx_fatal(FARGS, "Swap group %s does not contain any atoms.", swap->grp[ig].molname);
3207         }
3208     }
3209 }
3210
3211
3212 static void make_IMD_group(t_IMD* IMDgroup, char* IMDgname, t_blocka* grps, char** gnames)
3213 {
3214     int ig, i;
3215
3216
3217     ig            = search_string(IMDgname, grps->nr, gnames);
3218     IMDgroup->nat = grps->index[ig + 1] - grps->index[ig];
3219
3220     if (IMDgroup->nat > 0)
3221     {
3222         fprintf(stderr,
3223                 "Group '%s' with %d atoms can be activated for interactive molecular dynamics "
3224                 "(IMD).\n",
3225                 IMDgname, IMDgroup->nat);
3226         snew(IMDgroup->ind, IMDgroup->nat);
3227         for (i = 0; i < IMDgroup->nat; i++)
3228         {
3229             IMDgroup->ind[i] = grps->a[grps->index[ig] + i];
3230         }
3231     }
3232 }
3233
3234 /* Checks whether atoms are both part of a COM removal group and frozen.
3235  * If a fully frozen atom is part of a COM removal group, it is removed
3236  * from the COM removal group. A note is issued if such atoms are present.
3237  * A warning is issued for atom with one or two dimensions frozen that
3238  * are part of a COM removal group (mdrun would need to compute COM mass
3239  * per dimension to handle this correctly).
3240  * Also issues a warning when non-frozen atoms are not part of a COM
3241  * removal group while COM removal is active.
3242  */
3243 static void checkAndUpdateVcmFreezeGroupConsistency(SimulationGroups* groups,
3244                                                     const int         numAtoms,
3245                                                     const t_grpopts&  opts,
3246                                                     warninp_t         wi)
3247 {
3248     const int vcmRestGroup =
3249             std::max(int(groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size()), 1);
3250
3251     int numFullyFrozenVcmAtoms     = 0;
3252     int numPartiallyFrozenVcmAtoms = 0;
3253     int numNonVcmAtoms             = 0;
3254     for (int a = 0; a < numAtoms; a++)
3255     {
3256         const int freezeGroup   = getGroupType(*groups, SimulationAtomGroupType::Freeze, a);
3257         int       numFrozenDims = 0;
3258         for (int d = 0; d < DIM; d++)
3259         {
3260             numFrozenDims += opts.nFreeze[freezeGroup][d];
3261         }
3262
3263         const int vcmGroup = getGroupType(*groups, SimulationAtomGroupType::MassCenterVelocityRemoval, a);
3264         if (vcmGroup < vcmRestGroup)
3265         {
3266             if (numFrozenDims == DIM)
3267             {
3268                 /* Do not remove COM motion for this fully frozen atom */
3269                 if (groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval].empty())
3270                 {
3271                     groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval].resize(numAtoms, 0);
3272                 }
3273                 groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval][a] = vcmRestGroup;
3274                 numFullyFrozenVcmAtoms++;
3275             }
3276             else if (numFrozenDims > 0)
3277             {
3278                 numPartiallyFrozenVcmAtoms++;
3279             }
3280         }
3281         else if (numFrozenDims < DIM)
3282         {
3283             numNonVcmAtoms++;
3284         }
3285     }
3286
3287     if (numFullyFrozenVcmAtoms > 0)
3288     {
3289         std::string warningText = gmx::formatString(
3290                 "There are %d atoms that are fully frozen and part of COMM removal group(s), "
3291                 "removing these atoms from the COMM removal group(s)",
3292                 numFullyFrozenVcmAtoms);
3293         warning_note(wi, warningText.c_str());
3294     }
3295     if (numPartiallyFrozenVcmAtoms > 0 && numPartiallyFrozenVcmAtoms < numAtoms)
3296     {
3297         std::string warningText = gmx::formatString(
3298                 "There are %d atoms that are frozen along less then %d dimensions and part of COMM "
3299                 "removal group(s), due to limitations in the code these still contribute to the "
3300                 "mass of the COM along frozen dimensions and therefore the COMM correction will be "
3301                 "too small.",
3302                 numPartiallyFrozenVcmAtoms, DIM);
3303         warning(wi, warningText.c_str());
3304     }
3305     if (numNonVcmAtoms > 0)
3306     {
3307         std::string warningText = gmx::formatString(
3308                 "%d atoms are not part of any center of mass motion removal group.\n"
3309                 "This may lead to artifacts.\n"
3310                 "In most cases one should use one group for the whole system.",
3311                 numNonVcmAtoms);
3312         warning(wi, warningText.c_str());
3313     }
3314 }
3315
3316 void do_index(const char*                   mdparin,
3317               const char*                   ndx,
3318               gmx_mtop_t*                   mtop,
3319               bool                          bVerbose,
3320               const gmx::MdModulesNotifier& notifier,
3321               t_inputrec*                   ir,
3322               warninp_t                     wi)
3323 {
3324     t_blocka* defaultIndexGroups;
3325     int       natoms;
3326     t_symtab* symtab;
3327     t_atoms   atoms_all;
3328     char**    gnames;
3329     int       nr;
3330     real      tau_min;
3331     int       nstcmin;
3332     int       i, j, k, restnm;
3333     bool      bExcl, bTable, bAnneal;
3334     char      warn_buf[STRLEN];
3335
3336     if (bVerbose)
3337     {
3338         fprintf(stderr, "processing index file...\n");
3339     }
3340     if (ndx == nullptr)
3341     {
3342         snew(defaultIndexGroups, 1);
3343         snew(defaultIndexGroups->index, 1);
3344         snew(gnames, 1);
3345         atoms_all = gmx_mtop_global_atoms(mtop);
3346         analyse(&atoms_all, defaultIndexGroups, &gnames, FALSE, TRUE);
3347         done_atom(&atoms_all);
3348     }
3349     else
3350     {
3351         defaultIndexGroups = init_index(ndx, &gnames);
3352     }
3353
3354     SimulationGroups* groups = &mtop->groups;
3355     natoms                   = mtop->natoms;
3356     symtab                   = &mtop->symtab;
3357
3358     for (int i = 0; (i < defaultIndexGroups->nr); i++)
3359     {
3360         groups->groupNames.emplace_back(put_symtab(symtab, gnames[i]));
3361     }
3362     groups->groupNames.emplace_back(put_symtab(symtab, "rest"));
3363     restnm = groups->groupNames.size() - 1;
3364     GMX_RELEASE_ASSERT(restnm == defaultIndexGroups->nr, "Size of allocations must match");
3365     srenew(gnames, defaultIndexGroups->nr + 1);
3366     gnames[restnm] = *(groups->groupNames.back());
3367
3368     set_warning_line(wi, mdparin, -1);
3369
3370     auto temperatureCouplingTauValues       = gmx::splitString(is->tau_t);
3371     auto temperatureCouplingReferenceValues = gmx::splitString(is->ref_t);
3372     auto temperatureCouplingGroupNames      = gmx::splitString(is->tcgrps);
3373     if (temperatureCouplingTauValues.size() != temperatureCouplingGroupNames.size()
3374         || temperatureCouplingReferenceValues.size() != temperatureCouplingGroupNames.size())
3375     {
3376         gmx_fatal(FARGS,
3377                   "Invalid T coupling input: %zu groups, %zu ref-t values and "
3378                   "%zu tau-t values",
3379                   temperatureCouplingGroupNames.size(), temperatureCouplingReferenceValues.size(),
3380                   temperatureCouplingTauValues.size());
3381     }
3382
3383     const bool useReferenceTemperature = integratorHasReferenceTemperature(ir);
3384     do_numbering(natoms, groups, temperatureCouplingGroupNames, defaultIndexGroups, gnames,
3385                  SimulationAtomGroupType::TemperatureCoupling, restnm,
3386                  useReferenceTemperature ? egrptpALL : egrptpALL_GENREST, bVerbose, wi);
3387     nr            = groups->groups[SimulationAtomGroupType::TemperatureCoupling].size();
3388     ir->opts.ngtc = nr;
3389     snew(ir->opts.nrdf, nr);
3390     snew(ir->opts.tau_t, nr);
3391     snew(ir->opts.ref_t, nr);
3392     if (ir->eI == eiBD && ir->bd_fric == 0)
3393     {
3394         fprintf(stderr, "bd-fric=0, so tau-t will be used as the inverse friction constant(s)\n");
3395     }
3396
3397     if (useReferenceTemperature)
3398     {
3399         if (size_t(nr) != temperatureCouplingReferenceValues.size())
3400         {
3401             gmx_fatal(FARGS, "Not enough ref-t and tau-t values!");
3402         }
3403
3404         tau_min = 1e20;
3405         convertReals(wi, temperatureCouplingTauValues, "tau-t", ir->opts.tau_t);
3406         for (i = 0; (i < nr); i++)
3407         {
3408             if ((ir->eI == eiBD) && ir->opts.tau_t[i] <= 0)
3409             {
3410                 sprintf(warn_buf, "With integrator %s tau-t should be larger than 0", ei_names[ir->eI]);
3411                 warning_error(wi, warn_buf);
3412             }
3413
3414             if (ir->etc != etcVRESCALE && ir->opts.tau_t[i] == 0)
3415             {
3416                 warning_note(
3417                         wi,
3418                         "tau-t = -1 is the value to signal that a group should not have "
3419                         "temperature coupling. Treating your use of tau-t = 0 as if you used -1.");
3420             }
3421
3422             if (ir->opts.tau_t[i] >= 0)
3423             {
3424                 tau_min = std::min(tau_min, ir->opts.tau_t[i]);
3425             }
3426         }
3427         if (ir->etc != etcNO && ir->nsttcouple == -1)
3428         {
3429             ir->nsttcouple = ir_optimal_nsttcouple(ir);
3430         }
3431
3432         if (EI_VV(ir->eI))
3433         {
3434             if ((ir->etc == etcNOSEHOOVER) && (ir->epc == epcBERENDSEN))
3435             {
3436                 gmx_fatal(FARGS,
3437                           "Cannot do Nose-Hoover temperature with Berendsen pressure control with "
3438                           "md-vv; use either vrescale temperature with berendsen pressure or "
3439                           "Nose-Hoover temperature with MTTK pressure");
3440             }
3441             if (ir->epc == epcMTTK)
3442             {
3443                 if (ir->etc != etcNOSEHOOVER)
3444                 {
3445                     gmx_fatal(FARGS,
3446                               "Cannot do MTTK pressure coupling without Nose-Hoover temperature "
3447                               "control");
3448                 }
3449                 else
3450                 {
3451                     if (ir->nstpcouple != ir->nsttcouple)
3452                     {
3453                         int mincouple  = std::min(ir->nstpcouple, ir->nsttcouple);
3454                         ir->nstpcouple = ir->nsttcouple = mincouple;
3455                         sprintf(warn_buf,
3456                                 "for current Trotter decomposition methods with vv, nsttcouple and "
3457                                 "nstpcouple must be equal.  Both have been reset to "
3458                                 "min(nsttcouple,nstpcouple) = %d",
3459                                 mincouple);
3460                         warning_note(wi, warn_buf);
3461                     }
3462                 }
3463             }
3464         }
3465         /* velocity verlet with averaged kinetic energy KE = 0.5*(v(t+1/2) - v(t-1/2)) is implemented
3466            primarily for testing purposes, and does not work with temperature coupling other than 1 */
3467
3468         if (ETC_ANDERSEN(ir->etc))
3469         {
3470             if (ir->nsttcouple != 1)
3471             {
3472                 ir->nsttcouple = 1;
3473                 sprintf(warn_buf,
3474                         "Andersen temperature control methods assume nsttcouple = 1; there is no "
3475                         "need for larger nsttcouple > 1, since no global parameters are computed. "
3476                         "nsttcouple has been reset to 1");
3477                 warning_note(wi, warn_buf);
3478             }
3479         }
3480         nstcmin = tcouple_min_integration_steps(ir->etc);
3481         if (nstcmin > 1)
3482         {
3483             if (tau_min / (ir->delta_t * ir->nsttcouple) < nstcmin - 10 * GMX_REAL_EPS)
3484             {
3485                 sprintf(warn_buf,
3486                         "For proper integration of the %s thermostat, tau-t (%g) should be at "
3487                         "least %d times larger than nsttcouple*dt (%g)",
3488                         ETCOUPLTYPE(ir->etc), tau_min, nstcmin, ir->nsttcouple * ir->delta_t);
3489                 warning(wi, warn_buf);
3490             }
3491         }
3492         convertReals(wi, temperatureCouplingReferenceValues, "ref-t", ir->opts.ref_t);
3493         for (i = 0; (i < nr); i++)
3494         {
3495             if (ir->opts.ref_t[i] < 0)
3496             {
3497                 gmx_fatal(FARGS, "ref-t for group %d negative", i);
3498             }
3499         }
3500         /* set the lambda mc temperature to the md integrator temperature (which should be defined
3501            if we are in this conditional) if mc_temp is negative */
3502         if (ir->expandedvals->mc_temp < 0)
3503         {
3504             ir->expandedvals->mc_temp = ir->opts.ref_t[0]; /*for now, set to the first reft */
3505         }
3506     }
3507
3508     /* Simulated annealing for each group. There are nr groups */
3509     auto simulatedAnnealingGroupNames = gmx::splitString(is->anneal);
3510     if (simulatedAnnealingGroupNames.size() == 1
3511         && gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[0], "N", 1))
3512     {
3513         simulatedAnnealingGroupNames.resize(0);
3514     }
3515     if (!simulatedAnnealingGroupNames.empty() && gmx::ssize(simulatedAnnealingGroupNames) != nr)
3516     {
3517         gmx_fatal(FARGS, "Wrong number of annealing values: %zu (for %d groups)\n",
3518                   simulatedAnnealingGroupNames.size(), nr);
3519     }
3520     else
3521     {
3522         snew(ir->opts.annealing, nr);
3523         snew(ir->opts.anneal_npoints, nr);
3524         snew(ir->opts.anneal_time, nr);
3525         snew(ir->opts.anneal_temp, nr);
3526         for (i = 0; i < nr; i++)
3527         {
3528             ir->opts.annealing[i]      = eannNO;
3529             ir->opts.anneal_npoints[i] = 0;
3530             ir->opts.anneal_time[i]    = nullptr;
3531             ir->opts.anneal_temp[i]    = nullptr;
3532         }
3533         if (!simulatedAnnealingGroupNames.empty())
3534         {
3535             bAnneal = FALSE;
3536             for (i = 0; i < nr; i++)
3537             {
3538                 if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "N", 1))
3539                 {
3540                     ir->opts.annealing[i] = eannNO;
3541                 }
3542                 else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "S", 1))
3543                 {
3544                     ir->opts.annealing[i] = eannSINGLE;
3545                     bAnneal               = TRUE;
3546                 }
3547                 else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "P", 1))
3548                 {
3549                     ir->opts.annealing[i] = eannPERIODIC;
3550                     bAnneal               = TRUE;
3551                 }
3552             }
3553             if (bAnneal)
3554             {
3555                 /* Read the other fields too */
3556                 auto simulatedAnnealingPoints = gmx::splitString(is->anneal_npoints);
3557                 if (simulatedAnnealingPoints.size() != simulatedAnnealingGroupNames.size())
3558                 {
3559                     gmx_fatal(FARGS, "Found %zu annealing-npoints values for %zu groups\n",
3560                               simulatedAnnealingPoints.size(), simulatedAnnealingGroupNames.size());
3561                 }
3562                 convertInts(wi, simulatedAnnealingPoints, "annealing points", ir->opts.anneal_npoints);
3563                 size_t numSimulatedAnnealingFields = 0;
3564                 for (i = 0; i < nr; i++)
3565                 {
3566                     if (ir->opts.anneal_npoints[i] == 1)
3567                     {
3568                         gmx_fatal(
3569                                 FARGS,
3570                                 "Please specify at least a start and an end point for annealing\n");
3571                     }
3572                     snew(ir->opts.anneal_time[i], ir->opts.anneal_npoints[i]);
3573                     snew(ir->opts.anneal_temp[i], ir->opts.anneal_npoints[i]);
3574                     numSimulatedAnnealingFields += ir->opts.anneal_npoints[i];
3575                 }
3576
3577                 auto simulatedAnnealingTimes = gmx::splitString(is->anneal_time);
3578
3579                 if (simulatedAnnealingTimes.size() != numSimulatedAnnealingFields)
3580                 {
3581                     gmx_fatal(FARGS, "Found %zu annealing-time values, wanted %zu\n",
3582                               simulatedAnnealingTimes.size(), numSimulatedAnnealingFields);
3583                 }
3584                 auto simulatedAnnealingTemperatures = gmx::splitString(is->anneal_temp);
3585                 if (simulatedAnnealingTemperatures.size() != numSimulatedAnnealingFields)
3586                 {
3587                     gmx_fatal(FARGS, "Found %zu annealing-temp values, wanted %zu\n",
3588                               simulatedAnnealingTemperatures.size(), numSimulatedAnnealingFields);
3589                 }
3590
3591                 std::vector<real> allSimulatedAnnealingTimes(numSimulatedAnnealingFields);
3592                 std::vector<real> allSimulatedAnnealingTemperatures(numSimulatedAnnealingFields);
3593                 convertReals(wi, simulatedAnnealingTimes, "anneal-time",
3594                              allSimulatedAnnealingTimes.data());
3595                 convertReals(wi, simulatedAnnealingTemperatures, "anneal-temp",
3596                              allSimulatedAnnealingTemperatures.data());
3597                 for (i = 0, k = 0; i < nr; i++)
3598                 {
3599                     for (j = 0; j < ir->opts.anneal_npoints[i]; j++)
3600                     {
3601                         ir->opts.anneal_time[i][j] = allSimulatedAnnealingTimes[k];
3602                         ir->opts.anneal_temp[i][j] = allSimulatedAnnealingTemperatures[k];
3603                         if (j == 0)
3604                         {
3605                             if (ir->opts.anneal_time[i][0] > (ir->init_t + GMX_REAL_EPS))
3606                             {
3607                                 gmx_fatal(FARGS, "First time point for annealing > init_t.\n");
3608                             }
3609                         }
3610                         else
3611                         {
3612                             /* j>0 */
3613                             if (ir->opts.anneal_time[i][j] < ir->opts.anneal_time[i][j - 1])
3614                             {
3615                                 gmx_fatal(FARGS,
3616                                           "Annealing timepoints out of order: t=%f comes after "
3617                                           "t=%f\n",
3618                                           ir->opts.anneal_time[i][j], ir->opts.anneal_time[i][j - 1]);
3619                             }
3620                         }
3621                         if (ir->opts.anneal_temp[i][j] < 0)
3622                         {
3623                             gmx_fatal(FARGS, "Found negative temperature in annealing: %f\n",
3624                                       ir->opts.anneal_temp[i][j]);
3625                         }
3626                         k++;
3627                     }
3628                 }
3629                 /* Print out some summary information, to make sure we got it right */
3630                 for (i = 0; i < nr; i++)
3631                 {
3632                     if (ir->opts.annealing[i] != eannNO)
3633                     {
3634                         j = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
3635                         fprintf(stderr, "Simulated annealing for group %s: %s, %d timepoints\n",
3636                                 *(groups->groupNames[j]), eann_names[ir->opts.annealing[i]],
3637                                 ir->opts.anneal_npoints[i]);
3638                         fprintf(stderr, "Time (ps)   Temperature (K)\n");
3639                         /* All terms except the last one */
3640                         for (j = 0; j < (ir->opts.anneal_npoints[i] - 1); j++)
3641                         {
3642                             fprintf(stderr, "%9.1f      %5.1f\n", ir->opts.anneal_time[i][j],
3643                                     ir->opts.anneal_temp[i][j]);
3644                         }
3645
3646                         /* Finally the last one */
3647                         j = ir->opts.anneal_npoints[i] - 1;
3648                         if (ir->opts.annealing[i] == eannSINGLE)
3649                         {
3650                             fprintf(stderr, "%9.1f-     %5.1f\n", ir->opts.anneal_time[i][j],
3651                                     ir->opts.anneal_temp[i][j]);
3652                         }
3653                         else
3654                         {
3655                             fprintf(stderr, "%9.1f      %5.1f\n", ir->opts.anneal_time[i][j],
3656                                     ir->opts.anneal_temp[i][j]);
3657                             if (std::fabs(ir->opts.anneal_temp[i][j] - ir->opts.anneal_temp[i][0]) > GMX_REAL_EPS)
3658                             {
3659                                 warning_note(wi,
3660                                              "There is a temperature jump when your annealing "
3661                                              "loops back.\n");
3662                             }
3663                         }
3664                     }
3665                 }
3666             }
3667         }
3668     }
3669
3670     if (ir->bPull)
3671     {
3672         make_pull_groups(ir->pull, is->pull_grp, defaultIndexGroups, gnames);
3673
3674         make_pull_coords(ir->pull);
3675     }
3676
3677     if (ir->bRot)
3678     {
3679         make_rotation_groups(ir->rot, is->rot_grp, defaultIndexGroups, gnames);
3680     }
3681
3682     if (ir->eSwapCoords != eswapNO)
3683     {
3684         make_swap_groups(ir->swap, defaultIndexGroups, gnames);
3685     }
3686
3687     /* Make indices for IMD session */
3688     if (ir->bIMD)
3689     {
3690         make_IMD_group(ir->imd, is->imd_grp, defaultIndexGroups, gnames);
3691     }
3692
3693     gmx::IndexGroupsAndNames defaultIndexGroupsAndNames(
3694             *defaultIndexGroups, gmx::arrayRefFromArray(gnames, defaultIndexGroups->nr));
3695     notifier.preProcessingNotifications_.notify(defaultIndexGroupsAndNames);
3696
3697     auto accelerations          = gmx::splitString(is->acc);
3698     auto accelerationGroupNames = gmx::splitString(is->accgrps);
3699     if (accelerationGroupNames.size() * DIM != accelerations.size())
3700     {
3701         gmx_fatal(FARGS, "Invalid Acceleration input: %zu groups and %zu acc. values",
3702                   accelerationGroupNames.size(), accelerations.size());
3703     }
3704     do_numbering(natoms, groups, accelerationGroupNames, defaultIndexGroups, gnames,
3705                  SimulationAtomGroupType::Acceleration, restnm, egrptpALL_GENREST, bVerbose, wi);
3706     nr = groups->groups[SimulationAtomGroupType::Acceleration].size();
3707     snew(ir->opts.acc, nr);
3708     ir->opts.ngacc = nr;
3709
3710     convertRvecs(wi, accelerations, "anneal-time", ir->opts.acc);
3711
3712     auto freezeDims       = gmx::splitString(is->frdim);
3713     auto freezeGroupNames = gmx::splitString(is->freeze);
3714     if (freezeDims.size() != DIM * freezeGroupNames.size())
3715     {
3716         gmx_fatal(FARGS, "Invalid Freezing input: %zu groups and %zu freeze values",
3717                   freezeGroupNames.size(), freezeDims.size());
3718     }
3719     do_numbering(natoms, groups, freezeGroupNames, defaultIndexGroups, gnames,
3720                  SimulationAtomGroupType::Freeze, restnm, egrptpALL_GENREST, bVerbose, wi);
3721     nr             = groups->groups[SimulationAtomGroupType::Freeze].size();
3722     ir->opts.ngfrz = nr;
3723     snew(ir->opts.nFreeze, nr);
3724     for (i = k = 0; (size_t(i) < freezeGroupNames.size()); i++)
3725     {
3726         for (j = 0; (j < DIM); j++, k++)
3727         {
3728             ir->opts.nFreeze[i][j] = static_cast<int>(gmx::equalCaseInsensitive(freezeDims[k], "Y", 1));
3729             if (!ir->opts.nFreeze[i][j])
3730             {
3731                 if (!gmx::equalCaseInsensitive(freezeDims[k], "N", 1))
3732                 {
3733                     sprintf(warn_buf,
3734                             "Please use Y(ES) or N(O) for freezedim only "
3735                             "(not %s)",
3736                             freezeDims[k].c_str());
3737                     warning(wi, warn_buf);
3738                 }
3739             }
3740         }
3741     }
3742     for (; (i < nr); i++)
3743     {
3744         for (j = 0; (j < DIM); j++)
3745         {
3746             ir->opts.nFreeze[i][j] = 0;
3747         }
3748     }
3749
3750     auto energyGroupNames = gmx::splitString(is->energy);
3751     do_numbering(natoms, groups, energyGroupNames, defaultIndexGroups, gnames,
3752                  SimulationAtomGroupType::EnergyOutput, restnm, egrptpALL_GENREST, bVerbose, wi);
3753     add_wall_energrps(groups, ir->nwall, symtab);
3754     ir->opts.ngener    = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3755     auto vcmGroupNames = gmx::splitString(is->vcm);
3756     do_numbering(natoms, groups, vcmGroupNames, defaultIndexGroups, gnames,
3757                  SimulationAtomGroupType::MassCenterVelocityRemoval, restnm,
3758                  vcmGroupNames.empty() ? egrptpALL_GENREST : egrptpPART, bVerbose, wi);
3759
3760     if (ir->comm_mode != ecmNO)
3761     {
3762         checkAndUpdateVcmFreezeGroupConsistency(groups, natoms, ir->opts, wi);
3763     }
3764
3765     /* Now we have filled the freeze struct, so we can calculate NRDF */
3766     calc_nrdf(mtop, ir, gnames);
3767
3768     auto user1GroupNames = gmx::splitString(is->user1);
3769     do_numbering(natoms, groups, user1GroupNames, defaultIndexGroups, gnames,
3770                  SimulationAtomGroupType::User1, restnm, egrptpALL_GENREST, bVerbose, wi);
3771     auto user2GroupNames = gmx::splitString(is->user2);
3772     do_numbering(natoms, groups, user2GroupNames, defaultIndexGroups, gnames,
3773                  SimulationAtomGroupType::User2, restnm, egrptpALL_GENREST, bVerbose, wi);
3774     auto compressedXGroupNames = gmx::splitString(is->x_compressed_groups);
3775     do_numbering(natoms, groups, compressedXGroupNames, defaultIndexGroups, gnames,
3776                  SimulationAtomGroupType::CompressedPositionOutput, restnm, egrptpONE, bVerbose, wi);
3777     auto orirefFitGroupNames = gmx::splitString(is->orirefitgrp);
3778     do_numbering(natoms, groups, orirefFitGroupNames, defaultIndexGroups, gnames,
3779                  SimulationAtomGroupType::OrientationRestraintsFit, restnm, egrptpALL_GENREST,
3780                  bVerbose, wi);
3781
3782     /* QMMM input processing */
3783     auto qmGroupNames = gmx::splitString(is->QMMM);
3784     auto qmMethods    = gmx::splitString(is->QMmethod);
3785     auto qmBasisSets  = gmx::splitString(is->QMbasis);
3786     if (ir->eI != eiMimic)
3787     {
3788         if (qmMethods.size() != qmGroupNames.size() || qmBasisSets.size() != qmGroupNames.size())
3789         {
3790             gmx_fatal(FARGS,
3791                       "Invalid QMMM input: %zu groups %zu basissets"
3792                       " and %zu methods\n",
3793                       qmGroupNames.size(), qmBasisSets.size(), qmMethods.size());
3794         }
3795         /* group rest, if any, is always MM! */
3796         do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
3797                      SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
3798         nr            = qmGroupNames.size(); /*atoms->grps[egcQMMM].nr;*/
3799         ir->opts.ngQM = qmGroupNames.size();
3800         snew(ir->opts.QMmethod, nr);
3801         snew(ir->opts.QMbasis, nr);
3802         for (i = 0; i < nr; i++)
3803         {
3804             /* input consists of strings: RHF CASSCF PM3 .. These need to be
3805              * converted to the corresponding enum in names.c
3806              */
3807             ir->opts.QMmethod[i] = search_QMstring(qmMethods[i].c_str(), eQMmethodNR, eQMmethod_names);
3808             ir->opts.QMbasis[i] = search_QMstring(qmBasisSets[i].c_str(), eQMbasisNR, eQMbasis_names);
3809         }
3810         auto qmMultiplicities = gmx::splitString(is->QMmult);
3811         auto qmCharges        = gmx::splitString(is->QMcharge);
3812         auto qmbSH            = gmx::splitString(is->bSH);
3813         snew(ir->opts.QMmult, nr);
3814         snew(ir->opts.QMcharge, nr);
3815         snew(ir->opts.bSH, nr);
3816         convertInts(wi, qmMultiplicities, "QMmult", ir->opts.QMmult);
3817         convertInts(wi, qmCharges, "QMcharge", ir->opts.QMcharge);
3818         convertYesNos(wi, qmbSH, "bSH", ir->opts.bSH);
3819
3820         auto CASelectrons = gmx::splitString(is->CASelectrons);
3821         auto CASorbitals  = gmx::splitString(is->CASorbitals);
3822         snew(ir->opts.CASelectrons, nr);
3823         snew(ir->opts.CASorbitals, nr);
3824         convertInts(wi, CASelectrons, "CASelectrons", ir->opts.CASelectrons);
3825         convertInts(wi, CASorbitals, "CASOrbitals", ir->opts.CASorbitals);
3826
3827         auto SAon    = gmx::splitString(is->SAon);
3828         auto SAoff   = gmx::splitString(is->SAoff);
3829         auto SAsteps = gmx::splitString(is->SAsteps);
3830         snew(ir->opts.SAon, nr);
3831         snew(ir->opts.SAoff, nr);
3832         snew(ir->opts.SAsteps, nr);
3833         convertInts(wi, SAon, "SAon", ir->opts.SAon);
3834         convertInts(wi, SAoff, "SAoff", ir->opts.SAoff);
3835         convertInts(wi, SAsteps, "SAsteps", ir->opts.SAsteps);
3836     }
3837     else
3838     {
3839         /* MiMiC */
3840         if (qmGroupNames.size() > 1)
3841         {
3842             gmx_fatal(FARGS, "Currently, having more than one QM group in MiMiC is not supported");
3843         }
3844         /* group rest, if any, is always MM! */
3845         do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
3846                      SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
3847
3848         ir->opts.ngQM = qmGroupNames.size();
3849     }
3850
3851     /* end of QMMM input */
3852
3853     if (bVerbose)
3854     {
3855         for (auto group : gmx::keysOf(groups->groups))
3856         {
3857             fprintf(stderr, "%-16s has %zu element(s):", shortName(group), groups->groups[group].size());
3858             for (const auto& entry : groups->groups[group])
3859             {
3860                 fprintf(stderr, " %s", *(groups->groupNames[entry]));
3861             }
3862             fprintf(stderr, "\n");
3863         }
3864     }
3865
3866     nr = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3867     snew(ir->opts.egp_flags, nr * nr);
3868
3869     bExcl = do_egp_flag(ir, groups, "energygrp-excl", is->egpexcl, EGP_EXCL);
3870     if (bExcl && ir->cutoff_scheme == ecutsVERLET)
3871     {
3872         warning_error(wi, "Energy group exclusions are currently not supported");
3873     }
3874     if (bExcl && EEL_FULL(ir->coulombtype))
3875     {
3876         warning(wi, "Can not exclude the lattice Coulomb energy between energy groups");
3877     }
3878
3879     bTable = do_egp_flag(ir, groups, "energygrp-table", is->egptable, EGP_TABLE);
3880     if (bTable && !(ir->vdwtype == evdwUSER) && !(ir->coulombtype == eelUSER)
3881         && !(ir->coulombtype == eelPMEUSER) && !(ir->coulombtype == eelPMEUSERSWITCH))
3882     {
3883         gmx_fatal(FARGS,
3884                   "Can only have energy group pair tables in combination with user tables for VdW "
3885                   "and/or Coulomb");
3886     }
3887
3888     /* final check before going out of scope if simulated tempering variables
3889      * need to be set to default values.
3890      */
3891     if ((ir->expandedvals->nstexpanded < 0) && ir->bSimTemp)
3892     {
3893         ir->expandedvals->nstexpanded = 2 * static_cast<int>(ir->opts.tau_t[0] / ir->delta_t);
3894         warning(wi, gmx::formatString(
3895                             "the value for nstexpanded was not specified for "
3896                             " expanded ensemble simulated tempering. It is set to 2*tau_t (%d) "
3897                             "by default, but it is recommended to set it to an explicit value!",
3898                             ir->expandedvals->nstexpanded));
3899     }
3900     for (i = 0; (i < defaultIndexGroups->nr); i++)
3901     {
3902         sfree(gnames[i]);
3903     }
3904     sfree(gnames);
3905     done_blocka(defaultIndexGroups);
3906     sfree(defaultIndexGroups);
3907 }
3908
3909
3910 static void check_disre(const gmx_mtop_t* mtop)
3911 {
3912     if (gmx_mtop_ftype_count(mtop, F_DISRES) > 0)
3913     {
3914         const gmx_ffparams_t& ffparams  = mtop->ffparams;
3915         int                   ndouble   = 0;
3916         int                   old_label = -1;
3917         for (int i = 0; i < ffparams.numTypes(); i++)
3918         {
3919             int ftype = ffparams.functype[i];
3920             if (ftype == F_DISRES)
3921             {
3922                 int label = ffparams.iparams[i].disres.label;
3923                 if (label == old_label)
3924                 {
3925                     fprintf(stderr, "Distance restraint index %d occurs twice\n", label);
3926                     ndouble++;
3927                 }
3928                 old_label = label;
3929             }
3930         }
3931         if (ndouble > 0)
3932         {
3933             gmx_fatal(FARGS,
3934                       "Found %d double distance restraint indices,\n"
3935                       "probably the parameters for multiple pairs in one restraint "
3936                       "are not identical\n",
3937                       ndouble);
3938         }
3939     }
3940 }
3941
3942 static bool absolute_reference(const t_inputrec* ir, const gmx_mtop_t* sys, const bool posres_only, ivec AbsRef)
3943 {
3944     int                  d, g, i;
3945     gmx_mtop_ilistloop_t iloop;
3946     int                  nmol;
3947     const t_iparams*     pr;
3948
3949     clear_ivec(AbsRef);
3950
3951     if (!posres_only)
3952     {
3953         /* Check the COM */
3954         for (d = 0; d < DIM; d++)
3955         {
3956             AbsRef[d] = (d < ndof_com(ir) ? 0 : 1);
3957         }
3958         /* Check for freeze groups */
3959         for (g = 0; g < ir->opts.ngfrz; g++)
3960         {
3961             for (d = 0; d < DIM; d++)
3962             {
3963                 if (ir->opts.nFreeze[g][d] != 0)
3964                 {
3965                     AbsRef[d] = 1;
3966                 }
3967             }
3968         }
3969     }
3970
3971     /* Check for position restraints */
3972     iloop = gmx_mtop_ilistloop_init(sys);
3973     while (const InteractionLists* ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
3974     {
3975         if (nmol > 0 && (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
3976         {
3977             for (i = 0; i < (*ilist)[F_POSRES].size(); i += 2)
3978             {
3979                 pr = &sys->ffparams.iparams[(*ilist)[F_POSRES].iatoms[i]];
3980                 for (d = 0; d < DIM; d++)
3981                 {
3982                     if (pr->posres.fcA[d] != 0)
3983                     {
3984                         AbsRef[d] = 1;
3985                     }
3986                 }
3987             }
3988             for (i = 0; i < (*ilist)[F_FBPOSRES].size(); i += 2)
3989             {
3990                 /* Check for flat-bottom posres */
3991                 pr = &sys->ffparams.iparams[(*ilist)[F_FBPOSRES].iatoms[i]];
3992                 if (pr->fbposres.k != 0)
3993                 {
3994                     switch (pr->fbposres.geom)
3995                     {
3996                         case efbposresSPHERE: AbsRef[XX] = AbsRef[YY] = AbsRef[ZZ] = 1; break;
3997                         case efbposresCYLINDERX: AbsRef[YY] = AbsRef[ZZ] = 1; break;
3998                         case efbposresCYLINDERY: AbsRef[XX] = AbsRef[ZZ] = 1; break;
3999                         case efbposresCYLINDER:
4000                         /* efbposres is a synonym for efbposresCYLINDERZ for backwards compatibility */
4001                         case efbposresCYLINDERZ: AbsRef[XX] = AbsRef[YY] = 1; break;
4002                         case efbposresX: /* d=XX */
4003                         case efbposresY: /* d=YY */
4004                         case efbposresZ: /* d=ZZ */
4005                             d         = pr->fbposres.geom - efbposresX;
4006                             AbsRef[d] = 1;
4007                             break;
4008                         default:
4009                             gmx_fatal(FARGS,
4010                                       " Invalid geometry for flat-bottom position restraint.\n"
4011                                       "Expected nr between 1 and %d. Found %d\n",
4012                                       efbposresNR - 1, pr->fbposres.geom);
4013                     }
4014                 }
4015             }
4016         }
4017     }
4018
4019     return (AbsRef[XX] != 0 && AbsRef[YY] != 0 && AbsRef[ZZ] != 0);
4020 }
4021
4022 static void check_combination_rule_differences(const gmx_mtop_t* mtop,
4023                                                int               state,
4024                                                bool* bC6ParametersWorkWithGeometricRules,
4025                                                bool* bC6ParametersWorkWithLBRules,
4026                                                bool* bLBRulesPossible)
4027 {
4028     int         ntypes, tpi, tpj;
4029     int*        typecount;
4030     real        tol;
4031     double      c6i, c6j, c12i, c12j;
4032     double      c6, c6_geometric, c6_LB;
4033     double      sigmai, sigmaj, epsi, epsj;
4034     bool        bCanDoLBRules, bCanDoGeometricRules;
4035     const char* ptr;
4036
4037     /* A tolerance of 1e-5 seems reasonable for (possibly hand-typed)
4038      * force-field floating point parameters.
4039      */
4040     tol = 1e-5;
4041     ptr = getenv("GMX_LJCOMB_TOL");
4042     if (ptr != nullptr)
4043     {
4044         double dbl;
4045         double gmx_unused canary;
4046
4047         if (sscanf(ptr, "%lf%lf", &dbl, &canary) != 1)
4048         {
4049             gmx_fatal(FARGS,
4050                       "Could not parse a single floating-point number from GMX_LJCOMB_TOL (%s)", ptr);
4051         }
4052         tol = dbl;
4053     }
4054
4055     *bC6ParametersWorkWithLBRules        = TRUE;
4056     *bC6ParametersWorkWithGeometricRules = TRUE;
4057     bCanDoLBRules                        = TRUE;
4058     ntypes                               = mtop->ffparams.atnr;
4059     snew(typecount, ntypes);
4060     gmx_mtop_count_atomtypes(mtop, state, typecount);
4061     *bLBRulesPossible = TRUE;
4062     for (tpi = 0; tpi < ntypes; ++tpi)
4063     {
4064         c6i  = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c6;
4065         c12i = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c12;
4066         for (tpj = tpi; tpj < ntypes; ++tpj)
4067         {
4068             c6j          = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c6;
4069             c12j         = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c12;
4070             c6           = mtop->ffparams.iparams[ntypes * tpi + tpj].lj.c6;
4071             c6_geometric = std::sqrt(c6i * c6j);
4072             if (!gmx_numzero(c6_geometric))
4073             {
4074                 if (!gmx_numzero(c12i) && !gmx_numzero(c12j))
4075                 {
4076                     sigmai = gmx::sixthroot(c12i / c6i);
4077                     sigmaj = gmx::sixthroot(c12j / c6j);
4078                     epsi   = c6i * c6i / (4.0 * c12i);
4079                     epsj   = c6j * c6j / (4.0 * c12j);
4080                     c6_LB  = 4.0 * std::sqrt(epsi * epsj) * gmx::power6(0.5 * (sigmai + sigmaj));
4081                 }
4082                 else
4083                 {
4084                     *bLBRulesPossible = FALSE;
4085                     c6_LB             = c6_geometric;
4086                 }
4087                 bCanDoLBRules = gmx_within_tol(c6_LB, c6, tol);
4088             }
4089
4090             if (!bCanDoLBRules)
4091             {
4092                 *bC6ParametersWorkWithLBRules = FALSE;
4093             }
4094
4095             bCanDoGeometricRules = gmx_within_tol(c6_geometric, c6, tol);
4096
4097             if (!bCanDoGeometricRules)
4098             {
4099                 *bC6ParametersWorkWithGeometricRules = FALSE;
4100             }
4101         }
4102     }
4103     sfree(typecount);
4104 }
4105
4106 static void check_combination_rules(const t_inputrec* ir, const gmx_mtop_t* mtop, warninp_t wi)
4107 {
4108     bool bLBRulesPossible, bC6ParametersWorkWithGeometricRules, bC6ParametersWorkWithLBRules;
4109
4110     check_combination_rule_differences(mtop, 0, &bC6ParametersWorkWithGeometricRules,
4111                                        &bC6ParametersWorkWithLBRules, &bLBRulesPossible);
4112     if (ir->ljpme_combination_rule == eljpmeLB)
4113     {
4114         if (!bC6ParametersWorkWithLBRules || !bLBRulesPossible)
4115         {
4116             warning(wi,
4117                     "You are using arithmetic-geometric combination rules "
4118                     "in LJ-PME, but your non-bonded C6 parameters do not "
4119                     "follow these rules.");
4120         }
4121     }
4122     else
4123     {
4124         if (!bC6ParametersWorkWithGeometricRules)
4125         {
4126             if (ir->eDispCorr != edispcNO)
4127             {
4128                 warning_note(wi,
4129                              "You are using geometric combination rules in "
4130                              "LJ-PME, but your non-bonded C6 parameters do "
4131                              "not follow these rules. "
4132                              "This will introduce very small errors in the forces and energies in "
4133                              "your simulations. Dispersion correction will correct total energy "
4134                              "and/or pressure for isotropic systems, but not forces or surface "
4135                              "tensions.");
4136             }
4137             else
4138             {
4139                 warning_note(wi,
4140                              "You are using geometric combination rules in "
4141                              "LJ-PME, but your non-bonded C6 parameters do "
4142                              "not follow these rules. "
4143                              "This will introduce very small errors in the forces and energies in "
4144                              "your simulations. If your system is homogeneous, consider using "
4145                              "dispersion correction "
4146                              "for the total energy and pressure.");
4147             }
4148         }
4149     }
4150 }
4151
4152 void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_t wi)
4153 {
4154     char                      err_buf[STRLEN];
4155     int                       i, m, c, nmol;
4156     bool                      bCharge, bAcc;
4157     real *                    mgrp, mt;
4158     rvec                      acc;
4159     gmx_mtop_atomloop_block_t aloopb;
4160     ivec                      AbsRef;
4161     char                      warn_buf[STRLEN];
4162
4163     set_warning_line(wi, mdparin, -1);
4164
4165     if (absolute_reference(ir, sys, false, AbsRef))
4166     {
4167         warning_note(wi,
4168                      "Removing center of mass motion in the presence of position restraints might "
4169                      "cause artifacts. When you are using position restraints to equilibrate a "
4170                      "macro-molecule, the artifacts are usually negligible.");
4171     }
4172
4173     if (ir->cutoff_scheme == ecutsVERLET && ir->verletbuf_tol > 0 && ir->nstlist > 1
4174         && ((EI_MD(ir->eI) || EI_SD(ir->eI)) && (ir->etc == etcVRESCALE || ir->etc == etcBERENDSEN)))
4175     {
4176         /* Check if a too small Verlet buffer might potentially
4177          * cause more drift than the thermostat can couple off.
4178          */
4179         /* Temperature error fraction for warning and suggestion */
4180         const real T_error_warn    = 0.002;
4181         const real T_error_suggest = 0.001;
4182         /* For safety: 2 DOF per atom (typical with constraints) */
4183         const real nrdf_at = 2;
4184         real       T, tau, max_T_error;
4185         int        i;
4186
4187         T   = 0;
4188         tau = 0;
4189         for (i = 0; i < ir->opts.ngtc; i++)
4190         {
4191             T   = std::max(T, ir->opts.ref_t[i]);
4192             tau = std::max(tau, ir->opts.tau_t[i]);
4193         }
4194         if (T > 0)
4195         {
4196             /* This is a worst case estimate of the temperature error,
4197              * assuming perfect buffer estimation and no cancelation
4198              * of errors. The factor 0.5 is because energy distributes
4199              * equally over Ekin and Epot.
4200              */
4201             max_T_error = 0.5 * tau * ir->verletbuf_tol / (nrdf_at * BOLTZ * T);
4202             if (max_T_error > T_error_warn)
4203             {
4204                 sprintf(warn_buf,
4205                         "With a verlet-buffer-tolerance of %g kJ/mol/ps, a reference temperature "
4206                         "of %g and a tau_t of %g, your temperature might be off by up to %.1f%%. "
4207                         "To ensure the error is below %.1f%%, decrease verlet-buffer-tolerance to "
4208                         "%.0e or decrease tau_t.",
4209                         ir->verletbuf_tol, T, tau, 100 * max_T_error, 100 * T_error_suggest,
4210                         ir->verletbuf_tol * T_error_suggest / max_T_error);
4211                 warning(wi, warn_buf);
4212             }
4213         }
4214     }
4215
4216     if (ETC_ANDERSEN(ir->etc))
4217     {
4218         int i;
4219
4220         for (i = 0; i < ir->opts.ngtc; i++)
4221         {
4222             sprintf(err_buf,
4223                     "all tau_t must currently be equal using Andersen temperature control, "
4224                     "violated for group %d",
4225                     i);
4226             CHECK(ir->opts.tau_t[0] != ir->opts.tau_t[i]);
4227             sprintf(err_buf,
4228                     "all tau_t must be positive using Andersen temperature control, "
4229                     "tau_t[%d]=%10.6f",
4230                     i, ir->opts.tau_t[i]);
4231             CHECK(ir->opts.tau_t[i] < 0);
4232         }
4233
4234         if (ir->etc == etcANDERSENMASSIVE && ir->comm_mode != ecmNO)
4235         {
4236             for (i = 0; i < ir->opts.ngtc; i++)
4237             {
4238                 int nsteps = gmx::roundToInt(ir->opts.tau_t[i] / ir->delta_t);
4239                 sprintf(err_buf,
4240                         "tau_t/delta_t for group %d for temperature control method %s must be a "
4241                         "multiple of nstcomm (%d), as velocities of atoms in coupled groups are "
4242                         "randomized every time step. The input tau_t (%8.3f) leads to %d steps per "
4243                         "randomization",
4244                         i, etcoupl_names[ir->etc], ir->nstcomm, ir->opts.tau_t[i], nsteps);
4245                 CHECK(nsteps % ir->nstcomm != 0);
4246             }
4247         }
4248     }
4249
4250     if (EI_DYNAMICS(ir->eI) && !EI_SD(ir->eI) && ir->eI != eiBD && ir->comm_mode == ecmNO
4251         && !(absolute_reference(ir, sys, FALSE, AbsRef) || ir->nsteps <= 10) && !ETC_ANDERSEN(ir->etc))
4252     {
4253         warning(wi,
4254                 "You are not using center of mass motion removal (mdp option comm-mode), numerical "
4255                 "rounding errors can lead to build up of kinetic energy of the center of mass");
4256     }
4257
4258     if (ir->epc == epcPARRINELLORAHMAN && ir->etc == etcNOSEHOOVER)
4259     {
4260         real tau_t_max = 0;
4261         for (int g = 0; g < ir->opts.ngtc; g++)
4262         {
4263             tau_t_max = std::max(tau_t_max, ir->opts.tau_t[g]);
4264         }
4265         if (ir->tau_p < 1.9 * tau_t_max)
4266         {
4267             std::string message = gmx::formatString(
4268                     "With %s T-coupling and %s p-coupling, "
4269                     "%s (%g) should be at least twice as large as %s (%g) to avoid resonances",
4270                     etcoupl_names[ir->etc], epcoupl_names[ir->epc], "tau-p", ir->tau_p, "tau-t",
4271                     tau_t_max);
4272             warning(wi, message.c_str());
4273         }
4274     }
4275
4276     /* Check for pressure coupling with absolute position restraints */
4277     if (ir->epc != epcNO && ir->refcoord_scaling == erscNO)
4278     {
4279         absolute_reference(ir, sys, TRUE, AbsRef);
4280         {
4281             for (m = 0; m < DIM; m++)
4282             {
4283                 if (AbsRef[m] && norm2(ir->compress[m]) > 0)
4284                 {
4285                     warning(wi,
4286                             "You are using pressure coupling with absolute position restraints, "
4287                             "this will give artifacts. Use the refcoord_scaling option.");
4288                     break;
4289                 }
4290             }
4291         }
4292     }
4293
4294     bCharge = FALSE;
4295     aloopb  = gmx_mtop_atomloop_block_init(sys);
4296     const t_atom* atom;
4297     while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
4298     {
4299         if (atom->q != 0 || atom->qB != 0)
4300         {
4301             bCharge = TRUE;
4302         }
4303     }
4304
4305     if (!bCharge)
4306     {
4307         if (EEL_FULL(ir->coulombtype))
4308         {
4309             sprintf(err_buf,
4310                     "You are using full electrostatics treatment %s for a system without charges.\n"
4311                     "This costs a lot of performance for just processing zeros, consider using %s "
4312                     "instead.\n",
4313                     EELTYPE(ir->coulombtype), EELTYPE(eelCUT));
4314             warning(wi, err_buf);
4315         }
4316     }
4317     else
4318     {
4319         if (ir->coulombtype == eelCUT && ir->rcoulomb > 0)
4320         {
4321             sprintf(err_buf,
4322                     "You are using a plain Coulomb cut-off, which might produce artifacts.\n"
4323                     "You might want to consider using %s electrostatics.\n",
4324                     EELTYPE(eelPME));
4325             warning_note(wi, err_buf);
4326         }
4327     }
4328
4329     /* Check if combination rules used in LJ-PME are the same as in the force field */
4330     if (EVDW_PME(ir->vdwtype))
4331     {
4332         check_combination_rules(ir, sys, wi);
4333     }
4334
4335     /* Generalized reaction field */
4336     if (ir->coulombtype == eelGRF_NOTUSED)
4337     {
4338         warning_error(wi,
4339                       "Generalized reaction-field electrostatics is no longer supported. "
4340                       "You can use normal reaction-field instead and compute the reaction-field "
4341                       "constant by hand.");
4342     }
4343
4344     bAcc = FALSE;
4345     for (int i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4346     {
4347         for (m = 0; (m < DIM); m++)
4348         {
4349             if (fabs(ir->opts.acc[i][m]) > 1e-6)
4350             {
4351                 bAcc = TRUE;
4352             }
4353         }
4354     }
4355     if (bAcc)
4356     {
4357         clear_rvec(acc);
4358         snew(mgrp, sys->groups.groups[SimulationAtomGroupType::Acceleration].size());
4359         for (const AtomProxy atomP : AtomRange(*sys))
4360         {
4361             const t_atom& local = atomP.atom();
4362             int           i     = atomP.globalAtomNumber();
4363             mgrp[getGroupType(sys->groups, SimulationAtomGroupType::Acceleration, i)] += local.m;
4364         }
4365         mt = 0.0;
4366         for (i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4367         {
4368             for (m = 0; (m < DIM); m++)
4369             {
4370                 acc[m] += ir->opts.acc[i][m] * mgrp[i];
4371             }
4372             mt += mgrp[i];
4373         }
4374         for (m = 0; (m < DIM); m++)
4375         {
4376             if (fabs(acc[m]) > 1e-6)
4377             {
4378                 const char* dim[DIM] = { "X", "Y", "Z" };
4379                 fprintf(stderr, "Net Acceleration in %s direction, will %s be corrected\n", dim[m],
4380                         ir->nstcomm != 0 ? "" : "not");
4381                 if (ir->nstcomm != 0 && m < ndof_com(ir))
4382                 {
4383                     acc[m] /= mt;
4384                     for (i = 0;
4385                          (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4386                     {
4387                         ir->opts.acc[i][m] -= acc[m];
4388                     }
4389                 }
4390             }
4391         }
4392         sfree(mgrp);
4393     }
4394
4395     if (ir->efep != efepNO && ir->fepvals->sc_alpha != 0
4396         && !gmx_within_tol(sys->ffparams.reppow, 12.0, 10 * GMX_DOUBLE_EPS))
4397     {
4398         gmx_fatal(FARGS, "Soft-core interactions are only supported with VdW repulsion power 12");
4399     }
4400
4401     if (ir->bPull)
4402     {
4403         bool bWarned;
4404
4405         bWarned = FALSE;
4406         for (i = 0; i < ir->pull->ncoord && !bWarned; i++)
4407         {
4408             if (ir->pull->coord[i].group[0] == 0 || ir->pull->coord[i].group[1] == 0)
4409             {
4410                 absolute_reference(ir, sys, FALSE, AbsRef);
4411                 for (m = 0; m < DIM; m++)
4412                 {
4413                     if (ir->pull->coord[i].dim[m] && !AbsRef[m])
4414                     {
4415                         warning(wi,
4416                                 "You are using an absolute reference for pulling, but the rest of "
4417                                 "the system does not have an absolute reference. This will lead to "
4418                                 "artifacts.");
4419                         bWarned = TRUE;
4420                         break;
4421                     }
4422                 }
4423             }
4424         }
4425
4426         for (i = 0; i < 3; i++)
4427         {
4428             for (m = 0; m <= i; m++)
4429             {
4430                 if ((ir->epc != epcNO && ir->compress[i][m] != 0) || ir->deform[i][m] != 0)
4431                 {
4432                     for (c = 0; c < ir->pull->ncoord; c++)
4433                     {
4434                         if (ir->pull->coord[c].eGeom == epullgDIRPBC && ir->pull->coord[c].vec[m] != 0)
4435                         {
4436                             gmx_fatal(FARGS,
4437                                       "Can not have dynamic box while using pull geometry '%s' "
4438                                       "(dim %c)",
4439                                       EPULLGEOM(ir->pull->coord[c].eGeom), 'x' + m);
4440                         }
4441                     }
4442                 }
4443             }
4444         }
4445     }
4446
4447     check_disre(sys);
4448 }
4449
4450 void double_check(t_inputrec* ir, matrix box, bool bHasNormalConstraints, bool bHasAnyConstraints, warninp_t wi)
4451 {
4452     char        warn_buf[STRLEN];
4453     const char* ptr;
4454
4455     ptr = check_box(ir->pbcType, box);
4456     if (ptr)
4457     {
4458         warning_error(wi, ptr);
4459     }
4460
4461     if (bHasNormalConstraints && ir->eConstrAlg == econtSHAKE)
4462     {
4463         if (ir->shake_tol <= 0.0)
4464         {
4465             sprintf(warn_buf, "ERROR: shake-tol must be > 0 instead of %g\n", ir->shake_tol);
4466             warning_error(wi, warn_buf);
4467         }
4468     }
4469
4470     if ((ir->eConstrAlg == econtLINCS) && bHasNormalConstraints)
4471     {
4472         /* If we have Lincs constraints: */
4473         if (ir->eI == eiMD && ir->etc == etcNO && ir->eConstrAlg == econtLINCS && ir->nLincsIter == 1)
4474         {
4475             sprintf(warn_buf,
4476                     "For energy conservation with LINCS, lincs_iter should be 2 or larger.\n");
4477             warning_note(wi, warn_buf);
4478         }
4479
4480         if ((ir->eI == eiCG || ir->eI == eiLBFGS) && (ir->nProjOrder < 8))
4481         {
4482             sprintf(warn_buf,
4483                     "For accurate %s with LINCS constraints, lincs-order should be 8 or more.",
4484                     ei_names[ir->eI]);
4485             warning_note(wi, warn_buf);
4486         }
4487         if (ir->epc == epcMTTK)
4488         {
4489             warning_error(wi, "MTTK not compatible with lincs -- use shake instead.");
4490         }
4491     }
4492
4493     if (bHasAnyConstraints && ir->epc == epcMTTK)
4494     {
4495         warning_error(wi, "Constraints are not implemented with MTTK pressure control.");
4496     }
4497
4498     if (ir->LincsWarnAngle > 90.0)
4499     {
4500         sprintf(warn_buf, "lincs-warnangle can not be larger than 90 degrees, setting it to 90.\n");
4501         warning(wi, warn_buf);
4502         ir->LincsWarnAngle = 90.0;
4503     }
4504
4505     if (ir->pbcType != PbcType::No)
4506     {
4507         if (ir->nstlist == 0)
4508         {
4509             warning(wi,
4510                     "With nstlist=0 atoms are only put into the box at step 0, therefore drifting "
4511                     "atoms might cause the simulation to crash.");
4512         }
4513         if (gmx::square(ir->rlist) >= max_cutoff2(ir->pbcType, box))
4514         {
4515             sprintf(warn_buf,
4516                     "ERROR: The cut-off length is longer than half the shortest box vector or "
4517                     "longer than the smallest box diagonal element. Increase the box size or "
4518                     "decrease rlist.\n");
4519             warning_error(wi, warn_buf);
4520         }
4521     }
4522 }