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