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