*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017, The GROMACS development team.
+ * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cstdlib>
#include <algorithm>
+#include <memory>
+#include <numeric>
#include <string>
-#include "gromacs/awh/read_params.h"
+#include "gromacs/applied_forces/awh/read_params.h"
#include "gromacs/fileio/readinp.h"
#include "gromacs/fileio/warninp.h"
-#include "gromacs/gmxlib/chargegroup.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxpreprocess/toputil.h"
#include "gromacs/math/functions.h"
#include "gromacs/math/units.h"
+#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/calc_verletbuf.h"
+#include "gromacs/mdlib/vcm.h"
#include "gromacs/mdrun/mdmodules.h"
+#include "gromacs/mdtypes/awh_params.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/multipletimestepping.h"
#include "gromacs/mdtypes/pull_params.h"
#include "gromacs/options/options.h"
#include "gromacs/options/treesupport.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/symtab.h"
#include "gromacs/topology/topology.h"
+#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/keyvaluetreebuilder.h"
#include "gromacs/utility/keyvaluetreemdpwriter.h"
#include "gromacs/utility/keyvaluetreetransform.h"
-#include "gromacs/utility/mdmodulenotification.h"
+#include "gromacs/utility/mdmodulesnotifiers.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/strconvert.h"
#include "gromacs/utility/stringcompare.h"
#include "gromacs/utility/stringutil.h"
#include "gromacs/utility/textwriter.h"
-#define MAXPTR 254
-#define NOGID 255
+#define NOGID 255
+
+using gmx::BasicVector;
/* Resource parameters
* Do not change any of these until you read the instruction
* message.
*/
-typedef struct t_inputrec_strings
+struct gmx_inputrec_strings
{
- char tcgrps[STRLEN], tau_t[STRLEN], ref_t[STRLEN],
- acc[STRLEN], accgrps[STRLEN], freeze[STRLEN], frdim[STRLEN],
- energy[STRLEN], user1[STRLEN], user2[STRLEN], vcm[STRLEN], x_compressed_groups[STRLEN],
- couple_moltype[STRLEN], orirefitgrp[STRLEN], egptable[STRLEN], egpexcl[STRLEN],
- wall_atomtype[STRLEN], wall_density[STRLEN], deform[STRLEN], QMMM[STRLEN],
- imd_grp[STRLEN];
- char fep_lambda[efptNR][STRLEN];
- char lambda_weights[STRLEN];
- char **pull_grp;
- char **rot_grp;
- char anneal[STRLEN], anneal_npoints[STRLEN],
- anneal_time[STRLEN], anneal_temp[STRLEN];
- char QMmethod[STRLEN], QMbasis[STRLEN], QMcharge[STRLEN], QMmult[STRLEN],
- bSH[STRLEN], CASorbitals[STRLEN], CASelectrons[STRLEN], SAon[STRLEN],
- SAoff[STRLEN], SAsteps[STRLEN];
-
-} gmx_inputrec_strings;
-
-static gmx_inputrec_strings *is = nullptr;
+ char tcgrps[STRLEN], tau_t[STRLEN], ref_t[STRLEN], freeze[STRLEN], frdim[STRLEN],
+ energy[STRLEN], user1[STRLEN], user2[STRLEN], vcm[STRLEN], x_compressed_groups[STRLEN],
+ couple_moltype[STRLEN], orirefitgrp[STRLEN], egptable[STRLEN], egpexcl[STRLEN],
+ wall_atomtype[STRLEN], wall_density[STRLEN], deform[STRLEN], QMMM[STRLEN], imd_grp[STRLEN];
+ gmx::EnumerationArray<FreeEnergyPerturbationCouplingType, std::string> fep_lambda;
+ char lambda_weights[STRLEN];
+ std::vector<std::string> pullGroupNames;
+ std::vector<std::string> rotateGroupNames;
+ char anneal[STRLEN], anneal_npoints[STRLEN], anneal_time[STRLEN], anneal_temp[STRLEN];
+};
+
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+static gmx_inputrec_strings* inputrecStrings = nullptr;
void init_inputrec_strings()
{
- if (is)
+ if (inputrecStrings)
{
- gmx_incons("Attempted to call init_inputrec_strings before calling done_inputrec_strings. Only one inputrec (i.e. .mdp file) can be parsed at a time.");
+ gmx_incons(
+ "Attempted to call init_inputrec_strings before calling done_inputrec_strings. "
+ "Only one inputrec (i.e. .mdp file) can be parsed at a time.");
}
- snew(is, 1);
+ inputrecStrings = new gmx_inputrec_strings();
}
void done_inputrec_strings()
{
- sfree(is);
- is = nullptr;
+ delete inputrecStrings;
+ inputrecStrings = nullptr;
}
-enum {
- egrptpALL, /* All particles have to be a member of a group. */
- egrptpALL_GENREST, /* A rest group with name is generated for particles *
- * that are not part of any group. */
- egrptpPART, /* As egrptpALL_GENREST, but no name is generated *
- * for the rest group. */
- egrptpONE /* Merge all selected groups into one group, *
- * make a rest group for the remaining particles. */
+//! How to treat coverage of the whole system for a set of atom groupsx
+enum class GroupCoverage
+{
+ All, //!< All particles have to be a member of a group
+ AllGenerateRest, //<! A rest group with name is generated for particles not part of any group
+ Partial, //<! As \p AllGenerateRest, but no name for the rest group is generated
+ OneGroup //<! Merge all selected groups into one group, make a rest group for the remaining particles
};
-static const char *constraints[eshNR+1] = {
- "none", "h-bonds", "all-bonds", "h-angles", "all-angles", nullptr
-};
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+static const char* constraints[eshNR + 1] = { "none", "h-bonds", "all-bonds",
+ "h-angles", "all-angles", nullptr };
-static const char *couple_lam[ecouplamNR+1] = {
- "vdw-q", "vdw", "q", "none", nullptr
-};
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+static const char* couple_lam[ecouplamNR + 1] = { "vdw-q", "vdw", "q", "none", nullptr };
-static void GetSimTemps(int ntemps, t_simtemp *simtemp, double *temperature_lambdas)
+static void getSimTemps(int ntemps, t_simtemp* simtemp, gmx::ArrayRef<double> temperature_lambdas)
{
int i;
for (i = 0; i < ntemps; i++)
{
/* simple linear scaling -- allows more control */
- if (simtemp->eSimTempScale == esimtempLINEAR)
+ if (simtemp->eSimTempScale == SimulatedTempering::Linear)
{
- simtemp->temperatures[i] = simtemp->simtemp_low + (simtemp->simtemp_high-simtemp->simtemp_low)*temperature_lambdas[i];
+ simtemp->temperatures[i] =
+ simtemp->simtemp_low
+ + (simtemp->simtemp_high - simtemp->simtemp_low) * temperature_lambdas[i];
}
- else if (simtemp->eSimTempScale == esimtempGEOMETRIC) /* should give roughly equal acceptance for constant heat capacity . . . */
+ else if (simtemp->eSimTempScale
+ == SimulatedTempering::Geometric) /* should give roughly equal acceptance for constant heat capacity . . . */
{
- simtemp->temperatures[i] = simtemp->simtemp_low * std::pow(simtemp->simtemp_high/simtemp->simtemp_low, static_cast<real>((1.0*i)/(ntemps-1)));
+ simtemp->temperatures[i] = simtemp->simtemp_low
+ * std::pow(simtemp->simtemp_high / simtemp->simtemp_low,
+ static_cast<real>((1.0 * i) / (ntemps - 1)));
}
- else if (simtemp->eSimTempScale == esimtempEXPONENTIAL)
+ else if (simtemp->eSimTempScale == SimulatedTempering::Exponential)
{
- simtemp->temperatures[i] = simtemp->simtemp_low + (simtemp->simtemp_high-simtemp->simtemp_low)*(std::expm1(temperature_lambdas[i])/std::expm1(1.0));
+ simtemp->temperatures[i] = simtemp->simtemp_low
+ + (simtemp->simtemp_high - simtemp->simtemp_low)
+ * (std::expm1(temperature_lambdas[i]) / std::expm1(1.0));
}
else
{
char errorstr[128];
- sprintf(errorstr, "eSimTempScale=%d not defined", simtemp->eSimTempScale);
+ sprintf(errorstr, "eSimTempScale=%s not defined", enumValueToString(simtemp->eSimTempScale));
gmx_fatal(FARGS, "%s", errorstr);
}
}
}
-
-static void _low_check(bool b, const char *s, warninp_t wi)
+static void _low_check(bool b, const char* s, warninp_t wi)
{
if (b)
{
}
}
-static void check_nst(const char *desc_nst, int nst,
- const char *desc_p, int *p,
- warninp_t wi)
+static void check_nst(const char* desc_nst, int nst, const char* desc_p, int* p, warninp_t wi)
{
char buf[STRLEN];
if (*p > 0 && *p % nst != 0)
{
/* Round up to the next multiple of nst */
- *p = ((*p)/nst + 1)*nst;
- sprintf(buf, "%s should be a multiple of %s, changing %s to %d\n",
- desc_p, desc_nst, desc_p, *p);
+ *p = ((*p) / nst + 1) * nst;
+ sprintf(buf, "%s should be a multiple of %s, changing %s to %d\n", desc_p, desc_nst, desc_p, *p);
warning(wi, buf);
}
}
-static bool ir_NVE(const t_inputrec *ir)
-{
- return (EI_MD(ir->eI) && ir->etc == etcNO);
-}
-
-static int lcd(int n1, int n2)
-{
- int d, i;
-
- d = 1;
- for (i = 2; (i <= n1 && i <= n2); i++)
- {
- if (n1 % i == 0 && n2 % i == 0)
- {
- d = i;
- }
- }
-
- return d;
-}
-
//! Convert legacy mdp entries to modern ones.
-static void process_interaction_modifier(int *eintmod)
+static void process_interaction_modifier(InteractionModifiers* eintmod)
{
- if (*eintmod == eintmodPOTSHIFT_VERLET_UNSUPPORTED)
+ if (*eintmod == InteractionModifiers::PotShiftVerletUnsupported)
{
- *eintmod = eintmodPOTSHIFT;
+ *eintmod = InteractionModifiers::PotShift;
}
}
-void check_ir(const char *mdparin, const gmx::MdModulesNotifier &mdModulesNotifier,
- t_inputrec *ir, t_gromppopts *opts, warninp_t wi)
+void check_ir(const char* mdparin,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ t_inputrec* ir,
+ t_gromppopts* opts,
+ warninp_t wi)
/* Check internal consistency.
* NOTE: index groups are not set here yet, don't check things
* like temperature coupling group options here, but in triple_check
char err_buf[256], warn_buf[STRLEN];
int i, j;
real dt_pcoupl;
- t_lambda *fep = ir->fepvals;
- t_expanded *expand = ir->expandedvals;
+ t_lambda* fep = ir->fepvals.get();
+ t_expanded* expand = ir->expandedvals.get();
set_warning_line(wi, mdparin, -1);
- if (ir->coulombtype == eelRF_NEC_UNSUPPORTED)
+ /* We cannot check MTS requirements with an invalid MTS setup
+ * and we will already have generated errors with an invalid MTS setup.
+ */
+ if (gmx::haveValidMtsSetup(*ir))
{
- sprintf(warn_buf, "%s electrostatics is no longer supported",
- eel_names[eelRF_NEC_UNSUPPORTED]);
- warning_error(wi, warn_buf);
+ std::vector<std::string> errorMessages = gmx::checkMtsRequirements(*ir);
+
+ for (const auto& errorMessage : errorMessages)
+ {
+ warning_error(wi, errorMessage.c_str());
+ }
+ }
+
+ if (ir->coulombtype == CoulombInteractionType::RFNecUnsupported)
+ {
+ std::string message =
+ gmx::formatString("%s electrostatics is no longer supported",
+ enumValueToString(CoulombInteractionType::RFNecUnsupported));
+ warning_error(wi, message);
}
/* BASIC CUT-OFF STUFF */
{
warning_error(wi, "rvdw should be >= 0");
}
- if (ir->rlist < 0 &&
- !(ir->cutoff_scheme == ecutsVERLET && ir->verletbuf_tol > 0))
+ if (ir->rlist < 0 && !(ir->cutoff_scheme == CutoffScheme::Verlet && ir->verletbuf_tol > 0))
{
warning_error(wi, "rlist should be >= 0");
}
- sprintf(err_buf, "nstlist can not be smaller than 0. (If you were trying to use the heuristic neighbour-list update scheme for efficient buffering for improved energy conservation, please use the Verlet cut-off scheme instead.)");
+ sprintf(err_buf,
+ "nstlist can not be smaller than 0. (If you were trying to use the heuristic "
+ "neighbour-list update scheme for efficient buffering for improved energy "
+ "conservation, please use the Verlet cut-off scheme instead.)");
CHECK(ir->nstlist < 0);
process_interaction_modifier(&ir->coulomb_modifier);
process_interaction_modifier(&ir->vdw_modifier);
- if (ir->cutoff_scheme == ecutsGROUP)
+ if (ir->cutoff_scheme == CutoffScheme::Group)
{
gmx_fatal(FARGS,
"The group cutoff scheme has been removed since GROMACS 2020. "
"Please use the Verlet cutoff scheme.");
}
- if (ir->cutoff_scheme == ecutsVERLET)
+ if (ir->cutoff_scheme == CutoffScheme::Verlet)
{
real rc_max;
{
// Since we have PME coulomb + LJ cut-off kernels with rcoulomb>rvdw
// for PME load balancing, we can support this exception.
- bool bUsesPmeTwinRangeKernel = (EEL_PME_EWALD(ir->coulombtype) &&
- ir->vdwtype == evdwCUT &&
- ir->rcoulomb > ir->rvdw);
+ bool bUsesPmeTwinRangeKernel =
+ (EEL_PME_EWALD(ir->coulombtype) && ir->vdwtype == VanDerWaalsType::Cut
+ && ir->rcoulomb > ir->rvdw);
if (!bUsesPmeTwinRangeKernel)
{
- warning_error(wi, "With Verlet lists rcoulomb!=rvdw is not supported (except for rcoulomb>rvdw with PME electrostatics)");
+ warning_error(wi,
+ "With Verlet lists rcoulomb!=rvdw is not supported (except for "
+ "rcoulomb>rvdw with PME electrostatics)");
}
}
- if (ir->vdwtype == evdwSHIFT || ir->vdwtype == evdwSWITCH)
+ if (ir->vdwtype == VanDerWaalsType::Shift || ir->vdwtype == VanDerWaalsType::Switch)
{
- if (ir->vdw_modifier == eintmodNONE ||
- ir->vdw_modifier == eintmodPOTSHIFT)
+ if (ir->vdw_modifier == InteractionModifiers::None
+ || ir->vdw_modifier == InteractionModifiers::PotShift)
{
- ir->vdw_modifier = (ir->vdwtype == evdwSHIFT ? eintmodFORCESWITCH : eintmodPOTSWITCH);
-
- sprintf(warn_buf, "Replacing vdwtype=%s by the equivalent combination of vdwtype=%s and vdw_modifier=%s", evdw_names[ir->vdwtype], evdw_names[evdwCUT], eintmod_names[ir->vdw_modifier]);
+ ir->vdw_modifier =
+ (ir->vdwtype == VanDerWaalsType::Shift ? InteractionModifiers::ForceSwitch
+ : InteractionModifiers::PotSwitch);
+
+ sprintf(warn_buf,
+ "Replacing vdwtype=%s by the equivalent combination of vdwtype=%s and "
+ "vdw_modifier=%s",
+ enumValueToString(ir->vdwtype),
+ enumValueToString(VanDerWaalsType::Cut),
+ enumValueToString(ir->vdw_modifier));
warning_note(wi, warn_buf);
- ir->vdwtype = evdwCUT;
+ ir->vdwtype = VanDerWaalsType::Cut;
}
else
{
- sprintf(warn_buf, "Unsupported combination of vdwtype=%s and vdw_modifier=%s", evdw_names[ir->vdwtype], eintmod_names[ir->vdw_modifier]);
+ sprintf(warn_buf,
+ "Unsupported combination of vdwtype=%s and vdw_modifier=%s",
+ enumValueToString(ir->vdwtype),
+ enumValueToString(ir->vdw_modifier));
warning_error(wi, warn_buf);
}
}
- if (!(ir->vdwtype == evdwCUT || ir->vdwtype == evdwPME))
+ if (!(ir->vdwtype == VanDerWaalsType::Cut || ir->vdwtype == VanDerWaalsType::Pme))
{
- warning_error(wi, "With Verlet lists only cut-off and PME LJ interactions are supported");
+ warning_error(wi,
+ "With Verlet lists only cut-off and PME LJ interactions are supported");
}
- if (!(ir->coulombtype == eelCUT || EEL_RF(ir->coulombtype) ||
- EEL_PME(ir->coulombtype) || ir->coulombtype == eelEWALD))
+ if (!(ir->coulombtype == CoulombInteractionType::Cut || EEL_RF(ir->coulombtype)
+ || EEL_PME(ir->coulombtype) || ir->coulombtype == CoulombInteractionType::Ewald))
{
- warning_error(wi, "With Verlet lists only cut-off, reaction-field, PME and Ewald electrostatics are supported");
+ warning_error(wi,
+ "With Verlet lists only cut-off, reaction-field, PME and Ewald "
+ "electrostatics are supported");
}
- if (!(ir->coulomb_modifier == eintmodNONE ||
- ir->coulomb_modifier == eintmodPOTSHIFT))
+ if (!(ir->coulomb_modifier == InteractionModifiers::None
+ || ir->coulomb_modifier == InteractionModifiers::PotShift))
{
- sprintf(warn_buf, "coulomb_modifier=%s is not supported", eintmod_names[ir->coulomb_modifier]);
+ sprintf(warn_buf, "coulomb_modifier=%s is not supported", enumValueToString(ir->coulomb_modifier));
warning_error(wi, warn_buf);
}
if (EEL_USER(ir->coulombtype))
{
- sprintf(warn_buf, "Coulomb type %s is not supported with the verlet scheme", eel_names[ir->coulombtype]);
+ sprintf(warn_buf,
+ "Coulomb type %s is not supported with the verlet scheme",
+ enumValueToString(ir->coulombtype));
warning_error(wi, warn_buf);
}
if (ir->nstlist < 10)
{
- warning_note(wi, "With Verlet lists the optimal nstlist is >= 10, with GPUs >= 20. Note that with the Verlet scheme, nstlist has no effect on the accuracy of your simulation.");
+ warning_note(wi,
+ "With Verlet lists the optimal nstlist is >= 10, with GPUs >= 20. Note "
+ "that with the Verlet scheme, nstlist has no effect on the accuracy of "
+ "your simulation.");
}
rc_max = std::max(ir->rvdw, ir->rcoulomb);
if (ir->rlist < rc_max)
{
- warning_error(wi, "With verlet lists rlist can not be smaller than rvdw or rcoulomb");
+ warning_error(wi,
+ "With verlet lists rlist can not be smaller than rvdw or rcoulomb");
}
if (ir->rlist == rc_max && ir->nstlist > 1)
{
- warning_note(wi, "rlist is equal to rvdw and/or rcoulomb: there is no explicit Verlet buffer. The cluster pair list does have a buffering effect, but choosing a larger rlist might be necessary for good energy conservation.");
+ warning_note(
+ wi,
+ "rlist is equal to rvdw and/or rcoulomb: there is no explicit Verlet "
+ "buffer. The cluster pair list does have a buffering effect, but choosing "
+ "a larger rlist might be necessary for good energy conservation.");
}
}
else
{
if (ir->rlist > rc_max)
{
- warning_note(wi, "You have set rlist larger than the interaction cut-off, but you also have verlet-buffer-tolerance > 0. Will set rlist using verlet-buffer-tolerance.");
+ warning_note(wi,
+ "You have set rlist larger than the interaction cut-off, but you also "
+ "have verlet-buffer-tolerance > 0. Will set rlist using "
+ "verlet-buffer-tolerance.");
}
if (ir->nstlist == 1)
{
if (inputrec2nboundeddim(ir) < 3)
{
- warning_error(wi, "The box volume is required for calculating rlist from the energy drift with verlet-buffer-tolerance > 0. You are using at least one unbounded dimension, so no volume can be computed. Either use a finite box, or set rlist yourself together with verlet-buffer-tolerance = -1.");
+ warning_error(wi,
+ "The box volume is required for calculating rlist from the "
+ "energy drift with verlet-buffer-tolerance > 0. You are "
+ "using at least one unbounded dimension, so no volume can be "
+ "computed. Either use a finite box, or set rlist yourself "
+ "together with verlet-buffer-tolerance = -1.");
}
/* Set rlist temporarily so we can continue processing */
ir->rlist = rc_max;
else
{
/* Set the buffer to 5% of the cut-off */
- ir->rlist = (1.0 + verlet_buffer_ratio_nodynamics)*rc_max;
+ ir->rlist = (1.0 + verlet_buffer_ratio_nodynamics) * rc_max;
}
}
}
/* GENERAL INTEGRATOR STUFF */
if (!EI_MD(ir->eI))
{
- if (ir->etc != etcNO)
+ if (ir->etc != TemperatureCoupling::No)
{
if (EI_RANDOM(ir->eI))
{
- sprintf(warn_buf, "Setting tcoupl from '%s' to 'no'. %s handles temperature coupling implicitly. See the documentation for more information on which parameters affect temperature for %s.", etcoupl_names[ir->etc], ei_names[ir->eI], ei_names[ir->eI]);
+ sprintf(warn_buf,
+ "Setting tcoupl from '%s' to 'no'. %s handles temperature coupling "
+ "implicitly. See the documentation for more information on which "
+ "parameters affect temperature for %s.",
+ enumValueToString(ir->etc),
+ enumValueToString(ir->eI),
+ enumValueToString(ir->eI));
}
else
{
- sprintf(warn_buf, "Setting tcoupl from '%s' to 'no'. Temperature coupling does not apply to %s.", etcoupl_names[ir->etc], ei_names[ir->eI]);
+ sprintf(warn_buf,
+ "Setting tcoupl from '%s' to 'no'. Temperature coupling does not apply to "
+ "%s.",
+ enumValueToString(ir->etc),
+ enumValueToString(ir->eI));
}
warning_note(wi, warn_buf);
}
- ir->etc = etcNO;
+ ir->etc = TemperatureCoupling::No;
}
- if (ir->eI == eiVVAK)
+ if (ir->eI == IntegrationAlgorithm::VVAK)
{
- sprintf(warn_buf, "Integrator method %s is implemented primarily for validation purposes; for molecular dynamics, you should probably be using %s or %s", ei_names[eiVVAK], ei_names[eiMD], ei_names[eiVV]);
+ sprintf(warn_buf,
+ "Integrator method %s is implemented primarily for validation purposes; for "
+ "molecular dynamics, you should probably be using %s or %s",
+ enumValueToString(IntegrationAlgorithm::VVAK),
+ enumValueToString(IntegrationAlgorithm::MD),
+ enumValueToString(IntegrationAlgorithm::VV));
warning_note(wi, warn_buf);
}
if (!EI_DYNAMICS(ir->eI))
{
- if (ir->epc != epcNO)
+ if (ir->epc != PressureCoupling::No)
{
- sprintf(warn_buf, "Setting pcoupl from '%s' to 'no'. Pressure coupling does not apply to %s.", epcoupl_names[ir->epc], ei_names[ir->eI]);
+ sprintf(warn_buf,
+ "Setting pcoupl from '%s' to 'no'. Pressure coupling does not apply to %s.",
+ enumValueToString(ir->epc),
+ enumValueToString(ir->eI));
warning_note(wi, warn_buf);
}
- ir->epc = epcNO;
+ ir->epc = PressureCoupling::No;
}
if (EI_DYNAMICS(ir->eI))
{
*/
if (ir->nstlist > 0)
{
- ir->nstcalcenergy = lcd(ir->nstenergy, ir->nstlist);
+ ir->nstcalcenergy = std::gcd(ir->nstenergy, ir->nstlist);
}
else
{
}
}
}
- else if ( (ir->nstenergy > 0 && ir->nstcalcenergy > ir->nstenergy) ||
- (ir->efep != efepNO && ir->fepvals->nstdhdl > 0 &&
- (ir->nstcalcenergy > ir->fepvals->nstdhdl) ) )
+ else if ((ir->nstenergy > 0 && ir->nstcalcenergy > ir->nstenergy)
+ || (ir->efep != FreeEnergyPerturbationType::No && ir->fepvals->nstdhdl > 0
+ && (ir->nstcalcenergy > ir->fepvals->nstdhdl)))
{
- const char *nsten = "nstenergy";
- const char *nstdh = "nstdhdl";
- const char *min_name = nsten;
+ const char* nsten = "nstenergy";
+ const char* nstdh = "nstdhdl";
+ const char* min_name = nsten;
int min_nst = ir->nstenergy;
/* find the smallest of ( nstenergy, nstdhdl ) */
- if (ir->efep != efepNO && ir->fepvals->nstdhdl > 0 &&
- (ir->nstenergy == 0 || ir->fepvals->nstdhdl < ir->nstenergy))
+ if (ir->efep != FreeEnergyPerturbationType::No && ir->fepvals->nstdhdl > 0
+ && (ir->nstenergy == 0 || ir->fepvals->nstdhdl < ir->nstenergy))
{
min_nst = ir->fepvals->nstdhdl;
min_name = nstdh;
}
/* If the user sets nstenergy small, we should respect that */
- sprintf(warn_buf,
- "Setting nstcalcenergy (%d) equal to %s (%d)",
- ir->nstcalcenergy, min_name, min_nst);
+ sprintf(warn_buf, "Setting nstcalcenergy (%d) equal to %s (%d)", ir->nstcalcenergy, min_name, min_nst);
warning_note(wi, warn_buf);
ir->nstcalcenergy = min_nst;
}
- if (ir->epc != epcNO)
+ if (ir->epc != PressureCoupling::No)
{
if (ir->nstpcouple < 0)
{
ir->nstpcouple = ir_optimal_nstpcouple(ir);
}
+ if (ir->useMts && ir->nstpcouple % ir->mtsLevels.back().stepFactor != 0)
+ {
+ warning_error(wi,
+ "With multiple time stepping, nstpcouple should be a mutiple of "
+ "mts-factor");
+ }
}
if (ir->nstcalcenergy > 0)
{
- if (ir->efep != efepNO)
+ if (ir->efep != FreeEnergyPerturbationType::No)
{
/* nstdhdl should be a multiple of nstcalcenergy */
- check_nst("nstcalcenergy", ir->nstcalcenergy,
- "nstdhdl", &ir->fepvals->nstdhdl, wi);
+ check_nst("nstcalcenergy", ir->nstcalcenergy, "nstdhdl", &ir->fepvals->nstdhdl, wi);
}
if (ir->bExpanded)
{
/* nstexpanded should be a multiple of nstcalcenergy */
- check_nst("nstcalcenergy", ir->nstcalcenergy,
- "nstexpanded", &ir->expandedvals->nstexpanded, wi);
+ check_nst("nstcalcenergy", ir->nstcalcenergy, "nstexpanded", &ir->expandedvals->nstexpanded, wi);
}
/* for storing exact averages nstenergy should be
* a multiple of nstcalcenergy
*/
- check_nst("nstcalcenergy", ir->nstcalcenergy,
- "nstenergy", &ir->nstenergy, wi);
+ check_nst("nstcalcenergy", ir->nstcalcenergy, "nstenergy", &ir->nstenergy, wi);
}
- // Inquire all MdModules, if their parameters match with the energy
+ // Inquire all MDModules, if their parameters match with the energy
// calculation frequency
gmx::EnergyCalculationFrequencyErrors energyCalculationFrequencyErrors(ir->nstcalcenergy);
- mdModulesNotifier.notifier_.notify(&energyCalculationFrequencyErrors);
+ mdModulesNotifiers.preProcessingNotifier_.notify(&energyCalculationFrequencyErrors);
// Emit all errors from the energy calculation frequency checks
- for (const std::string &energyFrequencyErrorMessage : energyCalculationFrequencyErrors.errorMessages())
+ for (const std::string& energyFrequencyErrorMessage :
+ energyCalculationFrequencyErrors.errorMessages())
{
warning_error(wi, energyFrequencyErrorMessage);
}
if (ir->nsteps == 0 && !ir->bContinuation)
{
- warning_note(wi, "For a correct single-point energy evaluation with nsteps = 0, use continuation = yes to avoid constraining the input coordinates.");
+ warning_note(wi,
+ "For a correct single-point energy evaluation with nsteps = 0, use "
+ "continuation = yes to avoid constraining the input coordinates.");
}
/* LD STUFF */
- if ((EI_SD(ir->eI) || ir->eI == eiBD) &&
- ir->bContinuation && ir->ld_seed != -1)
+ if ((EI_SD(ir->eI) || ir->eI == IntegrationAlgorithm::BD) && ir->bContinuation && ir->ld_seed != -1)
{
- warning_note(wi, "You are doing a continuation with SD or BD, make sure that ld_seed is different from the previous run (using ld_seed=-1 will ensure this)");
+ warning_note(wi,
+ "You are doing a continuation with SD or BD, make sure that ld_seed is "
+ "different from the previous run (using ld_seed=-1 will ensure this)");
}
/* TPI STUFF */
if (EI_TPI(ir->eI))
{
- sprintf(err_buf, "TPI only works with pbc = %s", epbc_names[epbcXYZ]);
- CHECK(ir->ePBC != epbcXYZ);
+ sprintf(err_buf, "TPI only works with pbc = %s", c_pbcTypeNames[PbcType::Xyz].c_str());
+ CHECK(ir->pbcType != PbcType::Xyz);
sprintf(err_buf, "with TPI nstlist should be larger than zero");
CHECK(ir->nstlist <= 0);
sprintf(err_buf, "TPI does not work with full electrostatics other than PME");
}
/* SHAKE / LINCS */
- if ( (opts->nshake > 0) && (opts->bMorse) )
+ if ((opts->nshake > 0) && (opts->bMorse))
{
- sprintf(warn_buf,
- "Using morse bond-potentials while constraining bonds is useless");
+ sprintf(warn_buf, "Using morse bond-potentials while constraining bonds is useless");
warning(wi, warn_buf);
}
- if ((EI_SD(ir->eI) || ir->eI == eiBD) &&
- ir->bContinuation && ir->ld_seed != -1)
+ if ((EI_SD(ir->eI) || ir->eI == IntegrationAlgorithm::BD) && ir->bContinuation && ir->ld_seed != -1)
{
- warning_note(wi, "You are doing a continuation with SD or BD, make sure that ld_seed is different from the previous run (using ld_seed=-1 will ensure this)");
+ warning_note(wi,
+ "You are doing a continuation with SD or BD, make sure that ld_seed is "
+ "different from the previous run (using ld_seed=-1 will ensure this)");
}
/* verify simulated tempering options */
bool bAllTempZero = TRUE;
for (i = 0; i < fep->n_lambda; i++)
{
- sprintf(err_buf, "Entry %d for %s must be between 0 and 1, instead is %g", i, efpt_names[efptTEMPERATURE], fep->all_lambda[efptTEMPERATURE][i]);
- CHECK((fep->all_lambda[efptTEMPERATURE][i] < 0) || (fep->all_lambda[efptTEMPERATURE][i] > 1));
- if (fep->all_lambda[efptTEMPERATURE][i] > 0)
+ sprintf(err_buf,
+ "Entry %d for %s must be between 0 and 1, instead is %g",
+ i,
+ enumValueToString(FreeEnergyPerturbationCouplingType::Temperature),
+ fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Temperature)][i]);
+ CHECK((fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Temperature)][i] < 0)
+ || (fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Temperature)][i]
+ > 1));
+ if (fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Temperature)][i] > 0)
{
bAllTempZero = FALSE;
}
CHECK(bAllTempZero == TRUE);
sprintf(err_buf, "Simulated tempering is currently only compatible with md-vv");
- CHECK(ir->eI != eiVV);
+ CHECK(ir->eI != IntegrationAlgorithm::VV);
/* check compatability of the temperature coupling with simulated tempering */
- if (ir->etc == etcNOSEHOOVER)
+ if (ir->etc == TemperatureCoupling::NoseHoover)
{
- sprintf(warn_buf, "Nose-Hoover based temperature control such as [%s] my not be entirelyconsistent with simulated tempering", etcoupl_names[ir->etc]);
+ sprintf(warn_buf,
+ "Nose-Hoover based temperature control such as [%s] my not be "
+ "entirelyconsistent with simulated tempering",
+ enumValueToString(ir->etc));
warning_note(wi, warn_buf);
}
/* check that the temperatures make sense */
- sprintf(err_buf, "Higher simulated tempering temperature (%g) must be >= than the simulated tempering lower temperature (%g)", ir->simtempvals->simtemp_high, ir->simtempvals->simtemp_low);
+ sprintf(err_buf,
+ "Higher simulated tempering temperature (%g) must be >= than the simulated "
+ "tempering lower temperature (%g)",
+ ir->simtempvals->simtemp_high,
+ ir->simtempvals->simtemp_low);
CHECK(ir->simtempvals->simtemp_high <= ir->simtempvals->simtemp_low);
- sprintf(err_buf, "Higher simulated tempering temperature (%g) must be >= zero", ir->simtempvals->simtemp_high);
+ sprintf(err_buf,
+ "Higher simulated tempering temperature (%g) must be >= zero",
+ ir->simtempvals->simtemp_high);
CHECK(ir->simtempvals->simtemp_high <= 0);
- sprintf(err_buf, "Lower simulated tempering temperature (%g) must be >= zero", ir->simtempvals->simtemp_low);
+ sprintf(err_buf,
+ "Lower simulated tempering temperature (%g) must be >= zero",
+ ir->simtempvals->simtemp_low);
CHECK(ir->simtempvals->simtemp_low <= 0);
}
/* verify free energy options */
- if (ir->efep != efepNO)
+ if (ir->efep != FreeEnergyPerturbationType::No)
{
- fep = ir->fepvals;
- sprintf(err_buf, "The soft-core power is %d and can only be 1 or 2",
- fep->sc_power);
+ fep = ir->fepvals.get();
+ sprintf(err_buf, "The soft-core power is %d and can only be 1 or 2", fep->sc_power);
CHECK(fep->sc_alpha != 0 && fep->sc_power != 1 && fep->sc_power != 2);
- sprintf(err_buf, "The soft-core sc-r-power is %d and can only be 6 or 48",
+ sprintf(err_buf,
+ "The soft-core sc-r-power is %d and can only be 6. (sc-r-power 48 is no longer "
+ "supported.)",
static_cast<int>(fep->sc_r_power));
- CHECK(fep->sc_alpha != 0 && fep->sc_r_power != 6.0 && fep->sc_r_power != 48.0);
+ CHECK(fep->sc_alpha != 0 && fep->sc_r_power != 6.0);
- sprintf(err_buf, "Can't use positive delta-lambda (%g) if initial state/lambda does not start at zero", fep->delta_lambda);
- CHECK(fep->delta_lambda > 0 && ((fep->init_fep_state > 0) || (fep->init_lambda > 0)));
+ sprintf(err_buf,
+ "Can't use positive delta-lambda (%g) if initial state/lambda does not start at "
+ "zero",
+ fep->delta_lambda);
+ CHECK(fep->delta_lambda > 0 && ((fep->init_fep_state > 0) || (fep->init_lambda > 0)));
- sprintf(err_buf, "Can't use positive delta-lambda (%g) with expanded ensemble simulations", fep->delta_lambda);
- CHECK(fep->delta_lambda > 0 && (ir->efep == efepEXPANDED));
+ sprintf(err_buf,
+ "Can't use positive delta-lambda (%g) with expanded ensemble simulations",
+ fep->delta_lambda);
+ CHECK(fep->delta_lambda > 0 && (ir->efep == FreeEnergyPerturbationType::Expanded));
sprintf(err_buf, "Can only use expanded ensemble with md-vv (for now)");
- CHECK(!(EI_VV(ir->eI)) && (ir->efep == efepEXPANDED));
+ CHECK(!(EI_VV(ir->eI)) && (ir->efep == FreeEnergyPerturbationType::Expanded));
sprintf(err_buf, "Free-energy not implemented for Ewald");
- CHECK(ir->coulombtype == eelEWALD);
+ CHECK(ir->coulombtype == CoulombInteractionType::Ewald);
/* check validty of lambda inputs */
if (fep->n_lambda == 0)
}
else
{
- sprintf(err_buf, "initial thermodynamic state %d does not exist, only goes to %d", fep->init_fep_state, fep->n_lambda-1);
+ sprintf(err_buf,
+ "initial thermodynamic state %d does not exist, only goes to %d",
+ fep->init_fep_state,
+ fep->n_lambda - 1);
CHECK((fep->init_fep_state >= fep->n_lambda));
}
- sprintf(err_buf, "Lambda state must be set, either with init-lambda-state or with init-lambda");
+ sprintf(err_buf,
+ "Lambda state must be set, either with init-lambda-state or with init-lambda");
CHECK((fep->init_fep_state < 0) && (fep->init_lambda < 0));
- sprintf(err_buf, "init-lambda=%g while init-lambda-state=%d. Lambda state must be set either with init-lambda-state or with init-lambda, but not both",
- fep->init_lambda, fep->init_fep_state);
+ sprintf(err_buf,
+ "init-lambda=%g while init-lambda-state=%d. Lambda state must be set either with "
+ "init-lambda-state or with init-lambda, but not both",
+ fep->init_lambda,
+ fep->init_fep_state);
CHECK((fep->init_fep_state >= 0) && (fep->init_lambda >= 0));
-
if ((fep->init_lambda >= 0) && (fep->delta_lambda == 0))
{
int n_lambda_terms;
n_lambda_terms = 0;
- for (i = 0; i < efptNR; i++)
+ for (i = 0; i < static_cast<int>(FreeEnergyPerturbationCouplingType::Count); i++)
{
if (fep->separate_dvdl[i])
{
}
if (n_lambda_terms > 1)
{
- sprintf(warn_buf, "If lambda vector states (fep-lambdas, coul-lambdas etc.) are set, don't use init-lambda to set lambda state (except for slow growth). Use init-lambda-state instead.");
+ sprintf(warn_buf,
+ "If lambda vector states (fep-lambdas, coul-lambdas etc.) are set, don't "
+ "use init-lambda to set lambda state (except for slow growth). Use "
+ "init-lambda-state instead.");
warning(wi, warn_buf);
}
if (n_lambda_terms < 2 && fep->n_lambda > 0)
{
warning_note(wi,
- "init-lambda is deprecated for setting lambda state (except for slow growth). Use init-lambda-state instead.");
+ "init-lambda is deprecated for setting lambda state (except for slow "
+ "growth). Use init-lambda-state instead.");
}
}
- for (j = 0; j < efptNR; j++)
+ for (j = 0; j < static_cast<int>(FreeEnergyPerturbationCouplingType::Count); j++)
{
for (i = 0; i < fep->n_lambda; i++)
{
- sprintf(err_buf, "Entry %d for %s must be between 0 and 1, instead is %g", i, efpt_names[j], fep->all_lambda[j][i]);
+ auto enumValue = static_cast<FreeEnergyPerturbationCouplingType>(j);
+ sprintf(err_buf,
+ "Entry %d for %s must be between 0 and 1, instead is %g",
+ i,
+ enumValueToString(enumValue),
+ fep->all_lambda[j][i]);
CHECK((fep->all_lambda[j][i] < 0) || (fep->all_lambda[j][i] > 1));
}
}
{
for (i = 0; i < fep->n_lambda; i++)
{
- sprintf(err_buf, "For state %d, vdw-lambdas (%f) is changing with vdw softcore, while coul-lambdas (%f) is nonzero without coulomb softcore: this will lead to crashes, and is not supported.", i, fep->all_lambda[efptVDW][i],
- fep->all_lambda[efptCOUL][i]);
- CHECK((fep->sc_alpha > 0) &&
- (((fep->all_lambda[efptCOUL][i] > 0.0) &&
- (fep->all_lambda[efptCOUL][i] < 1.0)) &&
- ((fep->all_lambda[efptVDW][i] > 0.0) &&
- (fep->all_lambda[efptVDW][i] < 1.0))));
+ sprintf(err_buf,
+ "For state %d, vdw-lambdas (%f) is changing with vdw softcore, while "
+ "coul-lambdas (%f) is nonzero without coulomb softcore: this will lead to "
+ "crashes, and is not supported.",
+ i,
+ fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Vdw)][i],
+ fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Coul)][i]);
+ CHECK((fep->sc_alpha > 0)
+ && (((fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Coul)][i] > 0.0)
+ && (fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Coul)][i] < 1.0))
+ && ((fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Vdw)][i] > 0.0)
+ && (fep->all_lambda[static_cast<int>(FreeEnergyPerturbationCouplingType::Vdw)][i]
+ < 1.0))));
}
}
{
real sigma, lambda, r_sc;
- sigma = 0.34;
+ sigma = 0.34;
/* Maximum estimate for A and B charges equal with lambda power 1 */
lambda = 0.5;
- r_sc = std::pow(lambda*fep->sc_alpha*std::pow(sigma/ir->rcoulomb, fep->sc_r_power) + 1.0, 1.0/fep->sc_r_power);
- sprintf(warn_buf, "With PME there is a minor soft core effect present at the cut-off, proportional to (LJsigma/rcoulomb)^%g. This could have a minor effect on energy conservation, but usually other effects dominate. With a common sigma value of %g nm the fraction of the particle-particle potential at the cut-off at lambda=%g is around %.1e, while ewald-rtol is %.1e.",
+ r_sc = std::pow(lambda * fep->sc_alpha * std::pow(sigma / ir->rcoulomb, fep->sc_r_power) + 1.0,
+ 1.0 / fep->sc_r_power);
+ sprintf(warn_buf,
+ "With PME there is a minor soft core effect present at the cut-off, "
+ "proportional to (LJsigma/rcoulomb)^%g. This could have a minor effect on "
+ "energy conservation, but usually other effects dominate. With a common sigma "
+ "value of %g nm the fraction of the particle-particle potential at the cut-off "
+ "at lambda=%g is around %.1e, while ewald-rtol is %.1e.",
fep->sc_r_power,
- sigma, lambda, r_sc - 1.0, ir->ewald_rtol);
+ sigma,
+ lambda,
+ r_sc - 1.0,
+ ir->ewald_rtol);
warning_note(wi, warn_buf);
}
/* Free Energy Checks -- In an ideal world, slow growth and FEP would
be treated differently, but that's the next step */
- for (i = 0; i < efptNR; i++)
+ for (i = 0; i < static_cast<int>(FreeEnergyPerturbationCouplingType::Count); i++)
{
+ auto enumValue = static_cast<FreeEnergyPerturbationCouplingType>(i);
for (j = 0; j < fep->n_lambda; j++)
{
- sprintf(err_buf, "%s[%d] must be between 0 and 1", efpt_names[i], j);
+ sprintf(err_buf, "%s[%d] must be between 0 and 1", enumValueToString(enumValue), j);
CHECK((fep->all_lambda[i][j] < 0) || (fep->all_lambda[i][j] > 1));
}
}
+
+ if (fep->softcoreFunction == SoftcoreType::Gapsys)
+ {
+ if (fep->scGapsysScaleLinpointQ < 0.0)
+ {
+ sprintf(warn_buf,
+ "sc_scale_linpoint_Q_gapsys is equal %g but must be >= 0",
+ fep->scGapsysScaleLinpointQ);
+ warning_note(wi, warn_buf);
+ }
+
+ if ((fep->scGapsysScaleLinpointLJ < 0.0) || (fep->scGapsysScaleLinpointLJ >= 1.0))
+ {
+ sprintf(warn_buf,
+ "sc_scale_linpoint_LJ_gapsys is equal %g but must be in [0,1) when used "
+ "with "
+ "sc_function=gapsys.",
+ fep->scGapsysScaleLinpointLJ);
+ warning_note(wi, warn_buf);
+ }
+ }
}
- if ((ir->bSimTemp) || (ir->efep == efepEXPANDED))
+ if ((ir->bSimTemp) || (ir->efep == FreeEnergyPerturbationType::Expanded))
{
- fep = ir->fepvals;
+ fep = ir->fepvals.get();
/* checking equilibration of weights inputs for validity */
- sprintf(err_buf, "weight-equil-number-all-lambda (%d) is ignored if lmc-weights-equil is not equal to %s",
- expand->equil_n_at_lam, elmceq_names[elmceqNUMATLAM]);
- CHECK((expand->equil_n_at_lam > 0) && (expand->elmceq != elmceqNUMATLAM));
+ sprintf(err_buf,
+ "weight-equil-number-all-lambda (%d) is ignored if lmc-weights-equil is not equal "
+ "to %s",
+ expand->equil_n_at_lam,
+ enumValueToString(LambdaWeightWillReachEquilibrium::NumAtLambda));
+ CHECK((expand->equil_n_at_lam > 0)
+ && (expand->elmceq != LambdaWeightWillReachEquilibrium::NumAtLambda));
- sprintf(err_buf, "weight-equil-number-samples (%d) is ignored if lmc-weights-equil is not equal to %s",
- expand->equil_samples, elmceq_names[elmceqSAMPLES]);
- CHECK((expand->equil_samples > 0) && (expand->elmceq != elmceqSAMPLES));
+ sprintf(err_buf,
+ "weight-equil-number-samples (%d) is ignored if lmc-weights-equil is not equal to "
+ "%s",
+ expand->equil_samples,
+ enumValueToString(LambdaWeightWillReachEquilibrium::Samples));
+ CHECK((expand->equil_samples > 0) && (expand->elmceq != LambdaWeightWillReachEquilibrium::Samples));
- sprintf(err_buf, "weight-equil-number-steps (%d) is ignored if lmc-weights-equil is not equal to %s",
- expand->equil_steps, elmceq_names[elmceqSTEPS]);
- CHECK((expand->equil_steps > 0) && (expand->elmceq != elmceqSTEPS));
+ sprintf(err_buf,
+ "weight-equil-number-steps (%d) is ignored if lmc-weights-equil is not equal to %s",
+ expand->equil_steps,
+ enumValueToString(LambdaWeightWillReachEquilibrium::Steps));
+ CHECK((expand->equil_steps > 0) && (expand->elmceq != LambdaWeightWillReachEquilibrium::Steps));
- sprintf(err_buf, "weight-equil-wl-delta (%d) is ignored if lmc-weights-equil is not equal to %s",
- expand->equil_samples, elmceq_names[elmceqWLDELTA]);
- CHECK((expand->equil_wl_delta > 0) && (expand->elmceq != elmceqWLDELTA));
+ sprintf(err_buf,
+ "weight-equil-wl-delta (%d) is ignored if lmc-weights-equil is not equal to %s",
+ expand->equil_samples,
+ enumValueToString(LambdaWeightWillReachEquilibrium::WLDelta));
+ CHECK((expand->equil_wl_delta > 0) && (expand->elmceq != LambdaWeightWillReachEquilibrium::WLDelta));
- sprintf(err_buf, "weight-equil-count-ratio (%f) is ignored if lmc-weights-equil is not equal to %s",
- expand->equil_ratio, elmceq_names[elmceqRATIO]);
- CHECK((expand->equil_ratio > 0) && (expand->elmceq != elmceqRATIO));
+ sprintf(err_buf,
+ "weight-equil-count-ratio (%f) is ignored if lmc-weights-equil is not equal to %s",
+ expand->equil_ratio,
+ enumValueToString(LambdaWeightWillReachEquilibrium::Ratio));
+ CHECK((expand->equil_ratio > 0) && (expand->elmceq != LambdaWeightWillReachEquilibrium::Ratio));
- sprintf(err_buf, "weight-equil-number-all-lambda (%d) must be a positive integer if lmc-weights-equil=%s",
- expand->equil_n_at_lam, elmceq_names[elmceqNUMATLAM]);
- CHECK((expand->equil_n_at_lam <= 0) && (expand->elmceq == elmceqNUMATLAM));
+ sprintf(err_buf,
+ "weight-equil-number-all-lambda (%d) must be a positive integer if "
+ "lmc-weights-equil=%s",
+ expand->equil_n_at_lam,
+ enumValueToString(LambdaWeightWillReachEquilibrium::NumAtLambda));
+ CHECK((expand->equil_n_at_lam <= 0)
+ && (expand->elmceq == LambdaWeightWillReachEquilibrium::NumAtLambda));
- sprintf(err_buf, "weight-equil-number-samples (%d) must be a positive integer if lmc-weights-equil=%s",
- expand->equil_samples, elmceq_names[elmceqSAMPLES]);
- CHECK((expand->equil_samples <= 0) && (expand->elmceq == elmceqSAMPLES));
+ sprintf(err_buf,
+ "weight-equil-number-samples (%d) must be a positive integer if "
+ "lmc-weights-equil=%s",
+ expand->equil_samples,
+ enumValueToString(LambdaWeightWillReachEquilibrium::Samples));
+ CHECK((expand->equil_samples <= 0) && (expand->elmceq == LambdaWeightWillReachEquilibrium::Samples));
- sprintf(err_buf, "weight-equil-number-steps (%d) must be a positive integer if lmc-weights-equil=%s",
- expand->equil_steps, elmceq_names[elmceqSTEPS]);
- CHECK((expand->equil_steps <= 0) && (expand->elmceq == elmceqSTEPS));
+ sprintf(err_buf,
+ "weight-equil-number-steps (%d) must be a positive integer if lmc-weights-equil=%s",
+ expand->equil_steps,
+ enumValueToString(LambdaWeightWillReachEquilibrium::Steps));
+ CHECK((expand->equil_steps <= 0) && (expand->elmceq == LambdaWeightWillReachEquilibrium::Steps));
- sprintf(err_buf, "weight-equil-wl-delta (%f) must be > 0 if lmc-weights-equil=%s",
- expand->equil_wl_delta, elmceq_names[elmceqWLDELTA]);
- CHECK((expand->equil_wl_delta <= 0) && (expand->elmceq == elmceqWLDELTA));
+ sprintf(err_buf,
+ "weight-equil-wl-delta (%f) must be > 0 if lmc-weights-equil=%s",
+ expand->equil_wl_delta,
+ enumValueToString(LambdaWeightWillReachEquilibrium::WLDelta));
+ CHECK((expand->equil_wl_delta <= 0)
+ && (expand->elmceq == LambdaWeightWillReachEquilibrium::WLDelta));
- sprintf(err_buf, "weight-equil-count-ratio (%f) must be > 0 if lmc-weights-equil=%s",
- expand->equil_ratio, elmceq_names[elmceqRATIO]);
- CHECK((expand->equil_ratio <= 0) && (expand->elmceq == elmceqRATIO));
+ sprintf(err_buf,
+ "weight-equil-count-ratio (%f) must be > 0 if lmc-weights-equil=%s",
+ expand->equil_ratio,
+ enumValueToString(LambdaWeightWillReachEquilibrium::Ratio));
+ CHECK((expand->equil_ratio <= 0) && (expand->elmceq == LambdaWeightWillReachEquilibrium::Ratio));
- sprintf(err_buf, "lmc-weights-equil=%s only possible when lmc-stats = %s or lmc-stats %s",
- elmceq_names[elmceqWLDELTA], elamstats_names[elamstatsWL], elamstats_names[elamstatsWWL]);
- CHECK((expand->elmceq == elmceqWLDELTA) && (!EWL(expand->elamstats)));
+ sprintf(err_buf,
+ "lmc-weights-equil=%s only possible when lmc-stats = %s or lmc-stats %s",
+ enumValueToString(LambdaWeightWillReachEquilibrium::WLDelta),
+ enumValueToString(LambdaWeightCalculation::WL),
+ enumValueToString(LambdaWeightCalculation::WWL));
+ CHECK((expand->elmceq == LambdaWeightWillReachEquilibrium::WLDelta) && (!EWL(expand->elamstats)));
sprintf(err_buf, "lmc-repeats (%d) must be greater than 0", expand->lmc_repeats);
CHECK((expand->lmc_repeats <= 0));
CHECK((expand->minvarmin <= 0));
sprintf(err_buf, "weight-c-range (%d) must be greater or equal to 0", expand->c_range);
CHECK((expand->c_range < 0));
- sprintf(err_buf, "init-lambda-state (%d) must be zero if lmc-forced-nstart (%d)> 0 and lmc-move != 'no'",
- fep->init_fep_state, expand->lmc_forced_nstart);
- CHECK((fep->init_fep_state != 0) && (expand->lmc_forced_nstart > 0) && (expand->elmcmove != elmcmoveNO));
+ sprintf(err_buf,
+ "init-lambda-state (%d) must be zero if lmc-forced-nstart (%d)> 0 and lmc-move != "
+ "'no'",
+ fep->init_fep_state,
+ expand->lmc_forced_nstart);
+ CHECK((fep->init_fep_state != 0) && (expand->lmc_forced_nstart > 0)
+ && (expand->elmcmove != LambdaMoveCalculation::No));
sprintf(err_buf, "lmc-forced-nstart (%d) must not be negative", expand->lmc_forced_nstart);
CHECK((expand->lmc_forced_nstart < 0));
- sprintf(err_buf, "init-lambda-state (%d) must be in the interval [0,number of lambdas)", fep->init_fep_state);
+ sprintf(err_buf,
+ "init-lambda-state (%d) must be in the interval [0,number of lambdas)",
+ fep->init_fep_state);
CHECK((fep->init_fep_state < 0) || (fep->init_fep_state >= fep->n_lambda));
sprintf(err_buf, "init-wl-delta (%f) must be greater than or equal to 0", expand->init_wl_delta);
CHECK((expand->wl_scale <= 0) || (expand->wl_scale >= 1));
/* if there is no temperature control, we need to specify an MC temperature */
- if (!integratorHasReferenceTemperature(ir) && (expand->elmcmove != elmcmoveNO) && (expand->mc_temp <= 0.0))
+ if (!integratorHasReferenceTemperature(ir)
+ && (expand->elmcmove != LambdaMoveCalculation::No) && (expand->mc_temp <= 0.0))
{
- sprintf(err_buf, "If there is no temperature control, and lmc-mcmove!='no', mc_temp must be set to a positive number");
+ sprintf(err_buf,
+ "If there is no temperature control, and lmc-mcmove!='no', mc_temp must be set "
+ "to a positive number");
warning_error(wi, err_buf);
}
if (expand->nstTij > 0)
// Avoid modulus by zero in the case that already triggered an error exit.
if (ir->nstlog != 0)
{
- sprintf(err_buf, "nst-transition-matrix (%d) must be an integer multiple of nstlog (%d)",
- expand->nstTij, ir->nstlog);
+ sprintf(err_buf,
+ "nst-transition-matrix (%d) must be an integer multiple of nstlog (%d)",
+ expand->nstTij,
+ ir->nstlog);
CHECK((expand->nstTij % ir->nstlog) != 0);
}
}
}
/* PBC/WALLS */
- sprintf(err_buf, "walls only work with pbc=%s", epbc_names[epbcXY]);
- CHECK(ir->nwall && ir->ePBC != epbcXY);
+ sprintf(err_buf, "walls only work with pbc=%s", c_pbcTypeNames[PbcType::XY].c_str());
+ CHECK(ir->nwall && ir->pbcType != PbcType::XY);
/* VACUUM STUFF */
- if (ir->ePBC != epbcXYZ && ir->nwall != 2)
+ if (ir->pbcType != PbcType::Xyz && ir->nwall != 2)
{
- if (ir->ePBC == epbcNONE)
+ if (ir->pbcType == PbcType::No)
{
- if (ir->epc != epcNO)
+ if (ir->epc != PressureCoupling::No)
{
warning(wi, "Turning off pressure coupling for vacuum system");
- ir->epc = epcNO;
+ ir->epc = PressureCoupling::No;
}
}
else
{
- sprintf(err_buf, "Can not have pressure coupling with pbc=%s",
- epbc_names[ir->ePBC]);
- CHECK(ir->epc != epcNO);
+ sprintf(err_buf,
+ "Can not have pressure coupling with pbc=%s",
+ c_pbcTypeNames[ir->pbcType].c_str());
+ CHECK(ir->epc != PressureCoupling::No);
}
- sprintf(err_buf, "Can not have Ewald with pbc=%s", epbc_names[ir->ePBC]);
+ sprintf(err_buf, "Can not have Ewald with pbc=%s", c_pbcTypeNames[ir->pbcType].c_str());
CHECK(EEL_FULL(ir->coulombtype));
- sprintf(err_buf, "Can not have dispersion correction with pbc=%s",
- epbc_names[ir->ePBC]);
- CHECK(ir->eDispCorr != edispcNO);
+ sprintf(err_buf,
+ "Can not have dispersion correction with pbc=%s",
+ c_pbcTypeNames[ir->pbcType].c_str());
+ CHECK(ir->eDispCorr != DispersionCorrectionType::No);
}
if (ir->rlist == 0.0)
{
- sprintf(err_buf, "can only have neighborlist cut-off zero (=infinite)\n"
+ sprintf(err_buf,
+ "can only have neighborlist cut-off zero (=infinite)\n"
"with coulombtype = %s or coulombtype = %s\n"
"without periodic boundary conditions (pbc = %s) and\n"
"rcoulomb and rvdw set to zero",
- eel_names[eelCUT], eel_names[eelUSER], epbc_names[epbcNONE]);
- CHECK(((ir->coulombtype != eelCUT) && (ir->coulombtype != eelUSER)) ||
- (ir->ePBC != epbcNONE) ||
- (ir->rcoulomb != 0.0) || (ir->rvdw != 0.0));
+ enumValueToString(CoulombInteractionType::Cut),
+ enumValueToString(CoulombInteractionType::User),
+ c_pbcTypeNames[PbcType::No].c_str());
+ CHECK(((ir->coulombtype != CoulombInteractionType::Cut)
+ && (ir->coulombtype != CoulombInteractionType::User))
+ || (ir->pbcType != PbcType::No) || (ir->rcoulomb != 0.0) || (ir->rvdw != 0.0));
if (ir->nstlist > 0)
{
- warning_note(wi, "Simulating without cut-offs can be (slightly) faster with nstlist=0, nstype=simple and only one MPI rank");
+ warning_note(wi,
+ "Simulating without cut-offs can be (slightly) faster with nstlist=0, "
+ "nstype=simple and only one MPI rank");
}
}
{
// TODO Change this behaviour. There should be exactly one way
// to turn off an algorithm.
- ir->comm_mode = ecmNO;
+ ir->comm_mode = ComRemovalAlgorithm::No;
}
- if (ir->comm_mode != ecmNO)
+ if (ir->comm_mode != ComRemovalAlgorithm::No)
{
if (ir->nstcomm < 0)
{
// helpful for a few years, we should reject such input,
// lest we have to support every historical decision
// forever.
- warning(wi, "If you want to remove the rotation around the center of mass, you should set comm_mode = Angular instead of setting nstcomm < 0. nstcomm is modified to its absolute value");
+ warning(wi,
+ "If you want to remove the rotation around the center of mass, you should set "
+ "comm_mode = Angular instead of setting nstcomm < 0. nstcomm is modified to "
+ "its absolute value");
ir->nstcomm = abs(ir->nstcomm);
}
- if (ir->nstcalcenergy > 0 && ir->nstcomm < ir->nstcalcenergy)
+ if (ir->nstcalcenergy > 0 && ir->nstcomm < ir->nstcalcenergy
+ && ir->comm_mode != ComRemovalAlgorithm::LinearAccelerationCorrection)
{
- warning_note(wi, "nstcomm < nstcalcenergy defeats the purpose of nstcalcenergy, setting nstcomm to nstcalcenergy");
- ir->nstcomm = ir->nstcalcenergy;
+ warning_note(wi,
+ "nstcomm < nstcalcenergy defeats the purpose of nstcalcenergy, consider "
+ "setting nstcomm equal to nstcalcenergy for less overhead");
}
- if (ir->comm_mode == ecmANGULAR)
+ if (ir->comm_mode == ComRemovalAlgorithm::Angular)
{
- sprintf(err_buf, "Can not remove the rotation around the center of mass with periodic molecules");
+ sprintf(err_buf,
+ "Can not remove the rotation around the center of mass with periodic "
+ "molecules");
CHECK(ir->bPeriodicMols);
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
- warning(wi, "Removing the rotation around the center of mass in a periodic system, this can lead to artifacts. Only use this on a single (cluster of) molecules. This cluster should not cross periodic boundaries.");
+ warning(wi,
+ "Removing the rotation around the center of mass in a periodic system, "
+ "this can lead to artifacts. Only use this on a single (cluster of) "
+ "molecules. This cluster should not cross periodic boundaries.");
}
}
}
- if (EI_STATE_VELOCITY(ir->eI) && !EI_SD(ir->eI) && ir->ePBC == epbcNONE && ir->comm_mode != ecmANGULAR)
+ if (EI_STATE_VELOCITY(ir->eI) && !EI_SD(ir->eI) && ir->pbcType == PbcType::No
+ && ir->comm_mode != ComRemovalAlgorithm::Angular)
{
- sprintf(warn_buf, "Tumbling and flying ice-cubes: We are not removing rotation around center of mass in a non-periodic system. You should probably set comm_mode = ANGULAR or use integrator = %s.", ei_names[eiSD1]);
+ sprintf(warn_buf,
+ "Tumbling and flying ice-cubes: We are not removing rotation around center of mass "
+ "in a non-periodic system. You should probably set comm_mode = ANGULAR or use "
+ "integrator = %s.",
+ enumValueToString(IntegrationAlgorithm::SD1));
warning_note(wi, warn_buf);
}
/* TEMPERATURE COUPLING */
- if (ir->etc == etcYES)
+ if (ir->etc == TemperatureCoupling::Yes)
{
- ir->etc = etcBERENDSEN;
- warning_note(wi, "Old option for temperature coupling given: "
+ ir->etc = TemperatureCoupling::Berendsen;
+ warning_note(wi,
+ "Old option for temperature coupling given: "
"changing \"yes\" to \"Berendsen\"\n");
}
- if ((ir->etc == etcNOSEHOOVER) || (ir->epc == epcMTTK))
+ if ((ir->etc == TemperatureCoupling::NoseHoover) || (ir->epc == PressureCoupling::Mttk))
{
if (ir->opts.nhchainlength < 1)
{
- sprintf(warn_buf, "number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n", ir->opts.nhchainlength);
+ sprintf(warn_buf,
+ "number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to "
+ "1\n",
+ ir->opts.nhchainlength);
ir->opts.nhchainlength = 1;
warning(wi, warn_buf);
}
- if (ir->etc == etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
+ if (ir->etc == TemperatureCoupling::NoseHoover && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
{
- warning_note(wi, "leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
+ warning_note(
+ wi,
+ "leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
ir->opts.nhchainlength = 1;
}
}
ir->opts.nhchainlength = 0;
}
- if (ir->eI == eiVVAK)
+ if (ir->eI == IntegrationAlgorithm::VVAK)
{
- sprintf(err_buf, "%s implemented primarily for validation, and requires nsttcouple = 1 and nstpcouple = 1.",
- ei_names[eiVVAK]);
+ sprintf(err_buf,
+ "%s implemented primarily for validation, and requires nsttcouple = 1 and "
+ "nstpcouple = 1.",
+ enumValueToString(IntegrationAlgorithm::VVAK));
CHECK((ir->nsttcouple != 1) || (ir->nstpcouple != 1));
}
if (ETC_ANDERSEN(ir->etc))
{
- sprintf(err_buf, "%s temperature control not supported for integrator %s.", etcoupl_names[ir->etc], ei_names[ir->eI]);
+ sprintf(err_buf,
+ "%s temperature control not supported for integrator %s.",
+ enumValueToString(ir->etc),
+ enumValueToString(ir->eI));
CHECK(!(EI_VV(ir->eI)));
- if (ir->nstcomm > 0 && (ir->etc == etcANDERSEN))
+ if (ir->nstcomm > 0 && (ir->etc == TemperatureCoupling::Andersen))
{
- sprintf(warn_buf, "Center of mass removal not necessary for %s. All velocities of coupled groups are rerandomized periodically, so flying ice cube errors will not occur.", etcoupl_names[ir->etc]);
+ sprintf(warn_buf,
+ "Center of mass removal not necessary for %s. All velocities of coupled "
+ "groups are rerandomized periodically, so flying ice cube errors will not "
+ "occur.",
+ enumValueToString(ir->etc));
warning_note(wi, warn_buf);
}
- sprintf(err_buf, "nstcomm must be 1, not %d for %s, as velocities of atoms in coupled groups are randomized every time step", ir->nstcomm, etcoupl_names[ir->etc]);
- CHECK(ir->nstcomm > 1 && (ir->etc == etcANDERSEN));
+ sprintf(err_buf,
+ "nstcomm must be 1, not %d for %s, as velocities of atoms in coupled groups are "
+ "randomized every time step",
+ ir->nstcomm,
+ enumValueToString(ir->etc));
+ CHECK(ir->nstcomm > 1 && (ir->etc == TemperatureCoupling::Andersen));
}
- if (ir->etc == etcBERENDSEN)
+ if (ir->etc == TemperatureCoupling::Berendsen)
{
- sprintf(warn_buf, "The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
- ETCOUPLTYPE(ir->etc), ETCOUPLTYPE(etcVRESCALE));
+ sprintf(warn_buf,
+ "The %s thermostat does not generate the correct kinetic energy distribution. You "
+ "might want to consider using the %s thermostat.",
+ enumValueToString(ir->etc),
+ enumValueToString(TemperatureCoupling::VRescale));
warning_note(wi, warn_buf);
}
- if ((ir->etc == etcNOSEHOOVER || ETC_ANDERSEN(ir->etc))
- && ir->epc == epcBERENDSEN)
+ if ((ir->etc == TemperatureCoupling::NoseHoover || ETC_ANDERSEN(ir->etc))
+ && ir->epc == PressureCoupling::Berendsen)
{
- sprintf(warn_buf, "Using Berendsen pressure coupling invalidates the "
+ sprintf(warn_buf,
+ "Using Berendsen pressure coupling invalidates the "
"true ensemble for the thermostat");
warning(wi, warn_buf);
}
/* PRESSURE COUPLING */
- if (ir->epc == epcISOTROPIC)
+ if (ir->epc == PressureCoupling::Isotropic)
{
- ir->epc = epcBERENDSEN;
- warning_note(wi, "Old option for pressure coupling given: "
+ ir->epc = PressureCoupling::Berendsen;
+ warning_note(wi,
+ "Old option for pressure coupling given: "
"changing \"Isotropic\" to \"Berendsen\"\n");
}
- if (ir->epc != epcNO)
+ if (ir->epc != PressureCoupling::No)
{
- dt_pcoupl = ir->nstpcouple*ir->delta_t;
+ dt_pcoupl = ir->nstpcouple * ir->delta_t;
sprintf(err_buf, "tau-p must be > 0 instead of %g\n", ir->tau_p);
CHECK(ir->tau_p <= 0);
- if (ir->tau_p/dt_pcoupl < pcouple_min_integration_steps(ir->epc) - 10*GMX_REAL_EPS)
+ if (ir->tau_p / dt_pcoupl < pcouple_min_integration_steps(ir->epc) - 10 * GMX_REAL_EPS)
{
- sprintf(warn_buf, "For proper integration of the %s barostat, tau-p (%g) should be at least %d times larger than nstpcouple*dt (%g)",
- EPCOUPLTYPE(ir->epc), ir->tau_p, pcouple_min_integration_steps(ir->epc), dt_pcoupl);
+ sprintf(warn_buf,
+ "For proper integration of the %s barostat, tau-p (%g) should be at least %d "
+ "times larger than nstpcouple*dt (%g)",
+ enumValueToString(ir->epc),
+ ir->tau_p,
+ pcouple_min_integration_steps(ir->epc),
+ dt_pcoupl);
warning(wi, warn_buf);
}
- sprintf(err_buf, "compressibility must be > 0 when using pressure"
- " coupling %s\n", EPCOUPLTYPE(ir->epc));
- CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 ||
- ir->compress[ZZ][ZZ] < 0 ||
- (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
- ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
+ sprintf(err_buf,
+ "compressibility must be > 0 when using pressure"
+ " coupling %s\n",
+ enumValueToString(ir->epc));
+ CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || ir->compress[ZZ][ZZ] < 0
+ || (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 && ir->compress[ZZ][XX] <= 0
+ && ir->compress[ZZ][YY] <= 0));
- if (epcPARRINELLORAHMAN == ir->epc && opts->bGenVel)
+ if (PressureCoupling::ParrinelloRahman == ir->epc && opts->bGenVel)
{
sprintf(warn_buf,
"You are generating velocities so I am assuming you "
"equilibrating first with Berendsen pressure coupling. If "
"you are not equilibrating the system, you can probably "
"ignore this warning.",
- epcoupl_names[ir->epc]);
+ enumValueToString(ir->epc));
warning(wi, warn_buf);
}
}
if (!EI_VV(ir->eI))
{
- if (ir->epc == epcMTTK)
+ if (ir->epc == PressureCoupling::Mttk)
{
warning_error(wi, "MTTK pressure coupling requires a Velocity-verlet integrator");
}
/* ELECTROSTATICS */
/* More checks are in triple check (grompp.c) */
- if (ir->coulombtype == eelSWITCH)
+ if (ir->coulombtype == CoulombInteractionType::Switch)
{
- sprintf(warn_buf, "coulombtype = %s is only for testing purposes and can lead to serious "
+ sprintf(warn_buf,
+ "coulombtype = %s is only for testing purposes and can lead to serious "
"artifacts, advice: use coulombtype = %s",
- eel_names[ir->coulombtype],
- eel_names[eelRF_ZERO]);
+ enumValueToString(ir->coulombtype),
+ enumValueToString(CoulombInteractionType::RFZero));
warning(wi, warn_buf);
}
if (EEL_RF(ir->coulombtype) && ir->epsilon_rf == 1 && ir->epsilon_r != 1)
{
- sprintf(warn_buf, "epsilon-r = %g and epsilon-rf = 1 with reaction field, proceeding assuming old format and exchanging epsilon-r and epsilon-rf", ir->epsilon_r);
+ sprintf(warn_buf,
+ "epsilon-r = %g and epsilon-rf = 1 with reaction field, proceeding assuming old "
+ "format and exchanging epsilon-r and epsilon-rf",
+ ir->epsilon_r);
warning(wi, warn_buf);
ir->epsilon_rf = ir->epsilon_r;
ir->epsilon_r = 1.0;
if (ir->epsilon_r == 0)
{
sprintf(err_buf,
- "It is pointless to use long-range electrostatics with infinite relative permittivity."
- "Since you are effectively turning of electrostatics, a plain cutoff will be much faster.");
+ "It is pointless to use long-range electrostatics with infinite relative "
+ "permittivity."
+ "Since you are effectively turning of electrostatics, a plain cutoff will be much "
+ "faster.");
CHECK(EEL_FULL(ir->coulombtype));
}
{
/* reaction field (at the cut-off) */
- if (ir->coulombtype == eelRF_ZERO && ir->epsilon_rf != 0)
+ if (ir->coulombtype == CoulombInteractionType::RFZero && ir->epsilon_rf != 0)
{
- sprintf(warn_buf, "With coulombtype = %s, epsilon-rf must be 0, assuming you meant epsilon_rf=0",
- eel_names[ir->coulombtype]);
+ sprintf(warn_buf,
+ "With coulombtype = %s, epsilon-rf must be 0, assuming you meant epsilon_rf=0",
+ enumValueToString(ir->coulombtype));
warning(wi, warn_buf);
ir->epsilon_rf = 0.0;
}
sprintf(err_buf, "epsilon-rf must be >= epsilon-r");
- CHECK((ir->epsilon_rf < ir->epsilon_r && ir->epsilon_rf != 0) ||
- (ir->epsilon_r == 0));
+ CHECK((ir->epsilon_rf < ir->epsilon_r && ir->epsilon_rf != 0) || (ir->epsilon_r == 0));
if (ir->epsilon_rf == ir->epsilon_r)
{
- sprintf(warn_buf, "Using epsilon-rf = epsilon-r with %s does not make sense",
- eel_names[ir->coulombtype]);
+ sprintf(warn_buf,
+ "Using epsilon-rf = epsilon-r with %s does not make sense",
+ enumValueToString(ir->coulombtype));
warning(wi, warn_buf);
}
}
if (ir_coulomb_switched(ir))
{
sprintf(err_buf,
- "With coulombtype = %s rcoulomb_switch must be < rcoulomb. Or, better: Use the potential modifier options!",
- eel_names[ir->coulombtype]);
+ "With coulombtype = %s rcoulomb_switch must be < rcoulomb. Or, better: Use the "
+ "potential modifier options!",
+ enumValueToString(ir->coulombtype));
CHECK(ir->rcoulomb_switch >= ir->rcoulomb);
}
}
- if (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT)
+ if (ir->coulombtype == CoulombInteractionType::Switch || ir->coulombtype == CoulombInteractionType::Shift)
{
sprintf(err_buf,
- "Explicit switch/shift coulomb interactions cannot be used in combination with a secondary coulomb-modifier.");
- CHECK( ir->coulomb_modifier != eintmodNONE);
+ "Explicit switch/shift coulomb interactions cannot be used in combination with a "
+ "secondary coulomb-modifier.");
+ CHECK(ir->coulomb_modifier != InteractionModifiers::None);
}
- if (ir->vdwtype == evdwSWITCH || ir->vdwtype == evdwSHIFT)
+ if (ir->vdwtype == VanDerWaalsType::Switch || ir->vdwtype == VanDerWaalsType::Shift)
{
sprintf(err_buf,
- "Explicit switch/shift vdw interactions cannot be used in combination with a secondary vdw-modifier.");
- CHECK( ir->vdw_modifier != eintmodNONE);
+ "Explicit switch/shift vdw interactions cannot be used in combination with a "
+ "secondary vdw-modifier.");
+ CHECK(ir->vdw_modifier != InteractionModifiers::None);
}
- if (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT ||
- ir->vdwtype == evdwSWITCH || ir->vdwtype == evdwSHIFT)
+ if (ir->coulombtype == CoulombInteractionType::Switch || ir->coulombtype == CoulombInteractionType::Shift
+ || ir->vdwtype == VanDerWaalsType::Switch || ir->vdwtype == VanDerWaalsType::Shift)
{
sprintf(warn_buf,
- "The switch/shift interaction settings are just for compatibility; you will get better "
+ "The switch/shift interaction settings are just for compatibility; you will get "
+ "better "
"performance from applying potential modifiers to your interactions!\n");
warning_note(wi, warn_buf);
}
- if (ir->coulombtype == eelPMESWITCH || ir->coulomb_modifier == eintmodPOTSWITCH)
+ if (ir->coulombtype == CoulombInteractionType::PmeSwitch
+ || ir->coulomb_modifier == InteractionModifiers::PotSwitch)
{
- if (ir->rcoulomb_switch/ir->rcoulomb < 0.9499)
+ if (ir->rcoulomb_switch / ir->rcoulomb < 0.9499)
{
- real percentage = 100*(ir->rcoulomb-ir->rcoulomb_switch)/ir->rcoulomb;
- sprintf(warn_buf, "The switching range should be 5%% or less (currently %.2f%% using a switching range of %4f-%4f) for accurate electrostatic energies, energy conservation will be good regardless, since ewald_rtol = %g.",
- percentage, ir->rcoulomb_switch, ir->rcoulomb, ir->ewald_rtol);
+ real percentage = 100 * (ir->rcoulomb - ir->rcoulomb_switch) / ir->rcoulomb;
+ sprintf(warn_buf,
+ "The switching range should be 5%% or less (currently %.2f%% using a switching "
+ "range of %4f-%4f) for accurate electrostatic energies, energy conservation "
+ "will be good regardless, since ewald_rtol = %g.",
+ percentage,
+ ir->rcoulomb_switch,
+ ir->rcoulomb,
+ ir->ewald_rtol);
warning(wi, warn_buf);
}
}
- if (ir->vdwtype == evdwSWITCH || ir->vdw_modifier == eintmodPOTSWITCH)
+ if (ir->vdwtype == VanDerWaalsType::Switch || ir->vdw_modifier == InteractionModifiers::PotSwitch)
{
if (ir->rvdw_switch == 0)
{
- sprintf(warn_buf, "rvdw-switch is equal 0 even though you are using a switched Lennard-Jones potential. This suggests it was not set in the mdp, which can lead to large energy errors. In GROMACS, 0.05 to 0.1 nm is often a reasonable vdw switching range.");
+ sprintf(warn_buf,
+ "rvdw-switch is equal 0 even though you are using a switched Lennard-Jones "
+ "potential. This suggests it was not set in the mdp, which can lead to large "
+ "energy errors. In GROMACS, 0.05 to 0.1 nm is often a reasonable vdw "
+ "switching range.");
warning(wi, warn_buf);
}
}
if (EEL_FULL(ir->coulombtype))
{
- if (ir->coulombtype == eelPMESWITCH || ir->coulombtype == eelPMEUSER ||
- ir->coulombtype == eelPMEUSERSWITCH)
+ if (ir->coulombtype == CoulombInteractionType::PmeSwitch
+ || ir->coulombtype == CoulombInteractionType::PmeUser
+ || ir->coulombtype == CoulombInteractionType::PmeUserSwitch)
{
- sprintf(err_buf, "With coulombtype = %s, rcoulomb must be <= rlist",
- eel_names[ir->coulombtype]);
+ sprintf(err_buf,
+ "With coulombtype = %s, rcoulomb must be <= rlist",
+ enumValueToString(ir->coulombtype));
CHECK(ir->rcoulomb > ir->rlist);
}
}
{
// TODO: Move these checks into the ewald module with the options class
int orderMin = 3;
- int orderMax = (ir->coulombtype == eelP3M_AD ? 8 : 12);
+ int orderMax = (ir->coulombtype == CoulombInteractionType::P3mAD ? 8 : 12);
if (ir->pme_order < orderMin || ir->pme_order > orderMax)
{
- sprintf(warn_buf, "With coulombtype = %s, you should have %d <= pme-order <= %d", eel_names[ir->coulombtype], orderMin, orderMax);
+ sprintf(warn_buf,
+ "With coulombtype = %s, you should have %d <= pme-order <= %d",
+ enumValueToString(ir->coulombtype),
+ orderMin,
+ orderMax);
warning_error(wi, warn_buf);
}
}
if (ir->nwall == 2 && EEL_FULL(ir->coulombtype))
{
- if (ir->ewald_geometry == eewg3D)
+ if (ir->ewald_geometry == EwaldGeometry::ThreeD)
{
- sprintf(warn_buf, "With pbc=%s you should use ewald-geometry=%s",
- epbc_names[ir->ePBC], eewg_names[eewg3DC]);
+ sprintf(warn_buf,
+ "With pbc=%s you should use ewald-geometry=%s",
+ c_pbcTypeNames[ir->pbcType].c_str(),
+ enumValueToString(EwaldGeometry::ThreeDC));
warning(wi, warn_buf);
}
/* This check avoids extra pbc coding for exclusion corrections */
sprintf(err_buf, "wall-ewald-zfac should be >= 2");
CHECK(ir->wall_ewald_zfac < 2);
}
- if ((ir->ewald_geometry == eewg3DC) && (ir->ePBC != epbcXY) &&
- EEL_FULL(ir->coulombtype))
+ if ((ir->ewald_geometry == EwaldGeometry::ThreeDC) && (ir->pbcType != PbcType::XY)
+ && EEL_FULL(ir->coulombtype))
{
- sprintf(warn_buf, "With %s and ewald_geometry = %s you should use pbc = %s",
- eel_names[ir->coulombtype], eewg_names[eewg3DC], epbc_names[epbcXY]);
+ sprintf(warn_buf,
+ "With %s and ewald_geometry = %s you should use pbc = %s",
+ enumValueToString(ir->coulombtype),
+ enumValueToString(EwaldGeometry::ThreeDC),
+ c_pbcTypeNames[PbcType::XY].c_str());
warning(wi, warn_buf);
}
if ((ir->epsilon_surface != 0) && EEL_FULL(ir->coulombtype))
warning_note(wi, warn_buf);
sprintf(warn_buf,
"With epsilon_surface > 0 you can only use domain decomposition "
- "when there are only small molecules with all bonds constrained (mdrun will check for this).");
+ "when there are only small molecules with all bonds constrained (mdrun will check "
+ "for this).");
warning_note(wi, warn_buf);
}
sprintf(err_buf, "With switched vdw forces or potentials, rvdw-switch must be < rvdw");
CHECK(ir->rvdw_switch >= ir->rvdw);
- if (ir->rvdw_switch < 0.5*ir->rvdw)
+ if (ir->rvdw_switch < 0.5 * ir->rvdw)
{
- sprintf(warn_buf, "You are applying a switch function to vdw forces or potentials from %g to %g nm, which is more than half the interaction range, whereas switch functions are intended to act only close to the cut-off.",
- ir->rvdw_switch, ir->rvdw);
+ sprintf(warn_buf,
+ "You are applying a switch function to vdw forces or potentials from %g to %g "
+ "nm, which is more than half the interaction range, whereas switch functions "
+ "are intended to act only close to the cut-off.",
+ ir->rvdw_switch,
+ ir->rvdw);
warning_note(wi, warn_buf);
}
}
- if (ir->vdwtype == evdwPME)
+ if (ir->vdwtype == VanDerWaalsType::Pme)
{
- if (!(ir->vdw_modifier == eintmodNONE || ir->vdw_modifier == eintmodPOTSHIFT))
+ if (!(ir->vdw_modifier == InteractionModifiers::None
+ || ir->vdw_modifier == InteractionModifiers::PotShift))
{
- sprintf(err_buf, "With vdwtype = %s, the only supported modifiers are %s and %s",
- evdw_names[ir->vdwtype],
- eintmod_names[eintmodPOTSHIFT],
- eintmod_names[eintmodNONE]);
+ sprintf(err_buf,
+ "With vdwtype = %s, the only supported modifiers are %s and %s",
+ enumValueToString(ir->vdwtype),
+ enumValueToString(InteractionModifiers::PotShift),
+ enumValueToString(InteractionModifiers::None));
warning_error(wi, err_buf);
}
}
- if (ir->vdwtype == evdwUSER && ir->eDispCorr != edispcNO)
+ if (ir->vdwtype == VanDerWaalsType::User && ir->eDispCorr != DispersionCorrectionType::No)
{
- warning_note(wi, "You have selected user tables with dispersion correction, the dispersion will be corrected to -C6/r^6 beyond rvdw_switch (the tabulated interaction between rvdw_switch and rvdw will not be double counted). Make sure that you really want dispersion correction to -C6/r^6.");
+ warning_note(wi,
+ "You have selected user tables with dispersion correction, the dispersion "
+ "will be corrected to -C6/r^6 beyond rvdw_switch (the tabulated interaction "
+ "between rvdw_switch and rvdw will not be double counted). Make sure that you "
+ "really want dispersion correction to -C6/r^6.");
}
- if (ir->eI == eiLBFGS && (ir->coulombtype == eelCUT || ir->vdwtype == evdwCUT)
+ if (ir->eI == IntegrationAlgorithm::LBFGS
+ && (ir->coulombtype == CoulombInteractionType::Cut || ir->vdwtype == VanDerWaalsType::Cut)
&& ir->rvdw != 0)
{
warning(wi, "For efficient BFGS minimization, use switch/shift/pme instead of cut-off.");
}
- if (ir->eI == eiLBFGS && ir->nbfgscorr <= 0)
+ if (ir->eI == IntegrationAlgorithm::LBFGS && ir->nbfgscorr <= 0)
{
warning(wi, "Using L-BFGS with nbfgscorr<=0 just gets you steepest descent.");
}
/* IMPLICIT SOLVENT */
- if (ir->coulombtype == eelGB_NOTUSED)
+ if (ir->coulombtype == CoulombInteractionType::GBNotused)
{
- sprintf(warn_buf, "Invalid option %s for coulombtype",
- eel_names[ir->coulombtype]);
+ sprintf(warn_buf, "Invalid option %s for coulombtype", enumValueToString(ir->coulombtype));
warning_error(wi, warn_buf);
}
if (ir->bQMMM)
{
- if (ir->cutoff_scheme != ecutsGROUP)
- {
- warning_error(wi, "QMMM is currently only supported with cutoff-scheme=group");
- }
- if (!EI_DYNAMICS(ir->eI))
- {
- char buf[STRLEN];
- sprintf(buf, "QMMM is only supported with dynamics, not with integrator %s", ei_names[ir->eI]);
- warning_error(wi, buf);
- }
+ warning_error(wi, "The QMMM integration you are trying to use is no longer supported");
}
if (ir->bAdress)
{
gmx_fatal(FARGS, "AdResS simulations are no longer supported");
}
+
+ // cosine acceleration is only supported in leap-frog
+ if (ir->cos_accel != 0.0 && ir->eI != IntegrationAlgorithm::MD)
+ {
+ warning_error(wi, "cos-acceleration is only supported by integrator = md");
+ }
}
/* interpret a number of doubles from a string and put them in an array,
str = the input string
n = the (pre-allocated) number of doubles read
r = the output array of doubles. */
-static void parse_n_real(char *str, int *n, real **r, warninp_t wi)
+static std::vector<real> parse_n_real(const std::string& str, int* n, warninp_t wi)
{
auto values = gmx::splitString(str);
- *n = values.size();
+ *n = values.size();
- snew(*r, *n);
+ std::vector<real> r;
for (int i = 0; i < *n; i++)
{
try
{
- (*r)[i] = gmx::fromString<real>(values[i]);
+ r.emplace_back(gmx::fromString<real>(values[i]));
}
- catch (gmx::GromacsException &)
+ catch (gmx::GromacsException&)
{
- warning_error(wi, "Invalid value " + values[i] + " in string in mdp file. Expected a real number.");
+ warning_error(wi,
+ "Invalid value " + values[i]
+ + " in string in mdp file. Expected a real number.");
}
}
+ return r;
}
-static void do_fep_params(t_inputrec *ir, char fep_lambda[][STRLEN], char weights[STRLEN], warninp_t wi)
+static void do_fep_params(t_inputrec* ir, gmx::ArrayRef<std::string> fep_lambda, char weights[STRLEN], warninp_t wi)
{
- int i, j, max_n_lambda, nweights, nfep[efptNR];
- t_lambda *fep = ir->fepvals;
- t_expanded *expand = ir->expandedvals;
- real **count_fep_lambdas;
- bool bOneLambda = TRUE;
-
- snew(count_fep_lambdas, efptNR);
+ int i, j, max_n_lambda, nweights;
+ t_lambda* fep = ir->fepvals.get();
+ t_expanded* expand = ir->expandedvals.get();
+ gmx::EnumerationArray<FreeEnergyPerturbationCouplingType, std::vector<real>> count_fep_lambdas;
+ bool bOneLambda = TRUE;
+ gmx::EnumerationArray<FreeEnergyPerturbationCouplingType, int> nfep;
/* FEP input processing */
/* first, identify the number of lambda values for each type.
All that are nonzero must have the same number */
- for (i = 0; i < efptNR; i++)
+ for (auto i : keysOf(nfep))
{
- parse_n_real(fep_lambda[i], &(nfep[i]), &(count_fep_lambdas[i]), wi);
+ count_fep_lambdas[i] = parse_n_real(fep_lambda[static_cast<int>(i)], &(nfep[i]), wi);
}
/* now, determine the number of components. All must be either zero, or equal. */
max_n_lambda = 0;
- for (i = 0; i < efptNR; i++)
+ for (auto i : keysOf(nfep))
{
if (nfep[i] > max_n_lambda)
{
- max_n_lambda = nfep[i]; /* here's a nonzero one. All of them
- must have the same number if its not zero.*/
+ max_n_lambda = nfep[i]; /* here's a nonzero one. All of them
+ must have the same number if its not zero.*/
break;
}
}
- for (i = 0; i < efptNR; i++)
+ for (auto i : keysOf(nfep))
{
if (nfep[i] == 0)
{
}
else if (nfep[i] == max_n_lambda)
{
- if (i != efptTEMPERATURE) /* we treat this differently -- not really a reason to compute the derivative with
- respect to the temperature currently */
+ if (i != FreeEnergyPerturbationCouplingType::Temperature) /* we treat this differently -- not really a reason to compute
+ the derivative with respect to the temperature currently */
{
ir->fepvals->separate_dvdl[i] = TRUE;
}
}
else
{
- gmx_fatal(FARGS, "Number of lambdas (%d) for FEP type %s not equal to number of other types (%d)",
- nfep[i], efpt_names[i], max_n_lambda);
+ gmx_fatal(FARGS,
+ "Number of lambdas (%d) for FEP type %s not equal to number of other types "
+ "(%d)",
+ nfep[i],
+ enumValueToString(i),
+ max_n_lambda);
}
}
/* we don't print out dhdl if the temperature is changing, since we can't correctly define dhdl in this case */
- ir->fepvals->separate_dvdl[efptTEMPERATURE] = FALSE;
+ ir->fepvals->separate_dvdl[FreeEnergyPerturbationCouplingType::Temperature] = FALSE;
/* the number of lambdas is the number we've read in, which is either zero
or the same for all */
fep->n_lambda = max_n_lambda;
- /* allocate space for the array of lambda values */
- snew(fep->all_lambda, efptNR);
/* if init_lambda is defined, we need to set lambda */
if ((fep->init_lambda > 0) && (fep->n_lambda == 0))
{
- ir->fepvals->separate_dvdl[efptFEP] = TRUE;
+ ir->fepvals->separate_dvdl[FreeEnergyPerturbationCouplingType::Fep] = TRUE;
}
/* otherwise allocate the space for all of the lambdas, and transfer the data */
- for (i = 0; i < efptNR; i++)
+ for (auto i : keysOf(nfep))
{
- snew(fep->all_lambda[i], fep->n_lambda);
- if (nfep[i] > 0) /* if it's zero, then the count_fep_lambda arrays
- are zero */
+ fep->all_lambda[i].resize(fep->n_lambda);
+ if (nfep[i] > 0) /* if it's zero, then the count_fep_lambda arrays
+ are zero */
{
for (j = 0; j < fep->n_lambda; j++)
{
fep->all_lambda[i][j] = static_cast<double>(count_fep_lambdas[i][j]);
}
- sfree(count_fep_lambdas[i]);
}
}
- sfree(count_fep_lambdas);
- /* "fep-vals" is either zero or the full number. If zero, we'll need to define fep-lambdas for internal
- bookkeeping -- for now, init_lambda */
+ /* "fep-vals" is either zero or the full number. If zero, we'll need to define fep-lambdas for
+ internal bookkeeping -- for now, init_lambda */
- if ((nfep[efptFEP] == 0) && (fep->init_lambda >= 0))
+ if ((nfep[FreeEnergyPerturbationCouplingType::Fep] == 0) && (fep->init_lambda >= 0))
{
for (i = 0; i < fep->n_lambda; i++)
{
- fep->all_lambda[efptFEP][i] = fep->init_lambda;
+ fep->all_lambda[FreeEnergyPerturbationCouplingType::Fep][i] = fep->init_lambda;
}
}
}
else
{
- for (i = 0; i < efptNR; i++)
+ for (auto i : keysOf(nfep))
{
- if ((nfep[i] != 0) && (i != efptFEP))
+ if ((nfep[i] != 0) && (i != FreeEnergyPerturbationCouplingType::Fep))
{
bOneLambda = FALSE;
}
specified (i.e. nfep[i] == 0). This means if fep is not defined,
they are all zero. */
- for (i = 0; i < efptNR; i++)
+ for (auto i : keysOf(nfep))
{
- if ((nfep[i] == 0) && (i != efptFEP))
+ if ((nfep[i] == 0) && (i != FreeEnergyPerturbationCouplingType::Fep))
{
for (j = 0; j < fep->n_lambda; j++)
{
- fep->all_lambda[i][j] = fep->all_lambda[efptFEP][j];
+ fep->all_lambda[i][j] = fep->all_lambda[FreeEnergyPerturbationCouplingType::Fep][j];
}
}
}
- /* make it easier if sc_r_power = 48 by increasing it to the 4th power, to be in the right scale. */
- if (fep->sc_r_power == 48)
- {
- if (fep->sc_alpha > 0.1)
- {
- gmx_fatal(FARGS, "sc_alpha (%f) for sc_r_power = 48 should usually be between 0.001 and 0.004", fep->sc_alpha);
- }
- }
-
/* now read in the weights */
- parse_n_real(weights, &nweights, &(expand->init_lambda_weights), wi);
+ expand->init_lambda_weights = parse_n_real(weights, &nweights, wi);
if (nweights == 0)
{
- snew(expand->init_lambda_weights, fep->n_lambda); /* initialize to zero */
+ expand->init_lambda_weights.resize(fep->n_lambda); /* initialize to zero */
}
else if (nweights != fep->n_lambda)
{
- gmx_fatal(FARGS, "Number of weights (%d) is not equal to number of lambda values (%d)",
- nweights, fep->n_lambda);
+ gmx_fatal(FARGS,
+ "Number of weights (%d) is not equal to number of lambda values (%d)",
+ nweights,
+ fep->n_lambda);
}
- if ((expand->nstexpanded < 0) && (ir->efep != efepNO))
+ if ((expand->nstexpanded < 0) && (ir->efep != FreeEnergyPerturbationType::No))
{
expand->nstexpanded = fep->nstdhdl;
/* if you don't specify nstexpanded when doing expanded ensemble free energy calcs, it is set to nstdhdl */
}
-static void do_simtemp_params(t_inputrec *ir)
+static void do_simtemp_params(t_inputrec* ir)
{
-
- snew(ir->simtempvals->temperatures, ir->fepvals->n_lambda);
- GetSimTemps(ir->fepvals->n_lambda, ir->simtempvals, ir->fepvals->all_lambda[efptTEMPERATURE]);
-}
-
-static void
-convertYesNos(warninp_t /*wi*/, gmx::ArrayRef<const std::string> inputs, const char * /*name*/, gmx_bool *outputs)
-{
- int i = 0;
- for (const auto &input : inputs)
- {
- outputs[i] = gmx::equalCaseInsensitive(input, "Y", 1);
- ++i;
- }
+ ir->simtempvals->temperatures.resize(ir->fepvals->n_lambda);
+ getSimTemps(ir->fepvals->n_lambda,
+ ir->simtempvals.get(),
+ ir->fepvals->all_lambda[FreeEnergyPerturbationCouplingType::Temperature]);
}
-template <typename T> void
-convertInts(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char *name, T *outputs)
+template<typename T>
+void convertInts(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, T* outputs)
{
int i = 0;
- for (const auto &input : inputs)
+ for (const auto& input : inputs)
{
try
{
outputs[i] = gmx::fromStdString<T>(input);
}
- catch (gmx::GromacsException &)
+ catch (gmx::GromacsException&)
{
- auto message = gmx::formatString("Invalid value for mdp option %s. %s should only consist of integers separated by spaces.",
- name, name);
+ auto message = gmx::formatString(
+ "Invalid value for mdp option %s. %s should only consist of integers separated "
+ "by spaces.",
+ name,
+ name);
warning_error(wi, message);
}
++i;
}
}
-static void
-convertReals(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char *name, real *outputs)
+static void convertReals(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, real* outputs)
{
int i = 0;
- for (const auto &input : inputs)
+ for (const auto& input : inputs)
{
try
{
outputs[i] = gmx::fromString<real>(input);
}
- catch (gmx::GromacsException &)
+ catch (gmx::GromacsException&)
{
- auto message = gmx::formatString("Invalid value for mdp option %s. %s should only consist of real numbers separated by spaces.",
- name, name);
+ auto message = gmx::formatString(
+ "Invalid value for mdp option %s. %s should only consist of real numbers "
+ "separated by spaces.",
+ name,
+ name);
warning_error(wi, message);
}
++i;
}
}
-static void
-convertRvecs(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char *name, rvec *outputs)
-{
- int i = 0, d = 0;
- for (const auto &input : inputs)
- {
- try
- {
- outputs[i][d] = gmx::fromString<real>(input);
- }
- catch (gmx::GromacsException &)
- {
- auto message = gmx::formatString("Invalid value for mdp option %s. %s should only consist of real numbers separated by spaces.",
- name, name);
- warning_error(wi, message);
- }
- ++d;
- if (d == DIM)
- {
- d = 0;
- ++i;
- }
- }
-}
-
-static void do_wall_params(t_inputrec *ir,
- char *wall_atomtype, char *wall_density,
- t_gromppopts *opts,
- warninp_t wi)
+static void do_wall_params(t_inputrec* ir, char* wall_atomtype, char* wall_density, t_gromppopts* opts, warninp_t wi)
{
opts->wall_atomtype[0] = nullptr;
opts->wall_atomtype[1] = nullptr;
auto wallAtomTypes = gmx::splitString(wall_atomtype);
if (wallAtomTypes.size() != size_t(ir->nwall))
{
- gmx_fatal(FARGS, "Expected %d elements for wall_atomtype, found %zu",
- ir->nwall, wallAtomTypes.size());
+ gmx_fatal(FARGS,
+ "Expected %d elements for wall_atomtype, found %zu",
+ ir->nwall,
+ wallAtomTypes.size());
}
+ GMX_RELEASE_ASSERT(ir->nwall < 3, "Invalid number of walls");
for (int i = 0; i < ir->nwall; i++)
{
opts->wall_atomtype[i] = gmx_strdup(wallAtomTypes[i].c_str());
}
- if (ir->wall_type == ewt93 || ir->wall_type == ewt104)
+ if (ir->wall_type == WallType::NineThree || ir->wall_type == WallType::TenFour)
{
auto wallDensity = gmx::splitString(wall_density);
if (wallDensity.size() != size_t(ir->nwall))
{
- gmx_fatal(FARGS, "Expected %d elements for wall-density, found %zu", ir->nwall, wallDensity.size());
+ gmx_fatal(FARGS,
+ "Expected %d elements for wall-density, found %zu",
+ ir->nwall,
+ wallDensity.size());
}
convertReals(wi, wallDensity, "wall-density", ir->wall_density);
for (int i = 0; i < ir->nwall; i++)
}
}
-static void add_wall_energrps(SimulationGroups *groups, int nwall, t_symtab *symtab)
+static void add_wall_energrps(SimulationGroups* groups, int nwall, t_symtab* symtab)
{
if (nwall > 0)
{
- AtomGroupIndices *grps = &(groups->groups[SimulationAtomGroupType::EnergyOutput]);
+ AtomGroupIndices* grps = &(groups->groups[SimulationAtomGroupType::EnergyOutput]);
for (int i = 0; i < nwall; i++)
{
- groups->groupNames.emplace_back(
- put_symtab(
- symtab,
- gmx::formatString("wall%d", i).c_str()));
+ groups->groupNames.emplace_back(put_symtab(symtab, gmx::formatString("wall%d", i).c_str()));
grps->emplace_back(groups->groupNames.size() - 1);
}
}
}
-static void read_expandedparams(std::vector<t_inpfile> *inp,
- t_expanded *expand, warninp_t wi)
+static void read_expandedparams(std::vector<t_inpfile>* inp, t_expanded* expand, warninp_t wi)
{
/* read expanded ensemble parameters */
printStringNewline(inp, "expanded ensemble variables");
- expand->nstexpanded = get_eint(inp, "nstexpanded", -1, wi);
- expand->elamstats = get_eeenum(inp, "lmc-stats", elamstats_names, wi);
- expand->elmcmove = get_eeenum(inp, "lmc-move", elmcmove_names, wi);
- expand->elmceq = get_eeenum(inp, "lmc-weights-equil", elmceq_names, wi);
+ expand->nstexpanded = get_eint(inp, "nstexpanded", -1, wi);
+ expand->elamstats = getEnum<LambdaWeightCalculation>(inp, "lmc-stats", wi);
+ expand->elmcmove = getEnum<LambdaMoveCalculation>(inp, "lmc-move", wi);
+ expand->elmceq = getEnum<LambdaWeightWillReachEquilibrium>(inp, "lmc-weights-equil", wi);
expand->equil_n_at_lam = get_eint(inp, "weight-equil-number-all-lambda", -1, wi);
expand->equil_samples = get_eint(inp, "weight-equil-number-samples", -1, wi);
expand->equil_steps = get_eint(inp, "weight-equil-number-steps", -1, wi);
expand->equil_wl_delta = get_ereal(inp, "weight-equil-wl-delta", -1, wi);
expand->equil_ratio = get_ereal(inp, "weight-equil-count-ratio", -1, wi);
printStringNewline(inp, "Seed for Monte Carlo in lambda space");
- expand->lmc_seed = get_eint(inp, "lmc-seed", -1, wi);
- expand->mc_temp = get_ereal(inp, "mc-temperature", -1, wi);
- expand->lmc_repeats = get_eint(inp, "lmc-repeats", 1, wi);
- expand->gibbsdeltalam = get_eint(inp, "lmc-gibbsdelta", -1, wi);
- expand->lmc_forced_nstart = get_eint(inp, "lmc-forced-nstart", 0, wi);
- expand->bSymmetrizedTMatrix = (get_eeenum(inp, "symmetrized-transition-matrix", yesno_names, wi) != 0);
- expand->nstTij = get_eint(inp, "nst-transition-matrix", -1, wi);
- expand->minvarmin = get_eint(inp, "mininum-var-min", 100, wi); /*default is reasonable */
- expand->c_range = get_eint(inp, "weight-c-range", 0, wi); /* default is just C=0 */
- expand->wl_scale = get_ereal(inp, "wl-scale", 0.8, wi);
- expand->wl_ratio = get_ereal(inp, "wl-ratio", 0.8, wi);
- expand->init_wl_delta = get_ereal(inp, "init-wl-delta", 1.0, wi);
- expand->bWLoneovert = (get_eeenum(inp, "wl-oneovert", yesno_names, wi) != 0);
+ expand->lmc_seed = get_eint(inp, "lmc-seed", -1, wi);
+ expand->mc_temp = get_ereal(inp, "mc-temperature", -1, wi);
+ expand->lmc_repeats = get_eint(inp, "lmc-repeats", 1, wi);
+ expand->gibbsdeltalam = get_eint(inp, "lmc-gibbsdelta", -1, wi);
+ expand->lmc_forced_nstart = get_eint(inp, "lmc-forced-nstart", 0, wi);
+ expand->bSymmetrizedTMatrix =
+ (getEnum<Boolean>(inp, "symmetrized-transition-matrix", wi) != Boolean::No);
+ expand->nstTij = get_eint(inp, "nst-transition-matrix", -1, wi);
+ expand->minvarmin = get_eint(inp, "mininum-var-min", 100, wi); /*default is reasonable */
+ expand->c_range = get_eint(inp, "weight-c-range", 0, wi); /* default is just C=0 */
+ expand->wl_scale = get_ereal(inp, "wl-scale", 0.8, wi);
+ expand->wl_ratio = get_ereal(inp, "wl-ratio", 0.8, wi);
+ expand->init_wl_delta = get_ereal(inp, "init-wl-delta", 1.0, wi);
+ expand->bWLoneovert = (getEnum<Boolean>(inp, "wl-oneovert", wi) != Boolean::No);
}
/*! \brief Return whether an end state with the given coupling-lambda
*/
static bool couple_lambda_has_vdw_on(int couple_lambda_value)
{
- return (couple_lambda_value == ecouplamVDW ||
- couple_lambda_value == ecouplamVDWQ);
+ return (couple_lambda_value == ecouplamVDW || couple_lambda_value == ecouplamVDWQ);
}
namespace
class MdpErrorHandler : public gmx::IKeyValueTreeErrorHandler
{
- public:
- explicit MdpErrorHandler(warninp_t wi)
- : wi_(wi), mapping_(nullptr)
- {
- }
+public:
+ explicit MdpErrorHandler(warninp_t wi) : wi_(wi), mapping_(nullptr) {}
- void setBackMapping(const gmx::IKeyValueTreeBackMapping &mapping)
- {
- mapping_ = &mapping;
- }
+ void setBackMapping(const gmx::IKeyValueTreeBackMapping& mapping) { mapping_ = &mapping; }
- bool onError(gmx::UserInputError *ex, const gmx::KeyValueTreePath &context) override
- {
- ex->prependContext(gmx::formatString("Error in mdp option \"%s\":",
- getOptionName(context).c_str()));
- std::string message = gmx::formatExceptionMessageToString(*ex);
- warning_error(wi_, message.c_str());
- return true;
- }
+ bool onError(gmx::UserInputError* ex, const gmx::KeyValueTreePath& context) override
+ {
+ ex->prependContext(
+ gmx::formatString("Error in mdp option \"%s\":", getOptionName(context).c_str()));
+ std::string message = gmx::formatExceptionMessageToString(*ex);
+ warning_error(wi_, message.c_str());
+ return true;
+ }
- private:
- std::string getOptionName(const gmx::KeyValueTreePath &context)
+private:
+ std::string getOptionName(const gmx::KeyValueTreePath& context)
+ {
+ if (mapping_ != nullptr)
{
- if (mapping_ != nullptr)
- {
- gmx::KeyValueTreePath path = mapping_->originalPath(context);
- GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
- return path[0];
- }
- GMX_ASSERT(context.size() == 1, "Inconsistent context for mdp option parsing");
- return context[0];
+ gmx::KeyValueTreePath path = mapping_->originalPath(context);
+ GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
+ return path[0];
}
+ GMX_ASSERT(context.size() == 1, "Inconsistent context for mdp option parsing");
+ return context[0];
+ }
- warninp_t wi_;
- const gmx::IKeyValueTreeBackMapping *mapping_;
+ warninp_t wi_;
+ const gmx::IKeyValueTreeBackMapping* mapping_;
};
} // namespace
-void get_ir(const char *mdparin, const char *mdparout,
- gmx::MDModules *mdModules, t_inputrec *ir, t_gromppopts *opts,
- WriteMdpHeader writeMdpHeader, warninp_t wi)
+void get_ir(const char* mdparin,
+ const char* mdparout,
+ gmx::MDModules* mdModules,
+ t_inputrec* ir,
+ t_gromppopts* opts,
+ WriteMdpHeader writeMdpHeader,
+ warninp_t wi)
{
- char *dumstr[2];
- double dumdub[2][6];
- int i, j, m;
- char warn_buf[STRLEN];
- t_lambda *fep = ir->fepvals;
- t_expanded *expand = ir->expandedvals;
+ char* dumstr[2];
+ double dumdub[2][6];
+ int i, j, m;
+ char warn_buf[STRLEN];
+ t_lambda* fep = ir->fepvals.get();
+ t_expanded* expand = ir->expandedvals.get();
- const char *no_names[] = { "no", nullptr };
+ const char* no_names[] = { "no", nullptr };
init_inputrec_strings();
gmx::TextInputFile stream(mdparin);
snew(dumstr[0], STRLEN);
snew(dumstr[1], STRLEN);
- if (-1 == search_einp(inp, "cutoff-scheme"))
- {
- sprintf(warn_buf,
- "%s did not specify a value for the .mdp option "
- "\"cutoff-scheme\". As of GROMACS 2020, the Verlet scheme "
- "is the only cutoff scheme supported. This may affect your "
- "simulation if you are using an old mdp file that assumes use "
- "of the (removed) group cutoff scheme.", mdparin);
- warning_note(wi, warn_buf);
- }
-
/* ignore the following deprecated commands */
replace_inp_entry(inp, "title", nullptr);
replace_inp_entry(inp, "cpp", nullptr);
printStringNewline(&inp, "VARIOUS PREPROCESSING OPTIONS");
printStringNoNewline(&inp, "Preprocessor information: use cpp syntax.");
printStringNoNewline(&inp, "e.g.: -I/home/joe/doe -I/home/mary/roe");
- setStringEntry(&inp, "include", opts->include, nullptr);
- printStringNoNewline(&inp, "e.g.: -DPOSRES -DFLEXIBLE (note these variable names are case sensitive)");
- setStringEntry(&inp, "define", opts->define, nullptr);
+ setStringEntry(&inp, "include", opts->include, nullptr);
+ printStringNoNewline(
+ &inp, "e.g.: -DPOSRES -DFLEXIBLE (note these variable names are case sensitive)");
+ setStringEntry(&inp, "define", opts->define, nullptr);
printStringNewline(&inp, "RUN CONTROL PARAMETERS");
- ir->eI = get_eeenum(&inp, "integrator", ei_names, wi);
+ ir->eI = getEnum<IntegrationAlgorithm>(&inp, "integrator", wi);
printStringNoNewline(&inp, "Start time and timestep in ps");
ir->init_t = get_ereal(&inp, "tinit", 0.0, wi);
- ir->delta_t = get_ereal(&inp, "dt", 0.001, wi);
- ir->nsteps = get_eint64(&inp, "nsteps", 0, wi);
+ ir->delta_t = get_ereal(&inp, "dt", 0.001, wi);
+ ir->nsteps = get_eint64(&inp, "nsteps", 0, wi);
printStringNoNewline(&inp, "For exact run continuation or redoing part of a run");
- ir->init_step = get_eint64(&inp, "init-step", 0, wi);
- printStringNoNewline(&inp, "Part index is updated automatically on checkpointing (keeps files separate)");
+ ir->init_step = get_eint64(&inp, "init-step", 0, wi);
+ printStringNoNewline(
+ &inp, "Part index is updated automatically on checkpointing (keeps files separate)");
ir->simulation_part = get_eint(&inp, "simulation-part", 1, wi);
+ printStringNoNewline(&inp, "Multiple time-stepping");
+ ir->useMts = (getEnum<Boolean>(&inp, "mts", wi) != Boolean::No);
+ if (ir->useMts)
+ {
+ gmx::GromppMtsOpts& mtsOpts = opts->mtsOpts;
+ mtsOpts.numLevels = get_eint(&inp, "mts-levels", 2, wi);
+ mtsOpts.level2Forces = setStringEntry(&inp, "mts-level2-forces", "longrange-nonbonded");
+ mtsOpts.level2Factor = get_eint(&inp, "mts-level2-factor", 2, wi);
+
+ // We clear after reading without dynamics to not force the user to remove MTS mdp options
+ if (!EI_DYNAMICS(ir->eI))
+ {
+ ir->useMts = false;
+ }
+ }
printStringNoNewline(&inp, "mode for center of mass motion removal");
- ir->comm_mode = get_eeenum(&inp, "comm-mode", ecm_names, wi);
+ ir->comm_mode = getEnum<ComRemovalAlgorithm>(&inp, "comm-mode", wi);
printStringNoNewline(&inp, "number of steps for center of mass motion removal");
- ir->nstcomm = get_eint(&inp, "nstcomm", 100, wi);
+ ir->nstcomm = get_eint(&inp, "nstcomm", 100, wi);
printStringNoNewline(&inp, "group(s) for center of mass motion removal");
- setStringEntry(&inp, "comm-grps", is->vcm, nullptr);
+ setStringEntry(&inp, "comm-grps", inputrecStrings->vcm, nullptr);
printStringNewline(&inp, "LANGEVIN DYNAMICS OPTIONS");
printStringNoNewline(&inp, "Friction coefficient (amu/ps) and random seed");
- ir->bd_fric = get_ereal(&inp, "bd-fric", 0.0, wi);
- ir->ld_seed = get_eint64(&inp, "ld-seed", -1, wi);
+ ir->bd_fric = get_ereal(&inp, "bd-fric", 0.0, wi);
+ ir->ld_seed = get_eint64(&inp, "ld-seed", -1, wi);
/* Em stuff */
printStringNewline(&inp, "ENERGY MINIMIZATION OPTIONS");
printStringNoNewline(&inp, "Force tolerance and initial step-size");
- ir->em_tol = get_ereal(&inp, "emtol", 10.0, wi);
+ ir->em_tol = get_ereal(&inp, "emtol", 10.0, wi);
ir->em_stepsize = get_ereal(&inp, "emstep", 0.01, wi);
printStringNoNewline(&inp, "Max number of iterations in relax-shells");
- ir->niter = get_eint(&inp, "niter", 20, wi);
+ ir->niter = get_eint(&inp, "niter", 20, wi);
printStringNoNewline(&inp, "Step size (ps^2) for minimization of flexible constraints");
ir->fc_stepsize = get_ereal(&inp, "fcstep", 0, wi);
printStringNoNewline(&inp, "Frequency of steepest descents steps when doing CG");
ir->nstcgsteep = get_eint(&inp, "nstcgsteep", 1000, wi);
- ir->nbfgscorr = get_eint(&inp, "nbfgscorr", 10, wi);
+ ir->nbfgscorr = get_eint(&inp, "nbfgscorr", 10, wi);
printStringNewline(&inp, "TEST PARTICLE INSERTION OPTIONS");
- ir->rtpi = get_ereal(&inp, "rtpi", 0.05, wi);
+ ir->rtpi = get_ereal(&inp, "rtpi", 0.05, wi);
/* Output options */
printStringNewline(&inp, "OUTPUT CONTROL OPTIONS");
printStringNoNewline(&inp, "Output frequency for coords (x), velocities (v) and forces (f)");
- ir->nstxout = get_eint(&inp, "nstxout", 0, wi);
- ir->nstvout = get_eint(&inp, "nstvout", 0, wi);
- ir->nstfout = get_eint(&inp, "nstfout", 0, wi);
+ ir->nstxout = get_eint(&inp, "nstxout", 0, wi);
+ ir->nstvout = get_eint(&inp, "nstvout", 0, wi);
+ ir->nstfout = get_eint(&inp, "nstfout", 0, wi);
printStringNoNewline(&inp, "Output frequency for energies to log file and energy file");
ir->nstlog = get_eint(&inp, "nstlog", 1000, wi);
ir->nstcalcenergy = get_eint(&inp, "nstcalcenergy", 100, wi);
- ir->nstenergy = get_eint(&inp, "nstenergy", 1000, wi);
+ ir->nstenergy = get_eint(&inp, "nstenergy", 1000, wi);
printStringNoNewline(&inp, "Output frequency and precision for .xtc file");
- ir->nstxout_compressed = get_eint(&inp, "nstxout-compressed", 0, wi);
+ ir->nstxout_compressed = get_eint(&inp, "nstxout-compressed", 0, wi);
ir->x_compression_precision = get_ereal(&inp, "compressed-x-precision", 1000.0, wi);
printStringNoNewline(&inp, "This selects the subset of atoms for the compressed");
printStringNoNewline(&inp, "trajectory file. You can select multiple groups. By");
printStringNoNewline(&inp, "default, all atoms will be written.");
- setStringEntry(&inp, "compressed-x-grps", is->x_compressed_groups, nullptr);
+ setStringEntry(&inp, "compressed-x-grps", inputrecStrings->x_compressed_groups, nullptr);
printStringNoNewline(&inp, "Selection of energy groups");
- setStringEntry(&inp, "energygrps", is->energy, nullptr);
+ setStringEntry(&inp, "energygrps", inputrecStrings->energy, nullptr);
/* Neighbor searching */
printStringNewline(&inp, "NEIGHBORSEARCHING PARAMETERS");
- printStringNoNewline(&inp, "cut-off scheme (Verlet: particle based cut-offs, group: using charge groups)");
- ir->cutoff_scheme = get_eeenum(&inp, "cutoff-scheme", ecutscheme_names, wi);
+ printStringNoNewline(&inp, "cut-off scheme (Verlet: particle based cut-offs)");
+ ir->cutoff_scheme = getEnum<CutoffScheme>(&inp, "cutoff-scheme", wi);
printStringNoNewline(&inp, "nblist update frequency");
- ir->nstlist = get_eint(&inp, "nstlist", 10, wi);
+ ir->nstlist = get_eint(&inp, "nstlist", 10, wi);
printStringNoNewline(&inp, "Periodic boundary conditions: xyz, no, xy");
- ir->ePBC = get_eeenum(&inp, "pbc", epbc_names, wi);
- ir->bPeriodicMols = get_eeenum(&inp, "periodic-molecules", yesno_names, wi) != 0;
- printStringNoNewline(&inp, "Allowed energy error due to the Verlet buffer in kJ/mol/ps per atom,");
+ // TODO This conversion should be removed when proper std:string handling will be added to get_eeenum(...), etc.
+ std::vector<const char*> pbcTypesNamesChar;
+ for (const auto& pbcTypeName : c_pbcTypeNames)
+ {
+ pbcTypesNamesChar.push_back(pbcTypeName.c_str());
+ }
+ ir->pbcType = static_cast<PbcType>(get_eeenum(&inp, "pbc", pbcTypesNamesChar.data(), wi));
+ ir->bPeriodicMols = getEnum<Boolean>(&inp, "periodic-molecules", wi) != Boolean::No;
+ printStringNoNewline(&inp,
+ "Allowed energy error due to the Verlet buffer in kJ/mol/ps per atom,");
printStringNoNewline(&inp, "a value of -1 means: use rlist");
- ir->verletbuf_tol = get_ereal(&inp, "verlet-buffer-tolerance", 0.005, wi);
+ ir->verletbuf_tol = get_ereal(&inp, "verlet-buffer-tolerance", 0.005, wi);
printStringNoNewline(&inp, "nblist cut-off");
- ir->rlist = get_ereal(&inp, "rlist", 1.0, wi);
+ ir->rlist = get_ereal(&inp, "rlist", 1.0, wi);
printStringNoNewline(&inp, "long-range cut-off for switched potentials");
/* Electrostatics */
printStringNewline(&inp, "OPTIONS FOR ELECTROSTATICS AND VDW");
printStringNoNewline(&inp, "Method for doing electrostatics");
- ir->coulombtype = get_eeenum(&inp, "coulombtype", eel_names, wi);
- ir->coulomb_modifier = get_eeenum(&inp, "coulomb-modifier", eintmod_names, wi);
+ ir->coulombtype = getEnum<CoulombInteractionType>(&inp, "coulombtype", wi);
+ ir->coulomb_modifier = getEnum<InteractionModifiers>(&inp, "coulomb-modifier", wi);
printStringNoNewline(&inp, "cut-off lengths");
- ir->rcoulomb_switch = get_ereal(&inp, "rcoulomb-switch", 0.0, wi);
- ir->rcoulomb = get_ereal(&inp, "rcoulomb", 1.0, wi);
+ ir->rcoulomb_switch = get_ereal(&inp, "rcoulomb-switch", 0.0, wi);
+ ir->rcoulomb = get_ereal(&inp, "rcoulomb", 1.0, wi);
printStringNoNewline(&inp, "Relative dielectric constant for the medium and the reaction field");
- ir->epsilon_r = get_ereal(&inp, "epsilon-r", 1.0, wi);
+ ir->epsilon_r = get_ereal(&inp, "epsilon-r", 1.0, wi);
ir->epsilon_rf = get_ereal(&inp, "epsilon-rf", 0.0, wi);
printStringNoNewline(&inp, "Method for doing Van der Waals");
- ir->vdwtype = get_eeenum(&inp, "vdw-type", evdw_names, wi);
- ir->vdw_modifier = get_eeenum(&inp, "vdw-modifier", eintmod_names, wi);
+ ir->vdwtype = getEnum<VanDerWaalsType>(&inp, "vdw-type", wi);
+ ir->vdw_modifier = getEnum<InteractionModifiers>(&inp, "vdw-modifier", wi);
printStringNoNewline(&inp, "cut-off lengths");
- ir->rvdw_switch = get_ereal(&inp, "rvdw-switch", 0.0, wi);
- ir->rvdw = get_ereal(&inp, "rvdw", 1.0, wi);
+ ir->rvdw_switch = get_ereal(&inp, "rvdw-switch", 0.0, wi);
+ ir->rvdw = get_ereal(&inp, "rvdw", 1.0, wi);
printStringNoNewline(&inp, "Apply long range dispersion corrections for Energy and Pressure");
- ir->eDispCorr = get_eeenum(&inp, "DispCorr", edispc_names, wi);
+ ir->eDispCorr = getEnum<DispersionCorrectionType>(&inp, "DispCorr", wi);
printStringNoNewline(&inp, "Extension of the potential lookup tables beyond the cut-off");
ir->tabext = get_ereal(&inp, "table-extension", 1.0, wi);
printStringNoNewline(&inp, "Separate tables between energy group pairs");
- setStringEntry(&inp, "energygrp-table", is->egptable, nullptr);
+ setStringEntry(&inp, "energygrp-table", inputrecStrings->egptable, nullptr);
printStringNoNewline(&inp, "Spacing for the PME/PPPM FFT grid");
ir->fourier_spacing = get_ereal(&inp, "fourierspacing", 0.12, wi);
printStringNoNewline(&inp, "FFT grid size, when a value is 0 fourierspacing will be used");
- ir->nkx = get_eint(&inp, "fourier-nx", 0, wi);
- ir->nky = get_eint(&inp, "fourier-ny", 0, wi);
- ir->nkz = get_eint(&inp, "fourier-nz", 0, wi);
+ ir->nkx = get_eint(&inp, "fourier-nx", 0, wi);
+ ir->nky = get_eint(&inp, "fourier-ny", 0, wi);
+ ir->nkz = get_eint(&inp, "fourier-nz", 0, wi);
printStringNoNewline(&inp, "EWALD/PME/PPPM parameters");
- ir->pme_order = get_eint(&inp, "pme-order", 4, wi);
+ ir->pme_order = get_eint(&inp, "pme-order", 4, wi);
ir->ewald_rtol = get_ereal(&inp, "ewald-rtol", 0.00001, wi);
ir->ewald_rtol_lj = get_ereal(&inp, "ewald-rtol-lj", 0.001, wi);
- ir->ljpme_combination_rule = get_eeenum(&inp, "lj-pme-comb-rule", eljpme_names, wi);
- ir->ewald_geometry = get_eeenum(&inp, "ewald-geometry", eewg_names, wi);
+ ir->ljpme_combination_rule = getEnum<LongRangeVdW>(&inp, "lj-pme-comb-rule", wi);
+ ir->ewald_geometry = getEnum<EwaldGeometry>(&inp, "ewald-geometry", wi);
ir->epsilon_surface = get_ereal(&inp, "epsilon-surface", 0.0, wi);
/* Implicit solvation is no longer supported, but we need grompp
/* Coupling stuff */
printStringNewline(&inp, "OPTIONS FOR WEAK COUPLING ALGORITHMS");
printStringNoNewline(&inp, "Temperature coupling");
- ir->etc = get_eeenum(&inp, "tcoupl", etcoupl_names, wi);
- ir->nsttcouple = get_eint(&inp, "nsttcouple", -1, wi);
+ ir->etc = getEnum<TemperatureCoupling>(&inp, "tcoupl", wi);
+ ir->nsttcouple = get_eint(&inp, "nsttcouple", -1, wi);
ir->opts.nhchainlength = get_eint(&inp, "nh-chain-length", 10, wi);
- ir->bPrintNHChains = (get_eeenum(&inp, "print-nose-hoover-chain-variables", yesno_names, wi) != 0);
+ ir->bPrintNHChains = (getEnum<Boolean>(&inp, "print-nose-hoover-chain-variables", wi) != Boolean::No);
printStringNoNewline(&inp, "Groups to couple separately");
- setStringEntry(&inp, "tc-grps", is->tcgrps, nullptr);
+ setStringEntry(&inp, "tc-grps", inputrecStrings->tcgrps, nullptr);
printStringNoNewline(&inp, "Time constant (ps) and reference temperature (K)");
- setStringEntry(&inp, "tau-t", is->tau_t, nullptr);
- setStringEntry(&inp, "ref-t", is->ref_t, nullptr);
+ setStringEntry(&inp, "tau-t", inputrecStrings->tau_t, nullptr);
+ setStringEntry(&inp, "ref-t", inputrecStrings->ref_t, nullptr);
printStringNoNewline(&inp, "pressure coupling");
- ir->epc = get_eeenum(&inp, "pcoupl", epcoupl_names, wi);
- ir->epct = get_eeenum(&inp, "pcoupltype", epcoupltype_names, wi);
- ir->nstpcouple = get_eint(&inp, "nstpcouple", -1, wi);
+ ir->epc = getEnum<PressureCoupling>(&inp, "pcoupl", wi);
+ ir->epct = getEnum<PressureCouplingType>(&inp, "pcoupltype", wi);
+ ir->nstpcouple = get_eint(&inp, "nstpcouple", -1, wi);
printStringNoNewline(&inp, "Time constant (ps), compressibility (1/bar) and reference P (bar)");
- ir->tau_p = get_ereal(&inp, "tau-p", 1.0, wi);
- setStringEntry(&inp, "compressibility", dumstr[0], nullptr);
- setStringEntry(&inp, "ref-p", dumstr[1], nullptr);
+ ir->tau_p = get_ereal(&inp, "tau-p", 1.0, wi);
+ setStringEntry(&inp, "compressibility", dumstr[0], nullptr);
+ setStringEntry(&inp, "ref-p", dumstr[1], nullptr);
printStringNoNewline(&inp, "Scaling of reference coordinates, No, All or COM");
- ir->refcoord_scaling = get_eeenum(&inp, "refcoord-scaling", erefscaling_names, wi);
+ ir->refcoord_scaling = getEnum<RefCoordScaling>(&inp, "refcoord-scaling", wi);
/* QMMM */
printStringNewline(&inp, "OPTIONS FOR QMMM calculations");
- ir->bQMMM = (get_eeenum(&inp, "QMMM", yesno_names, wi) != 0);
- printStringNoNewline(&inp, "Groups treated Quantum Mechanically");
- setStringEntry(&inp, "QMMM-grps", is->QMMM, nullptr);
- printStringNoNewline(&inp, "QM method");
- setStringEntry(&inp, "QMmethod", is->QMmethod, nullptr);
- printStringNoNewline(&inp, "QMMM scheme");
- ir->QMMMscheme = get_eeenum(&inp, "QMMMscheme", eQMMMscheme_names, wi);
- printStringNoNewline(&inp, "QM basisset");
- setStringEntry(&inp, "QMbasis", is->QMbasis, nullptr);
- printStringNoNewline(&inp, "QM charge");
- setStringEntry(&inp, "QMcharge", is->QMcharge, nullptr);
- printStringNoNewline(&inp, "QM multiplicity");
- setStringEntry(&inp, "QMmult", is->QMmult, nullptr);
- printStringNoNewline(&inp, "Surface Hopping");
- setStringEntry(&inp, "SH", is->bSH, nullptr);
- printStringNoNewline(&inp, "CAS space options");
- setStringEntry(&inp, "CASorbitals", is->CASorbitals, nullptr);
- setStringEntry(&inp, "CASelectrons", is->CASelectrons, nullptr);
- setStringEntry(&inp, "SAon", is->SAon, nullptr);
- setStringEntry(&inp, "SAoff", is->SAoff, nullptr);
- setStringEntry(&inp, "SAsteps", is->SAsteps, nullptr);
- printStringNoNewline(&inp, "Scale factor for MM charges");
- ir->scalefactor = get_ereal(&inp, "MMChargeScaleFactor", 1.0, wi);
+ ir->bQMMM = (getEnum<Boolean>(&inp, "QMMM", wi) != Boolean::No);
+ printStringNoNewline(&inp, "Groups treated with MiMiC");
+ setStringEntry(&inp, "QMMM-grps", inputrecStrings->QMMM, nullptr);
/* Simulated annealing */
printStringNewline(&inp, "SIMULATED ANNEALING");
printStringNoNewline(&inp, "Type of annealing for each temperature group (no/single/periodic)");
- setStringEntry(&inp, "annealing", is->anneal, nullptr);
- printStringNoNewline(&inp, "Number of time points to use for specifying annealing in each group");
- setStringEntry(&inp, "annealing-npoints", is->anneal_npoints, nullptr);
+ setStringEntry(&inp, "annealing", inputrecStrings->anneal, nullptr);
+ printStringNoNewline(&inp,
+ "Number of time points to use for specifying annealing in each group");
+ setStringEntry(&inp, "annealing-npoints", inputrecStrings->anneal_npoints, nullptr);
printStringNoNewline(&inp, "List of times at the annealing points for each group");
- setStringEntry(&inp, "annealing-time", is->anneal_time, nullptr);
+ setStringEntry(&inp, "annealing-time", inputrecStrings->anneal_time, nullptr);
printStringNoNewline(&inp, "Temp. at each annealing point, for each group.");
- setStringEntry(&inp, "annealing-temp", is->anneal_temp, nullptr);
+ setStringEntry(&inp, "annealing-temp", inputrecStrings->anneal_temp, nullptr);
/* Startup run */
printStringNewline(&inp, "GENERATE VELOCITIES FOR STARTUP RUN");
- opts->bGenVel = (get_eeenum(&inp, "gen-vel", yesno_names, wi) != 0);
- opts->tempi = get_ereal(&inp, "gen-temp", 300.0, wi);
- opts->seed = get_eint(&inp, "gen-seed", -1, wi);
+ opts->bGenVel = (getEnum<Boolean>(&inp, "gen-vel", wi) != Boolean::No);
+ opts->tempi = get_ereal(&inp, "gen-temp", 300.0, wi);
+ opts->seed = get_eint(&inp, "gen-seed", -1, wi);
/* Shake stuff */
printStringNewline(&inp, "OPTIONS FOR BONDS");
- opts->nshake = get_eeenum(&inp, "constraints", constraints, wi);
+ opts->nshake = get_eeenum(&inp, "constraints", constraints, wi);
printStringNoNewline(&inp, "Type of constraint algorithm");
- ir->eConstrAlg = get_eeenum(&inp, "constraint-algorithm", econstr_names, wi);
+ ir->eConstrAlg = getEnum<ConstraintAlgorithm>(&inp, "constraint-algorithm", wi);
printStringNoNewline(&inp, "Do not constrain the start configuration");
- ir->bContinuation = (get_eeenum(&inp, "continuation", yesno_names, wi) != 0);
- printStringNoNewline(&inp, "Use successive overrelaxation to reduce the number of shake iterations");
- ir->bShakeSOR = (get_eeenum(&inp, "Shake-SOR", yesno_names, wi) != 0);
+ ir->bContinuation = (getEnum<Boolean>(&inp, "continuation", wi) != Boolean::No);
+ printStringNoNewline(&inp,
+ "Use successive overrelaxation to reduce the number of shake iterations");
+ ir->bShakeSOR = (getEnum<Boolean>(&inp, "Shake-SOR", wi) != Boolean::No);
printStringNoNewline(&inp, "Relative tolerance of shake");
ir->shake_tol = get_ereal(&inp, "shake-tol", 0.0001, wi);
printStringNoNewline(&inp, "Highest order in the expansion of the constraint coupling matrix");
printStringNoNewline(&inp, "rotates over more degrees than");
ir->LincsWarnAngle = get_ereal(&inp, "lincs-warnangle", 30.0, wi);
printStringNoNewline(&inp, "Convert harmonic bonds to morse potentials");
- opts->bMorse = (get_eeenum(&inp, "morse", yesno_names, wi) != 0);
+ opts->bMorse = (getEnum<Boolean>(&inp, "morse", wi) != Boolean::No);
/* Energy group exclusions */
printStringNewline(&inp, "ENERGY GROUP EXCLUSIONS");
- printStringNoNewline(&inp, "Pairs of energy groups for which all non-bonded interactions are excluded");
- setStringEntry(&inp, "energygrp-excl", is->egpexcl, nullptr);
+ printStringNoNewline(
+ &inp, "Pairs of energy groups for which all non-bonded interactions are excluded");
+ setStringEntry(&inp, "energygrp-excl", inputrecStrings->egpexcl, nullptr);
/* Walls */
printStringNewline(&inp, "WALLS");
- printStringNoNewline(&inp, "Number of walls, type, atom types, densities and box-z scale factor for Ewald");
+ printStringNoNewline(
+ &inp, "Number of walls, type, atom types, densities and box-z scale factor for Ewald");
ir->nwall = get_eint(&inp, "nwall", 0, wi);
- ir->wall_type = get_eeenum(&inp, "wall-type", ewt_names, wi);
+ ir->wall_type = getEnum<WallType>(&inp, "wall-type", wi);
ir->wall_r_linpot = get_ereal(&inp, "wall-r-linpot", -1, wi);
- setStringEntry(&inp, "wall-atomtype", is->wall_atomtype, nullptr);
- setStringEntry(&inp, "wall-density", is->wall_density, nullptr);
+ setStringEntry(&inp, "wall-atomtype", inputrecStrings->wall_atomtype, nullptr);
+ setStringEntry(&inp, "wall-density", inputrecStrings->wall_density, nullptr);
ir->wall_ewald_zfac = get_ereal(&inp, "wall-ewald-zfac", 3, wi);
/* COM pulling */
printStringNewline(&inp, "COM PULLING");
- ir->bPull = (get_eeenum(&inp, "pull", yesno_names, wi) != 0);
+ ir->bPull = (getEnum<Boolean>(&inp, "pull", wi) != Boolean::No);
if (ir->bPull)
{
- snew(ir->pull, 1);
- is->pull_grp = read_pullparams(&inp, ir->pull, wi);
+ ir->pull = std::make_unique<pull_params_t>();
+ inputrecStrings->pullGroupNames = read_pullparams(&inp, ir->pull.get(), wi);
+
+ if (ir->useMts)
+ {
+ for (int c = 0; c < ir->pull->ncoord; c++)
+ {
+ if (ir->pull->coord[c].eType == PullingAlgorithm::Constraint)
+ {
+ warning_error(wi,
+ "Constraint COM pulling is not supported in combination with "
+ "multiple time stepping");
+ break;
+ }
+ }
+ }
}
/* AWH biasing
- NOTE: needs COM pulling input */
+ NOTE: needs COM pulling or free energy input */
printStringNewline(&inp, "AWH biasing");
- ir->bDoAwh = (get_eeenum(&inp, "awh", yesno_names, wi) != 0);
+ ir->bDoAwh = (getEnum<Boolean>(&inp, "awh", wi) != Boolean::No);
if (ir->bDoAwh)
{
- if (ir->bPull)
- {
- ir->awhParams = gmx::readAndCheckAwhParams(&inp, ir, wi);
- }
- else
- {
- gmx_fatal(FARGS, "AWH biasing is only compatible with COM pulling turned on");
- }
+ ir->awhParams = std::make_unique<gmx::AwhParams>(&inp, wi);
}
/* Enforced rotation */
printStringNewline(&inp, "ENFORCED ROTATION");
printStringNoNewline(&inp, "Enforced rotation: No or Yes");
- ir->bRot = (get_eeenum(&inp, "rotation", yesno_names, wi) != 0);
+ ir->bRot = (getEnum<Boolean>(&inp, "rotation", wi) != Boolean::No);
if (ir->bRot)
{
snew(ir->rot, 1);
- is->rot_grp = read_rotparams(&inp, ir->rot, wi);
+ inputrecStrings->rotateGroupNames = read_rotparams(&inp, ir->rot, wi);
}
/* Interactive MD */
ir->bIMD = FALSE;
printStringNewline(&inp, "Group to display and/or manipulate in interactive MD session");
- setStringEntry(&inp, "IMD-group", is->imd_grp, nullptr);
- if (is->imd_grp[0] != '\0')
+ setStringEntry(&inp, "IMD-group", inputrecStrings->imd_grp, nullptr);
+ if (inputrecStrings->imd_grp[0] != '\0')
{
snew(ir->imd, 1);
ir->bIMD = TRUE;
/* Refinement */
printStringNewline(&inp, "NMR refinement stuff");
printStringNoNewline(&inp, "Distance restraints type: No, Simple or Ensemble");
- ir->eDisre = get_eeenum(&inp, "disre", edisre_names, wi);
- printStringNoNewline(&inp, "Force weighting of pairs in one distance restraint: Conservative or Equal");
- ir->eDisreWeighting = get_eeenum(&inp, "disre-weighting", edisreweighting_names, wi);
+ ir->eDisre = getEnum<DistanceRestraintRefinement>(&inp, "disre", wi);
+ printStringNoNewline(
+ &inp, "Force weighting of pairs in one distance restraint: Conservative or Equal");
+ ir->eDisreWeighting = getEnum<DistanceRestraintWeighting>(&inp, "disre-weighting", wi);
printStringNoNewline(&inp, "Use sqrt of the time averaged times the instantaneous violation");
- ir->bDisreMixed = (get_eeenum(&inp, "disre-mixed", yesno_names, wi) != 0);
- ir->dr_fc = get_ereal(&inp, "disre-fc", 1000.0, wi);
+ ir->bDisreMixed = (getEnum<Boolean>(&inp, "disre-mixed", wi) != Boolean::No);
+ ir->dr_fc = get_ereal(&inp, "disre-fc", 1000.0, wi);
ir->dr_tau = get_ereal(&inp, "disre-tau", 0.0, wi);
printStringNoNewline(&inp, "Output frequency for pair distances to energy file");
ir->nstdisreout = get_eint(&inp, "nstdisreout", 100, wi);
printStringNoNewline(&inp, "Orientation restraints: No or Yes");
- opts->bOrire = (get_eeenum(&inp, "orire", yesno_names, wi) != 0);
+ opts->bOrire = (getEnum<Boolean>(&inp, "orire", wi) != Boolean::No);
printStringNoNewline(&inp, "Orientation restraints force constant and tau for time averaging");
- ir->orires_fc = get_ereal(&inp, "orire-fc", 0.0, wi);
+ ir->orires_fc = get_ereal(&inp, "orire-fc", 0.0, wi);
ir->orires_tau = get_ereal(&inp, "orire-tau", 0.0, wi);
- setStringEntry(&inp, "orire-fitgrp", is->orirefitgrp, nullptr);
+ setStringEntry(&inp, "orire-fitgrp", inputrecStrings->orirefitgrp, nullptr);
printStringNoNewline(&inp, "Output frequency for trace(SD) and S to energy file");
ir->nstorireout = get_eint(&inp, "nstorireout", 100, wi);
/* free energy variables */
printStringNewline(&inp, "Free energy variables");
- ir->efep = get_eeenum(&inp, "free-energy", efep_names, wi);
- setStringEntry(&inp, "couple-moltype", is->couple_moltype, nullptr);
+ ir->efep = getEnum<FreeEnergyPerturbationType>(&inp, "free-energy", wi);
+ setStringEntry(&inp, "couple-moltype", inputrecStrings->couple_moltype, nullptr);
opts->couple_lam0 = get_eeenum(&inp, "couple-lambda0", couple_lam, wi);
opts->couple_lam1 = get_eeenum(&inp, "couple-lambda1", couple_lam, wi);
- opts->bCoupleIntra = (get_eeenum(&inp, "couple-intramol", yesno_names, wi) != 0);
+ opts->bCoupleIntra = (getEnum<Boolean>(&inp, "couple-intramol", wi) != Boolean::No);
- fep->init_lambda = get_ereal(&inp, "init-lambda", -1, wi); /* start with -1 so
- we can recognize if
- it was not entered */
+ fep->init_lambda = get_ereal(&inp, "init-lambda", -1, wi); /* start with -1 so
+ we can recognize if
+ it was not entered */
fep->init_fep_state = get_eint(&inp, "init-lambda-state", -1, wi);
fep->delta_lambda = get_ereal(&inp, "delta-lambda", 0.0, wi);
fep->nstdhdl = get_eint(&inp, "nstdhdl", 50, wi);
- setStringEntry(&inp, "fep-lambdas", is->fep_lambda[efptFEP], nullptr);
- setStringEntry(&inp, "mass-lambdas", is->fep_lambda[efptMASS], nullptr);
- setStringEntry(&inp, "coul-lambdas", is->fep_lambda[efptCOUL], nullptr);
- setStringEntry(&inp, "vdw-lambdas", is->fep_lambda[efptVDW], nullptr);
- setStringEntry(&inp, "bonded-lambdas", is->fep_lambda[efptBONDED], nullptr);
- setStringEntry(&inp, "restraint-lambdas", is->fep_lambda[efptRESTRAINT], nullptr);
- setStringEntry(&inp, "temperature-lambdas", is->fep_lambda[efptTEMPERATURE], nullptr);
+ inputrecStrings->fep_lambda[FreeEnergyPerturbationCouplingType::Fep] =
+ setStringEntry(&inp, "fep-lambdas", "");
+ inputrecStrings->fep_lambda[FreeEnergyPerturbationCouplingType::Mass] =
+ setStringEntry(&inp, "mass-lambdas", "");
+ inputrecStrings->fep_lambda[FreeEnergyPerturbationCouplingType::Coul] =
+ setStringEntry(&inp, "coul-lambdas", "");
+ inputrecStrings->fep_lambda[FreeEnergyPerturbationCouplingType::Vdw] =
+ setStringEntry(&inp, "vdw-lambdas", "");
+ inputrecStrings->fep_lambda[FreeEnergyPerturbationCouplingType::Bonded] =
+ setStringEntry(&inp, "bonded-lambdas", "");
+ inputrecStrings->fep_lambda[FreeEnergyPerturbationCouplingType::Restraint] =
+ setStringEntry(&inp, "restraint-lambdas", "");
+ inputrecStrings->fep_lambda[FreeEnergyPerturbationCouplingType::Temperature] =
+ setStringEntry(&inp, "temperature-lambdas", "");
fep->lambda_neighbors = get_eint(&inp, "calc-lambda-neighbors", 1, wi);
- setStringEntry(&inp, "init-lambda-weights", is->lambda_weights, nullptr);
- fep->edHdLPrintEnergy = get_eeenum(&inp, "dhdl-print-energy", edHdLPrintEnergy_names, wi);
- fep->sc_alpha = get_ereal(&inp, "sc-alpha", 0.0, wi);
- fep->sc_power = get_eint(&inp, "sc-power", 1, wi);
- fep->sc_r_power = get_ereal(&inp, "sc-r-power", 6.0, wi);
- fep->sc_sigma = get_ereal(&inp, "sc-sigma", 0.3, wi);
- fep->bScCoul = (get_eeenum(&inp, "sc-coul", yesno_names, wi) != 0);
- fep->dh_hist_size = get_eint(&inp, "dh_hist_size", 0, wi);
- fep->dh_hist_spacing = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
- fep->separate_dhdl_file = get_eeenum(&inp, "separate-dhdl-file", separate_dhdl_file_names, wi);
- fep->dhdl_derivatives = get_eeenum(&inp, "dhdl-derivatives", dhdl_derivatives_names, wi);
- fep->dh_hist_size = get_eint(&inp, "dh_hist_size", 0, wi);
- fep->dh_hist_spacing = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
+ setStringEntry(&inp, "init-lambda-weights", inputrecStrings->lambda_weights, nullptr);
+ fep->edHdLPrintEnergy = getEnum<FreeEnergyPrintEnergy>(&inp, "dhdl-print-energy", wi);
+ fep->softcoreFunction = getEnum<SoftcoreType>(&inp, "sc-function", wi);
+ fep->sc_alpha = get_ereal(&inp, "sc-alpha", 0.0, wi);
+ fep->sc_power = get_eint(&inp, "sc-power", 1, wi);
+ fep->sc_r_power = get_ereal(&inp, "sc-r-power", 6.0, wi);
+ fep->sc_sigma = get_ereal(&inp, "sc-sigma", 0.3, wi);
+ fep->bScCoul = (getEnum<Boolean>(&inp, "sc-coul", wi) != Boolean::No);
+ fep->scGapsysScaleLinpointLJ = get_ereal(&inp, "sc-gapsys-scale-linpoint-lj", 0.85, wi);
+ fep->scGapsysScaleLinpointQ = get_ereal(&inp, "sc-gapsys-scale-linpoint-q", 0.3, wi);
+ fep->scGapsysSigmaLJ = get_ereal(&inp, "sc-gapsys-sigma-lj", 0.3, wi);
+ fep->dh_hist_size = get_eint(&inp, "dh_hist_size", 0, wi);
+ fep->dh_hist_spacing = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
+ fep->separate_dhdl_file = getEnum<SeparateDhdlFile>(&inp, "separate-dhdl-file", wi);
+ fep->dhdl_derivatives = getEnum<DhDlDerivativeCalculation>(&inp, "dhdl-derivatives", wi);
+ fep->dh_hist_size = get_eint(&inp, "dh_hist_size", 0, wi);
+ fep->dh_hist_spacing = get_ereal(&inp, "dh_hist_spacing", 0.1, wi);
/* Non-equilibrium MD stuff */
printStringNewline(&inp, "Non-equilibrium MD stuff");
- setStringEntry(&inp, "acc-grps", is->accgrps, nullptr);
- setStringEntry(&inp, "accelerate", is->acc, nullptr);
- setStringEntry(&inp, "freezegrps", is->freeze, nullptr);
- setStringEntry(&inp, "freezedim", is->frdim, nullptr);
+ setStringEntry(&inp, "freezegrps", inputrecStrings->freeze, nullptr);
+ setStringEntry(&inp, "freezedim", inputrecStrings->frdim, nullptr);
ir->cos_accel = get_ereal(&inp, "cos-acceleration", 0, wi);
- setStringEntry(&inp, "deform", is->deform, nullptr);
+ setStringEntry(&inp, "deform", inputrecStrings->deform, nullptr);
/* simulated tempering variables */
printStringNewline(&inp, "simulated tempering variables");
- ir->bSimTemp = (get_eeenum(&inp, "simulated-tempering", yesno_names, wi) != 0);
- ir->simtempvals->eSimTempScale = get_eeenum(&inp, "simulated-tempering-scaling", esimtemp_names, wi);
- ir->simtempvals->simtemp_low = get_ereal(&inp, "sim-temp-low", 300.0, wi);
- ir->simtempvals->simtemp_high = get_ereal(&inp, "sim-temp-high", 300.0, wi);
+ ir->bSimTemp = (getEnum<Boolean>(&inp, "simulated-tempering", wi) != Boolean::No);
+ ir->simtempvals->eSimTempScale = getEnum<SimulatedTempering>(&inp, "simulated-tempering-scaling", wi);
+ ir->simtempvals->simtemp_low = get_ereal(&inp, "sim-temp-low", 300.0, wi);
+ ir->simtempvals->simtemp_high = get_ereal(&inp, "sim-temp-high", 300.0, wi);
/* expanded ensemble variables */
- if (ir->efep == efepEXPANDED || ir->bSimTemp)
+ if (ir->efep == FreeEnergyPerturbationType::Expanded || ir->bSimTemp)
{
read_expandedparams(&inp, expand, wi);
}
{
gmx::KeyValueTreeObject convertedValues = flatKeyValueTreeFromInpFile(inp);
gmx::KeyValueTreeTransformer transform;
- transform.rules()->addRule()
- .keyMatchType("/", gmx::StringCompareType::CaseAndDashInsensitive);
+ transform.rules()->addRule().keyMatchType("/", gmx::StringCompareType::CaseAndDashInsensitive);
mdModules->initMdpTransform(transform.rules());
- for (const auto &path : transform.mappedPaths())
+ for (const auto& path : transform.mappedPaths())
{
GMX_ASSERT(path.size() == 1, "Inconsistent mapping back to mdp options");
mark_einp_set(inp, path[0].c_str());
}
- MdpErrorHandler errorHandler(wi);
- auto result
- = transform.transform(convertedValues, &errorHandler);
- ir->params = new gmx::KeyValueTreeObject(result.object());
+ MdpErrorHandler errorHandler(wi);
+ auto result = transform.transform(convertedValues, &errorHandler);
+ ir->params = new gmx::KeyValueTreeObject(result.object());
mdModules->adjustInputrecBasedOnModules(ir);
errorHandler.setBackMapping(result.backMapping());
mdModules->assignOptionsToModules(*ir->params, &errorHandler);
}
/* Ion/water position swapping ("computational electrophysiology") */
- printStringNewline(&inp, "Ion/water position swapping for computational electrophysiology setups");
+ printStringNewline(&inp,
+ "Ion/water position swapping for computational electrophysiology setups");
printStringNoNewline(&inp, "Swap positions along direction: no, X, Y, Z");
- ir->eSwapCoords = get_eeenum(&inp, "swapcoords", eSwapTypes_names, wi);
- if (ir->eSwapCoords != eswapNO)
+ ir->eSwapCoords = getEnum<SwapType>(&inp, "swapcoords", wi);
+ if (ir->eSwapCoords != SwapType::No)
{
char buf[STRLEN];
int nIonTypes;
{
warning_error(wi, "You need to provide at least one ion type for position exchanges.");
}
- ir->swap->ngrp = nIonTypes + eSwapFixedGrpNR;
+ ir->swap->ngrp = nIonTypes + static_cast<int>(SwapGroupSplittingType::Count);
snew(ir->swap->grp, ir->swap->ngrp);
for (i = 0; i < ir->swap->ngrp; i++)
{
snew(ir->swap->grp[i].molname, STRLEN);
}
- printStringNoNewline(&inp, "Two index groups that contain the compartment-partitioning atoms");
- setStringEntry(&inp, "split-group0", ir->swap->grp[eGrpSplit0].molname, nullptr);
- setStringEntry(&inp, "split-group1", ir->swap->grp[eGrpSplit1].molname, nullptr);
- printStringNoNewline(&inp, "Use center of mass of split groups (yes/no), otherwise center of geometry is used");
- ir->swap->massw_split[0] = (get_eeenum(&inp, "massw-split0", yesno_names, wi) != 0);
- ir->swap->massw_split[1] = (get_eeenum(&inp, "massw-split1", yesno_names, wi) != 0);
+ printStringNoNewline(&inp,
+ "Two index groups that contain the compartment-partitioning atoms");
+ setStringEntry(&inp,
+ "split-group0",
+ ir->swap->grp[static_cast<int>(SwapGroupSplittingType::Split0)].molname,
+ nullptr);
+ setStringEntry(&inp,
+ "split-group1",
+ ir->swap->grp[static_cast<int>(SwapGroupSplittingType::Split1)].molname,
+ nullptr);
+ printStringNoNewline(&inp,
+ "Use center of mass of split groups (yes/no), otherwise center of "
+ "geometry is used");
+ ir->swap->massw_split[0] = (getEnum<Boolean>(&inp, "massw-split0", wi) != Boolean::No);
+ ir->swap->massw_split[1] = (getEnum<Boolean>(&inp, "massw-split1", wi) != Boolean::No);
printStringNoNewline(&inp, "Name of solvent molecules");
- setStringEntry(&inp, "solvent-group", ir->swap->grp[eGrpSolvent].molname, nullptr);
-
- printStringNoNewline(&inp, "Split cylinder: radius, upper and lower extension (nm) (this will define the channels)");
- printStringNoNewline(&inp, "Note that the split cylinder settings do not have an influence on the swapping protocol,");
- printStringNoNewline(&inp, "however, if correctly defined, the permeation events are recorded per channel");
+ setStringEntry(&inp,
+ "solvent-group",
+ ir->swap->grp[static_cast<int>(SwapGroupSplittingType::Solvent)].molname,
+ nullptr);
+
+ printStringNoNewline(&inp,
+ "Split cylinder: radius, upper and lower extension (nm) (this will "
+ "define the channels)");
+ printStringNoNewline(&inp,
+ "Note that the split cylinder settings do not have an influence on "
+ "the swapping protocol,");
+ printStringNoNewline(
+ &inp,
+ "however, if correctly defined, the permeation events are recorded per channel");
ir->swap->cyl0r = get_ereal(&inp, "cyl0-r", 2.0, wi);
ir->swap->cyl0u = get_ereal(&inp, "cyl0-up", 1.0, wi);
ir->swap->cyl0l = get_ereal(&inp, "cyl0-down", 1.0, wi);
ir->swap->cyl1u = get_ereal(&inp, "cyl1-up", 1.0, wi);
ir->swap->cyl1l = get_ereal(&inp, "cyl1-down", 1.0, wi);
- printStringNoNewline(&inp, "Average the number of ions per compartment over these many swap attempt steps");
+ printStringNoNewline(
+ &inp,
+ "Average the number of ions per compartment over these many swap attempt steps");
ir->swap->nAverage = get_eint(&inp, "coupl-steps", 10, wi);
- printStringNoNewline(&inp, "Names of the ion types that can be exchanged with solvent molecules,");
- printStringNoNewline(&inp, "and the requested number of ions of this type in compartments A and B");
+ printStringNoNewline(
+ &inp, "Names of the ion types that can be exchanged with solvent molecules,");
+ printStringNoNewline(
+ &inp, "and the requested number of ions of this type in compartments A and B");
printStringNoNewline(&inp, "-1 means fix the numbers as found in step 0");
for (i = 0; i < nIonTypes; i++)
{
- int ig = eSwapFixedGrpNR + i;
+ int ig = static_cast<int>(SwapGroupSplittingType::Count) + i;
sprintf(buf, "iontype%d-name", i);
setStringEntry(&inp, buf, ir->swap->grp[ig].molname, nullptr);
ir->swap->grp[ig].nmolReq[1] = get_eint(&inp, buf, -1, wi);
}
- printStringNoNewline(&inp, "By default (i.e. bulk offset = 0.0), ion/water exchanges happen between layers");
- printStringNoNewline(&inp, "at maximum distance (= bulk concentration) to the split group layers. However,");
- printStringNoNewline(&inp, "an offset b (-1.0 < b < +1.0) can be specified to offset the bulk layer from the middle at 0.0");
- printStringNoNewline(&inp, "towards one of the compartment-partitioning layers (at +/- 1.0).");
+ printStringNoNewline(
+ &inp,
+ "By default (i.e. bulk offset = 0.0), ion/water exchanges happen between layers");
+ printStringNoNewline(
+ &inp,
+ "at maximum distance (= bulk concentration) to the split group layers. However,");
+ printStringNoNewline(&inp,
+ "an offset b (-1.0 < b < +1.0) can be specified to offset the bulk "
+ "layer from the middle at 0.0");
+ printStringNoNewline(&inp,
+ "towards one of the compartment-partitioning layers (at +/- 1.0).");
ir->swap->bulkOffset[0] = get_ereal(&inp, "bulk-offsetA", 0.0, wi);
ir->swap->bulkOffset[1] = get_ereal(&inp, "bulk-offsetB", 0.0, wi);
if (!(ir->swap->bulkOffset[0] > -1.0 && ir->swap->bulkOffset[0] < 1.0)
- || !(ir->swap->bulkOffset[1] > -1.0 && ir->swap->bulkOffset[1] < 1.0) )
+ || !(ir->swap->bulkOffset[1] > -1.0 && ir->swap->bulkOffset[1] < 1.0))
{
warning_error(wi, "Bulk layer offsets must be > -1.0 and < 1.0 !");
}
- printStringNoNewline(&inp, "Start to swap ions if threshold difference to requested count is reached");
+ printStringNoNewline(
+ &inp, "Start to swap ions if threshold difference to requested count is reached");
ir->swap->threshold = get_ereal(&inp, "threshold", 1.0, wi);
}
/* User defined thingies */
printStringNewline(&inp, "User defined thingies");
- setStringEntry(&inp, "user1-grps", is->user1, nullptr);
- setStringEntry(&inp, "user2-grps", is->user2, nullptr);
- ir->userint1 = get_eint(&inp, "userint1", 0, wi);
- ir->userint2 = get_eint(&inp, "userint2", 0, wi);
- ir->userint3 = get_eint(&inp, "userint3", 0, wi);
- ir->userint4 = get_eint(&inp, "userint4", 0, wi);
- ir->userreal1 = get_ereal(&inp, "userreal1", 0, wi);
- ir->userreal2 = get_ereal(&inp, "userreal2", 0, wi);
- ir->userreal3 = get_ereal(&inp, "userreal3", 0, wi);
- ir->userreal4 = get_ereal(&inp, "userreal4", 0, wi);
+ setStringEntry(&inp, "user1-grps", inputrecStrings->user1, nullptr);
+ setStringEntry(&inp, "user2-grps", inputrecStrings->user2, nullptr);
+ ir->userint1 = get_eint(&inp, "userint1", 0, wi);
+ ir->userint2 = get_eint(&inp, "userint2", 0, wi);
+ ir->userint3 = get_eint(&inp, "userint3", 0, wi);
+ ir->userint4 = get_eint(&inp, "userint4", 0, wi);
+ ir->userreal1 = get_ereal(&inp, "userreal1", 0, wi);
+ ir->userreal2 = get_ereal(&inp, "userreal2", 0, wi);
+ ir->userreal3 = get_ereal(&inp, "userreal3", 0, wi);
+ ir->userreal4 = get_ereal(&inp, "userreal4", 0, wi);
#undef CTYPE
+ if (mdparout)
{
gmx::TextOutputFile stream(mdparout);
write_inpfile(&stream, mdparout, &inp, FALSE, writeMdpHeader, wi);
/* Process options if necessary */
for (m = 0; m < 2; m++)
{
- for (i = 0; i < 2*DIM; i++)
+ for (i = 0; i < 2 * DIM; i++)
{
dumdub[m][i] = 0.0;
}
- if (ir->epc)
+ if (ir->epc != PressureCoupling::No)
{
switch (ir->epct)
{
- case epctISOTROPIC:
+ case PressureCouplingType::Isotropic:
if (sscanf(dumstr[m], "%lf", &(dumdub[m][XX])) != 1)
{
- warning_error(wi, "Pressure coupling incorrect number of values (I need exactly 1)");
+ warning_error(
+ wi,
+ "Pressure coupling incorrect number of values (I need exactly 1)");
}
dumdub[m][YY] = dumdub[m][ZZ] = dumdub[m][XX];
break;
- case epctSEMIISOTROPIC:
- case epctSURFACETENSION:
+ case PressureCouplingType::SemiIsotropic:
+ case PressureCouplingType::SurfaceTension:
if (sscanf(dumstr[m], "%lf%lf", &(dumdub[m][XX]), &(dumdub[m][ZZ])) != 2)
{
- warning_error(wi, "Pressure coupling incorrect number of values (I need exactly 2)");
+ warning_error(
+ wi,
+ "Pressure coupling incorrect number of values (I need exactly 2)");
}
dumdub[m][YY] = dumdub[m][XX];
break;
- case epctANISOTROPIC:
- if (sscanf(dumstr[m], "%lf%lf%lf%lf%lf%lf",
- &(dumdub[m][XX]), &(dumdub[m][YY]), &(dumdub[m][ZZ]),
- &(dumdub[m][3]), &(dumdub[m][4]), &(dumdub[m][5])) != 6)
+ case PressureCouplingType::Anisotropic:
+ if (sscanf(dumstr[m],
+ "%lf%lf%lf%lf%lf%lf",
+ &(dumdub[m][XX]),
+ &(dumdub[m][YY]),
+ &(dumdub[m][ZZ]),
+ &(dumdub[m][3]),
+ &(dumdub[m][4]),
+ &(dumdub[m][5]))
+ != 6)
{
- warning_error(wi, "Pressure coupling incorrect number of values (I need exactly 6)");
+ warning_error(
+ wi,
+ "Pressure coupling incorrect number of values (I need exactly 6)");
}
break;
default:
- gmx_fatal(FARGS, "Pressure coupling type %s not implemented yet",
- epcoupltype_names[ir->epct]);
+ gmx_fatal(FARGS,
+ "Pressure coupling type %s not implemented yet",
+ enumValueToString(ir->epct));
}
}
}
ir->ref_p[i][i] = dumdub[1][i];
ir->compress[i][i] = dumdub[0][i];
}
- if (ir->epct == epctANISOTROPIC)
+ if (ir->epct == PressureCouplingType::Anisotropic)
{
ir->ref_p[XX][YY] = dumdub[1][3];
ir->ref_p[XX][ZZ] = dumdub[1][4];
ir->ref_p[YY][ZZ] = dumdub[1][5];
if (ir->ref_p[XX][YY] != 0 && ir->ref_p[XX][ZZ] != 0 && ir->ref_p[YY][ZZ] != 0)
{
- warning(wi, "All off-diagonal reference pressures are non-zero. Are you sure you want to apply a threefold shear stress?\n");
+ warning(wi,
+ "All off-diagonal reference pressures are non-zero. Are you sure you want to "
+ "apply a threefold shear stress?\n");
}
ir->compress[XX][YY] = dumdub[0][3];
ir->compress[XX][ZZ] = dumdub[0][4];
}
}
- if (ir->comm_mode == ecmNO)
+ if (ir->comm_mode == ComRemovalAlgorithm::No)
{
ir->nstcomm = 0;
}
opts->couple_moltype = nullptr;
- if (strlen(is->couple_moltype) > 0)
+ if (strlen(inputrecStrings->couple_moltype) > 0)
{
- if (ir->efep != efepNO)
+ if (ir->efep != FreeEnergyPerturbationType::No)
{
- opts->couple_moltype = gmx_strdup(is->couple_moltype);
+ opts->couple_moltype = gmx_strdup(inputrecStrings->couple_moltype);
if (opts->couple_lam0 == opts->couple_lam1)
{
warning(wi, "The lambda=0 and lambda=1 states for coupling are identical");
}
- if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE ||
- opts->couple_lam1 == ecouplamNONE))
+ if (ir->eI == IntegrationAlgorithm::MD
+ && (opts->couple_lam0 == ecouplamNONE || opts->couple_lam1 == ecouplamNONE))
{
- warning(wi, "For proper sampling of the (nearly) decoupled state, stochastic dynamics should be used");
+ warning_note(
+ wi,
+ "For proper sampling of the (nearly) decoupled state, stochastic dynamics "
+ "should be used");
}
}
else
{
- warning_note(wi, "Free energy is turned off, so we will not decouple the molecule listed in your input.");
+ warning_note(wi,
+ "Free energy is turned off, so we will not decouple the molecule listed "
+ "in your input.");
}
}
/* FREE ENERGY AND EXPANDED ENSEMBLE OPTIONS */
- if (ir->efep != efepNO)
+ if (ir->efep != FreeEnergyPerturbationType::No)
{
- if (fep->delta_lambda > 0)
+ if (fep->delta_lambda != 0)
{
- ir->efep = efepSLOWGROWTH;
+ ir->efep = FreeEnergyPerturbationType::SlowGrowth;
}
}
- if (fep->edHdLPrintEnergy == edHdLPrintEnergyYES)
+ if (fep->edHdLPrintEnergy == FreeEnergyPrintEnergy::Yes)
{
- fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
- warning_note(wi, "Old option for dhdl-print-energy given: "
+ fep->edHdLPrintEnergy = FreeEnergyPrintEnergy::Total;
+ warning_note(wi,
+ "Old option for dhdl-print-energy given: "
"changing \"yes\" to \"total\"\n");
}
- if (ir->bSimTemp && (fep->edHdLPrintEnergy == edHdLPrintEnergyNO))
+ if (ir->bSimTemp && (fep->edHdLPrintEnergy == FreeEnergyPrintEnergy::No))
{
/* always print out the energy to dhdl if we are doing
expanded ensemble, since we need the total energy for
we will allow that if the appropriate mdp setting has
been enabled. Otherwise, total it is:
*/
- fep->edHdLPrintEnergy = edHdLPrintEnergyTOTAL;
+ fep->edHdLPrintEnergy = FreeEnergyPrintEnergy::Total;
}
- if ((ir->efep != efepNO) || ir->bSimTemp)
+ if ((ir->efep != FreeEnergyPerturbationType::No) || ir->bSimTemp)
{
ir->bExpanded = FALSE;
- if ((ir->efep == efepEXPANDED) || ir->bSimTemp)
+ if ((ir->efep == FreeEnergyPerturbationType::Expanded) || ir->bSimTemp)
{
ir->bExpanded = TRUE;
}
- do_fep_params(ir, is->fep_lambda, is->lambda_weights, wi);
+ do_fep_params(ir, inputrecStrings->fep_lambda, inputrecStrings->lambda_weights, wi);
if (ir->bSimTemp) /* done after fep params */
{
do_simtemp_params(ir);
* If the (advanced) user does FEP through manual topology changes,
* this check will not be triggered.
*/
- if (ir->efep != efepNO && ir->fepvals->n_lambda == 0 &&
- ir->fepvals->sc_alpha != 0 &&
- (couple_lambda_has_vdw_on(opts->couple_lam0) &&
- couple_lambda_has_vdw_on(opts->couple_lam1)))
+ if (ir->efep != FreeEnergyPerturbationType::No && ir->fepvals->n_lambda == 0
+ && ir->fepvals->sc_alpha != 0
+ && (couple_lambda_has_vdw_on(opts->couple_lam0) && couple_lambda_has_vdw_on(opts->couple_lam1)))
{
- warning(wi, "You are using soft-core interactions while the Van der Waals interactions are not decoupled (note that the sc-coul option is only active when using lambda states). Although this will not lead to errors, you will need much more sampling than without soft-core interactions. Consider using sc-alpha=0.");
+ warning(wi,
+ "You are using soft-core interactions while the Van der Waals interactions are "
+ "not decoupled (note that the sc-coul option is only active when using lambda "
+ "states). Although this will not lead to errors, you will need much more "
+ "sampling than without soft-core interactions. Consider using sc-alpha=0.");
}
}
else
/* WALL PARAMETERS */
- do_wall_params(ir, is->wall_atomtype, is->wall_density, opts, wi);
+ do_wall_params(ir, inputrecStrings->wall_atomtype, inputrecStrings->wall_density, opts, wi);
/* ORIENTATION RESTRAINT PARAMETERS */
- if (opts->bOrire && gmx::splitString(is->orirefitgrp).size() != 1)
+ if (opts->bOrire && gmx::splitString(inputrecStrings->orirefitgrp).size() != 1)
{
warning_error(wi, "ERROR: Need one orientation restraint fit group\n");
}
}
double gmx_unused canary;
- int ndeform = sscanf(is->deform, "%lf %lf %lf %lf %lf %lf %lf",
- &(dumdub[0][0]), &(dumdub[0][1]), &(dumdub[0][2]),
- &(dumdub[0][3]), &(dumdub[0][4]), &(dumdub[0][5]), &canary);
-
- if (strlen(is->deform) > 0 && ndeform != 6)
- {
- warning_error(wi, gmx::formatString("Cannot parse exactly 6 box deformation velocities from string '%s'", is->deform).c_str());
+ int ndeform = sscanf(inputrecStrings->deform,
+ "%lf %lf %lf %lf %lf %lf %lf",
+ &(dumdub[0][0]),
+ &(dumdub[0][1]),
+ &(dumdub[0][2]),
+ &(dumdub[0][3]),
+ &(dumdub[0][4]),
+ &(dumdub[0][5]),
+ &canary);
+
+ if (strlen(inputrecStrings->deform) > 0 && ndeform != 6)
+ {
+ warning_error(wi,
+ gmx::formatString(
+ "Cannot parse exactly 6 box deformation velocities from string '%s'",
+ inputrecStrings->deform)
+ .c_str());
}
for (i = 0; i < 3; i++)
{
ir->deform[YY][XX] = dumdub[0][3];
ir->deform[ZZ][XX] = dumdub[0][4];
ir->deform[ZZ][YY] = dumdub[0][5];
- if (ir->epc != epcNO)
+ if (ir->epc != PressureCoupling::No)
{
for (i = 0; i < 3; i++)
{
{
if (ir->compress[m][j] != 0)
{
- sprintf(warn_buf, "An off-diagonal box element has deform set while compressibility > 0 for the same component of another box vector, this might lead to spurious periodicity effects.");
+ sprintf(warn_buf,
+ "An off-diagonal box element has deform set while "
+ "compressibility > 0 for the same component of another box "
+ "vector, this might lead to spurious periodicity effects.");
warning(wi, warn_buf);
}
}
}
/* Ion/water position swapping checks */
- if (ir->eSwapCoords != eswapNO)
+ if (ir->eSwapCoords != SwapType::No)
{
if (ir->swap->nstswap < 1)
{
}
}
- sfree(dumstr[0]);
- sfree(dumstr[1]);
-}
-
-static int search_QMstring(const char *s, int ng, const char *gn[])
-{
- /* same as normal search_string, but this one searches QM strings */
- int i;
-
- for (i = 0; (i < ng); i++)
+ /* Set up MTS levels, this needs to happen before checking AWH parameters */
+ if (ir->useMts)
{
- if (gmx_strcasecmp(s, gn[i]) == 0)
+ std::vector<std::string> errorMessages;
+ ir->mtsLevels = gmx::setupMtsLevels(opts->mtsOpts, &errorMessages);
+
+ for (const auto& errorMessage : errorMessages)
{
- return i;
+ warning_error(wi, errorMessage.c_str());
}
}
- gmx_fatal(FARGS, "this QM method or basisset (%s) is not implemented\n!", s);
-} /* search_QMstring */
+ if (ir->bDoAwh)
+ {
+ gmx::checkAwhParams(*ir->awhParams, *ir, wi);
+ }
-/* We would like gn to be const as well, but C doesn't allow this */
-/* TODO this is utility functionality (search for the index of a
- string in a collection), so should be refactored and located more
- centrally. */
-int search_string(const char *s, int ng, char *gn[])
+ sfree(dumstr[0]);
+ sfree(dumstr[1]);
+}
+
+int search_string(const char* s, int ng, char* const gn[])
{
int i;
s);
}
-static bool do_numbering(int natoms, SimulationGroups *groups,
- gmx::ArrayRef<std::string> groupsFromMdpFile,
- t_blocka *block, char *gnames[],
- SimulationAtomGroupType gtype, int restnm,
- int grptp, bool bVerbose,
- warninp_t wi)
+static void atomGroupRangeValidation(int natoms, int groupIndex, const t_blocka& block)
{
- unsigned short *cbuf;
- AtomGroupIndices *grps = &(groups->groups[gtype]);
- int j, gid, aj, ognr, ntot = 0;
- const char *title;
- bool bRest;
- char warn_buf[STRLEN];
+ /* Now go over the atoms in the group */
+ for (int j = block.index[groupIndex]; (j < block.index[groupIndex + 1]); j++)
+ {
+ int aj = block.a[j];
+
+ /* Range checking */
+ if ((aj < 0) || (aj >= natoms))
+ {
+ gmx_fatal(FARGS, "Invalid atom number %d in indexfile", aj + 1);
+ }
+ }
+}
+
+/*! Creates the groups of atom indices for group type \p gtype
+ *
+ * \param[in] natoms The total number of atoms in the system
+ * \param[in,out] groups Index \p gtype in this list of list of groups will be set
+ * \param[in] groupsFromMdpFile The list of group names set for \p gtype in the mdp file
+ * \param[in] block The list of atom indices for all available index groups
+ * \param[in] gnames The list of names for all available index groups
+ * \param[in] gtype The group type to creates groups for
+ * \param[in] restnm The index of rest group name in \p gnames
+ * \param[in] coverage How to treat coverage of all atoms in the system
+ * \param[in] bVerbose Whether to print when we make a rest group
+ * \param[in,out] wi List of warnings
+ */
+static void do_numbering(const int natoms,
+ SimulationGroups* groups,
+ gmx::ArrayRef<const std::string> groupsFromMdpFile,
+ const t_blocka* block,
+ char* const gnames[],
+ const SimulationAtomGroupType gtype,
+ const int restnm,
+ const GroupCoverage coverage,
+ const bool bVerbose,
+ warninp_t wi)
+{
+ unsigned short* cbuf;
+ AtomGroupIndices* grps = &(groups->groups[gtype]);
+ int ntot = 0;
+ const char* title;
+ char warn_buf[STRLEN];
title = shortName(gtype);
for (int i = 0; i != groupsFromMdpFile.ssize(); ++i)
{
/* Lookup the group name in the block structure */
- gid = search_string(groupsFromMdpFile[i].c_str(), block->nr, gnames);
- if ((grptp != egrptpONE) || (i == 0))
+ const int gid = search_string(groupsFromMdpFile[i].c_str(), block->nr, gnames);
+ if ((coverage != GroupCoverage::OneGroup) || (i == 0))
{
grps->emplace_back(gid);
}
-
+ GMX_ASSERT(block, "Can't have a nullptr block");
+ atomGroupRangeValidation(natoms, gid, *block);
/* Now go over the atoms in the group */
- for (j = block->index[gid]; (j < block->index[gid+1]); j++)
+ for (int j = block->index[gid]; (j < block->index[gid + 1]); j++)
{
-
- aj = block->a[j];
-
- /* Range checking */
- if ((aj < 0) || (aj >= natoms))
- {
- gmx_fatal(FARGS, "Invalid atom number %d in indexfile", aj + 1);
- }
+ const int aj = block->a[j];
/* Lookup up the old group number */
- ognr = cbuf[aj];
+ const int ognr = cbuf[aj];
if (ognr != NOGID)
{
- gmx_fatal(FARGS, "Atom %d in multiple %s groups (%d and %d)",
- aj+1, title, ognr+1, i+1);
+ gmx_fatal(FARGS, "Atom %d in multiple %s groups (%d and %d)", aj + 1, title, ognr + 1, i + 1);
}
else
{
/* Store the group number in buffer */
- if (grptp == egrptpONE)
+ if (coverage == GroupCoverage::OneGroup)
{
cbuf[aj] = 0;
}
}
/* Now check whether we have done all atoms */
- bRest = FALSE;
if (ntot != natoms)
{
- if (grptp == egrptpALL)
+ if (coverage == GroupCoverage::All)
{
- gmx_fatal(FARGS, "%d atoms are not part of any of the %s groups",
- natoms-ntot, title);
+ gmx_fatal(FARGS, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
}
- else if (grptp == egrptpPART)
+ else if (coverage == GroupCoverage::Partial)
{
- sprintf(warn_buf, "%d atoms are not part of any of the %s groups",
- natoms-ntot, title);
+ sprintf(warn_buf, "%d atoms are not part of any of the %s groups", natoms - ntot, title);
warning_note(wi, warn_buf);
}
/* Assign all atoms currently unassigned to a rest group */
- for (j = 0; (j < natoms); j++)
+ for (int j = 0; (j < natoms); j++)
{
if (cbuf[j] == NOGID)
{
cbuf[j] = grps->size();
- bRest = TRUE;
}
}
- if (grptp != egrptpPART)
+ if (coverage != GroupCoverage::Partial)
{
if (bVerbose)
{
- fprintf(stderr,
- "Making dummy/rest group for %s containing %d elements\n",
- title, natoms-ntot);
+ fprintf(stderr, "Making dummy/rest group for %s containing %d elements\n", title, natoms - ntot);
}
/* Add group name "rest" */
grps->emplace_back(restnm);
/* Assign the rest name to all atoms not currently assigned to a group */
- for (j = 0; (j < natoms); j++)
+ for (int j = 0; (j < natoms); j++)
{
if (cbuf[j] == NOGID)
{
}
sfree(cbuf);
-
- return (bRest && grptp == egrptpPART);
}
-static void calc_nrdf(const gmx_mtop_t *mtop, t_inputrec *ir, char **gnames)
+static void calc_nrdf(const gmx_mtop_t* mtop, t_inputrec* ir, char** gnames)
{
- t_grpopts *opts;
- pull_params_t *pull;
- int natoms, imin, jmin;
- int *nrdf2, *na_vcm, na_tot;
- double *nrdf_tc, *nrdf_vcm, nrdf_uc, *nrdf_vcm_sub;
- ivec *dof_vcm;
- int as;
+ t_grpopts* opts;
+ pull_params_t* pull;
+ int natoms, imin, jmin;
+ int * nrdf2, *na_vcm, na_tot;
+ double * nrdf_tc, *nrdf_vcm, nrdf_uc, *nrdf_vcm_sub;
+ ivec* dof_vcm;
+ int as;
/* Calculate nrdf.
* First calc 3xnr-atoms for each group
opts = &ir->opts;
- const SimulationGroups &groups = mtop->groups;
- natoms = mtop->natoms;
+ const SimulationGroups& groups = mtop->groups;
+ natoms = mtop->natoms;
/* Allocate one more for a possible rest group */
/* We need to sum degrees of freedom into doubles,
* since floats give too low nrdf's above 3 million atoms.
*/
- snew(nrdf_tc, groups.groups[SimulationAtomGroupType::TemperatureCoupling].size()+1);
- snew(nrdf_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size()+1);
- snew(dof_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size()+1);
- snew(na_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size()+1);
- snew(nrdf_vcm_sub, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size()+1);
+ snew(nrdf_tc, groups.groups[SimulationAtomGroupType::TemperatureCoupling].size() + 1);
+ snew(nrdf_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
+ snew(dof_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
+ snew(na_vcm, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
+ snew(nrdf_vcm_sub, groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size() + 1);
for (gmx::index i = 0; i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
{
nrdf_tc[i] = 0;
}
- for (gmx::index i = 0; i < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval])+1; i++)
+ for (gmx::index i = 0;
+ i < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1;
+ i++)
{
- nrdf_vcm[i] = 0;
+ nrdf_vcm[i] = 0;
clear_ivec(dof_vcm[i]);
na_vcm[i] = 0;
nrdf_vcm_sub[i] = 0;
snew(nrdf2, natoms);
for (const AtomProxy atomP : AtomRange(*mtop))
{
- const t_atom &local = atomP.atom();
+ const t_atom& local = atomP.atom();
int i = atomP.globalAtomNumber();
- nrdf2[i] = 0;
- if (local.ptype == eptAtom || local.ptype == eptNucleus)
+ nrdf2[i] = 0;
+ if (local.ptype == ParticleType::Atom || local.ptype == ParticleType::Nucleus)
{
int g = getGroupType(groups, SimulationAtomGroupType::Freeze, i);
for (int d = 0; d < DIM; d++)
if (opts->nFreeze[g][d] == 0)
{
/* Add one DOF for particle i (counted as 2*1) */
- nrdf2[i] += 2;
+ nrdf2[i] += 2;
/* VCM group i has dim d as a DOF */
- dof_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)][d] = 1;
+ dof_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)][d] =
+ 1;
}
}
- nrdf_tc [getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, i)] += 0.5*nrdf2[i];
- nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)] += 0.5*nrdf2[i];
+ nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, i)] +=
+ 0.5 * nrdf2[i];
+ nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, i)] +=
+ 0.5 * nrdf2[i];
}
}
as = 0;
- for (const gmx_molblock_t &molb : mtop->molblock)
+ for (const gmx_molblock_t& molb : mtop->molblock)
{
- const gmx_moltype_t &molt = mtop->moltype[molb.type];
- const t_atom *atom = molt.atoms.atom;
+ const gmx_moltype_t& molt = mtop->moltype[molb.type];
+ const t_atom* atom = molt.atoms.atom;
for (int mol = 0; mol < molb.nmol; mol++)
{
for (int ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
{
gmx::ArrayRef<const int> ia = molt.ilist[ftype].iatoms;
- for (int i = 0; i < molt.ilist[ftype].size(); )
+ for (int i = 0; i < molt.ilist[ftype].size();)
{
/* Subtract degrees of freedom for the constraints,
* if the particles still have degrees of freedom left.
*/
int ai = as + ia[i + 1];
int aj = as + ia[i + 2];
- if (((atom[ia[i + 1]].ptype == eptNucleus) ||
- (atom[ia[i + 1]].ptype == eptAtom)) &&
- ((atom[ia[i + 2]].ptype == eptNucleus) ||
- (atom[ia[i + 2]].ptype == eptAtom)))
+ if (((atom[ia[i + 1]].ptype == ParticleType::Nucleus)
+ || (atom[ia[i + 1]].ptype == ParticleType::Atom))
+ && ((atom[ia[i + 2]].ptype == ParticleType::Nucleus)
+ || (atom[ia[i + 2]].ptype == ParticleType::Atom)))
{
if (nrdf2[ai] > 0)
{
{
imin = 2;
}
- imin = std::min(imin, nrdf2[ai]);
- jmin = std::min(jmin, nrdf2[aj]);
+ imin = std::min(imin, nrdf2[ai]);
+ jmin = std::min(jmin, nrdf2[aj]);
nrdf2[ai] -= imin;
nrdf2[aj] -= jmin;
- nrdf_tc [getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -= 0.5*imin;
- nrdf_tc [getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, aj)] -= 0.5*jmin;
- nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -= 0.5*imin;
- nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, aj)] -= 0.5*jmin;
+ nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
+ 0.5 * imin;
+ nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, aj)] -=
+ 0.5 * jmin;
+ nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
+ 0.5 * imin;
+ nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, aj)] -=
+ 0.5 * jmin;
}
- i += interaction_function[ftype].nratoms+1;
+ i += interaction_function[ftype].nratoms + 1;
}
}
gmx::ArrayRef<const int> ia = molt.ilist[F_SETTLE].iatoms;
- for (int i = 0; i < molt.ilist[F_SETTLE].size(); )
+ for (int i = 0; i < molt.ilist[F_SETTLE].size();)
{
/* Subtract 1 dof from every atom in the SETTLE */
for (int j = 0; j < 3; j++)
{
- int ai = as + ia[i + 1 + j];
- imin = std::min(2, nrdf2[ai]);
+ int ai = as + ia[i + 1 + j];
+ imin = std::min(2, nrdf2[ai]);
nrdf2[ai] -= imin;
- nrdf_tc [getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -= 0.5*imin;
- nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -= 0.5*imin;
+ nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
+ 0.5 * imin;
+ nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
+ 0.5 * imin;
}
- i += 4;
+ i += 4;
}
as += molt.atoms.nr;
}
* belong to different TC or VCM groups it is anyhow difficult
* to determine the optimal nrdf assignment.
*/
- pull = ir->pull;
+ pull = ir->pull.get();
for (int i = 0; i < pull->ncoord; i++)
{
- if (pull->coord[i].eType != epullCONSTRAINT)
+ if (pull->coord[i].eType != PullingAlgorithm::Constraint)
{
continue;
}
for (int j = 0; j < 2; j++)
{
- const t_pull_group *pgrp;
+ const t_pull_group* pgrp;
pgrp = &pull->group[pull->coord[i].group[j]];
- if (pgrp->nat > 0)
+ if (!pgrp->ind.empty())
{
/* Subtract 1/2 dof from each group */
int ai = pgrp->ind[0];
- nrdf_tc [getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -= 0.5*imin;
- nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -= 0.5*imin;
+ nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] -=
+ 0.5 * imin;
+ nrdf_vcm[getGroupType(groups, SimulationAtomGroupType::MassCenterVelocityRemoval, ai)] -=
+ 0.5 * imin;
if (nrdf_tc[getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)] < 0)
{
- gmx_fatal(FARGS, "Center of mass pulling constraints caused the number of degrees of freedom for temperature coupling group %s to be negative", gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][getGroupType(groups, SimulationAtomGroupType::TemperatureCoupling, ai)]]);
+ gmx_fatal(FARGS,
+ "Center of mass pulling constraints caused the number of degrees "
+ "of freedom for temperature coupling group %s to be negative",
+ gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][getGroupType(
+ groups, SimulationAtomGroupType::TemperatureCoupling, ai)]]);
}
}
else
if (ir->nstcomm != 0)
{
- int ndim_rm_vcm;
+ GMX_RELEASE_ASSERT(!groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval].empty(),
+ "Expect at least one group when removing COM motion");
/* We remove COM motion up to dim ndof_com() */
- ndim_rm_vcm = ndof_com(ir);
+ const int ndim_rm_vcm = ndof_com(ir);
/* Subtract ndim_rm_vcm (or less with frozen dimensions) from
* the number of degrees of freedom in each vcm group when COM
* translation is removed and 6 when rotation is removed as well.
+ * Note that we do not and should not include the rest group here.
*/
- for (gmx::index j = 0; j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval])+1; j++)
+ for (gmx::index j = 0;
+ j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]);
+ j++)
{
switch (ir->comm_mode)
{
- case ecmLINEAR:
- case ecmLINEAR_ACCELERATION_CORRECTION:
+ case ComRemovalAlgorithm::Linear:
+ case ComRemovalAlgorithm::LinearAccelerationCorrection:
nrdf_vcm_sub[j] = 0;
for (int d = 0; d < ndim_rm_vcm; d++)
{
}
}
break;
- case ecmANGULAR:
- nrdf_vcm_sub[j] = 6;
- break;
- default:
- gmx_incons("Checking comm_mode");
+ case ComRemovalAlgorithm::Angular: nrdf_vcm_sub[j] = 6; break;
+ default: gmx_incons("Checking comm_mode");
}
}
- for (gmx::index i = 0; i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]); i++)
+ for (gmx::index i = 0;
+ i < gmx::ssize(groups.groups[SimulationAtomGroupType::TemperatureCoupling]);
+ i++)
{
/* Count the number of atoms of TC group i for every VCM group */
- for (gmx::index j = 0; j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval])+1; j++)
+ for (gmx::index j = 0;
+ j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1;
+ j++)
{
na_vcm[j] = 0;
}
*/
nrdf_uc = nrdf_tc[i];
nrdf_tc[i] = 0;
- for (gmx::index j = 0; j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval])+1; j++)
+ for (gmx::index j = 0;
+ j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1;
+ j++)
{
if (nrdf_vcm[j] > nrdf_vcm_sub[j])
{
- nrdf_tc[i] += nrdf_uc*(static_cast<double>(na_vcm[j])/static_cast<double>(na_tot))*
- (nrdf_vcm[j] - nrdf_vcm_sub[j])/nrdf_vcm[j];
+ nrdf_tc[i] += nrdf_uc * (static_cast<double>(na_vcm[j]) / static_cast<double>(na_tot))
+ * (nrdf_vcm[j] - nrdf_vcm_sub[j]) / nrdf_vcm[j];
}
}
}
}
fprintf(stderr,
"Number of degrees of freedom in T-Coupling group %s is %.2f\n",
- gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][i]], opts->nrdf[i]);
+ gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][i]],
+ opts->nrdf[i]);
}
sfree(nrdf2);
sfree(nrdf_vcm_sub);
}
-static bool do_egp_flag(t_inputrec *ir, SimulationGroups *groups,
- const char *option, const char *val, int flag)
+static bool do_egp_flag(t_inputrec* ir, SimulationGroups* groups, const char* option, const char* val, int flag)
{
/* The maximum number of energy group pairs would be MAXPTR*(MAXPTR+1)/2.
* But since this is much larger than STRLEN, such a line can not be parsed.
* The real maximum is the number of names that fit in a string: STRLEN/2.
*/
-#define EGP_MAX (STRLEN/2)
- int j, k, nr;
- bool bSet;
+ int j, k, nr;
+ bool bSet;
- auto names = gmx::splitString(val);
+ auto names = gmx::splitString(val);
if (names.size() % 2 != 0)
{
gmx_fatal(FARGS, "The number of groups for %s is odd", option);
{
// TODO this needs to be replaced by a solution using std::find_if
j = 0;
- while ((j < nr) &&
- gmx_strcasecmp(names[2*i].c_str(), *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][j]])))
+ while ((j < nr)
+ && gmx_strcasecmp(
+ names[2 * i].c_str(),
+ *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][j]])))
{
j++;
}
if (j == nr)
{
- gmx_fatal(FARGS, "%s in %s is not an energy group\n",
- names[2*i].c_str(), option);
+ gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i].c_str(), option);
}
k = 0;
- while ((k < nr) &&
- gmx_strcasecmp(names[2*i+1].c_str(), *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][k]])))
+ while ((k < nr)
+ && gmx_strcasecmp(
+ names[2 * i + 1].c_str(),
+ *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][k]])))
{
k++;
}
if (k == nr)
{
- gmx_fatal(FARGS, "%s in %s is not an energy group\n",
- names[2*i+1].c_str(), option);
+ gmx_fatal(FARGS, "%s in %s is not an energy group\n", names[2 * i + 1].c_str(), option);
}
if ((j < nr) && (k < nr))
{
- ir->opts.egp_flags[nr*j+k] |= flag;
- ir->opts.egp_flags[nr*k+j] |= flag;
+ ir->opts.egp_flags[nr * j + k] |= flag;
+ ir->opts.egp_flags[nr * k + j] |= flag;
bSet = TRUE;
}
}
}
-static void make_swap_groups(
- t_swapcoords *swap,
- t_blocka *grps,
- char **gnames)
+static void make_swap_groups(t_swapcoords* swap, t_blocka* grps, char** gnames)
{
int ig = -1, i = 0, gind;
- t_swapGroup *swapg;
+ t_swapGroup* swapg;
/* Just a quick check here, more thorough checks are in mdrun */
- if (strcmp(swap->grp[eGrpSplit0].molname, swap->grp[eGrpSplit1].molname) == 0)
+ if (strcmp(swap->grp[static_cast<int>(SwapGroupSplittingType::Split0)].molname,
+ swap->grp[static_cast<int>(SwapGroupSplittingType::Split1)].molname)
+ == 0)
{
- gmx_fatal(FARGS, "The split groups can not both be '%s'.", swap->grp[eGrpSplit0].molname);
+ gmx_fatal(FARGS,
+ "The split groups can not both be '%s'.",
+ swap->grp[static_cast<int>(SwapGroupSplittingType::Split0)].molname);
}
/* Get the index atoms of the split0, split1, solvent, and swap groups */
{
swapg = &swap->grp[ig];
gind = search_string(swap->grp[ig].molname, grps->nr, gnames);
- swapg->nat = grps->index[gind+1] - grps->index[gind];
+ swapg->nat = grps->index[gind + 1] - grps->index[gind];
if (swapg->nat > 0)
{
- fprintf(stderr, "%s group '%s' contains %d atoms.\n",
- ig < 3 ? eSwapFixedGrp_names[ig] : "Swap",
- swap->grp[ig].molname, swapg->nat);
+ fprintf(stderr,
+ "%s group '%s' contains %d atoms.\n",
+ ig < 3 ? enumValueToString(static_cast<SwapGroupSplittingType>(ig)) : "Swap",
+ swap->grp[ig].molname,
+ swapg->nat);
snew(swapg->ind, swapg->nat);
for (i = 0; i < swapg->nat; i++)
{
- swapg->ind[i] = grps->a[grps->index[gind]+i];
+ swapg->ind[i] = grps->a[grps->index[gind] + i];
}
}
else
}
-static void make_IMD_group(t_IMD *IMDgroup, char *IMDgname, t_blocka *grps, char **gnames)
+static void make_IMD_group(t_IMD* IMDgroup, char* IMDgname, t_blocka* grps, char** gnames)
{
- int ig, i;
+ int ig, i;
ig = search_string(IMDgname, grps->nr, gnames);
- IMDgroup->nat = grps->index[ig+1] - grps->index[ig];
+ IMDgroup->nat = grps->index[ig + 1] - grps->index[ig];
if (IMDgroup->nat > 0)
{
- fprintf(stderr, "Group '%s' with %d atoms can be activated for interactive molecular dynamics (IMD).\n",
- IMDgname, IMDgroup->nat);
+ fprintf(stderr,
+ "Group '%s' with %d atoms can be activated for interactive molecular dynamics "
+ "(IMD).\n",
+ IMDgname,
+ IMDgroup->nat);
snew(IMDgroup->ind, IMDgroup->nat);
for (i = 0; i < IMDgroup->nat; i++)
{
- IMDgroup->ind[i] = grps->a[grps->index[ig]+i];
+ IMDgroup->ind[i] = grps->a[grps->index[ig] + i];
}
}
}
-void do_index(const char* mdparin, const char *ndx,
- gmx_mtop_t *mtop,
- bool bVerbose,
- const gmx::MdModulesNotifier ¬ifier,
- t_inputrec *ir,
- warninp_t wi)
+/* Checks whether atoms are both part of a COM removal group and frozen.
+ * If a fully frozen atom is part of a COM removal group, it is removed
+ * from the COM removal group. A note is issued if such atoms are present.
+ * A warning is issued for atom with one or two dimensions frozen that
+ * are part of a COM removal group (mdrun would need to compute COM mass
+ * per dimension to handle this correctly).
+ * Also issues a warning when non-frozen atoms are not part of a COM
+ * removal group while COM removal is active.
+ */
+static void checkAndUpdateVcmFreezeGroupConsistency(SimulationGroups* groups,
+ const int numAtoms,
+ const t_grpopts& opts,
+ warninp_t wi)
{
- t_blocka *defaultIndexGroups;
+ const int vcmRestGroup =
+ std::max(int(groups->groups[SimulationAtomGroupType::MassCenterVelocityRemoval].size()), 1);
+
+ int numFullyFrozenVcmAtoms = 0;
+ int numPartiallyFrozenVcmAtoms = 0;
+ int numNonVcmAtoms = 0;
+ for (int a = 0; a < numAtoms; a++)
+ {
+ const int freezeGroup = getGroupType(*groups, SimulationAtomGroupType::Freeze, a);
+ int numFrozenDims = 0;
+ for (int d = 0; d < DIM; d++)
+ {
+ numFrozenDims += opts.nFreeze[freezeGroup][d];
+ }
+
+ const int vcmGroup = getGroupType(*groups, SimulationAtomGroupType::MassCenterVelocityRemoval, a);
+ if (vcmGroup < vcmRestGroup)
+ {
+ if (numFrozenDims == DIM)
+ {
+ /* Do not remove COM motion for this fully frozen atom */
+ if (groups->groupNumbers[SimulationAtomGroupType::MassCenterVelocityRemoval].empty())
+ {
+ groups->groupNumbers[SimulationAtomGroupType::MassCenterVelocityRemoval].resize(
+ numAtoms, 0);
+ }
+ groups->groupNumbers[SimulationAtomGroupType::MassCenterVelocityRemoval][a] = vcmRestGroup;
+ numFullyFrozenVcmAtoms++;
+ }
+ else if (numFrozenDims > 0)
+ {
+ numPartiallyFrozenVcmAtoms++;
+ }
+ }
+ else if (numFrozenDims < DIM)
+ {
+ numNonVcmAtoms++;
+ }
+ }
+
+ if (numFullyFrozenVcmAtoms > 0)
+ {
+ std::string warningText = gmx::formatString(
+ "There are %d atoms that are fully frozen and part of COMM removal group(s), "
+ "removing these atoms from the COMM removal group(s)",
+ numFullyFrozenVcmAtoms);
+ warning_note(wi, warningText.c_str());
+ }
+ if (numPartiallyFrozenVcmAtoms > 0 && numPartiallyFrozenVcmAtoms < numAtoms)
+ {
+ std::string warningText = gmx::formatString(
+ "There are %d atoms that are frozen along less then %d dimensions and part of COMM "
+ "removal group(s), due to limitations in the code these still contribute to the "
+ "mass of the COM along frozen dimensions and therefore the COMM correction will be "
+ "too small.",
+ numPartiallyFrozenVcmAtoms,
+ DIM);
+ warning(wi, warningText.c_str());
+ }
+ if (numNonVcmAtoms > 0)
+ {
+ std::string warningText = gmx::formatString(
+ "%d atoms are not part of any center of mass motion removal group.\n"
+ "This may lead to artifacts.\n"
+ "In most cases one should use one group for the whole system.",
+ numNonVcmAtoms);
+ warning(wi, warningText.c_str());
+ }
+}
+
+void do_index(const char* mdparin,
+ const char* ndx,
+ gmx_mtop_t* mtop,
+ bool bVerbose,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ t_inputrec* ir,
+ warninp_t wi)
+{
+ t_blocka* defaultIndexGroups;
int natoms;
- t_symtab *symtab;
+ t_symtab* symtab;
t_atoms atoms_all;
- char warnbuf[STRLEN], **gnames;
+ char** gnames;
int nr;
real tau_min;
int nstcmin;
int i, j, k, restnm;
- bool bExcl, bTable, bAnneal, bRest;
+ bool bExcl, bTable, bAnneal;
char warn_buf[STRLEN];
if (bVerbose)
snew(defaultIndexGroups, 1);
snew(defaultIndexGroups->index, 1);
snew(gnames, 1);
- atoms_all = gmx_mtop_global_atoms(mtop);
+ atoms_all = gmx_mtop_global_atoms(*mtop);
analyse(&atoms_all, defaultIndexGroups, &gnames, FALSE, TRUE);
done_atom(&atoms_all);
}
defaultIndexGroups = init_index(ndx, &gnames);
}
- SimulationGroups *groups = &mtop->groups;
- natoms = mtop->natoms;
- symtab = &mtop->symtab;
+ SimulationGroups* groups = &mtop->groups;
+ natoms = mtop->natoms;
+ symtab = &mtop->symtab;
for (int i = 0; (i < defaultIndexGroups->nr); i++)
{
groups->groupNames.emplace_back(put_symtab(symtab, gnames[i]));
}
groups->groupNames.emplace_back(put_symtab(symtab, "rest"));
- restnm = groups->groupNames.size() - 1;
+ restnm = groups->groupNames.size() - 1;
GMX_RELEASE_ASSERT(restnm == defaultIndexGroups->nr, "Size of allocations must match");
- srenew(gnames, defaultIndexGroups->nr+1);
- gnames[restnm] = *(groups->groupNames.back());
+ srenew(gnames, defaultIndexGroups->nr + 1);
+ gnames[restnm] = *(groups->groupNames.back());
set_warning_line(wi, mdparin, -1);
- auto temperatureCouplingTauValues = gmx::splitString(is->tau_t);
- auto temperatureCouplingReferenceValues = gmx::splitString(is->ref_t);
- auto temperatureCouplingGroupNames = gmx::splitString(is->tcgrps);
- if (temperatureCouplingTauValues.size() != temperatureCouplingGroupNames.size() ||
- temperatureCouplingReferenceValues.size() != temperatureCouplingGroupNames.size())
+ auto temperatureCouplingTauValues = gmx::splitString(inputrecStrings->tau_t);
+ auto temperatureCouplingReferenceValues = gmx::splitString(inputrecStrings->ref_t);
+ auto temperatureCouplingGroupNames = gmx::splitString(inputrecStrings->tcgrps);
+ if (temperatureCouplingTauValues.size() != temperatureCouplingGroupNames.size()
+ || temperatureCouplingReferenceValues.size() != temperatureCouplingGroupNames.size())
{
- gmx_fatal(FARGS, "Invalid T coupling input: %zu groups, %zu ref-t values and "
+ gmx_fatal(FARGS,
+ "Invalid T coupling input: %zu groups, %zu ref-t values and "
"%zu tau-t values",
temperatureCouplingGroupNames.size(),
temperatureCouplingReferenceValues.size(),
}
const bool useReferenceTemperature = integratorHasReferenceTemperature(ir);
- do_numbering(natoms, groups, temperatureCouplingGroupNames, defaultIndexGroups, gnames,
+ do_numbering(natoms,
+ groups,
+ temperatureCouplingGroupNames,
+ defaultIndexGroups,
+ gnames,
SimulationAtomGroupType::TemperatureCoupling,
- restnm, useReferenceTemperature ? egrptpALL : egrptpALL_GENREST, bVerbose, wi);
+ restnm,
+ useReferenceTemperature ? GroupCoverage::All : GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
nr = groups->groups[SimulationAtomGroupType::TemperatureCoupling].size();
ir->opts.ngtc = nr;
snew(ir->opts.nrdf, nr);
snew(ir->opts.tau_t, nr);
snew(ir->opts.ref_t, nr);
- if (ir->eI == eiBD && ir->bd_fric == 0)
+ if (ir->eI == IntegrationAlgorithm::BD && ir->bd_fric == 0)
{
fprintf(stderr, "bd-fric=0, so tau-t will be used as the inverse friction constant(s)\n");
}
convertReals(wi, temperatureCouplingTauValues, "tau-t", ir->opts.tau_t);
for (i = 0; (i < nr); i++)
{
- if ((ir->eI == eiBD) && ir->opts.tau_t[i] <= 0)
+ if ((ir->eI == IntegrationAlgorithm::BD) && ir->opts.tau_t[i] <= 0)
{
- sprintf(warn_buf, "With integrator %s tau-t should be larger than 0", ei_names[ir->eI]);
+ sprintf(warn_buf,
+ "With integrator %s tau-t should be larger than 0",
+ enumValueToString(ir->eI));
warning_error(wi, warn_buf);
}
- if (ir->etc != etcVRESCALE && ir->opts.tau_t[i] == 0)
+ if (ir->etc != TemperatureCoupling::VRescale && ir->opts.tau_t[i] == 0)
{
- warning_note(wi, "tau-t = -1 is the value to signal that a group should not have temperature coupling. Treating your use of tau-t = 0 as if you used -1.");
+ warning_note(
+ wi,
+ "tau-t = -1 is the value to signal that a group should not have "
+ "temperature coupling. Treating your use of tau-t = 0 as if you used -1.");
}
if (ir->opts.tau_t[i] >= 0)
tau_min = std::min(tau_min, ir->opts.tau_t[i]);
}
}
- if (ir->etc != etcNO && ir->nsttcouple == -1)
+ if (ir->etc != TemperatureCoupling::No && ir->nsttcouple == -1)
{
ir->nsttcouple = ir_optimal_nsttcouple(ir);
}
if (EI_VV(ir->eI))
{
- if ((ir->etc == etcNOSEHOOVER) && (ir->epc == epcBERENDSEN))
+ if ((ir->etc == TemperatureCoupling::NoseHoover) && (ir->epc == PressureCoupling::Berendsen))
{
- gmx_fatal(FARGS, "Cannot do Nose-Hoover temperature with Berendsen pressure control with md-vv; use either vrescale temperature with berendsen pressure or Nose-Hoover temperature with MTTK pressure");
+ gmx_fatal(FARGS,
+ "Cannot do Nose-Hoover temperature with Berendsen pressure control with "
+ "md-vv; use either vrescale temperature with berendsen pressure or "
+ "Nose-Hoover temperature with MTTK pressure");
}
- if (ir->epc == epcMTTK)
+ if (ir->epc == PressureCoupling::Mttk)
{
- if (ir->etc != etcNOSEHOOVER)
+ if (ir->etc != TemperatureCoupling::NoseHoover)
{
- gmx_fatal(FARGS, "Cannot do MTTK pressure coupling without Nose-Hoover temperature control");
+ gmx_fatal(FARGS,
+ "Cannot do MTTK pressure coupling without Nose-Hoover temperature "
+ "control");
}
else
{
if (ir->nstpcouple != ir->nsttcouple)
{
- int mincouple = std::min(ir->nstpcouple, ir->nsttcouple);
+ int mincouple = std::min(ir->nstpcouple, ir->nsttcouple);
ir->nstpcouple = ir->nsttcouple = mincouple;
- sprintf(warn_buf, "for current Trotter decomposition methods with vv, nsttcouple and nstpcouple must be equal. Both have been reset to min(nsttcouple,nstpcouple) = %d", mincouple);
+ sprintf(warn_buf,
+ "for current Trotter decomposition methods with vv, nsttcouple and "
+ "nstpcouple must be equal. Both have been reset to "
+ "min(nsttcouple,nstpcouple) = %d",
+ mincouple);
warning_note(wi, warn_buf);
}
}
if (ir->nsttcouple != 1)
{
ir->nsttcouple = 1;
- sprintf(warn_buf, "Andersen temperature control methods assume nsttcouple = 1; there is no need for larger nsttcouple > 1, since no global parameters are computed. nsttcouple has been reset to 1");
+ sprintf(warn_buf,
+ "Andersen temperature control methods assume nsttcouple = 1; there is no "
+ "need for larger nsttcouple > 1, since no global parameters are computed. "
+ "nsttcouple has been reset to 1");
warning_note(wi, warn_buf);
}
}
nstcmin = tcouple_min_integration_steps(ir->etc);
if (nstcmin > 1)
{
- if (tau_min/(ir->delta_t*ir->nsttcouple) < nstcmin - 10*GMX_REAL_EPS)
+ if (tau_min / (ir->delta_t * ir->nsttcouple) < nstcmin - 10 * GMX_REAL_EPS)
{
- sprintf(warn_buf, "For proper integration of the %s thermostat, tau-t (%g) should be at least %d times larger than nsttcouple*dt (%g)",
- ETCOUPLTYPE(ir->etc),
- tau_min, nstcmin,
- ir->nsttcouple*ir->delta_t);
+ sprintf(warn_buf,
+ "For proper integration of the %s thermostat, tau-t (%g) should be at "
+ "least %d times larger than nsttcouple*dt (%g)",
+ enumValueToString(ir->etc),
+ tau_min,
+ nstcmin,
+ ir->nsttcouple * ir->delta_t);
warning(wi, warn_buf);
}
}
}
/* Simulated annealing for each group. There are nr groups */
- auto simulatedAnnealingGroupNames = gmx::splitString(is->anneal);
- if (simulatedAnnealingGroupNames.size() == 1 &&
- gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[0], "N", 1))
+ auto simulatedAnnealingGroupNames = gmx::splitString(inputrecStrings->anneal);
+ if (simulatedAnnealingGroupNames.size() == 1
+ && gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[0], "N", 1))
{
simulatedAnnealingGroupNames.resize(0);
}
- if (!simulatedAnnealingGroupNames.empty() &&
- gmx::ssize(simulatedAnnealingGroupNames) != nr)
+ if (!simulatedAnnealingGroupNames.empty() && gmx::ssize(simulatedAnnealingGroupNames) != nr)
{
- gmx_fatal(FARGS, "Wrong number of annealing values: %zu (for %d groups)\n",
- simulatedAnnealingGroupNames.size(), nr);
+ gmx_fatal(FARGS,
+ "Wrong number of annealing values: %zu (for %d groups)\n",
+ simulatedAnnealingGroupNames.size(),
+ nr);
}
else
{
snew(ir->opts.anneal_temp, nr);
for (i = 0; i < nr; i++)
{
- ir->opts.annealing[i] = eannNO;
+ ir->opts.annealing[i] = SimulatedAnnealing::No;
ir->opts.anneal_npoints[i] = 0;
ir->opts.anneal_time[i] = nullptr;
ir->opts.anneal_temp[i] = nullptr;
{
if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "N", 1))
{
- ir->opts.annealing[i] = eannNO;
+ ir->opts.annealing[i] = SimulatedAnnealing::No;
}
else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "S", 1))
{
- ir->opts.annealing[i] = eannSINGLE;
+ ir->opts.annealing[i] = SimulatedAnnealing::Single;
bAnneal = TRUE;
}
else if (gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[i], "P", 1))
{
- ir->opts.annealing[i] = eannPERIODIC;
+ ir->opts.annealing[i] = SimulatedAnnealing::Periodic;
bAnneal = TRUE;
}
}
if (bAnneal)
{
/* Read the other fields too */
- auto simulatedAnnealingPoints = gmx::splitString(is->anneal_npoints);
+ auto simulatedAnnealingPoints = gmx::splitString(inputrecStrings->anneal_npoints);
if (simulatedAnnealingPoints.size() != simulatedAnnealingGroupNames.size())
{
- gmx_fatal(FARGS, "Found %zu annealing-npoints values for %zu groups\n",
- simulatedAnnealingPoints.size(), simulatedAnnealingGroupNames.size());
+ gmx_fatal(FARGS,
+ "Found %zu annealing-npoints values for %zu groups\n",
+ simulatedAnnealingPoints.size(),
+ simulatedAnnealingGroupNames.size());
}
convertInts(wi, simulatedAnnealingPoints, "annealing points", ir->opts.anneal_npoints);
size_t numSimulatedAnnealingFields = 0;
{
if (ir->opts.anneal_npoints[i] == 1)
{
- gmx_fatal(FARGS, "Please specify at least a start and an end point for annealing\n");
+ gmx_fatal(
+ FARGS,
+ "Please specify at least a start and an end point for annealing\n");
}
snew(ir->opts.anneal_time[i], ir->opts.anneal_npoints[i]);
snew(ir->opts.anneal_temp[i], ir->opts.anneal_npoints[i]);
numSimulatedAnnealingFields += ir->opts.anneal_npoints[i];
}
- auto simulatedAnnealingTimes = gmx::splitString(is->anneal_time);
+ auto simulatedAnnealingTimes = gmx::splitString(inputrecStrings->anneal_time);
if (simulatedAnnealingTimes.size() != numSimulatedAnnealingFields)
{
- gmx_fatal(FARGS, "Found %zu annealing-time values, wanted %zu\n",
- simulatedAnnealingTimes.size(), numSimulatedAnnealingFields);
+ gmx_fatal(FARGS,
+ "Found %zu annealing-time values, wanted %zu\n",
+ simulatedAnnealingTimes.size(),
+ numSimulatedAnnealingFields);
}
- auto simulatedAnnealingTemperatures = gmx::splitString(is->anneal_temp);
+ auto simulatedAnnealingTemperatures = gmx::splitString(inputrecStrings->anneal_temp);
if (simulatedAnnealingTemperatures.size() != numSimulatedAnnealingFields)
{
- gmx_fatal(FARGS, "Found %zu annealing-temp values, wanted %zu\n",
- simulatedAnnealingTemperatures.size(), numSimulatedAnnealingFields);
+ gmx_fatal(FARGS,
+ "Found %zu annealing-temp values, wanted %zu\n",
+ simulatedAnnealingTemperatures.size(),
+ numSimulatedAnnealingFields);
}
std::vector<real> allSimulatedAnnealingTimes(numSimulatedAnnealingFields);
std::vector<real> allSimulatedAnnealingTemperatures(numSimulatedAnnealingFields);
convertReals(wi, simulatedAnnealingTimes, "anneal-time", allSimulatedAnnealingTimes.data());
- convertReals(wi, simulatedAnnealingTemperatures, "anneal-temp", allSimulatedAnnealingTemperatures.data());
+ convertReals(wi,
+ simulatedAnnealingTemperatures,
+ "anneal-temp",
+ allSimulatedAnnealingTemperatures.data());
for (i = 0, k = 0; i < nr; i++)
{
for (j = 0; j < ir->opts.anneal_npoints[i]; j++)
ir->opts.anneal_temp[i][j] = allSimulatedAnnealingTemperatures[k];
if (j == 0)
{
- if (ir->opts.anneal_time[i][0] > (ir->init_t+GMX_REAL_EPS))
+ if (ir->opts.anneal_time[i][0] > (ir->init_t + GMX_REAL_EPS))
{
gmx_fatal(FARGS, "First time point for annealing > init_t.\n");
}
else
{
/* j>0 */
- if (ir->opts.anneal_time[i][j] < ir->opts.anneal_time[i][j-1])
+ if (ir->opts.anneal_time[i][j] < ir->opts.anneal_time[i][j - 1])
{
- gmx_fatal(FARGS, "Annealing timepoints out of order: t=%f comes after t=%f\n",
- ir->opts.anneal_time[i][j], ir->opts.anneal_time[i][j-1]);
+ gmx_fatal(FARGS,
+ "Annealing timepoints out of order: t=%f comes after "
+ "t=%f\n",
+ ir->opts.anneal_time[i][j],
+ ir->opts.anneal_time[i][j - 1]);
}
}
if (ir->opts.anneal_temp[i][j] < 0)
{
- gmx_fatal(FARGS, "Found negative temperature in annealing: %f\n", ir->opts.anneal_temp[i][j]);
+ gmx_fatal(FARGS,
+ "Found negative temperature in annealing: %f\n",
+ ir->opts.anneal_temp[i][j]);
}
k++;
}
/* Print out some summary information, to make sure we got it right */
for (i = 0; i < nr; i++)
{
- if (ir->opts.annealing[i] != eannNO)
+ if (ir->opts.annealing[i] != SimulatedAnnealing::No)
{
j = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
- fprintf(stderr, "Simulated annealing for group %s: %s, %d timepoints\n",
- *(groups->groupNames[j]), eann_names[ir->opts.annealing[i]],
+ fprintf(stderr,
+ "Simulated annealing for group %s: %s, %d timepoints\n",
+ *(groups->groupNames[j]),
+ enumValueToString(ir->opts.annealing[i]),
ir->opts.anneal_npoints[i]);
fprintf(stderr, "Time (ps) Temperature (K)\n");
/* All terms except the last one */
- for (j = 0; j < (ir->opts.anneal_npoints[i]-1); j++)
+ for (j = 0; j < (ir->opts.anneal_npoints[i] - 1); j++)
{
- fprintf(stderr, "%9.1f %5.1f\n", ir->opts.anneal_time[i][j], ir->opts.anneal_temp[i][j]);
+ fprintf(stderr,
+ "%9.1f %5.1f\n",
+ ir->opts.anneal_time[i][j],
+ ir->opts.anneal_temp[i][j]);
}
/* Finally the last one */
- j = ir->opts.anneal_npoints[i]-1;
- if (ir->opts.annealing[i] == eannSINGLE)
+ j = ir->opts.anneal_npoints[i] - 1;
+ if (ir->opts.annealing[i] == SimulatedAnnealing::Single)
{
- fprintf(stderr, "%9.1f- %5.1f\n", ir->opts.anneal_time[i][j], ir->opts.anneal_temp[i][j]);
+ fprintf(stderr,
+ "%9.1f- %5.1f\n",
+ ir->opts.anneal_time[i][j],
+ ir->opts.anneal_temp[i][j]);
}
else
{
- fprintf(stderr, "%9.1f %5.1f\n", ir->opts.anneal_time[i][j], ir->opts.anneal_temp[i][j]);
- if (std::fabs(ir->opts.anneal_temp[i][j]-ir->opts.anneal_temp[i][0]) > GMX_REAL_EPS)
+ fprintf(stderr,
+ "%9.1f %5.1f\n",
+ ir->opts.anneal_time[i][j],
+ ir->opts.anneal_temp[i][j]);
+ if (std::fabs(ir->opts.anneal_temp[i][j] - ir->opts.anneal_temp[i][0]) > GMX_REAL_EPS)
{
- warning_note(wi, "There is a temperature jump when your annealing loops back.\n");
+ warning_note(wi,
+ "There is a temperature jump when your annealing "
+ "loops back.\n");
}
}
}
if (ir->bPull)
{
- make_pull_groups(ir->pull, is->pull_grp, defaultIndexGroups, gnames);
+ for (int i = 1; i < ir->pull->ngroup; i++)
+ {
+ const int gid = search_string(
+ inputrecStrings->pullGroupNames[i].c_str(), defaultIndexGroups->nr, gnames);
+ GMX_ASSERT(defaultIndexGroups, "Must have initialized default index groups");
+ atomGroupRangeValidation(natoms, gid, *defaultIndexGroups);
+ }
+
+ process_pull_groups(ir->pull->group, inputrecStrings->pullGroupNames, defaultIndexGroups, gnames);
- make_pull_coords(ir->pull);
+ checkPullCoords(ir->pull->group, ir->pull->coord);
}
if (ir->bRot)
{
- make_rotation_groups(ir->rot, is->rot_grp, defaultIndexGroups, gnames);
+ make_rotation_groups(ir->rot, inputrecStrings->rotateGroupNames, defaultIndexGroups, gnames);
}
- if (ir->eSwapCoords != eswapNO)
+ if (ir->eSwapCoords != SwapType::No)
{
make_swap_groups(ir->swap, defaultIndexGroups, gnames);
}
/* Make indices for IMD session */
if (ir->bIMD)
{
- make_IMD_group(ir->imd, is->imd_grp, defaultIndexGroups, gnames);
+ make_IMD_group(ir->imd, inputrecStrings->imd_grp, defaultIndexGroups, gnames);
}
gmx::IndexGroupsAndNames defaultIndexGroupsAndNames(
*defaultIndexGroups, gmx::arrayRefFromArray(gnames, defaultIndexGroups->nr));
- notifier.notifier_.notify(defaultIndexGroupsAndNames);
+ mdModulesNotifiers.preProcessingNotifier_.notify(defaultIndexGroupsAndNames);
- auto accelerations = gmx::splitString(is->acc);
- auto accelerationGroupNames = gmx::splitString(is->accgrps);
- if (accelerationGroupNames.size() * DIM != accelerations.size())
- {
- gmx_fatal(FARGS, "Invalid Acceleration input: %zu groups and %zu acc. values",
- accelerationGroupNames.size(), accelerations.size());
- }
- do_numbering(natoms, groups, accelerationGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::Acceleration,
- restnm, egrptpALL_GENREST, bVerbose, wi);
- nr = groups->groups[SimulationAtomGroupType::Acceleration].size();
- snew(ir->opts.acc, nr);
- ir->opts.ngacc = nr;
-
- convertRvecs(wi, accelerations, "anneal-time", ir->opts.acc);
-
- auto freezeDims = gmx::splitString(is->frdim);
- auto freezeGroupNames = gmx::splitString(is->freeze);
+ auto freezeDims = gmx::splitString(inputrecStrings->frdim);
+ auto freezeGroupNames = gmx::splitString(inputrecStrings->freeze);
if (freezeDims.size() != DIM * freezeGroupNames.size())
{
- gmx_fatal(FARGS, "Invalid Freezing input: %zu groups and %zu freeze values",
- freezeGroupNames.size(), freezeDims.size());
- }
- do_numbering(natoms, groups, freezeGroupNames, defaultIndexGroups, gnames,
+ gmx_fatal(FARGS,
+ "Invalid Freezing input: %zu groups and %zu freeze values",
+ freezeGroupNames.size(),
+ freezeDims.size());
+ }
+ do_numbering(natoms,
+ groups,
+ freezeGroupNames,
+ defaultIndexGroups,
+ gnames,
SimulationAtomGroupType::Freeze,
- restnm, egrptpALL_GENREST, bVerbose, wi);
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
nr = groups->groups[SimulationAtomGroupType::Freeze].size();
ir->opts.ngfrz = nr;
snew(ir->opts.nFreeze, nr);
{
if (!gmx::equalCaseInsensitive(freezeDims[k], "N", 1))
{
- sprintf(warnbuf, "Please use Y(ES) or N(O) for freezedim only "
- "(not %s)", freezeDims[k].c_str());
+ sprintf(warn_buf,
+ "Please use Y(ES) or N(O) for freezedim only "
+ "(not %s)",
+ freezeDims[k].c_str());
warning(wi, warn_buf);
}
}
}
}
- auto energyGroupNames = gmx::splitString(is->energy);
- do_numbering(natoms, groups, energyGroupNames, defaultIndexGroups, gnames,
+ auto energyGroupNames = gmx::splitString(inputrecStrings->energy);
+ do_numbering(natoms,
+ groups,
+ energyGroupNames,
+ defaultIndexGroups,
+ gnames,
SimulationAtomGroupType::EnergyOutput,
- restnm, egrptpALL_GENREST, bVerbose, wi);
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
add_wall_energrps(groups, ir->nwall, symtab);
- ir->opts.ngener = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
- auto vcmGroupNames = gmx::splitString(is->vcm);
- bRest =
- do_numbering(natoms, groups, vcmGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::MassCenterVelocityRemoval,
- restnm, vcmGroupNames.empty() ? egrptpALL_GENREST : egrptpPART, bVerbose, wi);
- if (bRest)
- {
- warning(wi, "Some atoms are not part of any center of mass motion removal group.\n"
- "This may lead to artifacts.\n"
- "In most cases one should use one group for the whole system.");
+ ir->opts.ngener = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
+ auto vcmGroupNames = gmx::splitString(inputrecStrings->vcm);
+ do_numbering(natoms,
+ groups,
+ vcmGroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::MassCenterVelocityRemoval,
+ restnm,
+ vcmGroupNames.empty() ? GroupCoverage::AllGenerateRest : GroupCoverage::Partial,
+ bVerbose,
+ wi);
+
+ if (ir->comm_mode != ComRemovalAlgorithm::No)
+ {
+ checkAndUpdateVcmFreezeGroupConsistency(groups, natoms, ir->opts, wi);
}
/* Now we have filled the freeze struct, so we can calculate NRDF */
calc_nrdf(mtop, ir, gnames);
- auto user1GroupNames = gmx::splitString(is->user1);
- do_numbering(natoms, groups, user1GroupNames, defaultIndexGroups, gnames,
+ auto user1GroupNames = gmx::splitString(inputrecStrings->user1);
+ do_numbering(natoms,
+ groups,
+ user1GroupNames,
+ defaultIndexGroups,
+ gnames,
SimulationAtomGroupType::User1,
- restnm, egrptpALL_GENREST, bVerbose, wi);
- auto user2GroupNames = gmx::splitString(is->user2);
- do_numbering(natoms, groups, user2GroupNames, defaultIndexGroups, gnames,
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
+ auto user2GroupNames = gmx::splitString(inputrecStrings->user2);
+ do_numbering(natoms,
+ groups,
+ user2GroupNames,
+ defaultIndexGroups,
+ gnames,
SimulationAtomGroupType::User2,
- restnm, egrptpALL_GENREST, bVerbose, wi);
- auto compressedXGroupNames = gmx::splitString(is->x_compressed_groups);
- do_numbering(natoms, groups, compressedXGroupNames, defaultIndexGroups, gnames,
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
+ auto compressedXGroupNames = gmx::splitString(inputrecStrings->x_compressed_groups);
+ do_numbering(natoms,
+ groups,
+ compressedXGroupNames,
+ defaultIndexGroups,
+ gnames,
SimulationAtomGroupType::CompressedPositionOutput,
- restnm, egrptpONE, bVerbose, wi);
- auto orirefFitGroupNames = gmx::splitString(is->orirefitgrp);
- do_numbering(natoms, groups, orirefFitGroupNames, defaultIndexGroups, gnames,
+ restnm,
+ GroupCoverage::OneGroup,
+ bVerbose,
+ wi);
+ auto orirefFitGroupNames = gmx::splitString(inputrecStrings->orirefitgrp);
+ do_numbering(natoms,
+ groups,
+ orirefFitGroupNames,
+ defaultIndexGroups,
+ gnames,
SimulationAtomGroupType::OrientationRestraintsFit,
- restnm, egrptpALL_GENREST, bVerbose, wi);
-
- /* QMMM input processing */
- auto qmGroupNames = gmx::splitString(is->QMMM);
- auto qmMethods = gmx::splitString(is->QMmethod);
- auto qmBasisSets = gmx::splitString(is->QMbasis);
- if (ir->eI != eiMimic)
- {
- if (qmMethods.size() != qmGroupNames.size() ||
- qmBasisSets.size() != qmGroupNames.size())
- {
- gmx_fatal(FARGS, "Invalid QMMM input: %zu groups %zu basissets"
- " and %zu methods\n", qmGroupNames.size(),
- qmBasisSets.size(), qmMethods.size());
- }
- /* group rest, if any, is always MM! */
- do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::QuantumMechanics,
- restnm, egrptpALL_GENREST, bVerbose, wi);
- nr = qmGroupNames.size(); /*atoms->grps[egcQMMM].nr;*/
- ir->opts.ngQM = qmGroupNames.size();
- snew(ir->opts.QMmethod, nr);
- snew(ir->opts.QMbasis, nr);
- for (i = 0; i < nr; i++)
- {
- /* input consists of strings: RHF CASSCF PM3 .. These need to be
- * converted to the corresponding enum in names.c
- */
- ir->opts.QMmethod[i] = search_QMstring(qmMethods[i].c_str(),
- eQMmethodNR,
- eQMmethod_names);
- ir->opts.QMbasis[i] = search_QMstring(qmBasisSets[i].c_str(),
- eQMbasisNR,
- eQMbasis_names);
-
- }
- auto qmMultiplicities = gmx::splitString(is->QMmult);
- auto qmCharges = gmx::splitString(is->QMcharge);
- auto qmbSH = gmx::splitString(is->bSH);
- snew(ir->opts.QMmult, nr);
- snew(ir->opts.QMcharge, nr);
- snew(ir->opts.bSH, nr);
- convertInts(wi, qmMultiplicities, "QMmult", ir->opts.QMmult);
- convertInts(wi, qmCharges, "QMcharge", ir->opts.QMcharge);
- convertYesNos(wi, qmbSH, "bSH", ir->opts.bSH);
-
- auto CASelectrons = gmx::splitString(is->CASelectrons);
- auto CASorbitals = gmx::splitString(is->CASorbitals);
- snew(ir->opts.CASelectrons, nr);
- snew(ir->opts.CASorbitals, nr);
- convertInts(wi, CASelectrons, "CASelectrons", ir->opts.CASelectrons);
- convertInts(wi, CASorbitals, "CASOrbitals", ir->opts.CASorbitals);
-
- auto SAon = gmx::splitString(is->SAon);
- auto SAoff = gmx::splitString(is->SAoff);
- auto SAsteps = gmx::splitString(is->SAsteps);
- snew(ir->opts.SAon, nr);
- snew(ir->opts.SAoff, nr);
- snew(ir->opts.SAsteps, nr);
- convertInts(wi, SAon, "SAon", ir->opts.SAon);
- convertInts(wi, SAoff, "SAoff", ir->opts.SAoff);
- convertInts(wi, SAsteps, "SAsteps", ir->opts.SAsteps);
- }
- else
- {
- /* MiMiC */
- if (qmGroupNames.size() > 1)
- {
- gmx_fatal(FARGS, "Currently, having more than one QM group in MiMiC is not supported");
- }
- /* group rest, if any, is always MM! */
- do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::QuantumMechanics,
- restnm, egrptpALL_GENREST, bVerbose, wi);
-
- ir->opts.ngQM = qmGroupNames.size();
- }
-
- /* end of QMMM input */
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
+
+ /* MiMiC QMMM input processing */
+ auto qmGroupNames = gmx::splitString(inputrecStrings->QMMM);
+ if (qmGroupNames.size() > 1)
+ {
+ gmx_fatal(FARGS, "Currently, having more than one QM group in MiMiC is not supported");
+ }
+ /* group rest, if any, is always MM! */
+ do_numbering(natoms,
+ groups,
+ qmGroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::QuantumMechanics,
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
+ ir->opts.ngQM = qmGroupNames.size();
+
+ /* end of MiMiC QMMM input */
if (bVerbose)
{
for (auto group : gmx::keysOf(groups->groups))
{
fprintf(stderr, "%-16s has %zu element(s):", shortName(group), groups->groups[group].size());
- for (const auto &entry : groups->groups[group])
+ for (const auto& entry : groups->groups[group])
{
fprintf(stderr, " %s", *(groups->groupNames[entry]));
}
}
nr = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
- snew(ir->opts.egp_flags, nr*nr);
+ snew(ir->opts.egp_flags, nr * nr);
- bExcl = do_egp_flag(ir, groups, "energygrp-excl", is->egpexcl, EGP_EXCL);
- if (bExcl && ir->cutoff_scheme == ecutsVERLET)
+ bExcl = do_egp_flag(ir, groups, "energygrp-excl", inputrecStrings->egpexcl, EGP_EXCL);
+ if (bExcl && ir->cutoff_scheme == CutoffScheme::Verlet)
{
- warning_error(wi, "Energy group exclusions are not (yet) implemented for the Verlet scheme");
+ warning_error(wi, "Energy group exclusions are currently not supported");
}
if (bExcl && EEL_FULL(ir->coulombtype))
{
warning(wi, "Can not exclude the lattice Coulomb energy between energy groups");
}
- bTable = do_egp_flag(ir, groups, "energygrp-table", is->egptable, EGP_TABLE);
- if (bTable && !(ir->vdwtype == evdwUSER) &&
- !(ir->coulombtype == eelUSER) && !(ir->coulombtype == eelPMEUSER) &&
- !(ir->coulombtype == eelPMEUSERSWITCH))
+ bTable = do_egp_flag(ir, groups, "energygrp-table", inputrecStrings->egptable, EGP_TABLE);
+ if (bTable && !(ir->vdwtype == VanDerWaalsType::User)
+ && !(ir->coulombtype == CoulombInteractionType::User)
+ && !(ir->coulombtype == CoulombInteractionType::PmeUser)
+ && !(ir->coulombtype == CoulombInteractionType::PmeUserSwitch))
{
- gmx_fatal(FARGS, "Can only have energy group pair tables in combination with user tables for VdW and/or Coulomb");
+ gmx_fatal(FARGS,
+ "Can only have energy group pair tables in combination with user tables for VdW "
+ "and/or Coulomb");
}
/* final check before going out of scope if simulated tempering variables
*/
if ((ir->expandedvals->nstexpanded < 0) && ir->bSimTemp)
{
- ir->expandedvals->nstexpanded = 2*static_cast<int>(ir->opts.tau_t[0]/ir->delta_t);
- warning(wi, gmx::formatString("the value for nstexpanded was not specified for "
- " expanded ensemble simulated tempering. It is set to 2*tau_t (%d) "
- "by default, but it is recommended to set it to an explicit value!",
- ir->expandedvals->nstexpanded));
+ ir->expandedvals->nstexpanded = 2 * static_cast<int>(ir->opts.tau_t[0] / ir->delta_t);
+ warning(wi,
+ gmx::formatString(
+ "the value for nstexpanded was not specified for "
+ " expanded ensemble simulated tempering. It is set to 2*tau_t (%d) "
+ "by default, but it is recommended to set it to an explicit value!",
+ ir->expandedvals->nstexpanded));
}
for (i = 0; (i < defaultIndexGroups->nr); i++)
{
sfree(gnames);
done_blocka(defaultIndexGroups);
sfree(defaultIndexGroups);
-
}
-
-static void check_disre(const gmx_mtop_t *mtop)
+static void check_disre(const gmx_mtop_t& mtop)
{
if (gmx_mtop_ftype_count(mtop, F_DISRES) > 0)
{
- const gmx_ffparams_t &ffparams = mtop->ffparams;
+ const gmx_ffparams_t& ffparams = mtop.ffparams;
int ndouble = 0;
int old_label = -1;
for (int i = 0; i < ffparams.numTypes(); i++)
}
if (ndouble > 0)
{
- gmx_fatal(FARGS, "Found %d double distance restraint indices,\n"
+ gmx_fatal(FARGS,
+ "Found %d double distance restraint indices,\n"
"probably the parameters for multiple pairs in one restraint "
- "are not identical\n", ndouble);
+ "are not identical\n",
+ ndouble);
}
}
}
-static bool absolute_reference(t_inputrec *ir, gmx_mtop_t *sys,
- bool posres_only,
- ivec AbsRef)
+//! Returns whether dimensions have an absolute reference due to walls, pbc or freezing
+static BasicVector<bool> haveAbsoluteReference(const t_inputrec& ir)
{
- int d, g, i;
- gmx_mtop_ilistloop_t iloop;
- int nmol;
- t_iparams *pr;
-
- clear_ivec(AbsRef);
+ BasicVector<bool> absRef = { false, false, false };
- if (!posres_only)
+ /* Check the degrees of freedom of the COM (not taking COMM removal into account) */
+ for (int d = 0; d < DIM; d++)
{
- /* Check the COM */
- for (d = 0; d < DIM; d++)
- {
- AbsRef[d] = (d < ndof_com(ir) ? 0 : 1);
- }
- /* Check for freeze groups */
- for (g = 0; g < ir->opts.ngfrz; g++)
+ absRef[d] = (d >= ndof_com(&ir));
+ }
+ /* Check for freeze groups */
+ for (int g = 0; g < ir.opts.ngfrz; g++)
+ {
+ for (int d = 0; d < DIM; d++)
{
- for (d = 0; d < DIM; d++)
+ if (ir.opts.nFreeze[g][d] != 0)
{
- if (ir->opts.nFreeze[g][d] != 0)
- {
- AbsRef[d] = 1;
- }
+ absRef[d] = true;
}
}
}
- /* Check for position restraints */
- iloop = gmx_mtop_ilistloop_init(sys);
- while (const InteractionLists *ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
+ return absRef;
+}
+
+//! Returns whether position restraints are used for dimensions
+static BasicVector<bool> havePositionRestraints(const gmx_mtop_t& sys)
+{
+ BasicVector<bool> havePosres = { false, false, false };
+
+ for (const auto ilists : IListRange(sys))
{
- if (nmol > 0 &&
- (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
+ const auto& posResList = ilists.list()[F_POSRES];
+ const auto& fbPosResList = ilists.list()[F_FBPOSRES];
+ if (ilists.nmol() > 0 && (!havePosres[XX] || !havePosres[YY] || !havePosres[ZZ]))
{
- for (i = 0; i < (*ilist)[F_POSRES].size(); i += 2)
+ for (int i = 0; i < posResList.size(); i += 2)
{
- pr = &sys->ffparams.iparams[(*ilist)[F_POSRES].iatoms[i]];
- for (d = 0; d < DIM; d++)
+ const t_iparams& pr = sys.ffparams.iparams[posResList.iatoms[i]];
+ for (int d = 0; d < DIM; d++)
{
- if (pr->posres.fcA[d] != 0)
+ if (pr.posres.fcA[d] != 0)
{
- AbsRef[d] = 1;
+ havePosres[d] = true;
}
}
}
- for (i = 0; i < (*ilist)[F_FBPOSRES].size(); i += 2)
+ for (int i = 0; i < fbPosResList.size(); i += 2)
{
/* Check for flat-bottom posres */
- pr = &sys->ffparams.iparams[(*ilist)[F_FBPOSRES].iatoms[i]];
- if (pr->fbposres.k != 0)
+ const t_iparams& pr = sys.ffparams.iparams[fbPosResList.iatoms[i]];
+ if (pr.fbposres.k != 0)
{
- switch (pr->fbposres.geom)
+ switch (pr.fbposres.geom)
{
- case efbposresSPHERE:
- AbsRef[XX] = AbsRef[YY] = AbsRef[ZZ] = 1;
- break;
- case efbposresCYLINDERX:
- AbsRef[YY] = AbsRef[ZZ] = 1;
- break;
- case efbposresCYLINDERY:
- AbsRef[XX] = AbsRef[ZZ] = 1;
- break;
+ case efbposresSPHERE: havePosres = { true, true, true }; break;
+ case efbposresCYLINDERX: havePosres[YY] = havePosres[ZZ] = true; break;
+ case efbposresCYLINDERY: havePosres[XX] = havePosres[ZZ] = true; break;
case efbposresCYLINDER:
/* efbposres is a synonym for efbposresCYLINDERZ for backwards compatibility */
- case efbposresCYLINDERZ:
- AbsRef[XX] = AbsRef[YY] = 1;
- break;
+ case efbposresCYLINDERZ: havePosres[XX] = havePosres[YY] = true; break;
case efbposresX: /* d=XX */
case efbposresY: /* d=YY */
case efbposresZ: /* d=ZZ */
- d = pr->fbposres.geom - efbposresX;
- AbsRef[d] = 1;
+ havePosres[pr.fbposres.geom - efbposresX] = true;
break;
default:
- gmx_fatal(FARGS, " Invalid geometry for flat-bottom position restraint.\n"
- "Expected nr between 1 and %d. Found %d\n", efbposresNR-1,
- pr->fbposres.geom);
+ gmx_fatal(FARGS,
+ "Invalid geometry for flat-bottom position restraint.\n"
+ "Expected nr between 1 and %d. Found %d\n",
+ efbposresNR - 1,
+ pr.fbposres.geom);
}
}
}
}
}
- return (AbsRef[XX] != 0 && AbsRef[YY] != 0 && AbsRef[ZZ] != 0);
+ return havePosres;
}
-static void
-check_combination_rule_differences(const gmx_mtop_t *mtop, int state,
- bool *bC6ParametersWorkWithGeometricRules,
- bool *bC6ParametersWorkWithLBRules,
- bool *bLBRulesPossible)
+static void check_combination_rule_differences(const gmx_mtop_t& mtop,
+ int state,
+ bool* bC6ParametersWorkWithGeometricRules,
+ bool* bC6ParametersWorkWithLBRules,
+ bool* bLBRulesPossible)
{
- int ntypes, tpi, tpj;
- int *typecount;
- real tol;
- double c6i, c6j, c12i, c12j;
- double c6, c6_geometric, c6_LB;
- double sigmai, sigmaj, epsi, epsj;
- bool bCanDoLBRules, bCanDoGeometricRules;
- const char *ptr;
+ int ntypes, tpi, tpj;
+ int* typecount;
+ real tol;
+ double c6i, c6j, c12i, c12j;
+ double c6, c6_geometric, c6_LB;
+ double sigmai, sigmaj, epsi, epsj;
+ bool bCanDoLBRules, bCanDoGeometricRules;
+ const char* ptr;
/* A tolerance of 1e-5 seems reasonable for (possibly hand-typed)
* force-field floating point parameters.
if (sscanf(ptr, "%lf%lf", &dbl, &canary) != 1)
{
- gmx_fatal(FARGS, "Could not parse a single floating-point number from GMX_LJCOMB_TOL (%s)", ptr);
+ gmx_fatal(
+ FARGS, "Could not parse a single floating-point number from GMX_LJCOMB_TOL (%s)", ptr);
}
tol = dbl;
}
- *bC6ParametersWorkWithLBRules = TRUE;
- *bC6ParametersWorkWithGeometricRules = TRUE;
- bCanDoLBRules = TRUE;
- ntypes = mtop->ffparams.atnr;
+ *bC6ParametersWorkWithLBRules = TRUE;
+ *bC6ParametersWorkWithGeometricRules = TRUE;
+ bCanDoLBRules = TRUE;
+ ntypes = mtop.ffparams.atnr;
snew(typecount, ntypes);
gmx_mtop_count_atomtypes(mtop, state, typecount);
- *bLBRulesPossible = TRUE;
+ *bLBRulesPossible = TRUE;
for (tpi = 0; tpi < ntypes; ++tpi)
{
- c6i = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c6;
- c12i = mtop->ffparams.iparams[(ntypes + 1) * tpi].lj.c12;
+ c6i = mtop.ffparams.iparams[(ntypes + 1) * tpi].lj.c6;
+ c12i = mtop.ffparams.iparams[(ntypes + 1) * tpi].lj.c12;
for (tpj = tpi; tpj < ntypes; ++tpj)
{
- c6j = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c6;
- c12j = mtop->ffparams.iparams[(ntypes + 1) * tpj].lj.c12;
- c6 = mtop->ffparams.iparams[ntypes * tpi + tpj].lj.c6;
+ c6j = mtop.ffparams.iparams[(ntypes + 1) * tpj].lj.c6;
+ c12j = mtop.ffparams.iparams[(ntypes + 1) * tpj].lj.c12;
+ c6 = mtop.ffparams.iparams[ntypes * tpi + tpj].lj.c6;
c6_geometric = std::sqrt(c6i * c6j);
if (!gmx_numzero(c6_geometric))
{
if (!gmx_numzero(c12i) && !gmx_numzero(c12j))
{
- sigmai = gmx::sixthroot(c12i / c6i);
- sigmaj = gmx::sixthroot(c12j / c6j);
- epsi = c6i * c6i /(4.0 * c12i);
- epsj = c6j * c6j /(4.0 * c12j);
- c6_LB = 4.0 * std::sqrt(epsi * epsj) * gmx::power6(0.5 * (sigmai + sigmaj));
+ sigmai = gmx::sixthroot(c12i / c6i);
+ sigmaj = gmx::sixthroot(c12j / c6j);
+ epsi = c6i * c6i / (4.0 * c12i);
+ epsj = c6j * c6j / (4.0 * c12j);
+ c6_LB = 4.0 * std::sqrt(epsi * epsj) * gmx::power6(0.5 * (sigmai + sigmaj));
}
else
{
sfree(typecount);
}
-static void
-check_combination_rules(const t_inputrec *ir, const gmx_mtop_t *mtop,
- warninp_t wi)
+static void check_combination_rules(const t_inputrec* ir, const gmx_mtop_t& mtop, warninp_t wi)
{
bool bLBRulesPossible, bC6ParametersWorkWithGeometricRules, bC6ParametersWorkWithLBRules;
- check_combination_rule_differences(mtop, 0,
- &bC6ParametersWorkWithGeometricRules,
- &bC6ParametersWorkWithLBRules,
- &bLBRulesPossible);
- if (ir->ljpme_combination_rule == eljpmeLB)
+ check_combination_rule_differences(
+ mtop, 0, &bC6ParametersWorkWithGeometricRules, &bC6ParametersWorkWithLBRules, &bLBRulesPossible);
+ if (ir->ljpme_combination_rule == LongRangeVdW::LB)
{
if (!bC6ParametersWorkWithLBRules || !bLBRulesPossible)
{
- warning(wi, "You are using arithmetic-geometric combination rules "
+ warning(wi,
+ "You are using arithmetic-geometric combination rules "
"in LJ-PME, but your non-bonded C6 parameters do not "
"follow these rules.");
}
{
if (!bC6ParametersWorkWithGeometricRules)
{
- if (ir->eDispCorr != edispcNO)
+ if (ir->eDispCorr != DispersionCorrectionType::No)
{
- warning_note(wi, "You are using geometric combination rules in "
+ warning_note(wi,
+ "You are using geometric combination rules in "
"LJ-PME, but your non-bonded C6 parameters do "
"not follow these rules. "
"This will introduce very small errors in the forces and energies in "
"your simulations. Dispersion correction will correct total energy "
- "and/or pressure for isotropic systems, but not forces or surface tensions.");
+ "and/or pressure for isotropic systems, but not forces or surface "
+ "tensions.");
}
else
{
- warning_note(wi, "You are using geometric combination rules in "
+ warning_note(wi,
+ "You are using geometric combination rules in "
"LJ-PME, but your non-bonded C6 parameters do "
"not follow these rules. "
"This will introduce very small errors in the forces and energies in "
- "your simulations. If your system is homogeneous, consider using dispersion correction "
+ "your simulations. If your system is homogeneous, consider using "
+ "dispersion correction "
"for the total energy and pressure.");
}
}
}
}
-void triple_check(const char *mdparin, t_inputrec *ir, gmx_mtop_t *sys,
- warninp_t wi)
+static bool allTrue(const BasicVector<bool>& boolVector)
{
+ return boolVector[0] && boolVector[1] && boolVector[2];
+}
+
+void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_t wi)
+{
+ // Not meeting MTS requirements should have resulted in a fatal error, so we can assert here
+ GMX_ASSERT(gmx::checkMtsRequirements(*ir).empty(), "All MTS requirements should be met here");
+
char err_buf[STRLEN];
int i, m, c, nmol;
- bool bCharge, bAcc;
- real *mgrp, mt;
- rvec acc;
+ bool bCharge;
gmx_mtop_atomloop_block_t aloopb;
- ivec AbsRef;
char warn_buf[STRLEN];
set_warning_line(wi, mdparin, -1);
- if (ir->cutoff_scheme == ecutsVERLET &&
- ir->verletbuf_tol > 0 &&
- ir->nstlist > 1 &&
- ((EI_MD(ir->eI) || EI_SD(ir->eI)) &&
- (ir->etc == etcVRESCALE || ir->etc == etcBERENDSEN)))
+ if (ir->comm_mode != ComRemovalAlgorithm::No && allTrue(havePositionRestraints(*sys)))
+ {
+ warning_note(wi,
+ "Removing center of mass motion in the presence of position restraints might "
+ "cause artifacts. When you are using position restraints to equilibrate a "
+ "macro-molecule, the artifacts are usually negligible.");
+ }
+
+ if (ir->cutoff_scheme == CutoffScheme::Verlet && ir->verletbuf_tol > 0 && ir->nstlist > 1
+ && ((EI_MD(ir->eI) || EI_SD(ir->eI))
+ && (ir->etc == TemperatureCoupling::VRescale || ir->etc == TemperatureCoupling::Berendsen)))
{
/* Check if a too small Verlet buffer might potentially
* cause more drift than the thermostat can couple off.
const real T_error_warn = 0.002;
const real T_error_suggest = 0.001;
/* For safety: 2 DOF per atom (typical with constraints) */
- const real nrdf_at = 2;
+ const real nrdf_at = 2;
real T, tau, max_T_error;
int i;
* of errors. The factor 0.5 is because energy distributes
* equally over Ekin and Epot.
*/
- max_T_error = 0.5*tau*ir->verletbuf_tol/(nrdf_at*BOLTZ*T);
+ max_T_error = 0.5 * tau * ir->verletbuf_tol / (nrdf_at * gmx::c_boltz * T);
if (max_T_error > T_error_warn)
{
- sprintf(warn_buf, "With a verlet-buffer-tolerance of %g kJ/mol/ps, a reference temperature of %g and a tau_t of %g, your temperature might be off by up to %.1f%%. To ensure the error is below %.1f%%, decrease verlet-buffer-tolerance to %.0e or decrease tau_t.",
- ir->verletbuf_tol, T, tau,
- 100*max_T_error,
- 100*T_error_suggest,
- ir->verletbuf_tol*T_error_suggest/max_T_error);
+ sprintf(warn_buf,
+ "With a verlet-buffer-tolerance of %g kJ/mol/ps, a reference temperature "
+ "of %g and a tau_t of %g, your temperature might be off by up to %.1f%%. "
+ "To ensure the error is below %.1f%%, decrease verlet-buffer-tolerance to "
+ "%.0e or decrease tau_t.",
+ ir->verletbuf_tol,
+ T,
+ tau,
+ 100 * max_T_error,
+ 100 * T_error_suggest,
+ ir->verletbuf_tol * T_error_suggest / max_T_error);
warning(wi, warn_buf);
}
}
for (i = 0; i < ir->opts.ngtc; i++)
{
- sprintf(err_buf, "all tau_t must currently be equal using Andersen temperature control, violated for group %d", i);
+ sprintf(err_buf,
+ "all tau_t must currently be equal using Andersen temperature control, "
+ "violated for group %d",
+ i);
CHECK(ir->opts.tau_t[0] != ir->opts.tau_t[i]);
- sprintf(err_buf, "all tau_t must be positive using Andersen temperature control, tau_t[%d]=%10.6f",
- i, ir->opts.tau_t[i]);
+ sprintf(err_buf,
+ "all tau_t must be positive using Andersen temperature control, "
+ "tau_t[%d]=%10.6f",
+ i,
+ ir->opts.tau_t[i]);
CHECK(ir->opts.tau_t[i] < 0);
}
- if (ir->etc == etcANDERSENMASSIVE && ir->comm_mode != ecmNO)
+ if (ir->etc == TemperatureCoupling::AndersenMassive && ir->comm_mode != ComRemovalAlgorithm::No)
{
for (i = 0; i < ir->opts.ngtc; i++)
{
- int nsteps = gmx::roundToInt(ir->opts.tau_t[i]/ir->delta_t);
- sprintf(err_buf, "tau_t/delta_t for group %d for temperature control method %s must be a multiple of nstcomm (%d), as velocities of atoms in coupled groups are randomized every time step. The input tau_t (%8.3f) leads to %d steps per randomization", i, etcoupl_names[ir->etc], ir->nstcomm, ir->opts.tau_t[i], nsteps);
+ int nsteps = gmx::roundToInt(ir->opts.tau_t[i] / ir->delta_t);
+ sprintf(err_buf,
+ "tau_t/delta_t for group %d for temperature control method %s must be a "
+ "multiple of nstcomm (%d), as velocities of atoms in coupled groups are "
+ "randomized every time step. The input tau_t (%8.3f) leads to %d steps per "
+ "randomization",
+ i,
+ enumValueToString(ir->etc),
+ ir->nstcomm,
+ ir->opts.tau_t[i],
+ nsteps);
CHECK(nsteps % ir->nstcomm != 0);
}
}
}
- if (EI_DYNAMICS(ir->eI) && !EI_SD(ir->eI) && ir->eI != eiBD &&
- ir->comm_mode == ecmNO &&
- !(absolute_reference(ir, sys, FALSE, AbsRef) || ir->nsteps <= 10) &&
- !ETC_ANDERSEN(ir->etc))
+ if (EI_DYNAMICS(ir->eI) && !EI_SD(ir->eI) && ir->eI != IntegrationAlgorithm::BD
+ && ir->comm_mode == ComRemovalAlgorithm::No
+ && !(allTrue(haveAbsoluteReference(*ir)) || allTrue(havePositionRestraints(*sys)) || ir->nsteps <= 10)
+ && !ETC_ANDERSEN(ir->etc))
{
- warning(wi, "You are not using center of mass motion removal (mdp option comm-mode), numerical rounding errors can lead to build up of kinetic energy of the center of mass");
+ warning(wi,
+ "You are not using center of mass motion removal (mdp option comm-mode), numerical "
+ "rounding errors can lead to build up of kinetic energy of the center of mass");
}
- if (ir->epc == epcPARRINELLORAHMAN &&
- ir->etc == etcNOSEHOOVER)
+ if (ir->epc == PressureCoupling::ParrinelloRahman && ir->etc == TemperatureCoupling::NoseHoover)
{
real tau_t_max = 0;
for (int g = 0; g < ir->opts.ngtc; g++)
{
tau_t_max = std::max(tau_t_max, ir->opts.tau_t[g]);
}
- if (ir->tau_p < 1.9*tau_t_max)
- {
- std::string message =
- gmx::formatString("With %s T-coupling and %s p-coupling, "
- "%s (%g) should be at least twice as large as %s (%g) to avoid resonances",
- etcoupl_names[ir->etc],
- epcoupl_names[ir->epc],
- "tau-p", ir->tau_p,
- "tau-t", tau_t_max);
+ if (ir->tau_p < 1.9 * tau_t_max)
+ {
+ std::string message = gmx::formatString(
+ "With %s T-coupling and %s p-coupling, "
+ "%s (%g) should be at least twice as large as %s (%g) to avoid resonances",
+ enumValueToString(ir->etc),
+ enumValueToString(ir->epc),
+ "tau-p",
+ ir->tau_p,
+ "tau-t",
+ tau_t_max);
warning(wi, message.c_str());
}
}
/* Check for pressure coupling with absolute position restraints */
- if (ir->epc != epcNO && ir->refcoord_scaling == erscNO)
+ if (ir->epc != PressureCoupling::No && ir->refcoord_scaling == RefCoordScaling::No)
{
- absolute_reference(ir, sys, TRUE, AbsRef);
+ const BasicVector<bool> havePosres = havePositionRestraints(*sys);
{
for (m = 0; m < DIM; m++)
{
- if (AbsRef[m] && norm2(ir->compress[m]) > 0)
+ if (havePosres[m] && norm2(ir->compress[m]) > 0)
{
- warning(wi, "You are using pressure coupling with absolute position restraints, this will give artifacts. Use the refcoord_scaling option.");
+ warning(wi,
+ "You are using pressure coupling with absolute position restraints, "
+ "this will give artifacts. Use the refcoord_scaling option.");
break;
}
}
}
bCharge = FALSE;
- aloopb = gmx_mtop_atomloop_block_init(sys);
- const t_atom *atom;
+ aloopb = gmx_mtop_atomloop_block_init(*sys);
+ const t_atom* atom;
while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
{
if (atom->q != 0 || atom->qB != 0)
{
sprintf(err_buf,
"You are using full electrostatics treatment %s for a system without charges.\n"
- "This costs a lot of performance for just processing zeros, consider using %s instead.\n",
- EELTYPE(ir->coulombtype), EELTYPE(eelCUT));
+ "This costs a lot of performance for just processing zeros, consider using %s "
+ "instead.\n",
+ enumValueToString(ir->coulombtype),
+ enumValueToString(CoulombInteractionType::Cut));
warning(wi, err_buf);
}
}
else
{
- if (ir->coulombtype == eelCUT && ir->rcoulomb > 0)
+ if (ir->coulombtype == CoulombInteractionType::Cut && ir->rcoulomb > 0)
{
sprintf(err_buf,
"You are using a plain Coulomb cut-off, which might produce artifacts.\n"
"You might want to consider using %s electrostatics.\n",
- EELTYPE(eelPME));
+ enumValueToString(CoulombInteractionType::Pme));
warning_note(wi, err_buf);
}
}
/* Check if combination rules used in LJ-PME are the same as in the force field */
if (EVDW_PME(ir->vdwtype))
{
- check_combination_rules(ir, sys, wi);
+ check_combination_rules(ir, *sys, wi);
}
/* Generalized reaction field */
- if (ir->coulombtype == eelGRF_NOTUSED)
- {
- warning_error(wi, "Generalized reaction-field electrostatics is no longer supported. "
- "You can use normal reaction-field instead and compute the reaction-field constant by hand.");
- }
-
- bAcc = FALSE;
- for (int i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
- {
- for (m = 0; (m < DIM); m++)
- {
- if (fabs(ir->opts.acc[i][m]) > 1e-6)
- {
- bAcc = TRUE;
- }
- }
- }
- if (bAcc)
+ if (ir->coulombtype == CoulombInteractionType::GRFNotused)
{
- clear_rvec(acc);
- snew(mgrp, sys->groups.groups[SimulationAtomGroupType::Acceleration].size());
- for (const AtomProxy atomP : AtomRange(*sys))
- {
- const t_atom &local = atomP.atom();
- int i = atomP.globalAtomNumber();
- mgrp[getGroupType(sys->groups, SimulationAtomGroupType::Acceleration, i)] += local.m;
- }
- mt = 0.0;
- for (i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
- {
- for (m = 0; (m < DIM); m++)
- {
- acc[m] += ir->opts.acc[i][m]*mgrp[i];
- }
- mt += mgrp[i];
- }
- for (m = 0; (m < DIM); m++)
- {
- if (fabs(acc[m]) > 1e-6)
- {
- const char *dim[DIM] = { "X", "Y", "Z" };
- fprintf(stderr,
- "Net Acceleration in %s direction, will %s be corrected\n",
- dim[m], ir->nstcomm != 0 ? "" : "not");
- if (ir->nstcomm != 0 && m < ndof_com(ir))
- {
- acc[m] /= mt;
- for (i = 0; (i < gmx::ssize(sys->groups.groups[SimulationAtomGroupType::Acceleration])); i++)
- {
- ir->opts.acc[i][m] -= acc[m];
- }
- }
- }
- }
- sfree(mgrp);
+ warning_error(wi,
+ "Generalized reaction-field electrostatics is no longer supported. "
+ "You can use normal reaction-field instead and compute the reaction-field "
+ "constant by hand.");
}
- if (ir->efep != efepNO && ir->fepvals->sc_alpha != 0 &&
- !gmx_within_tol(sys->ffparams.reppow, 12.0, 10*GMX_DOUBLE_EPS))
+ if (ir->efep != FreeEnergyPerturbationType::No && ir->fepvals->sc_alpha != 0
+ && !gmx_within_tol(sys->ffparams.reppow, 12.0, 10 * GMX_DOUBLE_EPS))
{
gmx_fatal(FARGS, "Soft-core interactions are only supported with VdW repulsion power 12");
}
bWarned = FALSE;
for (i = 0; i < ir->pull->ncoord && !bWarned; i++)
{
- if (ir->pull->coord[i].group[0] == 0 ||
- ir->pull->coord[i].group[1] == 0)
+ if (ir->pull->coord[i].eGeom != PullGroupGeometry::Transformation
+ && (ir->pull->coord[i].group[0] == 0 || ir->pull->coord[i].group[1] == 0))
{
- absolute_reference(ir, sys, FALSE, AbsRef);
+ const auto absRef = haveAbsoluteReference(*ir);
+ const auto havePosres = havePositionRestraints(*sys);
for (m = 0; m < DIM; m++)
{
- if (ir->pull->coord[i].dim[m] && !AbsRef[m])
+ if (ir->pull->coord[i].dim[m] && !(absRef[m] || havePosres[m]))
{
- warning(wi, "You are using an absolute reference for pulling, but the rest of the system does not have an absolute reference. This will lead to artifacts.");
+ warning(wi,
+ "You are using an absolute reference for pulling, but the rest of "
+ "the system does not have an absolute reference. This will lead to "
+ "artifacts.");
bWarned = TRUE;
break;
}
{
for (m = 0; m <= i; m++)
{
- if ((ir->epc != epcNO && ir->compress[i][m] != 0) ||
- ir->deform[i][m] != 0)
+ if ((ir->epc != PressureCoupling::No && ir->compress[i][m] != 0) || ir->deform[i][m] != 0)
{
for (c = 0; c < ir->pull->ncoord; c++)
{
- if (ir->pull->coord[c].eGeom == epullgDIRPBC &&
- ir->pull->coord[c].vec[m] != 0)
+ if (ir->pull->coord[c].eGeom == PullGroupGeometry::DirectionPBC
+ && ir->pull->coord[c].vec[m] != 0)
{
- gmx_fatal(FARGS, "Can not have dynamic box while using pull geometry '%s' (dim %c)", EPULLGEOM(ir->pull->coord[c].eGeom), 'x'+m);
+ gmx_fatal(FARGS,
+ "Can not have dynamic box while using pull geometry '%s' "
+ "(dim %c)",
+ enumValueToString(ir->pull->coord[c].eGeom),
+ 'x' + m);
}
}
}
}
}
- check_disre(sys);
+ check_disre(*sys);
}
-void double_check(t_inputrec *ir, matrix box,
- bool bHasNormalConstraints,
- bool bHasAnyConstraints,
- warninp_t wi)
+void double_check(t_inputrec* ir, matrix box, bool bHasNormalConstraints, bool bHasAnyConstraints, warninp_t wi)
{
char warn_buf[STRLEN];
- const char *ptr;
+ const char* ptr;
- ptr = check_box(ir->ePBC, box);
+ ptr = check_box(ir->pbcType, box);
if (ptr)
{
warning_error(wi, ptr);
}
- if (bHasNormalConstraints && ir->eConstrAlg == econtSHAKE)
+ if (bHasNormalConstraints && ir->eConstrAlg == ConstraintAlgorithm::Shake)
{
if (ir->shake_tol <= 0.0)
{
- sprintf(warn_buf, "ERROR: shake-tol must be > 0 instead of %g\n",
- ir->shake_tol);
+ sprintf(warn_buf, "ERROR: shake-tol must be > 0 instead of %g\n", ir->shake_tol);
warning_error(wi, warn_buf);
}
}
- if ( (ir->eConstrAlg == econtLINCS) && bHasNormalConstraints)
+ if ((ir->eConstrAlg == ConstraintAlgorithm::Lincs) && bHasNormalConstraints)
{
/* If we have Lincs constraints: */
- if (ir->eI == eiMD && ir->etc == etcNO &&
- ir->eConstrAlg == econtLINCS && ir->nLincsIter == 1)
+ if (ir->eI == IntegrationAlgorithm::MD && ir->etc == TemperatureCoupling::No
+ && ir->eConstrAlg == ConstraintAlgorithm::Lincs && ir->nLincsIter == 1)
{
- sprintf(warn_buf, "For energy conservation with LINCS, lincs_iter should be 2 or larger.\n");
+ sprintf(warn_buf,
+ "For energy conservation with LINCS, lincs_iter should be 2 or larger.\n");
warning_note(wi, warn_buf);
}
- if ((ir->eI == eiCG || ir->eI == eiLBFGS) && (ir->nProjOrder < 8))
+ if ((ir->eI == IntegrationAlgorithm::CG || ir->eI == IntegrationAlgorithm::LBFGS)
+ && (ir->nProjOrder < 8))
{
- sprintf(warn_buf, "For accurate %s with LINCS constraints, lincs-order should be 8 or more.", ei_names[ir->eI]);
+ sprintf(warn_buf,
+ "For accurate %s with LINCS constraints, lincs-order should be 8 or more.",
+ enumValueToString(ir->eI));
warning_note(wi, warn_buf);
}
- if (ir->epc == epcMTTK)
+ if (ir->epc == PressureCoupling::Mttk)
{
warning_error(wi, "MTTK not compatible with lincs -- use shake instead.");
}
}
- if (bHasAnyConstraints && ir->epc == epcMTTK)
+ if (bHasAnyConstraints && ir->epc == PressureCoupling::Mttk)
{
warning_error(wi, "Constraints are not implemented with MTTK pressure control.");
}
ir->LincsWarnAngle = 90.0;
}
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
if (ir->nstlist == 0)
{
- warning(wi, "With nstlist=0 atoms are only put into the box at step 0, therefore drifting atoms might cause the simulation to crash.");
- }
- if (gmx::square(ir->rlist) >= max_cutoff2(ir->ePBC, box))
- {
- sprintf(warn_buf, "ERROR: The cut-off length is longer than half the shortest box vector or longer than the smallest box diagonal element. Increase the box size or decrease rlist.\n");
- warning_error(wi, warn_buf);
+ warning(wi,
+ "With nstlist=0 atoms are only put into the box at step 0, therefore drifting "
+ "atoms might cause the simulation to crash.");
}
- }
-}
-
-void check_chargegroup_radii(const gmx_mtop_t *mtop, const t_inputrec *ir,
- rvec *x,
- warninp_t wi)
-{
- real rvdw1, rvdw2, rcoul1, rcoul2;
- char warn_buf[STRLEN];
-
- calc_chargegroup_radii(mtop, x, &rvdw1, &rvdw2, &rcoul1, &rcoul2);
-
- if (rvdw1 > 0)
- {
- printf("Largest charge group radii for Van der Waals: %5.3f, %5.3f nm\n",
- rvdw1, rvdw2);
- }
- if (rcoul1 > 0)
- {
- printf("Largest charge group radii for Coulomb: %5.3f, %5.3f nm\n",
- rcoul1, rcoul2);
- }
-
- if (ir->rlist > 0)
- {
- if (rvdw1 + rvdw2 > ir->rlist ||
- rcoul1 + rcoul2 > ir->rlist)
+ if (gmx::square(ir->rlist) >= max_cutoff2(ir->pbcType, box))
{
sprintf(warn_buf,
- "The sum of the two largest charge group radii (%f) "
- "is larger than rlist (%f)\n",
- std::max(rvdw1+rvdw2, rcoul1+rcoul2), ir->rlist);
- warning(wi, warn_buf);
- }
- else
- {
- /* Here we do not use the zero at cut-off macro,
- * since user defined interactions might purposely
- * not be zero at the cut-off.
- */
- if (ir_vdw_is_zero_at_cutoff(ir) &&
- rvdw1 + rvdw2 > ir->rlist - ir->rvdw)
- {
- sprintf(warn_buf, "The sum of the two largest charge group "
- "radii (%f) is larger than rlist (%f) - rvdw (%f).\n"
- "With exact cut-offs, better performance can be "
- "obtained with cutoff-scheme = %s, because it "
- "does not use charge groups at all.",
- rvdw1+rvdw2,
- ir->rlist, ir->rvdw,
- ecutscheme_names[ecutsVERLET]);
- if (ir_NVE(ir))
- {
- warning(wi, warn_buf);
- }
- else
- {
- warning_note(wi, warn_buf);
- }
- }
- if (ir_coulomb_is_zero_at_cutoff(ir) &&
- rcoul1 + rcoul2 > ir->rlist - ir->rcoulomb)
- {
- sprintf(warn_buf, "The sum of the two largest charge group radii (%f) is larger than rlist (%f) - rcoulomb (%f).\n"
- "With exact cut-offs, better performance can be obtained with cutoff-scheme = %s, because it does not use charge groups at all.",
- rcoul1+rcoul2,
- ir->rlist, ir->rcoulomb,
- ecutscheme_names[ecutsVERLET]);
- if (ir_NVE(ir))
- {
- warning(wi, warn_buf);
- }
- else
- {
- warning_note(wi, warn_buf);
- }
- }
+ "ERROR: The cut-off length is longer than half the shortest box vector or "
+ "longer than the smallest box diagonal element. Increase the box size or "
+ "decrease rlist.\n");
+ warning_error(wi, warn_buf);
}
}
}