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