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