Rework state checkpoint enum handling
authorPaul Bauer <paul.bauer.q@gmail.com>
Wed, 24 Feb 2021 17:05:57 +0000 (17:05 +0000)
committerPaul Bauer <paul.bauer.q@gmail.com>
Wed, 24 Feb 2021 17:05:57 +0000 (17:05 +0000)
The state enumerations have been changed to enum classes and enumeration
arrays. This was required by clang-tidy to remove the global available char
arrays.

Added templated function to convert enum to underlying int.

Was able to simplify quite a lot of the checkpoint handling that had to
work around the pure ints used before the enumerations to get the
correct names for the entries.

18 files changed:
src/gromacs/domdec/collect.cpp
src/gromacs/domdec/distribute.cpp
src/gromacs/domdec/partition.cpp
src/gromacs/domdec/redistribute.cpp
src/gromacs/fileio/checkpoint.cpp
src/gromacs/fileio/tpxio.cpp
src/gromacs/gmxpreprocess/grompp.cpp
src/gromacs/listed_forces/disre.cpp
src/gromacs/listed_forces/orires.cpp
src/gromacs/mdlib/broadcaststructs.cpp
src/gromacs/mdlib/md_support.cpp
src/gromacs/mdlib/update.cpp
src/gromacs/mdrun/md.cpp
src/gromacs/mdrun/minimize.cpp
src/gromacs/mdrun/runner.cpp
src/gromacs/mdtypes/state.cpp
src/gromacs/mdtypes/state.h
src/gromacs/modularsimulator/statepropagatordata.cpp

index 63167f8f395d435d6496b504787df2de0916ab65..6d6c4a2dc45087ac5ef096b69ea445954894f5b7 100644 (file)
@@ -306,7 +306,7 @@ void dd_collect_state(gmx_domdec_t* dd, const t_state* state_local, t_state* sta
         state->baros_integral     = state_local->baros_integral;
         state->pull_com_prev_step = state_local->pull_com_prev_step;
     }
-    if (state_local->flags & (1 << estX))
+    if (state_local->flags & enumValueToBitMask(StateEntry::X))
     {
         auto globalXRef = state ? state->x : gmx::ArrayRef<gmx::RVec>();
         dd_collect_vec(dd,
@@ -316,7 +316,7 @@ void dd_collect_state(gmx_domdec_t* dd, const t_state* state_local, t_state* sta
                        state_local->x,
                        globalXRef);
     }
-    if (state_local->flags & (1 << estV))
+    if (state_local->flags & enumValueToBitMask(StateEntry::V))
     {
         auto globalVRef = state ? state->v : gmx::ArrayRef<gmx::RVec>();
         dd_collect_vec(dd,
@@ -326,7 +326,7 @@ void dd_collect_state(gmx_domdec_t* dd, const t_state* state_local, t_state* sta
                        state_local->v,
                        globalVRef);
     }
-    if (state_local->flags & (1 << estCGP))
+    if (state_local->flags & enumValueToBitMask(StateEntry::Cgp))
     {
         auto globalCgpRef = state ? state->cg_p : gmx::ArrayRef<gmx::RVec>();
         dd_collect_vec(dd,
index efa2611c1b6742c1f408560682bc466805f8437b..9adb561d415741a49d1ff1bb93507fb5334624bc 100644 (file)
@@ -262,15 +262,15 @@ static void dd_distribute_state(gmx_domdec_t* dd, const t_state* state, t_state*
 
     state_change_natoms(state_local, dd->comm->atomRanges.numHomeAtoms());
 
-    if (state_local->flags & (1 << estX))
+    if (state_local->flags & enumValueToBitMask(StateEntry::X))
     {
         distributeVec(dd, DDMASTER(dd) ? state->x : gmx::ArrayRef<const gmx::RVec>(), state_local->x);
     }
-    if (state_local->flags & (1 << estV))
+    if (state_local->flags & enumValueToBitMask(StateEntry::V))
     {
         distributeVec(dd, DDMASTER(dd) ? state->v : gmx::ArrayRef<const gmx::RVec>(), state_local->v);
     }
-    if (state_local->flags & (1 << estCGP))
+    if (state_local->flags & enumValueToBitMask(StateEntry::Cgp))
     {
         distributeVec(dd, DDMASTER(dd) ? state->cg_p : gmx::ArrayRef<const gmx::RVec>(), state_local->cg_p);
     }
index c093a39d42527753e36f9d6fde4db71924d5594b..bf73b3b25fb25333ed07fa2b9c98625fa78f29e6 100644 (file)
@@ -2616,15 +2616,15 @@ static void dd_sort_state(gmx_domdec_t* dd, t_forcerec* fr, t_state* state)
     gmx::ArrayRef<const gmx_cgsort_t> cgsort = sort->sorted;
     GMX_RELEASE_ASSERT(cgsort.ssize() == dd->ncg_home, "We should sort all the home atom groups");
 
-    if (state->flags & (1 << estX))
+    if (state->flags & enumValueToBitMask(StateEntry::X))
     {
         orderVector(cgsort, makeArrayRef(state->x), rvecBuffer.buffer);
     }
-    if (state->flags & (1 << estV))
+    if (state->flags & enumValueToBitMask(StateEntry::V))
     {
         orderVector(cgsort, makeArrayRef(state->v), rvecBuffer.buffer);
     }
-    if (state->flags & (1 << estCGP))
+    if (state->flags & enumValueToBitMask(StateEntry::Cgp))
     {
         orderVector(cgsort, makeArrayRef(state->cg_p), rvecBuffer.buffer);
     }
index 7a6537ca8de5a8f9ac3fdabc34902a812a462886..0aaf1cdefd2f64f30e105e6b200f26fdf8405046 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 2005,2006,2007,2008,2009 by the GROMACS development team.
  * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
  * 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.
@@ -228,20 +228,20 @@ static void print_cg_move(FILE*               fplog,
 
 static void rotate_state_atom(t_state* state, int a)
 {
-    if (state->flags & (1 << estX))
+    if (state->flags & enumValueToBitMask(StateEntry::X))
     {
         auto x = makeArrayRef(state->x);
         /* Rotate the complete state; for a rectangular box only */
         x[a][YY] = state->box[YY][YY] - x[a][YY];
         x[a][ZZ] = state->box[ZZ][ZZ] - x[a][ZZ];
     }
-    if (state->flags & (1 << estV))
+    if (state->flags & enumValueToBitMask(StateEntry::V))
     {
         auto v   = makeArrayRef(state->v);
         v[a][YY] = -v[a][YY];
         v[a][ZZ] = -v[a][ZZ];
     }
-    if (state->flags & (1 << estCGP))
+    if (state->flags & enumValueToBitMask(StateEntry::Cgp))
     {
         auto cg_p   = makeArrayRef(state->cg_p);
         cg_p[a][YY] = -cg_p[a][YY];
@@ -571,8 +571,8 @@ void dd_redistribute_cg(FILE*         fplog,
     }
 
     // Positions are always present, so there's nothing to flag
-    bool bV   = (state->flags & (1 << estV)) != 0;
-    bool bCGP = (state->flags & (1 << estCGP)) != 0;
+    bool bV   = (state->flags & enumValueToBitMask(StateEntry::V)) != 0;
+    bool bCGP = (state->flags & enumValueToBitMask(StateEntry::Cgp)) != 0;
 
     DDBufferAccess<int> moveBuffer(comm->intBuffer, dd->ncg_home);
     gmx::ArrayRef<int>  move = moveBuffer.buffer;
index bb08642efb755317ed9e754ebeefdd12d6d5d9ab..f1ce7802f9b35867dbcfd681838c9869d89eb775 100644 (file)
@@ -77,6 +77,7 @@
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/baseversion.h"
 #include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/futil.h"
 #include "gromacs/utility/gmxassert.h"
@@ -179,183 +180,228 @@ enum cptv
  * the correct code path. */
 static const int cpt_version = cptv_Count - 1;
 
+const char* enumValueToString(StateEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StateEntry, const char*> stateEntryNames = {
+        "FE-lambda",
+        "box",
+        "box-rel",
+        "box-v",
+        "pres_prev",
+        "nosehoover-xi",
+        "thermostat-integral",
+        "x",
+        "v",
+        "sdx-unsupported",
+        "CGp",
+        "LD-rng-unsupported",
+        "LD-rng-i-unsupported",
+        "disre_initf",
+        "disre_rm3tav",
+        "orire_initf",
+        "orire_Dtav",
+        "svir_prev",
+        "nosehoover-vxi",
+        "v_eta",
+        "vol0",
+        "nhpres_xi",
+        "nhpres_vxi",
+        "fvir_prev",
+        "fep_state",
+        "MC-rng-unsupported",
+        "MC-rng-i-unsupported",
+        "barostat-integral"
+    };
+    return stateEntryNames[enumValue];
+}
 
-const char* est_names[estNR] = { "FE-lambda",
-                                 "box",
-                                 "box-rel",
-                                 "box-v",
-                                 "pres_prev",
-                                 "nosehoover-xi",
-                                 "thermostat-integral",
-                                 "x",
-                                 "v",
-                                 "sdx-unsupported",
-                                 "CGp",
-                                 "LD-rng-unsupported",
-                                 "LD-rng-i-unsupported",
-                                 "disre_initf",
-                                 "disre_rm3tav",
-                                 "orire_initf",
-                                 "orire_Dtav",
-                                 "svir_prev",
-                                 "nosehoover-vxi",
-                                 "v_eta",
-                                 "vol0",
-                                 "nhpres_xi",
-                                 "nhpres_vxi",
-                                 "fvir_prev",
-                                 "fep_state",
-                                 "MC-rng-unsupported",
-                                 "MC-rng-i-unsupported",
-                                 "barostat-integral" };
-
-enum
-{
-    eeksEKIN_N,
-    eeksEKINH,
-    eeksDEKINDL,
-    eeksMVCOS,
-    eeksEKINF,
-    eeksEKINO,
-    eeksEKINSCALEF,
-    eeksEKINSCALEH,
-    eeksVSCALE,
-    eeksEKINTOTAL,
-    eeksNR
+enum class StateKineticEntry : int
+{
+    EkinNumber,
+    EkinHalfStep,
+    DEkinDLambda,
+    Mvcos,
+    EkinFullStep,
+    EkinHalfStepOld,
+    EkinNoseHooverScaleFullStep,
+    EkinNoseHooverScaleHalfStep,
+    VelocityScale,
+    EkinTotal,
+    Count
 };
 
-static const char* eeks_names[eeksNR] = { "Ekin_n",         "Ekinh",          "dEkindlambda",
-                                          "mv_cos",         "Ekinf",          "Ekinh_old",
-                                          "EkinScaleF_NHC", "EkinScaleH_NHC", "Vscale_NHC",
-                                          "Ekin_Total" };
-
-enum
-{
-    eenhENERGY_N,
-    eenhENERGY_AVER,
-    eenhENERGY_SUM,
-    eenhENERGY_NSUM,
-    eenhENERGY_SUM_SIM,
-    eenhENERGY_NSUM_SIM,
-    eenhENERGY_NSTEPS,
-    eenhENERGY_NSTEPS_SIM,
-    eenhENERGY_DELTA_H_NN,
-    eenhENERGY_DELTA_H_LIST,
-    eenhENERGY_DELTA_H_STARTTIME,
-    eenhENERGY_DELTA_H_STARTLAMBDA,
-    eenhNR
+static const char* enumValueToString(StateKineticEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StateKineticEntry, const char*> stateKineticEntryNames = {
+        "Ekin_n",    "Ekinh",          "dEkindlambda",   "mv_cos",     "Ekinf",
+        "Ekinh_old", "EkinScaleF_NHC", "EkinScaleH_NHC", "Vscale_NHC", "Ekin_Total"
+    };
+    return stateKineticEntryNames[enumValue];
+}
+
+enum class StateEnergyEntry : int
+{
+    N,
+    Aver,
+    Sum,
+    NumSum,
+    SumSim,
+    NumSumSim,
+    NumSteps,
+    NumStepsSim,
+    DeltaHNN,
+    DeltaHList,
+    DeltaHStartTime,
+    DeltaHStartLambda,
+    Count
 };
 
-enum
+enum class StatePullEntry : int
 {
-    epullhPULL_NUMCOORDINATES,
-    epullhPULL_NUMGROUPS,
-    epullhPULL_NUMVALUESINXSUM,
-    epullhPULL_NUMVALUESINFSUM,
-    epullhNR
+    NumCoordinates,
+    NumGroups,
+    NumValuesInXSum,
+    NumValuesInFSum,
+    Count
 };
 
-enum
+enum class StatePullCoordEntry : int
 {
-    epullcoordh_VALUE_REF_SUM,
-    epullcoordh_VALUE_SUM,
-    epullcoordh_DR01_SUM,
-    epullcoordh_DR23_SUM,
-    epullcoordh_DR45_SUM,
-    epullcoordh_FSCAL_SUM,
-    epullcoordh_DYNAX_SUM,
-    epullcoordh_NR
+    ValueReferenceSum,
+    ValueSum,
+    DR01Sum,
+    DR23Sum,
+    DR45Sum,
+    FScalarSum,
+    DynaxSum,
+    Count
 };
 
-enum
+static const char* enumValueToString(StatePullCoordEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StatePullCoordEntry, const char*> statePullCoordEntryNames = {
+        "reference-sum", "sum", "dr01-sum", "dr23-sum", "dr45-sum", "fscal-sum", "dynax-sum"
+    };
+    return statePullCoordEntryNames[enumValue];
+}
+
+enum class StatePullGroupEntry : int
 {
-    epullgrouph_X_SUM,
-    epullgrouph_NR
+    XSum,
+    Count
 };
 
-static const char* eenh_names[eenhNR] = { "energy_n",
-                                          "energy_aver",
-                                          "energy_sum",
-                                          "energy_nsum",
-                                          "energy_sum_sim",
-                                          "energy_nsum_sim",
-                                          "energy_nsteps",
-                                          "energy_nsteps_sim",
-                                          "energy_delta_h_nn",
-                                          "energy_delta_h_list",
-                                          "energy_delta_h_start_time",
-                                          "energy_delta_h_start_lambda" };
-
-static const char* ePullhNames[epullhNR] = { "pullhistory_numcoordinates",
-                                             "pullhistory_numgroups",
-                                             "pullhistory_numvaluesinxsum",
-                                             "pullhistory_numvaluesinfsum" };
+static const char* enumValueToString(StatePullGroupEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StatePullGroupEntry, const char*> statePullGroupEntryNames = {
+        "coordinate-sum"
+    };
+    return statePullGroupEntryNames[enumValue];
+}
+
+static const char* enumValueToString(StateEnergyEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StateEnergyEntry, const char*> stateEnergyEntryNames = {
+        "energy_n",
+        "energy_aver",
+        "energy_sum",
+        "energy_nsum",
+        "energy_sum_sim",
+        "energy_nsum_sim",
+        "energy_nsteps",
+        "energy_nsteps_sim",
+        "energy_delta_h_nn",
+        "energy_delta_h_list",
+        "energy_delta_h_start_time",
+        "energy_delta_h_start_lambda"
+    };
+    return stateEnergyEntryNames[enumValue];
+}
+
+static const char* enumValueToString(StatePullEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StatePullEntry, const char*> statePullEntryNames = {
+        "pullhistory_numcoordinates",
+        "pullhistory_numgroups",
+        "pullhistory_numvaluesinxsum",
+        "pullhistory_numvaluesinfsum"
+    };
+    return statePullEntryNames[enumValue];
+}
 
 /* free energy history variables -- need to be preserved over checkpoint */
-enum
-{
-    edfhBEQUIL,
-    edfhNATLAMBDA,
-    edfhWLHISTO,
-    edfhWLDELTA,
-    edfhSUMWEIGHTS,
-    edfhSUMDG,
-    edfhSUMMINVAR,
-    edfhSUMVAR,
-    edfhACCUMP,
-    edfhACCUMM,
-    edfhACCUMP2,
-    edfhACCUMM2,
-    edfhTIJ,
-    edfhTIJEMP,
-    edfhNR
-};
-/* free energy history variable names  */
-static const char* edfh_names[edfhNR] = { "bEquilibrated",
-                                          "N_at_state",
-                                          "Wang-Landau Histogram",
-                                          "Wang-Landau Delta",
-                                          "Weights",
-                                          "Free Energies",
-                                          "minvar",
-                                          "variance",
-                                          "accumulated_plus",
-                                          "accumulated_minus",
-                                          "accumulated_plus_2",
-                                          "accumulated_minus_2",
-                                          "Tij",
-                                          "Tij_empirical" };
-
-/* AWH biasing history variables */
-enum
-{
-    eawhhIN_INITIAL,
-    eawhhEQUILIBRATEHISTOGRAM,
-    eawhhHISTSIZE,
-    eawhhNPOINTS,
-    eawhhCOORDPOINT,
-    eawhhUMBRELLAGRIDPOINT,
-    eawhhUPDATELIST,
-    eawhhLOGSCALEDSAMPLEWEIGHT,
-    eawhhNUMUPDATES,
-    eawhhFORCECORRELATIONGRID,
-    eawhhNR
+enum class StateFepEntry : int
+{
+    IsEquilibrated,
+    NumAtLambda,
+    WangLandauHistogram,
+    WangLandauDelta,
+    SumWeights,
+    SumDG,
+    SumMinVar,
+    SumVar,
+    Accump,
+    Accumm,
+    Accump2,
+    Accumm2,
+    Tij,
+    TijEmp,
+    Count
 };
 
-static const char* eawhh_names[eawhhNR] = { "awh_in_initial", "awh_equilibrateHistogram",
-                                            "awh_histsize",   "awh_npoints",
-                                            "awh_coordpoint", "awh_umbrellaGridpoint",
-                                            "awh_updatelist", "awh_logScaledSampleWeight",
-                                            "awh_numupdates", "awh_forceCorrelationGrid" };
+//! free energy history names
+static const char* enumValueToString(StateFepEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StateFepEntry, const char*> stateFepEntryNames = {
+        "bEquilibrated",
+        "N_at_state",
+        "Wang-Landau Histogram",
+        "Wang-Landau Delta",
+        "Weights",
+        "Free Energies",
+        "minvar",
+        "variance",
+        "accumulated_plus",
+        "accumulated_minus",
+        "accumulated_plus_2",
+        "accumulated_minus_2",
+        "Tij",
+        "Tij_empirical"
+    };
+    return stateFepEntryNames[enumValue];
+}
 
-enum
-{
-    epullsPREVSTEPCOM,
-    epullsNR
+//! AWH biasing history variables
+enum class StateAwhEntry : int
+{
+    InInitial,
+    EquilibrateHistogram,
+    HistogramSize,
+    NumPoints,
+    CoordPoint,
+    UmbrellaGridPoint,
+    UpdateList,
+    LogScaledSampleWeight,
+    NumUpdates,
+    ForceCorrelationGrid,
+    Count
 };
 
-static const char* epull_prev_step_com_names[epullsNR] = { "Pull groups prev step COM" };
+static const char* enumValueToString(StateAwhEntry enumValue)
+{
+    static constexpr gmx::EnumerationArray<StateAwhEntry, const char*> stateAwhEntryNames = {
+        "awh_in_initial", "awh_equilibrateHistogram", "awh_histsize",   "awh_npoints",
+        "awh_coordpoint", "awh_umbrellaGridpoint",    "awh_updatelist", "awh_logScaledSampleWeight",
+        "awh_numupdates", "awh_forceCorrelationGrid"
+    };
+    return stateAwhEntryNames[enumValue];
+}
 
+enum class StatePullCommunicationEntry : int
+{
+    PreviousStepCom,
+    Count
+};
 
 //! Higher level vector element type, only used for formatting checkpoint dumps
 enum class CptElementType
@@ -366,35 +412,6 @@ enum class CptElementType
     matrix3x3 //!< float[3][3] or double[3][3], not linked to precision of type real
 };
 
-//! \brief Parts of the checkpoint state, only used for reporting
-enum class StatePart
-{
-    microState,         //!< The microstate of the simulated system
-    kineticEnergy,      //!< Kinetic energy, needed for T/P-coupling state
-    energyHistory,      //!< Energy observable statistics
-    freeEnergyHistory,  //!< Free-energy state and observable statistics
-    accWeightHistogram, //!< Accelerated weight histogram method state
-    pullState,          //!< COM of previous step.
-    pullHistory         //!< Pull history statistics (sums since last written output)
-};
-
-//! \brief Return the name of a checkpoint entry based on part and part entry
-static const char* entryName(StatePart part, int ecpt)
-{
-    switch (part)
-    {
-        case StatePart::microState: return est_names[ecpt];
-        case StatePart::kineticEnergy: return eeks_names[ecpt];
-        case StatePart::energyHistory: return eenh_names[ecpt];
-        case StatePart::freeEnergyHistory: return edfh_names[ecpt];
-        case StatePart::accWeightHistogram: return eawhh_names[ecpt];
-        case StatePart::pullState: return epull_prev_step_com_names[ecpt];
-        case StatePart::pullHistory: return ePullhNames[ecpt];
-    }
-
-    return nullptr;
-}
-
 static void cp_warning(FILE* fp)
 {
     fprintf(fp, "\nWARNING: Checkpoint file is corrupted or truncated\n\n");
@@ -591,7 +608,8 @@ static inline xdrproc_t xdrProc(int xdrType)
  * The formatting of the printing is set by \p cptElementType.
  * When list==NULL only reads the elements.
  */
-static bool_t listXdrVector(XDR* xd, StatePart part, int ecpt, int nf, int xdrType, FILE* list, CptElementType cptElementType)
+template<typename Enum>
+static bool_t listXdrVector(XDR* xd, Enum ecpt, int nf, int xdrType, FILE* list, CptElementType cptElementType)
 {
     bool_t res = 0;
 
@@ -604,32 +622,32 @@ static bool_t listXdrVector(XDR* xd, StatePart part, int ecpt, int nf, int xdrTy
         switch (xdrType)
         {
             case xdr_datatype_int:
-                pr_ivec(list, 0, entryName(part, ecpt), reinterpret_cast<const int*>(data.data()), nf, TRUE);
+                pr_ivec(list, 0, enumValueToString(ecpt), reinterpret_cast<const int*>(data.data()), nf, TRUE);
                 break;
             case xdr_datatype_float:
 #if !GMX_DOUBLE
                 if (cptElementType == CptElementType::real3)
                 {
-                    pr_rvecs(list, 0, entryName(part, ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
+                    pr_rvecs(list, 0, enumValueToString(ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
                 }
                 else
 #endif
                 {
                     /* Note: With double precision code dumping a single precision rvec will produce float iso rvec print, but that's a minor annoyance */
-                    pr_fvec(list, 0, entryName(part, ecpt), reinterpret_cast<const float*>(data.data()), nf, TRUE);
+                    pr_fvec(list, 0, enumValueToString(ecpt), reinterpret_cast<const float*>(data.data()), nf, TRUE);
                 }
                 break;
             case xdr_datatype_double:
 #if GMX_DOUBLE
                 if (cptElementType == CptElementType::real3)
                 {
-                    pr_rvecs(list, 0, entryName(part, ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
+                    pr_rvecs(list, 0, enumValueToString(ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
                 }
                 else
 #endif
                 {
                     /* Note: With single precision code dumping a double precision rvec will produce float iso rvec print, but that's a minor annoyance */
-                    pr_dvec(list, 0, entryName(part, ecpt), reinterpret_cast<const double*>(data.data()), nf, TRUE);
+                    pr_dvec(list, 0, enumValueToString(ecpt), reinterpret_cast<const double*>(data.data()), nf, TRUE);
                 }
                 break;
             default: GMX_RELEASE_ASSERT(false, "Data type not implemented for listing");
@@ -685,10 +703,9 @@ static void convertArrayRealPrecision(const char gmx_unused* c, int gmx_unused*
  * If nval n<0, *nptr (with v) or vector->size() is used. On read using v,
  * the value is stored in nptr
  */
-template<typename T, typename AllocatorType>
+template<typename T, typename AllocatorType, typename Enum>
 static int doVectorLow(XDR*                           xd,
-                       StatePart                      part,
-                       int                            ecpt,
+                       Enum                           ecpt,
                        int                            sflags,
                        int                            nval,
                        int*                           nptr,
@@ -739,7 +756,7 @@ static int doVectorLow(XDR*                           xd,
         return -1;
     }
 
-    if (list == nullptr && (sflags & (1 << ecpt)))
+    if (list == nullptr && (sflags & enumValueToBitMask(ecpt)))
     {
         if (nval >= 0)
         {
@@ -747,7 +764,7 @@ static int doVectorLow(XDR*                           xd,
             {
                 gmx_fatal(FARGS,
                           "Count mismatch for state entry %s, code count is %d, file count is %d\n",
-                          entryName(part, ecpt),
+                          enumValueToString(ecpt),
                           nval,
                           numElemInTheFile);
             }
@@ -763,7 +780,7 @@ static int doVectorLow(XDR*                           xd,
             char buf[STRLEN];
             sprintf(buf,
                     "mismatch for state entry %s, code precision is %s, file precision is %s",
-                    entryName(part, ecpt),
+                    enumValueToString(ecpt),
                     xdr_datatype_names[xdrTypeInTheCode],
                     xdr_datatype_names[xdrTypeInTheFile]);
 
@@ -828,27 +845,27 @@ static int doVectorLow(XDR*                           xd,
     }
     else
     {
-        res = listXdrVector(xd, part, ecpt, numElemInTheFile, xdrTypeInTheFile, list, cptElementType);
+        res = listXdrVector(xd, ecpt, numElemInTheFile, xdrTypeInTheFile, list, cptElementType);
     }
 
     return 0;
 }
 
 //! \brief Read/Write a std::vector, on read checks the number of elements matches \p numElements, if specified.
-template<typename T>
-static int
-doVector(XDR* xd, StatePart part, int ecpt, int sflags, std::vector<T>* vector, FILE* list, int numElements = -1)
+template<typename T, typename Enum>
+static int doVector(XDR* xd, Enum ecpt, int sflags, std::vector<T>* vector, FILE* list, int numElements = -1)
 {
     return doVectorLow<T>(
-            xd, part, ecpt, sflags, numElements, nullptr, nullptr, vector, list, CptElementType::real);
+            xd, ecpt, sflags, numElements, nullptr, nullptr, vector, list, CptElementType::real);
 }
 
 //! \brief Read/Write an ArrayRef<real>.
-static int doRealArrayRef(XDR* xd, StatePart part, int ecpt, int sflags, gmx::ArrayRef<real> vector, FILE* list)
+template<typename Enum>
+static int doRealArrayRef(XDR* xd, Enum ecpt, int sflags, gmx::ArrayRef<real> vector, FILE* list)
 {
     real* v_real = vector.data();
     return doVectorLow<real, std::allocator<real>>(
-            xd, part, ecpt, sflags, vector.size(), nullptr, &v_real, nullptr, list, CptElementType::real);
+            xd, ecpt, sflags, vector.size(), nullptr, &v_real, nullptr, list, CptElementType::real);
 }
 
 //! Convert from view of RVec to view of real.
@@ -858,20 +875,19 @@ static gmx::ArrayRef<real> realArrayRefFromRVecArrayRef(gmx::ArrayRef<gmx::RVec>
 }
 
 //! \brief Read/Write a PaddedVector whose value_type is RVec.
-template<typename PaddedVectorOfRVecType>
-static int
-doRvecVector(XDR* xd, StatePart part, int ecpt, int sflags, PaddedVectorOfRVecType* v, int numAtoms, FILE* list)
+template<typename PaddedVectorOfRVecType, typename Enum>
+static int doRvecVector(XDR* xd, Enum ecpt, int sflags, PaddedVectorOfRVecType* v, int numAtoms, FILE* list)
 {
     const int numReals = numAtoms * DIM;
 
     if (list == nullptr)
     {
         GMX_RELEASE_ASSERT(
-                sflags & (1 << ecpt),
+                sflags & enumValueToBitMask(ecpt),
                 "When not listing, the flag for the entry should be set when requesting i/o");
         GMX_RELEASE_ASSERT(v->size() == numAtoms, "v should have sufficient size for numAtoms");
 
-        return doRealArrayRef(xd, part, ecpt, sflags, realArrayRefFromRVecArrayRef(makeArrayRef(*v)), list);
+        return doRealArrayRef(xd, ecpt, sflags, realArrayRefFromRVecArrayRef(makeArrayRef(*v)), list);
     }
     else
     {
@@ -880,7 +896,7 @@ doRvecVector(XDR* xd, StatePart part, int ecpt, int sflags, PaddedVectorOfRVecTy
         using realAllocator =
                 typename std::allocator_traits<typename PaddedVectorOfRVecType::allocator_type>::template rebind_alloc<real>;
         return doVectorLow<real, realAllocator>(
-                xd, part, ecpt, sflags, numReals, nullptr, nullptr, nullptr, list, CptElementType::real);
+                xd, ecpt, sflags, numReals, nullptr, nullptr, nullptr, list, CptElementType::real);
     }
 }
 
@@ -888,77 +904,86 @@ doRvecVector(XDR* xd, StatePart part, int ecpt, int sflags, PaddedVectorOfRVecTy
  * but on reading it assumes that n matches the value in the checkpoint file,
  * a fatal error is generated when this is not the case.
  */
-static int do_cpte_reals(XDR* xd, StatePart part, int ecpt, int sflags, int n, real** v, FILE* list)
+template<typename Enum>
+static int do_cpte_reals(XDR* xd, Enum ecpt, int sflags, int n, real** v, FILE* list)
 {
     return doVectorLow<real, std::allocator<real>>(
-            xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
+            xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
 }
 
 /* This function does the same as do_cpte_reals,
  * except that on reading it ignores the passed value of *n
  * and stores the value read from the checkpoint file in *n.
  */
-static int do_cpte_n_reals(XDR* xd, StatePart part, int ecpt, int sflags, int* n, real** v, FILE* list)
+template<typename Enum>
+static int do_cpte_n_reals(XDR* xd, Enum ecpt, int sflags, int* n, real** v, FILE* list)
 {
     return doVectorLow<real, std::allocator<real>>(
-            xd, part, ecpt, sflags, -1, n, v, nullptr, list, CptElementType::real);
+            xd, ecpt, sflags, -1, n, v, nullptr, list, CptElementType::real);
 }
 
-static int do_cpte_real(XDR* xd, StatePart part, int ecpt, int sflags, real* r, FILE* list)
+template<typename Enum>
+static int do_cpte_real(XDR* xd, Enum ecpt, int sflags, real* r, FILE* list)
 {
     return doVectorLow<real, std::allocator<real>>(
-            xd, part, ecpt, sflags, 1, nullptr, &r, nullptr, list, CptElementType::real);
+            xd, ecpt, sflags, 1, nullptr, &r, nullptr, list, CptElementType::real);
 }
 
-static int do_cpte_ints(XDR* xd, StatePart part, int ecpt, int sflags, int n, int** v, FILE* list)
+template<typename Enum>
+static int do_cpte_ints(XDR* xd, Enum ecpt, int sflags, int n, int** v, FILE* list)
 {
     return doVectorLow<int, std::allocator<int>>(
-            xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::integer);
+            xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::integer);
 }
 
-static int do_cpte_int(XDR* xd, StatePart part, int ecpt, int sflags, int* i, FILE* list)
+template<typename Enum>
+static int do_cpte_int(XDR* xd, Enum ecpt, int sflags, int* i, FILE* list)
 {
-    return do_cpte_ints(xd, part, ecpt, sflags, 1, &i, list);
+    return do_cpte_ints(xd, ecpt, sflags, 1, &i, list);
 }
 
-static int do_cpte_bool(XDR* xd, StatePart part, int ecpt, int sflags, bool* b, FILE* list)
+template<typename Enum>
+static int do_cpte_bool(XDR* xd, Enum ecpt, int sflags, bool* b, FILE* list)
 {
     int i   = static_cast<int>(*b);
-    int ret = do_cpte_int(xd, part, ecpt, sflags, &i, list);
+    int ret = do_cpte_int(xd, ecpt, sflags, &i, list);
     *b      = (i != 0);
     return ret;
 }
 
-static int do_cpte_doubles(XDR* xd, StatePart part, int ecpt, int sflags, int n, double** v, FILE* list)
+template<typename Enum>
+static int do_cpte_doubles(XDR* xd, Enum ecpt, int sflags, int n, double** v, FILE* list)
 {
     return doVectorLow<double, std::allocator<double>>(
-            xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
+            xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
 }
 
-static int do_cpte_double(XDR* xd, StatePart part, int ecpt, int sflags, double* r, FILE* list)
+template<typename Enum>
+static int do_cpte_double(XDR* xd, Enum ecpt, int sflags, double* r, FILE* list)
 {
-    return do_cpte_doubles(xd, part, ecpt, sflags, 1, &r, list);
+    return do_cpte_doubles(xd, ecpt, sflags, 1, &r, list);
 }
 
-static int do_cpte_matrix(XDR* xd, StatePart part, int ecpt, int sflags, matrix v, FILE* list)
+template<typename Enum>
+static int do_cpte_matrix(XDR* xd, Enum ecpt, int sflags, matrix v, FILE* list)
 {
     real* vr;
     int   ret;
 
     vr  = &(v[0][0]);
     ret = doVectorLow<real, std::allocator<real>>(
-            xd, part, ecpt, sflags, DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
+            xd, ecpt, sflags, DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
 
     if (list && ret == 0)
     {
-        pr_rvecs(list, 0, entryName(part, ecpt), v, DIM);
+        pr_rvecs(list, 0, enumValueToString(ecpt), v, DIM);
     }
 
     return ret;
 }
 
-
-static int do_cpte_nmatrix(XDR* xd, StatePart part, int ecpt, int sflags, int n, real** v, FILE* list)
+template<typename Enum>
+static int do_cpte_nmatrix(XDR* xd, Enum ecpt, int sflags, int n, real** v, FILE* list)
 {
     int  i;
     int  ret, reti;
@@ -972,10 +997,10 @@ static int do_cpte_nmatrix(XDR* xd, StatePart part, int ecpt, int sflags, int n,
     for (i = 0; i < n; i++)
     {
         reti = doVectorLow<real, std::allocator<real>>(
-                xd, part, ecpt, sflags, n, nullptr, &(v[i]), nullptr, nullptr, CptElementType::matrix3x3);
+                xd, ecpt, sflags, n, nullptr, &(v[i]), nullptr, nullptr, CptElementType::matrix3x3);
         if (list && reti == 0)
         {
-            sprintf(name, "%s[%d]", entryName(part, ecpt), i);
+            sprintf(name, "%s[%d]", enumValueToString(ecpt), i);
             pr_reals(list, 0, name, v[i], n);
         }
         if (reti != 0)
@@ -986,7 +1011,8 @@ static int do_cpte_nmatrix(XDR* xd, StatePart part, int ecpt, int sflags, int n,
     return ret;
 }
 
-static int do_cpte_matrices(XDR* xd, StatePart part, int ecpt, int sflags, int n, matrix** v, FILE* list)
+template<typename Enum>
+static int do_cpte_matrices(XDR* xd, Enum ecpt, int sflags, int n, matrix** v, FILE* list)
 {
     bool_t  res = 0;
     matrix *vp, *va = nullptr;
@@ -1004,11 +1030,11 @@ static int do_cpte_matrices(XDR* xd, StatePart part, int ecpt, int sflags, int n
     {
         gmx_fatal(FARGS,
                   "Count mismatch for state entry %s, code count is %d, file count is %d\n",
-                  entryName(part, ecpt),
+                  enumValueToString(ecpt),
                   n,
                   nf);
     }
-    if (list || !(sflags & (1 << ecpt)))
+    if (list || !(sflags & enumValueToBitMask(ecpt)))
     {
         snew(va, nf);
         vp = va;
@@ -1033,7 +1059,7 @@ static int do_cpte_matrices(XDR* xd, StatePart part, int ecpt, int sflags, int n
         }
     }
     ret = doVectorLow<real, std::allocator<real>>(
-            xd, part, ecpt, sflags, nf * DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
+            xd, ecpt, sflags, nf * DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
     for (i = 0; i < nf; i++)
     {
         for (j = 0; j < DIM; j++)
@@ -1050,7 +1076,7 @@ static int do_cpte_matrices(XDR* xd, StatePart part, int ecpt, int sflags, int n
     {
         for (i = 0; i < nf; i++)
         {
-            pr_rvecs(list, 0, entryName(part, ecpt), vp[i], DIM);
+            pr_rvecs(list, 0, enumValueToString(ecpt), vp[i], DIM);
         }
     }
     if (va)
@@ -1192,11 +1218,12 @@ static void do_cpt_header(XDR* xd, gmx_bool bRead, FILE* list, CheckpointHeaderC
     }
     else
     {
-        contents->flags_eks   = 0;
-        contents->flags_enh   = (contents->flags_state >> (estORIRE_DTAV + 1));
+        contents->flags_eks = 0;
+        contents->flags_enh = (contents->flags_state >> (static_cast<int>(StateEntry::OrireDtav) + 1));
         contents->flags_state = (contents->flags_state
-                                 & ~((1 << (estORIRE_DTAV + 1)) | (1 << (estORIRE_DTAV + 2))
-                                     | (1 << (estORIRE_DTAV + 3))));
+                                 & ~((1 << (static_cast<int>(StateEntry::OrireDtav) + 1))
+                                     | (1 << (static_cast<int>(StateEntry::OrireDtav) + 2))
+                                     | (1 << (static_cast<int>(StateEntry::OrireDtav) + 3))));
     }
     if (contents->file_version >= 14)
     {
@@ -1283,106 +1310,111 @@ static int do_cpt_footer(XDR* xd, int file_version)
 
 static int do_cpt_state(XDR* xd, int fflags, t_state* state, FILE* list)
 {
-    int             ret    = 0;
-    const StatePart part   = StatePart::microState;
-    const int       sflags = state->flags;
+    int       ret    = 0;
+    const int sflags = state->flags;
     // If reading, state->natoms was probably just read, so
     // allocations need to be managed. If writing, this won't change
     // anything that matters.
+    using StateFlags = gmx::EnumerationArray<StateEntry, bool>;
     state_change_natoms(state, state->natoms);
-    for (int i = 0; (i < estNR && ret == 0); i++)
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        if (fflags & (1 << i))
+        if (fflags & enumValueToBitMask(*i))
         {
-            switch (i)
+            switch (*i)
             {
-                case estLAMBDA:
+                case StateEntry::Lambda:
                     ret = doRealArrayRef(
                             xd,
-                            part,
-                            i,
+                            *i,
                             sflags,
                             gmx::arrayRefFromArray<real>(
                                     state->lambda.data(),
                                     gmx::EnumerationArray<FreeEnergyPerturbationCouplingType, real>::size()),
                             list);
                     break;
-                case estFEPSTATE:
-                    ret = do_cpte_int(xd, part, i, sflags, &state->fep_state, list);
+                case StateEntry::FepState:
+                    ret = do_cpte_int(xd, *i, sflags, &state->fep_state, list);
+                    break;
+                case StateEntry::Box: ret = do_cpte_matrix(xd, *i, sflags, state->box, list); break;
+                case StateEntry::BoxRel:
+                    ret = do_cpte_matrix(xd, *i, sflags, state->box_rel, list);
                     break;
-                case estBOX: ret = do_cpte_matrix(xd, part, i, sflags, state->box, list); break;
-                case estBOX_REL:
-                    ret = do_cpte_matrix(xd, part, i, sflags, state->box_rel, list);
+                case StateEntry::BoxV:
+                    ret = do_cpte_matrix(xd, *i, sflags, state->boxv, list);
                     break;
-                case estBOXV: ret = do_cpte_matrix(xd, part, i, sflags, state->boxv, list); break;
-                case estPRES_PREV:
-                    ret = do_cpte_matrix(xd, part, i, sflags, state->pres_prev, list);
+                case StateEntry::PressurePrevious:
+                    ret = do_cpte_matrix(xd, *i, sflags, state->pres_prev, list);
                     break;
-                case estSVIR_PREV:
-                    ret = do_cpte_matrix(xd, part, i, sflags, state->svir_prev, list);
+                case StateEntry::SVirPrev:
+                    ret = do_cpte_matrix(xd, *i, sflags, state->svir_prev, list);
                     break;
-                case estFVIR_PREV:
-                    ret = do_cpte_matrix(xd, part, i, sflags, state->fvir_prev, list);
+                case StateEntry::FVirPrev:
+                    ret = do_cpte_matrix(xd, *i, sflags, state->fvir_prev, list);
                     break;
-                case estNH_XI:
-                    ret = doVector<double>(xd, part, i, sflags, &state->nosehoover_xi, list);
+                case StateEntry::Nhxi:
+                    ret = doVector<double>(xd, *i, sflags, &state->nosehoover_xi, list);
                     break;
-                case estNH_VXI:
-                    ret = doVector<double>(xd, part, i, sflags, &state->nosehoover_vxi, list);
+                case StateEntry::Nhvxi:
+                    ret = doVector<double>(xd, *i, sflags, &state->nosehoover_vxi, list);
                     break;
-                case estNHPRES_XI:
-                    ret = doVector<double>(xd, part, i, sflags, &state->nhpres_xi, list);
+                case StateEntry::Nhpresxi:
+                    ret = doVector<double>(xd, *i, sflags, &state->nhpres_xi, list);
                     break;
-                case estNHPRES_VXI:
-                    ret = doVector<double>(xd, part, i, sflags, &state->nhpres_vxi, list);
+                case StateEntry::Nhpresvxi:
+                    ret = doVector<double>(xd, *i, sflags, &state->nhpres_vxi, list);
                     break;
-                case estTHERM_INT:
-                    ret = doVector<double>(xd, part, i, sflags, &state->therm_integral, list);
+                case StateEntry::ThermInt:
+                    ret = doVector<double>(xd, *i, sflags, &state->therm_integral, list);
                     break;
-                case estBAROS_INT:
-                    ret = do_cpte_double(xd, part, i, sflags, &state->baros_integral, list);
+                case StateEntry::BarosInt:
+                    ret = do_cpte_double(xd, *i, sflags, &state->baros_integral, list);
                     break;
-                case estVETA: ret = do_cpte_real(xd, part, i, sflags, &state->veta, list); break;
-                case estVOL0: ret = do_cpte_real(xd, part, i, sflags, &state->vol0, list); break;
-                case estX:
-                    ret = doRvecVector(xd, part, i, sflags, &state->x, state->natoms, list);
+                case StateEntry::Veta:
+                    ret = do_cpte_real(xd, *i, sflags, &state->veta, list);
                     break;
-                case estV:
-                    ret = doRvecVector(xd, part, i, sflags, &state->v, state->natoms, list);
+                case StateEntry::Vol0:
+                    ret = do_cpte_real(xd, *i, sflags, &state->vol0, list);
+                    break;
+                case StateEntry::X:
+                    ret = doRvecVector(xd, *i, sflags, &state->x, state->natoms, list);
+                    break;
+                case StateEntry::V:
+                    ret = doRvecVector(xd, *i, sflags, &state->v, state->natoms, list);
                     break;
                 /* The RNG entries are no longer written,
                  * the next 4 lines are only for reading old files.
                  * It's OK that three case statements fall through.
                  */
-                case estLD_RNG_NOTSUPPORTED:
-                case estLD_RNGI_NOTSUPPORTED:
-                case estMC_RNG_NOTSUPPORTED:
-                case estMC_RNGI_NOTSUPPORTED:
-                    ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list);
+                case StateEntry::LDRngNotSupported:
+                case StateEntry::LDRngINotSupported:
+                case StateEntry::MCRngNotSupported:
+                case StateEntry::MCRngINotSupported:
+                    ret = do_cpte_ints(xd, *i, sflags, 0, nullptr, list);
                     break;
-                case estDISRE_INITF:
-                    ret = do_cpte_real(xd, part, i, sflags, &state->hist.disre_initf, list);
+                case StateEntry::DisreInitF:
+                    ret = do_cpte_real(xd, *i, sflags, &state->hist.disre_initf, list);
                     break;
-                case estDISRE_RM3TAV:
+                case StateEntry::DisreRm3Tav:
                     ret = do_cpte_n_reals(
-                            xd, part, i, sflags, &state->hist.ndisrepairs, &state->hist.disre_rm3tav, list);
+                            xd, *i, sflags, &state->hist.ndisrepairs, &state->hist.disre_rm3tav, list);
                     break;
-                case estORIRE_INITF:
-                    ret = do_cpte_real(xd, part, i, sflags, &state->hist.orire_initf, list);
+                case StateEntry::OrireInitF:
+                    ret = do_cpte_real(xd, *i, sflags, &state->hist.orire_initf, list);
                     break;
-                case estORIRE_DTAV:
+                case StateEntry::OrireDtav:
                     ret = do_cpte_n_reals(
-                            xd, part, i, sflags, &state->hist.norire_Dtav, &state->hist.orire_Dtav, list);
+                            xd, *i, sflags, &state->hist.norire_Dtav, &state->hist.orire_Dtav, list);
                     break;
-                case estPULLCOMPREVSTEP:
-                    ret = doVector<double>(xd, part, i, sflags, &state->pull_com_prev_step, list);
+                case StateEntry::PullComPrevStep:
+                    ret = doVector<double>(xd, *i, sflags, &state->pull_com_prev_step, list);
                     break;
                 default:
                     gmx_fatal(FARGS,
                               "Unknown state entry %d\n"
                               "You are reading a checkpoint file written by different code, which "
                               "is not supported",
-                              i);
+                              enumValueToBitMask(*i));
             }
         }
     }
@@ -1393,47 +1425,49 @@ static int do_cpt_ekinstate(XDR* xd, int fflags, ekinstate_t* ekins, FILE* list)
 {
     int ret = 0;
 
-    const StatePart part = StatePart::kineticEnergy;
-    for (int i = 0; (i < eeksNR && ret == 0); i++)
+    using StateFlags = gmx::EnumerationArray<StateKineticEntry, bool>;
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        if (fflags & (1 << i))
+        if (fflags & enumValueToBitMask(*i))
         {
-            switch (i)
+            switch (*i)
             {
 
-                case eeksEKIN_N:
-                    ret = do_cpte_int(xd, part, i, fflags, &ekins->ekin_n, list);
+                case StateKineticEntry::EkinNumber:
+                    ret = do_cpte_int(xd, *i, fflags, &ekins->ekin_n, list);
                     break;
-                case eeksEKINH:
-                    ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinh, list);
+                case StateKineticEntry::EkinHalfStep:
+                    ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinh, list);
                     break;
-                case eeksEKINF:
-                    ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinf, list);
+                case StateKineticEntry::EkinFullStep:
+                    ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinf, list);
                     break;
-                case eeksEKINO:
-                    ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinh_old, list);
+                case StateKineticEntry::EkinHalfStepOld:
+                    ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinh_old, list);
                     break;
-                case eeksEKINTOTAL:
-                    ret = do_cpte_matrix(xd, part, i, fflags, ekins->ekin_total, list);
+                case StateKineticEntry::EkinTotal:
+                    ret = do_cpte_matrix(xd, *i, fflags, ekins->ekin_total, list);
                     break;
-                case eeksEKINSCALEF:
-                    ret = doVector<double>(xd, part, i, fflags, &ekins->ekinscalef_nhc, list);
+                case StateKineticEntry::EkinNoseHooverScaleFullStep:
+                    ret = doVector<double>(xd, *i, fflags, &ekins->ekinscalef_nhc, list);
                     break;
-                case eeksVSCALE:
-                    ret = doVector<double>(xd, part, i, fflags, &ekins->vscale_nhc, list);
+                case StateKineticEntry::VelocityScale:
+                    ret = doVector<double>(xd, *i, fflags, &ekins->vscale_nhc, list);
                     break;
-                case eeksEKINSCALEH:
-                    ret = doVector<double>(xd, part, i, fflags, &ekins->ekinscaleh_nhc, list);
+                case StateKineticEntry::EkinNoseHooverScaleHalfStep:
+                    ret = doVector<double>(xd, *i, fflags, &ekins->ekinscaleh_nhc, list);
                     break;
-                case eeksDEKINDL:
-                    ret = do_cpte_real(xd, part, i, fflags, &ekins->dekindl, list);
+                case StateKineticEntry::DEkinDLambda:
+                    ret = do_cpte_real(xd, *i, fflags, &ekins->dekindl, list);
+                    break;
+                case StateKineticEntry::Mvcos:
+                    ret = do_cpte_real(xd, *i, fflags, &ekins->mvcos, list);
                     break;
-                case eeksMVCOS: ret = do_cpte_real(xd, part, i, fflags, &ekins->mvcos, list); break;
                 default:
                     gmx_fatal(FARGS,
                               "Unknown ekin data state entry %d\n"
                               "You are probably reading a new checkpoint file with old code",
-                              i);
+                              enumValueToBitMask(*i));
             }
         }
     }
@@ -1609,45 +1643,45 @@ static int do_cpt_enerhist(XDR* xd, gmx_bool bRead, int fflags, energyhistory_t*
     }
 
     delta_h_history_t* deltaH = enerhist->deltaHForeignLambdas.get();
-    const StatePart    part   = StatePart::energyHistory;
-    for (int i = 0; (i < eenhNR && ret == 0); i++)
+    using StateFlags          = gmx::EnumerationArray<StateEnergyEntry, bool>;
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        if (fflags & (1 << i))
+        if (fflags & enumValueToBitMask(*i))
         {
-            switch (i)
+            switch (*i)
             {
-                case eenhENERGY_N:
-                    ret = do_cpte_int(xd, part, i, fflags, &energyHistoryNumEnergies, list);
+                case StateEnergyEntry::N:
+                    ret = do_cpte_int(xd, *i, fflags, &energyHistoryNumEnergies, list);
                     break;
-                case eenhENERGY_AVER:
-                    ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_ave, list);
+                case StateEnergyEntry::Aver:
+                    ret = doVector<double>(xd, *i, fflags, &enerhist->ener_ave, list);
                     break;
-                case eenhENERGY_SUM:
-                    ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_sum, list);
+                case StateEnergyEntry::Sum:
+                    ret = doVector<double>(xd, *i, fflags, &enerhist->ener_sum, list);
                     break;
-                case eenhENERGY_NSUM:
-                    do_cpt_step_err(xd, eenh_names[i], &enerhist->nsum, list);
+                case StateEnergyEntry::NumSum:
+                    do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsum, list);
                     break;
-                case eenhENERGY_SUM_SIM:
-                    ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_sum_sim, list);
+                case StateEnergyEntry::SumSim:
+                    ret = doVector<double>(xd, *i, fflags, &enerhist->ener_sum_sim, list);
                     break;
-                case eenhENERGY_NSUM_SIM:
-                    do_cpt_step_err(xd, eenh_names[i], &enerhist->nsum_sim, list);
+                case StateEnergyEntry::NumSumSim:
+                    do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsum_sim, list);
                     break;
-                case eenhENERGY_NSTEPS:
-                    do_cpt_step_err(xd, eenh_names[i], &enerhist->nsteps, list);
+                case StateEnergyEntry::NumSteps:
+                    do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsteps, list);
                     break;
-                case eenhENERGY_NSTEPS_SIM:
-                    do_cpt_step_err(xd, eenh_names[i], &enerhist->nsteps_sim, list);
+                case StateEnergyEntry::NumStepsSim:
+                    do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsteps_sim, list);
                     break;
-                case eenhENERGY_DELTA_H_NN:
+                case StateEnergyEntry::DeltaHNN:
                 {
                     int numDeltaH = 0;
                     if (!bRead && deltaH != nullptr)
                     {
                         numDeltaH = deltaH->dh.size();
                     }
-                    do_cpt_int_err(xd, eenh_names[i], &numDeltaH, list);
+                    do_cpt_int_err(xd, enumValueToString(*i), &numDeltaH, list);
                     if (bRead)
                     {
                         if (deltaH == nullptr)
@@ -1660,39 +1694,42 @@ static int do_cpt_enerhist(XDR* xd, gmx_bool bRead, int fflags, energyhistory_t*
                     }
                     break;
                 }
-                case eenhENERGY_DELTA_H_LIST:
+                case StateEnergyEntry::DeltaHList:
                     for (auto dh : deltaH->dh)
                     {
-                        ret = doVector<real>(xd, part, i, fflags, &dh, list);
+                        ret = doVector<real>(xd, *i, fflags, &dh, list);
                     }
                     break;
-                case eenhENERGY_DELTA_H_STARTTIME:
-                    ret = do_cpte_double(xd, part, i, fflags, &(deltaH->start_time), list);
+                case StateEnergyEntry::DeltaHStartTime:
+                    ret = do_cpte_double(xd, *i, fflags, &(deltaH->start_time), list);
                     break;
-                case eenhENERGY_DELTA_H_STARTLAMBDA:
-                    ret = do_cpte_double(xd, part, i, fflags, &(deltaH->start_lambda), list);
+                case StateEnergyEntry::DeltaHStartLambda:
+                    ret = do_cpte_double(xd, *i, fflags, &(deltaH->start_lambda), list);
                     break;
                 default:
                     gmx_fatal(FARGS,
                               "Unknown energy history entry %d\n"
                               "You are probably reading a new checkpoint file with old code",
-                              i);
+                              enumValueToBitMask(*i));
             }
         }
     }
 
-    if ((fflags & (1 << eenhENERGY_SUM)) && !(fflags & (1 << eenhENERGY_SUM_SIM)))
+    if ((fflags & enumValueToBitMask(StateEnergyEntry::Sum))
+        && !(fflags & enumValueToBitMask(StateEnergyEntry::SumSim)))
     {
         /* Assume we have an old file format and copy sum to sum_sim */
         enerhist->ener_sum_sim = enerhist->ener_sum;
     }
 
-    if ((fflags & (1 << eenhENERGY_NSUM)) && !(fflags & (1 << eenhENERGY_NSTEPS)))
+    if ((fflags & enumValueToBitMask(StateEnergyEntry::NumSum))
+        && !(fflags & enumValueToBitMask(StateEnergyEntry::NumSteps)))
     {
         /* Assume we have an old file format and copy nsum to nsteps */
         enerhist->nsteps = enerhist->nsum;
     }
-    if ((fflags & (1 << eenhENERGY_NSUM_SIM)) && !(fflags & (1 << eenhENERGY_NSTEPS_SIM)))
+    if ((fflags & enumValueToBitMask(StateEnergyEntry::NumSumSim))
+        && !(fflags & enumValueToBitMask(StateEnergyEntry::NumStepsSim)))
     {
         /* Assume we have an old file format and copy nsum to nsteps */
         enerhist->nsteps_sim = enerhist->nsum_sim;
@@ -1701,75 +1738,83 @@ static int do_cpt_enerhist(XDR* xd, gmx_bool bRead, int fflags, energyhistory_t*
     return ret;
 }
 
-static int doCptPullCoordHist(XDR* xd, PullCoordinateHistory* pullCoordHist, const StatePart part, FILE* list)
+static int doCptPullCoordHist(XDR* xd, PullCoordinateHistory* pullCoordHist, FILE* list)
 {
     int ret   = 0;
     int flags = 0;
 
-    flags |= ((1 << epullcoordh_VALUE_REF_SUM) | (1 << epullcoordh_VALUE_SUM)
-              | (1 << epullcoordh_DR01_SUM) | (1 << epullcoordh_DR23_SUM)
-              | (1 << epullcoordh_DR45_SUM) | (1 << epullcoordh_FSCAL_SUM));
+    flags |= (enumValueToBitMask(StatePullCoordEntry::ValueReferenceSum)
+              | enumValueToBitMask(StatePullCoordEntry::ValueSum)
+              | enumValueToBitMask(StatePullCoordEntry::DR01Sum)
+              | enumValueToBitMask(StatePullCoordEntry::DR23Sum)
+              | enumValueToBitMask(StatePullCoordEntry::DR45Sum)
+              | enumValueToBitMask(StatePullCoordEntry::FScalarSum));
 
-    for (int i = 0; i < epullcoordh_NR && ret == 0; i++)
+    using StateFlags = gmx::EnumerationArray<StatePullCoordEntry, bool>;
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        switch (i)
+        switch (*i)
         {
-            case epullcoordh_VALUE_REF_SUM:
-                ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->valueRef), list);
+            case StatePullCoordEntry::ValueReferenceSum:
+                ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->valueRef), list);
                 break;
-            case epullcoordh_VALUE_SUM:
-                ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->value), list);
+            case StatePullCoordEntry::ValueSum:
+                ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->value), list);
                 break;
-            case epullcoordh_DR01_SUM:
+            case StatePullCoordEntry::DR01Sum:
                 for (int j = 0; j < DIM && ret == 0; j++)
                 {
-                    ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dr01[j]), list);
+                    ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr01[j]), list);
                 }
                 break;
-            case epullcoordh_DR23_SUM:
+            case StatePullCoordEntry::DR23Sum:
                 for (int j = 0; j < DIM && ret == 0; j++)
                 {
-                    ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dr23[j]), list);
+                    ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr23[j]), list);
                 }
                 break;
-            case epullcoordh_DR45_SUM:
+            case StatePullCoordEntry::DR45Sum:
                 for (int j = 0; j < DIM && ret == 0; j++)
                 {
-                    ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dr45[j]), list);
+                    ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr45[j]), list);
                 }
                 break;
-            case epullcoordh_FSCAL_SUM:
-                ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->scalarForce), list);
+            case StatePullCoordEntry::FScalarSum:
+                ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->scalarForce), list);
                 break;
-            case epullcoordh_DYNAX_SUM:
+            case StatePullCoordEntry::DynaxSum:
                 for (int j = 0; j < DIM && ret == 0; j++)
                 {
-                    ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dynaX[j]), list);
+                    ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dynaX[j]), list);
                 }
                 break;
+            default:
+                gmx_fatal(FARGS, "Unhandled StatePullCoordEntry enum value: %d", enumValueToBitMask(*i));
         }
     }
 
     return ret;
 }
 
-static int doCptPullGroupHist(XDR* xd, PullGroupHistory* pullGroupHist, const StatePart part, FILE* list)
+static int doCptPullGroupHist(XDR* xd, PullGroupHistory* pullGroupHist, FILE* list)
 {
     int ret   = 0;
     int flags = 0;
 
-    flags |= ((1 << epullgrouph_X_SUM));
+    flags |= (enumValueToBitMask(StatePullGroupEntry::XSum));
 
-    for (int i = 0; i < epullgrouph_NR; i++)
+    using StateFlags = gmx::EnumerationArray<StatePullGroupEntry, bool>;
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        switch (i)
+        switch (*i)
         {
-            case epullgrouph_X_SUM:
+            case StatePullGroupEntry::XSum:
                 for (int j = 0; j < DIM && ret == 0; j++)
                 {
-                    ret = do_cpte_double(xd, part, i, flags, &(pullGroupHist->x[j]), list);
+                    ret = do_cpte_double(xd, *i, flags, &(pullGroupHist->x[j]), list);
                 }
                 break;
+            default: gmx_fatal(FARGS, "Unhandled pull group state entry");
         }
     }
 
@@ -1777,7 +1822,7 @@ static int doCptPullGroupHist(XDR* xd, PullGroupHistory* pullGroupHist, const St
 }
 
 
-static int doCptPullHist(XDR* xd, gmx_bool bRead, int fflags, PullHistory* pullHist, const StatePart part, FILE* list)
+static int doCptPullHist(XDR* xd, gmx_bool bRead, int fflags, PullHistory* pullHist, FILE* list)
 {
     int ret                       = 0;
     int pullHistoryNumCoordinates = 0;
@@ -1801,29 +1846,30 @@ static int doCptPullHist(XDR* xd, gmx_bool bRead, int fflags, PullHistory* pullH
         GMX_RELEASE_ASSERT(fflags == 0, "Without pull history, all flags should be off");
     }
 
-    for (int i = 0; (i < epullhNR && ret == 0); i++)
+    using StateFlags = gmx::EnumerationArray<StatePullEntry, bool>;
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        if (fflags & (1 << i))
+        if (fflags & (1 << enumValueToBitMask(*i)))
         {
-            switch (i)
+            switch (*i)
             {
-                case epullhPULL_NUMCOORDINATES:
-                    ret = do_cpte_int(xd, part, i, fflags, &pullHistoryNumCoordinates, list);
+                case StatePullEntry::NumCoordinates:
+                    ret = do_cpte_int(xd, *i, fflags, &pullHistoryNumCoordinates, list);
                     break;
-                case epullhPULL_NUMGROUPS:
-                    do_cpt_int_err(xd, eenh_names[i], &pullHistoryNumGroups, list);
+                case StatePullEntry::NumGroups:
+                    do_cpt_int_err(xd, enumValueToString(*i), &pullHistoryNumGroups, list);
                     break;
-                case epullhPULL_NUMVALUESINXSUM:
-                    do_cpt_int_err(xd, eenh_names[i], &pullHist->numValuesInXSum, list);
+                case StatePullEntry::NumValuesInXSum:
+                    do_cpt_int_err(xd, enumValueToString(*i), &pullHist->numValuesInXSum, list);
                     break;
-                case epullhPULL_NUMVALUESINFSUM:
-                    do_cpt_int_err(xd, eenh_names[i], &pullHist->numValuesInFSum, list);
+                case StatePullEntry::NumValuesInFSum:
+                    do_cpt_int_err(xd, enumValueToString(*i), &pullHist->numValuesInFSum, list);
                     break;
                 default:
                     gmx_fatal(FARGS,
                               "Unknown pull history entry %d\n"
                               "You are probably reading a new checkpoint file with old code",
-                              i);
+                              enumValueToBitMask(*i));
             }
         }
     }
@@ -1836,11 +1882,11 @@ static int doCptPullHist(XDR* xd, gmx_bool bRead, int fflags, PullHistory* pullH
     {
         for (size_t i = 0; i < pullHist->pullCoordinateSums.size() && ret == 0; i++)
         {
-            ret = doCptPullCoordHist(xd, &(pullHist->pullCoordinateSums[i]), part, list);
+            ret = doCptPullCoordHist(xd, &(pullHist->pullCoordinateSums[i]), list);
         }
         for (size_t i = 0; i < pullHist->pullGroupSums.size() && ret == 0; i++)
         {
-            ret = doCptPullGroupHist(xd, &(pullHist->pullGroupSums[i]), part, list);
+            ret = doCptPullGroupHist(xd, &(pullHist->pullGroupSums[i]), list);
         }
     }
 
@@ -1864,61 +1910,61 @@ static int do_cpt_df_hist(XDR* xd, int fflags, int nlambda, df_history_t** dfhis
     }
     df_history_t* dfhist = *dfhistPtr;
 
-    const StatePart part = StatePart::freeEnergyHistory;
-    for (int i = 0; (i < edfhNR && ret == 0); i++)
+    using StateFlags = gmx::EnumerationArray<StateFepEntry, bool>;
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        if (fflags & (1 << i))
+        if (fflags & enumValueToBitMask(*i))
         {
-            switch (i)
+            switch (*i)
             {
-                case edfhBEQUIL:
-                    ret = do_cpte_bool(xd, part, i, fflags, &dfhist->bEquil, list);
+                case StateFepEntry::IsEquilibrated:
+                    ret = do_cpte_bool(xd, *i, fflags, &dfhist->bEquil, list);
                     break;
-                case edfhNATLAMBDA:
-                    ret = do_cpte_ints(xd, part, i, fflags, nlambda, &dfhist->n_at_lam, list);
+                case StateFepEntry::NumAtLambda:
+                    ret = do_cpte_ints(xd, *i, fflags, nlambda, &dfhist->n_at_lam, list);
                     break;
-                case edfhWLHISTO:
-                    ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->wl_histo, list);
+                case StateFepEntry::WangLandauHistogram:
+                    ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->wl_histo, list);
                     break;
-                case edfhWLDELTA:
-                    ret = do_cpte_real(xd, part, i, fflags, &dfhist->wl_delta, list);
+                case StateFepEntry::WangLandauDelta:
+                    ret = do_cpte_real(xd, *i, fflags, &dfhist->wl_delta, list);
                     break;
-                case edfhSUMWEIGHTS:
-                    ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_weights, list);
+                case StateFepEntry::SumWeights:
+                    ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_weights, list);
                     break;
-                case edfhSUMDG:
-                    ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_dg, list);
+                case StateFepEntry::SumDG:
+                    ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_dg, list);
                     break;
-                case edfhSUMMINVAR:
-                    ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_minvar, list);
+                case StateFepEntry::SumMinVar:
+                    ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_minvar, list);
                     break;
-                case edfhSUMVAR:
-                    ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_variance, list);
+                case StateFepEntry::SumVar:
+                    ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_variance, list);
                     break;
-                case edfhACCUMP:
-                    ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_p, list);
+                case StateFepEntry::Accump:
+                    ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_p, list);
                     break;
-                case edfhACCUMM:
-                    ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_m, list);
+                case StateFepEntry::Accumm:
+                    ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_m, list);
                     break;
-                case edfhACCUMP2:
-                    ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_p2, list);
+                case StateFepEntry::Accump2:
+                    ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_p2, list);
                     break;
-                case edfhACCUMM2:
-                    ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_m2, list);
+                case StateFepEntry::Accumm2:
+                    ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_m2, list);
                     break;
-                case edfhTIJ:
-                    ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->Tij, list);
+                case StateFepEntry::Tij:
+                    ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->Tij, list);
                     break;
-                case edfhTIJEMP:
-                    ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->Tij_empirical, list);
+                case StateFepEntry::TijEmp:
+                    ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->Tij_empirical, list);
                     break;
 
                 default:
                     gmx_fatal(FARGS,
                               "Unknown df history entry %d\n"
                               "You are probably reading a new checkpoint file with old code",
-                              i);
+                              enumValueToBitMask(*i));
             }
         }
     }
@@ -1992,13 +2038,13 @@ static int do_cpt_correlation_grid(XDR*                         xd,
                                    gmx_unused int               fflags,
                                    gmx::CorrelationGridHistory* corrGrid,
                                    FILE*                        list,
-                                   int                          eawhh)
+                                   StateAwhEntry                eawhh)
 {
     int ret = 0;
 
-    do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->numCorrelationTensors), list);
-    do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->tensorSize), list);
-    do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->blockDataListSize), list);
+    do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->numCorrelationTensors), list);
+    do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->tensorSize), list);
+    do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->blockDataListSize), list);
 
     if (bRead)
     {
@@ -2008,17 +2054,19 @@ static int do_cpt_correlation_grid(XDR*                         xd,
 
     for (gmx::CorrelationBlockDataHistory& blockData : corrGrid->blockDataBuffer)
     {
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeight), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumSquareWeight), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeightX), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeightY), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksSquareBlockWeight), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockSquareWeight), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockWeightBlockWeightX), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockWeightBlockWeightY), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockLength), list);
-        do_cpt_int_err(xd, eawhh_names[eawhh], &(blockData.previousBlockIndex), list);
-        do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.correlationIntegral), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeight), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumSquareWeight), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeightX), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeightY), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.sumOverBlocksSquareBlockWeight), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockSquareWeight), list);
+        do_cpt_double_err(
+                xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockWeightBlockWeightX), list);
+        do_cpt_double_err(
+                xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockWeightBlockWeightY), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockLength), list);
+        do_cpt_int_err(xd, enumValueToString(eawhh), &(blockData.previousBlockIndex), list);
+        do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.correlationIntegral), list);
     }
 
     return ret;
@@ -2029,70 +2077,71 @@ static int do_cpt_awh_bias(XDR* xd, gmx_bool bRead, int fflags, gmx::AwhBiasHist
     int ret = 0;
 
     gmx::AwhBiasStateHistory* state = &biasHistory->state;
-    for (int i = 0; (i < eawhhNR && ret == 0); i++)
+    using StateFlags                = gmx::EnumerationArray<StateAwhEntry, bool>;
+    for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
     {
-        if (fflags & (1 << i))
+        if (fflags & enumValueToBitMask(*i))
         {
-            switch (i)
+            switch (*i)
             {
-                case eawhhIN_INITIAL:
-                    do_cpt_bool_err(xd, eawhh_names[i], &state->in_initial, list);
+                case StateAwhEntry::InInitial:
+                    do_cpt_bool_err(xd, enumValueToString(*i), &state->in_initial, list);
                     break;
-                case eawhhEQUILIBRATEHISTOGRAM:
-                    do_cpt_bool_err(xd, eawhh_names[i], &state->equilibrateHistogram, list);
+                case StateAwhEntry::EquilibrateHistogram:
+                    do_cpt_bool_err(xd, enumValueToString(*i), &state->equilibrateHistogram, list);
                     break;
-                case eawhhHISTSIZE:
-                    do_cpt_double_err(xd, eawhh_names[i], &state->histSize, list);
+                case StateAwhEntry::HistogramSize:
+                    do_cpt_double_err(xd, enumValueToString(*i), &state->histSize, list);
                     break;
-                case eawhhNPOINTS:
+                case StateAwhEntry::NumPoints:
                 {
                     int numPoints;
                     if (!bRead)
                     {
                         numPoints = biasHistory->pointState.size();
                     }
-                    do_cpt_int_err(xd, eawhh_names[i], &numPoints, list);
+                    do_cpt_int_err(xd, enumValueToString(*i), &numPoints, list);
                     if (bRead)
                     {
                         biasHistory->pointState.resize(numPoints);
                     }
                 }
                 break;
-                case eawhhCOORDPOINT:
+                case StateAwhEntry::CoordPoint:
                     for (auto& psh : biasHistory->pointState)
                     {
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.target, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.free_energy, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.bias, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_iteration, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_covering, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_tot, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_ref, list);
-                        do_cpt_step_err(xd, eawhh_names[i], &psh.last_update_index, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.log_pmfsum, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.visits_iteration, list);
-                        do_cpt_double_err(xd, eawhh_names[i], &psh.visits_tot, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.target, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.free_energy, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.bias, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_iteration, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_covering, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_tot, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_ref, list);
+                        do_cpt_step_err(xd, enumValueToString(*i), &psh.last_update_index, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.log_pmfsum, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.visits_iteration, list);
+                        do_cpt_double_err(xd, enumValueToString(*i), &psh.visits_tot, list);
                     }
                     break;
-                case eawhhUMBRELLAGRIDPOINT:
-                    do_cpt_int_err(xd, eawhh_names[i], &(state->umbrellaGridpoint), list);
+                case StateAwhEntry::UmbrellaGridPoint:
+                    do_cpt_int_err(xd, enumValueToString(*i), &(state->umbrellaGridpoint), list);
                     break;
-                case eawhhUPDATELIST:
-                    do_cpt_int_err(xd, eawhh_names[i], &(state->origin_index_updatelist), list);
-                    do_cpt_int_err(xd, eawhh_names[i], &(state->end_index_updatelist), list);
+                case StateAwhEntry::UpdateList:
+                    do_cpt_int_err(xd, enumValueToString(*i), &(state->origin_index_updatelist), list);
+                    do_cpt_int_err(xd, enumValueToString(*i), &(state->end_index_updatelist), list);
                     break;
-                case eawhhLOGSCALEDSAMPLEWEIGHT:
-                    do_cpt_double_err(xd, eawhh_names[i], &(state->logScaledSampleWeight), list);
-                    do_cpt_double_err(xd, eawhh_names[i], &(state->maxLogScaledSampleWeight), list);
+                case StateAwhEntry::LogScaledSampleWeight:
+                    do_cpt_double_err(xd, enumValueToString(*i), &(state->logScaledSampleWeight), list);
+                    do_cpt_double_err(xd, enumValueToString(*i), &(state->maxLogScaledSampleWeight), list);
                     break;
-                case eawhhNUMUPDATES:
-                    do_cpt_step_err(xd, eawhh_names[i], &(state->numUpdates), list);
+                case StateAwhEntry::NumUpdates:
+                    do_cpt_step_err(xd, enumValueToString(*i), &(state->numUpdates), list);
                     break;
-                case eawhhFORCECORRELATIONGRID:
+                case StateAwhEntry::ForceCorrelationGrid:
                     ret = do_cpt_correlation_grid(
-                            xd, bRead, fflags, &biasHistory->forceCorrelationGrid, list, i);
+                            xd, bRead, fflags, &biasHistory->forceCorrelationGrid, list, *i);
                     break;
-                default: gmx_fatal(FARGS, "Unknown awh history entry %d\n", i);
+                default: gmx_fatal(FARGS, "Unknown awh history entry %d\n", enumValueToBitMask(*i));
             }
         }
     }
@@ -2269,9 +2318,15 @@ void write_checkpoint_data(t_fileio*                         fp,
     headerContents.flags_eks = 0;
     if (state->ekinstate.bUpToDate)
     {
-        headerContents.flags_eks = ((1 << eeksEKIN_N) | (1 << eeksEKINH) | (1 << eeksEKINF)
-                                    | (1 << eeksEKINO) | (1 << eeksEKINSCALEF) | (1 << eeksEKINSCALEH)
-                                    | (1 << eeksVSCALE) | (1 << eeksDEKINDL) | (1 << eeksMVCOS));
+        headerContents.flags_eks = (enumValueToBitMask(StateKineticEntry::EkinNumber)
+                                    | enumValueToBitMask(StateKineticEntry::EkinHalfStep)
+                                    | enumValueToBitMask(StateKineticEntry::EkinFullStep)
+                                    | enumValueToBitMask(StateKineticEntry::EkinHalfStepOld)
+                                    | enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleFullStep)
+                                    | enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleHalfStep)
+                                    | enumValueToBitMask(StateKineticEntry::VelocityScale)
+                                    | enumValueToBitMask(StateKineticEntry::DEkinDLambda)
+                                    | enumValueToBitMask(StateKineticEntry::Mvcos));
     }
     headerContents.isModularSimulatorCheckpoint = !modularSimulatorCheckpointData->empty();
 
@@ -2279,22 +2334,26 @@ void write_checkpoint_data(t_fileio*                         fp,
     headerContents.flags_enh  = 0;
     if (enerhist != nullptr && (enerhist->nsum > 0 || enerhist->nsum_sim > 0))
     {
-        headerContents.flags_enh |=
-                (1 << eenhENERGY_N) | (1 << eenhENERGY_NSTEPS) | (1 << eenhENERGY_NSTEPS_SIM);
+        headerContents.flags_enh |= enumValueToBitMask(StateEnergyEntry::N)
+                                    | enumValueToBitMask(StateEnergyEntry::NumSteps)
+                                    | enumValueToBitMask(StateEnergyEntry::NumStepsSim);
         if (enerhist->nsum > 0)
         {
-            headerContents.flags_enh |=
-                    ((1 << eenhENERGY_AVER) | (1 << eenhENERGY_SUM) | (1 << eenhENERGY_NSUM));
+            headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::Aver)
+                                         | enumValueToBitMask(StateEnergyEntry::Sum)
+                                         | enumValueToBitMask(StateEnergyEntry::NumSum));
         }
         if (enerhist->nsum_sim > 0)
         {
-            headerContents.flags_enh |= ((1 << eenhENERGY_SUM_SIM) | (1 << eenhENERGY_NSUM_SIM));
+            headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::SumSim)
+                                         | enumValueToBitMask(StateEnergyEntry::NumSumSim));
         }
         if (enerhist->deltaHForeignLambdas != nullptr)
         {
-            headerContents.flags_enh |=
-                    ((1 << eenhENERGY_DELTA_H_NN) | (1 << eenhENERGY_DELTA_H_LIST)
-                     | (1 << eenhENERGY_DELTA_H_STARTTIME) | (1 << eenhENERGY_DELTA_H_STARTLAMBDA));
+            headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::DeltaHNN)
+                                         | enumValueToBitMask(StateEnergyEntry::DeltaHList)
+                                         | enumValueToBitMask(StateEnergyEntry::DeltaHStartTime)
+                                         | enumValueToBitMask(StateEnergyEntry::DeltaHStartLambda));
         }
     }
 
@@ -2302,36 +2361,50 @@ void write_checkpoint_data(t_fileio*                         fp,
     headerContents.flagsPullHistory = 0;
     if (pullHist != nullptr && (pullHist->numValuesInXSum > 0 || pullHist->numValuesInFSum > 0))
     {
-        headerContents.flagsPullHistory |= (1 << epullhPULL_NUMCOORDINATES);
-        headerContents.flagsPullHistory |= ((1 << epullhPULL_NUMGROUPS) | (1 << epullhPULL_NUMVALUESINXSUM)
-                                            | (1 << epullhPULL_NUMVALUESINFSUM));
+        headerContents.flagsPullHistory |= enumValueToBitMask(StatePullEntry::NumCoordinates);
+        headerContents.flagsPullHistory |= (enumValueToBitMask(StatePullEntry::NumGroups)
+                                            | enumValueToBitMask(StatePullEntry::NumValuesInXSum)
+                                            | enumValueToBitMask(StatePullEntry::NumValuesInFSum));
     }
 
     headerContents.flags_dfh = 0;
     if (bExpanded)
     {
-        headerContents.flags_dfh = ((1 << edfhBEQUIL) | (1 << edfhNATLAMBDA) | (1 << edfhSUMWEIGHTS)
-                                    | (1 << edfhSUMDG) | (1 << edfhTIJ) | (1 << edfhTIJEMP));
+        headerContents.flags_dfh =
+                (enumValueToBitMask(StateFepEntry::IsEquilibrated)
+                 | enumValueToBitMask(StateFepEntry::NumAtLambda)
+                 | enumValueToBitMask(StateFepEntry::SumWeights) | enumValueToBitMask(StateFepEntry::SumDG)
+                 | enumValueToBitMask(StateFepEntry::Tij) | enumValueToBitMask(StateFepEntry::TijEmp));
         if (EWL(elamstats))
         {
-            headerContents.flags_dfh |= ((1 << edfhWLDELTA) | (1 << edfhWLHISTO));
+            headerContents.flags_dfh |= (enumValueToBitMask(StateFepEntry::WangLandauDelta)
+                                         | enumValueToBitMask(StateFepEntry::WangLandauHistogram));
         }
         if ((elamstats == LambdaWeightCalculation::Minvar) || (elamstats == LambdaWeightCalculation::Barker)
             || (elamstats == LambdaWeightCalculation::Metropolis))
         {
-            headerContents.flags_dfh |= ((1 << edfhACCUMP) | (1 << edfhACCUMM) | (1 << edfhACCUMP2)
-                                         | (1 << edfhACCUMM2) | (1 << edfhSUMMINVAR) | (1 << edfhSUMVAR));
+            headerContents.flags_dfh |= (enumValueToBitMask(StateFepEntry::Accump)
+                                         | enumValueToBitMask(StateFepEntry::Accumm)
+                                         | enumValueToBitMask(StateFepEntry::Accump2)
+                                         | enumValueToBitMask(StateFepEntry::Accumm2)
+                                         | enumValueToBitMask(StateFepEntry::SumMinVar)
+                                         | enumValueToBitMask(StateFepEntry::SumVar));
         }
     }
 
     headerContents.flags_awhh = 0;
     if (state->awhHistory != nullptr && !state->awhHistory->bias.empty())
     {
-        headerContents.flags_awhh |=
-                ((1 << eawhhIN_INITIAL) | (1 << eawhhEQUILIBRATEHISTOGRAM) | (1 << eawhhHISTSIZE)
-                 | (1 << eawhhNPOINTS) | (1 << eawhhCOORDPOINT) | (1 << eawhhUMBRELLAGRIDPOINT)
-                 | (1 << eawhhUPDATELIST) | (1 << eawhhLOGSCALEDSAMPLEWEIGHT)
-                 | (1 << eawhhNUMUPDATES) | (1 << eawhhFORCECORRELATIONGRID));
+        headerContents.flags_awhh |= (enumValueToBitMask(StateAwhEntry::InInitial)
+                                      | enumValueToBitMask(StateAwhEntry::EquilibrateHistogram)
+                                      | enumValueToBitMask(StateAwhEntry::HistogramSize)
+                                      | enumValueToBitMask(StateAwhEntry::NumPoints)
+                                      | enumValueToBitMask(StateAwhEntry::CoordPoint)
+                                      | enumValueToBitMask(StateAwhEntry::UmbrellaGridPoint)
+                                      | enumValueToBitMask(StateAwhEntry::UpdateList)
+                                      | enumValueToBitMask(StateAwhEntry::LogScaledSampleWeight)
+                                      | enumValueToBitMask(StateAwhEntry::NumUpdates)
+                                      | enumValueToBitMask(StateAwhEntry::ForceCorrelationGrid));
     }
 
     do_cpt_header(gmx_fio_getxdr(fp), FALSE, nullptr, &headerContents);
@@ -2339,8 +2412,7 @@ void write_checkpoint_data(t_fileio*                         fp,
     if ((do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr) < 0)
         || (do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state->ekinstate, nullptr) < 0)
         || (do_cpt_enerhist(gmx_fio_getxdr(fp), FALSE, headerContents.flags_enh, enerhist, nullptr) < 0)
-        || (doCptPullHist(gmx_fio_getxdr(fp), FALSE, headerContents.flagsPullHistory, pullHist, StatePart::pullHistory, nullptr)
-            < 0)
+        || (doCptPullHist(gmx_fio_getxdr(fp), FALSE, headerContents.flagsPullHistory, pullHist, nullptr) < 0)
         || (do_cpt_df_hist(gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state->dfhist, nullptr)
             < 0)
         || (do_cpt_EDstate(
@@ -2664,13 +2736,14 @@ static void read_checkpoint(const char*                    fn,
     {
         cp_error();
     }
-    state->ekinstate.hasReadEkinState = (((headerContents->flags_eks & (1 << eeksEKINH)) != 0)
-                                         || ((headerContents->flags_eks & (1 << eeksEKINF)) != 0)
-                                         || ((headerContents->flags_eks & (1 << eeksEKINO)) != 0)
-                                         || (((headerContents->flags_eks & (1 << eeksEKINSCALEF))
-                                              | (headerContents->flags_eks & (1 << eeksEKINSCALEH))
-                                              | (headerContents->flags_eks & (1 << eeksVSCALE)))
-                                             != 0));
+    state->ekinstate.hasReadEkinState =
+            (((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinHalfStep)) != 0)
+             || ((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinFullStep)) != 0)
+             || ((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinHalfStepOld)) != 0)
+             || (((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleFullStep))
+                  | (headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleHalfStep))
+                  | (headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::VelocityScale)))
+                 != 0));
 
     if (headerContents->flags_enh && observablesHistory->energyHistory == nullptr)
     {
@@ -2693,7 +2766,6 @@ static void read_checkpoint(const char*                    fn,
                             TRUE,
                             headerContents->flagsPullHistory,
                             observablesHistory->pullHistory.get(),
-                            StatePart::pullHistory,
                             nullptr);
         if (ret)
         {
@@ -2888,8 +2960,7 @@ static CheckpointHeaderContents read_checkpoint_data(t_fileio*
         cp_error();
     }
     PullHistory pullHist = {};
-    ret                  = doCptPullHist(
-            gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, StatePart::pullHistory, nullptr);
+    ret = doCptPullHist(gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, nullptr);
     if (ret)
     {
         cp_error();
@@ -2966,18 +3037,18 @@ void read_checkpoint_trxframe(t_fileio* fp, t_trxframe* fr)
     fr->lambda    = state.lambda[FreeEnergyPerturbationCouplingType::Fep];
     fr->fep_state = state.fep_state;
     fr->bAtoms    = FALSE;
-    fr->bX        = ((state.flags & (1 << estX)) != 0);
+    fr->bX        = ((state.flags & enumValueToBitMask(StateEntry::X)) != 0);
     if (fr->bX)
     {
         fr->x = makeRvecArray(state.x, state.natoms);
     }
-    fr->bV = ((state.flags & (1 << estV)) != 0);
+    fr->bV = ((state.flags & enumValueToBitMask(StateEntry::V)) != 0);
     if (fr->bV)
     {
         fr->v = makeRvecArray(state.v, state.natoms);
     }
     fr->bF   = FALSE;
-    fr->bBox = ((state.flags & (1 << estBOX)) != 0);
+    fr->bBox = ((state.flags & enumValueToBitMask(StateEntry::Box)) != 0);
     if (fr->bBox)
     {
         copy_mat(state.box, fr->box);
@@ -3016,8 +3087,7 @@ void list_checkpoint(const char* fn, FILE* out)
     if (ret == 0)
     {
         PullHistory pullHist = {};
-        ret                  = doCptPullHist(
-                gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, StatePart::pullHistory, out);
+        ret = doCptPullHist(gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, out);
     }
 
     if (ret == 0)
index b99e3bcf6e8ec014475e0f9d2ff53d3685f3a26f..38c5335216d5a135e89a0ad1e9780f81d0412516 100644 (file)
@@ -3008,11 +3008,11 @@ static void do_tpx_state_second(gmx::ISerializer* serializer, TpxFileHeader* tpx
             // of the tpx file.
             if (tpx->bX)
             {
-                state->flags |= (1 << estX);
+                state->flags |= enumValueToBitMask(StateEntry::X);
             }
             if (tpx->bV)
             {
-                state->flags |= (1 << estV);
+                state->flags |= enumValueToBitMask(StateEntry::V);
             }
             state_change_natoms(state, tpx->natoms);
         }
@@ -3028,7 +3028,7 @@ static void do_tpx_state_second(gmx::ISerializer* serializer, TpxFileHeader* tpx
     {
         if (serializer->reading())
         {
-            state->flags |= (1 << estX);
+            state->flags |= enumValueToBitMask(StateEntry::X);
         }
         serializer->doRvecArray(x, tpx->natoms);
     }
@@ -3038,7 +3038,7 @@ static void do_tpx_state_second(gmx::ISerializer* serializer, TpxFileHeader* tpx
     {
         if (serializer->reading())
         {
-            state->flags |= (1 << estV);
+            state->flags |= enumValueToBitMask(StateEntry::V);
         }
         if (!v)
         {
@@ -3242,8 +3242,8 @@ static TpxFileHeader populateTpxHeader(const t_state& state, const t_inputrec* i
     header.lambda         = state.lambda[FreeEnergyPerturbationCouplingType::Fep];
     header.bIr            = ir != nullptr;
     header.bTop           = mtop != nullptr;
-    header.bX             = (state.flags & (1 << estX)) != 0;
-    header.bV             = (state.flags & (1 << estV)) != 0;
+    header.bX             = (state.flags & enumValueToBitMask(StateEntry::X)) != 0;
+    header.bV             = (state.flags & enumValueToBitMask(StateEntry::V)) != 0;
     header.bF             = false;
     header.bBox           = true;
     header.fileVersion    = tpx_version;
index a47fb29950cb09e5c7a8baebd751e370b0b48e8d..97d6d6ffcfe31e598e52d0a6f7d9bf4ad068b8d0 100644 (file)
@@ -714,10 +714,10 @@ static void new_status(const char*                           topfile,
     /* It would be nice to get rid of the copies below, but we don't know
      * a priori if the number of atoms in confin matches what we expect.
      */
-    state->flags |= (1 << estX);
+    state->flags |= enumValueToBitMask(StateEntry::X);
     if (v != nullptr)
     {
-        state->flags |= (1 << estV);
+        state->flags |= enumValueToBitMask(StateEntry::V);
     }
     state_change_natoms(state, state->natoms);
     std::copy(x, x + state->natoms, state->x.data());
@@ -778,7 +778,7 @@ static void new_status(const char*                           topfile,
             opts->seed = static_cast<int>(gmx::makeRandomSeed());
             GMX_LOG(logger.info).asParagraph().appendTextFormatted("Setting gen_seed to %d", opts->seed);
         }
-        state->flags |= (1 << estV);
+        state->flags |= enumValueToBitMask(StateEntry::V);
         maxwell_speed(opts->tempi, opts->seed, sys, state->v.rvec_array(), logger);
 
         stop_cm(logger, state->natoms, mass, state->x.rvec_array(), state->v.rvec_array());
index 91f61c4f10468c58853aab94f305d59354b96ad8..89c48d588c637dd2c0aaedfd2a06d85852a05e6d 100644 (file)
@@ -199,10 +199,10 @@ void init_disres(FILE*                 fplog,
 
         hist = &state->hist;
         /* Set the "history lack" factor to 1 */
-        state->flags |= (1 << estDISRE_INITF);
+        state->flags |= enumValueToBitMask(StateEntry::DisreInitF);
         hist->disre_initf = 1.0;
         /* Allocate space for the r^-3 time averages */
-        state->flags |= (1 << estDISRE_RM3TAV);
+        state->flags |= enumValueToBitMask(StateEntry::DisreRm3Tav);
         hist->ndisrepairs = dd->npair;
         snew(hist->disre_rm3tav, hist->ndisrepairs);
     }
index ff9a7b5cec8375855afb1464652693c75c4d5c30..0ad51f201e7998e1e3d9c3d78cc35c8c13669bd7 100644 (file)
@@ -193,9 +193,9 @@ void init_orires(FILE*                 fplog,
         od->edt_1 = 1.0 - od->edt;
 
         /* Extend the state with the orires history */
-        globalState->flags |= (1 << estORIRE_INITF);
+        globalState->flags |= enumValueToBitMask(StateEntry::OrireInitF);
         globalState->hist.orire_initf = 1;
-        globalState->flags |= (1 << estORIRE_DTAV);
+        globalState->flags |= enumValueToBitMask(StateEntry::OrireDtav);
         globalState->hist.norire_Dtav = od->nr * 5;
         snew(globalState->hist.orire_Dtav, globalState->hist.norire_Dtav);
     }
index 7f2919765d9ce50fd2d50af3ea6b87d01ed1aee3..ad751dff21871eab5b6b82a0fc69aa68ab17d99b 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "gromacs/fileio/tpxio.h"
 #include "gromacs/mdtypes/state.h"
+#include "gromacs/utility/enumerationhelpers.h"
 
 template<typename AllocatorType>
 static void bcastPaddedRVecVector(MPI_Comm                                     communicator,
@@ -72,20 +73,22 @@ void broadcastStateWithoutDynamics(MPI_Comm communicator,
     block_bc(communicator, state->natoms);
     block_bc(communicator, state->flags);
 
-    for (int i = 0; i < estNR; i++)
+    for (auto i : gmx::EnumerationArray<StateEntry, bool>::keys())
     {
-        if (state->flags & (1 << i))
+        if (state->flags & enumValueToBitMask(i))
         {
             switch (i)
             {
-                case estLAMBDA:
+                case StateEntry::Lambda:
                     nblock_bc(communicator,
                               static_cast<int>(FreeEnergyPerturbationCouplingType::Count),
                               state->lambda.data());
                     break;
-                case estFEPSTATE: block_bc(communicator, state->fep_state); break;
-                case estBOX: block_bc(communicator, state->box); break;
-                case estX: bcastPaddedRVecVector(communicator, &state->x, state->natoms); break;
+                case StateEntry::FepState: block_bc(communicator, state->fep_state); break;
+                case StateEntry::Box: block_bc(communicator, state->box); break;
+                case StateEntry::X:
+                    bcastPaddedRVecVector(communicator, &state->x, state->natoms);
+                    break;
                 default:
                     GMX_RELEASE_ASSERT(false,
                                        "The state has a dynamic entry, while no dynamic entries "
index 8104b92d00c7265dfa842e696e12659c6b152c17..3ffbcb4a1dcb7efde94e634e2d5f8e176917a621 100644 (file)
@@ -523,58 +523,58 @@ void set_state_entries(t_state* state, const t_inputrec* ir, bool useModularSimu
     state->flags = 0;
     if (ir->efep != FreeEnergyPerturbationType::No || ir->bExpanded)
     {
-        state->flags |= (1 << estLAMBDA);
-        state->flags |= (1 << estFEPSTATE);
+        state->flags |= enumValueToBitMask(StateEntry::Lambda);
+        state->flags |= enumValueToBitMask(StateEntry::FepState);
     }
-    state->flags |= (1 << estX);
+    state->flags |= enumValueToBitMask(StateEntry::X);
     GMX_RELEASE_ASSERT(state->x.size() == state->natoms,
                        "We should start a run with an initialized state->x");
     if (EI_DYNAMICS(ir->eI))
     {
-        state->flags |= (1 << estV);
+        state->flags |= enumValueToBitMask(StateEntry::V);
     }
 
     state->nnhpres = 0;
     if (ir->pbcType != PbcType::No)
     {
-        state->flags |= (1 << estBOX);
+        state->flags |= enumValueToBitMask(StateEntry::Box);
         if (inputrecPreserveShape(ir))
         {
-            state->flags |= (1 << estBOX_REL);
+            state->flags |= enumValueToBitMask(StateEntry::BoxRel);
         }
         if ((ir->epc == PressureCoupling::ParrinelloRahman) || (ir->epc == PressureCoupling::Mttk))
         {
-            state->flags |= (1 << estBOXV);
+            state->flags |= enumValueToBitMask(StateEntry::BoxV);
             if (!useModularSimulator)
             {
-                state->flags |= (1 << estPRES_PREV);
+                state->flags |= enumValueToBitMask(StateEntry::PressurePrevious);
             }
         }
         if (inputrecNptTrotter(ir) || (inputrecNphTrotter(ir)))
         {
             state->nnhpres = 1;
-            state->flags |= (1 << estNHPRES_XI);
-            state->flags |= (1 << estNHPRES_VXI);
-            state->flags |= (1 << estSVIR_PREV);
-            state->flags |= (1 << estFVIR_PREV);
-            state->flags |= (1 << estVETA);
-            state->flags |= (1 << estVOL0);
+            state->flags |= enumValueToBitMask(StateEntry::Nhpresxi);
+            state->flags |= enumValueToBitMask(StateEntry::Nhpresvxi);
+            state->flags |= enumValueToBitMask(StateEntry::SVirPrev);
+            state->flags |= enumValueToBitMask(StateEntry::FVirPrev);
+            state->flags |= enumValueToBitMask(StateEntry::Veta);
+            state->flags |= enumValueToBitMask(StateEntry::Vol0);
         }
         if (ir->epc == PressureCoupling::Berendsen || ir->epc == PressureCoupling::CRescale)
         {
-            state->flags |= (1 << estBAROS_INT);
+            state->flags |= enumValueToBitMask(StateEntry::BarosInt);
         }
     }
 
     if (ir->etc == TemperatureCoupling::NoseHoover)
     {
-        state->flags |= (1 << estNH_XI);
-        state->flags |= (1 << estNH_VXI);
+        state->flags |= enumValueToBitMask(StateEntry::Nhxi);
+        state->flags |= enumValueToBitMask(StateEntry::Nhvxi);
     }
 
     if (ir->etc == TemperatureCoupling::VRescale || ir->etc == TemperatureCoupling::Berendsen)
     {
-        state->flags |= (1 << estTHERM_INT);
+        state->flags |= enumValueToBitMask(StateEntry::ThermInt);
     }
 
     init_gtc_state(state, state->ngtc, state->nnhpres, ir->opts.nhchainlength); /* allocate the space for nose-hoover chains */
@@ -588,6 +588,6 @@ void set_state_entries(t_state* state, const t_inputrec* ir, bool useModularSimu
 
     if (ir->pull && ir->pull->bSetPbcRefToPrevStepCOM)
     {
-        state->flags |= (1 << estPULLCOMPREVSTEP);
+        state->flags |= enumValueToBitMask(StateEntry::PullComPrevStep);
     }
 }
index daff232482f260d1a21035120d73cb628556c152..84aa9a830543f1055d041cd2c258debbb6d8ae5e 100644 (file)
@@ -1450,11 +1450,11 @@ void Update::Impl::update_coords(const t_inputrec&
     real dt = inputRecord.delta_t;
 
     /* We need to update the NMR restraint history when time averaging is used */
-    if (state->flags & (1 << estDISRE_RM3TAV))
+    if (state->flags & enumValueToBitMask(StateEntry::DisreRm3Tav))
     {
         update_disres_history(*fcdata.disres, &state->hist);
     }
-    if (state->flags & (1 << estORIRE_DTAV))
+    if (state->flags & enumValueToBitMask(StateEntry::OrireDtav))
     {
         update_orires_history(*fcdata.orires, &state->hist);
     }
index 254e4d8e6139e85402490197f60c595b92a699f8..fe3b1423ff8a1a7a59efd78fadc02f0cec680d3a 100644 (file)
@@ -546,7 +546,7 @@ void gmx::LegacySimulator::do_md()
 
     if (!ir->bContinuation)
     {
-        if (state->flags & (1U << estV))
+        if (state->flags & enumValueToBitMask(StateEntry::V))
         {
             auto v = makeArrayRef(state->v);
             /* Set the velocities of vsites, shells and frozen atoms to zero */
@@ -1915,7 +1915,7 @@ void gmx::LegacySimulator::do_md()
         /* With all integrators, except VV, we need to retain the pressure
          * at the current step for coupling at the next step.
          */
-        if ((state->flags & (1U << estPRES_PREV))
+        if ((state->flags & enumValueToBitMask(StateEntry::PressurePrevious))
             && (bGStatEveryStep || (ir->nstpcouple > 0 && step % ir->nstpcouple == 0)))
         {
             /* Store the pressure in t_state for pressure coupling
index 2b0ad5dc6141f7c097f386b4e4087be626d3bcde..102b4393c7d5c2525eae153632a993f7345d2f56 100644 (file)
@@ -701,7 +701,7 @@ static bool do_em_step(const t_commrec*                          cr,
             GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
         }
 
-        if (s2->flags & (1 << estCGP))
+        if (s2->flags & enumValueToBitMask(StateEntry::Cgp))
         {
             /* Copy the CG p vector */
             const rvec* p1 = s1->cg_p.rvec_array();
@@ -1196,7 +1196,7 @@ void LegacySimulator::do_cg()
     if (MASTER(cr))
     {
         // In CG, the state is extended with a search direction
-        state_global->flags |= (1 << estCGP);
+        state_global->flags |= enumValueToBitMask(StateEntry::Cgp);
 
         // Ensure the extra per-atom state array gets allocated
         state_change_natoms(state_global, state_global->natoms);
index dce96b70ae4d9860563d31bcf77709793c79bae5..350ace3f2f7b8fc59c3b98b97f4334c40626628c 100644 (file)
@@ -1005,7 +1005,7 @@ int Mdrunner::mdrunner()
     if (SIMMASTER(cr))
     {
         /* In rerun, set velocities to zero if present */
-        if (doRerun && ((globalState->flags & (1 << estV)) != 0))
+        if (doRerun && ((globalState->flags & enumValueToBitMask(StateEntry::V)) != 0))
         {
             // rerun does not use velocities
             GMX_LOG(mdlog.info)
@@ -1017,7 +1017,7 @@ int Mdrunner::mdrunner()
             {
                 clear_rvec(globalState->v[i]);
             }
-            globalState->flags &= ~(1 << estV);
+            globalState->flags &= ~enumValueToBitMask(StateEntry::V);
         }
 
         /* now make sure the state is initialized and propagated */
index dfb55ef30dbff4a098917247d5011872c8b0e683..79a98f08455eb70017c5147bf25d4ca22ed555b6 100644 (file)
@@ -167,15 +167,15 @@ void state_change_natoms(t_state* state, int natoms)
 
     /* We need padding, since we might use SIMD access, but the
      * containers here all ensure that. */
-    if (state->flags & (1 << estX))
+    if (state->flags & enumValueToBitMask(StateEntry::X))
     {
         state->x.resizeWithPadding(natoms);
     }
-    if (state->flags & (1 << estV))
+    if (state->flags & enumValueToBitMask(StateEntry::V))
     {
         state->v.resizeWithPadding(natoms);
     }
-    if (state->flags & (1 << estCGP))
+    if (state->flags & enumValueToBitMask(StateEntry::Cgp))
     {
         state->cg_p.resizeWithPadding(natoms);
     }
@@ -206,17 +206,17 @@ void comp_state(const t_state* st1, const t_state* st2, gmx_bool bRMSD, real fto
     cmp_rvecs(stdout, "box_rel", DIM, st1->box_rel, st2->box_rel, FALSE, ftol, abstol);
     fprintf(stdout, "comparing boxv\n");
     cmp_rvecs(stdout, "boxv", DIM, st1->boxv, st2->boxv, FALSE, ftol, abstol);
-    if (st1->flags & (1 << estSVIR_PREV))
+    if (st1->flags & enumValueToBitMask(StateEntry::SVirPrev))
     {
         fprintf(stdout, "comparing shake vir_prev\n");
         cmp_rvecs(stdout, "svir_prev", DIM, st1->svir_prev, st2->svir_prev, FALSE, ftol, abstol);
     }
-    if (st1->flags & (1 << estFVIR_PREV))
+    if (st1->flags & enumValueToBitMask(StateEntry::FVirPrev))
     {
         fprintf(stdout, "comparing force vir_prev\n");
         cmp_rvecs(stdout, "fvir_prev", DIM, st1->fvir_prev, st2->fvir_prev, FALSE, ftol, abstol);
     }
-    if (st1->flags & (1 << estPRES_PREV))
+    if (st1->flags & enumValueToBitMask(StateEntry::PressurePrevious))
     {
         fprintf(stdout, "comparing prev_pres\n");
         cmp_rvecs(stdout, "pres_prev", DIM, st1->pres_prev, st2->pres_prev, FALSE, ftol, abstol);
@@ -250,12 +250,14 @@ void comp_state(const t_state* st1, const t_state* st2, gmx_bool bRMSD, real fto
     cmp_int(stdout, "natoms", -1, st1->natoms, st2->natoms);
     if (st1->natoms == st2->natoms)
     {
-        if ((st1->flags & (1 << estX)) && (st2->flags & (1 << estX)))
+        if ((st1->flags & enumValueToBitMask(StateEntry::X))
+            && (st2->flags & enumValueToBitMask(StateEntry::X)))
         {
             fprintf(stdout, "comparing x\n");
             cmp_rvecs(stdout, "x", st1->natoms, st1->x.rvec_array(), st2->x.rvec_array(), bRMSD, ftol, abstol);
         }
-        if ((st1->flags & (1 << estV)) && (st2->flags & (1 << estV)))
+        if ((st1->flags & enumValueToBitMask(StateEntry::V))
+            && (st2->flags & enumValueToBitMask(StateEntry::V)))
         {
             fprintf(stdout, "comparing v\n");
             cmp_rvecs(stdout, "v", st1->natoms, st1->v.rvec_array(), st2->v.rvec_array(), bRMSD, ftol, abstol);
index b4e5d7042b77528d0af1b1827d804f1a466c5931..bef760925a4de0328f03bcbc6ca1ffff79dbcb76 100644 (file)
@@ -94,42 +94,52 @@ using PaddedHostVector = gmx::PaddedHostVector<T>;
  * The order of these enums should not be changed,
  * since that affects the checkpoint (.cpt) file format.
  */
-enum
+enum class StateEntry : int
 {
-    estLAMBDA,
-    estBOX,
-    estBOX_REL,
-    estBOXV,
-    estPRES_PREV,
-    estNH_XI,
-    estTHERM_INT,
-    estX,
-    estV,
-    estSDX_NOTSUPPORTED,
-    estCGP,
-    estLD_RNG_NOTSUPPORTED,
-    estLD_RNGI_NOTSUPPORTED,
-    estDISRE_INITF,
-    estDISRE_RM3TAV,
-    estORIRE_INITF,
-    estORIRE_DTAV,
-    estSVIR_PREV,
-    estNH_VXI,
-    estVETA,
-    estVOL0,
-    estNHPRES_XI,
-    estNHPRES_VXI,
-    estFVIR_PREV,
-    estFEPSTATE,
-    estMC_RNG_NOTSUPPORTED,
-    estMC_RNGI_NOTSUPPORTED,
-    estBAROS_INT,
-    estPULLCOMPREVSTEP,
-    estNR
+    Lambda,
+    Box,
+    BoxRel,
+    BoxV,
+    PressurePrevious,
+    Nhxi,
+    ThermInt,
+    X,
+    V,
+    SDxNotSupported,
+    Cgp,
+    LDRngNotSupported,
+    LDRngINotSupported,
+    DisreInitF,
+    DisreRm3Tav,
+    OrireInitF,
+    OrireDtav,
+    SVirPrev,
+    Nhvxi,
+    Veta,
+    Vol0,
+    Nhpresxi,
+    Nhpresvxi,
+    FVirPrev,
+    FepState,
+    MCRngNotSupported,
+    MCRngINotSupported,
+    BarosInt,
+    PullComPrevStep,
+    Count
 };
 
-//! \brief The names of the state entries, defined in src/gmxlib/checkpoint.c
-extern const char* est_names[estNR];
+//! \brief The names of the state entries, defined in src/gromacs/fileio/checkpoint.cpp
+const char* enumValueToString(StateEntry enumValue);
+/*! \brief Convert enum to bitmask value.
+ *
+ * Used for setting flags in checkpoint header and verifying which flags are set.
+ */
+template<typename Enum>
+inline int enumValueToBitMask(Enum enumValue)
+{
+    static_assert(static_cast<int>(Enum::Count) <= std::numeric_limits<int>::digits);
+    return 1 << static_cast<int>(enumValue);
+}
 
 /*! \libinternal \brief History information for NMR distance and orientation restraints
  *
index 99406066fe0a9fe81af3586e0a4c18680d3811b4..6f769861af6400056bcf1af54ffba8b7aae9b7aa 100644 (file)
@@ -112,7 +112,7 @@ StatePropagatorData::StatePropagatorData(int                numAtoms,
     {
         auto localState = std::make_unique<t_state>();
         dd_init_local_state(cr->dd, globalState, localState.get());
-        stateHasVelocities = ((static_cast<unsigned int>(localState->flags) & (1U << estV)) != 0U);
+        stateHasVelocities = ((localState->flags & enumValueToBitMask(StateEntry::V)) != 0);
         setLocalState(std::move(localState));
     }
     else
@@ -123,7 +123,7 @@ StatePropagatorData::StatePropagatorData(int                numAtoms,
         x_           = globalState->x;
         v_           = globalState->v;
         copy_mat(globalState->box, box_);
-        stateHasVelocities = ((static_cast<unsigned int>(globalState->flags) & (1U << estV)) != 0U);
+        stateHasVelocities = ((globalState->flags & enumValueToBitMask(StateEntry::V)) != 0);
         previousX_.resizeWithPadding(localNAtoms_);
         ddpCount_ = globalState->ddp_count;
         copyPosition();
@@ -258,7 +258,8 @@ int StatePropagatorData::totalNumAtoms() const
 std::unique_ptr<t_state> StatePropagatorData::localState()
 {
     auto state   = std::make_unique<t_state>();
-    state->flags = (1U << estX) | (1U << estV) | (1U << estBOX);
+    state->flags = enumValueToBitMask(StateEntry::X) | enumValueToBitMask(StateEntry::V)
+                   | enumValueToBitMask(StateEntry::Box);
     state_change_natoms(state.get(), localNAtoms_);
     state->x = x_;
     state->v = v_;
@@ -365,7 +366,8 @@ void StatePropagatorData::Element::saveState()
         {
             localStateBackup_->lambda[i] = freeEnergyPerturbationData_->constLambdaView()[i];
         }
-        localStateBackup_->flags |= (1U << estLAMBDA) | (1U << estFEPSTATE);
+        localStateBackup_->flags |=
+                enumValueToBitMask(StateEntry::Lambda) | enumValueToBitMask(StateEntry::FepState);
     }
 }