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