Make PBC type enumeration into PbcType enum class
[gromacs.git] / src / gromacs / gmxpreprocess / readir.cpp
blob657fcea1e64c1251cf396c72933b5454799c5c3c
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013-2019,2020, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gmxpre.h"
39 #include "readir.h"
41 #include <cctype>
42 #include <climits>
43 #include <cmath>
44 #include <cstdlib>
46 #include <algorithm>
47 #include <string>
49 #include "gromacs/awh/read_params.h"
50 #include "gromacs/fileio/readinp.h"
51 #include "gromacs/fileio/warninp.h"
52 #include "gromacs/gmxlib/network.h"
53 #include "gromacs/gmxpreprocess/toputil.h"
54 #include "gromacs/math/functions.h"
55 #include "gromacs/math/units.h"
56 #include "gromacs/math/vec.h"
57 #include "gromacs/mdlib/calc_verletbuf.h"
58 #include "gromacs/mdrun/mdmodules.h"
59 #include "gromacs/mdtypes/inputrec.h"
60 #include "gromacs/mdtypes/md_enums.h"
61 #include "gromacs/mdtypes/pull_params.h"
62 #include "gromacs/options/options.h"
63 #include "gromacs/options/treesupport.h"
64 #include "gromacs/pbcutil/pbc.h"
65 #include "gromacs/selection/indexutil.h"
66 #include "gromacs/topology/block.h"
67 #include "gromacs/topology/ifunc.h"
68 #include "gromacs/topology/index.h"
69 #include "gromacs/topology/mtop_util.h"
70 #include "gromacs/topology/symtab.h"
71 #include "gromacs/topology/topology.h"
72 #include "gromacs/utility/cstringutil.h"
73 #include "gromacs/utility/exceptions.h"
74 #include "gromacs/utility/fatalerror.h"
75 #include "gromacs/utility/filestream.h"
76 #include "gromacs/utility/gmxassert.h"
77 #include "gromacs/utility/ikeyvaluetreeerror.h"
78 #include "gromacs/utility/keyvaluetree.h"
79 #include "gromacs/utility/keyvaluetreebuilder.h"
80 #include "gromacs/utility/keyvaluetreemdpwriter.h"
81 #include "gromacs/utility/keyvaluetreetransform.h"
82 #include "gromacs/utility/mdmodulenotification.h"
83 #include "gromacs/utility/smalloc.h"
84 #include "gromacs/utility/strconvert.h"
85 #include "gromacs/utility/stringcompare.h"
86 #include "gromacs/utility/stringutil.h"
87 #include "gromacs/utility/textwriter.h"
89 #define MAXPTR 254
90 #define NOGID 255
92 /* Resource parameters
93 * Do not change any of these until you read the instruction
94 * in readinp.h. Some cpp's do not take spaces after the backslash
95 * (like the c-shell), which will give you a very weird compiler
96 * message.
99 typedef struct t_inputrec_strings
101 char tcgrps[STRLEN], tau_t[STRLEN], ref_t[STRLEN], acc[STRLEN], accgrps[STRLEN], freeze[STRLEN],
102 frdim[STRLEN], energy[STRLEN], user1[STRLEN], user2[STRLEN], vcm[STRLEN],
103 x_compressed_groups[STRLEN], couple_moltype[STRLEN], orirefitgrp[STRLEN],
104 egptable[STRLEN], egpexcl[STRLEN], wall_atomtype[STRLEN], wall_density[STRLEN],
105 deform[STRLEN], QMMM[STRLEN], imd_grp[STRLEN];
106 char fep_lambda[efptNR][STRLEN];
107 char lambda_weights[STRLEN];
108 char** pull_grp;
109 char** rot_grp;
110 char anneal[STRLEN], anneal_npoints[STRLEN], anneal_time[STRLEN], anneal_temp[STRLEN];
111 char QMmethod[STRLEN], QMbasis[STRLEN], QMcharge[STRLEN], QMmult[STRLEN], bSH[STRLEN],
112 CASorbitals[STRLEN], CASelectrons[STRLEN], SAon[STRLEN], SAoff[STRLEN], SAsteps[STRLEN];
114 } gmx_inputrec_strings;
116 static gmx_inputrec_strings* is = nullptr;
118 void init_inputrec_strings()
120 if (is)
122 gmx_incons(
123 "Attempted to call init_inputrec_strings before calling done_inputrec_strings. "
124 "Only one inputrec (i.e. .mdp file) can be parsed at a time.");
126 snew(is, 1);
129 void done_inputrec_strings()
131 sfree(is);
132 is = nullptr;
136 enum
138 egrptpALL, /* All particles have to be a member of a group. */
139 egrptpALL_GENREST, /* A rest group with name is generated for particles *
140 * that are not part of any group. */
141 egrptpPART, /* As egrptpALL_GENREST, but no name is generated *
142 * for the rest group. */
143 egrptpONE /* Merge all selected groups into one group, *
144 * make a rest group for the remaining particles. */
147 static const char* constraints[eshNR + 1] = { "none", "h-bonds", "all-bonds",
148 "h-angles", "all-angles", nullptr };
150 static const char* couple_lam[ecouplamNR + 1] = { "vdw-q", "vdw", "q", "none", nullptr };
152 static void GetSimTemps(int ntemps, t_simtemp* simtemp, double* temperature_lambdas)
155 int i;
157 for (i = 0; i < ntemps; i++)
159 /* simple linear scaling -- allows more control */
160 if (simtemp->eSimTempScale == esimtempLINEAR)
162 simtemp->temperatures[i] =
163 simtemp->simtemp_low
164 + (simtemp->simtemp_high - simtemp->simtemp_low) * temperature_lambdas[i];
166 else if (simtemp->eSimTempScale
167 == esimtempGEOMETRIC) /* should give roughly equal acceptance for constant heat capacity . . . */
169 simtemp->temperatures[i] = simtemp->simtemp_low
170 * std::pow(simtemp->simtemp_high / simtemp->simtemp_low,
171 static_cast<real>((1.0 * i) / (ntemps - 1)));
173 else if (simtemp->eSimTempScale == esimtempEXPONENTIAL)
175 simtemp->temperatures[i] = simtemp->simtemp_low
176 + (simtemp->simtemp_high - simtemp->simtemp_low)
177 * (std::expm1(temperature_lambdas[i]) / std::expm1(1.0));
179 else
181 char errorstr[128];
182 sprintf(errorstr, "eSimTempScale=%d not defined", simtemp->eSimTempScale);
183 gmx_fatal(FARGS, "%s", errorstr);
189 static void _low_check(bool b, const char* s, warninp_t wi)
191 if (b)
193 warning_error(wi, s);
197 static void check_nst(const char* desc_nst, int nst, const char* desc_p, int* p, warninp_t wi)
199 char buf[STRLEN];
201 if (*p > 0 && *p % nst != 0)
203 /* Round up to the next multiple of nst */
204 *p = ((*p) / nst + 1) * nst;
205 sprintf(buf, "%s should be a multiple of %s, changing %s to %d\n", desc_p, desc_nst, desc_p, *p);
206 warning(wi, buf);
210 static int lcd(int n1, int n2)
212 int d, i;
214 d = 1;
215 for (i = 2; (i <= n1 && i <= n2); i++)
217 if (n1 % i == 0 && n2 % i == 0)
219 d = i;
223 return d;
226 //! Convert legacy mdp entries to modern ones.
227 static void process_interaction_modifier(int* eintmod)
229 if (*eintmod == eintmodPOTSHIFT_VERLET_UNSUPPORTED)
231 *eintmod = eintmodPOTSHIFT;
235 void check_ir(const char* mdparin,
236 const gmx::MdModulesNotifier& mdModulesNotifier,
237 t_inputrec* ir,
238 t_gromppopts* opts,
239 warninp_t wi)
240 /* Check internal consistency.
241 * NOTE: index groups are not set here yet, don't check things
242 * like temperature coupling group options here, but in triple_check
245 /* Strange macro: first one fills the err_buf, and then one can check
246 * the condition, which will print the message and increase the error
247 * counter.
249 #define CHECK(b) _low_check(b, err_buf, wi)
250 char err_buf[256], warn_buf[STRLEN];
251 int i, j;
252 real dt_pcoupl;
253 t_lambda* fep = ir->fepvals;
254 t_expanded* expand = ir->expandedvals;
256 set_warning_line(wi, mdparin, -1);
258 if (ir->coulombtype == eelRF_NEC_UNSUPPORTED)
260 sprintf(warn_buf, "%s electrostatics is no longer supported", eel_names[eelRF_NEC_UNSUPPORTED]);
261 warning_error(wi, warn_buf);
264 /* BASIC CUT-OFF STUFF */
265 if (ir->rcoulomb < 0)
267 warning_error(wi, "rcoulomb should be >= 0");
269 if (ir->rvdw < 0)
271 warning_error(wi, "rvdw should be >= 0");
273 if (ir->rlist < 0 && !(ir->cutoff_scheme == ecutsVERLET && ir->verletbuf_tol > 0))
275 warning_error(wi, "rlist should be >= 0");
277 sprintf(err_buf,
278 "nstlist can not be smaller than 0. (If you were trying to use the heuristic "
279 "neighbour-list update scheme for efficient buffering for improved energy "
280 "conservation, please use the Verlet cut-off scheme instead.)");
281 CHECK(ir->nstlist < 0);
283 process_interaction_modifier(&ir->coulomb_modifier);
284 process_interaction_modifier(&ir->vdw_modifier);
286 if (ir->cutoff_scheme == ecutsGROUP)
288 gmx_fatal(FARGS,
289 "The group cutoff scheme has been removed since GROMACS 2020. "
290 "Please use the Verlet cutoff scheme.");
292 if (ir->cutoff_scheme == ecutsVERLET)
294 real rc_max;
296 /* Normal Verlet type neighbor-list, currently only limited feature support */
297 if (inputrec2nboundeddim(ir) < 3)
299 warning_error(wi, "With Verlet lists only full pbc or pbc=xy with walls is supported");
302 // We don't (yet) have general Verlet kernels for rcoulomb!=rvdw
303 if (ir->rcoulomb != ir->rvdw)
305 // Since we have PME coulomb + LJ cut-off kernels with rcoulomb>rvdw
306 // for PME load balancing, we can support this exception.
307 bool bUsesPmeTwinRangeKernel = (EEL_PME_EWALD(ir->coulombtype) && ir->vdwtype == evdwCUT
308 && ir->rcoulomb > ir->rvdw);
309 if (!bUsesPmeTwinRangeKernel)
311 warning_error(wi,
312 "With Verlet lists rcoulomb!=rvdw is not supported (except for "
313 "rcoulomb>rvdw with PME electrostatics)");
317 if (ir->vdwtype == evdwSHIFT || ir->vdwtype == evdwSWITCH)
319 if (ir->vdw_modifier == eintmodNONE || ir->vdw_modifier == eintmodPOTSHIFT)
321 ir->vdw_modifier = (ir->vdwtype == evdwSHIFT ? eintmodFORCESWITCH : eintmodPOTSWITCH);
323 sprintf(warn_buf,
324 "Replacing vdwtype=%s by the equivalent combination of vdwtype=%s and "
325 "vdw_modifier=%s",
326 evdw_names[ir->vdwtype], evdw_names[evdwCUT], eintmod_names[ir->vdw_modifier]);
327 warning_note(wi, warn_buf);
329 ir->vdwtype = evdwCUT;
331 else
333 sprintf(warn_buf, "Unsupported combination of vdwtype=%s and vdw_modifier=%s",
334 evdw_names[ir->vdwtype], eintmod_names[ir->vdw_modifier]);
335 warning_error(wi, warn_buf);
339 if (!(ir->vdwtype == evdwCUT || ir->vdwtype == evdwPME))
341 warning_error(wi,
342 "With Verlet lists only cut-off and PME LJ interactions are supported");
344 if (!(ir->coulombtype == eelCUT || EEL_RF(ir->coulombtype) || EEL_PME(ir->coulombtype)
345 || ir->coulombtype == eelEWALD))
347 warning_error(wi,
348 "With Verlet lists only cut-off, reaction-field, PME and Ewald "
349 "electrostatics are supported");
351 if (!(ir->coulomb_modifier == eintmodNONE || ir->coulomb_modifier == eintmodPOTSHIFT))
353 sprintf(warn_buf, "coulomb_modifier=%s is not supported", eintmod_names[ir->coulomb_modifier]);
354 warning_error(wi, warn_buf);
357 if (EEL_USER(ir->coulombtype))
359 sprintf(warn_buf, "Coulomb type %s is not supported with the verlet scheme",
360 eel_names[ir->coulombtype]);
361 warning_error(wi, warn_buf);
364 if (ir->nstlist <= 0)
366 warning_error(wi, "With Verlet lists nstlist should be larger than 0");
369 if (ir->nstlist < 10)
371 warning_note(wi,
372 "With Verlet lists the optimal nstlist is >= 10, with GPUs >= 20. Note "
373 "that with the Verlet scheme, nstlist has no effect on the accuracy of "
374 "your simulation.");
377 rc_max = std::max(ir->rvdw, ir->rcoulomb);
379 if (EI_TPI(ir->eI))
381 /* With TPI we set the pairlist cut-off later using the radius of the insterted molecule */
382 ir->verletbuf_tol = 0;
383 ir->rlist = rc_max;
385 else if (ir->verletbuf_tol <= 0)
387 if (ir->verletbuf_tol == 0)
389 warning_error(wi, "Can not have Verlet buffer tolerance of exactly 0");
392 if (ir->rlist < rc_max)
394 warning_error(wi,
395 "With verlet lists rlist can not be smaller than rvdw or rcoulomb");
398 if (ir->rlist == rc_max && ir->nstlist > 1)
400 warning_note(
402 "rlist is equal to rvdw and/or rcoulomb: there is no explicit Verlet "
403 "buffer. The cluster pair list does have a buffering effect, but choosing "
404 "a larger rlist might be necessary for good energy conservation.");
407 else
409 if (ir->rlist > rc_max)
411 warning_note(wi,
412 "You have set rlist larger than the interaction cut-off, but you also "
413 "have verlet-buffer-tolerance > 0. Will set rlist using "
414 "verlet-buffer-tolerance.");
417 if (ir->nstlist == 1)
419 /* No buffer required */
420 ir->rlist = rc_max;
422 else
424 if (EI_DYNAMICS(ir->eI))
426 if (inputrec2nboundeddim(ir) < 3)
428 warning_error(wi,
429 "The box volume is required for calculating rlist from the "
430 "energy drift with verlet-buffer-tolerance > 0. You are "
431 "using at least one unbounded dimension, so no volume can be "
432 "computed. Either use a finite box, or set rlist yourself "
433 "together with verlet-buffer-tolerance = -1.");
435 /* Set rlist temporarily so we can continue processing */
436 ir->rlist = rc_max;
438 else
440 /* Set the buffer to 5% of the cut-off */
441 ir->rlist = (1.0 + verlet_buffer_ratio_nodynamics) * rc_max;
447 /* GENERAL INTEGRATOR STUFF */
448 if (!EI_MD(ir->eI))
450 if (ir->etc != etcNO)
452 if (EI_RANDOM(ir->eI))
454 sprintf(warn_buf,
455 "Setting tcoupl from '%s' to 'no'. %s handles temperature coupling "
456 "implicitly. See the documentation for more information on which "
457 "parameters affect temperature for %s.",
458 etcoupl_names[ir->etc], ei_names[ir->eI], ei_names[ir->eI]);
460 else
462 sprintf(warn_buf,
463 "Setting tcoupl from '%s' to 'no'. Temperature coupling does not apply to "
464 "%s.",
465 etcoupl_names[ir->etc], ei_names[ir->eI]);
467 warning_note(wi, warn_buf);
469 ir->etc = etcNO;
471 if (ir->eI == eiVVAK)
473 sprintf(warn_buf,
474 "Integrator method %s is implemented primarily for validation purposes; for "
475 "molecular dynamics, you should probably be using %s or %s",
476 ei_names[eiVVAK], ei_names[eiMD], ei_names[eiVV]);
477 warning_note(wi, warn_buf);
479 if (!EI_DYNAMICS(ir->eI))
481 if (ir->epc != epcNO)
483 sprintf(warn_buf,
484 "Setting pcoupl from '%s' to 'no'. Pressure coupling does not apply to %s.",
485 epcoupl_names[ir->epc], ei_names[ir->eI]);
486 warning_note(wi, warn_buf);
488 ir->epc = epcNO;
490 if (EI_DYNAMICS(ir->eI))
492 if (ir->nstcalcenergy < 0)
494 ir->nstcalcenergy = ir_optimal_nstcalcenergy(ir);
495 if (ir->nstenergy != 0 && ir->nstenergy < ir->nstcalcenergy)
497 /* nstcalcenergy larger than nstener does not make sense.
498 * We ideally want nstcalcenergy=nstener.
500 if (ir->nstlist > 0)
502 ir->nstcalcenergy = lcd(ir->nstenergy, ir->nstlist);
504 else
506 ir->nstcalcenergy = ir->nstenergy;
510 else if ((ir->nstenergy > 0 && ir->nstcalcenergy > ir->nstenergy)
511 || (ir->efep != efepNO && ir->fepvals->nstdhdl > 0
512 && (ir->nstcalcenergy > ir->fepvals->nstdhdl)))
515 const char* nsten = "nstenergy";
516 const char* nstdh = "nstdhdl";
517 const char* min_name = nsten;
518 int min_nst = ir->nstenergy;
520 /* find the smallest of ( nstenergy, nstdhdl ) */
521 if (ir->efep != efepNO && ir->fepvals->nstdhdl > 0
522 && (ir->nstenergy == 0 || ir->fepvals->nstdhdl < ir->nstenergy))
524 min_nst = ir->fepvals->nstdhdl;
525 min_name = nstdh;
527 /* If the user sets nstenergy small, we should respect that */
528 sprintf(warn_buf, "Setting nstcalcenergy (%d) equal to %s (%d)", ir->nstcalcenergy,
529 min_name, min_nst);
530 warning_note(wi, warn_buf);
531 ir->nstcalcenergy = min_nst;
534 if (ir->epc != epcNO)
536 if (ir->nstpcouple < 0)
538 ir->nstpcouple = ir_optimal_nstpcouple(ir);
542 if (ir->nstcalcenergy > 0)
544 if (ir->efep != efepNO)
546 /* nstdhdl should be a multiple of nstcalcenergy */
547 check_nst("nstcalcenergy", ir->nstcalcenergy, "nstdhdl", &ir->fepvals->nstdhdl, wi);
549 if (ir->bExpanded)
551 /* nstexpanded should be a multiple of nstcalcenergy */
552 check_nst("nstcalcenergy", ir->nstcalcenergy, "nstexpanded",
553 &ir->expandedvals->nstexpanded, wi);
555 /* for storing exact averages nstenergy should be
556 * a multiple of nstcalcenergy
558 check_nst("nstcalcenergy", ir->nstcalcenergy, "nstenergy", &ir->nstenergy, wi);
561 // Inquire all MdModules, if their parameters match with the energy
562 // calculation frequency
563 gmx::EnergyCalculationFrequencyErrors energyCalculationFrequencyErrors(ir->nstcalcenergy);
564 mdModulesNotifier.notifier_.notify(&energyCalculationFrequencyErrors);
566 // Emit all errors from the energy calculation frequency checks
567 for (const std::string& energyFrequencyErrorMessage :
568 energyCalculationFrequencyErrors.errorMessages())
570 warning_error(wi, energyFrequencyErrorMessage);
574 if (ir->nsteps == 0 && !ir->bContinuation)
576 warning_note(wi,
577 "For a correct single-point energy evaluation with nsteps = 0, use "
578 "continuation = yes to avoid constraining the input coordinates.");
581 /* LD STUFF */
582 if ((EI_SD(ir->eI) || ir->eI == eiBD) && ir->bContinuation && ir->ld_seed != -1)
584 warning_note(wi,
585 "You are doing a continuation with SD or BD, make sure that ld_seed is "
586 "different from the previous run (using ld_seed=-1 will ensure this)");
589 /* TPI STUFF */
590 if (EI_TPI(ir->eI))
592 sprintf(err_buf, "TPI only works with pbc = %s", c_pbcTypeNames[PbcType::Xyz].c_str());
593 CHECK(ir->pbcType != PbcType::Xyz);
594 sprintf(err_buf, "with TPI nstlist should be larger than zero");
595 CHECK(ir->nstlist <= 0);
596 sprintf(err_buf, "TPI does not work with full electrostatics other than PME");
597 CHECK(EEL_FULL(ir->coulombtype) && !EEL_PME(ir->coulombtype));
600 /* SHAKE / LINCS */
601 if ((opts->nshake > 0) && (opts->bMorse))
603 sprintf(warn_buf, "Using morse bond-potentials while constraining bonds is useless");
604 warning(wi, warn_buf);
607 if ((EI_SD(ir->eI) || ir->eI == eiBD) && ir->bContinuation && ir->ld_seed != -1)
609 warning_note(wi,
610 "You are doing a continuation with SD or BD, make sure that ld_seed is "
611 "different from the previous run (using ld_seed=-1 will ensure this)");
613 /* verify simulated tempering options */
615 if (ir->bSimTemp)
617 bool bAllTempZero = TRUE;
618 for (i = 0; i < fep->n_lambda; i++)
620 sprintf(err_buf, "Entry %d for %s must be between 0 and 1, instead is %g", i,
621 efpt_names[efptTEMPERATURE], fep->all_lambda[efptTEMPERATURE][i]);
622 CHECK((fep->all_lambda[efptTEMPERATURE][i] < 0) || (fep->all_lambda[efptTEMPERATURE][i] > 1));
623 if (fep->all_lambda[efptTEMPERATURE][i] > 0)
625 bAllTempZero = FALSE;
628 sprintf(err_buf, "if simulated tempering is on, temperature-lambdas may not be all zero");
629 CHECK(bAllTempZero == TRUE);
631 sprintf(err_buf, "Simulated tempering is currently only compatible with md-vv");
632 CHECK(ir->eI != eiVV);
634 /* check compatability of the temperature coupling with simulated tempering */
636 if (ir->etc == etcNOSEHOOVER)
638 sprintf(warn_buf,
639 "Nose-Hoover based temperature control such as [%s] my not be "
640 "entirelyconsistent with simulated tempering",
641 etcoupl_names[ir->etc]);
642 warning_note(wi, warn_buf);
645 /* check that the temperatures make sense */
647 sprintf(err_buf,
648 "Higher simulated tempering temperature (%g) must be >= than the simulated "
649 "tempering lower temperature (%g)",
650 ir->simtempvals->simtemp_high, ir->simtempvals->simtemp_low);
651 CHECK(ir->simtempvals->simtemp_high <= ir->simtempvals->simtemp_low);
653 sprintf(err_buf, "Higher simulated tempering temperature (%g) must be >= zero",
654 ir->simtempvals->simtemp_high);
655 CHECK(ir->simtempvals->simtemp_high <= 0);
657 sprintf(err_buf, "Lower simulated tempering temperature (%g) must be >= zero",
658 ir->simtempvals->simtemp_low);
659 CHECK(ir->simtempvals->simtemp_low <= 0);
662 /* verify free energy options */
664 if (ir->efep != efepNO)
666 fep = ir->fepvals;
667 sprintf(err_buf, "The soft-core power is %d and can only be 1 or 2", fep->sc_power);
668 CHECK(fep->sc_alpha != 0 && fep->sc_power != 1 && fep->sc_power != 2);
670 sprintf(err_buf, "The soft-core sc-r-power is %d and can only be 6 or 48",
671 static_cast<int>(fep->sc_r_power));
672 CHECK(fep->sc_alpha != 0 && fep->sc_r_power != 6.0 && fep->sc_r_power != 48.0);
674 sprintf(err_buf,
675 "Can't use positive delta-lambda (%g) if initial state/lambda does not start at "
676 "zero",
677 fep->delta_lambda);
678 CHECK(fep->delta_lambda > 0 && ((fep->init_fep_state > 0) || (fep->init_lambda > 0)));
680 sprintf(err_buf, "Can't use positive delta-lambda (%g) with expanded ensemble simulations",
681 fep->delta_lambda);
682 CHECK(fep->delta_lambda > 0 && (ir->efep == efepEXPANDED));
684 sprintf(err_buf, "Can only use expanded ensemble with md-vv (for now)");
685 CHECK(!(EI_VV(ir->eI)) && (ir->efep == efepEXPANDED));
687 sprintf(err_buf, "Free-energy not implemented for Ewald");
688 CHECK(ir->coulombtype == eelEWALD);
690 /* check validty of lambda inputs */
691 if (fep->n_lambda == 0)
693 /* Clear output in case of no states:*/
694 sprintf(err_buf, "init-lambda-state set to %d: no lambda states are defined.",
695 fep->init_fep_state);
696 CHECK((fep->init_fep_state >= 0) && (fep->n_lambda == 0));
698 else
700 sprintf(err_buf, "initial thermodynamic state %d does not exist, only goes to %d",
701 fep->init_fep_state, fep->n_lambda - 1);
702 CHECK((fep->init_fep_state >= fep->n_lambda));
705 sprintf(err_buf,
706 "Lambda state must be set, either with init-lambda-state or with init-lambda");
707 CHECK((fep->init_fep_state < 0) && (fep->init_lambda < 0));
709 sprintf(err_buf,
710 "init-lambda=%g while init-lambda-state=%d. Lambda state must be set either with "
711 "init-lambda-state or with init-lambda, but not both",
712 fep->init_lambda, fep->init_fep_state);
713 CHECK((fep->init_fep_state >= 0) && (fep->init_lambda >= 0));
716 if ((fep->init_lambda >= 0) && (fep->delta_lambda == 0))
718 int n_lambda_terms;
719 n_lambda_terms = 0;
720 for (i = 0; i < efptNR; i++)
722 if (fep->separate_dvdl[i])
724 n_lambda_terms++;
727 if (n_lambda_terms > 1)
729 sprintf(warn_buf,
730 "If lambda vector states (fep-lambdas, coul-lambdas etc.) are set, don't "
731 "use init-lambda to set lambda state (except for slow growth). Use "
732 "init-lambda-state instead.");
733 warning(wi, warn_buf);
736 if (n_lambda_terms < 2 && fep->n_lambda > 0)
738 warning_note(wi,
739 "init-lambda is deprecated for setting lambda state (except for slow "
740 "growth). Use init-lambda-state instead.");
744 for (j = 0; j < efptNR; j++)
746 for (i = 0; i < fep->n_lambda; i++)
748 sprintf(err_buf, "Entry %d for %s must be between 0 and 1, instead is %g", i,
749 efpt_names[j], fep->all_lambda[j][i]);
750 CHECK((fep->all_lambda[j][i] < 0) || (fep->all_lambda[j][i] > 1));
754 if ((fep->sc_alpha > 0) && (!fep->bScCoul))
756 for (i = 0; i < fep->n_lambda; i++)
758 sprintf(err_buf,
759 "For state %d, vdw-lambdas (%f) is changing with vdw softcore, while "
760 "coul-lambdas (%f) is nonzero without coulomb softcore: this will lead to "
761 "crashes, and is not supported.",
762 i, fep->all_lambda[efptVDW][i], fep->all_lambda[efptCOUL][i]);
763 CHECK((fep->sc_alpha > 0)
764 && (((fep->all_lambda[efptCOUL][i] > 0.0) && (fep->all_lambda[efptCOUL][i] < 1.0))
765 && ((fep->all_lambda[efptVDW][i] > 0.0) && (fep->all_lambda[efptVDW][i] < 1.0))));
769 if ((fep->bScCoul) && (EEL_PME(ir->coulombtype)))
771 real sigma, lambda, r_sc;
773 sigma = 0.34;
774 /* Maximum estimate for A and B charges equal with lambda power 1 */
775 lambda = 0.5;
776 r_sc = std::pow(lambda * fep->sc_alpha * std::pow(sigma / ir->rcoulomb, fep->sc_r_power) + 1.0,
777 1.0 / fep->sc_r_power);
778 sprintf(warn_buf,
779 "With PME there is a minor soft core effect present at the cut-off, "
780 "proportional to (LJsigma/rcoulomb)^%g. This could have a minor effect on "
781 "energy conservation, but usually other effects dominate. With a common sigma "
782 "value of %g nm the fraction of the particle-particle potential at the cut-off "
783 "at lambda=%g is around %.1e, while ewald-rtol is %.1e.",
784 fep->sc_r_power, sigma, lambda, r_sc - 1.0, ir->ewald_rtol);
785 warning_note(wi, warn_buf);
788 /* Free Energy Checks -- In an ideal world, slow growth and FEP would
789 be treated differently, but that's the next step */
791 for (i = 0; i < efptNR; i++)
793 for (j = 0; j < fep->n_lambda; j++)
795 sprintf(err_buf, "%s[%d] must be between 0 and 1", efpt_names[i], j);
796 CHECK((fep->all_lambda[i][j] < 0) || (fep->all_lambda[i][j] > 1));
801 if ((ir->bSimTemp) || (ir->efep == efepEXPANDED))
803 fep = ir->fepvals;
805 /* checking equilibration of weights inputs for validity */
807 sprintf(err_buf,
808 "weight-equil-number-all-lambda (%d) is ignored if lmc-weights-equil is not equal "
809 "to %s",
810 expand->equil_n_at_lam, elmceq_names[elmceqNUMATLAM]);
811 CHECK((expand->equil_n_at_lam > 0) && (expand->elmceq != elmceqNUMATLAM));
813 sprintf(err_buf,
814 "weight-equil-number-samples (%d) is ignored if lmc-weights-equil is not equal to "
815 "%s",
816 expand->equil_samples, elmceq_names[elmceqSAMPLES]);
817 CHECK((expand->equil_samples > 0) && (expand->elmceq != elmceqSAMPLES));
819 sprintf(err_buf,
820 "weight-equil-number-steps (%d) is ignored if lmc-weights-equil is not equal to %s",
821 expand->equil_steps, elmceq_names[elmceqSTEPS]);
822 CHECK((expand->equil_steps > 0) && (expand->elmceq != elmceqSTEPS));
824 sprintf(err_buf,
825 "weight-equil-wl-delta (%d) is ignored if lmc-weights-equil is not equal to %s",
826 expand->equil_samples, elmceq_names[elmceqWLDELTA]);
827 CHECK((expand->equil_wl_delta > 0) && (expand->elmceq != elmceqWLDELTA));
829 sprintf(err_buf,
830 "weight-equil-count-ratio (%f) is ignored if lmc-weights-equil is not equal to %s",
831 expand->equil_ratio, elmceq_names[elmceqRATIO]);
832 CHECK((expand->equil_ratio > 0) && (expand->elmceq != elmceqRATIO));
834 sprintf(err_buf,
835 "weight-equil-number-all-lambda (%d) must be a positive integer if "
836 "lmc-weights-equil=%s",
837 expand->equil_n_at_lam, elmceq_names[elmceqNUMATLAM]);
838 CHECK((expand->equil_n_at_lam <= 0) && (expand->elmceq == elmceqNUMATLAM));
840 sprintf(err_buf,
841 "weight-equil-number-samples (%d) must be a positive integer if "
842 "lmc-weights-equil=%s",
843 expand->equil_samples, elmceq_names[elmceqSAMPLES]);
844 CHECK((expand->equil_samples <= 0) && (expand->elmceq == elmceqSAMPLES));
846 sprintf(err_buf,
847 "weight-equil-number-steps (%d) must be a positive integer if lmc-weights-equil=%s",
848 expand->equil_steps, elmceq_names[elmceqSTEPS]);
849 CHECK((expand->equil_steps <= 0) && (expand->elmceq == elmceqSTEPS));
851 sprintf(err_buf, "weight-equil-wl-delta (%f) must be > 0 if lmc-weights-equil=%s",
852 expand->equil_wl_delta, elmceq_names[elmceqWLDELTA]);
853 CHECK((expand->equil_wl_delta <= 0) && (expand->elmceq == elmceqWLDELTA));
855 sprintf(err_buf, "weight-equil-count-ratio (%f) must be > 0 if lmc-weights-equil=%s",
856 expand->equil_ratio, elmceq_names[elmceqRATIO]);
857 CHECK((expand->equil_ratio <= 0) && (expand->elmceq == elmceqRATIO));
859 sprintf(err_buf, "lmc-weights-equil=%s only possible when lmc-stats = %s or lmc-stats %s",
860 elmceq_names[elmceqWLDELTA], elamstats_names[elamstatsWL], elamstats_names[elamstatsWWL]);
861 CHECK((expand->elmceq == elmceqWLDELTA) && (!EWL(expand->elamstats)));
863 sprintf(err_buf, "lmc-repeats (%d) must be greater than 0", expand->lmc_repeats);
864 CHECK((expand->lmc_repeats <= 0));
865 sprintf(err_buf, "minimum-var-min (%d) must be greater than 0", expand->minvarmin);
866 CHECK((expand->minvarmin <= 0));
867 sprintf(err_buf, "weight-c-range (%d) must be greater or equal to 0", expand->c_range);
868 CHECK((expand->c_range < 0));
869 sprintf(err_buf,
870 "init-lambda-state (%d) must be zero if lmc-forced-nstart (%d)> 0 and lmc-move != "
871 "'no'",
872 fep->init_fep_state, expand->lmc_forced_nstart);
873 CHECK((fep->init_fep_state != 0) && (expand->lmc_forced_nstart > 0)
874 && (expand->elmcmove != elmcmoveNO));
875 sprintf(err_buf, "lmc-forced-nstart (%d) must not be negative", expand->lmc_forced_nstart);
876 CHECK((expand->lmc_forced_nstart < 0));
877 sprintf(err_buf, "init-lambda-state (%d) must be in the interval [0,number of lambdas)",
878 fep->init_fep_state);
879 CHECK((fep->init_fep_state < 0) || (fep->init_fep_state >= fep->n_lambda));
881 sprintf(err_buf, "init-wl-delta (%f) must be greater than or equal to 0", expand->init_wl_delta);
882 CHECK((expand->init_wl_delta < 0));
883 sprintf(err_buf, "wl-ratio (%f) must be between 0 and 1", expand->wl_ratio);
884 CHECK((expand->wl_ratio <= 0) || (expand->wl_ratio >= 1));
885 sprintf(err_buf, "wl-scale (%f) must be between 0 and 1", expand->wl_scale);
886 CHECK((expand->wl_scale <= 0) || (expand->wl_scale >= 1));
888 /* if there is no temperature control, we need to specify an MC temperature */
889 if (!integratorHasReferenceTemperature(ir) && (expand->elmcmove != elmcmoveNO)
890 && (expand->mc_temp <= 0.0))
892 sprintf(err_buf,
893 "If there is no temperature control, and lmc-mcmove!='no', mc_temp must be set "
894 "to a positive number");
895 warning_error(wi, err_buf);
897 if (expand->nstTij > 0)
899 sprintf(err_buf, "nstlog must be non-zero");
900 CHECK(ir->nstlog == 0);
901 // Avoid modulus by zero in the case that already triggered an error exit.
902 if (ir->nstlog != 0)
904 sprintf(err_buf,
905 "nst-transition-matrix (%d) must be an integer multiple of nstlog (%d)",
906 expand->nstTij, ir->nstlog);
907 CHECK((expand->nstTij % ir->nstlog) != 0);
912 /* PBC/WALLS */
913 sprintf(err_buf, "walls only work with pbc=%s", c_pbcTypeNames[PbcType::XY].c_str());
914 CHECK(ir->nwall && ir->pbcType != PbcType::XY);
916 /* VACUUM STUFF */
917 if (ir->pbcType != PbcType::Xyz && ir->nwall != 2)
919 if (ir->pbcType == PbcType::No)
921 if (ir->epc != epcNO)
923 warning(wi, "Turning off pressure coupling for vacuum system");
924 ir->epc = epcNO;
927 else
929 sprintf(err_buf, "Can not have pressure coupling with pbc=%s",
930 c_pbcTypeNames[ir->pbcType].c_str());
931 CHECK(ir->epc != epcNO);
933 sprintf(err_buf, "Can not have Ewald with pbc=%s", c_pbcTypeNames[ir->pbcType].c_str());
934 CHECK(EEL_FULL(ir->coulombtype));
936 sprintf(err_buf, "Can not have dispersion correction with pbc=%s",
937 c_pbcTypeNames[ir->pbcType].c_str());
938 CHECK(ir->eDispCorr != edispcNO);
941 if (ir->rlist == 0.0)
943 sprintf(err_buf,
944 "can only have neighborlist cut-off zero (=infinite)\n"
945 "with coulombtype = %s or coulombtype = %s\n"
946 "without periodic boundary conditions (pbc = %s) and\n"
947 "rcoulomb and rvdw set to zero",
948 eel_names[eelCUT], eel_names[eelUSER], c_pbcTypeNames[PbcType::No].c_str());
949 CHECK(((ir->coulombtype != eelCUT) && (ir->coulombtype != eelUSER))
950 || (ir->pbcType != PbcType::No) || (ir->rcoulomb != 0.0) || (ir->rvdw != 0.0));
952 if (ir->nstlist > 0)
954 warning_note(wi,
955 "Simulating without cut-offs can be (slightly) faster with nstlist=0, "
956 "nstype=simple and only one MPI rank");
960 /* COMM STUFF */
961 if (ir->nstcomm == 0)
963 // TODO Change this behaviour. There should be exactly one way
964 // to turn off an algorithm.
965 ir->comm_mode = ecmNO;
967 if (ir->comm_mode != ecmNO)
969 if (ir->nstcomm < 0)
971 // TODO Such input was once valid. Now that we've been
972 // helpful for a few years, we should reject such input,
973 // lest we have to support every historical decision
974 // forever.
975 warning(wi,
976 "If you want to remove the rotation around the center of mass, you should set "
977 "comm_mode = Angular instead of setting nstcomm < 0. nstcomm is modified to "
978 "its absolute value");
979 ir->nstcomm = abs(ir->nstcomm);
982 if (ir->nstcalcenergy > 0 && ir->nstcomm < ir->nstcalcenergy)
984 warning_note(wi,
985 "nstcomm < nstcalcenergy defeats the purpose of nstcalcenergy, setting "
986 "nstcomm to nstcalcenergy");
987 ir->nstcomm = ir->nstcalcenergy;
990 if (ir->comm_mode == ecmANGULAR)
992 sprintf(err_buf,
993 "Can not remove the rotation around the center of mass with periodic "
994 "molecules");
995 CHECK(ir->bPeriodicMols);
996 if (ir->pbcType != PbcType::No)
998 warning(wi,
999 "Removing the rotation around the center of mass in a periodic system, "
1000 "this can lead to artifacts. Only use this on a single (cluster of) "
1001 "molecules. This cluster should not cross periodic boundaries.");
1006 if (EI_STATE_VELOCITY(ir->eI) && !EI_SD(ir->eI) && ir->pbcType == PbcType::No && ir->comm_mode != ecmANGULAR)
1008 sprintf(warn_buf,
1009 "Tumbling and flying ice-cubes: We are not removing rotation around center of mass "
1010 "in a non-periodic system. You should probably set comm_mode = ANGULAR or use "
1011 "integrator = %s.",
1012 ei_names[eiSD1]);
1013 warning_note(wi, warn_buf);
1016 /* TEMPERATURE COUPLING */
1017 if (ir->etc == etcYES)
1019 ir->etc = etcBERENDSEN;
1020 warning_note(wi,
1021 "Old option for temperature coupling given: "
1022 "changing \"yes\" to \"Berendsen\"\n");
1025 if ((ir->etc == etcNOSEHOOVER) || (ir->epc == epcMTTK))
1027 if (ir->opts.nhchainlength < 1)
1029 sprintf(warn_buf,
1030 "number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to "
1031 "1\n",
1032 ir->opts.nhchainlength);
1033 ir->opts.nhchainlength = 1;
1034 warning(wi, warn_buf);
1037 if (ir->etc == etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
1039 warning_note(
1041 "leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
1042 ir->opts.nhchainlength = 1;
1045 else
1047 ir->opts.nhchainlength = 0;
1050 if (ir->eI == eiVVAK)
1052 sprintf(err_buf,
1053 "%s implemented primarily for validation, and requires nsttcouple = 1 and "
1054 "nstpcouple = 1.",
1055 ei_names[eiVVAK]);
1056 CHECK((ir->nsttcouple != 1) || (ir->nstpcouple != 1));
1059 if (ETC_ANDERSEN(ir->etc))
1061 sprintf(err_buf, "%s temperature control not supported for integrator %s.",
1062 etcoupl_names[ir->etc], ei_names[ir->eI]);
1063 CHECK(!(EI_VV(ir->eI)));
1065 if (ir->nstcomm > 0 && (ir->etc == etcANDERSEN))
1067 sprintf(warn_buf,
1068 "Center of mass removal not necessary for %s. All velocities of coupled "
1069 "groups are rerandomized periodically, so flying ice cube errors will not "
1070 "occur.",
1071 etcoupl_names[ir->etc]);
1072 warning_note(wi, warn_buf);
1075 sprintf(err_buf,
1076 "nstcomm must be 1, not %d for %s, as velocities of atoms in coupled groups are "
1077 "randomized every time step",
1078 ir->nstcomm, etcoupl_names[ir->etc]);
1079 CHECK(ir->nstcomm > 1 && (ir->etc == etcANDERSEN));
1082 if (ir->etc == etcBERENDSEN)
1084 sprintf(warn_buf,
1085 "The %s thermostat does not generate the correct kinetic energy distribution. You "
1086 "might want to consider using the %s thermostat.",
1087 ETCOUPLTYPE(ir->etc), ETCOUPLTYPE(etcVRESCALE));
1088 warning_note(wi, warn_buf);
1091 if ((ir->etc == etcNOSEHOOVER || ETC_ANDERSEN(ir->etc)) && ir->epc == epcBERENDSEN)
1093 sprintf(warn_buf,
1094 "Using Berendsen pressure coupling invalidates the "
1095 "true ensemble for the thermostat");
1096 warning(wi, warn_buf);
1099 /* PRESSURE COUPLING */
1100 if (ir->epc == epcISOTROPIC)
1102 ir->epc = epcBERENDSEN;
1103 warning_note(wi,
1104 "Old option for pressure coupling given: "
1105 "changing \"Isotropic\" to \"Berendsen\"\n");
1108 if (ir->epc != epcNO)
1110 dt_pcoupl = ir->nstpcouple * ir->delta_t;
1112 sprintf(err_buf, "tau-p must be > 0 instead of %g\n", ir->tau_p);
1113 CHECK(ir->tau_p <= 0);
1115 if (ir->tau_p / dt_pcoupl < pcouple_min_integration_steps(ir->epc) - 10 * GMX_REAL_EPS)
1117 sprintf(warn_buf,
1118 "For proper integration of the %s barostat, tau-p (%g) should be at least %d "
1119 "times larger than nstpcouple*dt (%g)",
1120 EPCOUPLTYPE(ir->epc), ir->tau_p, pcouple_min_integration_steps(ir->epc), dt_pcoupl);
1121 warning(wi, warn_buf);
1124 sprintf(err_buf,
1125 "compressibility must be > 0 when using pressure"
1126 " coupling %s\n",
1127 EPCOUPLTYPE(ir->epc));
1128 CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || ir->compress[ZZ][ZZ] < 0
1129 || (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 && ir->compress[ZZ][XX] <= 0
1130 && ir->compress[ZZ][YY] <= 0));
1132 if (epcPARRINELLORAHMAN == ir->epc && opts->bGenVel)
1134 sprintf(warn_buf,
1135 "You are generating velocities so I am assuming you "
1136 "are equilibrating a system. You are using "
1137 "%s pressure coupling, but this can be "
1138 "unstable for equilibration. If your system crashes, try "
1139 "equilibrating first with Berendsen pressure coupling. If "
1140 "you are not equilibrating the system, you can probably "
1141 "ignore this warning.",
1142 epcoupl_names[ir->epc]);
1143 warning(wi, warn_buf);
1147 if (!EI_VV(ir->eI))
1149 if (ir->epc == epcMTTK)
1151 warning_error(wi, "MTTK pressure coupling requires a Velocity-verlet integrator");
1155 /* ELECTROSTATICS */
1156 /* More checks are in triple check (grompp.c) */
1158 if (ir->coulombtype == eelSWITCH)
1160 sprintf(warn_buf,
1161 "coulombtype = %s is only for testing purposes and can lead to serious "
1162 "artifacts, advice: use coulombtype = %s",
1163 eel_names[ir->coulombtype], eel_names[eelRF_ZERO]);
1164 warning(wi, warn_buf);
1167 if (EEL_RF(ir->coulombtype) && ir->epsilon_rf == 1 && ir->epsilon_r != 1)
1169 sprintf(warn_buf,
1170 "epsilon-r = %g and epsilon-rf = 1 with reaction field, proceeding assuming old "
1171 "format and exchanging epsilon-r and epsilon-rf",
1172 ir->epsilon_r);
1173 warning(wi, warn_buf);
1174 ir->epsilon_rf = ir->epsilon_r;
1175 ir->epsilon_r = 1.0;
1178 if (ir->epsilon_r == 0)
1180 sprintf(err_buf,
1181 "It is pointless to use long-range electrostatics with infinite relative "
1182 "permittivity."
1183 "Since you are effectively turning of electrostatics, a plain cutoff will be much "
1184 "faster.");
1185 CHECK(EEL_FULL(ir->coulombtype));
1188 if (getenv("GMX_DO_GALACTIC_DYNAMICS") == nullptr)
1190 sprintf(err_buf, "epsilon-r must be >= 0 instead of %g\n", ir->epsilon_r);
1191 CHECK(ir->epsilon_r < 0);
1194 if (EEL_RF(ir->coulombtype))
1196 /* reaction field (at the cut-off) */
1198 if (ir->coulombtype == eelRF_ZERO && ir->epsilon_rf != 0)
1200 sprintf(warn_buf,
1201 "With coulombtype = %s, epsilon-rf must be 0, assuming you meant epsilon_rf=0",
1202 eel_names[ir->coulombtype]);
1203 warning(wi, warn_buf);
1204 ir->epsilon_rf = 0.0;
1207 sprintf(err_buf, "epsilon-rf must be >= epsilon-r");
1208 CHECK((ir->epsilon_rf < ir->epsilon_r && ir->epsilon_rf != 0) || (ir->epsilon_r == 0));
1209 if (ir->epsilon_rf == ir->epsilon_r)
1211 sprintf(warn_buf, "Using epsilon-rf = epsilon-r with %s does not make sense",
1212 eel_names[ir->coulombtype]);
1213 warning(wi, warn_buf);
1216 /* Allow rlist>rcoulomb for tabulated long range stuff. This just
1217 * means the interaction is zero outside rcoulomb, but it helps to
1218 * provide accurate energy conservation.
1220 if (ir_coulomb_might_be_zero_at_cutoff(ir))
1222 if (ir_coulomb_switched(ir))
1224 sprintf(err_buf,
1225 "With coulombtype = %s rcoulomb_switch must be < rcoulomb. Or, better: Use the "
1226 "potential modifier options!",
1227 eel_names[ir->coulombtype]);
1228 CHECK(ir->rcoulomb_switch >= ir->rcoulomb);
1232 if (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT)
1234 sprintf(err_buf,
1235 "Explicit switch/shift coulomb interactions cannot be used in combination with a "
1236 "secondary coulomb-modifier.");
1237 CHECK(ir->coulomb_modifier != eintmodNONE);
1239 if (ir->vdwtype == evdwSWITCH || ir->vdwtype == evdwSHIFT)
1241 sprintf(err_buf,
1242 "Explicit switch/shift vdw interactions cannot be used in combination with a "
1243 "secondary vdw-modifier.");
1244 CHECK(ir->vdw_modifier != eintmodNONE);
1247 if (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT || ir->vdwtype == evdwSWITCH
1248 || ir->vdwtype == evdwSHIFT)
1250 sprintf(warn_buf,
1251 "The switch/shift interaction settings are just for compatibility; you will get "
1252 "better "
1253 "performance from applying potential modifiers to your interactions!\n");
1254 warning_note(wi, warn_buf);
1257 if (ir->coulombtype == eelPMESWITCH || ir->coulomb_modifier == eintmodPOTSWITCH)
1259 if (ir->rcoulomb_switch / ir->rcoulomb < 0.9499)
1261 real percentage = 100 * (ir->rcoulomb - ir->rcoulomb_switch) / ir->rcoulomb;
1262 sprintf(warn_buf,
1263 "The switching range should be 5%% or less (currently %.2f%% using a switching "
1264 "range of %4f-%4f) for accurate electrostatic energies, energy conservation "
1265 "will be good regardless, since ewald_rtol = %g.",
1266 percentage, ir->rcoulomb_switch, ir->rcoulomb, ir->ewald_rtol);
1267 warning(wi, warn_buf);
1271 if (ir->vdwtype == evdwSWITCH || ir->vdw_modifier == eintmodPOTSWITCH)
1273 if (ir->rvdw_switch == 0)
1275 sprintf(warn_buf,
1276 "rvdw-switch is equal 0 even though you are using a switched Lennard-Jones "
1277 "potential. This suggests it was not set in the mdp, which can lead to large "
1278 "energy errors. In GROMACS, 0.05 to 0.1 nm is often a reasonable vdw "
1279 "switching range.");
1280 warning(wi, warn_buf);
1284 if (EEL_FULL(ir->coulombtype))
1286 if (ir->coulombtype == eelPMESWITCH || ir->coulombtype == eelPMEUSER
1287 || ir->coulombtype == eelPMEUSERSWITCH)
1289 sprintf(err_buf, "With coulombtype = %s, rcoulomb must be <= rlist",
1290 eel_names[ir->coulombtype]);
1291 CHECK(ir->rcoulomb > ir->rlist);
1295 if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
1297 // TODO: Move these checks into the ewald module with the options class
1298 int orderMin = 3;
1299 int orderMax = (ir->coulombtype == eelP3M_AD ? 8 : 12);
1301 if (ir->pme_order < orderMin || ir->pme_order > orderMax)
1303 sprintf(warn_buf, "With coulombtype = %s, you should have %d <= pme-order <= %d",
1304 eel_names[ir->coulombtype], orderMin, orderMax);
1305 warning_error(wi, warn_buf);
1309 if (ir->nwall == 2 && EEL_FULL(ir->coulombtype))
1311 if (ir->ewald_geometry == eewg3D)
1313 sprintf(warn_buf, "With pbc=%s you should use ewald-geometry=%s",
1314 c_pbcTypeNames[ir->pbcType].c_str(), eewg_names[eewg3DC]);
1315 warning(wi, warn_buf);
1317 /* This check avoids extra pbc coding for exclusion corrections */
1318 sprintf(err_buf, "wall-ewald-zfac should be >= 2");
1319 CHECK(ir->wall_ewald_zfac < 2);
1321 if ((ir->ewald_geometry == eewg3DC) && (ir->pbcType != PbcType::XY) && EEL_FULL(ir->coulombtype))
1323 sprintf(warn_buf, "With %s and ewald_geometry = %s you should use pbc = %s",
1324 eel_names[ir->coulombtype], eewg_names[eewg3DC], c_pbcTypeNames[PbcType::XY].c_str());
1325 warning(wi, warn_buf);
1327 if ((ir->epsilon_surface != 0) && EEL_FULL(ir->coulombtype))
1329 sprintf(err_buf, "Cannot have periodic molecules with epsilon_surface > 0");
1330 CHECK(ir->bPeriodicMols);
1331 sprintf(warn_buf, "With epsilon_surface > 0 all molecules should be neutral.");
1332 warning_note(wi, warn_buf);
1333 sprintf(warn_buf,
1334 "With epsilon_surface > 0 you can only use domain decomposition "
1335 "when there are only small molecules with all bonds constrained (mdrun will check "
1336 "for this).");
1337 warning_note(wi, warn_buf);
1340 if (ir_vdw_switched(ir))
1342 sprintf(err_buf, "With switched vdw forces or potentials, rvdw-switch must be < rvdw");
1343 CHECK(ir->rvdw_switch >= ir->rvdw);
1345 if (ir->rvdw_switch < 0.5 * ir->rvdw)
1347 sprintf(warn_buf,
1348 "You are applying a switch function to vdw forces or potentials from %g to %g "
1349 "nm, which is more than half the interaction range, whereas switch functions "
1350 "are intended to act only close to the cut-off.",
1351 ir->rvdw_switch, ir->rvdw);
1352 warning_note(wi, warn_buf);
1356 if (ir->vdwtype == evdwPME)
1358 if (!(ir->vdw_modifier == eintmodNONE || ir->vdw_modifier == eintmodPOTSHIFT))
1360 sprintf(err_buf, "With vdwtype = %s, the only supported modifiers are %s and %s",
1361 evdw_names[ir->vdwtype], eintmod_names[eintmodPOTSHIFT], eintmod_names[eintmodNONE]);
1362 warning_error(wi, err_buf);
1366 if (ir->vdwtype == evdwUSER && ir->eDispCorr != edispcNO)
1368 warning_note(wi,
1369 "You have selected user tables with dispersion correction, the dispersion "
1370 "will be corrected to -C6/r^6 beyond rvdw_switch (the tabulated interaction "
1371 "between rvdw_switch and rvdw will not be double counted). Make sure that you "
1372 "really want dispersion correction to -C6/r^6.");
1375 if (ir->eI == eiLBFGS && (ir->coulombtype == eelCUT || ir->vdwtype == evdwCUT) && ir->rvdw != 0)
1377 warning(wi, "For efficient BFGS minimization, use switch/shift/pme instead of cut-off.");
1380 if (ir->eI == eiLBFGS && ir->nbfgscorr <= 0)
1382 warning(wi, "Using L-BFGS with nbfgscorr<=0 just gets you steepest descent.");
1385 /* IMPLICIT SOLVENT */
1386 if (ir->coulombtype == eelGB_NOTUSED)
1388 sprintf(warn_buf, "Invalid option %s for coulombtype", eel_names[ir->coulombtype]);
1389 warning_error(wi, warn_buf);
1392 if (ir->bQMMM)
1394 warning_error(wi, "QMMM is currently not supported");
1395 if (!EI_DYNAMICS(ir->eI))
1397 char buf[STRLEN];
1398 sprintf(buf, "QMMM is only supported with dynamics, not with integrator %s", ei_names[ir->eI]);
1399 warning_error(wi, buf);
1403 if (ir->bAdress)
1405 gmx_fatal(FARGS, "AdResS simulations are no longer supported");
1409 /* interpret a number of doubles from a string and put them in an array,
1410 after allocating space for them.
1411 str = the input string
1412 n = the (pre-allocated) number of doubles read
1413 r = the output array of doubles. */
1414 static void parse_n_real(char* str, int* n, real** r, warninp_t wi)
1416 auto values = gmx::splitString(str);
1417 *n = values.size();
1419 snew(*r, *n);
1420 for (int i = 0; i < *n; i++)
1424 (*r)[i] = gmx::fromString<real>(values[i]);
1426 catch (gmx::GromacsException&)
1428 warning_error(wi, "Invalid value " + values[i]
1429 + " in string in mdp file. Expected a real number.");
1435 static void do_fep_params(t_inputrec* ir, char fep_lambda[][STRLEN], char weights[STRLEN], warninp_t wi)
1438 int i, j, max_n_lambda, nweights, nfep[efptNR];
1439 t_lambda* fep = ir->fepvals;
1440 t_expanded* expand = ir->expandedvals;
1441 real** count_fep_lambdas;
1442 bool bOneLambda = TRUE;
1444 snew(count_fep_lambdas, efptNR);
1446 /* FEP input processing */
1447 /* first, identify the number of lambda values for each type.
1448 All that are nonzero must have the same number */
1450 for (i = 0; i < efptNR; i++)
1452 parse_n_real(fep_lambda[i], &(nfep[i]), &(count_fep_lambdas[i]), wi);
1455 /* now, determine the number of components. All must be either zero, or equal. */
1457 max_n_lambda = 0;
1458 for (i = 0; i < efptNR; i++)
1460 if (nfep[i] > max_n_lambda)
1462 max_n_lambda = nfep[i]; /* here's a nonzero one. All of them
1463 must have the same number if its not zero.*/
1464 break;
1468 for (i = 0; i < efptNR; i++)
1470 if (nfep[i] == 0)
1472 ir->fepvals->separate_dvdl[i] = FALSE;
1474 else if (nfep[i] == max_n_lambda)
1476 if (i != efptTEMPERATURE) /* we treat this differently -- not really a reason to compute
1477 the derivative with respect to the temperature currently */
1479 ir->fepvals->separate_dvdl[i] = TRUE;
1482 else
1484 gmx_fatal(FARGS,
1485 "Number of lambdas (%d) for FEP type %s not equal to number of other types "
1486 "(%d)",
1487 nfep[i], efpt_names[i], max_n_lambda);
1490 /* we don't print out dhdl if the temperature is changing, since we can't correctly define dhdl in this case */
1491 ir->fepvals->separate_dvdl[efptTEMPERATURE] = FALSE;
1493 /* the number of lambdas is the number we've read in, which is either zero
1494 or the same for all */
1495 fep->n_lambda = max_n_lambda;
1497 /* allocate space for the array of lambda values */
1498 snew(fep->all_lambda, efptNR);
1499 /* if init_lambda is defined, we need to set lambda */
1500 if ((fep->init_lambda > 0) && (fep->n_lambda == 0))
1502 ir->fepvals->separate_dvdl[efptFEP] = TRUE;
1504 /* otherwise allocate the space for all of the lambdas, and transfer the data */
1505 for (i = 0; i < efptNR; i++)
1507 snew(fep->all_lambda[i], fep->n_lambda);
1508 if (nfep[i] > 0) /* if it's zero, then the count_fep_lambda arrays
1509 are zero */
1511 for (j = 0; j < fep->n_lambda; j++)
1513 fep->all_lambda[i][j] = static_cast<double>(count_fep_lambdas[i][j]);
1515 sfree(count_fep_lambdas[i]);
1518 sfree(count_fep_lambdas);
1520 /* "fep-vals" is either zero or the full number. If zero, we'll need to define fep-lambdas for
1521 internal bookkeeping -- for now, init_lambda */
1523 if ((nfep[efptFEP] == 0) && (fep->init_lambda >= 0))
1525 for (i = 0; i < fep->n_lambda; i++)
1527 fep->all_lambda[efptFEP][i] = fep->init_lambda;
1531 /* check to see if only a single component lambda is defined, and soft core is defined.
1532 In this case, turn on coulomb soft core */
1534 if (max_n_lambda == 0)
1536 bOneLambda = TRUE;
1538 else
1540 for (i = 0; i < efptNR; i++)
1542 if ((nfep[i] != 0) && (i != efptFEP))
1544 bOneLambda = FALSE;
1548 if ((bOneLambda) && (fep->sc_alpha > 0))
1550 fep->bScCoul = TRUE;
1553 /* Fill in the others with the efptFEP if they are not explicitly
1554 specified (i.e. nfep[i] == 0). This means if fep is not defined,
1555 they are all zero. */
1557 for (i = 0; i < efptNR; i++)
1559 if ((nfep[i] == 0) && (i != efptFEP))
1561 for (j = 0; j < fep->n_lambda; j++)
1563 fep->all_lambda[i][j] = fep->all_lambda[efptFEP][j];
1569 /* make it easier if sc_r_power = 48 by increasing it to the 4th power, to be in the right scale. */
1570 if (fep->sc_r_power == 48)
1572 if (fep->sc_alpha > 0.1)
1574 gmx_fatal(FARGS,
1575 "sc_alpha (%f) for sc_r_power = 48 should usually be between 0.001 and 0.004",
1576 fep->sc_alpha);
1580 /* now read in the weights */
1581 parse_n_real(weights, &nweights, &(expand->init_lambda_weights), wi);
1582 if (nweights == 0)
1584 snew(expand->init_lambda_weights, fep->n_lambda); /* initialize to zero */
1586 else if (nweights != fep->n_lambda)
1588 gmx_fatal(FARGS, "Number of weights (%d) is not equal to number of lambda values (%d)",
1589 nweights, fep->n_lambda);
1591 if ((expand->nstexpanded < 0) && (ir->efep != efepNO))
1593 expand->nstexpanded = fep->nstdhdl;
1594 /* if you don't specify nstexpanded when doing expanded ensemble free energy calcs, it is set to nstdhdl */
1599 static void do_simtemp_params(t_inputrec* ir)
1602 snew(ir->simtempvals->temperatures, ir->fepvals->n_lambda);
1603 GetSimTemps(ir->fepvals->n_lambda, ir->simtempvals, ir->fepvals->all_lambda[efptTEMPERATURE]);
1606 static void convertYesNos(warninp_t /*wi*/,
1607 gmx::ArrayRef<const std::string> inputs,
1608 const char* /*name*/,
1609 gmx_bool* outputs)
1611 int i = 0;
1612 for (const auto& input : inputs)
1614 outputs[i] = gmx::equalCaseInsensitive(input, "Y", 1);
1615 ++i;
1619 template<typename T>
1620 void convertInts(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, T* outputs)
1622 int i = 0;
1623 for (const auto& input : inputs)
1627 outputs[i] = gmx::fromStdString<T>(input);
1629 catch (gmx::GromacsException&)
1631 auto message = gmx::formatString(
1632 "Invalid value for mdp option %s. %s should only consist of integers separated "
1633 "by spaces.",
1634 name, name);
1635 warning_error(wi, message);
1637 ++i;
1641 static void convertReals(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, real* outputs)
1643 int i = 0;
1644 for (const auto& input : inputs)
1648 outputs[i] = gmx::fromString<real>(input);
1650 catch (gmx::GromacsException&)
1652 auto message = gmx::formatString(
1653 "Invalid value for mdp option %s. %s should only consist of real numbers "
1654 "separated by spaces.",
1655 name, name);
1656 warning_error(wi, message);
1658 ++i;
1662 static void convertRvecs(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, rvec* outputs)
1664 int i = 0, d = 0;
1665 for (const auto& input : inputs)
1669 outputs[i][d] = gmx::fromString<real>(input);
1671 catch (gmx::GromacsException&)
1673 auto message = gmx::formatString(
1674 "Invalid value for mdp option %s. %s should only consist of real numbers "
1675 "separated by spaces.",
1676 name, name);
1677 warning_error(wi, message);
1679 ++d;
1680 if (d == DIM)
1682 d = 0;
1683 ++i;
1688 static void do_wall_params(t_inputrec* ir, char* wall_atomtype, char* wall_density, t_gromppopts* opts, warninp_t wi)
1690 opts->wall_atomtype[0] = nullptr;
1691 opts->wall_atomtype[1] = nullptr;
1693 ir->wall_atomtype[0] = -1;
1694 ir->wall_atomtype[1] = -1;
1695 ir->wall_density[0] = 0;
1696 ir->wall_density[1] = 0;
1698 if (ir->nwall > 0)
1700 auto wallAtomTypes = gmx::splitString(wall_atomtype);
1701 if (wallAtomTypes.size() != size_t(ir->nwall))
1703 gmx_fatal(FARGS, "Expected %d elements for wall_atomtype, found %zu", ir->nwall,
1704 wallAtomTypes.size());
1706 for (int i = 0; i < ir->nwall; i++)
1708 opts->wall_atomtype[i] = gmx_strdup(wallAtomTypes[i].c_str());
1711 if (ir->wall_type == ewt93 || ir->wall_type == ewt104)
1713 auto wallDensity = gmx::splitString(wall_density);
1714 if (wallDensity.size() != size_t(ir->nwall))
1716 gmx_fatal(FARGS, "Expected %d elements for wall-density, found %zu", ir->nwall,
1717 wallDensity.size());
1719 convertReals(wi, wallDensity, "wall-density", ir->wall_density);
1720 for (int i = 0; i < ir->nwall; i++)
1722 if (ir->wall_density[i] <= 0)
1724 gmx_fatal(FARGS, "wall-density[%d] = %f\n", i, ir->wall_density[i]);
1731 static void add_wall_energrps(SimulationGroups* groups, int nwall, t_symtab* symtab)
1733 if (nwall > 0)
1735 AtomGroupIndices* grps = &(groups->groups[SimulationAtomGroupType::EnergyOutput]);
1736 for (int i = 0; i < nwall; i++)
1738 groups->groupNames.emplace_back(put_symtab(symtab, gmx::formatString("wall%d", i).c_str()));
1739 grps->emplace_back(groups->groupNames.size() - 1);
1744 static void read_expandedparams(std::vector<t_inpfile>* inp, t_expanded* expand, warninp_t wi)
1746 /* read expanded ensemble parameters */
1747 printStringNewline(inp, "expanded ensemble variables");
1748 expand->nstexpanded = get_eint(inp, "nstexpanded", -1, wi);
1749 expand->elamstats = get_eeenum(inp, "lmc-stats", elamstats_names, wi);
1750 expand->elmcmove = get_eeenum(inp, "lmc-move", elmcmove_names, wi);
1751 expand->elmceq = get_eeenum(inp, "lmc-weights-equil", elmceq_names, wi);
1752 expand->equil_n_at_lam = get_eint(inp, "weight-equil-number-all-lambda", -1, wi);
1753 expand->equil_samples = get_eint(inp, "weight-equil-number-samples", -1, wi);
1754 expand->equil_steps = get_eint(inp, "weight-equil-number-steps", -1, wi);
1755 expand->equil_wl_delta = get_ereal(inp, "weight-equil-wl-delta", -1, wi);
1756 expand->equil_ratio = get_ereal(inp, "weight-equil-count-ratio", -1, wi);
1757 printStringNewline(inp, "Seed for Monte Carlo in lambda space");
1758 expand->lmc_seed = get_eint(inp, "lmc-seed", -1, wi);
1759 expand->mc_temp = get_ereal(inp, "mc-temperature", -1, wi);
1760 expand->lmc_repeats = get_eint(inp, "lmc-repeats", 1, wi);
1761 expand->gibbsdeltalam = get_eint(inp, "lmc-gibbsdelta", -1, wi);
1762 expand->lmc_forced_nstart = get_eint(inp, "lmc-forced-nstart", 0, wi);
1763 expand->bSymmetrizedTMatrix =
1764 (get_eeenum(inp, "symmetrized-transition-matrix", yesno_names, wi) != 0);
1765 expand->nstTij = get_eint(inp, "nst-transition-matrix", -1, wi);
1766 expand->minvarmin = get_eint(inp, "mininum-var-min", 100, wi); /*default is reasonable */
1767 expand->c_range = get_eint(inp, "weight-c-range", 0, wi); /* default is just C=0 */
1768 expand->wl_scale = get_ereal(inp, "wl-scale", 0.8, wi);
1769 expand->wl_ratio = get_ereal(inp, "wl-ratio", 0.8, wi);
1770 expand->init_wl_delta = get_ereal(inp, "init-wl-delta", 1.0, wi);
1771 expand->bWLoneovert = (get_eeenum(inp, "wl-oneovert", yesno_names, wi) != 0);
1774 /*! \brief Return whether an end state with the given coupling-lambda
1775 * value describes fully-interacting VDW.
1777 * \param[in] couple_lambda_value Enumeration ecouplam value describing the end state
1778 * \return Whether VDW is on (i.e. the user chose vdw or vdw-q in the .mdp file)
1780 static bool couple_lambda_has_vdw_on(int couple_lambda_value)
1782 return (couple_lambda_value == ecouplamVDW || couple_lambda_value == ecouplamVDWQ);
1785 namespace
1788 class MdpErrorHandler : public gmx::IKeyValueTreeErrorHandler
1790 public:
1791 explicit MdpErrorHandler(warninp_t wi) : wi_(wi), mapping_(nullptr) {}
1793 void setBackMapping(const gmx::IKeyValueTreeBackMapping& mapping) { mapping_ = &mapping; }
1795 bool onError(gmx::UserInputError* ex, const gmx::KeyValueTreePath& context) override
1797 ex->prependContext(
1798 gmx::formatString("Error in mdp option \"%s\":", getOptionName(context).c_str()));
1799 std::string message = gmx::formatExceptionMessageToString(*ex);
1800 warning_error(wi_, message.c_str());
1801 return true;
1804 private:
1805 std::string getOptionName(const gmx::KeyValueTreePath& context)
1807 if (mapping_ != nullptr)
1809 gmx::KeyValueTreePath path = mapping_->originalPath(context);
1810 GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
1811 return path[0];
1813 GMX_ASSERT(context.size() == 1, "Inconsistent context for mdp option parsing");
1814 return context[0];
1817 warninp_t wi_;
1818 const gmx::IKeyValueTreeBackMapping* mapping_;
1821 } // namespace
1823 void get_ir(const char* mdparin,
1824 const char* mdparout,
1825 gmx::MDModules* mdModules,
1826 t_inputrec* ir,
1827 t_gromppopts* opts,
1828 WriteMdpHeader writeMdpHeader,
1829 warninp_t wi)
1831 char* dumstr[2];
1832 double dumdub[2][6];
1833 int i, j, m;
1834 char warn_buf[STRLEN];
1835 t_lambda* fep = ir->fepvals;
1836 t_expanded* expand = ir->expandedvals;
1838 const char* no_names[] = { "no", nullptr };
1840 init_inputrec_strings();
1841 gmx::TextInputFile stream(mdparin);
1842 std::vector<t_inpfile> inp = read_inpfile(&stream, mdparin, wi);
1844 snew(dumstr[0], STRLEN);
1845 snew(dumstr[1], STRLEN);
1847 /* ignore the following deprecated commands */
1848 replace_inp_entry(inp, "title", nullptr);
1849 replace_inp_entry(inp, "cpp", nullptr);
1850 replace_inp_entry(inp, "domain-decomposition", nullptr);
1851 replace_inp_entry(inp, "andersen-seed", nullptr);
1852 replace_inp_entry(inp, "dihre", nullptr);
1853 replace_inp_entry(inp, "dihre-fc", nullptr);
1854 replace_inp_entry(inp, "dihre-tau", nullptr);
1855 replace_inp_entry(inp, "nstdihreout", nullptr);
1856 replace_inp_entry(inp, "nstcheckpoint", nullptr);
1857 replace_inp_entry(inp, "optimize-fft", nullptr);
1858 replace_inp_entry(inp, "adress_type", nullptr);
1859 replace_inp_entry(inp, "adress_const_wf", nullptr);
1860 replace_inp_entry(inp, "adress_ex_width", nullptr);
1861 replace_inp_entry(inp, "adress_hy_width", nullptr);
1862 replace_inp_entry(inp, "adress_ex_forcecap", nullptr);
1863 replace_inp_entry(inp, "adress_interface_correction", nullptr);
1864 replace_inp_entry(inp, "adress_site", nullptr);
1865 replace_inp_entry(inp, "adress_reference_coords", nullptr);
1866 replace_inp_entry(inp, "adress_tf_grp_names", nullptr);
1867 replace_inp_entry(inp, "adress_cg_grp_names", nullptr);
1868 replace_inp_entry(inp, "adress_do_hybridpairs", nullptr);
1869 replace_inp_entry(inp, "rlistlong", nullptr);
1870 replace_inp_entry(inp, "nstcalclr", nullptr);
1871 replace_inp_entry(inp, "pull-print-com2", nullptr);
1872 replace_inp_entry(inp, "gb-algorithm", nullptr);
1873 replace_inp_entry(inp, "nstgbradii", nullptr);
1874 replace_inp_entry(inp, "rgbradii", nullptr);
1875 replace_inp_entry(inp, "gb-epsilon-solvent", nullptr);
1876 replace_inp_entry(inp, "gb-saltconc", nullptr);
1877 replace_inp_entry(inp, "gb-obc-alpha", nullptr);
1878 replace_inp_entry(inp, "gb-obc-beta", nullptr);
1879 replace_inp_entry(inp, "gb-obc-gamma", nullptr);
1880 replace_inp_entry(inp, "gb-dielectric-offset", nullptr);
1881 replace_inp_entry(inp, "sa-algorithm", nullptr);
1882 replace_inp_entry(inp, "sa-surface-tension", nullptr);
1883 replace_inp_entry(inp, "ns-type", nullptr);
1885 /* replace the following commands with the clearer new versions*/
1886 replace_inp_entry(inp, "unconstrained-start", "continuation");
1887 replace_inp_entry(inp, "foreign-lambda", "fep-lambdas");
1888 replace_inp_entry(inp, "verlet-buffer-drift", "verlet-buffer-tolerance");
1889 replace_inp_entry(inp, "nstxtcout", "nstxout-compressed");
1890 replace_inp_entry(inp, "xtc-grps", "compressed-x-grps");
1891 replace_inp_entry(inp, "xtc-precision", "compressed-x-precision");
1892 replace_inp_entry(inp, "pull-print-com1", "pull-print-com");
1894 printStringNewline(&inp, "VARIOUS PREPROCESSING OPTIONS");
1895 printStringNoNewline(&inp, "Preprocessor information: use cpp syntax.");
1896 printStringNoNewline(&inp, "e.g.: -I/home/joe/doe -I/home/mary/roe");
1897 setStringEntry(&inp, "include", opts->include, nullptr);
1898 printStringNoNewline(
1899 &inp, "e.g.: -DPOSRES -DFLEXIBLE (note these variable names are case sensitive)");
1900 setStringEntry(&inp, "define", opts->define, nullptr);
1902 printStringNewline(&inp, "RUN CONTROL PARAMETERS");
1903 ir->eI = get_eeenum(&inp, "integrator", ei_names, wi);
1904 printStringNoNewline(&inp, "Start time and timestep in ps");
1905 ir->init_t = get_ereal(&inp, "tinit", 0.0, wi);
1906 ir->delta_t = get_ereal(&inp, "dt", 0.001, wi);
1907 ir->nsteps = get_eint64(&inp, "nsteps", 0, wi);
1908 printStringNoNewline(&inp, "For exact run continuation or redoing part of a run");
1909 ir->init_step = get_eint64(&inp, "init-step", 0, wi);
1910 printStringNoNewline(
1911 &inp, "Part index is updated automatically on checkpointing (keeps files separate)");
1912 ir->simulation_part = get_eint(&inp, "simulation-part", 1, wi);
1913 printStringNoNewline(&inp, "mode for center of mass motion removal");
1914 ir->comm_mode = get_eeenum(&inp, "comm-mode", ecm_names, wi);
1915 printStringNoNewline(&inp, "number of steps for center of mass motion removal");
1916 ir->nstcomm = get_eint(&inp, "nstcomm", 100, wi);
1917 printStringNoNewline(&inp, "group(s) for center of mass motion removal");
1918 setStringEntry(&inp, "comm-grps", is->vcm, nullptr);
1920 printStringNewline(&inp, "LANGEVIN DYNAMICS OPTIONS");
1921 printStringNoNewline(&inp, "Friction coefficient (amu/ps) and random seed");
1922 ir->bd_fric = get_ereal(&inp, "bd-fric", 0.0, wi);
1923 ir->ld_seed = get_eint64(&inp, "ld-seed", -1, wi);
1925 /* Em stuff */
1926 printStringNewline(&inp, "ENERGY MINIMIZATION OPTIONS");
1927 printStringNoNewline(&inp, "Force tolerance and initial step-size");
1928 ir->em_tol = get_ereal(&inp, "emtol", 10.0, wi);
1929 ir->em_stepsize = get_ereal(&inp, "emstep", 0.01, wi);
1930 printStringNoNewline(&inp, "Max number of iterations in relax-shells");
1931 ir->niter = get_eint(&inp, "niter", 20, wi);
1932 printStringNoNewline(&inp, "Step size (ps^2) for minimization of flexible constraints");
1933 ir->fc_stepsize = get_ereal(&inp, "fcstep", 0, wi);
1934 printStringNoNewline(&inp, "Frequency of steepest descents steps when doing CG");
1935 ir->nstcgsteep = get_eint(&inp, "nstcgsteep", 1000, wi);
1936 ir->nbfgscorr = get_eint(&inp, "nbfgscorr", 10, wi);
1938 printStringNewline(&inp, "TEST PARTICLE INSERTION OPTIONS");
1939 ir->rtpi = get_ereal(&inp, "rtpi", 0.05, wi);
1941 /* Output options */
1942 printStringNewline(&inp, "OUTPUT CONTROL OPTIONS");
1943 printStringNoNewline(&inp, "Output frequency for coords (x), velocities (v) and forces (f)");
1944 ir->nstxout = get_eint(&inp, "nstxout", 0, wi);
1945 ir->nstvout = get_eint(&inp, "nstvout", 0, wi);
1946 ir->nstfout = get_eint(&inp, "nstfout", 0, wi);
1947 printStringNoNewline(&inp, "Output frequency for energies to log file and energy file");
1948 ir->nstlog = get_eint(&inp, "nstlog", 1000, wi);
1949 ir->nstcalcenergy = get_eint(&inp, "nstcalcenergy", 100, wi);
1950 ir->nstenergy = get_eint(&inp, "nstenergy", 1000, wi);
1951 printStringNoNewline(&inp, "Output frequency and precision for .xtc file");
1952 ir->nstxout_compressed = get_eint(&inp, "nstxout-compressed", 0, wi);
1953 ir->x_compression_precision = get_ereal(&inp, "compressed-x-precision", 1000.0, wi);
1954 printStringNoNewline(&inp, "This selects the subset of atoms for the compressed");
1955 printStringNoNewline(&inp, "trajectory file. You can select multiple groups. By");
1956 printStringNoNewline(&inp, "default, all atoms will be written.");
1957 setStringEntry(&inp, "compressed-x-grps", is->x_compressed_groups, nullptr);
1958 printStringNoNewline(&inp, "Selection of energy groups");
1959 setStringEntry(&inp, "energygrps", is->energy, nullptr);
1961 /* Neighbor searching */
1962 printStringNewline(&inp, "NEIGHBORSEARCHING PARAMETERS");
1963 printStringNoNewline(&inp, "cut-off scheme (Verlet: particle based cut-offs)");
1964 ir->cutoff_scheme = get_eeenum(&inp, "cutoff-scheme", ecutscheme_names, wi);
1965 printStringNoNewline(&inp, "nblist update frequency");
1966 ir->nstlist = get_eint(&inp, "nstlist", 10, wi);
1967 printStringNoNewline(&inp, "Periodic boundary conditions: xyz, no, xy");
1968 // TODO This conversion should be removed when proper std:string handling will be added to get_eeenum(...), etc.
1969 std::vector<const char*> pbcTypesNamesChar;
1970 for (const auto& pbcTypeName : c_pbcTypeNames)
1972 pbcTypesNamesChar.push_back(pbcTypeName.c_str());
1974 ir->pbcType = static_cast<PbcType>(get_eeenum(&inp, "pbc", pbcTypesNamesChar.data(), wi));
1975 ir->bPeriodicMols = get_eeenum(&inp, "periodic-molecules", yesno_names, wi) != 0;
1976 printStringNoNewline(&inp,
1977 "Allowed energy error due to the Verlet buffer in kJ/mol/ps per atom,");
1978 printStringNoNewline(&inp, "a value of -1 means: use rlist");
1979 ir->verletbuf_tol = get_ereal(&inp, "verlet-buffer-tolerance", 0.005, wi);
1980 printStringNoNewline(&inp, "nblist cut-off");
1981 ir->rlist = get_ereal(&inp, "rlist", 1.0, wi);
1982 printStringNoNewline(&inp, "long-range cut-off for switched potentials");
1984 /* Electrostatics */
1985 printStringNewline(&inp, "OPTIONS FOR ELECTROSTATICS AND VDW");
1986 printStringNoNewline(&inp, "Method for doing electrostatics");
1987 ir->coulombtype = get_eeenum(&inp, "coulombtype", eel_names, wi);
1988 ir->coulomb_modifier = get_eeenum(&inp, "coulomb-modifier", eintmod_names, wi);
1989 printStringNoNewline(&inp, "cut-off lengths");
1990 ir->rcoulomb_switch = get_ereal(&inp, "rcoulomb-switch", 0.0, wi);
1991 ir->rcoulomb = get_ereal(&inp, "rcoulomb", 1.0, wi);
1992 printStringNoNewline(&inp,
1993 "Relative dielectric constant for the medium and the reaction field");
1994 ir->epsilon_r = get_ereal(&inp, "epsilon-r", 1.0, wi);
1995 ir->epsilon_rf = get_ereal(&inp, "epsilon-rf", 0.0, wi);
1996 printStringNoNewline(&inp, "Method for doing Van der Waals");
1997 ir->vdwtype = get_eeenum(&inp, "vdw-type", evdw_names, wi);
1998 ir->vdw_modifier = get_eeenum(&inp, "vdw-modifier", eintmod_names, wi);
1999 printStringNoNewline(&inp, "cut-off lengths");
2000 ir->rvdw_switch = get_ereal(&inp, "rvdw-switch", 0.0, wi);
2001 ir->rvdw = get_ereal(&inp, "rvdw", 1.0, wi);
2002 printStringNoNewline(&inp, "Apply long range dispersion corrections for Energy and Pressure");
2003 ir->eDispCorr = get_eeenum(&inp, "DispCorr", edispc_names, wi);
2004 printStringNoNewline(&inp, "Extension of the potential lookup tables beyond the cut-off");
2005 ir->tabext = get_ereal(&inp, "table-extension", 1.0, wi);
2006 printStringNoNewline(&inp, "Separate tables between energy group pairs");
2007 setStringEntry(&inp, "energygrp-table", is->egptable, nullptr);
2008 printStringNoNewline(&inp, "Spacing for the PME/PPPM FFT grid");
2009 ir->fourier_spacing = get_ereal(&inp, "fourierspacing", 0.12, wi);
2010 printStringNoNewline(&inp, "FFT grid size, when a value is 0 fourierspacing will be used");
2011 ir->nkx = get_eint(&inp, "fourier-nx", 0, wi);
2012 ir->nky = get_eint(&inp, "fourier-ny", 0, wi);
2013 ir->nkz = get_eint(&inp, "fourier-nz", 0, wi);
2014 printStringNoNewline(&inp, "EWALD/PME/PPPM parameters");
2015 ir->pme_order = get_eint(&inp, "pme-order", 4, wi);
2016 ir->ewald_rtol = get_ereal(&inp, "ewald-rtol", 0.00001, wi);
2017 ir->ewald_rtol_lj = get_ereal(&inp, "ewald-rtol-lj", 0.001, wi);
2018 ir->ljpme_combination_rule = get_eeenum(&inp, "lj-pme-comb-rule", eljpme_names, wi);
2019 ir->ewald_geometry = get_eeenum(&inp, "ewald-geometry", eewg_names, wi);
2020 ir->epsilon_surface = get_ereal(&inp, "epsilon-surface", 0.0, wi);
2022 /* Implicit solvation is no longer supported, but we need grompp
2023 to be able to refuse old .mdp files that would have built a tpr
2024 to run it. Thus, only "no" is accepted. */
2025 ir->implicit_solvent = (get_eeenum(&inp, "implicit-solvent", no_names, wi) != 0);
2027 /* Coupling stuff */
2028 printStringNewline(&inp, "OPTIONS FOR WEAK COUPLING ALGORITHMS");
2029 printStringNoNewline(&inp, "Temperature coupling");
2030 ir->etc = get_eeenum(&inp, "tcoupl", etcoupl_names, wi);
2031 ir->nsttcouple = get_eint(&inp, "nsttcouple", -1, wi);
2032 ir->opts.nhchainlength = get_eint(&inp, "nh-chain-length", 10, wi);
2033 ir->bPrintNHChains = (get_eeenum(&inp, "print-nose-hoover-chain-variables", yesno_names, wi) != 0);
2034 printStringNoNewline(&inp, "Groups to couple separately");
2035 setStringEntry(&inp, "tc-grps", is->tcgrps, nullptr);
2036 printStringNoNewline(&inp, "Time constant (ps) and reference temperature (K)");
2037 setStringEntry(&inp, "tau-t", is->tau_t, nullptr);
2038 setStringEntry(&inp, "ref-t", is->ref_t, nullptr);
2039 printStringNoNewline(&inp, "pressure coupling");
2040 ir->epc = get_eeenum(&inp, "pcoupl", epcoupl_names, wi);
2041 ir->epct = get_eeenum(&inp, "pcoupltype", epcoupltype_names, wi);
2042 ir->nstpcouple = get_eint(&inp, "nstpcouple", -1, wi);
2043 printStringNoNewline(&inp, "Time constant (ps), compressibility (1/bar) and reference P (bar)");
2044 ir->tau_p = get_ereal(&inp, "tau-p", 1.0, wi);
2045 setStringEntry(&inp, "compressibility", dumstr[0], nullptr);
2046 setStringEntry(&inp, "ref-p", dumstr[1], nullptr);
2047 printStringNoNewline(&inp, "Scaling of reference coordinates, No, All or COM");
2048 ir->refcoord_scaling = get_eeenum(&inp, "refcoord-scaling", erefscaling_names, wi);
2050 /* QMMM */
2051 printStringNewline(&inp, "OPTIONS FOR QMMM calculations");
2052 ir->bQMMM = (get_eeenum(&inp, "QMMM", yesno_names, wi) != 0);
2053 printStringNoNewline(&inp, "Groups treated Quantum Mechanically");
2054 setStringEntry(&inp, "QMMM-grps", is->QMMM, nullptr);
2055 printStringNoNewline(&inp, "QM method");
2056 setStringEntry(&inp, "QMmethod", is->QMmethod, nullptr);
2057 printStringNoNewline(&inp, "QMMM scheme");
2058 ir->QMMMscheme = get_eeenum(&inp, "QMMMscheme", eQMMMscheme_names, wi);
2059 printStringNoNewline(&inp, "QM basisset");
2060 setStringEntry(&inp, "QMbasis", is->QMbasis, nullptr);
2061 printStringNoNewline(&inp, "QM charge");
2062 setStringEntry(&inp, "QMcharge", is->QMcharge, nullptr);
2063 printStringNoNewline(&inp, "QM multiplicity");
2064 setStringEntry(&inp, "QMmult", is->QMmult, nullptr);
2065 printStringNoNewline(&inp, "Surface Hopping");
2066 setStringEntry(&inp, "SH", is->bSH, nullptr);
2067 printStringNoNewline(&inp, "CAS space options");
2068 setStringEntry(&inp, "CASorbitals", is->CASorbitals, nullptr);
2069 setStringEntry(&inp, "CASelectrons", is->CASelectrons, nullptr);
2070 setStringEntry(&inp, "SAon", is->SAon, nullptr);
2071 setStringEntry(&inp, "SAoff", is->SAoff, nullptr);
2072 setStringEntry(&inp, "SAsteps", is->SAsteps, nullptr);
2073 printStringNoNewline(&inp, "Scale factor for MM charges");
2074 ir->scalefactor = get_ereal(&inp, "MMChargeScaleFactor", 1.0, wi);
2076 /* Simulated annealing */
2077 printStringNewline(&inp, "SIMULATED ANNEALING");
2078 printStringNoNewline(&inp, "Type of annealing for each temperature group (no/single/periodic)");
2079 setStringEntry(&inp, "annealing", is->anneal, nullptr);
2080 printStringNoNewline(&inp,
2081 "Number of time points to use for specifying annealing in each group");
2082 setStringEntry(&inp, "annealing-npoints", is->anneal_npoints, nullptr);
2083 printStringNoNewline(&inp, "List of times at the annealing points for each group");
2084 setStringEntry(&inp, "annealing-time", is->anneal_time, nullptr);
2085 printStringNoNewline(&inp, "Temp. at each annealing point, for each group.");
2086 setStringEntry(&inp, "annealing-temp", is->anneal_temp, nullptr);
2088 /* Startup run */
2089 printStringNewline(&inp, "GENERATE VELOCITIES FOR STARTUP RUN");
2090 opts->bGenVel = (get_eeenum(&inp, "gen-vel", yesno_names, wi) != 0);
2091 opts->tempi = get_ereal(&inp, "gen-temp", 300.0, wi);
2092 opts->seed = get_eint(&inp, "gen-seed", -1, wi);
2094 /* Shake stuff */
2095 printStringNewline(&inp, "OPTIONS FOR BONDS");
2096 opts->nshake = get_eeenum(&inp, "constraints", constraints, wi);
2097 printStringNoNewline(&inp, "Type of constraint algorithm");
2098 ir->eConstrAlg = get_eeenum(&inp, "constraint-algorithm", econstr_names, wi);
2099 printStringNoNewline(&inp, "Do not constrain the start configuration");
2100 ir->bContinuation = (get_eeenum(&inp, "continuation", yesno_names, wi) != 0);
2101 printStringNoNewline(&inp,
2102 "Use successive overrelaxation to reduce the number of shake iterations");
2103 ir->bShakeSOR = (get_eeenum(&inp, "Shake-SOR", yesno_names, wi) != 0);
2104 printStringNoNewline(&inp, "Relative tolerance of shake");
2105 ir->shake_tol = get_ereal(&inp, "shake-tol", 0.0001, wi);
2106 printStringNoNewline(&inp, "Highest order in the expansion of the constraint coupling matrix");
2107 ir->nProjOrder = get_eint(&inp, "lincs-order", 4, wi);
2108 printStringNoNewline(&inp, "Number of iterations in the final step of LINCS. 1 is fine for");
2109 printStringNoNewline(&inp, "normal simulations, but use 2 to conserve energy in NVE runs.");
2110 printStringNoNewline(&inp, "For energy minimization with constraints it should be 4 to 8.");
2111 ir->nLincsIter = get_eint(&inp, "lincs-iter", 1, wi);
2112 printStringNoNewline(&inp, "Lincs will write a warning to the stderr if in one step a bond");
2113 printStringNoNewline(&inp, "rotates over more degrees than");
2114 ir->LincsWarnAngle = get_ereal(&inp, "lincs-warnangle", 30.0, wi);
2115 printStringNoNewline(&inp, "Convert harmonic bonds to morse potentials");
2116 opts->bMorse = (get_eeenum(&inp, "morse", yesno_names, wi) != 0);
2118 /* Energy group exclusions */
2119 printStringNewline(&inp, "ENERGY GROUP EXCLUSIONS");
2120 printStringNoNewline(
2121 &inp, "Pairs of energy groups for which all non-bonded interactions are excluded");
2122 setStringEntry(&inp, "energygrp-excl", is->egpexcl, nullptr);
2124 /* Walls */
2125 printStringNewline(&inp, "WALLS");
2126 printStringNoNewline(
2127 &inp, "Number of walls, type, atom types, densities and box-z scale factor for Ewald");
2128 ir->nwall = get_eint(&inp, "nwall", 0, wi);
2129 ir->wall_type = get_eeenum(&inp, "wall-type", ewt_names, wi);
2130 ir->wall_r_linpot = get_ereal(&inp, "wall-r-linpot", -1, wi);
2131 setStringEntry(&inp, "wall-atomtype", is->wall_atomtype, nullptr);
2132 setStringEntry(&inp, "wall-density", is->wall_density, nullptr);
2133 ir->wall_ewald_zfac = get_ereal(&inp, "wall-ewald-zfac", 3, wi);
2135 /* COM pulling */
2136 printStringNewline(&inp, "COM PULLING");
2137 ir->bPull = (get_eeenum(&inp, "pull", yesno_names, wi) != 0);
2138 if (ir->bPull)
2140 snew(ir->pull, 1);
2141 is->pull_grp = read_pullparams(&inp, ir->pull, wi);
2144 /* AWH biasing
2145 NOTE: needs COM pulling input */
2146 printStringNewline(&inp, "AWH biasing");
2147 ir->bDoAwh = (get_eeenum(&inp, "awh", yesno_names, wi) != 0);
2148 if (ir->bDoAwh)
2150 if (ir->bPull)
2152 ir->awhParams = gmx::readAndCheckAwhParams(&inp, ir, wi);
2154 else
2156 gmx_fatal(FARGS, "AWH biasing is only compatible with COM pulling turned on");
2160 /* Enforced rotation */
2161 printStringNewline(&inp, "ENFORCED ROTATION");
2162 printStringNoNewline(&inp, "Enforced rotation: No or Yes");
2163 ir->bRot = (get_eeenum(&inp, "rotation", yesno_names, wi) != 0);
2164 if (ir->bRot)
2166 snew(ir->rot, 1);
2167 is->rot_grp = read_rotparams(&inp, ir->rot, wi);
2170 /* Interactive MD */
2171 ir->bIMD = FALSE;
2172 printStringNewline(&inp, "Group to display and/or manipulate in interactive MD session");
2173 setStringEntry(&inp, "IMD-group", is->imd_grp, nullptr);
2174 if (is->imd_grp[0] != '\0')
2176 snew(ir->imd, 1);
2177 ir->bIMD = TRUE;
2180 /* Refinement */
2181 printStringNewline(&inp, "NMR refinement stuff");
2182 printStringNoNewline(&inp, "Distance restraints type: No, Simple or Ensemble");
2183 ir->eDisre = get_eeenum(&inp, "disre", edisre_names, wi);
2184 printStringNoNewline(
2185 &inp, "Force weighting of pairs in one distance restraint: Conservative or Equal");
2186 ir->eDisreWeighting = get_eeenum(&inp, "disre-weighting", edisreweighting_names, wi);
2187 printStringNoNewline(&inp, "Use sqrt of the time averaged times the instantaneous violation");
2188 ir->bDisreMixed = (get_eeenum(&inp, "disre-mixed", yesno_names, wi) != 0);
2189 ir->dr_fc = get_ereal(&inp, "disre-fc", 1000.0, wi);
2190 ir->dr_tau = get_ereal(&inp, "disre-tau", 0.0, wi);
2191 printStringNoNewline(&inp, "Output frequency for pair distances to energy file");
2192 ir->nstdisreout = get_eint(&inp, "nstdisreout", 100, wi);
2193 printStringNoNewline(&inp, "Orientation restraints: No or Yes");
2194 opts->bOrire = (get_eeenum(&inp, "orire", yesno_names, wi) != 0);
2195 printStringNoNewline(&inp, "Orientation restraints force constant and tau for time averaging");
2196 ir->orires_fc = get_ereal(&inp, "orire-fc", 0.0, wi);
2197 ir->orires_tau = get_ereal(&inp, "orire-tau", 0.0, wi);
2198 setStringEntry(&inp, "orire-fitgrp", is->orirefitgrp, nullptr);
2199 printStringNoNewline(&inp, "Output frequency for trace(SD) and S to energy file");
2200 ir->nstorireout = get_eint(&inp, "nstorireout", 100, wi);
2202 /* free energy variables */
2203 printStringNewline(&inp, "Free energy variables");
2204 ir->efep = get_eeenum(&inp, "free-energy", efep_names, wi);
2205 setStringEntry(&inp, "couple-moltype", is->couple_moltype, nullptr);
2206 opts->couple_lam0 = get_eeenum(&inp, "couple-lambda0", couple_lam, wi);
2207 opts->couple_lam1 = get_eeenum(&inp, "couple-lambda1", couple_lam, wi);
2208 opts->bCoupleIntra = (get_eeenum(&inp, "couple-intramol", yesno_names, wi) != 0);
2210 fep->init_lambda = get_ereal(&inp, "init-lambda", -1, wi); /* start with -1 so
2211 we can recognize if
2212 it was not entered */
2213 fep->init_fep_state = get_eint(&inp, "init-lambda-state", -1, wi);
2214 fep->delta_lambda = get_ereal(&inp, "delta-lambda", 0.0, wi);
2215 fep->nstdhdl = get_eint(&inp, "nstdhdl", 50, wi);
2216 setStringEntry(&inp, "fep-lambdas", is->fep_lambda[efptFEP], nullptr);
2217 setStringEntry(&inp, "mass-lambdas", is->fep_lambda[efptMASS], nullptr);
2218 setStringEntry(&inp, "coul-lambdas", is->fep_lambda[efptCOUL], nullptr);
2219 setStringEntry(&inp, "vdw-lambdas", is->fep_lambda[efptVDW], nullptr);
2220 setStringEntry(&inp, "bonded-lambdas", is->fep_lambda[efptBONDED], nullptr);
2221 setStringEntry(&inp, "restraint-lambdas", is->fep_lambda[efptRESTRAINT], nullptr);
2222 setStringEntry(&inp, "temperature-lambdas", is->fep_lambda[efptTEMPERATURE], nullptr);
2223 fep->lambda_neighbors = get_eint(&inp, "calc-lambda-neighbors", 1, wi);
2224 setStringEntry(&inp, "init-lambda-weights", is->lambda_weights, nullptr);
2225 fep->edHdLPrintEnergy = get_eeenum(&inp, "dhdl-print-energy", edHdLPrintEnergy_names, wi);
2226 fep->sc_alpha = get_ereal(&inp, "sc-alpha", 0.0, wi);
2227 fep->sc_power = get_eint(&inp, "sc-power", 1, wi);
2228 fep->sc_r_power = get_ereal(&inp, "sc-r-power", 6.0, wi);
2229 fep->sc_sigma = get_ereal(&inp, "sc-sigma", 0.3, wi);
2230 fep->bScCoul = (get_eeenum(&inp, "sc-coul", yesno_names, wi) != 0);
2231 fep->dh_hist_size = get_eint(&inp, "dh_hist_size", 0, wi);
2232 fep->dh_hist_spacing = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
2233 fep->separate_dhdl_file = get_eeenum(&inp, "separate-dhdl-file", separate_dhdl_file_names, wi);
2234 fep->dhdl_derivatives = get_eeenum(&inp, "dhdl-derivatives", dhdl_derivatives_names, wi);
2235 fep->dh_hist_size = get_eint(&inp, "dh_hist_size", 0, wi);
2236 fep->dh_hist_spacing = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
2238 /* Non-equilibrium MD stuff */
2239 printStringNewline(&inp, "Non-equilibrium MD stuff");
2240 setStringEntry(&inp, "acc-grps", is->accgrps, nullptr);
2241 setStringEntry(&inp, "accelerate", is->acc, nullptr);
2242 setStringEntry(&inp, "freezegrps", is->freeze, nullptr);
2243 setStringEntry(&inp, "freezedim", is->frdim, nullptr);
2244 ir->cos_accel = get_ereal(&inp, "cos-acceleration", 0, wi);
2245 setStringEntry(&inp, "deform", is->deform, nullptr);
2247 /* simulated tempering variables */
2248 printStringNewline(&inp, "simulated tempering variables");
2249 ir->bSimTemp = (get_eeenum(&inp, "simulated-tempering", yesno_names, wi) != 0);
2250 ir->simtempvals->eSimTempScale = get_eeenum(&inp, "simulated-tempering-scaling", esimtemp_names, wi);
2251 ir->simtempvals->simtemp_low = get_ereal(&inp, "sim-temp-low", 300.0, wi);
2252 ir->simtempvals->simtemp_high = get_ereal(&inp, "sim-temp-high", 300.0, wi);
2254 /* expanded ensemble variables */
2255 if (ir->efep == efepEXPANDED || ir->bSimTemp)
2257 read_expandedparams(&inp, expand, wi);
2260 /* Electric fields */
2262 gmx::KeyValueTreeObject convertedValues = flatKeyValueTreeFromInpFile(inp);
2263 gmx::KeyValueTreeTransformer transform;
2264 transform.rules()->addRule().keyMatchType("/", gmx::StringCompareType::CaseAndDashInsensitive);
2265 mdModules->initMdpTransform(transform.rules());
2266 for (const auto& path : transform.mappedPaths())
2268 GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
2269 mark_einp_set(inp, path[0].c_str());
2271 MdpErrorHandler errorHandler(wi);
2272 auto result = transform.transform(convertedValues, &errorHandler);
2273 ir->params = new gmx::KeyValueTreeObject(result.object());
2274 mdModules->adjustInputrecBasedOnModules(ir);
2275 errorHandler.setBackMapping(result.backMapping());
2276 mdModules->assignOptionsToModules(*ir->params, &errorHandler);
2279 /* Ion/water position swapping ("computational electrophysiology") */
2280 printStringNewline(&inp,
2281 "Ion/water position swapping for computational electrophysiology setups");
2282 printStringNoNewline(&inp, "Swap positions along direction: no, X, Y, Z");
2283 ir->eSwapCoords = get_eeenum(&inp, "swapcoords", eSwapTypes_names, wi);
2284 if (ir->eSwapCoords != eswapNO)
2286 char buf[STRLEN];
2287 int nIonTypes;
2290 snew(ir->swap, 1);
2291 printStringNoNewline(&inp, "Swap attempt frequency");
2292 ir->swap->nstswap = get_eint(&inp, "swap-frequency", 1, wi);
2293 printStringNoNewline(&inp, "Number of ion types to be controlled");
2294 nIonTypes = get_eint(&inp, "iontypes", 1, wi);
2295 if (nIonTypes < 1)
2297 warning_error(wi, "You need to provide at least one ion type for position exchanges.");
2299 ir->swap->ngrp = nIonTypes + eSwapFixedGrpNR;
2300 snew(ir->swap->grp, ir->swap->ngrp);
2301 for (i = 0; i < ir->swap->ngrp; i++)
2303 snew(ir->swap->grp[i].molname, STRLEN);
2305 printStringNoNewline(&inp,
2306 "Two index groups that contain the compartment-partitioning atoms");
2307 setStringEntry(&inp, "split-group0", ir->swap->grp[eGrpSplit0].molname, nullptr);
2308 setStringEntry(&inp, "split-group1", ir->swap->grp[eGrpSplit1].molname, nullptr);
2309 printStringNoNewline(&inp,
2310 "Use center of mass of split groups (yes/no), otherwise center of "
2311 "geometry is used");
2312 ir->swap->massw_split[0] = (get_eeenum(&inp, "massw-split0", yesno_names, wi) != 0);
2313 ir->swap->massw_split[1] = (get_eeenum(&inp, "massw-split1", yesno_names, wi) != 0);
2315 printStringNoNewline(&inp, "Name of solvent molecules");
2316 setStringEntry(&inp, "solvent-group", ir->swap->grp[eGrpSolvent].molname, nullptr);
2318 printStringNoNewline(&inp,
2319 "Split cylinder: radius, upper and lower extension (nm) (this will "
2320 "define the channels)");
2321 printStringNoNewline(&inp,
2322 "Note that the split cylinder settings do not have an influence on "
2323 "the swapping protocol,");
2324 printStringNoNewline(
2325 &inp,
2326 "however, if correctly defined, the permeation events are recorded per channel");
2327 ir->swap->cyl0r = get_ereal(&inp, "cyl0-r", 2.0, wi);
2328 ir->swap->cyl0u = get_ereal(&inp, "cyl0-up", 1.0, wi);
2329 ir->swap->cyl0l = get_ereal(&inp, "cyl0-down", 1.0, wi);
2330 ir->swap->cyl1r = get_ereal(&inp, "cyl1-r", 2.0, wi);
2331 ir->swap->cyl1u = get_ereal(&inp, "cyl1-up", 1.0, wi);
2332 ir->swap->cyl1l = get_ereal(&inp, "cyl1-down", 1.0, wi);
2334 printStringNoNewline(
2335 &inp,
2336 "Average the number of ions per compartment over these many swap attempt steps");
2337 ir->swap->nAverage = get_eint(&inp, "coupl-steps", 10, wi);
2339 printStringNoNewline(
2340 &inp, "Names of the ion types that can be exchanged with solvent molecules,");
2341 printStringNoNewline(
2342 &inp, "and the requested number of ions of this type in compartments A and B");
2343 printStringNoNewline(&inp, "-1 means fix the numbers as found in step 0");
2344 for (i = 0; i < nIonTypes; i++)
2346 int ig = eSwapFixedGrpNR + i;
2348 sprintf(buf, "iontype%d-name", i);
2349 setStringEntry(&inp, buf, ir->swap->grp[ig].molname, nullptr);
2350 sprintf(buf, "iontype%d-in-A", i);
2351 ir->swap->grp[ig].nmolReq[0] = get_eint(&inp, buf, -1, wi);
2352 sprintf(buf, "iontype%d-in-B", i);
2353 ir->swap->grp[ig].nmolReq[1] = get_eint(&inp, buf, -1, wi);
2356 printStringNoNewline(
2357 &inp,
2358 "By default (i.e. bulk offset = 0.0), ion/water exchanges happen between layers");
2359 printStringNoNewline(
2360 &inp,
2361 "at maximum distance (= bulk concentration) to the split group layers. However,");
2362 printStringNoNewline(&inp,
2363 "an offset b (-1.0 < b < +1.0) can be specified to offset the bulk "
2364 "layer from the middle at 0.0");
2365 printStringNoNewline(&inp,
2366 "towards one of the compartment-partitioning layers (at +/- 1.0).");
2367 ir->swap->bulkOffset[0] = get_ereal(&inp, "bulk-offsetA", 0.0, wi);
2368 ir->swap->bulkOffset[1] = get_ereal(&inp, "bulk-offsetB", 0.0, wi);
2369 if (!(ir->swap->bulkOffset[0] > -1.0 && ir->swap->bulkOffset[0] < 1.0)
2370 || !(ir->swap->bulkOffset[1] > -1.0 && ir->swap->bulkOffset[1] < 1.0))
2372 warning_error(wi, "Bulk layer offsets must be > -1.0 and < 1.0 !");
2375 printStringNoNewline(
2376 &inp, "Start to swap ions if threshold difference to requested count is reached");
2377 ir->swap->threshold = get_ereal(&inp, "threshold", 1.0, wi);
2380 /* AdResS is no longer supported, but we need grompp to be able to
2381 refuse to process old .mdp files that used it. */
2382 ir->bAdress = (get_eeenum(&inp, "adress", no_names, wi) != 0);
2384 /* User defined thingies */
2385 printStringNewline(&inp, "User defined thingies");
2386 setStringEntry(&inp, "user1-grps", is->user1, nullptr);
2387 setStringEntry(&inp, "user2-grps", is->user2, nullptr);
2388 ir->userint1 = get_eint(&inp, "userint1", 0, wi);
2389 ir->userint2 = get_eint(&inp, "userint2", 0, wi);
2390 ir->userint3 = get_eint(&inp, "userint3", 0, wi);
2391 ir->userint4 = get_eint(&inp, "userint4", 0, wi);
2392 ir->userreal1 = get_ereal(&inp, "userreal1", 0, wi);
2393 ir->userreal2 = get_ereal(&inp, "userreal2", 0, wi);
2394 ir->userreal3 = get_ereal(&inp, "userreal3", 0, wi);
2395 ir->userreal4 = get_ereal(&inp, "userreal4", 0, wi);
2396 #undef CTYPE
2399 gmx::TextOutputFile stream(mdparout);
2400 write_inpfile(&stream, mdparout, &inp, FALSE, writeMdpHeader, wi);
2402 // Transform module data into a flat key-value tree for output.
2403 gmx::KeyValueTreeBuilder builder;
2404 gmx::KeyValueTreeObjectBuilder builderObject = builder.rootObject();
2405 mdModules->buildMdpOutput(&builderObject);
2407 gmx::TextWriter writer(&stream);
2408 writeKeyValueTreeAsMdp(&writer, builder.build());
2410 stream.close();
2413 /* Process options if necessary */
2414 for (m = 0; m < 2; m++)
2416 for (i = 0; i < 2 * DIM; i++)
2418 dumdub[m][i] = 0.0;
2420 if (ir->epc)
2422 switch (ir->epct)
2424 case epctISOTROPIC:
2425 if (sscanf(dumstr[m], "%lf", &(dumdub[m][XX])) != 1)
2427 warning_error(
2429 "Pressure coupling incorrect number of values (I need exactly 1)");
2431 dumdub[m][YY] = dumdub[m][ZZ] = dumdub[m][XX];
2432 break;
2433 case epctSEMIISOTROPIC:
2434 case epctSURFACETENSION:
2435 if (sscanf(dumstr[m], "%lf%lf", &(dumdub[m][XX]), &(dumdub[m][ZZ])) != 2)
2437 warning_error(
2439 "Pressure coupling incorrect number of values (I need exactly 2)");
2441 dumdub[m][YY] = dumdub[m][XX];
2442 break;
2443 case epctANISOTROPIC:
2444 if (sscanf(dumstr[m], "%lf%lf%lf%lf%lf%lf", &(dumdub[m][XX]), &(dumdub[m][YY]),
2445 &(dumdub[m][ZZ]), &(dumdub[m][3]), &(dumdub[m][4]), &(dumdub[m][5]))
2446 != 6)
2448 warning_error(
2450 "Pressure coupling incorrect number of values (I need exactly 6)");
2452 break;
2453 default:
2454 gmx_fatal(FARGS, "Pressure coupling type %s not implemented yet",
2455 epcoupltype_names[ir->epct]);
2459 clear_mat(ir->ref_p);
2460 clear_mat(ir->compress);
2461 for (i = 0; i < DIM; i++)
2463 ir->ref_p[i][i] = dumdub[1][i];
2464 ir->compress[i][i] = dumdub[0][i];
2466 if (ir->epct == epctANISOTROPIC)
2468 ir->ref_p[XX][YY] = dumdub[1][3];
2469 ir->ref_p[XX][ZZ] = dumdub[1][4];
2470 ir->ref_p[YY][ZZ] = dumdub[1][5];
2471 if (ir->ref_p[XX][YY] != 0 && ir->ref_p[XX][ZZ] != 0 && ir->ref_p[YY][ZZ] != 0)
2473 warning(wi,
2474 "All off-diagonal reference pressures are non-zero. Are you sure you want to "
2475 "apply a threefold shear stress?\n");
2477 ir->compress[XX][YY] = dumdub[0][3];
2478 ir->compress[XX][ZZ] = dumdub[0][4];
2479 ir->compress[YY][ZZ] = dumdub[0][5];
2480 for (i = 0; i < DIM; i++)
2482 for (m = 0; m < i; m++)
2484 ir->ref_p[i][m] = ir->ref_p[m][i];
2485 ir->compress[i][m] = ir->compress[m][i];
2490 if (ir->comm_mode == ecmNO)
2492 ir->nstcomm = 0;
2495 opts->couple_moltype = nullptr;
2496 if (strlen(is->couple_moltype) > 0)
2498 if (ir->efep != efepNO)
2500 opts->couple_moltype = gmx_strdup(is->couple_moltype);
2501 if (opts->couple_lam0 == opts->couple_lam1)
2503 warning(wi, "The lambda=0 and lambda=1 states for coupling are identical");
2505 if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE || opts->couple_lam1 == ecouplamNONE))
2507 warning_note(
2509 "For proper sampling of the (nearly) decoupled state, stochastic dynamics "
2510 "should be used");
2513 else
2515 warning_note(wi,
2516 "Free energy is turned off, so we will not decouple the molecule listed "
2517 "in your input.");
2520 /* FREE ENERGY AND EXPANDED ENSEMBLE OPTIONS */
2521 if (ir->efep != efepNO)
2523 if (fep->delta_lambda > 0)
2525 ir->efep = efepSLOWGROWTH;
2529 if (fep->edHdLPrintEnergy == edHdLPrintEnergyYES)
2531 fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
2532 warning_note(wi,
2533 "Old option for dhdl-print-energy given: "
2534 "changing \"yes\" to \"total\"\n");
2537 if (ir->bSimTemp && (fep->edHdLPrintEnergy == edHdLPrintEnergyNO))
2539 /* always print out the energy to dhdl if we are doing
2540 expanded ensemble, since we need the total energy for
2541 analysis if the temperature is changing. In some
2542 conditions one may only want the potential energy, so
2543 we will allow that if the appropriate mdp setting has
2544 been enabled. Otherwise, total it is:
2546 fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
2549 if ((ir->efep != efepNO) || ir->bSimTemp)
2551 ir->bExpanded = FALSE;
2552 if ((ir->efep == efepEXPANDED) || ir->bSimTemp)
2554 ir->bExpanded = TRUE;
2556 do_fep_params(ir, is->fep_lambda, is->lambda_weights, wi);
2557 if (ir->bSimTemp) /* done after fep params */
2559 do_simtemp_params(ir);
2562 /* Because sc-coul (=FALSE by default) only acts on the lambda state
2563 * setup and not on the old way of specifying the free-energy setup,
2564 * we should check for using soft-core when not needed, since that
2565 * can complicate the sampling significantly.
2566 * Note that we only check for the automated coupling setup.
2567 * If the (advanced) user does FEP through manual topology changes,
2568 * this check will not be triggered.
2570 if (ir->efep != efepNO && ir->fepvals->n_lambda == 0 && ir->fepvals->sc_alpha != 0
2571 && (couple_lambda_has_vdw_on(opts->couple_lam0) && couple_lambda_has_vdw_on(opts->couple_lam1)))
2573 warning(wi,
2574 "You are using soft-core interactions while the Van der Waals interactions are "
2575 "not decoupled (note that the sc-coul option is only active when using lambda "
2576 "states). Although this will not lead to errors, you will need much more "
2577 "sampling than without soft-core interactions. Consider using sc-alpha=0.");
2580 else
2582 ir->fepvals->n_lambda = 0;
2585 /* WALL PARAMETERS */
2587 do_wall_params(ir, is->wall_atomtype, is->wall_density, opts, wi);
2589 /* ORIENTATION RESTRAINT PARAMETERS */
2591 if (opts->bOrire && gmx::splitString(is->orirefitgrp).size() != 1)
2593 warning_error(wi, "ERROR: Need one orientation restraint fit group\n");
2596 /* DEFORMATION PARAMETERS */
2598 clear_mat(ir->deform);
2599 for (i = 0; i < 6; i++)
2601 dumdub[0][i] = 0;
2604 double gmx_unused canary;
2605 int ndeform = sscanf(is->deform, "%lf %lf %lf %lf %lf %lf %lf", &(dumdub[0][0]), &(dumdub[0][1]),
2606 &(dumdub[0][2]), &(dumdub[0][3]), &(dumdub[0][4]), &(dumdub[0][5]), &canary);
2608 if (strlen(is->deform) > 0 && ndeform != 6)
2610 warning_error(
2611 wi, gmx::formatString(
2612 "Cannot parse exactly 6 box deformation velocities from string '%s'", is->deform)
2613 .c_str());
2615 for (i = 0; i < 3; i++)
2617 ir->deform[i][i] = dumdub[0][i];
2619 ir->deform[YY][XX] = dumdub[0][3];
2620 ir->deform[ZZ][XX] = dumdub[0][4];
2621 ir->deform[ZZ][YY] = dumdub[0][5];
2622 if (ir->epc != epcNO)
2624 for (i = 0; i < 3; i++)
2626 for (j = 0; j <= i; j++)
2628 if (ir->deform[i][j] != 0 && ir->compress[i][j] != 0)
2630 warning_error(wi, "A box element has deform set and compressibility > 0");
2634 for (i = 0; i < 3; i++)
2636 for (j = 0; j < i; j++)
2638 if (ir->deform[i][j] != 0)
2640 for (m = j; m < DIM; m++)
2642 if (ir->compress[m][j] != 0)
2644 sprintf(warn_buf,
2645 "An off-diagonal box element has deform set while "
2646 "compressibility > 0 for the same component of another box "
2647 "vector, this might lead to spurious periodicity effects.");
2648 warning(wi, warn_buf);
2656 /* Ion/water position swapping checks */
2657 if (ir->eSwapCoords != eswapNO)
2659 if (ir->swap->nstswap < 1)
2661 warning_error(wi, "swap_frequency must be 1 or larger when ion swapping is requested");
2663 if (ir->swap->nAverage < 1)
2665 warning_error(wi, "coupl_steps must be 1 or larger.\n");
2667 if (ir->swap->threshold < 1.0)
2669 warning_error(wi, "Ion count threshold must be at least 1.\n");
2673 sfree(dumstr[0]);
2674 sfree(dumstr[1]);
2677 static int search_QMstring(const char* s, int ng, const char* gn[])
2679 /* same as normal search_string, but this one searches QM strings */
2680 int i;
2682 for (i = 0; (i < ng); i++)
2684 if (gmx_strcasecmp(s, gn[i]) == 0)
2686 return i;
2690 gmx_fatal(FARGS, "this QM method or basisset (%s) is not implemented\n!", s);
2691 } /* search_QMstring */
2693 /* We would like gn to be const as well, but C doesn't allow this */
2694 /* TODO this is utility functionality (search for the index of a
2695 string in a collection), so should be refactored and located more
2696 centrally. */
2697 int search_string(const char* s, int ng, char* gn[])
2699 int i;
2701 for (i = 0; (i < ng); i++)
2703 if (gmx_strcasecmp(s, gn[i]) == 0)
2705 return i;
2709 gmx_fatal(FARGS,
2710 "Group %s referenced in the .mdp file was not found in the index file.\n"
2711 "Group names must match either [moleculetype] names or custom index group\n"
2712 "names, in which case you must supply an index file to the '-n' option\n"
2713 "of grompp.",
2717 static bool do_numbering(int natoms,
2718 SimulationGroups* groups,
2719 gmx::ArrayRef<std::string> groupsFromMdpFile,
2720 t_blocka* block,
2721 char* gnames[],
2722 SimulationAtomGroupType gtype,
2723 int restnm,
2724 int grptp,
2725 bool bVerbose,
2726 warninp_t wi)
2728 unsigned short* cbuf;
2729 AtomGroupIndices* grps = &(groups->groups[gtype]);
2730 int j, gid, aj, ognr, ntot = 0;
2731 const char* title;
2732 bool bRest;
2733 char warn_buf[STRLEN];
2735 title = shortName(gtype);
2737 snew(cbuf, natoms);
2738 /* Mark all id's as not set */
2739 for (int i = 0; (i < natoms); i++)
2741 cbuf[i] = NOGID;
2744 for (int i = 0; i != groupsFromMdpFile.ssize(); ++i)
2746 /* Lookup the group name in the block structure */
2747 gid = search_string(groupsFromMdpFile[i].c_str(), block->nr, gnames);
2748 if ((grptp != egrptpONE) || (i == 0))
2750 grps->emplace_back(gid);
2753 /* Now go over the atoms in the group */
2754 for (j = block->index[gid]; (j < block->index[gid + 1]); j++)
2757 aj = block->a[j];
2759 /* Range checking */
2760 if ((aj < 0) || (aj >= natoms))
2762 gmx_fatal(FARGS, "Invalid atom number %d in indexfile", aj + 1);
2764 /* Lookup up the old group number */
2765 ognr = cbuf[aj];
2766 if (ognr != NOGID)
2768 gmx_fatal(FARGS, "Atom %d in multiple %s groups (%d and %d)", aj + 1, title,
2769 ognr + 1, i + 1);
2771 else
2773 /* Store the group number in buffer */
2774 if (grptp == egrptpONE)
2776 cbuf[aj] = 0;
2778 else
2780 cbuf[aj] = i;
2782 ntot++;
2787 /* Now check whether we have done all atoms */
2788 bRest = FALSE;
2789 if (ntot != natoms)
2791 if (grptp == egrptpALL)
2793 gmx_fatal(FARGS, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
2795 else if (grptp == egrptpPART)
2797 sprintf(warn_buf, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
2798 warning_note(wi, warn_buf);
2800 /* Assign all atoms currently unassigned to a rest group */
2801 for (j = 0; (j < natoms); j++)
2803 if (cbuf[j] == NOGID)
2805 cbuf[j] = grps->size();
2806 bRest = TRUE;
2809 if (grptp != egrptpPART)
2811 if (bVerbose)
2813 fprintf(stderr, "Making dummy/rest group for %s containing %d elements\n", title,
2814 natoms - ntot);
2816 /* Add group name "rest" */
2817 grps->emplace_back(restnm);
2819 /* Assign the rest name to all atoms not currently assigned to a group */
2820 for (j = 0; (j < natoms); j++)
2822 if (cbuf[j] == NOGID)
2824 // group size was not updated before this here, so need to use -1.
2825 cbuf[j] = grps->size() - 1;
2831 if (grps->size() == 1 && (ntot == 0 || ntot == natoms))
2833 /* All atoms are part of one (or no) group, no index required */
2834 groups->groupNumbers[gtype].clear();
2836 else
2838 for (int j = 0; (j < natoms); j++)
2840 groups->groupNumbers[gtype].emplace_back(cbuf[j]);
2844 sfree(cbuf);
2846 return (bRest && grptp == egrptpPART);
2849 static void calc_nrdf(const gmx_mtop_t* mtop, t_inputrec* ir, char** gnames)
2851 t_grpopts* opts;
2852 pull_params_t* pull;
2853 int natoms, imin, jmin;
2854 int * nrdf2, *na_vcm, na_tot;
2855 double * nrdf_tc, *nrdf_vcm, nrdf_uc, *nrdf_vcm_sub;
2856 ivec* dof_vcm;
2857 int as;
2859 /* Calculate nrdf.
2860 * First calc 3xnr-atoms for each group
2861 * then subtract half a degree of freedom for each constraint
2863 * Only atoms and nuclei contribute to the degrees of freedom...
2866 opts = &ir->opts;
2868 const SimulationGroups& groups = mtop->groups;
2869 natoms = mtop->natoms;
2871 /* Allocate one more for a possible rest group */
2872 /* We need to sum degrees of freedom into doubles,
2873 * since floats give too low nrdf's above 3 million atoms.
2875 snew(nrdf_tc, groups.groups[SimulationAtomGroupType::TemperatureCoupling].size() + 1);
2876 snew(nrdf_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2877 snew(dof_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2878 snew(na_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2879 snew(nrdf_vcm_sub, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
2881 for (gmx::index i = 0; i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
2883 nrdf_tc[i] = 0;
2885 for (gmx::index i = 0;
2886 i < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; i++)
2888 nrdf_vcm[i] = 0;
2889 clear_ivec(dof_vcm[i]);
2890 na_vcm[i] = 0;
2891 nrdf_vcm_sub[i] = 0;
2893 snew(nrdf2, natoms);
2894 for (const AtomProxy atomP : AtomRange(*mtop))
2896 const t_atom& local = atomP.atom();
2897 int i = atomP.globalAtomNumber();
2898 nrdf2[i] = 0;
2899 if (local.ptype == eptAtom || local.ptype == eptNucleus)
2901 int g = getGroupType(groups, SimulationAtomGroupType::Freeze, i);
2902 for (int d = 0; d < DIM; d++)
2904 if (opts->nFreeze[g][d] == 0)
2906 /* Add one DOF for particle i (counted as 2*1) */
2907 nrdf2[i] += 2;
2908 /* VCM group i has dim d as a DOF */
2909 dof_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)][d] =
2913 nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, i)] +=
2914 0.5 * nrdf2[i];
2915 nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)] +=
2916 0.5 * nrdf2[i];
2920 as = 0;
2921 for (const gmx_molblock_t& molb : mtop->molblock)
2923 const gmx_moltype_t& molt = mtop->moltype[molb.type];
2924 const t_atom* atom = molt.atoms.atom;
2925 for (int mol = 0; mol < molb.nmol; mol++)
2927 for (int ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
2929 gmx::ArrayRef<const int> ia = molt.ilist[ftype].iatoms;
2930 for (int i = 0; i < molt.ilist[ftype].size();)
2932 /* Subtract degrees of freedom for the constraints,
2933 * if the particles still have degrees of freedom left.
2934 * If one of the particles is a vsite or a shell, then all
2935 * constraint motion will go there, but since they do not
2936 * contribute to the constraints the degrees of freedom do not
2937 * change.
2939 int ai = as + ia[i + 1];
2940 int aj = as + ia[i + 2];
2941 if (((atom[ia[i + 1]].ptype == eptNucleus) || (atom[ia[i + 1]].ptype == eptAtom))
2942 && ((atom[ia[i + 2]].ptype == eptNucleus) || (atom[ia[i + 2]].ptype == eptAtom)))
2944 if (nrdf2[ai] > 0)
2946 jmin = 1;
2948 else
2950 jmin = 2;
2952 if (nrdf2[aj] > 0)
2954 imin = 1;
2956 else
2958 imin = 2;
2960 imin = std::min(imin, nrdf2[ai]);
2961 jmin = std::min(jmin, nrdf2[aj]);
2962 nrdf2[ai] -= imin;
2963 nrdf2[aj] -= jmin;
2964 nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
2965 0.5 * imin;
2966 nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, aj)] -=
2967 0.5 * jmin;
2968 nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
2969 0.5 * imin;
2970 nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, aj)] -=
2971 0.5 * jmin;
2973 i += interaction_function[ftype].nratoms + 1;
2976 gmx::ArrayRef<const int> ia = molt.ilist[F_SETTLE].iatoms;
2977 for (int i = 0; i < molt.ilist[F_SETTLE].size();)
2979 /* Subtract 1 dof from every atom in the SETTLE */
2980 for (int j = 0; j < 3; j++)
2982 int ai = as + ia[i + 1 + j];
2983 imin = std::min(2, nrdf2[ai]);
2984 nrdf2[ai] -= imin;
2985 nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
2986 0.5 * imin;
2987 nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
2988 0.5 * imin;
2990 i += 4;
2992 as += molt.atoms.nr;
2996 if (ir->bPull)
2998 /* Correct nrdf for the COM constraints.
2999 * We correct using the TC and VCM group of the first atom
3000 * in the reference and pull group. If atoms in one pull group
3001 * belong to different TC or VCM groups it is anyhow difficult
3002 * to determine the optimal nrdf assignment.
3004 pull = ir->pull;
3006 for (int i = 0; i < pull->ncoord; i++)
3008 if (pull->coord[i].eType != epullCONSTRAINT)
3010 continue;
3013 imin = 1;
3015 for (int j = 0; j < 2; j++)
3017 const t_pull_group* pgrp;
3019 pgrp = &pull->group[pull->coord[i].group[j]];
3021 if (pgrp->nat > 0)
3023 /* Subtract 1/2 dof from each group */
3024 int ai = pgrp->ind[0];
3025 nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
3026 0.5 * imin;
3027 nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
3028 0.5 * imin;
3029 if (nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] < 0)
3031 gmx_fatal(FARGS,
3032 "Center of mass pulling constraints caused the number of degrees "
3033 "of freedom for temperature coupling group %s to be negative",
3034 gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][getGroupType(
3035 groups, SimulationAtomGroupType::TemperatureCoupling, ai)]]);
3038 else
3040 /* We need to subtract the whole DOF from group j=1 */
3041 imin += 1;
3047 if (ir->nstcomm != 0)
3049 int ndim_rm_vcm;
3051 /* We remove COM motion up to dim ndof_com() */
3052 ndim_rm_vcm = ndof_com(ir);
3054 /* Subtract ndim_rm_vcm (or less with frozen dimensions) from
3055 * the number of degrees of freedom in each vcm group when COM
3056 * translation is removed and 6 when rotation is removed as well.
3058 for (gmx::index j = 0;
3059 j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; j++)
3061 switch (ir->comm_mode)
3063 case ecmLINEAR:
3064 case ecmLINEAR_ACCELERATION_CORRECTION:
3065 nrdf_vcm_sub[j] = 0;
3066 for (int d = 0; d < ndim_rm_vcm; d++)
3068 if (dof_vcm[j][d])
3070 nrdf_vcm_sub[j]++;
3073 break;
3074 case ecmANGULAR: nrdf_vcm_sub[j] = 6; break;
3075 default: gmx_incons("Checking comm_mode");
3079 for (gmx::index i = 0;
3080 i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
3082 /* Count the number of atoms of TC group i for every VCM group */
3083 for (gmx::index j = 0;
3084 j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; j++)
3086 na_vcm[j] = 0;
3088 na_tot = 0;
3089 for (int ai = 0; ai < natoms; ai++)
3091 if (getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai) == i)
3093 na_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)]++;
3094 na_tot++;
3097 /* Correct for VCM removal according to the fraction of each VCM
3098 * group present in this TC group.
3100 nrdf_uc = nrdf_tc[i];
3101 nrdf_tc[i] = 0;
3102 for (gmx::index j = 0;
3103 j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; j++)
3105 if (nrdf_vcm[j] > nrdf_vcm_sub[j])
3107 nrdf_tc[i] += nrdf_uc * (static_cast<double>(na_vcm[j]) / static_cast<double>(na_tot))
3108 * (nrdf_vcm[j] - nrdf_vcm_sub[j]) / nrdf_vcm[j];
3113 for (int i = 0; (i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling])); i++)
3115 opts->nrdf[i] = nrdf_tc[i];
3116 if (opts->nrdf[i] < 0)
3118 opts->nrdf[i] = 0;
3120 fprintf(stderr, "Number of degrees of freedom in T-Coupling group %s is %.2f\n",
3121 gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][i]], opts->nrdf[i]);
3124 sfree(nrdf2);
3125 sfree(nrdf_tc);
3126 sfree(nrdf_vcm);
3127 sfree(dof_vcm);
3128 sfree(na_vcm);
3129 sfree(nrdf_vcm_sub);
3132 static bool do_egp_flag(t_inputrec* ir, SimulationGroups* groups, const char* option, const char* val, int flag)
3134 /* The maximum number of energy group pairs would be MAXPTR*(MAXPTR+1)/2.
3135 * But since this is much larger than STRLEN, such a line can not be parsed.
3136 * The real maximum is the number of names that fit in a string: STRLEN/2.
3138 #define EGP_MAX (STRLEN / 2)
3139 int j, k, nr;
3140 bool bSet;
3142 auto names = gmx::splitString(val);
3143 if (names.size() % 2 != 0)
3145 gmx_fatal(FARGS, "The number of groups for %s is odd", option);
3147 nr = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3148 bSet = FALSE;
3149 for (size_t i = 0; i < names.size() / 2; i++)
3151 // TODO this needs to be replaced by a solution using std::find_if
3152 j = 0;
3153 while ((j < nr)
3154 && gmx_strcasecmp(
3155 names[2 * i].c_str(),
3156 *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][j]])))
3158 j++;
3160 if (j == nr)
3162 gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i].c_str(), option);
3164 k = 0;
3165 while ((k < nr)
3166 && gmx_strcasecmp(
3167 names[2 * i + 1].c_str(),
3168 *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][k]])))
3170 k++;
3172 if (k == nr)
3174 gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i + 1].c_str(), option);
3176 if ((j < nr) && (k < nr))
3178 ir->opts.egp_flags[nr * j + k] |= flag;
3179 ir->opts.egp_flags[nr * k + j] |= flag;
3180 bSet = TRUE;
3184 return bSet;
3188 static void make_swap_groups(t_swapcoords* swap, t_blocka* grps, char** gnames)
3190 int ig = -1, i = 0, gind;
3191 t_swapGroup* swapg;
3194 /* Just a quick check here, more thorough checks are in mdrun */
3195 if (strcmp(swap->grp[eGrpSplit0].molname, swap->grp[eGrpSplit1].molname) == 0)
3197 gmx_fatal(FARGS, "The split groups can not both be '%s'.", swap->grp[eGrpSplit0].molname);
3200 /* Get the index atoms of the split0, split1, solvent, and swap groups */
3201 for (ig = 0; ig < swap->ngrp; ig++)
3203 swapg = &swap->grp[ig];
3204 gind = search_string(swap->grp[ig].molname, grps->nr, gnames);
3205 swapg->nat = grps->index[gind + 1] - grps->index[gind];
3207 if (swapg->nat > 0)
3209 fprintf(stderr, "%s group '%s' contains %d atoms.\n",
3210 ig < 3 ? eSwapFixedGrp_names[ig] : "Swap", swap->grp[ig].molname, swapg->nat);
3211 snew(swapg->ind, swapg->nat);
3212 for (i = 0; i < swapg->nat; i++)
3214 swapg->ind[i] = grps->a[grps->index[gind] + i];
3217 else
3219 gmx_fatal(FARGS, "Swap group %s does not contain any atoms.", swap->grp[ig].molname);
3225 static void make_IMD_group(t_IMD* IMDgroup, char* IMDgname, t_blocka* grps, char** gnames)
3227 int ig, i;
3230 ig = search_string(IMDgname, grps->nr, gnames);
3231 IMDgroup->nat = grps->index[ig + 1] - grps->index[ig];
3233 if (IMDgroup->nat > 0)
3235 fprintf(stderr,
3236 "Group '%s' with %d atoms can be activated for interactive molecular dynamics "
3237 "(IMD).\n",
3238 IMDgname, IMDgroup->nat);
3239 snew(IMDgroup->ind, IMDgroup->nat);
3240 for (i = 0; i < IMDgroup->nat; i++)
3242 IMDgroup->ind[i] = grps->a[grps->index[ig] + i];
3247 void do_index(const char* mdparin,
3248 const char* ndx,
3249 gmx_mtop_t* mtop,
3250 bool bVerbose,
3251 const gmx::MdModulesNotifier& notifier,
3252 t_inputrec* ir,
3253 warninp_t wi)
3255 t_blocka* defaultIndexGroups;
3256 int natoms;
3257 t_symtab* symtab;
3258 t_atoms atoms_all;
3259 char warnbuf[STRLEN], **gnames;
3260 int nr;
3261 real tau_min;
3262 int nstcmin;
3263 int i, j, k, restnm;
3264 bool bExcl, bTable, bAnneal, bRest;
3265 char warn_buf[STRLEN];
3267 if (bVerbose)
3269 fprintf(stderr, "processing index file...\n");
3271 if (ndx == nullptr)
3273 snew(defaultIndexGroups, 1);
3274 snew(defaultIndexGroups->index, 1);
3275 snew(gnames, 1);
3276 atoms_all = gmx_mtop_global_atoms(mtop);
3277 analyse(&atoms_all, defaultIndexGroups, &gnames, FALSE, TRUE);
3278 done_atom(&atoms_all);
3280 else
3282 defaultIndexGroups = init_index(ndx, &gnames);
3285 SimulationGroups* groups = &mtop->groups;
3286 natoms = mtop->natoms;
3287 symtab = &mtop->symtab;
3289 for (int i = 0; (i < defaultIndexGroups->nr); i++)
3291 groups->groupNames.emplace_back(put_symtab(symtab, gnames[i]));
3293 groups->groupNames.emplace_back(put_symtab(symtab, "rest"));
3294 restnm = groups->groupNames.size() - 1;
3295 GMX_RELEASE_ASSERT(restnm == defaultIndexGroups->nr, "Size of allocations must match");
3296 srenew(gnames, defaultIndexGroups->nr + 1);
3297 gnames[restnm] = *(groups->groupNames.back());
3299 set_warning_line(wi, mdparin, -1);
3301 auto temperatureCouplingTauValues = gmx::splitString(is->tau_t);
3302 auto temperatureCouplingReferenceValues = gmx::splitString(is->ref_t);
3303 auto temperatureCouplingGroupNames = gmx::splitString(is->tcgrps);
3304 if (temperatureCouplingTauValues.size() != temperatureCouplingGroupNames.size()
3305 || temperatureCouplingReferenceValues.size() != temperatureCouplingGroupNames.size())
3307 gmx_fatal(FARGS,
3308 "Invalid T coupling input: %zu groups, %zu ref-t values and "
3309 "%zu tau-t values",
3310 temperatureCouplingGroupNames.size(), temperatureCouplingReferenceValues.size(),
3311 temperatureCouplingTauValues.size());
3314 const bool useReferenceTemperature = integratorHasReferenceTemperature(ir);
3315 do_numbering(natoms, groups, temperatureCouplingGroupNames, defaultIndexGroups, gnames,
3316 SimulationAtomGroupType::TemperatureCoupling, restnm,
3317 useReferenceTemperature ? egrptpALL : egrptpALL_GENREST, bVerbose, wi);
3318 nr = groups->groups[SimulationAtomGroupType::TemperatureCoupling].size();
3319 ir->opts.ngtc = nr;
3320 snew(ir->opts.nrdf, nr);
3321 snew(ir->opts.tau_t, nr);
3322 snew(ir->opts.ref_t, nr);
3323 if (ir->eI == eiBD && ir->bd_fric == 0)
3325 fprintf(stderr, "bd-fric=0, so tau-t will be used as the inverse friction constant(s)\n");
3328 if (useReferenceTemperature)
3330 if (size_t(nr) != temperatureCouplingReferenceValues.size())
3332 gmx_fatal(FARGS, "Not enough ref-t and tau-t values!");
3335 tau_min = 1e20;
3336 convertReals(wi, temperatureCouplingTauValues, "tau-t", ir->opts.tau_t);
3337 for (i = 0; (i < nr); i++)
3339 if ((ir->eI == eiBD) && ir->opts.tau_t[i] <= 0)
3341 sprintf(warn_buf, "With integrator %s tau-t should be larger than 0", ei_names[ir->eI]);
3342 warning_error(wi, warn_buf);
3345 if (ir->etc != etcVRESCALE && ir->opts.tau_t[i] == 0)
3347 warning_note(
3349 "tau-t = -1 is the value to signal that a group should not have "
3350 "temperature coupling. Treating your use of tau-t = 0 as if you used -1.");
3353 if (ir->opts.tau_t[i] >= 0)
3355 tau_min = std::min(tau_min, ir->opts.tau_t[i]);
3358 if (ir->etc != etcNO && ir->nsttcouple == -1)
3360 ir->nsttcouple = ir_optimal_nsttcouple(ir);
3363 if (EI_VV(ir->eI))
3365 if ((ir->etc == etcNOSEHOOVER) && (ir->epc == epcBERENDSEN))
3367 gmx_fatal(FARGS,
3368 "Cannot do Nose-Hoover temperature with Berendsen pressure control with "
3369 "md-vv; use either vrescale temperature with berendsen pressure or "
3370 "Nose-Hoover temperature with MTTK pressure");
3372 if (ir->epc == epcMTTK)
3374 if (ir->etc != etcNOSEHOOVER)
3376 gmx_fatal(FARGS,
3377 "Cannot do MTTK pressure coupling without Nose-Hoover temperature "
3378 "control");
3380 else
3382 if (ir->nstpcouple != ir->nsttcouple)
3384 int mincouple = std::min(ir->nstpcouple, ir->nsttcouple);
3385 ir->nstpcouple = ir->nsttcouple = mincouple;
3386 sprintf(warn_buf,
3387 "for current Trotter decomposition methods with vv, nsttcouple and "
3388 "nstpcouple must be equal. Both have been reset to "
3389 "min(nsttcouple,nstpcouple) = %d",
3390 mincouple);
3391 warning_note(wi, warn_buf);
3396 /* velocity verlet with averaged kinetic energy KE = 0.5*(v(t+1/2) - v(t-1/2)) is implemented
3397 primarily for testing purposes, and does not work with temperature coupling other than 1 */
3399 if (ETC_ANDERSEN(ir->etc))
3401 if (ir->nsttcouple != 1)
3403 ir->nsttcouple = 1;
3404 sprintf(warn_buf,
3405 "Andersen temperature control methods assume nsttcouple = 1; there is no "
3406 "need for larger nsttcouple > 1, since no global parameters are computed. "
3407 "nsttcouple has been reset to 1");
3408 warning_note(wi, warn_buf);
3411 nstcmin = tcouple_min_integration_steps(ir->etc);
3412 if (nstcmin > 1)
3414 if (tau_min / (ir->delta_t * ir->nsttcouple) < nstcmin - 10 * GMX_REAL_EPS)
3416 sprintf(warn_buf,
3417 "For proper integration of the %s thermostat, tau-t (%g) should be at "
3418 "least %d times larger than nsttcouple*dt (%g)",
3419 ETCOUPLTYPE(ir->etc), tau_min, nstcmin, ir->nsttcouple * ir->delta_t);
3420 warning(wi, warn_buf);
3423 convertReals(wi, temperatureCouplingReferenceValues, "ref-t", ir->opts.ref_t);
3424 for (i = 0; (i < nr); i++)
3426 if (ir->opts.ref_t[i] < 0)
3428 gmx_fatal(FARGS, "ref-t for group %d negative", i);
3431 /* set the lambda mc temperature to the md integrator temperature (which should be defined
3432 if we are in this conditional) if mc_temp is negative */
3433 if (ir->expandedvals->mc_temp < 0)
3435 ir->expandedvals->mc_temp = ir->opts.ref_t[0]; /*for now, set to the first reft */
3439 /* Simulated annealing for each group. There are nr groups */
3440 auto simulatedAnnealingGroupNames = gmx::splitString(is->anneal);
3441 if (simulatedAnnealingGroupNames.size() == 1
3442 && gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[0], "N", 1))
3444 simulatedAnnealingGroupNames.resize(0);
3446 if (!simulatedAnnealingGroupNames.empty() && gmx::ssize(simulatedAnnealingGroupNames) != nr)
3448 gmx_fatal(FARGS, "Wrong number of annealing values: %zu (for %d groups)\n",
3449 simulatedAnnealingGroupNames.size(), nr);
3451 else
3453 snew(ir->opts.annealing, nr);
3454 snew(ir->opts.anneal_npoints, nr);
3455 snew(ir->opts.anneal_time, nr);
3456 snew(ir->opts.anneal_temp, nr);
3457 for (i = 0; i < nr; i++)
3459 ir->opts.annealing[i] = eannNO;
3460 ir->opts.anneal_npoints[i] = 0;
3461 ir->opts.anneal_time[i] = nullptr;
3462 ir->opts.anneal_temp[i] = nullptr;
3464 if (!simulatedAnnealingGroupNames.empty())
3466 bAnneal = FALSE;
3467 for (i = 0; i < nr; i++)
3469 if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "N", 1))
3471 ir->opts.annealing[i] = eannNO;
3473 else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "S", 1))
3475 ir->opts.annealing[i] = eannSINGLE;
3476 bAnneal = TRUE;
3478 else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "P", 1))
3480 ir->opts.annealing[i] = eannPERIODIC;
3481 bAnneal = TRUE;
3484 if (bAnneal)
3486 /* Read the other fields too */
3487 auto simulatedAnnealingPoints = gmx::splitString(is->anneal_npoints);
3488 if (simulatedAnnealingPoints.size() != simulatedAnnealingGroupNames.size())
3490 gmx_fatal(FARGS, "Found %zu annealing-npoints values for %zu groups\n",
3491 simulatedAnnealingPoints.size(), simulatedAnnealingGroupNames.size());
3493 convertInts(wi, simulatedAnnealingPoints, "annealing points", ir->opts.anneal_npoints);
3494 size_t numSimulatedAnnealingFields = 0;
3495 for (i = 0; i < nr; i++)
3497 if (ir->opts.anneal_npoints[i] == 1)
3499 gmx_fatal(
3500 FARGS,
3501 "Please specify at least a start and an end point for annealing\n");
3503 snew(ir->opts.anneal_time[i], ir->opts.anneal_npoints[i]);
3504 snew(ir->opts.anneal_temp[i], ir->opts.anneal_npoints[i]);
3505 numSimulatedAnnealingFields += ir->opts.anneal_npoints[i];
3508 auto simulatedAnnealingTimes = gmx::splitString(is->anneal_time);
3510 if (simulatedAnnealingTimes.size() != numSimulatedAnnealingFields)
3512 gmx_fatal(FARGS, "Found %zu annealing-time values, wanted %zu\n",
3513 simulatedAnnealingTimes.size(), numSimulatedAnnealingFields);
3515 auto simulatedAnnealingTemperatures = gmx::splitString(is->anneal_temp);
3516 if (simulatedAnnealingTemperatures.size() != numSimulatedAnnealingFields)
3518 gmx_fatal(FARGS, "Found %zu annealing-temp values, wanted %zu\n",
3519 simulatedAnnealingTemperatures.size(), numSimulatedAnnealingFields);
3522 std::vector<real> allSimulatedAnnealingTimes(numSimulatedAnnealingFields);
3523 std::vector<real> allSimulatedAnnealingTemperatures(numSimulatedAnnealingFields);
3524 convertReals(wi, simulatedAnnealingTimes, "anneal-time",
3525 allSimulatedAnnealingTimes.data());
3526 convertReals(wi, simulatedAnnealingTemperatures, "anneal-temp",
3527 allSimulatedAnnealingTemperatures.data());
3528 for (i = 0, k = 0; i < nr; i++)
3530 for (j = 0; j < ir->opts.anneal_npoints[i]; j++)
3532 ir->opts.anneal_time[i][j] = allSimulatedAnnealingTimes[k];
3533 ir->opts.anneal_temp[i][j] = allSimulatedAnnealingTemperatures[k];
3534 if (j == 0)
3536 if (ir->opts.anneal_time[i][0] > (ir->init_t + GMX_REAL_EPS))
3538 gmx_fatal(FARGS, "First time point for annealing > init_t.\n");
3541 else
3543 /* j>0 */
3544 if (ir->opts.anneal_time[i][j] < ir->opts.anneal_time[i][j - 1])
3546 gmx_fatal(FARGS,
3547 "Annealing timepoints out of order: t=%f comes after "
3548 "t=%f\n",
3549 ir->opts.anneal_time[i][j], ir->opts.anneal_time[i][j - 1]);
3552 if (ir->opts.anneal_temp[i][j] < 0)
3554 gmx_fatal(FARGS, "Found negative temperature in annealing: %f\n",
3555 ir->opts.anneal_temp[i][j]);
3557 k++;
3560 /* Print out some summary information, to make sure we got it right */
3561 for (i = 0; i < nr; i++)
3563 if (ir->opts.annealing[i] != eannNO)
3565 j = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
3566 fprintf(stderr, "Simulated annealing for group %s: %s, %d timepoints\n",
3567 *(groups->groupNames[j]), eann_names[ir->opts.annealing[i]],
3568 ir->opts.anneal_npoints[i]);
3569 fprintf(stderr, "Time (ps) Temperature (K)\n");
3570 /* All terms except the last one */
3571 for (j = 0; j < (ir->opts.anneal_npoints[i] - 1); j++)
3573 fprintf(stderr, "%9.1f %5.1f\n", ir->opts.anneal_time[i][j],
3574 ir->opts.anneal_temp[i][j]);
3577 /* Finally the last one */
3578 j = ir->opts.anneal_npoints[i] - 1;
3579 if (ir->opts.annealing[i] == eannSINGLE)
3581 fprintf(stderr, "%9.1f- %5.1f\n", ir->opts.anneal_time[i][j],
3582 ir->opts.anneal_temp[i][j]);
3584 else
3586 fprintf(stderr, "%9.1f %5.1f\n", ir->opts.anneal_time[i][j],
3587 ir->opts.anneal_temp[i][j]);
3588 if (std::fabs(ir->opts.anneal_temp[i][j] - ir->opts.anneal_temp[i][0]) > GMX_REAL_EPS)
3590 warning_note(wi,
3591 "There is a temperature jump when your annealing "
3592 "loops back.\n");
3601 if (ir->bPull)
3603 make_pull_groups(ir->pull, is->pull_grp, defaultIndexGroups, gnames);
3605 make_pull_coords(ir->pull);
3608 if (ir->bRot)
3610 make_rotation_groups(ir->rot, is->rot_grp, defaultIndexGroups, gnames);
3613 if (ir->eSwapCoords != eswapNO)
3615 make_swap_groups(ir->swap, defaultIndexGroups, gnames);
3618 /* Make indices for IMD session */
3619 if (ir->bIMD)
3621 make_IMD_group(ir->imd, is->imd_grp, defaultIndexGroups, gnames);
3624 gmx::IndexGroupsAndNames defaultIndexGroupsAndNames(
3625 *defaultIndexGroups, gmx::arrayRefFromArray(gnames, defaultIndexGroups->nr));
3626 notifier.notifier_.notify(defaultIndexGroupsAndNames);
3628 auto accelerations = gmx::splitString(is->acc);
3629 auto accelerationGroupNames = gmx::splitString(is->accgrps);
3630 if (accelerationGroupNames.size() * DIM != accelerations.size())
3632 gmx_fatal(FARGS, "Invalid Acceleration input: %zu groups and %zu acc. values",
3633 accelerationGroupNames.size(), accelerations.size());
3635 do_numbering(natoms, groups, accelerationGroupNames, defaultIndexGroups, gnames,
3636 SimulationAtomGroupType::Acceleration, restnm, egrptpALL_GENREST, bVerbose, wi);
3637 nr = groups->groups[SimulationAtomGroupType::Acceleration].size();
3638 snew(ir->opts.acc, nr);
3639 ir->opts.ngacc = nr;
3641 convertRvecs(wi, accelerations, "anneal-time", ir->opts.acc);
3643 auto freezeDims = gmx::splitString(is->frdim);
3644 auto freezeGroupNames = gmx::splitString(is->freeze);
3645 if (freezeDims.size() != DIM * freezeGroupNames.size())
3647 gmx_fatal(FARGS, "Invalid Freezing input: %zu groups and %zu freeze values",
3648 freezeGroupNames.size(), freezeDims.size());
3650 do_numbering(natoms, groups, freezeGroupNames, defaultIndexGroups, gnames,
3651 SimulationAtomGroupType::Freeze, restnm, egrptpALL_GENREST, bVerbose, wi);
3652 nr = groups->groups[SimulationAtomGroupType::Freeze].size();
3653 ir->opts.ngfrz = nr;
3654 snew(ir->opts.nFreeze, nr);
3655 for (i = k = 0; (size_t(i) < freezeGroupNames.size()); i++)
3657 for (j = 0; (j < DIM); j++, k++)
3659 ir->opts.nFreeze[i][j] = static_cast<int>(gmx::equalCaseInsensitive(freezeDims[k], "Y", 1));
3660 if (!ir->opts.nFreeze[i][j])
3662 if (!gmx::equalCaseInsensitive(freezeDims[k], "N", 1))
3664 sprintf(warnbuf,
3665 "Please use Y(ES) or N(O) for freezedim only "
3666 "(not %s)",
3667 freezeDims[k].c_str());
3668 warning(wi, warn_buf);
3673 for (; (i < nr); i++)
3675 for (j = 0; (j < DIM); j++)
3677 ir->opts.nFreeze[i][j] = 0;
3681 auto energyGroupNames = gmx::splitString(is->energy);
3682 do_numbering(natoms, groups, energyGroupNames, defaultIndexGroups, gnames,
3683 SimulationAtomGroupType::EnergyOutput, restnm, egrptpALL_GENREST, bVerbose, wi);
3684 add_wall_energrps(groups, ir->nwall, symtab);
3685 ir->opts.ngener = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3686 auto vcmGroupNames = gmx::splitString(is->vcm);
3687 bRest = do_numbering(natoms, groups, vcmGroupNames, defaultIndexGroups, gnames,
3688 SimulationAtomGroupType::MassCenterVelocityRemoval, restnm,
3689 vcmGroupNames.empty() ? egrptpALL_GENREST : egrptpPART, bVerbose, wi);
3690 if (bRest)
3692 warning(wi,
3693 "Some atoms are not part of any center of mass motion removal group.\n"
3694 "This may lead to artifacts.\n"
3695 "In most cases one should use one group for the whole system.");
3698 /* Now we have filled the freeze struct, so we can calculate NRDF */
3699 calc_nrdf(mtop, ir, gnames);
3701 auto user1GroupNames = gmx::splitString(is->user1);
3702 do_numbering(natoms, groups, user1GroupNames, defaultIndexGroups, gnames,
3703 SimulationAtomGroupType::User1, restnm, egrptpALL_GENREST, bVerbose, wi);
3704 auto user2GroupNames = gmx::splitString(is->user2);
3705 do_numbering(natoms, groups, user2GroupNames, defaultIndexGroups, gnames,
3706 SimulationAtomGroupType::User2, restnm, egrptpALL_GENREST, bVerbose, wi);
3707 auto compressedXGroupNames = gmx::splitString(is->x_compressed_groups);
3708 do_numbering(natoms, groups, compressedXGroupNames, defaultIndexGroups, gnames,
3709 SimulationAtomGroupType::CompressedPositionOutput, restnm, egrptpONE, bVerbose, wi);
3710 auto orirefFitGroupNames = gmx::splitString(is->orirefitgrp);
3711 do_numbering(natoms, groups, orirefFitGroupNames, defaultIndexGroups, gnames,
3712 SimulationAtomGroupType::OrientationRestraintsFit, restnm, egrptpALL_GENREST,
3713 bVerbose, wi);
3715 /* QMMM input processing */
3716 auto qmGroupNames = gmx::splitString(is->QMMM);
3717 auto qmMethods = gmx::splitString(is->QMmethod);
3718 auto qmBasisSets = gmx::splitString(is->QMbasis);
3719 if (ir->eI != eiMimic)
3721 if (qmMethods.size() != qmGroupNames.size() || qmBasisSets.size() != qmGroupNames.size())
3723 gmx_fatal(FARGS,
3724 "Invalid QMMM input: %zu groups %zu basissets"
3725 " and %zu methods\n",
3726 qmGroupNames.size(), qmBasisSets.size(), qmMethods.size());
3728 /* group rest, if any, is always MM! */
3729 do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
3730 SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
3731 nr = qmGroupNames.size(); /*atoms->grps[egcQMMM].nr;*/
3732 ir->opts.ngQM = qmGroupNames.size();
3733 snew(ir->opts.QMmethod, nr);
3734 snew(ir->opts.QMbasis, nr);
3735 for (i = 0; i < nr; i++)
3737 /* input consists of strings: RHF CASSCF PM3 .. These need to be
3738 * converted to the corresponding enum in names.c
3740 ir->opts.QMmethod[i] = search_QMstring(qmMethods[i].c_str(), eQMmethodNR, eQMmethod_names);
3741 ir->opts.QMbasis[i] = search_QMstring(qmBasisSets[i].c_str(), eQMbasisNR, eQMbasis_names);
3743 auto qmMultiplicities = gmx::splitString(is->QMmult);
3744 auto qmCharges = gmx::splitString(is->QMcharge);
3745 auto qmbSH = gmx::splitString(is->bSH);
3746 snew(ir->opts.QMmult, nr);
3747 snew(ir->opts.QMcharge, nr);
3748 snew(ir->opts.bSH, nr);
3749 convertInts(wi, qmMultiplicities, "QMmult", ir->opts.QMmult);
3750 convertInts(wi, qmCharges, "QMcharge", ir->opts.QMcharge);
3751 convertYesNos(wi, qmbSH, "bSH", ir->opts.bSH);
3753 auto CASelectrons = gmx::splitString(is->CASelectrons);
3754 auto CASorbitals = gmx::splitString(is->CASorbitals);
3755 snew(ir->opts.CASelectrons, nr);
3756 snew(ir->opts.CASorbitals, nr);
3757 convertInts(wi, CASelectrons, "CASelectrons", ir->opts.CASelectrons);
3758 convertInts(wi, CASorbitals, "CASOrbitals", ir->opts.CASorbitals);
3760 auto SAon = gmx::splitString(is->SAon);
3761 auto SAoff = gmx::splitString(is->SAoff);
3762 auto SAsteps = gmx::splitString(is->SAsteps);
3763 snew(ir->opts.SAon, nr);
3764 snew(ir->opts.SAoff, nr);
3765 snew(ir->opts.SAsteps, nr);
3766 convertInts(wi, SAon, "SAon", ir->opts.SAon);
3767 convertInts(wi, SAoff, "SAoff", ir->opts.SAoff);
3768 convertInts(wi, SAsteps, "SAsteps", ir->opts.SAsteps);
3770 else
3772 /* MiMiC */
3773 if (qmGroupNames.size() > 1)
3775 gmx_fatal(FARGS, "Currently, having more than one QM group in MiMiC is not supported");
3777 /* group rest, if any, is always MM! */
3778 do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
3779 SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
3781 ir->opts.ngQM = qmGroupNames.size();
3784 /* end of QMMM input */
3786 if (bVerbose)
3788 for (auto group : gmx::keysOf(groups->groups))
3790 fprintf(stderr, "%-16s has %zu element(s):", shortName(group), groups->groups[group].size());
3791 for (const auto& entry : groups->groups[group])
3793 fprintf(stderr, " %s", *(groups->groupNames[entry]));
3795 fprintf(stderr, "\n");
3799 nr = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
3800 snew(ir->opts.egp_flags, nr * nr);
3802 bExcl = do_egp_flag(ir, groups, "energygrp-excl", is->egpexcl, EGP_EXCL);
3803 if (bExcl && ir->cutoff_scheme == ecutsVERLET)
3805 warning_error(wi, "Energy group exclusions are currently not supported");
3807 if (bExcl && EEL_FULL(ir->coulombtype))
3809 warning(wi, "Can not exclude the lattice Coulomb energy between energy groups");
3812 bTable = do_egp_flag(ir, groups, "energygrp-table", is->egptable, EGP_TABLE);
3813 if (bTable && !(ir->vdwtype == evdwUSER) && !(ir->coulombtype == eelUSER)
3814 && !(ir->coulombtype == eelPMEUSER) && !(ir->coulombtype == eelPMEUSERSWITCH))
3816 gmx_fatal(FARGS,
3817 "Can only have energy group pair tables in combination with user tables for VdW "
3818 "and/or Coulomb");
3821 /* final check before going out of scope if simulated tempering variables
3822 * need to be set to default values.
3824 if ((ir->expandedvals->nstexpanded < 0) && ir->bSimTemp)
3826 ir->expandedvals->nstexpanded = 2 * static_cast<int>(ir->opts.tau_t[0] / ir->delta_t);
3827 warning(wi, gmx::formatString(
3828 "the value for nstexpanded was not specified for "
3829 " expanded ensemble simulated tempering. It is set to 2*tau_t (%d) "
3830 "by default, but it is recommended to set it to an explicit value!",
3831 ir->expandedvals->nstexpanded));
3833 for (i = 0; (i < defaultIndexGroups->nr); i++)
3835 sfree(gnames[i]);
3837 sfree(gnames);
3838 done_blocka(defaultIndexGroups);
3839 sfree(defaultIndexGroups);
3843 static void check_disre(const gmx_mtop_t* mtop)
3845 if (gmx_mtop_ftype_count(mtop, F_DISRES) > 0)
3847 const gmx_ffparams_t& ffparams = mtop->ffparams;
3848 int ndouble = 0;
3849 int old_label = -1;
3850 for (int i = 0; i < ffparams.numTypes(); i++)
3852 int ftype = ffparams.functype[i];
3853 if (ftype == F_DISRES)
3855 int label = ffparams.iparams[i].disres.label;
3856 if (label == old_label)
3858 fprintf(stderr, "Distance restraint index %d occurs twice\n", label);
3859 ndouble++;
3861 old_label = label;
3864 if (ndouble > 0)
3866 gmx_fatal(FARGS,
3867 "Found %d double distance restraint indices,\n"
3868 "probably the parameters for multiple pairs in one restraint "
3869 "are not identical\n",
3870 ndouble);
3875 static bool absolute_reference(const t_inputrec* ir, const gmx_mtop_t* sys, const bool posres_only, ivec AbsRef)
3877 int d, g, i;
3878 gmx_mtop_ilistloop_t iloop;
3879 int nmol;
3880 const t_iparams* pr;
3882 clear_ivec(AbsRef);
3884 if (!posres_only)
3886 /* Check the COM */
3887 for (d = 0; d < DIM; d++)
3889 AbsRef[d] = (d < ndof_com(ir) ? 0 : 1);
3891 /* Check for freeze groups */
3892 for (g = 0; g < ir->opts.ngfrz; g++)
3894 for (d = 0; d < DIM; d++)
3896 if (ir->opts.nFreeze[g][d] != 0)
3898 AbsRef[d] = 1;
3904 /* Check for position restraints */
3905 iloop = gmx_mtop_ilistloop_init(sys);
3906 while (const InteractionLists* ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
3908 if (nmol > 0 && (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
3910 for (i = 0; i < (*ilist)[F_POSRES].size(); i += 2)
3912 pr = &sys->ffparams.iparams[(*ilist)[F_POSRES].iatoms[i]];
3913 for (d = 0; d < DIM; d++)
3915 if (pr->posres.fcA[d] != 0)
3917 AbsRef[d] = 1;
3921 for (i = 0; i < (*ilist)[F_FBPOSRES].size(); i += 2)
3923 /* Check for flat-bottom posres */
3924 pr = &sys->ffparams.iparams[(*ilist)[F_FBPOSRES].iatoms[i]];
3925 if (pr->fbposres.k != 0)
3927 switch (pr->fbposres.geom)
3929 case efbposresSPHERE: AbsRef[XX] = AbsRef[YY] = AbsRef[ZZ] = 1; break;
3930 case efbposresCYLINDERX: AbsRef[YY] = AbsRef[ZZ] = 1; break;
3931 case efbposresCYLINDERY: AbsRef[XX] = AbsRef[ZZ] = 1; break;
3932 case efbposresCYLINDER:
3933 /* efbposres is a synonym for efbposresCYLINDERZ for backwards compatibility */
3934 case efbposresCYLINDERZ: AbsRef[XX] = AbsRef[YY] = 1; break;
3935 case efbposresX: /* d=XX */
3936 case efbposresY: /* d=YY */
3937 case efbposresZ: /* d=ZZ */
3938 d = pr->fbposres.geom - efbposresX;
3939 AbsRef[d] = 1;
3940 break;
3941 default:
3942 gmx_fatal(FARGS,
3943 " Invalid geometry for flat-bottom position restraint.\n"
3944 "Expected nr between 1 and %d. Found %d\n",
3945 efbposresNR - 1, pr->fbposres.geom);
3952 return (AbsRef[XX] != 0 && AbsRef[YY] != 0 && AbsRef[ZZ] != 0);
3955 static void check_combination_rule_differences(const gmx_mtop_t* mtop,
3956 int state,
3957 bool* bC6ParametersWorkWithGeometricRules,
3958 bool* bC6ParametersWorkWithLBRules,
3959 bool* bLBRulesPossible)
3961 int ntypes, tpi, tpj;
3962 int* typecount;
3963 real tol;
3964 double c6i, c6j, c12i, c12j;
3965 double c6, c6_geometric, c6_LB;
3966 double sigmai, sigmaj, epsi, epsj;
3967 bool bCanDoLBRules, bCanDoGeometricRules;
3968 const char* ptr;
3970 /* A tolerance of 1e-5 seems reasonable for (possibly hand-typed)
3971 * force-field floating point parameters.
3973 tol = 1e-5;
3974 ptr = getenv("GMX_LJCOMB_TOL");
3975 if (ptr != nullptr)
3977 double dbl;
3978 double gmx_unused canary;
3980 if (sscanf(ptr, "%lf%lf", &dbl, &canary) != 1)
3982 gmx_fatal(FARGS,
3983 "Could not parse a single floating-point number from GMX_LJCOMB_TOL (%s)", ptr);
3985 tol = dbl;
3988 *bC6ParametersWorkWithLBRules = TRUE;
3989 *bC6ParametersWorkWithGeometricRules = TRUE;
3990 bCanDoLBRules = TRUE;
3991 ntypes = mtop->ffparams.atnr;
3992 snew(typecount, ntypes);
3993 gmx_mtop_count_atomtypes(mtop, state, typecount);
3994 *bLBRulesPossible = TRUE;
3995 for (tpi = 0; tpi < ntypes; ++tpi)
3997 c6i = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c6;
3998 c12i = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c12;
3999 for (tpj = tpi; tpj < ntypes; ++tpj)
4001 c6j = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c6;
4002 c12j = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c12;
4003 c6 = mtop->ffparams.iparams[ntypes * tpi + tpj].lj.c6;
4004 c6_geometric = std::sqrt(c6i * c6j);
4005 if (!gmx_numzero(c6_geometric))
4007 if (!gmx_numzero(c12i) && !gmx_numzero(c12j))
4009 sigmai = gmx::sixthroot(c12i / c6i);
4010 sigmaj = gmx::sixthroot(c12j / c6j);
4011 epsi = c6i * c6i / (4.0 * c12i);
4012 epsj = c6j * c6j / (4.0 * c12j);
4013 c6_LB = 4.0 * std::sqrt(epsi * epsj) * gmx::power6(0.5 * (sigmai + sigmaj));
4015 else
4017 *bLBRulesPossible = FALSE;
4018 c6_LB = c6_geometric;
4020 bCanDoLBRules = gmx_within_tol(c6_LB, c6, tol);
4023 if (!bCanDoLBRules)
4025 *bC6ParametersWorkWithLBRules = FALSE;
4028 bCanDoGeometricRules = gmx_within_tol(c6_geometric, c6, tol);
4030 if (!bCanDoGeometricRules)
4032 *bC6ParametersWorkWithGeometricRules = FALSE;
4036 sfree(typecount);
4039 static void check_combination_rules(const t_inputrec* ir, const gmx_mtop_t* mtop, warninp_t wi)
4041 bool bLBRulesPossible, bC6ParametersWorkWithGeometricRules, bC6ParametersWorkWithLBRules;
4043 check_combination_rule_differences(mtop, 0, &bC6ParametersWorkWithGeometricRules,
4044 &bC6ParametersWorkWithLBRules, &bLBRulesPossible);
4045 if (ir->ljpme_combination_rule == eljpmeLB)
4047 if (!bC6ParametersWorkWithLBRules || !bLBRulesPossible)
4049 warning(wi,
4050 "You are using arithmetic-geometric combination rules "
4051 "in LJ-PME, but your non-bonded C6 parameters do not "
4052 "follow these rules.");
4055 else
4057 if (!bC6ParametersWorkWithGeometricRules)
4059 if (ir->eDispCorr != edispcNO)
4061 warning_note(wi,
4062 "You are using geometric combination rules in "
4063 "LJ-PME, but your non-bonded C6 parameters do "
4064 "not follow these rules. "
4065 "This will introduce very small errors in the forces and energies in "
4066 "your simulations. Dispersion correction will correct total energy "
4067 "and/or pressure for isotropic systems, but not forces or surface "
4068 "tensions.");
4070 else
4072 warning_note(wi,
4073 "You are using geometric combination rules in "
4074 "LJ-PME, but your non-bonded C6 parameters do "
4075 "not follow these rules. "
4076 "This will introduce very small errors in the forces and energies in "
4077 "your simulations. If your system is homogeneous, consider using "
4078 "dispersion correction "
4079 "for the total energy and pressure.");
4085 void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_t wi)
4087 char err_buf[STRLEN];
4088 int i, m, c, nmol;
4089 bool bCharge, bAcc;
4090 real * mgrp, mt;
4091 rvec acc;
4092 gmx_mtop_atomloop_block_t aloopb;
4093 ivec AbsRef;
4094 char warn_buf[STRLEN];
4096 set_warning_line(wi, mdparin, -1);
4098 if (absolute_reference(ir, sys, false, AbsRef))
4100 warning_note(wi,
4101 "Removing center of mass motion in the presence of position restraints might "
4102 "cause artifacts");
4105 if (ir->cutoff_scheme == ecutsVERLET && ir->verletbuf_tol > 0 && ir->nstlist > 1
4106 && ((EI_MD(ir->eI) || EI_SD(ir->eI)) && (ir->etc == etcVRESCALE || ir->etc == etcBERENDSEN)))
4108 /* Check if a too small Verlet buffer might potentially
4109 * cause more drift than the thermostat can couple off.
4111 /* Temperature error fraction for warning and suggestion */
4112 const real T_error_warn = 0.002;
4113 const real T_error_suggest = 0.001;
4114 /* For safety: 2 DOF per atom (typical with constraints) */
4115 const real nrdf_at = 2;
4116 real T, tau, max_T_error;
4117 int i;
4119 T = 0;
4120 tau = 0;
4121 for (i = 0; i < ir->opts.ngtc; i++)
4123 T = std::max(T, ir->opts.ref_t[i]);
4124 tau = std::max(tau, ir->opts.tau_t[i]);
4126 if (T > 0)
4128 /* This is a worst case estimate of the temperature error,
4129 * assuming perfect buffer estimation and no cancelation
4130 * of errors. The factor 0.5 is because energy distributes
4131 * equally over Ekin and Epot.
4133 max_T_error = 0.5 * tau * ir->verletbuf_tol / (nrdf_at * BOLTZ * T);
4134 if (max_T_error > T_error_warn)
4136 sprintf(warn_buf,
4137 "With a verlet-buffer-tolerance of %g kJ/mol/ps, a reference temperature "
4138 "of %g and a tau_t of %g, your temperature might be off by up to %.1f%%. "
4139 "To ensure the error is below %.1f%%, decrease verlet-buffer-tolerance to "
4140 "%.0e or decrease tau_t.",
4141 ir->verletbuf_tol, T, tau, 100 * max_T_error, 100 * T_error_suggest,
4142 ir->verletbuf_tol * T_error_suggest / max_T_error);
4143 warning(wi, warn_buf);
4148 if (ETC_ANDERSEN(ir->etc))
4150 int i;
4152 for (i = 0; i < ir->opts.ngtc; i++)
4154 sprintf(err_buf,
4155 "all tau_t must currently be equal using Andersen temperature control, "
4156 "violated for group %d",
4158 CHECK(ir->opts.tau_t[0] != ir->opts.tau_t[i]);
4159 sprintf(err_buf,
4160 "all tau_t must be positive using Andersen temperature control, "
4161 "tau_t[%d]=%10.6f",
4162 i, ir->opts.tau_t[i]);
4163 CHECK(ir->opts.tau_t[i] < 0);
4166 if (ir->etc == etcANDERSENMASSIVE && ir->comm_mode != ecmNO)
4168 for (i = 0; i < ir->opts.ngtc; i++)
4170 int nsteps = gmx::roundToInt(ir->opts.tau_t[i] / ir->delta_t);
4171 sprintf(err_buf,
4172 "tau_t/delta_t for group %d for temperature control method %s must be a "
4173 "multiple of nstcomm (%d), as velocities of atoms in coupled groups are "
4174 "randomized every time step. The input tau_t (%8.3f) leads to %d steps per "
4175 "randomization",
4176 i, etcoupl_names[ir->etc], ir->nstcomm, ir->opts.tau_t[i], nsteps);
4177 CHECK(nsteps % ir->nstcomm != 0);
4182 if (EI_DYNAMICS(ir->eI) && !EI_SD(ir->eI) && ir->eI != eiBD && ir->comm_mode == ecmNO
4183 && !(absolute_reference(ir, sys, FALSE, AbsRef) || ir->nsteps <= 10) && !ETC_ANDERSEN(ir->etc))
4185 warning(wi,
4186 "You are not using center of mass motion removal (mdp option comm-mode), numerical "
4187 "rounding errors can lead to build up of kinetic energy of the center of mass");
4190 if (ir->epc == epcPARRINELLORAHMAN && ir->etc == etcNOSEHOOVER)
4192 real tau_t_max = 0;
4193 for (int g = 0; g < ir->opts.ngtc; g++)
4195 tau_t_max = std::max(tau_t_max, ir->opts.tau_t[g]);
4197 if (ir->tau_p < 1.9 * tau_t_max)
4199 std::string message = gmx::formatString(
4200 "With %s T-coupling and %s p-coupling, "
4201 "%s (%g) should be at least twice as large as %s (%g) to avoid resonances",
4202 etcoupl_names[ir->etc], epcoupl_names[ir->epc], "tau-p", ir->tau_p, "tau-t",
4203 tau_t_max);
4204 warning(wi, message.c_str());
4208 /* Check for pressure coupling with absolute position restraints */
4209 if (ir->epc != epcNO && ir->refcoord_scaling == erscNO)
4211 absolute_reference(ir, sys, TRUE, AbsRef);
4213 for (m = 0; m < DIM; m++)
4215 if (AbsRef[m] && norm2(ir->compress[m]) > 0)
4217 warning(wi,
4218 "You are using pressure coupling with absolute position restraints, "
4219 "this will give artifacts. Use the refcoord_scaling option.");
4220 break;
4226 bCharge = FALSE;
4227 aloopb = gmx_mtop_atomloop_block_init(sys);
4228 const t_atom* atom;
4229 while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
4231 if (atom->q != 0 || atom->qB != 0)
4233 bCharge = TRUE;
4237 if (!bCharge)
4239 if (EEL_FULL(ir->coulombtype))
4241 sprintf(err_buf,
4242 "You are using full electrostatics treatment %s for a system without charges.\n"
4243 "This costs a lot of performance for just processing zeros, consider using %s "
4244 "instead.\n",
4245 EELTYPE(ir->coulombtype), EELTYPE(eelCUT));
4246 warning(wi, err_buf);
4249 else
4251 if (ir->coulombtype == eelCUT && ir->rcoulomb > 0)
4253 sprintf(err_buf,
4254 "You are using a plain Coulomb cut-off, which might produce artifacts.\n"
4255 "You might want to consider using %s electrostatics.\n",
4256 EELTYPE(eelPME));
4257 warning_note(wi, err_buf);
4261 /* Check if combination rules used in LJ-PME are the same as in the force field */
4262 if (EVDW_PME(ir->vdwtype))
4264 check_combination_rules(ir, sys, wi);
4267 /* Generalized reaction field */
4268 if (ir->coulombtype == eelGRF_NOTUSED)
4270 warning_error(wi,
4271 "Generalized reaction-field electrostatics is no longer supported. "
4272 "You can use normal reaction-field instead and compute the reaction-field "
4273 "constant by hand.");
4276 bAcc = FALSE;
4277 for (int i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4279 for (m = 0; (m < DIM); m++)
4281 if (fabs(ir->opts.acc[i][m]) > 1e-6)
4283 bAcc = TRUE;
4287 if (bAcc)
4289 clear_rvec(acc);
4290 snew(mgrp, sys->groups.groups[SimulationAtomGroupType::Acceleration].size());
4291 for (const AtomProxy atomP : AtomRange(*sys))
4293 const t_atom& local = atomP.atom();
4294 int i = atomP.globalAtomNumber();
4295 mgrp[getGroupType(sys->groups, SimulationAtomGroupType::Acceleration, i)] += local.m;
4297 mt = 0.0;
4298 for (i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4300 for (m = 0; (m < DIM); m++)
4302 acc[m] += ir->opts.acc[i][m] * mgrp[i];
4304 mt += mgrp[i];
4306 for (m = 0; (m < DIM); m++)
4308 if (fabs(acc[m]) > 1e-6)
4310 const char* dim[DIM] = { "X", "Y", "Z" };
4311 fprintf(stderr, "Net Acceleration in %s direction, will %s be corrected\n", dim[m],
4312 ir->nstcomm != 0 ? "" : "not");
4313 if (ir->nstcomm != 0 && m < ndof_com(ir))
4315 acc[m] /= mt;
4316 for (i = 0;
4317 (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
4319 ir->opts.acc[i][m] -= acc[m];
4324 sfree(mgrp);
4327 if (ir->efep != efepNO && ir->fepvals->sc_alpha != 0
4328 && !gmx_within_tol(sys->ffparams.reppow, 12.0, 10 * GMX_DOUBLE_EPS))
4330 gmx_fatal(FARGS, "Soft-core interactions are only supported with VdW repulsion power 12");
4333 if (ir->bPull)
4335 bool bWarned;
4337 bWarned = FALSE;
4338 for (i = 0; i < ir->pull->ncoord && !bWarned; i++)
4340 if (ir->pull->coord[i].group[0] == 0 || ir->pull->coord[i].group[1] == 0)
4342 absolute_reference(ir, sys, FALSE, AbsRef);
4343 for (m = 0; m < DIM; m++)
4345 if (ir->pull->coord[i].dim[m] && !AbsRef[m])
4347 warning(wi,
4348 "You are using an absolute reference for pulling, but the rest of "
4349 "the system does not have an absolute reference. This will lead to "
4350 "artifacts.");
4351 bWarned = TRUE;
4352 break;
4358 for (i = 0; i < 3; i++)
4360 for (m = 0; m <= i; m++)
4362 if ((ir->epc != epcNO && ir->compress[i][m] != 0) || ir->deform[i][m] != 0)
4364 for (c = 0; c < ir->pull->ncoord; c++)
4366 if (ir->pull->coord[c].eGeom == epullgDIRPBC && ir->pull->coord[c].vec[m] != 0)
4368 gmx_fatal(FARGS,
4369 "Can not have dynamic box while using pull geometry '%s' "
4370 "(dim %c)",
4371 EPULLGEOM(ir->pull->coord[c].eGeom), 'x' + m);
4379 check_disre(sys);
4382 void double_check(t_inputrec* ir, matrix box, bool bHasNormalConstraints, bool bHasAnyConstraints, warninp_t wi)
4384 char warn_buf[STRLEN];
4385 const char* ptr;
4387 ptr = check_box(ir->pbcType, box);
4388 if (ptr)
4390 warning_error(wi, ptr);
4393 if (bHasNormalConstraints && ir->eConstrAlg == econtSHAKE)
4395 if (ir->shake_tol <= 0.0)
4397 sprintf(warn_buf, "ERROR: shake-tol must be > 0 instead of %g\n", ir->shake_tol);
4398 warning_error(wi, warn_buf);
4402 if ((ir->eConstrAlg == econtLINCS) && bHasNormalConstraints)
4404 /* If we have Lincs constraints: */
4405 if (ir->eI == eiMD && ir->etc == etcNO && ir->eConstrAlg == econtLINCS && ir->nLincsIter == 1)
4407 sprintf(warn_buf,
4408 "For energy conservation with LINCS, lincs_iter should be 2 or larger.\n");
4409 warning_note(wi, warn_buf);
4412 if ((ir->eI == eiCG || ir->eI == eiLBFGS) && (ir->nProjOrder < 8))
4414 sprintf(warn_buf,
4415 "For accurate %s with LINCS constraints, lincs-order should be 8 or more.",
4416 ei_names[ir->eI]);
4417 warning_note(wi, warn_buf);
4419 if (ir->epc == epcMTTK)
4421 warning_error(wi, "MTTK not compatible with lincs -- use shake instead.");
4425 if (bHasAnyConstraints && ir->epc == epcMTTK)
4427 warning_error(wi, "Constraints are not implemented with MTTK pressure control.");
4430 if (ir->LincsWarnAngle > 90.0)
4432 sprintf(warn_buf, "lincs-warnangle can not be larger than 90 degrees, setting it to 90.\n");
4433 warning(wi, warn_buf);
4434 ir->LincsWarnAngle = 90.0;
4437 if (ir->pbcType != PbcType::No)
4439 if (ir->nstlist == 0)
4441 warning(wi,
4442 "With nstlist=0 atoms are only put into the box at step 0, therefore drifting "
4443 "atoms might cause the simulation to crash.");
4445 if (gmx::square(ir->rlist) >= max_cutoff2(ir->pbcType, box))
4447 sprintf(warn_buf,
4448 "ERROR: The cut-off length is longer than half the shortest box vector or "
4449 "longer than the smallest box diagonal element. Increase the box size or "
4450 "decrease rlist.\n");
4451 warning_error(wi, warn_buf);