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