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