From 4d5aeff9c1ac037fcf6c7b65ed37b905eba00afa Mon Sep 17 00:00:00 2001 From: Pascal Merz Date: Tue, 9 Feb 2021 10:06:15 +0000 Subject: [PATCH] Make temperature and pressure coupling enums enum classes This makes the plain enums denoting the temperature and pressure coupling enums enum classes. Most of this change is simple renaming, changing etcXXX into TemperatureCoupling::XXX, and epcXXX into PressureCoupling::XXX. As these are the first of many enums in md_enums.h being refactored into enum classes, this also introduces some reusable functionality, including a templated function mapping enums to a string representing the functionality, and helper functions used when reading inputrec from file or comparing inputrec instances. This keeps explicit static_casts from / to int in two places: When serializing the inputrec, and when transferring the values over multiple simulations. --- docs/doxygen/lib/modularsimulator.md | 4 +- src/gromacs/domdec/domdec_setup.cpp | 5 +- src/gromacs/domdec/partition.cpp | 6 +- src/gromacs/fileio/enxio.cpp | 6 +- src/gromacs/fileio/readinp.cpp | 4 +- src/gromacs/fileio/readinp.h | 18 +- src/gromacs/fileio/tpxio.cpp | 4 +- src/gromacs/gmxpreprocess/grompp.cpp | 18 +- src/gromacs/gmxpreprocess/readir.cpp | 160 +++++++++----- src/gromacs/mdlib/calc_verletbuf.cpp | 4 +- src/gromacs/mdlib/constr.cpp | 4 +- src/gromacs/mdlib/coupling.cpp | 204 +++++++++--------- src/gromacs/mdlib/coupling.h | 4 +- src/gromacs/mdlib/energyoutput.cpp | 28 +-- src/gromacs/mdlib/energyoutput.h | 4 +- src/gromacs/mdlib/md_support.cpp | 15 +- src/gromacs/mdlib/mdebin_bar.cpp | 4 +- src/gromacs/mdlib/perf_est.cpp | 4 +- src/gromacs/mdlib/tests/energyoutput.cpp | 28 +-- src/gromacs/mdlib/tests/leapfrogtestdata.cpp | 8 +- src/gromacs/mdlib/update.cpp | 30 +-- src/gromacs/mdrun/md.cpp | 24 ++- src/gromacs/mdrun/replicaexchange.cpp | 14 +- src/gromacs/mdrun/runner.cpp | 3 +- src/gromacs/mdtypes/inputrec.cpp | 61 +++--- src/gromacs/mdtypes/inputrec.h | 8 +- src/gromacs/mdtypes/md_enums.cpp | 24 ++- src/gromacs/mdtypes/md_enums.h | 69 +++--- .../modularsimulator/modularsimulator.cpp | 25 ++- .../velocityscalingtemperaturecoupling.cpp | 10 +- .../velocityscalingtemperaturecoupling.h | 7 +- src/gromacs/nbnxm/pairlist_tuning.cpp | 6 +- src/gromacs/taskassignment/decidegpuusage.cpp | 8 +- src/gromacs/tools/report_methods.cpp | 10 +- src/gromacs/utility/compare.h | 17 +- src/gromacs/utility/iserializer.h | 13 +- 36 files changed, 496 insertions(+), 365 deletions(-) diff --git a/docs/doxygen/lib/modularsimulator.md b/docs/doxygen/lib/modularsimulator.md index c5f73730fa..108e127fea 100644 --- a/docs/doxygen/lib/modularsimulator.md +++ b/docs/doxygen/lib/modularsimulator.md @@ -200,7 +200,7 @@ the simulator algorithm. builder->add(); // We have a full state here (positions(t), velocities(t-dt/2), forces(t) builder->add(); - if (legacySimulatorData_->inputrec->etc == etcVRESCALE) + if (legacySimulatorData_->inputrec->etc == TemperatureCoupling::VRescale) { builder->add(-1, VRescaleThermostatUseFullStepKE::No); } @@ -214,7 +214,7 @@ the simulator algorithm. builder->add>(); // We have the energies at time t here builder->add(); - if (legacySimulatorData_->inputrec->epc == epcPARRINELLORAHMAN) + if (legacySimulatorData_->inputrec->epc == PressureCoupling::ParrinelloRahman) { builder->add(-1); } diff --git a/src/gromacs/domdec/domdec_setup.cpp b/src/gromacs/domdec/domdec_setup.cpp index 200afa8a5f..6cf0368a71 100644 --- a/src/gromacs/domdec/domdec_setup.cpp +++ b/src/gromacs/domdec/domdec_setup.cpp @@ -362,7 +362,8 @@ static float comm_cost_est(real limit, { for (int j = i + 1; j < ddbox.npbcdim; j++) { - if (box[j][i] != 0 || ir.deform[j][i] != 0 || (ir.epc != epcNO && ir.compress[j][i] != 0)) + if (box[j][i] != 0 || ir.deform[j][i] != 0 + || (ir.epc != PressureCoupling::No && ir.compress[j][i] != 0)) { if (nc[j] > 1 && nc[i] == 1) { @@ -725,7 +726,7 @@ real getDDGridSetupCellSizeLimit(const gmx::MDLogger& mdlog, "Scaling the initial minimum size with 1/%g (option -dds) = %g", dlb_scale, 1 / dlb_scale); cellSizeLimit /= dlb_scale; } - else if (ir.epc != epcNO) + else if (ir.epc != PressureCoupling::No) { GMX_LOG(mdlog.info) .appendTextFormatted( diff --git a/src/gromacs/domdec/partition.cpp b/src/gromacs/domdec/partition.cpp index 9640d2756b..06b4937caf 100644 --- a/src/gromacs/domdec/partition.cpp +++ b/src/gromacs/domdec/partition.cpp @@ -1,7 +1,7 @@ /* * This file is part of the GROMACS molecular simulation package. * - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -2761,7 +2761,7 @@ void dd_partition_system(FILE* fplog, // TODO if the update code becomes accessible here, use // upd->deform for this logic. bBoxChanged = (bMasterState || inputrecDeform(ir)); - if (ir->epc != epcNO) + if (ir->epc != PressureCoupling::No) { /* With nstpcouple > 1 pressure coupling happens. * one step after calculating the pressure. @@ -2799,7 +2799,7 @@ void dd_partition_system(FILE* fplog, * Since it requires (possibly expensive) global communication, * we might want to do DLB less frequently. */ - if (bBoxChanged || ir->epc != epcNO) + if (bBoxChanged || ir->epc != PressureCoupling::No) { bDoDLB = bBoxChanged; } diff --git a/src/gromacs/fileio/enxio.cpp b/src/gromacs/fileio/enxio.cpp index 56d2279c7b..278306e208 100644 --- a/src/gromacs/fileio/enxio.cpp +++ b/src/gromacs/fileio/enxio.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -1198,7 +1198,7 @@ void get_enx_state(const char* fn, real t, const SimulationGroups& groups, t_inp } npcoupl = TRICLINIC(ir->compress) ? 6 : 3; - if (ir->epc == epcPARRINELLORAHMAN) + if (ir->epc == PressureCoupling::ParrinelloRahman) { clear_mat(state->boxv); for (i = 0; i < npcoupl; i++) @@ -1208,7 +1208,7 @@ void get_enx_state(const char* fn, real t, const SimulationGroups& groups, t_inp fprintf(stderr, "\nREAD %d BOX VELOCITIES FROM %s\n\n", npcoupl, fn); } - if (ir->etc == etcNOSEHOOVER) + if (ir->etc == TemperatureCoupling::NoseHoover) { char cns[20]; diff --git a/src/gromacs/fileio/readinp.cpp b/src/gromacs/fileio/readinp.cpp index 1da9fd268a..bf47bcd36a 100644 --- a/src/gromacs/fileio/readinp.cpp +++ b/src/gromacs/fileio/readinp.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -308,7 +308,7 @@ void mark_einp_set(gmx::ArrayRef inp, const char* name) } } -static int get_einp(std::vector* inp, const char* name) +int get_einp(std::vector* inp, const char* name) { std::vector& inpRef = *inp; bool notfound = false; diff --git a/src/gromacs/fileio/readinp.h b/src/gromacs/fileio/readinp.h index 37034e7c7d..5c2e8e5f17 100644 --- a/src/gromacs/fileio/readinp.h +++ b/src/gromacs/fileio/readinp.h @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -160,6 +160,22 @@ int get_eeenum(std::vector* inp, const std::string& name, const char* int get_eenum(std::vector* inp, const char* name, const char** defs); /* defs must be NULL terminated */ +//! Get index of option `name`. Exposed here so that `getEnum` can access it. +int get_einp(std::vector* inp, const char* name); + +/*! \brief Read option from input and return corresponding enum value + * + * If the option is not set, return the first value of the enum as default. + * + * \tparam EnumType The type of enum to be returned + * \param[in] inp The input file vector + * \param[in] name The name of the option to be read + * \param[out] wi Handler for context-sensitive warnings. + * \return Enum value corresponding to read input + */ +template +EnumType getEnum(std::vector* inp, const char* name, warninp* wi); + //! Replace for macro CCTYPE, prints comment string after newline void printStringNewline(std::vector* inp, const char* line); //! Replace for macro CTYPE, prints comment string diff --git a/src/gromacs/fileio/tpxio.cpp b/src/gromacs/fileio/tpxio.cpp index d50be6feb9..b963ed295b 100644 --- a/src/gromacs/fileio/tpxio.cpp +++ b/src/gromacs/fileio/tpxio.cpp @@ -1306,7 +1306,7 @@ static void do_inputrec(gmx::ISerializer* serializer, t_inputrec* ir, int file_v serializer->doInt(&ir->ljpme_combination_rule); } serializer->doBool(&ir->bContinuation); - serializer->doInt(&ir->etc); + serializer->doEnumAsInt(&ir->etc); /* before version 18, ir->etc was a gmx_bool (ir->btc), * but the values 0 and 1 still mean no and * berendsen temperature coupling, respectively. @@ -1323,7 +1323,7 @@ static void do_inputrec(gmx::ISerializer* serializer, t_inputrec* ir, int file_v { ir->nsttcouple = ir->nstcalcenergy; } - serializer->doInt(&ir->epc); + serializer->doEnumAsInt(&ir->epc); serializer->doInt(&ir->epct); if (file_version >= 71) { diff --git a/src/gromacs/gmxpreprocess/grompp.cpp b/src/gromacs/gmxpreprocess/grompp.cpp index 441007676f..2f6f29e3e0 100644 --- a/src/gromacs/gmxpreprocess/grompp.cpp +++ b/src/gromacs/gmxpreprocess/grompp.cpp @@ -907,7 +907,7 @@ static void cont_status(const char* slog, GMX_LOG(logger.info).asParagraph().appendTextFormatted("Using frame at t = %g ps", use_time); GMX_LOG(logger.info).asParagraph().appendTextFormatted("Starting time for run is %g ps", ir->init_t); - if ((ir->epc != epcNO || ir->etc == etcNOSEHOOVER) && ener) + if ((ir->epc != PressureCoupling::No || ir->etc == TemperatureCoupling::NoseHoover) && ener) { get_enx_state(ener, use_time, sys->groups, ir, state); preserve_box_shape(ir, state->box_rel, state->boxv); @@ -2035,7 +2035,7 @@ int gmx_grompp(int argc, char* argv[]) } } - if (EI_SD(ir->eI) && ir->etc != etcNO) + if (EI_SD(ir->eI) && ir->etc != TemperatureCoupling::No) { warning_note(wi, "Temperature coupling is ignored with SD integrators."); } @@ -2047,14 +2047,14 @@ int gmx_grompp(int argc, char* argv[]) if (nint_ftype(&sys, mi, F_POSRES) > 0 || nint_ftype(&sys, mi, F_FBPOSRES) > 0) { - if (ir->epc == epcPARRINELLORAHMAN || ir->epc == epcMTTK) + if (ir->epc == PressureCoupling::ParrinelloRahman || ir->epc == PressureCoupling::Mttk) { std::string warningMessage = gmx::formatString( "You are combining position restraints with %s pressure coupling, which can " "lead to instabilities. If you really want to combine position restraints with " "pressure coupling, we suggest to use %s pressure coupling instead.", - EPCOUPLTYPE(ir->epc), - EPCOUPLTYPE(epcBERENDSEN)); + enumValueToString(ir->epc), + enumValueToString(PressureCoupling::Berendsen)); warning_note(wi, warningMessage); } @@ -2200,7 +2200,7 @@ int gmx_grompp(int argc, char* argv[]) { real buffer_temp; - if (EI_MD(ir->eI) && ir->etc == etcNO) + if (EI_MD(ir->eI) && ir->etc == TemperatureCoupling::No) { if (bGenVel) { @@ -2232,7 +2232,7 @@ int gmx_grompp(int argc, char* argv[]) buffer_temp = get_max_reference_temp(ir, wi); } - if (EI_MD(ir->eI) && ir->etc == etcNO && buffer_temp == 0) + if (EI_MD(ir->eI) && ir->etc == TemperatureCoupling::No && buffer_temp == 0) { /* NVE with initial T=0: we add a fixed ratio to rlist. * Since we don't actually use verletbuf_tol, we set it to -1 @@ -2248,7 +2248,7 @@ int gmx_grompp(int argc, char* argv[]) * Note that we can't warn when nsteps=0, since we don't * know how many steps the user intends to run. */ - if (EI_MD(ir->eI) && ir->etc == etcNO && ir->nstlist > 1 && ir->nsteps > 0) + if (EI_MD(ir->eI) && ir->etc == TemperatureCoupling::No && ir->nstlist > 1 && ir->nsteps > 0) { const real driftTolerance = 0.01; /* We use 2 DOF per atom = 2kT pot+kin energy, @@ -2393,7 +2393,7 @@ int gmx_grompp(int argc, char* argv[]) if (ir->bDoAwh) { tensor compressibility = { { 0 } }; - if (ir->epc != epcNO) + if (ir->epc != PressureCoupling::No) { copy_mat(ir->compress, compressibility); } diff --git a/src/gromacs/gmxpreprocess/readir.cpp b/src/gromacs/gmxpreprocess/readir.cpp index 4ac809a63f..603fae0cdb 100644 --- a/src/gromacs/gmxpreprocess/readir.cpp +++ b/src/gromacs/gmxpreprocess/readir.cpp @@ -450,7 +450,7 @@ void check_ir(const char* mdparin, /* GENERAL INTEGRATOR STUFF */ if (!EI_MD(ir->eI)) { - if (ir->etc != etcNO) + if (ir->etc != TemperatureCoupling::No) { if (EI_RANDOM(ir->eI)) { @@ -458,7 +458,7 @@ void check_ir(const char* mdparin, "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], + enumValueToString(ir->etc), ei_names[ir->eI], ei_names[ir->eI]); } @@ -467,12 +467,12 @@ void check_ir(const char* mdparin, sprintf(warn_buf, "Setting tcoupl from '%s' to 'no'. Temperature coupling does not apply to " "%s.", - etcoupl_names[ir->etc], + enumValueToString(ir->etc), ei_names[ir->eI]); } warning_note(wi, warn_buf); } - ir->etc = etcNO; + ir->etc = TemperatureCoupling::No; } if (ir->eI == eiVVAK) { @@ -486,15 +486,15 @@ void check_ir(const char* mdparin, } 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], + enumValueToString(ir->epc), ei_names[ir->eI]); warning_note(wi, warn_buf); } - ir->epc = epcNO; + ir->epc = PressureCoupling::No; } if (EI_DYNAMICS(ir->eI)) { @@ -539,7 +539,7 @@ void check_ir(const char* mdparin, ir->nstcalcenergy = min_nst; } - if (ir->epc != epcNO) + if (ir->epc != PressureCoupling::No) { if (ir->nstpcouple < 0) { @@ -649,12 +649,12 @@ void check_ir(const char* mdparin, /* 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); } @@ -969,10 +969,10 @@ void check_ir(const char* mdparin, { 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 @@ -980,7 +980,7 @@ void check_ir(const char* mdparin, sprintf(err_buf, "Can not have pressure coupling with pbc=%s", c_pbcTypeNames[ir->pbcType].c_str()); - CHECK(ir->epc != epcNO); + CHECK(ir->epc != PressureCoupling::No); } sprintf(err_buf, "Can not have Ewald with pbc=%s", c_pbcTypeNames[ir->pbcType].c_str()); CHECK(EEL_FULL(ir->coulombtype)); @@ -1069,15 +1069,15 @@ void check_ir(const char* mdparin, } /* 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) { @@ -1089,7 +1089,7 @@ void check_ir(const char* mdparin, 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, @@ -1115,17 +1115,17 @@ void check_ir(const char* mdparin, { sprintf(err_buf, "%s temperature control not supported for integrator %s.", - etcoupl_names[ir->etc], + enumValueToString(ir->etc), ei_names[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); } @@ -1133,21 +1133,22 @@ void check_ir(const char* mdparin, "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)); + 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 " @@ -1156,15 +1157,15 @@ void check_ir(const char* mdparin, } /* 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; @@ -1176,7 +1177,7 @@ void check_ir(const char* mdparin, 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), + enumValueToString(ir->epc), ir->tau_p, pcouple_min_integration_steps(ir->epc), dt_pcoupl); @@ -1186,12 +1187,12 @@ void check_ir(const char* mdparin, 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 " @@ -1201,14 +1202,14 @@ void check_ir(const char* mdparin, "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"); } @@ -1805,6 +1806,53 @@ static void read_expandedparams(std::vector* inp, t_expanded* expand, expand->bWLoneovert = (get_eeenum(inp, "wl-oneovert", yesno_names, wi) != 0); } +template +EnumType getEnum(std::vector* inp, const char* name, warninp_t wi) +{ + // If we there's no valid option, we'll use the first enum entry as default. + // Note, this assumes the enum is zero based, which is also assumed by + // EnumerationWrapper and EnumerationArray. + const auto defaultEnumValue = EnumType::Default; + const auto& defaultName = enumValueToString(defaultEnumValue); + // Get index of option in input + const auto ii = get_einp(inp, name); + if (ii == -1) + { + // If the option wasn't set, we use the first enum entry as default + inp->back().value_.assign(defaultName); + return defaultEnumValue; + } + + // Check if option string can be mapped to a valid enum value + const auto* optionString = (*inp)[ii].value_.c_str(); + for (auto enumValue : gmx::EnumerationWrapper{}) + { + if (gmx_strcasecmp_min(enumValueToString(enumValue), optionString) == 0) + { + return enumValue; + } + } + + // If we get here, the option set is invalid. Print error. + std::string errorMessage = gmx::formatString( + "Invalid enum '%s' for variable %s, using '%s'\n", optionString, name, defaultName); + errorMessage += gmx::formatString("Next time, use one of:"); + for (auto enumValue : gmx::EnumerationWrapper{}) + { + errorMessage += gmx::formatString(" '%s'", enumValueToString(enumValue)); + } + if (wi != nullptr) + { + warning_error(wi, errorMessage); + } + else + { + fprintf(stderr, "%s\n", errorMessage.c_str()); + } + (*inp)[ii].value_.assign(defaultName); + return defaultEnumValue; +} + /*! \brief Return whether an end state with the given coupling-lambda * value describes fully-interacting VDW. * @@ -2075,7 +2123,7 @@ void get_ir(const char* mdparin, /* 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(&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); @@ -2085,7 +2133,7 @@ void get_ir(const char* mdparin, 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->epc = getEnum(&inp, "pcoupl", wi); ir->epct = get_eeenum(&inp, "pcoupltype", epcoupltype_names, wi); ir->nstpcouple = get_eint(&inp, "nstpcouple", -1, wi); printStringNoNewline(&inp, "Time constant (ps), compressibility (1/bar) and reference P (bar)"); @@ -2450,7 +2498,7 @@ void get_ir(const char* mdparin, { dumdub[m][i] = 0.0; } - if (ir->epc) + if (ir->epc != PressureCoupling::No) { switch (ir->epct) { @@ -2667,7 +2715,7 @@ void get_ir(const char* mdparin, 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++) { @@ -3498,7 +3546,7 @@ void do_index(const char* mdparin, 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, @@ -3511,23 +3559,23 @@ void do_index(const char* mdparin, 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 " @@ -3572,7 +3620,7 @@ void do_index(const char* mdparin, 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), + enumValueToString(ir->etc), tau_min, nstcmin, ir->nsttcouple * ir->delta_t); @@ -4282,7 +4330,8 @@ void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_ } 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))) + && ((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. @@ -4347,7 +4396,7 @@ void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_ CHECK(ir->opts.tau_t[i] < 0); } - if (ir->etc == etcANDERSENMASSIVE && ir->comm_mode != ecmNO) + if (ir->etc == TemperatureCoupling::AndersenMassive && ir->comm_mode != ecmNO) { for (i = 0; i < ir->opts.ngtc; i++) { @@ -4358,7 +4407,7 @@ void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_ "randomized every time step. The input tau_t (%8.3f) leads to %d steps per " "randomization", i, - etcoupl_names[ir->etc], + enumValueToString(ir->etc), ir->nstcomm, ir->opts.tau_t[i], nsteps); @@ -4375,7 +4424,7 @@ void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_ "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++) @@ -4387,8 +4436,8 @@ void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_ 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], + enumValueToString(ir->etc), + enumValueToString(ir->epc), "tau-p", ir->tau_p, "tau-t", @@ -4398,7 +4447,7 @@ void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_ } /* Check for pressure coupling with absolute position restraints */ - if (ir->epc != epcNO && ir->refcoord_scaling == erscNO) + if (ir->epc != PressureCoupling::No && ir->refcoord_scaling == erscNO) { absolute_reference(ir, sys, TRUE, AbsRef); { @@ -4501,7 +4550,7 @@ void triple_check(const char* mdparin, t_inputrec* ir, gmx_mtop_t* sys, warninp_ { 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++) { @@ -4545,7 +4594,8 @@ void double_check(t_inputrec* ir, matrix box, bool bHasNormalConstraints, bool b if ((ir->eConstrAlg == econtLINCS) && bHasNormalConstraints) { /* If we have Lincs constraints: */ - if (ir->eI == eiMD && ir->etc == etcNO && ir->eConstrAlg == econtLINCS && ir->nLincsIter == 1) + if (ir->eI == eiMD && ir->etc == TemperatureCoupling::No && ir->eConstrAlg == econtLINCS + && ir->nLincsIter == 1) { sprintf(warn_buf, "For energy conservation with LINCS, lincs_iter should be 2 or larger.\n"); @@ -4559,13 +4609,13 @@ void double_check(t_inputrec* ir, matrix box, bool bHasNormalConstraints, bool b ei_names[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."); } diff --git a/src/gromacs/mdlib/calc_verletbuf.cpp b/src/gromacs/mdlib/calc_verletbuf.cpp index b904b9c409..cad2c62caa 100644 --- a/src/gromacs/mdlib/calc_verletbuf.cpp +++ b/src/gromacs/mdlib/calc_verletbuf.cpp @@ -2,7 +2,7 @@ * This file is part of the GROMACS molecular simulation package. * * Copyright (c) 2012-2018, The GROMACS development team. - * Copyright (c) 2019,2020, by the GROMACS development team, led by + * Copyright (c) 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. @@ -1322,7 +1322,7 @@ real minCellSizeForAtomDisplacement(const gmx_mtop_t& mtop, PartitioningPerMoltype updateGrouping, real chanceRequested) { - if (!EI_DYNAMICS(ir.eI) || (EI_MD(ir.eI) && ir.etc == etcNO)) + if (!EI_DYNAMICS(ir.eI) || (EI_MD(ir.eI) && ir.etc == TemperatureCoupling::No)) { return minCellSizeFromPairlistBuffer(ir); } diff --git a/src/gromacs/mdlib/constr.cpp b/src/gromacs/mdlib/constr.cpp index 3c78f53cd3..391fe432d6 100644 --- a/src/gromacs/mdlib/constr.cpp +++ b/src/gromacs/mdlib/constr.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -1106,7 +1106,7 @@ Constraints::Impl::Impl(const gmx_mtop_t& mtop_p, nrnb(nrnb_p), wcycle(wcycle_p) { - if (numConstraints + numSettles > 0 && ir.epc == epcMTTK) + if (numConstraints + numSettles > 0 && ir.epc == PressureCoupling::Mttk) { gmx_fatal(FARGS, "Constraints are not implemented with MTTK pressure control."); } diff --git a/src/gromacs/mdlib/coupling.cpp b/src/gromacs/mdlib/coupling.cpp index 29af5cb479..b49e86103e 100644 --- a/src/gromacs/mdlib/coupling.cpp +++ b/src/gromacs/mdlib/coupling.cpp @@ -114,7 +114,7 @@ void update_tcouple(int64_t step, // For VV temperature coupling parameters are updated on the current // step, for the others - one step before. - if (inputrec->etc == etcNO) + if (inputrec->etc == TemperatureCoupling::No) { doTemperatureCoupling = false; } @@ -136,11 +136,13 @@ void update_tcouple(int64_t step, // subroutines switch (inputrec->etc) { - case etcNO: break; - case etcBERENDSEN: + case TemperatureCoupling::No: + case TemperatureCoupling::Andersen: + case TemperatureCoupling::AndersenMassive: break; + case TemperatureCoupling::Berendsen: berendsen_tcoupl(inputrec, ekind, dttc, state->therm_integral); break; - case etcNOSEHOOVER: + case TemperatureCoupling::NoseHoover: nosehoover_tcoupl(&(inputrec->opts), ekind, dttc, @@ -148,9 +150,10 @@ void update_tcouple(int64_t step, state->nosehoover_vxi.data(), MassQ); break; - case etcVRESCALE: + case TemperatureCoupling::VRescale: vrescale_tcoupl(inputrec, step, ekind, dttc, state->therm_integral.data()); break; + default: gmx_fatal(FARGS, "Unknown temperature coupling algorithm"); } /* rescale in place here */ if (EI_VV(inputrec->eI)) @@ -180,7 +183,7 @@ void update_pcouple_before_coordinates(FILE* fplog, /* Berendsen P-coupling is completely handled after the coordinate update. * Trotter P-coupling is handled by separate calls to trotter_update(). */ - if (inputrec->epc == epcPARRINELLORAHMAN + if (inputrec->epc == PressureCoupling::ParrinelloRahman && do_per_step(step + inputrec->nstpcouple - 1, inputrec->nstpcouple)) { real dtpc = inputrec->nstpcouple * inputrec->delta_t; @@ -213,62 +216,63 @@ void update_pcouple_after_coordinates(FILE* fplog, /* now update boxes */ switch (inputrec->epc) { - case (epcNO): break; - case (epcBERENDSEN): + case (PressureCoupling::No): break; + case (PressureCoupling::Berendsen): if (do_per_step(step, inputrec->nstpcouple)) { real dtpc = inputrec->nstpcouple * dt; - pressureCouplingCalculateScalingMatrix(fplog, - step, - inputrec, - dtpc, - pressure, - state->box, - forceVirial, - constraintVirial, - pressureCouplingMu, - &state->baros_integral); - pressureCouplingScaleBoxAndCoordinates(inputrec, - pressureCouplingMu, - state->box, - state->box_rel, - start, - homenr, - state->x.rvec_array(), - nullptr, - md->cFREEZE, - nrnb, - scaleCoordinates); + pressureCouplingCalculateScalingMatrix(fplog, + step, + inputrec, + dtpc, + pressure, + state->box, + forceVirial, + constraintVirial, + pressureCouplingMu, + &state->baros_integral); + pressureCouplingScaleBoxAndCoordinates(inputrec, + pressureCouplingMu, + state->box, + state->box_rel, + start, + homenr, + state->x.rvec_array(), + nullptr, + md->cFREEZE, + nrnb, + scaleCoordinates); } break; - case (epcCRESCALE): + case (PressureCoupling::CRescale): if (do_per_step(step, inputrec->nstpcouple)) { real dtpc = inputrec->nstpcouple * dt; - pressureCouplingCalculateScalingMatrix(fplog, - step, - inputrec, - dtpc, - pressure, - state->box, - forceVirial, - constraintVirial, - pressureCouplingMu, - &state->baros_integral); - pressureCouplingScaleBoxAndCoordinates(inputrec, - pressureCouplingMu, - state->box, - state->box_rel, - start, - homenr, - state->x.rvec_array(), - state->v.rvec_array(), - md->cFREEZE, - nrnb, - scaleCoordinates); + pressureCouplingCalculateScalingMatrix(fplog, + step, + inputrec, + dtpc, + pressure, + state->box, + forceVirial, + constraintVirial, + pressureCouplingMu, + &state->baros_integral); + pressureCouplingScaleBoxAndCoordinates( + inputrec, + pressureCouplingMu, + state->box, + state->box_rel, + start, + homenr, + state->x.rvec_array(), + state->v.rvec_array(), + md->cFREEZE, + nrnb, + scaleCoordinates); } break; - case (epcPARRINELLORAHMAN): + case (PressureCoupling::ParrinelloRahman): if (do_per_step(step + inputrec->nstpcouple - 1, inputrec->nstpcouple)) { /* The box velocities were updated in do_pr_pcoupl, @@ -296,7 +300,7 @@ void update_pcouple_after_coordinates(FILE* fplog, } } break; - case (epcMTTK): + case (PressureCoupling::Mttk): switch (inputrec->epct) { case (epctISOTROPIC): @@ -341,7 +345,7 @@ extern gmx_bool update_randomize_velocities(const t_inputrec* ir, real rate = (ir->delta_t) / ir->opts.tau_t[0]; - if (ir->etc == etcANDERSEN && constr != nullptr) + if (ir->etc == TemperatureCoupling::Andersen && constr != nullptr) { /* Currently, Andersen thermostat does not support constrained systems. Functionality exists in the andersen_tcoupl @@ -356,7 +360,7 @@ extern gmx_bool update_randomize_velocities(const t_inputrec* ir, /* proceed with andersen if 1) it's fixed probability per particle andersen or 2) it's massive andersen and it's tau_t/dt */ - if ((ir->etc == etcANDERSEN) || do_per_step(step, gmx::roundToInt(1.0 / rate))) + if ((ir->etc == TemperatureCoupling::Andersen) || do_per_step(step, gmx::roundToInt(1.0 / rate))) { andersen_tcoupl( ir, step, cr, md, v, rate, upd->getAndersenRandomizeGroup(), upd->getBoltzmanFactor()); @@ -847,7 +851,7 @@ static inline real compressibilityFactor(int i, int j, const t_inputrec* ir, rea } //! Details of Berendsen / C-rescale scaling matrix calculation -template +template static void calculateScalingMatrixImplDetail(const t_inputrec* ir, matrix mu, real dt, @@ -858,7 +862,7 @@ static void calculateScalingMatrixImplDetail(const t_inputrec* ir, int64_t step); //! Calculate Berendsen / C-rescale scaling matrix -template +template static void calculateScalingMatrixImpl(const t_inputrec* ir, matrix mu, real dt, @@ -882,14 +886,14 @@ static void calculateScalingMatrixImpl(const t_inputrec* ir, } template<> -void calculateScalingMatrixImplDetail(const t_inputrec* ir, - matrix mu, - real dt, - const matrix pres, - const matrix box, - real scalar_pressure, - real xy_pressure, - int64_t gmx_unused step) +void calculateScalingMatrixImplDetail(const t_inputrec* ir, + matrix mu, + real dt, + const matrix pres, + const matrix box, + real scalar_pressure, + real xy_pressure, + int64_t gmx_unused step) { real p_corr_z = 0; switch (ir->epct) @@ -949,14 +953,14 @@ void calculateScalingMatrixImplDetail(const t_inputrec* ir, } template<> -void calculateScalingMatrixImplDetail(const t_inputrec* ir, - matrix mu, - real dt, - const matrix pres, - const matrix box, - real scalar_pressure, - real xy_pressure, - int64_t step) +void calculateScalingMatrixImplDetail(const t_inputrec* ir, + matrix mu, + real dt, + const matrix pres, + const matrix box, + real scalar_pressure, + real xy_pressure, + int64_t step) { gmx::ThreeFry2x64<64> rng(ir->ld_seed, gmx::RandomDomain::Barostat); gmx::NormalDistribution normalDist; @@ -1025,7 +1029,7 @@ void calculateScalingMatrixImplDetail(const t_inputrec* ir, } } -template +template void pressureCouplingCalculateScalingMatrix(FILE* fplog, int64_t step, const t_inputrec* ir, @@ -1037,7 +1041,8 @@ void pressureCouplingCalculateScalingMatrix(FILE* fplog, matrix mu, double* baros_integral) { - static_assert(pressureCouplingType == epcBERENDSEN || pressureCouplingType == epcCRESCALE, + static_assert(pressureCouplingType == PressureCoupling::Berendsen + || pressureCouplingType == PressureCoupling::CRescale, "pressureCouplingCalculateScalingMatrix is only implemented for Berendsen and " "C-rescale pressure coupling"); @@ -1098,7 +1103,7 @@ void pressureCouplingCalculateScalingMatrix(FILE* fplog, } } -template +template void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir, const matrix mu, matrix box, @@ -1111,13 +1116,14 @@ void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir, t_nrnb* nrnb, const bool scaleCoordinates) { - static_assert(pressureCouplingType == epcBERENDSEN || pressureCouplingType == epcCRESCALE, + static_assert(pressureCouplingType == PressureCoupling::Berendsen + || pressureCouplingType == PressureCoupling::CRescale, "pressureCouplingScaleBoxAndCoordinates is only implemented for Berendsen and " "C-rescale pressure coupling"); ivec* nFreeze = ir->opts.nFreeze; matrix inv_mu; - if (pressureCouplingType == epcCRESCALE) + if (pressureCouplingType == PressureCoupling::CRescale) { gmx::invertBoxMatrix(mu, inv_mu); } @@ -1139,7 +1145,7 @@ void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir, if (!nFreeze[g][XX]) { x[n][XX] = mu[XX][XX] * x[n][XX] + mu[YY][XX] * x[n][YY] + mu[ZZ][XX] * x[n][ZZ]; - if (pressureCouplingType == epcCRESCALE) + if (pressureCouplingType == PressureCoupling::CRescale) { v[n][XX] = inv_mu[XX][XX] * v[n][XX] + inv_mu[YY][XX] * v[n][YY] + inv_mu[ZZ][XX] * v[n][ZZ]; @@ -1148,7 +1154,7 @@ void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir, if (!nFreeze[g][YY]) { x[n][YY] = mu[YY][YY] * x[n][YY] + mu[ZZ][YY] * x[n][ZZ]; - if (pressureCouplingType == epcCRESCALE) + if (pressureCouplingType == PressureCoupling::CRescale) { v[n][YY] = inv_mu[YY][YY] * v[n][YY] + inv_mu[ZZ][YY] * v[n][ZZ]; } @@ -1156,7 +1162,7 @@ void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir, if (!nFreeze[g][ZZ]) { x[n][ZZ] = mu[ZZ][ZZ] * x[n][ZZ]; - if (pressureCouplingType == epcCRESCALE) + if (pressureCouplingType == PressureCoupling::CRescale) { v[n][ZZ] = inv_mu[ZZ][ZZ] * v[n][ZZ]; } @@ -1250,7 +1256,7 @@ void andersen_tcoupl(const t_inputrec* ir, } if (randomize[gc]) { - if (ir->etc == etcANDERSENMASSIVE) + if (ir->etc == TemperatureCoupling::AndersenMassive) { /* Randomize particle always */ bRandomize = TRUE; @@ -1548,7 +1554,7 @@ init_npt_vars(const t_inputrec* ir, t_state* state, t_extmass* MassQ, gmx_bool b nnhpres = state->nnhpres; nh = state->nhchainlength; - if (EI_VV(ir->eI) && (ir->epc == epcMTTK) && (ir->etc != etcNOSEHOOVER)) + if (EI_VV(ir->eI) && (ir->epc == PressureCoupling::Mttk) && (ir->etc != TemperatureCoupling::NoseHoover)) { gmx_fatal(FARGS, "Cannot do MTTK pressure coupling without Nose-Hoover temperature control"); } @@ -1824,7 +1830,7 @@ real NPT_energy(const t_inputrec* ir, const t_state* state, const t_extmass* Mas { real energyNPT = 0; - if (ir->epc != epcNO) + if (ir->epc != PressureCoupling::No) { /* Compute the contribution of the pressure to the conserved quantity*/ @@ -1832,7 +1838,7 @@ real NPT_energy(const t_inputrec* ir, const t_state* state, const t_extmass* Mas switch (ir->epc) { - case epcPARRINELLORAHMAN: + case PressureCoupling::ParrinelloRahman: { /* contribution from the pressure momenta */ tensor invMass; @@ -1858,21 +1864,21 @@ real NPT_energy(const t_inputrec* ir, const t_state* state, const t_extmass* Mas energyNPT += vol * trace(ir->ref_p) / (DIM * PRESFAC); break; } - case epcMTTK: + case PressureCoupling::Mttk: /* contribution from the pressure momenta */ energyNPT += 0.5 * gmx::square(state->veta) / MassQ->Winv; /* contribution from the PV term */ energyNPT += vol * trace(ir->ref_p) / (DIM * PRESFAC); - if (ir->epc == epcMTTK) + if (ir->epc == PressureCoupling::Mttk) { /* contribution from the MTTK chain */ energyNPT += energyPressureMTTK(ir, state, MassQ); } break; - case epcBERENDSEN: - case epcCRESCALE: energyNPT += state->baros_integral; break; + case PressureCoupling::Berendsen: + case PressureCoupling::CRescale: energyNPT += state->baros_integral; break; default: GMX_RELEASE_ASSERT( false, @@ -1884,12 +1890,14 @@ real NPT_energy(const t_inputrec* ir, const t_state* state, const t_extmass* Mas switch (ir->etc) { - case etcNO: break; - case etcVRESCALE: - case etcBERENDSEN: energyNPT += energyVrescale(ir, state); break; - case etcNOSEHOOVER: energyNPT += energyNoseHoover(ir, state, MassQ); break; - case etcANDERSEN: - case etcANDERSENMASSIVE: + case TemperatureCoupling::No: break; + case TemperatureCoupling::VRescale: + case TemperatureCoupling::Berendsen: energyNPT += energyVrescale(ir, state); break; + case TemperatureCoupling::NoseHoover: + energyNPT += energyNoseHoover(ir, state, MassQ); + break; + case TemperatureCoupling::Andersen: + case TemperatureCoupling::AndersenMassive: // Not supported, excluded in integratorHasConservedEnergyQuantity() break; default: @@ -2153,15 +2161,15 @@ void pleaseCiteCouplingAlgorithms(FILE* fplog, const t_inputrec& ir) { if (EI_DYNAMICS(ir.eI)) { - if (ir.etc == etcBERENDSEN) + if (ir.etc == TemperatureCoupling::Berendsen) { please_cite(fplog, "Berendsen84a"); } - if (ir.etc == etcVRESCALE) + if (ir.etc == TemperatureCoupling::VRescale) { please_cite(fplog, "Bussi2007a"); } - if (ir.epc == epcCRESCALE) + if (ir.epc == PressureCoupling::CRescale) { please_cite(fplog, "Bernetti2020"); } diff --git a/src/gromacs/mdlib/coupling.h b/src/gromacs/mdlib/coupling.h index 25f959a1e5..7f8d3c5a26 100644 --- a/src/gromacs/mdlib/coupling.h +++ b/src/gromacs/mdlib/coupling.h @@ -191,7 +191,7 @@ void parrinellorahman_pcoupl(FILE* fplog, * computes the current value of the scaling matrix. The template * parameter determines the pressure coupling algorithm. */ -template +template void pressureCouplingCalculateScalingMatrix(FILE* fplog, int64_t step, const t_inputrec* ir, @@ -210,7 +210,7 @@ void pressureCouplingCalculateScalingMatrix(FILE* fplog, * the scaling matrix mu. The template parameter determines the pressure * coupling algorithm. */ -template +template void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir, const matrix mu, matrix box, diff --git a/src/gromacs/mdlib/energyoutput.cpp b/src/gromacs/mdlib/energyoutput.cpp index f26716a3d2..b66cb0a933 100644 --- a/src/gromacs/mdlib/energyoutput.cpp +++ b/src/gromacs/mdlib/energyoutput.cpp @@ -261,12 +261,12 @@ EnergyOutput::EnergyOutput(ener_file* fp_ene, } } - epc_ = isRerun ? epcNO : ir->epc; + epc_ = isRerun ? PressureCoupling::No : ir->epc; bDiagPres_ = !TRICLINIC(ir->ref_p) && !isRerun; ref_p_ = (ir->ref_p[XX][XX] + ir->ref_p[YY][YY] + ir->ref_p[ZZ][ZZ]) / DIM; bTricl_ = TRICLINIC(ir->compress) || TRICLINIC(ir->deform); bDynBox_ = inputrecDynamicBox(ir); - etc_ = isRerun ? etcNO : ir->etc; + etc_ = isRerun ? TemperatureCoupling::No : ir->etc; bNHC_trotter_ = inputrecNvtTrotter(ir) && !isRerun; bPrintNHChains_ = ir->bPrintNHChains && !isRerun; bMTTK_ = (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)) && !isRerun; @@ -310,7 +310,7 @@ EnergyOutput::EnergyOutput(ener_file* fp_ene, ipres_ = get_ebin_space(ebin_, asize(pres_nm), pres_nm, unit_pres_bar); isurft_ = get_ebin_space(ebin_, asize(surft_nm), surft_nm, unit_surft_bar); } - if (epc_ == epcPARRINELLORAHMAN || epc_ == epcMTTK) + if (epc_ == PressureCoupling::ParrinelloRahman || epc_ == PressureCoupling::Mttk) { ipc_ = get_ebin_space(ebin_, bTricl_ ? boxvel_nm.size() : DIM, boxvel_nm.data(), unit_vel); } @@ -408,7 +408,7 @@ EnergyOutput::EnergyOutput(ener_file* fp_ene, { nTCP_ = 0; } - if (etc_ == etcNOSEHOOVER) + if (etc_ == TemperatureCoupling::NoseHoover) { if (bNHC_trotter_) { @@ -418,7 +418,7 @@ EnergyOutput::EnergyOutput(ener_file* fp_ene, { mde_n_ = 2 * nTC_; } - if (epc_ == epcMTTK) + if (epc_ == PressureCoupling::Mttk) { mdeb_n_ = 2 * nNHC_ * nTCP_; } @@ -447,7 +447,7 @@ EnergyOutput::EnergyOutput(ener_file* fp_ene, } int allocated = 0; - if (etc_ == etcNOSEHOOVER) + if (etc_ == TemperatureCoupling::NoseHoover) { if (bPrintNHChains_) { @@ -500,7 +500,8 @@ EnergyOutput::EnergyOutput(ener_file* fp_ene, } } } - else if (etc_ == etcBERENDSEN || etc_ == etcYES || etc_ == etcVRESCALE) + else if (etc_ == TemperatureCoupling::Berendsen || etc_ == TemperatureCoupling::Yes + || etc_ == TemperatureCoupling::VRescale) { for (i = 0; (i < nTC_); i++) { @@ -725,7 +726,7 @@ FILE* open_dhdl(const char* filename, const t_inputrec* ir, const gmx_output_env } nsetsextend = nsets; - if ((ir->epc != epcNO) && (fep->n_lambda > 0) && (fep->init_lambda < 0)) + if ((ir->epc != PressureCoupling::No) && (fep->n_lambda > 0) && (fep->init_lambda < 0)) { nsetsextend += 1; /* for PV term, other terms possible if required for the reduced potential (only needed with foreign @@ -925,7 +926,7 @@ void EnergyOutput::addDataAtEnergyStep(bool bDoDHDL, tmp = (pres[ZZ][ZZ] - (pres[XX][XX] + pres[YY][YY]) * 0.5) * box[ZZ][ZZ]; add_ebin(ebin_, isurft_, 1, &tmp, bSum); } - if (epc_ == epcPARRINELLORAHMAN || epc_ == epcMTTK) + if (epc_ == PressureCoupling::ParrinelloRahman || epc_ == PressureCoupling::Mttk) { tmp6[0] = ptCouplingArrays.boxv[XX][XX]; tmp6[1] = ptCouplingArrays.boxv[YY][YY]; @@ -979,7 +980,7 @@ void EnergyOutput::addDataAtEnergyStep(bool bDoDHDL, } add_ebin(ebin_, itemp_, nTC_, tmp_r_, bSum); - if (etc_ == etcNOSEHOOVER) + if (etc_ == TemperatureCoupling::NoseHoover) { /* whether to print Nose-Hoover chains: */ if (bPrintNHChains_) @@ -1022,7 +1023,8 @@ void EnergyOutput::addDataAtEnergyStep(bool bDoDHDL, } } } - else if (etc_ == etcBERENDSEN || etc_ == etcYES || etc_ == etcVRESCALE) + else if (etc_ == TemperatureCoupling::Berendsen || etc_ == TemperatureCoupling::Yes + || etc_ == TemperatureCoupling::VRescale) { for (int i = 0; (i < nTC_); i++) { @@ -1094,8 +1096,8 @@ void EnergyOutput::addDataAtEnergyStep(bool bDoDHDL, { fprintf(fp_dhdl_, " %#.8g", dE_[i]); } - if (bDynBox_ && bDiagPres_ && (epc_ != epcNO) && foreignTerms.numLambdas() > 0 - && (fep->init_lambda < 0)) + if (bDynBox_ && bDiagPres_ && (epc_ != PressureCoupling::No) + && foreignTerms.numLambdas() > 0 && (fep->init_lambda < 0)) { fprintf(fp_dhdl_, " %#.8g", pv); /* PV term only needed when there are alternate state diff --git a/src/gromacs/mdlib/energyoutput.h b/src/gromacs/mdlib/energyoutput.h index 91f8112c00..d78919a559 100644 --- a/src/gromacs/mdlib/energyoutput.h +++ b/src/gromacs/mdlib/energyoutput.h @@ -308,7 +308,7 @@ private: bool bMTTK_ = false; //! Temperature control scheme - int etc_ = 0; + TemperatureCoupling etc_ = TemperatureCoupling::No; //! Which of the main energy terms should be printed bool bEner_[F_NRE] = { false }; @@ -361,7 +361,7 @@ private: int isurft_ = 0; //! Pressure control scheme - int epc_ = 0; + PressureCoupling epc_ = PressureCoupling::No; //! Index for velocity of the box borders int ipc_ = 0; diff --git a/src/gromacs/mdlib/md_support.cpp b/src/gromacs/mdlib/md_support.cpp index 1455e0eeb5..176ef3d751 100644 --- a/src/gromacs/mdlib/md_support.cpp +++ b/src/gromacs/mdlib/md_support.cpp @@ -452,7 +452,8 @@ int computeGlobalCommunicationPeriod(const t_inputrec* ir) int nstglobalcomm = 10; { // Set up the default behaviour - if (!(ir->nstcalcenergy > 0 || ir->nstlist > 0 || ir->etc != etcNO || ir->epc != epcNO)) + if (!(ir->nstcalcenergy > 0 || ir->nstlist > 0 || ir->etc != TemperatureCoupling::No + || ir->epc != PressureCoupling::No)) { /* The user didn't choose the period for anything important, so we just make sure we can send signals and @@ -475,8 +476,8 @@ int computeGlobalCommunicationPeriod(const t_inputrec* ir) */ nstglobalcomm = lcd4(ir->nstcalcenergy, ir->nstlist, - ir->etc != etcNO ? ir->nsttcouple : 0, - ir->epc != epcNO ? ir->nstpcouple : 0); + ir->etc != TemperatureCoupling::No ? ir->nsttcouple : 0, + ir->epc != PressureCoupling::No ? ir->nstpcouple : 0); } } return nstglobalcomm; @@ -540,7 +541,7 @@ void set_state_entries(t_state* state, const t_inputrec* ir, bool useModularSimu { state->flags |= (1 << estBOX_REL); } - if ((ir->epc == epcPARRINELLORAHMAN) || (ir->epc == epcMTTK)) + if ((ir->epc == PressureCoupling::ParrinelloRahman) || (ir->epc == PressureCoupling::Mttk)) { state->flags |= (1 << estBOXV); if (!useModularSimulator) @@ -558,19 +559,19 @@ void set_state_entries(t_state* state, const t_inputrec* ir, bool useModularSimu state->flags |= (1 << estVETA); state->flags |= (1 << estVOL0); } - if (ir->epc == epcBERENDSEN || ir->epc == epcCRESCALE) + if (ir->epc == PressureCoupling::Berendsen || ir->epc == PressureCoupling::CRescale) { state->flags |= (1 << estBAROS_INT); } } - if (ir->etc == etcNOSEHOOVER) + if (ir->etc == TemperatureCoupling::NoseHoover) { state->flags |= (1 << estNH_XI); state->flags |= (1 << estNH_VXI); } - if (ir->etc == etcVRESCALE || ir->etc == etcBERENDSEN) + if (ir->etc == TemperatureCoupling::VRescale || ir->etc == TemperatureCoupling::Berendsen) { state->flags |= (1 << estTHERM_INT); } diff --git a/src/gromacs/mdlib/mdebin_bar.cpp b/src/gromacs/mdlib/mdebin_bar.cpp index 994ed39ccc..8c2791b2fd 100644 --- a/src/gromacs/mdlib/mdebin_bar.cpp +++ b/src/gromacs/mdlib/mdebin_bar.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -490,7 +490,7 @@ void mde_delta_h_coll_init(t_mde_delta_h_coll* dhc, const t_inputrec* ir) dhc->ndh += 1; bEnergy = TRUE; } - if (ir->epc > epcNO) + if (ir->epc > PressureCoupling::No) { dhc->ndh += 1; /* include pressure-volume work */ bPV = TRUE; diff --git a/src/gromacs/mdlib/perf_est.cpp b/src/gromacs/mdlib/perf_est.cpp index 402d10a38f..765eed2dc7 100644 --- a/src/gromacs/mdlib/perf_est.cpp +++ b/src/gromacs/mdlib/perf_est.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2008, The GROMACS development team. * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -181,7 +181,7 @@ void count_bonded_distances(const gmx_mtop_t& mtop, const t_inputrec& ir, double { nonsimd_step_frac = 0; } - if (ir.epc != epcNO && 1.0 / ir.nstpcouple > nonsimd_step_frac) + if (ir.epc != PressureCoupling::No && 1.0 / ir.nstpcouple > nonsimd_step_frac) { nonsimd_step_frac = 1.0 / ir.nstpcouple; } diff --git a/src/gromacs/mdlib/tests/energyoutput.cpp b/src/gromacs/mdlib/tests/energyoutput.cpp index b6937b19c5..7755ecdfbd 100644 --- a/src/gromacs/mdlib/tests/energyoutput.cpp +++ b/src/gromacs/mdlib/tests/energyoutput.cpp @@ -98,9 +98,9 @@ void fcloseWrapper(FILE* fp) struct EnergyOutputTestParameters { //! Thermostat (enum) - int temperatureCouplingScheme; + TemperatureCoupling temperatureCouplingScheme; //! Barostat (enum) - int pressureCouplingScheme; + PressureCoupling pressureCouplingScheme; //! Integrator int integrator; //! Number of saved energy frames (to test averages output). @@ -116,17 +116,19 @@ struct EnergyOutputTestParameters * Only several combinations of the parameters are used. Using all possible combinations will * require ~10 MB of test data and ~2 sec to run the tests. */ -const EnergyOutputTestParameters parametersSets[] = { { etcNO, epcNO, eiMD, 1, false, false }, - { etcNO, epcNO, eiMD, 1, true, false }, - { etcNO, epcNO, eiMD, 1, false, true }, - { etcNO, epcNO, eiMD, 0, false, false }, - { etcNO, epcNO, eiMD, 10, false, false }, - { etcVRESCALE, epcNO, eiMD, 1, false, false }, - { etcNOSEHOOVER, epcNO, eiMD, 1, false, false }, - { etcNO, epcPARRINELLORAHMAN, eiMD, 1, false, false }, - { etcNO, epcMTTK, eiMD, 1, false, false }, - { etcNO, epcNO, eiVV, 1, false, false }, - { etcNO, epcMTTK, eiVV, 1, false, false } }; +const EnergyOutputTestParameters parametersSets[] = { + { TemperatureCoupling::No, PressureCoupling::No, eiMD, 1, false, false }, + { TemperatureCoupling::No, PressureCoupling::No, eiMD, 1, true, false }, + { TemperatureCoupling::No, PressureCoupling::No, eiMD, 1, false, true }, + { TemperatureCoupling::No, PressureCoupling::No, eiMD, 0, false, false }, + { TemperatureCoupling::No, PressureCoupling::No, eiMD, 10, false, false }, + { TemperatureCoupling::VRescale, PressureCoupling::No, eiMD, 1, false, false }, + { TemperatureCoupling::NoseHoover, PressureCoupling::No, eiMD, 1, false, false }, + { TemperatureCoupling::No, PressureCoupling::ParrinelloRahman, eiMD, 1, false, false }, + { TemperatureCoupling::No, PressureCoupling::Mttk, eiMD, 1, false, false }, + { TemperatureCoupling::No, PressureCoupling::No, eiVV, 1, false, false }, + { TemperatureCoupling::No, PressureCoupling::Mttk, eiVV, 1, false, false } +}; /*! \brief Test fixture to test energy output. * diff --git a/src/gromacs/mdlib/tests/leapfrogtestdata.cpp b/src/gromacs/mdlib/tests/leapfrogtestdata.cpp index be38a6b971..5a1e2cbf45 100644 --- a/src/gromacs/mdlib/tests/leapfrogtestdata.cpp +++ b/src/gromacs/mdlib/tests/leapfrogtestdata.cpp @@ -123,7 +123,7 @@ LeapFrogTestData::LeapFrogTestData(int numAtoms, if (numTCoupleGroups_ == 0) { - inputRecord_.etc = etcNO; + inputRecord_.etc = TemperatureCoupling::No; for (int i = 0; i < numAtoms_; i++) { mdAtoms_.cTC[i] = 0; @@ -135,7 +135,7 @@ LeapFrogTestData::LeapFrogTestData(int numAtoms, } else { - inputRecord_.etc = etcYES; + inputRecord_.etc = TemperatureCoupling::Yes; for (int i = 0; i < numAtoms_; i++) { mdAtoms_.cTC[i] = i % numTCoupleGroups_; @@ -186,7 +186,7 @@ LeapFrogTestData::LeapFrogTestData(int numAtoms, if (doPressureCouple_) { - inputRecord_.epc = epcPARRINELLORAHMAN; + inputRecord_.epc = PressureCoupling::ParrinelloRahman; inputRecord_.nstpcouple = nstpcouple; dtPressureCouple_ = inputRecord_.nstpcouple * inputRecord_.delta_t; @@ -204,7 +204,7 @@ LeapFrogTestData::LeapFrogTestData(int numAtoms, } else { - inputRecord_.epc = epcNO; + inputRecord_.epc = PressureCoupling::No; velocityScalingMatrix_[XX][XX] = 1.0; velocityScalingMatrix_[XX][YY] = 0.0; velocityScalingMatrix_[XX][ZZ] = 0.0; diff --git a/src/gromacs/mdlib/update.cpp b/src/gromacs/mdlib/update.cpp index 67f2d5bdb4..ad61495af8 100644 --- a/src/gromacs/mdlib/update.cpp +++ b/src/gromacs/mdlib/update.cpp @@ -610,14 +610,14 @@ static void do_update_md(int start, const rvec* gmx_restrict x, rvec* gmx_restrict xprime, rvec* gmx_restrict v, - const rvec* gmx_restrict f, - const int etc, - const int epc, - const int nsttcouple, - const int nstpcouple, - const t_mdatoms* md, - const gmx_ekindata_t* ekind, - const matrix box, + const rvec* gmx_restrict f, + const TemperatureCoupling etc, + const PressureCoupling epc, + const int nsttcouple, + const int nstpcouple, + const t_mdatoms* md, + const gmx_ekindata_t* ekind, + const matrix box, const double* gmx_restrict nh_vxi, const matrix M) { @@ -625,10 +625,11 @@ static void do_update_md(int start, "For SIMD optimization certain compilers need to have xprime != x"); /* Note: Berendsen pressure scaling is handled after do_update_md() */ - bool doTempCouple = (etc != etcNO && do_per_step(step + nsttcouple - 1, nsttcouple)); - bool doNoseHoover = (etc == etcNOSEHOOVER && doTempCouple); - bool doParrinelloRahman = - (epc == epcPARRINELLORAHMAN && do_per_step(step + nstpcouple - 1, nstpcouple)); + bool doTempCouple = + (etc != TemperatureCoupling::No && do_per_step(step + nsttcouple - 1, nsttcouple)); + bool doNoseHoover = (etc == TemperatureCoupling::NoseHoover && doTempCouple); + bool doParrinelloRahman = (epc == PressureCoupling::ParrinelloRahman + && do_per_step(step + nstpcouple - 1, nstpcouple)); bool doPROffDiagonal = (doParrinelloRahman && (M[YY][XX] != 0 || M[ZZ][XX] != 0 || M[ZZ][YY] != 0)); real dtPressureCouple = (doParrinelloRahman ? nstpcouple * dt : 0); @@ -1561,8 +1562,9 @@ void Update::Impl::update_coords(const t_inputrec& case (eiVV): case (eiVVAK): { - gmx_bool bExtended = (inputRecord.etc == etcNOSEHOOVER || inputRecord.epc == epcPARRINELLORAHMAN - || inputRecord.epc == epcMTTK); + gmx_bool bExtended = (inputRecord.etc == TemperatureCoupling::NoseHoover + || inputRecord.epc == PressureCoupling::ParrinelloRahman + || inputRecord.epc == PressureCoupling::Mttk); /* assuming barostat coupled to group 0 */ real alpha = 1.0 + DIM / static_cast(inputRecord.opts.nrdf[0]); diff --git a/src/gromacs/mdrun/md.cpp b/src/gromacs/mdrun/md.cpp index 04cc254287..2cc3dad638 100644 --- a/src/gromacs/mdrun/md.cpp +++ b/src/gromacs/mdrun/md.cpp @@ -432,11 +432,11 @@ void gmx::LegacySimulator::do_md() GMX_RELEASE_ASSERT(ir->eI == eiMD, "Only the md integrator is supported with the GPU update.\n"); GMX_RELEASE_ASSERT( - ir->etc != etcNOSEHOOVER, + ir->etc != TemperatureCoupling::NoseHoover, "Nose-Hoover temperature coupling is not supported with the GPU update.\n"); GMX_RELEASE_ASSERT( - ir->epc == epcNO || ir->epc == epcPARRINELLORAHMAN || ir->epc == epcBERENDSEN - || ir->epc == epcCRESCALE, + ir->epc == PressureCoupling::No || ir->epc == PressureCoupling::ParrinelloRahman + || ir->epc == PressureCoupling::Berendsen || ir->epc == PressureCoupling::CRescale, "Only Parrinello-Rahman, Berendsen, and C-rescale pressure coupling are supported " "with the GPU update.\n"); GMX_RELEASE_ASSERT(!mdatoms->haveVsites, @@ -1072,13 +1072,14 @@ void gmx::LegacySimulator::do_md() { bCalcEnerStep = do_per_step(step, ir->nstcalcenergy); bCalcVir = bCalcEnerStep - || (ir->epc != epcNO + || (ir->epc != PressureCoupling::No && (do_per_step(step, ir->nstpcouple) || do_per_step(step - 1, ir->nstpcouple))); } else { bCalcEnerStep = do_per_step(step, ir->nstcalcenergy); - bCalcVir = bCalcEnerStep || (ir->epc != epcNO && do_per_step(step, ir->nstpcouple)); + bCalcVir = bCalcEnerStep + || (ir->epc != PressureCoupling::No && do_per_step(step, ir->nstpcouple)); } bCalcEner = bCalcEnerStep; @@ -1405,7 +1406,7 @@ void gmx::LegacySimulator::do_md() // Parrinello-Rahman requires the pressure to be availible before the update to compute // the velocity scaling matrix. Hence, it runs one step after the nstpcouple step. - const bool doParrinelloRahman = (ir->epc == epcPARRINELLORAHMAN + const bool doParrinelloRahman = (ir->epc == PressureCoupling::ParrinelloRahman && do_per_step(step + ir->nstpcouple - 1, ir->nstpcouple)); if (EI_VV(ir->eI)) @@ -1481,7 +1482,8 @@ void gmx::LegacySimulator::do_md() } const bool doTemperatureScaling = - (ir->etc != etcNO && do_per_step(step + ir->nsttcouple - 1, ir->nsttcouple)); + (ir->etc != TemperatureCoupling::No + && do_per_step(step + ir->nsttcouple - 1, ir->nsttcouple)); // This applies Leap-Frog, LINCS and SETTLE in succession integrator->integrate( @@ -1676,10 +1678,10 @@ void gmx::LegacySimulator::do_md() update_pcouple_after_coordinates( fplog, step, ir, mdatoms, pres, force_vir, shake_vir, pressureCouplingMu, state, nrnb, upd.deform(), !useGpuForUpdate); - const bool doBerendsenPressureCoupling = - (inputrec->epc == epcBERENDSEN && do_per_step(step, inputrec->nstpcouple)); - const bool doCRescalePressureCoupling = - (inputrec->epc == epcCRESCALE && do_per_step(step, inputrec->nstpcouple)); + const bool doBerendsenPressureCoupling = (inputrec->epc == PressureCoupling::Berendsen + && do_per_step(step, inputrec->nstpcouple)); + const bool doCRescalePressureCoupling = (inputrec->epc == PressureCoupling::CRescale + && do_per_step(step, inputrec->nstpcouple)); if (useGpuForUpdate && (doBerendsenPressureCoupling || doCRescalePressureCoupling || doParrinelloRahman)) { diff --git a/src/gromacs/mdrun/replicaexchange.cpp b/src/gromacs/mdrun/replicaexchange.cpp index 19172eb0de..e23bea4250 100644 --- a/src/gromacs/mdrun/replicaexchange.cpp +++ b/src/gromacs/mdrun/replicaexchange.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. - * Copyright (c) 2011-2019,2020, by the GROMACS development team, led by + * Copyright (c) 2011-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. @@ -253,9 +253,9 @@ gmx_repl_ex_t init_replica_exchange(FILE* fplog, const int nst = replExParams.exchangeInterval; check_multi_int64( fplog, ms, (ir->init_step + nst - 1) / nst, "first exchange step: init_step/-replex", FALSE); - check_multi_int(fplog, ms, ir->etc, "the temperature coupling", FALSE); + check_multi_int(fplog, ms, static_cast(ir->etc), "the temperature coupling", FALSE); check_multi_int(fplog, ms, ir->opts.ngtc, "the number of temperature coupling groups", FALSE); - check_multi_int(fplog, ms, ir->epc, "the pressure coupling", FALSE); + check_multi_int(fplog, ms, static_cast(ir->epc), "the pressure coupling", FALSE); check_multi_int(fplog, ms, ir->efep, "free energy", FALSE); check_multi_int(fplog, ms, ir->fepvals->n_lambda, "number of lambda states", FALSE); @@ -293,19 +293,19 @@ gmx_repl_ex_t init_replica_exchange(FILE* fplog, if (bTemp) { please_cite(fplog, "Sugita1999a"); - if (ir->epc != epcNO) + if (ir->epc != PressureCoupling::No) { re->bNPT = TRUE; fprintf(fplog, "Repl Using Constant Pressure REMD.\n"); please_cite(fplog, "Okabe2001a"); } - if (ir->etc == etcBERENDSEN) + if (ir->etc == TemperatureCoupling::Berendsen) { gmx_fatal(FARGS, "REMD with the %s thermostat does not produce correct potential energy " "distributions, consider using the %s thermostat instead", - ETCOUPLTYPE(ir->etc), - ETCOUPLTYPE(etcVRESCALE)); + enumValueToString(ir->etc), + enumValueToString(TemperatureCoupling::VRescale)); } } if (bLambda) diff --git a/src/gromacs/mdrun/runner.cpp b/src/gromacs/mdrun/runner.cpp index d42675f9fa..cb76c778a3 100644 --- a/src/gromacs/mdrun/runner.cpp +++ b/src/gromacs/mdrun/runner.cpp @@ -431,7 +431,8 @@ static void prepare_verlet_scheme(FILE* fplog, "With Verlet lists and no PME rcoulomb and rvdw should be identical"); } /* For NVE simulations, we will retain the initial list buffer */ - if (EI_DYNAMICS(ir->eI) && ir->verletbuf_tol > 0 && !(EI_MD(ir->eI) && ir->etc == etcNO)) + if (EI_DYNAMICS(ir->eI) && ir->verletbuf_tol > 0 + && !(EI_MD(ir->eI) && ir->etc == TemperatureCoupling::No)) { /* Update the Verlet buffer size for the current run setup */ diff --git a/src/gromacs/mdtypes/inputrec.cpp b/src/gromacs/mdtypes/inputrec.cpp index ef67f95d5d..903e3ef62e 100644 --- a/src/gromacs/mdtypes/inputrec.cpp +++ b/src/gromacs/mdtypes/inputrec.cpp @@ -119,22 +119,22 @@ int ir_optimal_nstcalcenergy(const t_inputrec* ir) return nst; } -int tcouple_min_integration_steps(int etc) +int tcouple_min_integration_steps(TemperatureCoupling etc) { int n; switch (etc) { - case etcNO: n = 0; break; - case etcBERENDSEN: - case etcYES: n = nstmin_berendsen_tcouple; break; - case etcVRESCALE: + case TemperatureCoupling::No: n = 0; break; + case TemperatureCoupling::Berendsen: + case TemperatureCoupling::Yes: n = nstmin_berendsen_tcouple; break; + case TemperatureCoupling::VRescale: /* V-rescale supports instantaneous rescaling */ n = 0; break; - case etcNOSEHOOVER: n = nstmin_harmonic; break; - case etcANDERSEN: - case etcANDERSENMASSIVE: n = 1; break; + case TemperatureCoupling::NoseHoover: n = nstmin_harmonic; break; + case TemperatureCoupling::Andersen: + case TemperatureCoupling::AndersenMassive: n = 1; break; default: gmx_incons("Unknown etc value"); } @@ -152,7 +152,7 @@ int ir_optimal_nsttcouple(const t_inputrec* ir) nwanted = c_defaultNstTCouple; tau_min = 1e20; - if (ir->etc != etcNO) + if (ir->etc != TemperatureCoupling::No) { for (g = 0; g < ir->opts.ngtc; g++) { @@ -183,18 +183,18 @@ int ir_optimal_nsttcouple(const t_inputrec* ir) return n; } -int pcouple_min_integration_steps(int epc) +int pcouple_min_integration_steps(PressureCoupling epc) { int n; switch (epc) { - case epcNO: n = 0; break; - case epcBERENDSEN: - case epcCRESCALE: - case epcISOTROPIC: n = nstmin_berendsen_pcouple; break; - case epcPARRINELLORAHMAN: - case epcMTTK: n = nstmin_harmonic; break; + case PressureCoupling::No: n = 0; break; + case PressureCoupling::Berendsen: + case PressureCoupling::CRescale: + case PressureCoupling::Isotropic: n = nstmin_berendsen_pcouple; break; + case PressureCoupling::ParrinelloRahman: + case PressureCoupling::Mttk: n = nstmin_harmonic; break; default: gmx_incons("Unknown epc value"); } @@ -906,12 +906,12 @@ void pr_inputrec(FILE* fp, int indent, const char* title, const t_inputrec* ir, PR("epsilon-surface", ir->epsilon_surface); /* Options for weak coupling algorithms */ - PS("tcoupl", ETCOUPLTYPE(ir->etc)); + PS("tcoupl", enumValueToString(ir->etc)); PI("nsttcouple", ir->nsttcouple); PI("nh-chain-length", ir->opts.nhchainlength); PS("print-nose-hoover-chain-variables", EBOOL(ir->bPrintNHChains)); - PS("pcoupl", EPCOUPLTYPE(ir->epc)); + PS("pcoupl", enumValueToString(ir->epc)); PS("pcoupltype", EPCOUPLTYPETYPE(ir->epct)); PI("nstpcouple", ir->nstpcouple); PR("tau-p", ir->tau_p); @@ -1382,13 +1382,13 @@ void cmp_inputrec(FILE* fp, const t_inputrec* ir1, const t_inputrec* ir2, real f static_cast(ir1->bContinuation), static_cast(ir2->bContinuation)); cmp_int(fp, "inputrec->bShakeSOR", -1, static_cast(ir1->bShakeSOR), static_cast(ir2->bShakeSOR)); - cmp_int(fp, "inputrec->etc", -1, ir1->etc, ir2->etc); + cmpEnum(fp, "inputrec->etc", ir1->etc, ir2->etc); cmp_int(fp, "inputrec->bPrintNHChains", -1, static_cast(ir1->bPrintNHChains), static_cast(ir2->bPrintNHChains)); - cmp_int(fp, "inputrec->epc", -1, ir1->epc, ir2->epc); + cmpEnum(fp, "inputrec->epc", ir1->epc, ir2->epc); cmp_int(fp, "inputrec->epct", -1, ir1->epct, ir2->epct); cmp_real(fp, "inputrec->tau_p", -1, ir1->tau_p, ir2->tau_p, ftol, abstol); cmp_rvec(fp, "inputrec->ref_p(x)", -1, ir1->ref_p[XX], ir2->ref_p[XX], ftol, abstol); @@ -1516,12 +1516,12 @@ gmx_bool inputrecDeform(const t_inputrec* ir) gmx_bool inputrecDynamicBox(const t_inputrec* ir) { - return (ir->epc != epcNO || ir->eI == eiTPI || inputrecDeform(ir)); + return (ir->epc != PressureCoupling::No || ir->eI == eiTPI || inputrecDeform(ir)); } gmx_bool inputrecPreserveShape(const t_inputrec* ir) { - return (ir->epc != epcNO && ir->deform[XX][XX] == 0 + return (ir->epc != PressureCoupling::No && ir->deform[XX][XX] == 0 && (ir->epct == epctISOTROPIC || ir->epct == epctSEMIISOTROPIC)); } @@ -1538,17 +1538,20 @@ gmx_bool inputrecExclForces(const t_inputrec* ir) gmx_bool inputrecNptTrotter(const t_inputrec* ir) { - return (((ir->eI == eiVV) || (ir->eI == eiVVAK)) && (ir->epc == epcMTTK) && (ir->etc == etcNOSEHOOVER)); + return (((ir->eI == eiVV) || (ir->eI == eiVVAK)) && (ir->epc == PressureCoupling::Mttk) + && (ir->etc == TemperatureCoupling::NoseHoover)); } gmx_bool inputrecNvtTrotter(const t_inputrec* ir) { - return (((ir->eI == eiVV) || (ir->eI == eiVVAK)) && (ir->epc != epcMTTK) && (ir->etc == etcNOSEHOOVER)); + return (((ir->eI == eiVV) || (ir->eI == eiVVAK)) && (ir->epc != PressureCoupling::Mttk) + && (ir->etc == TemperatureCoupling::NoseHoover)); } gmx_bool inputrecNphTrotter(const t_inputrec* ir) { - return (((ir->eI == eiVV) || (ir->eI == eiVVAK)) && (ir->epc == epcMTTK) && (ir->etc != etcNOSEHOOVER)); + return (((ir->eI == eiVV) || (ir->eI == eiVVAK)) && (ir->epc == PressureCoupling::Mttk) + && (ir->etc != TemperatureCoupling::NoseHoover)); } bool inputrecPbcXY2Walls(const t_inputrec* ir) @@ -1563,7 +1566,7 @@ bool integratorHasConservedEnergyQuantity(const t_inputrec* ir) // Energy minimization or stochastic integrator: no conservation return false; } - else if (ir->etc == etcNO && ir->epc == epcNO) + else if (ir->etc == TemperatureCoupling::No && ir->epc == PressureCoupling::No) { // The total energy is conserved, no additional conserved quanitity return false; @@ -1572,7 +1575,7 @@ bool integratorHasConservedEnergyQuantity(const t_inputrec* ir) { // Shear stress with Parrinello-Rahman is not supported (tedious) bool shearWithPR = - ((ir->epc == epcPARRINELLORAHMAN || ir->epc == epcMTTK) + ((ir->epc == PressureCoupling::ParrinelloRahman || ir->epc == PressureCoupling::Mttk) && (ir->ref_p[YY][XX] != 0 || ir->ref_p[ZZ][XX] != 0 || ir->ref_p[ZZ][YY] != 0)); return !ETC_ANDERSEN(ir->etc) && !shearWithPR; @@ -1581,7 +1584,7 @@ bool integratorHasConservedEnergyQuantity(const t_inputrec* ir) bool integratorHasReferenceTemperature(const t_inputrec* ir) { - return ((ir->etc != etcNO) || EI_SD(ir->eI) || (ir->eI == eiBD) || EI_TPI(ir->eI)); + return ((ir->etc != TemperatureCoupling::No) || EI_SD(ir->eI) || (ir->eI == eiBD) || EI_TPI(ir->eI)); } int inputrec2nboundeddim(const t_inputrec* ir) @@ -1619,7 +1622,7 @@ real maxReferenceTemperature(const t_inputrec& ir) return 0; } - if (EI_MD(ir.eI) && ir.etc == etcNO) + if (EI_MD(ir.eI) && ir.etc == TemperatureCoupling::No) { return -1; } diff --git a/src/gromacs/mdtypes/inputrec.h b/src/gromacs/mdtypes/inputrec.h index 996e6d30cf..dc2350acd7 100644 --- a/src/gromacs/mdtypes/inputrec.h +++ b/src/gromacs/mdtypes/inputrec.h @@ -379,13 +379,13 @@ struct t_inputrec // NOLINT (clang-analyzer-optin.performance.Padding) //! Continuation run: starting state is correct (ie. constrained) gmx_bool bContinuation; //! Temperature coupling - int etc; + TemperatureCoupling etc; //! Interval in steps for temperature coupling int nsttcouple; //! Whether to print nose-hoover chains gmx_bool bPrintNHChains; //! Pressure coupling - int epc; + PressureCoupling epc; //! Pressure coupling type int epct; //! Interval in steps for pressure coupling @@ -572,11 +572,11 @@ struct t_inputrec // NOLINT (clang-analyzer-optin.performance.Padding) int ir_optimal_nstcalcenergy(const t_inputrec* ir); -int tcouple_min_integration_steps(int etc); +int tcouple_min_integration_steps(TemperatureCoupling etc); int ir_optimal_nsttcouple(const t_inputrec* ir); -int pcouple_min_integration_steps(int epc); +int pcouple_min_integration_steps(PressureCoupling epc); int ir_optimal_nstpcouple(const t_inputrec* ir); diff --git a/src/gromacs/mdtypes/md_enums.cpp b/src/gromacs/mdtypes/md_enums.cpp index bd498df332..c3313017cb 100644 --- a/src/gromacs/mdtypes/md_enums.cpp +++ b/src/gromacs/mdtypes/md_enums.cpp @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -39,6 +39,8 @@ #include "md_enums.h" +#include "gromacs/utility/enumerationhelpers.h" + const char* enum_name(int index, int max_index, const char* const names[]) { if (index < 0 || index >= max_index) @@ -95,13 +97,21 @@ const char* eintmod_names[eintmodNR + 1] = { "Exact-cutoff", "Force-switch", nullptr }; -const char* etcoupl_names[etcNR + 1] = { - "No", "Berendsen", "Nose-Hoover", "yes", "Andersen", "Andersen-massive", "V-rescale", nullptr -}; /* yes is alias for berendsen */ +const char* enumValueToString(TemperatureCoupling enumValue) +{ + static constexpr gmx::EnumerationArray temperatureCouplingNames = { + "No", "Berendsen", "Nose-Hoover", "yes", "Andersen", "Andersen-massive", "V-rescale" + }; /* yes is alias for berendsen */ + return temperatureCouplingNames[enumValue]; +} -const char* epcoupl_names[epcNR + 1] = { "No", "Berendsen", "Parrinello-Rahman", - "Isotropic", "MTTK", "C-rescale", - nullptr }; /* isotropic is alias for berendsen */ +const char* enumValueToString(PressureCoupling enumValue) +{ + static constexpr gmx::EnumerationArray pressureCouplingNames = { + "No", "Berendsen", "Parrinello-Rahman", "Isotropic", "MTTK", "C-rescale" + }; /* isotropic is alias for berendsen */ + return pressureCouplingNames[enumValue]; +} const char* epcoupltype_names[epctNR + 1] = { "Isotropic", "Semiisotropic", diff --git a/src/gromacs/mdtypes/md_enums.h b/src/gromacs/mdtypes/md_enums.h index 7631433612..2f358ca418 100644 --- a/src/gromacs/mdtypes/md_enums.h +++ b/src/gromacs/mdtypes/md_enums.h @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -85,43 +85,50 @@ enum eChannel /*! \brief Temperature coupling type * * yes is an alias for berendsen + * + * Note: Keep `Count` as the second-to-last entry, and `Default` as the last entry - + * this is needed to keep EnumerationWrapper, EnumerationArray and (de)serialization + * working. */ -enum -{ - etcNO, - etcBERENDSEN, - etcNOSEHOOVER, - etcYES, - etcANDERSEN, - etcANDERSENMASSIVE, - etcVRESCALE, - etcNR -}; -//! Strings corresponding to temperatyre coupling types -extern const char* etcoupl_names[etcNR + 1]; -//! Macro for selecting t coupling string -#define ETCOUPLTYPE(e) enum_name(e, etcNR, etcoupl_names) +enum class TemperatureCoupling : int +{ + No, + Berendsen, + NoseHoover, + Yes, + Andersen, + AndersenMassive, + VRescale, + Count, + Default = No +}; +//! Return names of temperature coupling schemes +const char* enumValueToString(TemperatureCoupling enumValue); //! Return whether this is andersen coupling -#define ETC_ANDERSEN(e) (((e) == etcANDERSENMASSIVE) || ((e) == etcANDERSEN)) +#define ETC_ANDERSEN(e) \ + (((e) == TemperatureCoupling::AndersenMassive) || ((e) == TemperatureCoupling::Andersen)) /*! \brief Pressure coupling types * * isotropic is an alias for berendsen + * + * Note: Keep `Count` as the second-to-last entry, and `Default` as the last entry - + * this is needed to keep EnumerationWrapper, EnumerationArray and (de)serialization + * working. */ -enum -{ - epcNO, - epcBERENDSEN, - epcPARRINELLORAHMAN, - epcISOTROPIC, - epcMTTK, - epcCRESCALE, - epcNR -}; -//! String corresponding to pressure coupling algorithm -extern const char* epcoupl_names[epcNR + 1]; -//! Macro to return the correct pcoupling string -#define EPCOUPLTYPE(e) enum_name(e, epcNR, epcoupl_names) +enum class PressureCoupling : int +{ + No, + Berendsen, + ParrinelloRahman, + Isotropic, + Mttk, + CRescale, + Count, + Default = No +}; +//! Return names of pressure coupling schemes +const char* enumValueToString(PressureCoupling enumValue); //! Flat-bottom posres geometries enum diff --git a/src/gromacs/modularsimulator/modularsimulator.cpp b/src/gromacs/modularsimulator/modularsimulator.cpp index 3109250f9b..d43052c48f 100644 --- a/src/gromacs/modularsimulator/modularsimulator.cpp +++ b/src/gromacs/modularsimulator/modularsimulator.cpp @@ -111,8 +111,8 @@ void ModularSimulator::addIntegrationElements(ModularSimulatorAlgorithmBuilder* // The leap frog integration algorithm builder->add(); builder->add(); - if (legacySimulatorData_->inputrec->etc == etcVRESCALE - || legacySimulatorData_->inputrec->etc == etcBERENDSEN) + if (legacySimulatorData_->inputrec->etc == TemperatureCoupling::VRescale + || legacySimulatorData_->inputrec->etc == TemperatureCoupling::Berendsen) { builder->add( -1, UseFullStepKE::No, ReportPreviousStepConservedEnergy::No); @@ -126,7 +126,7 @@ void ModularSimulator::addIntegrationElements(ModularSimulatorAlgorithmBuilder* } builder->add>(); builder->add(); - if (legacySimulatorData_->inputrec->epc == epcPARRINELLORAHMAN) + if (legacySimulatorData_->inputrec->epc == PressureCoupling::ParrinelloRahman) { builder->add(-1); } @@ -145,8 +145,8 @@ void ModularSimulator::addIntegrationElements(ModularSimulatorAlgorithmBuilder* } builder->add>(); builder->add(); - if (legacySimulatorData_->inputrec->etc == etcVRESCALE - || legacySimulatorData_->inputrec->etc == etcBERENDSEN) + if (legacySimulatorData_->inputrec->etc == TemperatureCoupling::VRescale + || legacySimulatorData_->inputrec->etc == TemperatureCoupling::Berendsen) { builder->add( 0, UseFullStepKE::Yes, ReportPreviousStepConservedEnergy::Yes); @@ -161,7 +161,7 @@ void ModularSimulator::addIntegrationElements(ModularSimulatorAlgorithmBuilder* } builder->add>(); builder->add(); - if (legacySimulatorData_->inputrec->epc == epcPARRINELLORAHMAN) + if (legacySimulatorData_->inputrec->epc == PressureCoupling::ParrinelloRahman) { builder->add(-1); } @@ -206,7 +206,7 @@ bool ModularSimulator::isInputCompatible(bool exitOn GMX_RELEASE_ASSERT( !(modularSimulatorExplicitlyTurnedOff && inputrec->eI == eiVV - && inputrec->epc == epcPARRINELLORAHMAN), + && inputrec->epc == PressureCoupling::ParrinelloRahman), "Cannot use a Parrinello-Rahman barostat with md-vv and " "GMX_DISABLE_MODULAR_SIMULATOR=ON, " "as the Parrinello-Rahman barostat is not implemented in the legacy simulator. Unset " @@ -228,14 +228,16 @@ bool ModularSimulator::isInputCompatible(bool exitOn isInputCompatible && conditionalAssert(!doRerun, "Rerun is not supported by the modular simulator."); isInputCompatible = isInputCompatible - && conditionalAssert(inputrec->etc == etcNO || inputrec->etc == etcVRESCALE - || inputrec->etc == etcBERENDSEN, + && conditionalAssert(inputrec->etc == TemperatureCoupling::No + || inputrec->etc == TemperatureCoupling::VRescale + || inputrec->etc == TemperatureCoupling::Berendsen, "Only v-rescale and Berendsen thermostat are " "supported by the modular simulator."); isInputCompatible = isInputCompatible && conditionalAssert( - inputrec->epc == epcNO || inputrec->epc == epcPARRINELLORAHMAN, + inputrec->epc == PressureCoupling::No + || inputrec->epc == PressureCoupling::ParrinelloRahman, "Only Parrinello-Rahman barostat is supported by the modular simulator."); isInputCompatible = isInputCompatible @@ -356,7 +358,8 @@ bool ModularSimulator::isInputCompatible(bool exitOn && conditionalAssert(!GMX_FAHCORE, "GMX_FAHCORE not supported by the modular simulator."); GMX_RELEASE_ASSERT( - isInputCompatible || !(inputrec->eI == eiVV && inputrec->epc == epcPARRINELLORAHMAN), + isInputCompatible + || !(inputrec->eI == eiVV && inputrec->epc == PressureCoupling::ParrinelloRahman), "Requested Parrinello-Rahman barostat with md-vv, but other options are not compatible " "with the modular simulator. The Parrinello-Rahman barostat is not implemented for " "md-vv in the legacy simulator. Use a different pressure control algorithm."); diff --git a/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.cpp b/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.cpp index 89e8b69e05..95158d5034 100644 --- a/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.cpp +++ b/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.cpp @@ -1,7 +1,7 @@ /* * This file is part of the GROMACS molecular simulation package. * - * Copyright (c) 2019,2020, by the GROMACS development team, led by + * Copyright (c) 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. @@ -283,7 +283,7 @@ VelocityScalingTemperatureCoupling::VelocityScalingTemperatureCoupling( const real* couplingTime, const real* numDegreesOfFreedom, EnergyData* energyData, - TemperatureCouplingType couplingType) : + TemperatureCoupling couplingType) : nstcouple_(nstcouple), offset_(offset), useFullStepKE_(useFullStepKE), @@ -301,17 +301,17 @@ VelocityScalingTemperatureCoupling::VelocityScalingTemperatureCoupling( temperatureCouplingIntegralPreviousStep_ = temperatureCouplingIntegral_; } energyData->setVelocityScalingTemperatureCoupling(this); - if (couplingType == etcVRESCALE) + if (couplingType == TemperatureCoupling::VRescale) { temperatureCouplingImpl_ = std::make_unique(seed); } - else if (couplingType == etcBERENDSEN) + else if (couplingType == TemperatureCoupling::Berendsen) { temperatureCouplingImpl_ = std::make_unique(); } else { - throw NotImplementedError("Temperature coupling " + std::string(ETCOUPLTYPE(couplingType)) + throw NotImplementedError("Temperature coupling " + std::string(enumValueToString(couplingType)) + " is not implemented for modular simulator."); } } diff --git a/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.h b/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.h index 9bd3f74038..68daad8497 100644 --- a/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.h +++ b/src/gromacs/modularsimulator/velocityscalingtemperaturecoupling.h @@ -1,7 +1,7 @@ /* * This file is part of the GROMACS molecular simulation package. * - * Copyright (c) 2019,2020, by the GROMACS development team, led by + * Copyright (c) 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. @@ -75,9 +75,6 @@ enum class ReportPreviousStepConservedEnergy Count }; -//! Typedef to match current use of ints as types. -using TemperatureCouplingType = int; - /*! \internal * \ingroup module_modularsimulator * \brief Element implementing the a velocity-scaling thermostat @@ -104,7 +101,7 @@ public: const real* couplingTime, const real* numDegreesOfFreedom, EnergyData* energyData, - TemperatureCouplingType couplingType); + TemperatureCoupling couplingType); /*! \brief Register run function for step / time * diff --git a/src/gromacs/nbnxm/pairlist_tuning.cpp b/src/gromacs/nbnxm/pairlist_tuning.cpp index c9c3f3df8d..db31748bbf 100644 --- a/src/gromacs/nbnxm/pairlist_tuning.cpp +++ b/src/gromacs/nbnxm/pairlist_tuning.cpp @@ -1,7 +1,7 @@ /* * This file is part of the GROMACS molecular simulation package. * - * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by + * Copyright (c) 2017,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. @@ -80,7 +80,7 @@ static bool supportsDynamicPairlistGenerationInterval(const t_inputrec& ir) { return ir.cutoff_scheme == ecutsVERLET && EI_DYNAMICS(ir.eI) - && !(EI_MD(ir.eI) && ir.etc == etcNO) && ir.verletbuf_tol > 0; + && !(EI_MD(ir.eI) && ir.etc == TemperatureCoupling::No) && ir.verletbuf_tol > 0; } /*! \brief Cost of non-bonded kernels @@ -190,7 +190,7 @@ void increaseNstlist(FILE* fp, } } - if (EI_MD(ir->eI) && ir->etc == etcNO) + if (EI_MD(ir->eI) && ir->etc == TemperatureCoupling::No) { if (MASTER(cr)) { diff --git a/src/gromacs/taskassignment/decidegpuusage.cpp b/src/gromacs/taskassignment/decidegpuusage.cpp index 7d96638fde..5d771e5265 100644 --- a/src/gromacs/taskassignment/decidegpuusage.cpp +++ b/src/gromacs/taskassignment/decidegpuusage.cpp @@ -2,7 +2,7 @@ * This file is part of the GROMACS molecular simulation package. * * Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team. - * Copyright (c) 2020, by the GROMACS development team, led by + * Copyright (c) 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. @@ -617,12 +617,12 @@ bool decideWhetherToUseGpuForUpdate(const bool isDomainDecom { errorMessage += "Only the md integrator is supported.\n"; } - if (inputrec.etc == etcNOSEHOOVER) + if (inputrec.etc == TemperatureCoupling::NoseHoover) { errorMessage += "Nose-Hoover temperature coupling is not supported.\n"; } - if (!(inputrec.epc == epcNO || inputrec.epc == epcPARRINELLORAHMAN - || inputrec.epc == epcBERENDSEN || inputrec.epc == epcCRESCALE)) + if (!(inputrec.epc == PressureCoupling::No || inputrec.epc == PressureCoupling::ParrinelloRahman + || inputrec.epc == PressureCoupling::Berendsen || inputrec.epc == PressureCoupling::CRescale)) { errorMessage += "Only Parrinello-Rahman, Berendsen, and C-rescale pressure coupling are " diff --git a/src/gromacs/tools/report_methods.cpp b/src/gromacs/tools/report_methods.cpp index f7889056b1..9aba51b78d 100644 --- a/src/gromacs/tools/report_methods.cpp +++ b/src/gromacs/tools/report_methods.cpp @@ -1,7 +1,7 @@ /* * This file is part of the GROMACS molecular simulation package. * - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -118,15 +118,15 @@ void writeParameterInformation(TextWriter* writer, const t_inputrec& ir, bool wr } writer->writeLine(formatString( "A single cut-off of %g nm was used for Van der Waals interactions.", ir.rlist)); - if (ir.etc != 0) + if (ir.etc != TemperatureCoupling::No) { writer->writeLine(formatString("Temperature coupling was done with the %s algorithm.", - etcoupl_names[ir.etc])); + enumValueToString(ir.etc))); } - if (ir.epc != 0) + if (ir.epc != PressureCoupling::No) { writer->writeLine(formatString("Pressure coupling was done with the %s algorithm.", - epcoupl_names[ir.epc])); + enumValueToString(ir.epc))); } writer->ensureEmptyLine(); } diff --git a/src/gromacs/utility/compare.h b/src/gromacs/utility/compare.h index 6ab41cd3d3..e8e39484ce 100644 --- a/src/gromacs/utility/compare.h +++ b/src/gromacs/utility/compare.h @@ -4,7 +4,7 @@ * Copyright (c) 1991-2000, University of Groningen, The Netherlands. * Copyright (c) 2001-2004, The GROMACS development team. * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team. - * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by + * 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. @@ -47,6 +47,7 @@ #include +#include "gromacs/mdtypes/md_enums.h" #include "gromacs/utility/basedefinitions.h" #include "gromacs/utility/real.h" @@ -84,4 +85,18 @@ void cmp_float(FILE* fp, const char* s, int index, float i1, float i2, float fto //! Compares two doubles and prints differences. void cmp_double(FILE* fp, const char* s, int index, double i1, double i2, double ftol, double abstol); +//! Compare two enums of generic type and print differences. +template +void cmpEnum(FILE* fp, const char* s, EnumType value1, EnumType value2) +{ + if (value1 != value2) + { + fprintf(fp, "%s (", s); + fprintf(fp, "%s", enumValueToString(value1)); + fprintf(fp, " - "); + fprintf(fp, "%s", enumValueToString(value2)); + fprintf(fp, ")\n"); + } +} + #endif diff --git a/src/gromacs/utility/iserializer.h b/src/gromacs/utility/iserializer.h index aa68dea4f7..ffa4dd6345 100644 --- a/src/gromacs/utility/iserializer.h +++ b/src/gromacs/utility/iserializer.h @@ -1,7 +1,7 @@ /* * This file is part of the GROMACS molecular simulation package. * - * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by + * Copyright (c) 2016,2017,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. @@ -179,6 +179,17 @@ public: } } ///@} + + //! Serialize enum value with underlying type int + template + void doEnumAsInt(EnumType* enumValue) + { + static_assert(std::is_same, int>::value, + "Only enums with underlying type int are supported."); + auto castedValue = static_cast(*enumValue); + doInt(&castedValue); + *enumValue = static_cast(castedValue); + } }; } // namespace gmx -- 2.22.0