*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013-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/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
+using gmx::BasicVector;
+
/* Resource parameters
* Do not change any of these until you read the instruction
* in readinp.h. Some cpp's do not take spaces after the backslash
* 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.");
}
- snew(is, 1);
+ inputrecStrings = new gmx_inputrec_strings();
}
void done_inputrec_strings()
{
- sfree(is);
- is = nullptr;
+ delete inputrecStrings;
+ inputrecStrings = nullptr;
}
-enum
+//! How to treat coverage of the whole system for a set of atom groupsx
+enum class GroupCoverage
{
- 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. */
+ 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
};
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
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* 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];
}
else if (simtemp->eSimTempScale
- == esimtempGEOMETRIC) /* should give roughly equal acceptance for constant heat capacity . . . */
+ == 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)));
}
- else if (simtemp->eSimTempScale == esimtempEXPONENTIAL)
+ else if (simtemp->eSimTempScale == SimulatedTempering::Exponential)
{
simtemp->temperatures[i] = simtemp->simtemp_low
+ (simtemp->simtemp_high - simtemp->simtemp_low)
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 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");
}
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,
}
}
- 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);
+ 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",
- evdw_names[ir->vdwtype], evdw_names[evdwCUT], eintmod_names[ir->vdw_modifier]);
+ 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");
}
- 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");
}
- 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);
}
/* GENERAL INTEGRATOR STUFF */
if (!EI_MD(ir->eI))
{
- if (ir->etc != etcNO)
+ if (ir->etc != TemperatureCoupling::No)
{
if (EI_RANDOM(ir->eI))
{
"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]);
+ 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]);
+ 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]);
+ 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]);
+ 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->efep != FreeEnergyPerturbationType::No && ir->fepvals->nstdhdl > 0
&& (ir->nstcalcenergy > ir->fepvals->nstdhdl)))
{
int min_nst = ir->nstenergy;
/* find the smallest of ( nstenergy, nstdhdl ) */
- if (ir->efep != efepNO && ir->fepvals->nstdhdl > 0
+ 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);
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);
}
- // 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 :
}
/* 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 "
/* 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");
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 "
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]);
+ enumValueToString(ir->etc));
warning_note(wi, warn_buf);
}
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);
+ 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",
+ 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",
+ 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;
+ 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 "
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",
+ 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));
+ 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)
{
/* Clear output in case of no states:*/
- sprintf(err_buf, "init-lambda-state set to %d: no lambda states are defined.",
- fep->init_fep_state);
+ sprintf(err_buf, "init-lambda-state set to %d: no lambda states are defined.", fep->init_fep_state);
CHECK((fep->init_fep_state >= 0) && (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,
"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);
+ fep->init_lambda,
+ fep->init_fep_state);
CHECK((fep->init_fep_state >= 0) && (fep->init_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])
{
}
}
- 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 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]);
+ 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[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))));
+ && (((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))));
}
}
"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);
+ fep->sc_r_power,
+ 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));
+ 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));
+ 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));
+ 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));
+ 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));
+ 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));
+ 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));
+ 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));
+ 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));
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);
+ fep->init_fep_state,
+ expand->lmc_forced_nstart);
CHECK((fep->init_fep_state != 0) && (expand->lmc_forced_nstart > 0)
- && (expand->elmcmove != elmcmoveNO));
+ && (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)",
+ 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));
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 "
{
sprintf(err_buf,
"nst-transition-matrix (%d) must be an integer multiple of nstlog (%d)",
- expand->nstTij, ir->nstlog);
+ 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)
"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)
{
{
// 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)
{
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;
+ "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");
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, "
}
}
- 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]);
+ enumValueToString(IntegrationAlgorithm::SD1));
warning_note(wi, warn_buf);
}
/* TEMPERATURE COUPLING */
- if (ir->etc == etcYES)
+ if (ir->etc == TemperatureCoupling::Yes)
{
- ir->etc = etcBERENDSEN;
+ 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)
{
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,
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]);
+ 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]);
+ 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));
+ 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));
+ 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 "
}
/* PRESSURE COUPLING */
- if (ir->epc == epcISOTROPIC)
+ if (ir->epc == PressureCoupling::Isotropic)
{
- ir->epc = epcBERENDSEN;
+ 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;
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);
+ 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));
+ 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 "
"artifacts, advice: use coulombtype = %s",
- eel_names[ir->coulombtype], eel_names[eelRF_ZERO]);
+ enumValueToString(ir->coulombtype),
+ enumValueToString(CoulombInteractionType::RFZero));
warning(wi, warn_buf);
}
{
/* 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]);
+ enumValueToString(ir->coulombtype));
warning(wi, warn_buf);
ir->epsilon_rf = 0.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);
}
}
sprintf(err_buf,
"With coulombtype = %s rcoulomb_switch must be < rcoulomb. Or, better: Use the "
"potential modifier options!",
- eel_names[ir->coulombtype]);
+ 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);
+ 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);
+ 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 "
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)
{
"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);
+ 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)
{
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))
"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);
+ 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 "
"really want dispersion correction to -C6/r^6.");
}
- if (ir->eI == eiLBFGS && (ir->coulombtype == eelCUT || ir->vdwtype == evdwCUT) && ir->rvdw != 0)
+ 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)
{
- warning_error(wi, "QMMM is currently not supported");
- 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();
- 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&)
{
- 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)
{
}
}
- 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
+ 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;
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);
+ 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);
+ fep->all_lambda[i].resize(fep->n_lambda);
if (nfep[i] > 0) /* if it's zero, then the count_fep_lambda arrays
are zero */
{
{
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 */
- 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)
{
-
- 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>
auto message = gmx::formatString(
"Invalid value for mdp option %s. %s should only consist of integers separated "
"by spaces.",
- name, name);
+ name,
+ name);
warning_error(wi, message);
}
++i;
auto message = gmx::formatString(
"Invalid value for mdp option %s. %s should only consist of real numbers "
"separated by spaces.",
- name, name);
+ 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)
{
opts->wall_atomtype[0] = 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,
+ 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,
+ gmx_fatal(FARGS,
+ "Expected %d elements for wall-density, found %zu",
+ ir->nwall,
wallDensity.size());
}
convertReals(wi, wallDensity, "wall-density", ir->wall_density);
{
/* 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->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);
+ (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 = (get_eeenum(inp, "wl-oneovert", yesno_names, wi) != 0);
+ expand->bWLoneovert = (getEnum<Boolean>(inp, "wl-oneovert", wi) != Boolean::No);
}
/*! \brief Return whether an end state with the given coupling-lambda
double dumdub[2][6];
int i, j, m;
char warn_buf[STRLEN];
- t_lambda* fep = ir->fepvals;
- t_expanded* expand = ir->expandedvals;
+ t_lambda* fep = ir->fepvals.get();
+ t_expanded* expand = ir->expandedvals.get();
const char* no_names[] = { "no", nullptr };
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);
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);
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");
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)");
- ir->cutoff_scheme = get_eeenum(&inp, "cutoff-scheme", ecutscheme_names, wi);
+ ir->cutoff_scheme = getEnum<CutoffScheme>(&inp, "cutoff-scheme", wi);
printStringNoNewline(&inp, "nblist update frequency");
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;
+ // 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");
/* 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);
- printStringNoNewline(&inp,
- "Relative dielectric constant for the medium and the reaction field");
+ 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_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);
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->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->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->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);
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);
+ setStringEntry(&inp, "annealing", inputrecStrings->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-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->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);
printStringNewline(&inp, "OPTIONS FOR BONDS");
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);
+ ir->bContinuation = (getEnum<Boolean>(&inp, "continuation", wi) != Boolean::No);
printStringNoNewline(&inp,
"Use successive overrelaxation to reduce the number of shake iterations");
- ir->bShakeSOR = (get_eeenum(&inp, "Shake-SOR", yesno_names, wi) != 0);
+ 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);
+ 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");
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);
+ ir->eDisre = getEnum<DistanceRestraintRefinement>(&inp, "disre", 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->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->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_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
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->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);
}
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++)
{
}
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);
+ 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] = (get_eeenum(&inp, "massw-split0", yesno_names, wi) != 0);
- ir->swap->massw_split[1] = (get_eeenum(&inp, "massw-split1", yesno_names, wi) != 0);
+ 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);
+ 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 "
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);
/* User defined thingies */
printStringNewline(&inp, "User defined thingies");
- setStringEntry(&inp, "user1-grps", is->user1, nullptr);
- setStringEntry(&inp, "user2-grps", is->user2, nullptr);
+ 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->userreal4 = get_ereal(&inp, "userreal4", 0, wi);
#undef CTYPE
+ if (mdparout)
{
gmx::TextOutputFile stream(mdparout);
write_inpfile(&stream, mdparout, &inp, FALSE, writeMdpHeader, wi);
{
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(
}
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(
}
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]))
+ 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(
}
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];
}
}
- 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_note(
wi,
}
}
/* 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;
+ 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
+ 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,
/* 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)
+ 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'", is->deform)
- .c_str());
+ 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++)
{
}
/* 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);
+ }
+
+ sfree(dumstr[0]);
+ sfree(dumstr[1]);
+}
-/* 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[])
+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)
+{
+ /* 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 j, gid, aj, ognr, ntot = 0;
+ int ntot = 0;
const char* title;
- bool bRest;
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);
}
- 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);
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)
nrdf_tc[i] = 0;
}
for (gmx::index i = 0;
- i < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1; i++)
+ i < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1;
+ i++)
{
nrdf_vcm[i] = 0;
clear_ivec(dof_vcm[i]);
const t_atom& local = atomP.atom();
int i = atomP.globalAtomNumber();
nrdf2[i] = 0;
- if (local.ptype == eptAtom || local.ptype == eptNucleus)
+ if (local.ptype == ParticleType::Atom || local.ptype == ParticleType::Nucleus)
{
int g = getGroupType(groups, SimulationAtomGroupType::Freeze, i);
for (int d = 0; d < DIM; d++)
*/
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)
{
* 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;
}
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];
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++)
+ 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;
+ 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++)
+ 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++)
+ 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++)
+ j < gmx::ssize(groups.groups[SimulationAtomGroupType::MassCenterVelocityRemoval]) + 1;
+ j++)
{
if (nrdf_vcm[j] > nrdf_vcm_sub[j])
{
{
opts->nrdf[i] = 0;
}
- fprintf(stderr, "Number of degrees of freedom in T-Coupling group %s is %.2f\n",
- gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][i]], opts->nrdf[i]);
+ fprintf(stderr,
+ "Number of degrees of freedom in T-Coupling group %s is %.2f\n",
+ gnames[groups.groups[SimulationAtomGroupType::TemperatureCoupling][i]],
+ opts->nrdf[i]);
}
sfree(nrdf2);
* 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;
j = 0;
while ((j < nr)
&& gmx_strcasecmp(
- names[2 * i].c_str(),
- *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][j]])))
+ names[2 * i].c_str(),
+ *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][j]])))
{
j++;
}
k = 0;
while ((k < nr)
&& gmx_strcasecmp(
- names[2 * i + 1].c_str(),
- *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][k]])))
+ names[2 * i + 1].c_str(),
+ *(groups->groupNames[groups->groups[SimulationAtomGroupType::EnergyOutput][k]])))
{
k++;
}
/* 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 */
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++)
{
fprintf(stderr,
"Group '%s' with %d atoms can be activated for interactive molecular dynamics "
"(IMD).\n",
- IMDgname, IMDgroup->nat);
+ IMDgname,
+ IMDgroup->nat);
snew(IMDgroup->ind, IMDgroup->nat);
for (i = 0; i < IMDgroup->nat; i++)
{
}
}
-void do_index(const char* mdparin,
- const char* ndx,
- gmx_mtop_t* mtop,
- bool bVerbose,
- const gmx::MdModulesNotifier& notifier,
- 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)
+{
+ 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_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);
}
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);
+ 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 "
"%zu tau-t values",
- temperatureCouplingGroupNames.size(), temperatureCouplingReferenceValues.size(),
+ temperatureCouplingGroupNames.size(),
+ temperatureCouplingReferenceValues.size(),
temperatureCouplingTauValues.size());
}
const bool useReferenceTemperature = integratorHasReferenceTemperature(ir);
- do_numbering(natoms, groups, temperatureCouplingGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::TemperatureCoupling, restnm,
- useReferenceTemperature ? egrptpALL : egrptpALL_GENREST, bVerbose, wi);
+ do_numbering(natoms,
+ groups,
+ temperatureCouplingGroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::TemperatureCoupling,
+ 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_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");
}
- 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 "
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);
+ 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);
+ auto simulatedAnnealingGroupNames = gmx::splitString(inputrecStrings->anneal);
if (simulatedAnnealingGroupNames.size() == 1
&& gmx::equalCaseInsensitive(simulatedAnnealingGroupNames[0], "N", 1))
{
}
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;
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",
+ convertReals(wi, simulatedAnnealingTimes, "anneal-time", allSimulatedAnnealingTimes.data());
+ convertReals(wi,
+ simulatedAnnealingTemperatures,
+ "anneal-temp",
allSimulatedAnnealingTemperatures.data());
for (i = 0, k = 0; i < nr; i++)
{
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]);
+ 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",
+ 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++)
{
- fprintf(stderr, "%9.1f %5.1f\n", ir->opts.anneal_time[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)
+ if (ir->opts.annealing[i] == SimulatedAnnealing::Single)
{
- fprintf(stderr, "%9.1f- %5.1f\n", ir->opts.anneal_time[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],
+ 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)
{
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);
+ }
- make_pull_coords(ir->pull);
+ process_pull_groups(ir->pull->group, inputrecStrings->pullGroupNames, defaultIndexGroups, gnames);
+
+ 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,
- SimulationAtomGroupType::Freeze, restnm, egrptpALL_GENREST, bVerbose, wi);
+ 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,
+ 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,
+ sprintf(warn_buf,
"Please use Y(ES) or N(O) for freezedim only "
"(not %s)",
freezeDims[k].c_str());
}
}
- auto energyGroupNames = gmx::splitString(is->energy);
- do_numbering(natoms, groups, energyGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::EnergyOutput, restnm, egrptpALL_GENREST, bVerbose, wi);
+ auto energyGroupNames = gmx::splitString(inputrecStrings->energy);
+ do_numbering(natoms,
+ groups,
+ energyGroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::EnergyOutput,
+ 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)
+ 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)
{
- 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.");
+ 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,
- SimulationAtomGroupType::User1, restnm, egrptpALL_GENREST, bVerbose, wi);
- auto user2GroupNames = gmx::splitString(is->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,
- SimulationAtomGroupType::CompressedPositionOutput, restnm, egrptpONE, bVerbose, wi);
- auto orirefFitGroupNames = gmx::splitString(is->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 */
+ auto user1GroupNames = gmx::splitString(inputrecStrings->user1);
+ do_numbering(natoms,
+ groups,
+ user1GroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::User1,
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
+ auto user2GroupNames = gmx::splitString(inputrecStrings->user2);
+ do_numbering(natoms,
+ groups,
+ user2GroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::User2,
+ restnm,
+ GroupCoverage::AllGenerateRest,
+ bVerbose,
+ wi);
+ auto compressedXGroupNames = gmx::splitString(inputrecStrings->x_compressed_groups);
+ do_numbering(natoms,
+ groups,
+ compressedXGroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::CompressedPositionOutput,
+ restnm,
+ GroupCoverage::OneGroup,
+ bVerbose,
+ wi);
+ auto orirefFitGroupNames = gmx::splitString(inputrecStrings->orirefitgrp);
+ do_numbering(natoms,
+ groups,
+ orirefFitGroupNames,
+ defaultIndexGroups,
+ gnames,
+ SimulationAtomGroupType::OrientationRestraintsFit,
+ 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)
{
nr = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
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 currently not supported");
}
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 "
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));
+ 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++)
{
}
-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++)
}
}
-static bool absolute_reference(const t_inputrec* ir, const gmx_mtop_t* sys, const 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;
- const t_iparams* pr;
+ BasicVector<bool> absRef = { false, false, false };
- clear_ivec(AbsRef);
-
- 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"
+ "Invalid geometry for flat-bottom position restraint.\n"
"Expected nr between 1 and %d. Found %d\n",
- efbposresNR - 1, pr->fbposres.geom);
+ 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,
+static void check_combination_rule_differences(const gmx_mtop_t& mtop,
int state,
bool* bC6ParametersWorkWithGeometricRules,
bool* bC6ParametersWorkWithLBRules,
ptr = getenv("GMX_LJCOMB_TOL");
if (ptr != nullptr)
{
- double dbl;
+ double dbl;
double gmx_unused canary;
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;
+ ntypes = mtop.ffparams.atnr;
snew(typecount, ntypes);
gmx_mtop_count_atomtypes(mtop, state, typecount);
*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))
{
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)
{
{
if (!bC6ParametersWorkWithGeometricRules)
{
- if (ir->eDispCorr != edispcNO)
+ if (ir->eDispCorr != DispersionCorrectionType::No)
{
warning_note(wi,
"You are using geometric combination rules in "
}
}
+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 (absolute_reference(ir, sys, false, AbsRef))
+ 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");
+ "cause artifacts. When you are using position restraints to equilibrate a "
+ "macro-molecule, the artifacts are usually negligible.");
}
- 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->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.
* 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,
"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,
+ tau,
+ 100 * max_T_error,
+ 100 * T_error_suggest,
ir->verletbuf_tol * T_error_suggest / max_T_error);
warning(wi, warn_buf);
}
sprintf(err_buf,
"all tau_t must be positive using Andersen temperature control, "
"tau_t[%d]=%10.6f",
- i, ir->opts.tau_t[i]);
+ 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++)
{
"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);
+ 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");
}
- 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++)
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",
+ 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, "
}
bCharge = FALSE;
- aloopb = gmx_mtop_atomloop_block_init(sys);
+ aloopb = gmx_mtop_atomloop_block_init(*sys);
const t_atom* atom;
while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
{
"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));
+ 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)
+ if (ir->coulombtype == CoulombInteractionType::GRFNotused)
{
warning_error(wi,
"Generalized reaction-field electrostatics is no longer supported. "
"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)
- {
- 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);
- }
-
- if (ir->efep != efepNO && ir->fepvals->sc_alpha != 0
+ 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 "
{
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);
+ 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)
char warn_buf[STRLEN];
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)
{
}
}
- 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");
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]);
+ 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)
{
"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))
+ if (gmx::square(ir->rlist) >= max_cutoff2(ir->pbcType, box))
{
sprintf(warn_buf,
"ERROR: The cut-off length is longer than half the shortest box vector or "