Replace EnumOption with EnumerationArrayOption
authorMark Abraham <mark.j.abraham@gmail.com>
Tue, 7 Apr 2020 21:02:10 +0000 (21:02 +0000)
committerMark Abraham <mark.j.abraham@gmail.com>
Tue, 7 Apr 2020 21:02:10 +0000 (21:02 +0000)
Avoids code needing to mis-use the m_elements member of the
EnumerationArray. Encourages using class enums for command-line
options. Removes a bunch of clang-tidy suppressions and will be needed
for dealing properly with even more warnings coming with clang-tidy 9.
Removes a bunch of comments about how this list has to match that enum
somewhere else, because the compiler will tell us that.

Fixed time-unit conversion bug introduced a decade ago in
bc23d95b8c54b383cc731666f692f03237f8e949. That's exactly the kind
of bug that now gets caught at compile time.

Removed strange first field of legacy enums time_unit_t and
xvg_format_t that forced complicated casting and searching. It didn't
seem to do anything useful.

Removed unnecessary EnumIntOption.

Some test code is now in gmx::test namespace for brevity (consistent
with other test code), now that the enum values are much longer.

Change-Id: I9fd398d8981115d2317614912e64a9129ff1253a

42 files changed:
src/api/cpp/tpr.cpp
src/gromacs/analysisdata/modules/plot.cpp
src/gromacs/analysisdata/modules/plot.h
src/gromacs/applied_forces/densityfittingamplitudelookup.h
src/gromacs/applied_forces/densityfittingoptions.cpp
src/gromacs/commandline/pargs.cpp
src/gromacs/commandline/tests/cmdlinehelpwriter.cpp
src/gromacs/coordinateio/enums.h
src/gromacs/coordinateio/requirements.cpp
src/gromacs/fileio/oenv.cpp
src/gromacs/fileio/oenv.h
src/gromacs/fileio/xvgr.cpp
src/gromacs/gmxana/gmx_anaeig.cpp
src/gromacs/gmxana/gmx_analyze.cpp
src/gromacs/gmxana/gmx_enemat.cpp
src/gromacs/gmxana/gmx_saltbr.cpp
src/gromacs/gmxpreprocess/insert_molecules.cpp
src/gromacs/gmxpreprocess/pdb2gmx.cpp
src/gromacs/math/densityfit.h
src/gromacs/options/basicoptions.h
src/gromacs/options/tests/optionsassigner.cpp
src/gromacs/options/tests/refdata/TreeValueSupportTest_SupportsEnumerationArrayOption.xml [moved from src/gromacs/options/tests/refdata/TreeValueSupportTest_SupportsEnumIntOption.xml with 100% similarity]
src/gromacs/options/tests/timeunitmanager.cpp
src/gromacs/options/tests/treesupport.cpp
src/gromacs/options/timeunitmanager.cpp
src/gromacs/options/timeunitmanager.h
src/gromacs/selection/compiler.cpp
src/gromacs/selection/selectioncollection.cpp
src/gromacs/selection/selectioncollection_impl.h
src/gromacs/trajectoryanalysis/analysissettings_impl.h
src/gromacs/trajectoryanalysis/modules/angle.cpp
src/gromacs/trajectoryanalysis/modules/pairdist.cpp
src/gromacs/trajectoryanalysis/modules/rdf.cpp
src/gromacs/trajectoryanalysis/modules/select.cpp
src/gromacs/trajectoryanalysis/runnercommon.cpp
src/gromacs/trajectoryanalysis/tests/refdata/TrajectoryAnalysisCommandLineRunnerTest_WritesHelp.xml
src/programs/mdrun/nonbonded_bench.cpp
src/testutils/refdata.cpp
src/testutils/refdata.h
src/testutils/tests/interactivetest.cpp
src/testutils/tests/refdata_tests.cpp
src/testutils/tests/xvgtest_tests.cpp

index 1ddcd43cb82ffafbec9e0025c7ac0aecd2c07365..9d18cd01862a14cdeb3f69a7bcbdc730932d5f05 100644 (file)
@@ -764,12 +764,9 @@ bool rewrite_tprfile(const std::string& inFile, const std::string& outFile, doub
 
     /* set program name, command line, and default values for output options */
     gmx_output_env_t* oenv;
-    gmx::TimeUnit     timeUnit = gmx::TimeUnit_Default;
+    gmx::TimeUnit     timeUnit = gmx::TimeUnit::Default;
     bool              bView{ false }; // argument that says we don't want to view graphs.
-    int               xvgFormat{ 0 };
-    output_env_init(&oenv, gmx::getProgramContext(),
-                    static_cast<time_unit_t>(timeUnit + 1), // NOLINT(misc-misplaced-widening-cast)
-                    bView, static_cast<xvg_format_t>(xvgFormat + 1), 0);
+    output_env_init(&oenv, gmx::getProgramContext(), timeUnit, bView, XvgFormat::Xmgrace, 0);
 
     double run_t = irInstance.init_step * irInstance.delta_t + irInstance.init_t;
 
index 573dbd47043e9556739c781fdf9dd8106f3401dc..0ea52a0b8d054a779253b09c46c96b608c29a7f8 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 #include "gromacs/utility/stringutil.h"
 #include "gromacs/utility/unique_cptr.h"
 
-namespace
-{
-
-//! Enum values for plot formats.
-const char* const g_plotFormats[] = { "none", "xmgrace", "xmgr" };
-
-} // namespace
-
 namespace gmx
 {
 
@@ -82,8 +74,8 @@ namespace gmx
 
 AnalysisDataPlotSettings::AnalysisDataPlotSettings() :
     selections_(nullptr),
-    timeUnit_(TimeUnit_Default),
-    plotFormat_(1)
+    timeUnit_(TimeUnit::Default),
+    plotFormat_(XvgFormat::Xmgrace)
 {
 }
 
@@ -92,11 +84,18 @@ void AnalysisDataPlotSettings::setSelectionCollection(const SelectionCollection*
     selections_ = selections;
 }
 
+/*! \brief Names for XvgFormat
+ *
+ * Technically this duplicates a definition in pargs.cpp for legacy
+ * support code, but as the latter will go away and the alternatives
+ * are ugly, the duplication is acceptable. */
+const gmx::EnumerationArray<XvgFormat, const char*> c_xvgFormatNames = { { "xmgrace", "xmgr",
+                                                                           "none" } };
 
 void AnalysisDataPlotSettings::initOptions(IOptionsContainer* options)
 {
     options->addOption(
-            EnumIntOption("xvg").enumValue(g_plotFormats).store(&plotFormat_).description("Plot formatting"));
+            EnumOption<XvgFormat>("xvg").enumValue(c_xvgFormatNames).store(&plotFormat_).description("Plot formatting"));
 }
 
 
@@ -308,18 +307,15 @@ void AbstractPlotModule::dataStarted(AbstractAnalysisData* /* data */)
         }
         else
         {
-            // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
-            time_unit_t       time_unit = static_cast<time_unit_t>(impl_->settings_.timeUnit() + 1);
-            xvg_format_t      xvg_format = (impl_->settings_.plotFormat() > 0
-                                               ? static_cast<xvg_format_t>(impl_->settings_.plotFormat())
-                                               : exvgNONE);
+            const TimeUnit    timeUnit  = impl_->settings_.timeUnit();
+            const XvgFormat   xvgFormat = impl_->settings_.plotFormat();
             gmx_output_env_t* oenv;
-            output_env_init(&oenv, getProgramContext(), time_unit, FALSE, xvg_format, 0);
+            output_env_init(&oenv, getProgramContext(), timeUnit, FALSE, xvgFormat, 0);
             const unique_cptr<gmx_output_env_t, output_env_done> oenvGuard(oenv);
             impl_->fp_ = xvgropen(impl_->filename_.c_str(), impl_->title_.c_str(), impl_->xlabel_,
                                   impl_->ylabel_, oenv);
             const SelectionCollection* selections = impl_->settings_.selectionCollection();
-            if (selections != nullptr && output_env_get_xvg_format(oenv) != exvgNONE)
+            if (selections != nullptr && output_env_get_xvg_format(oenv) != XvgFormat::None)
             {
                 selections->printXvgrInfo(impl_->fp_);
             }
index 359f066f19eb2ee445e4f12271a2a8844f7237d3..7064a49c22567d8f26d717a42d1422ecf29ea109 100644 (file)
@@ -51,6 +51,8 @@
 #include "gromacs/options/timeunitmanager.h"
 #include "gromacs/utility/classhelpers.h"
 
+enum class XvgFormat : int;
+
 namespace gmx
 {
 
@@ -76,10 +78,8 @@ public:
     TimeUnit timeUnit() const { return timeUnit_; }
     /*! \brief
      * Returns the plot format.
-     *
-     * \todo Use a proper enum.
      */
-    int plotFormat() const { return plotFormat_; }
+    XvgFormat plotFormat() const { return plotFormat_; }
 
     /*! \brief
      * Set selection collection to print as comments into the output.
@@ -111,7 +111,7 @@ public:
 private:
     const SelectionCollection* selections_;
     TimeUnit                   timeUnit_;
-    int                        plotFormat_;
+    XvgFormat                  plotFormat_;
 };
 
 /*! \brief
index e3f7f28ffb315f2244d541a0e3d59cdff9234b5a..9b32472cf56bca2cd9d4c7f6b19c1f4f5b1f7e96 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -57,7 +57,7 @@ namespace gmx
 /*! \brief
  * The methods that determine how amplitudes are spread on a grid in density guided simulations.
  */
-enum class DensityFittingAmplitudeMethod
+enum class DensityFittingAmplitudeMethod : int
 {
     Unity,  //!< same spread amplitude, unity, for all atoms
     Mass,   //!< atom mass is the spread amplitude
@@ -65,11 +65,6 @@ enum class DensityFittingAmplitudeMethod
     Count
 };
 
-//! The names of the methods to determine the amplitude of the atoms to be spread on a grid
-const EnumerationArray<DensityFittingAmplitudeMethod, const char* const> c_densityFittingAmplitudeMethodNames = {
-    { "unity", "mass", "charge" }
-};
-
 class DensityFittingAmplitudeLookupImpl;
 
 /*! \internal \brief Class that translates atom properties into amplitudes.
index 5a1a01d1beb67d9336228d67106ce3f20f629a6b..29b69cbbeced09d4fd6c42324c8a7247b8b4fd8d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -48,6 +48,7 @@
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/optionsection.h"
 #include "gromacs/selection/indexutil.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/keyvaluetreebuilder.h"
 #include "gromacs/utility/keyvaluetreetransform.h"
@@ -147,6 +148,15 @@ void DensityFittingOptions::initMdpTransform(IKeyValueTreeTransformRules* rules)
                                                c_adaptiveForceScalingTimeConstantTag_);
 }
 
+//! Name the methods that may be used to evaluate similarity between densities
+static const EnumerationArray<DensitySimilarityMeasureMethod, const char*> c_densitySimilarityMeasureMethodNames = {
+    { "inner-product", "relative-entropy", "cross-correlation" }
+};
+//! The names of the methods to determine the amplitude of the atoms to be spread on a grid
+static const EnumerationArray<DensityFittingAmplitudeMethod, const char*> c_densityFittingAmplitudeMethodNames = {
+    { "unity", "mass", "charge" }
+};
+
 void DensityFittingOptions::buildMdpOutput(KeyValueTreeObjectBuilder* builder) const
 {
 
@@ -208,11 +218,11 @@ void DensityFittingOptions::initMdpOptions(IOptionsContainerWithSections* option
     section.addOption(StringOption(c_groupTag_.c_str()).store(&groupString_));
 
     section.addOption(EnumOption<DensitySimilarityMeasureMethod>(c_similarityMeasureTag_.c_str())
-                              .enumValue(c_densitySimilarityMeasureMethodNames.m_elements)
+                              .enumValue(c_densitySimilarityMeasureMethodNames)
                               .store(&parameters_.similarityMeasureMethod_));
 
     section.addOption(EnumOption<DensityFittingAmplitudeMethod>(c_amplitudeMethodTag_.c_str())
-                              .enumValue(c_densityFittingAmplitudeMethodNames.m_elements)
+                              .enumValue(c_densityFittingAmplitudeMethodNames)
                               .store(&parameters_.amplitudeLookupMethod_));
 
     section.addOption(RealOption(c_forceConstantTag_.c_str()).store(&parameters_.forceConstant_));
index db4f40e3460cb62952cf6420f0c1a733b58c0aa3..1b4f6a8c523a994490fca7a4e8179a6369419bf8 100644 (file)
@@ -59,6 +59,7 @@
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/basenetwork.h"
 #include "gromacs/utility/classhelpers.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/gmxassert.h"
@@ -187,29 +188,30 @@ namespace gmx
 namespace
 {
 
-/*! \brief
- * Returns the index of the default xvg format.
+//! Names for XvgFormat
+const gmx::EnumerationArray<XvgFormat, const char*> c_xvgFormatNames = { { "xmgrace", "xmgr",
+                                                                           "none" } };
+
+/*! \brief Returns the default xvg format, as modified by GMX_VIEW_XVG
+ * if that environment variable is set.
  *
  * \ingroup module_commandline
  */
-int getDefaultXvgFormat(gmx::ArrayRef<const char* const> xvgFormats)
+XvgFormat getDefaultXvgFormat()
 {
     const char* const select = getenv("GMX_VIEW_XVG");
     if (select != nullptr)
     {
-        ArrayRef<const char* const>::const_iterator i =
-                std::find(xvgFormats.begin(), xvgFormats.end(), std::string(select));
-        if (i != xvgFormats.end())
-        {
-            return std::distance(xvgFormats.begin(), i);
-        }
-        else
+        for (XvgFormat c : keysOf(c_xvgFormatNames))
         {
-            return exvgNONE - 1;
+            if (std::strcmp(select, c_xvgFormatNames[c]) == 0)
+            {
+                return c;
+            }
         }
+        return XvgFormat::None;
     }
-    /* The default is the first option */
-    return 0;
+    return XvgFormat::Xmgrace;
 }
 
 /*! \brief
@@ -387,8 +389,13 @@ void OptionsAdapter::pargsToOptions(Options* options, t_pargs* pa)
             return;
         case etENUM:
         {
+            // TODO This is the only use of LegacyEnumOption. It
+            // exists to support dozens of analysis tools use that
+            // don't make sense to fix without either test coverage or
+            // automated refactoring. No new uses of LegacyEnumOption
+            // should be made.
             const int defaultIndex = (pa->u.c[0] != nullptr ? nenum(pa->u.c) - 1 : 0);
-            data.optionInfo        = options->addOption(EnumIntOption(name)
+            data.optionInfo        = options->addOption(LegacyEnumOption<int>(name)
                                                          .store(&data.enumIndex)
                                                          .defaultValue(defaultIndex)
                                                          .enumValueFromNullTerminatedArray(pa->u.c + 1)
@@ -455,9 +462,6 @@ gmx_bool parse_common_args(int*               argc,
                            const char**       bugs,
                            gmx_output_env_t** oenv)
 {
-    /* This array should match the order of the enum in oenv.h */
-    const char* const xvg_formats[] = { "xmgrace", "xmgr", "none" };
-
     // Lambda function to test the (local) Flags parameter against a bit mask.
     auto isFlagSet = [Flags](unsigned long bits) { return (Flags & bits) == bits; };
 
@@ -465,8 +469,7 @@ gmx_bool parse_common_args(int*               argc,
     {
         double                         tbegin = 0.0, tend = 0.0, tdelta = 0.0;
         bool                           bBeginTimeSet = false, bEndTimeSet = false, bDtSet = false;
-        bool                           bView     = false;
-        int                            xvgFormat = 0;
+        bool                           bView = false;
         gmx::OptionsAdapter            adapter(*argc, argv);
         gmx::Options                   options;
         gmx::OptionsBehaviorCollection behaviors(&options);
@@ -494,7 +497,7 @@ gmx_bool parse_common_args(int*               argc,
             options.addOption(gmx::DoubleOption("dt").store(&tdelta).storeIsSet(&bDtSet).timeValue().description(
                     "Only use frame when t MOD dt = first time (default unit %t)"));
         }
-        gmx::TimeUnit timeUnit = gmx::TimeUnit_Default;
+        gmx::TimeUnit timeUnit = gmx::TimeUnit::Default;
         if (isFlagSet(PCA_TIME_UNIT))
         {
             std::shared_ptr<gmx::TimeUnitBehavior> timeUnitBehavior(new gmx::TimeUnitBehavior());
@@ -515,11 +518,13 @@ gmx_bool parse_common_args(int*               argc,
         {
             bXvgr = bXvgr || (fnm[i].ftp == efXVG);
         }
-        xvgFormat = gmx::getDefaultXvgFormat(xvg_formats);
+        XvgFormat xvgFormat = gmx::getDefaultXvgFormat();
         if (bXvgr)
         {
-            options.addOption(
-                    gmx::EnumIntOption("xvg").enumValue(xvg_formats).store(&xvgFormat).description("xvg plot formatting"));
+            options.addOption(gmx::EnumOption<XvgFormat>("xvg")
+                                      .enumValue(gmx::c_xvgFormatNames)
+                                      .store(&xvgFormat)
+                                      .description("xvg plot formatting"));
         }
 
         /* Now append the program specific arguments */
@@ -555,8 +560,7 @@ gmx_bool parse_common_args(int*               argc,
 
         /* set program name, command line, and default values for output options */
         // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
-        output_env_init(oenv, gmx::getProgramContext(), static_cast<time_unit_t>(timeUnit + 1),
-                        bView, static_cast<xvg_format_t>(xvgFormat + 1), 0);
+        output_env_init(oenv, gmx::getProgramContext(), timeUnit, bView, xvgFormat, 0);
 
         /* Extract Time info from arguments */
         if (bBeginTimeSet)
index 8fdcece7e4faa24b1565037dbded7cef93331aba..c8dd3e9f28191149d126b22d041ccd7ff19581d7 100644 (file)
@@ -58,6 +58,7 @@
 #include "gromacs/options/filenameoption.h"
 #include "gromacs/options/options.h"
 #include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/stringstream.h"
 #include "gromacs/utility/textwriter.h"
 
@@ -114,10 +115,19 @@ TEST_F(CommandLineHelpWriterTest, HandlesOptionTypes)
     options.addOption(DoubleOption("time").description("Time option (%t)").timeValue().defaultValue(10.0));
     options.addOption(StringOption("string").description("String option").defaultValue("test"));
     const char* const enumValues[] = { "no", "opt1", "opt2" };
+    enum class TestEnum : int
+    {
+        No,
+        Opt1,
+        Opt2,
+        Count
+    };
+    const gmx::EnumerationArray<TestEnum, const char*> testEnumNames = { { "no", "opt1", "opt2" } };
+
     options.addOption(
             StringOption("enum").description("Enum option").enumValue(enumValues).defaultEnumIndex(0));
     options.addOption(
-            EnumIntOption("ienum").description("Enum option").enumValue(enumValues).defaultValue(1));
+            EnumOption<TestEnum>("ienum").description("Enum option").enumValue(testEnumNames).defaultValue(TestEnum::Opt1));
 
     std::string filename;
     options.addOption(FileNameOption("f")
@@ -153,10 +163,11 @@ TEST_F(CommandLineHelpWriterTest, HandlesOptionTypes)
 }
 
 //! Enum value for testing.
-enum TestEnum
+enum class TestEnum : int
 {
-    eFoo,
-    eBar
+    Foo,
+    Bar,
+    Count
 };
 
 /*
@@ -183,8 +194,8 @@ TEST_F(CommandLineHelpWriterTest, HandlesDefaultValuesFromVariables)
     svalues.emplace_back("foo");
     options.addOption(StringOption("str").description("String option").storeVector(&svalues).multiValue());
 
-    TestEnum          evalue    = eBar;
-    const char* const allowed[] = { "foo", "bar" };
+    TestEnum                                           evalue  = TestEnum::Bar;
+    const gmx::EnumerationArray<TestEnum, const char*> allowed = { { "foo", "bar" } };
     options.addOption(
             EnumOption<TestEnum>("enum").description("Enum option").enumValue(allowed).store(&evalue));
 
index ecd2d4652ca6cf84047176841c589e493bbff845..b1b10033b34263e71d7728c7642b8a48ff17925b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -138,14 +138,13 @@ inline unsigned long convertFlag(CoordinateFileFlags flag)
 }
 
 //! Enum class for setting basic flags in a t_trxframe
-enum class ChangeSettingType
+enum class ChangeSettingType : int
 {
     PreservedIfPresent,
     Always,
-    Never
+    Never,
+    Count
 };
-//! Mapping for enums from \ref ChangeSettingType.
-const char* const cChangeSettingTypeEnum[] = { "preserved-if-present", "always", "never" };
 
 //! Enum class for t_atoms settings
 enum class ChangeAtomsType
@@ -153,21 +152,17 @@ enum class ChangeAtomsType
     PreservedIfPresent,
     AlwaysFromStructure,
     Never,
-    Always
+    Always,
+    Count
 };
 
-//! Mapping for enums from \ref ChangeAtomsType.
-const char* const cChangeAtomsTypeEnum[] = { "preserved-if-present", "always-from-structure",
-                                             "never", "always" };
-
 //! Enum class for setting fields new or not.
 enum class ChangeFrameInfoType
 {
     PreservedIfPresent,
-    Always
+    Always,
+    Count
 };
-//! Mapping for enums from \ref ChangeFrameInfoType.
-const char* const cChangeFrameInfoTypeEnum[] = { "preserved-if-present", "always" };
 
 //! Enum class for setting frame time from user input.
 enum class ChangeFrameTimeType
@@ -175,14 +170,10 @@ enum class ChangeFrameTimeType
     PreservedIfPresent,
     StartTime,
     TimeStep,
-    Both
+    Both,
+    Count
 };
 
-//! Mapping for values from \ref ChangeFrameTimeType.
-const char* const cChangeFrameTimeTypeEnum[] = { "preserved-if-present", "starttime", "timestep",
-                                                 "both" };
-
-
 } // namespace gmx
 
 #endif
index 71757b51d1bf2c0f53c1a7372015e5e822a05fb8..dc3f8a830a33d2da0a13900923f0837cffdfdf68 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/filenameoption.h"
 #include "gromacs/options/ioptionscontainer.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/exceptions.h"
 
 namespace gmx
 {
 
+//! Mapping for enums from \ref ChangeSettingType.
+static const EnumerationArray<ChangeSettingType, const char*> c_changeSettingTypeNames = {
+    { "preserved-if-present", "always", "never" }
+};
+//! Mapping for enums from \ref ChangeAtomsType.
+static const EnumerationArray<ChangeAtomsType, const char*> c_changeAtomsTypeNames = {
+    { "preserved-if-present", "always-from-structure", "never", "always" }
+};
+/* Currently unused
+//! Mapping for enums from \ref ChangeFrameInfoType.
+static const EnumerationArray<ChangeFrameInfoType, const char*> c_changeFrameInfoTypeNames = { {
+"preserved-if-present", "always" } };
+//! Mapping for values from \ref ChangeFrameTimeType.
+static const EnumerationArray<ChangeFrameTimeType, const char*> c_changeFrameTimeTypeNames = { {
+"preserved-if-present", "starttime", "timestep", "both" } };
+*/
+
 void OutputRequirementOptionDirector::initOptions(IOptionsContainer* options)
 {
     options->addOption(EnumOption<ChangeSettingType>("vel")
-                               .enumValue(cChangeSettingTypeEnum)
+                               .enumValue(c_changeSettingTypeNames)
                                .store(&velocity_)
                                .description("Save velocities from frame if possible"));
     options->addOption(EnumOption<ChangeSettingType>("force")
-                               .enumValue(cChangeSettingTypeEnum)
+                               .enumValue(c_changeSettingTypeNames)
                                .store(&force_)
                                .description("Save forces from frame if possible"));
     options->addOption(
-            EnumOption<ChangeAtomsType>("atoms").enumValue(cChangeAtomsTypeEnum).store(&atoms_).description("Decide on providing new atom information from topology or using current frame atom information"));
+            EnumOption<ChangeAtomsType>("atoms").enumValue(c_changeAtomsTypeNames).store(&atoms_).description("Decide on providing new atom information from topology or using current frame atom information"));
     options->addOption(IntegerOption("precision")
                                .store(&prec_)
                                .defaultValue(prec_)
index 8f19e66c225aeb8f1c9d51992c7e79d47aea2356..0c99fa191a521704831fc02f86b81c540e23b968 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "oenv.h"
 
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/programcontext.h"
 #include "gromacs/utility/smalloc.h"
@@ -48,9 +49,9 @@ struct gmx_output_env_t
 {
     explicit gmx_output_env_t(const gmx::IProgramContext& context) :
         programContext(context),
-        time_unit(time_ps),
+        timeUnit(gmx::TimeUnit::Picoseconds),
         view(FALSE),
-        xvg_format(exvgNONE),
+        xvgFormat(XvgFormat::None),
         verbosity(0),
         trajectory_io_verbosity(0)
     {
@@ -59,12 +60,12 @@ struct gmx_output_env_t
 
     const gmx::IProgramContext& programContext;
 
-    /* the time unit, enum defined in oenv.h */
-    time_unit_t time_unit;
+    /* the time unit, enum defined in timeunitmanager.h */
+    gmx::TimeUnit timeUnit;
     /* view of file requested */
     gmx_bool view;
     /* xvg output format, enum defined in oenv.h */
-    xvg_format_t xvg_format;
+    XvgFormat xvgFormat;
     /* The level of verbosity for this program */
     int verbosity;
     /* The level of verbosity during trajectory I/O. Default=1, quiet=0. */
@@ -81,31 +82,36 @@ struct gmx_output_env_t
  ******************************************************************/
 
 /* read only time names */
-/* These must correspond to the time units type time_unit_t in oenv.h */
-static const real  timefactors[]     = { real(0),    real(1e3),  real(1),     real(1e-3),
-                                    real(1e-6), real(1e-9), real(1e-12), real(0) };
-static const real  timeinvfactors[]  = { real(0),   real(1e-3), real(1),    real(1e3),
-                                       real(1e6), real(1e9),  real(1e12), real(0) };
-static const char* time_units_str[]  = { nullptr, "fs", "ps", "ns", "us", "\\mus", "ms", "s" };
-static const char* time_units_xvgr[] = { nullptr, "fs", "ps", "ns", "ms", "s", nullptr };
+static const gmx::EnumerationArray<gmx::TimeUnit, real> c_picosecondsInTimeUnit = {
+    { real(1e3), real(1), real(1e-3), real(1e-6), real(1e-9), real(1e-12) }
+};
+static const gmx::EnumerationArray<gmx::TimeUnit, real> c_timeUnitsInPicoseconds = {
+    { real(1e-3), real(1), real(1e3), real(1e6), real(1e9), real(1e12) }
+};
+static const gmx::EnumerationArray<gmx::TimeUnit, const char*> c_timeUnitNames = {
+    { "fs", "ps", "ns", "us", "ms", "s" }
+};
+static const gmx::EnumerationArray<gmx::TimeUnit, const char*> c_timeUnitNamesForXvgr = {
+    { "fs", "ps", "ns", "\\mus", "ms", "s" }
+};
 
 
 /***** OUTPUT_ENV MEMBER FUNCTIONS ******/
 
 void output_env_init(gmx_output_env_t**          oenvp,
                      const gmx::IProgramContext& context,
-                     time_unit_t                 tmu,
+                     gmx::TimeUnit               tmu,
                      gmx_bool                    view,
-                     xvg_format_t                xvg_format,
+                     XvgFormat                   xvgFormat,
                      int                         verbosity)
 {
     try
     {
         gmx_output_env_t* oenv        = new gmx_output_env_t(context);
         *oenvp                        = oenv;
-        oenv->time_unit               = tmu;
+        oenv->timeUnit                = tmu;
         oenv->view                    = view;
-        oenv->xvg_format              = xvg_format;
+        oenv->xvgFormat               = xvgFormat;
         oenv->verbosity               = verbosity;
         const char* env               = getenv("GMX_TRAJECTORY_IO_VERBOSITY");
         oenv->trajectory_io_verbosity = (env != nullptr ? strtol(env, nullptr, 10) : 1);
@@ -141,40 +147,38 @@ int output_env_get_trajectory_io_verbosity(const gmx_output_env_t* oenv)
 
 std::string output_env_get_time_unit(const gmx_output_env_t* oenv)
 {
-    return time_units_str[oenv->time_unit];
+    return c_timeUnitNames[oenv->timeUnit];
 }
 
 std::string output_env_get_time_label(const gmx_output_env_t* oenv)
 {
-    return gmx::formatString(
-            "Time (%s)", time_units_str[oenv->time_unit] ? time_units_str[oenv->time_unit] : "ps");
+    return gmx::formatString("Time (%s)", c_timeUnitNames[oenv->timeUnit]);
 }
 
 std::string output_env_get_xvgr_tlabel(const gmx_output_env_t* oenv)
 {
-    return gmx::formatString(
-            "Time (%s)", time_units_xvgr[oenv->time_unit] ? time_units_xvgr[oenv->time_unit] : "ps");
+    return gmx::formatString("Time (%s)", c_timeUnitNamesForXvgr[oenv->timeUnit]);
 }
 
 real output_env_get_time_factor(const gmx_output_env_t* oenv)
 {
-    return timefactors[oenv->time_unit];
+    return c_picosecondsInTimeUnit[oenv->timeUnit];
 }
 
 real output_env_get_time_invfactor(const gmx_output_env_t* oenv)
 {
-    return timeinvfactors[oenv->time_unit];
+    return c_timeUnitsInPicoseconds[oenv->timeUnit];
 }
 
 real output_env_conv_time(const gmx_output_env_t* oenv, real time)
 {
-    return time * timefactors[oenv->time_unit];
+    return time * c_picosecondsInTimeUnit[oenv->timeUnit];
 }
 
 void output_env_conv_times(const gmx_output_env_t* oenv, int n, real* time)
 {
     int    i;
-    double fact = timefactors[oenv->time_unit];
+    double fact = c_picosecondsInTimeUnit[oenv->timeUnit];
 
     if (fact != 1.)
     {
@@ -190,9 +194,9 @@ gmx_bool output_env_get_view(const gmx_output_env_t* oenv)
     return oenv->view;
 }
 
-xvg_format_t output_env_get_xvg_format(const gmx_output_env_t* oenv)
+XvgFormat output_env_get_xvg_format(const gmx_output_env_t* oenv)
 {
-    return oenv->xvg_format;
+    return oenv->xvgFormat;
 }
 
 const char* output_env_get_program_display_name(const gmx_output_env_t* oenv)
index 0624e1d77ba51d894203224b07108167cb0e2bd5..586a3916b54688ebdd909e55dd571b3e4f8811c9 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2019,2020, 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.
@@ -53,27 +53,37 @@ struct gmx_output_env_t;
    There are still legacy functions for the program name, and the command
    line, but the output_env versions are now preferred.*/
 
-typedef enum
+namespace gmx
 {
-    timeNULL,
-    time_fs,
-    time_ps,
-    time_ns,
-    time_us,
-    time_ms,
-    time_s
-} time_unit_t;
-/* the time units. For the time being, ps means no conversion. */
-
-typedef enum
+
+/*! \brief
+ * Time values for TimeUnitManager and legacy oenv module.
+ *
+ * \inpublicapi
+ */
+enum class TimeUnit : int
 {
-    exvgNULL,
-    exvgXMGRACE,
-    exvgXMGR,
-    exvgNONE
-} xvg_format_t;
-/* the xvg output formattings */
+    Femtoseconds,
+    Picoseconds,
+    Nanoseconds,
+    Microseconds,
+    Milliseconds,
+    Seconds,
+    Count,
+    Default = Picoseconds
+};
+
+} // namespace gmx
 
+//! The xvg output format
+enum class XvgFormat : int
+{
+    // Select,
+    Xmgrace,
+    Xmgr,
+    None,
+    Count
+};
 
 void output_env_init_default(gmx_output_env_t** oenvp);
 /* initialize an output_env structure, with reasonable default settings.
@@ -113,7 +123,7 @@ void output_env_conv_times(const gmx_output_env_t* oenv, int n, real* time);
 gmx_bool output_env_get_view(const gmx_output_env_t* oenv);
 /* Return TRUE when user requested viewing of the file */
 
-xvg_format_t output_env_get_xvg_format(const gmx_output_env_t* oenv);
+XvgFormat output_env_get_xvg_format(const gmx_output_env_t* oenv);
 /* Returns enum (see above) for xvg output formatting */
 
 /*! \brief
@@ -128,9 +138,9 @@ class IProgramContext;
 
 void output_env_init(gmx_output_env_t**          oenvp,
                      const gmx::IProgramContext& context,
-                     time_unit_t                 tmu,
+                     gmx::TimeUnit               tmu,
                      gmx_bool                    view,
-                     xvg_format_t                xvg_format,
+                     XvgFormat                   xvgFormat,
                      int                         verbosity);
 /* initialize an output_env structure, setting the command line,
    the default time value a gmx_boolean view that is set to TRUE when the
index 5c31183410b9a7e4501bbe63d02be1dbb543fa62..90e207413752cf361860e2200c801dcea885a15d 100644 (file)
 
 gmx_bool output_env_get_print_xvgr_codes(const gmx_output_env_t* oenv)
 {
-    int xvg_format;
+    XvgFormat xvgFormat = output_env_get_xvg_format(oenv);
 
-    xvg_format = output_env_get_xvg_format(oenv);
-
-    return (xvg_format == exvgXMGRACE || xvg_format == exvgXMGR);
+    return (xvgFormat == XvgFormat::Xmgrace || xvgFormat == XvgFormat::Xmgr);
 }
 
 static char* xvgrstr(const std::string& gmx, const gmx_output_env_t* oenv, char* buf, int buflen)
@@ -73,13 +71,12 @@ static char* xvgrstr(const std::string& gmx, const gmx_output_env_t* oenv, char*
     const char* sym[]  = { "beta",  "chi", "delta", "eta", "lambda", "mu",
                           "omega", "phi", "psi",   "rho", "theta",  nullptr };
     const char  symc[] = { 'b', 'c', 'd', 'h', 'l', 'm', 'w', 'f', 'y', 'r', 'q', '\0' };
-    int         xvgf;
     gmx_bool    bXVGR;
     int         g, b, i;
     char        c;
 
-    xvgf  = output_env_get_xvg_format(oenv);
-    bXVGR = (xvgf == exvgXMGRACE || xvgf == exvgXMGR);
+    XvgFormat xvgf = output_env_get_xvg_format(oenv);
+    bXVGR          = (xvgf == XvgFormat::Xmgrace || xvgf == XvgFormat::Xmgr);
 
     g = 0;
     b = 0;
@@ -146,8 +143,8 @@ static char* xvgrstr(const std::string& gmx, const gmx_output_env_t* oenv, char*
                 /* Backward compatibility for xmgr normal font "\4" */
                 switch (xvgf)
                 {
-                    case exvgXMGRACE: sprintf(buf + b, "%s", "\\f{}"); break;
-                    case exvgXMGR: sprintf(buf + b, "%s", "\\4"); break;
+                    case XvgFormat::Xmgrace: sprintf(buf + b, "%s", "\\f{}"); break;
+                    case XvgFormat::Xmgr: sprintf(buf + b, "%s", "\\4"); break;
                     default: buf[b] = '\0'; break;
                 }
                 g++;
@@ -158,8 +155,8 @@ static char* xvgrstr(const std::string& gmx, const gmx_output_env_t* oenv, char*
                 /* Backward compatibility for xmgr symbol font "\8" */
                 switch (xvgf)
                 {
-                    case exvgXMGRACE: sprintf(buf + b, "%s", "\\x"); break;
-                    case exvgXMGR: sprintf(buf + b, "%s", "\\8"); break;
+                    case XvgFormat::Xmgrace: sprintf(buf + b, "%s", "\\x"); break;
+                    case XvgFormat::Xmgr: sprintf(buf + b, "%s", "\\8"); break;
                     default: buf[b] = '\0'; break;
                 }
                 g++;
@@ -182,8 +179,10 @@ static char* xvgrstr(const std::string& gmx, const gmx_output_env_t* oenv, char*
                     }
                     switch (xvgf)
                     {
-                        case exvgXMGRACE: sprintf(buf + b, "%s%c%s", "\\x", c, "\\f{}"); break;
-                        case exvgXMGR: sprintf(buf + b, "%s%c%s", "\\8", c, "\\4"); break;
+                        case XvgFormat::Xmgrace:
+                            sprintf(buf + b, "%s%c%s", "\\x", c, "\\f{}");
+                            break;
+                        case XvgFormat::Xmgr: sprintf(buf + b, "%s%c%s", "\\8", c, "\\4"); break;
                         default:
                             std::strncat(buf + b, &gmx[g], std::strlen(sym[i]));
                             b += std::strlen(sym[i]);
@@ -247,7 +246,7 @@ void xvgr_header(FILE*                   fp,
         switch (exvg_graph_type)
         {
             case exvggtXNY:
-                if (output_env_get_xvg_format(oenv) == exvgXMGR)
+                if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
                 {
                     fprintf(fp, "@TYPE nxy\n");
                 }
@@ -351,7 +350,7 @@ static void xvgr_legend(FILE* out, int nsets, const T* setname, const gmx_output
         {
             if (!stringIsEmpty(setname[i]))
             {
-                if (output_env_get_xvg_format(oenv) == exvgXMGR)
+                if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
                 {
                     fprintf(out, "@ legend string %d \"%s\"\n", i, xvgrstr(setname[i], oenv, buf, STRLEN));
                 }
@@ -385,7 +384,7 @@ void xvgr_new_dataset(FILE* out, int nr_first, int nsets, const char** setname,
         {
             if (setname[i])
             {
-                if (output_env_get_xvg_format(oenv) == exvgXMGR)
+                if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
                 {
                     fprintf(out, "@ legend string %d \"%s\"\n", i + nr_first,
                             xvgrstr(setname[i], oenv, buf, STRLEN));
index 448640c2d45b7e910ff4ba7b013048971ba9f240..08a5a7419494cff3ce04fc3fb76be897d91d3ebf 100644 (file)
@@ -111,7 +111,7 @@ static void write_xvgr_graphs(const char*             file,
     real  ymin, ymax, xsp, ysp;
 
     out = gmx_ffopen(file, "w");
-    if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
+    if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgrace)
     {
         fprintf(out, "@ autoscale onread none\n");
     }
index 8dd13887554f0f3ab39c0266b6ec9e7632e7c45e..75888d57fc5093e1170fe6c57adef84baeb375c2 100644 (file)
@@ -631,13 +631,13 @@ static void estimate_error(const char*             eefile,
             tau2 = fitparm[2];
         }
         fprintf(stdout, "Set %3d:  err.est. %g  a %g  tau1 %g  tau2 %g\n", s + 1, ee, a, tau1, tau2);
-        if (output_env_get_xvg_format(oenv) == exvgXMGR)
+        if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
         {
             fprintf(fp, "@ legend string %d \"av %f\"\n", 2 * s, av[s]);
             fprintf(fp, "@ legend string %d \"ee %6g\"\n", 2 * s + 1,
                     optimal_error_estimate(sig[s], fitparm, n * dt));
         }
-        else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
+        else if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgrace)
         {
             fprintf(fp, "@ s%d legend \"av %f\"\n", 2 * s, av[s]);
             fprintf(fp, "@ s%d legend \"ee %6g\"\n", 2 * s + 1,
index ba05ed46fabf91cebcccee30ce5d57980b325601..25b5db751300e6417cf675caed0d6de5476311a6 100644 (file)
@@ -538,7 +538,7 @@ int gmx_enemat(int argc, char* argv[])
         if (output_env_get_print_xvgr_codes(oenv))
         {
             char str1[STRLEN], str2[STRLEN];
-            if (output_env_get_xvg_format(oenv) == exvgXMGR)
+            if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
             {
                 sprintf(str1, "@ legend string ");
                 sprintf(str2, " ");
index e82a4a365f4a98a943bd3320dd93adef36a0411f..46faac366874ede6ebfe40754e4f519d5ef9ea7c 100644 (file)
@@ -255,11 +255,11 @@ int gmx_saltbr(int argc, char* argv[])
                     }
                     else
                     {
-                        if (output_env_get_xvg_format(oenv) == exvgXMGR)
+                        if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
                         {
                             fprintf(out[nnn], "@ legend string %d \"%s\"\n", nset[nnn], buf);
                         }
-                        else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
+                        else if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgrace)
                         {
                             fprintf(out[nnn], "@ s%d legend \"%s\"\n", nset[nnn], buf);
                         }
index 6afabf9da4a36ffb54c28906c3a28569e70cda7b..94cde0b968457025ee9637f91b9441495cb9b310 100644 (file)
@@ -73,6 +73,7 @@
 #include "gromacs/topology/topology.h"
 #include "gromacs/trajectory/trajectoryframe.h"
 #include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/smalloc.h"
 using gmx::RVec;
 
 /* enum for random rotations of inserted solutes */
-enum RotationType
+enum class RotationType : int
 {
-    en_rotXYZ,
-    en_rotZ,
-    en_rotNone
+    XYZ,
+    Z,
+    None,
+    Count
 };
-const char* const cRotationEnum[] = { "xyz", "z", "none" };
+static const gmx::EnumerationArray<RotationType, const char*> c_rotationTypeNames = { { "xyz", "z",
+                                                                                        "none" } };
 
 static void center_molecule(gmx::ArrayRef<RVec> x)
 {
@@ -114,18 +117,19 @@ static void generate_trial_conf(gmx::ArrayRef<RVec>       xin,
     real alfa = 0.0, beta = 0.0, gamma = 0.0;
     switch (enum_rot)
     {
-        case en_rotXYZ:
+        case RotationType::XYZ:
             alfa  = dist(*rng);
             beta  = dist(*rng);
             gamma = dist(*rng);
             break;
-        case en_rotZ:
+        case RotationType::Z:
             alfa = beta = 0.;
             gamma       = dist(*rng);
             break;
-        case en_rotNone: alfa = beta = gamma = 0.; break;
+        case RotationType::None: alfa = beta = gamma = 0.; break;
+        default: GMX_THROW(gmx::InternalError("Invalid RotationType"));
     }
-    if (enum_rot == en_rotXYZ || enum_rot == en_rotZ)
+    if (enum_rot == RotationType::XYZ || enum_rot == RotationType::Z)
     {
         rotate_conf(xout->size(), as_rvec_array(xout->data()), nullptr, alfa, beta, gamma);
     }
@@ -332,7 +336,7 @@ public:
         seed_(0),
         defaultDistance_(0.105),
         scaleFactor_(0.57),
-        enumRot_(en_rotXYZ)
+        enumRot_(RotationType::XYZ)
     {
         clear_rvec(newBox_);
         clear_rvec(deltaR_);
@@ -473,7 +477,7 @@ void InsertMolecules::initOptions(IOptionsContainer* options, ICommandLineOption
     options->addOption(RealOption("dr").vector().store(deltaR_).description(
             "Allowed displacement in x/y/z from positions in [TT]-ip[tt] file"));
     options->addOption(EnumOption<RotationType>("rot")
-                               .enumValue(cRotationEnum)
+                               .enumValue(c_rotationTypeNames)
                                .store(&enumRot_)
                                .description("Rotate inserted molecules randomly"));
 }
index 8f1a716f58fa4206c27ef7f7a82d594af0e56b41..171db584ce42c131032848b49bad725999ddf1f7 100644 (file)
@@ -1125,25 +1125,27 @@ static void find_nc_ter(t_atoms* pdba, int r0, int r1, int* r_start, int* r_end,
     }
 }
 
-/* enum for chain separation */
-enum ChainSepType
+enum class ChainSeparationType : int
 {
-    enChainSep_id_or_ter,
-    enChainSep_id_and_ter,
-    enChainSep_ter,
-    enChainSep_id,
-    enChainSep_interactive
+    IdOrTer,
+    IdAndTer,
+    Ter,
+    Id,
+    Interactive,
+    Count
 };
-static const char* ChainSepEnum[]       = { "id_or_ter", "id_and_ter", "ter", "id", "interactive" };
-static const char* ChainSepInfoString[] = {
-    "Splitting chemical chains based on TER records or chain id changing.\n",
-    "Splitting chemical chains based on TER records and chain id changing.\n",
-    "Splitting chemical chains based on TER records only (ignoring chain id).\n",
-    "Splitting chemical chains based on changing chain id only (ignoring TER records).\n",
-    "Splitting chemical chains interactively.\n"
+static const gmx::EnumerationArray<ChainSeparationType, const char*> c_chainSeparationTypeNames = {
+    { "id_or_ter", "id_and_ter", "ter", "id", "interactive" }
+};
+static const gmx::EnumerationArray<ChainSeparationType, const char*> c_chainSeparationTypeNotificationMessages = {
+    { "Splitting chemical chains based on TER records or chain id changing.\n",
+      "Splitting chemical chains based on TER records and chain id changing.\n",
+      "Splitting chemical chains based on TER records only (ignoring chain id).\n",
+      "Splitting chemical chains based on changing chain id only (ignoring TER records).\n",
+      "Splitting chemical chains interactively.\n" }
 };
 
-static void modify_chain_numbers(t_atoms* pdba, ChainSepType enumChainSep, const gmx::MDLogger& logger)
+static void modify_chain_numbers(t_atoms* pdba, ChainSeparationType chainSeparation, const gmx::MDLogger& logger)
 {
     int         i;
     char        old_prev_chainid;
@@ -1165,7 +1167,7 @@ static void modify_chain_numbers(t_atoms* pdba, ChainSepType enumChainSep, const
     char        this_chainid;
 
     /* The default chain enumeration is based on TER records only */
-    printf("%s", ChainSepInfoString[enumChainSep]);
+    printf("%s", c_chainSeparationTypeNotificationMessages[chainSeparation]);
 
     old_prev_chainid  = '?';
     old_prev_chainnum = -1;
@@ -1195,36 +1197,36 @@ static void modify_chain_numbers(t_atoms* pdba, ChainSepType enumChainSep, const
         this_resnum   = ri->nr;
         this_chainid  = ri->chainid;
 
-        switch (enumChainSep)
+        switch (chainSeparation)
         {
-            case enChainSep_id_or_ter:
+            case ChainSeparationType::IdOrTer:
                 if (old_this_chainid != old_prev_chainid || old_this_chainnum != old_prev_chainnum)
                 {
                     new_chainnum++;
                 }
                 break;
 
-            case enChainSep_id_and_ter:
+            case ChainSeparationType::IdAndTer:
                 if (old_this_chainid != old_prev_chainid && old_this_chainnum != old_prev_chainnum)
                 {
                     new_chainnum++;
                 }
                 break;
 
-            case enChainSep_id:
+            case ChainSeparationType::Id:
                 if (old_this_chainid != old_prev_chainid)
                 {
                     new_chainnum++;
                 }
                 break;
 
-            case enChainSep_ter:
+            case ChainSeparationType::Ter:
                 if (old_this_chainnum != old_prev_chainnum)
                 {
                     new_chainnum++;
                 }
                 break;
-            case enChainSep_interactive:
+            case ChainSeparationType::Interactive:
                 if (old_this_chainid != old_prev_chainid || old_this_chainnum != old_prev_chainnum)
                 {
                     if (i > 0)
@@ -1250,7 +1252,8 @@ static void modify_chain_numbers(t_atoms* pdba, ChainSepType enumChainSep, const
                     }
                 }
                 break;
-            default: gmx_fatal(FARGS, "Internal inconsistency - this shouldn't happen...");
+            case ChainSeparationType::Count:
+                gmx_fatal(FARGS, "Internal inconsistency - this shouldn't happen...");
         }
         old_prev_chainid  = old_this_chainid;
         old_prev_chainnum = old_this_chainnum;
@@ -1285,39 +1288,42 @@ struct t_chain
     std::vector<gmx::RVec>              x;
 };
 
-// TODO make all enums into scoped enums
-/* enum for vsites */
-enum VSitesType
+enum class VSitesType : int
 {
-    enVSites_none,
-    enVSites_hydrogens,
-    enVSites_aromatics
+    None,
+    Hydrogens,
+    Aromatics,
+    Count
+};
+static const gmx::EnumerationArray<VSitesType, const char*> c_vsitesTypeNames = {
+    { "none", "hydrogens", "aromatics" }
 };
-static const char* VSitesEnum[] = { "none", "hydrogens", "aromatics" };
 
-/* enum for water model */
-enum WaterType
+enum class WaterType : int
 {
-    enWater_select,
-    enWater_none,
-    enWater_spc,
-    enWater_spce,
-    enWater_tip3p,
-    enWater_tip4p,
-    enWater_tip5p,
-    enWater_tips3p
+    Select,
+    None,
+    Spc,
+    SpcE,
+    Tip3p,
+    Tip4p,
+    Tip5p,
+    Tips3p,
+    Count
+};
+static const gmx::EnumerationArray<WaterType, const char*> c_waterTypeNames = {
+    { "select", "none", "spc", "spce", "tip3p", "tip4p", "tip5p", "tips3p" }
 };
-static const char* WaterEnum[] = { "select", "none",  "spc",   "spce",
-                                   "tip3p",  "tip4p", "tip5p", "tips3p" };
 
-/* enum for merge */
-enum MergeType
+enum class MergeType : int
 {
-    enMerge_no,
-    enMerge_all,
-    enMerge_interactive
+    No,
+    All,
+    Interactive,
+    Count
 };
-static const char* MergeEnum[] = { "no", "all", "interactive" };
+static const gmx::EnumerationArray<MergeType, const char*> c_mergeTypeNames = { { "no", "all",
+                                                                                  "interactive" } };
 
 namespace gmx
 {
@@ -1332,10 +1338,10 @@ public:
         bVsites_(FALSE),
         bPrevWat_(FALSE),
         bVsiteAromatics_(FALSE),
-        enumChainSep_(enChainSep_id_or_ter),
-        enumVSites_(enVSites_none),
-        enumWater_(enWater_select),
-        enumMerge_(enMerge_no),
+        chainSeparation_(ChainSeparationType::IdOrTer),
+        vsitesType_(VSitesType::None),
+        waterType_(WaterType::Select),
+        mergeType_(MergeType::No),
         itp_file_(nullptr),
         mHmult_(0)
     {
@@ -1394,10 +1400,10 @@ private:
     std::string outFile_;
     std::string ff_;
 
-    ChainSepType enumChainSep_;
-    VSitesType   enumVSites_;
-    WaterType    enumWater_;
-    MergeType    enumMerge_;
+    ChainSeparationType chainSeparation_;
+    VSitesType          vsitesType_;
+    WaterType           waterType_;
+    MergeType           mergeType_;
 
     FILE*                          itp_file_;
     char                           forcefield_[STRLEN];
@@ -1532,16 +1538,19 @@ void pdb2gmx::initOptions(IOptionsContainer* options, ICommandLineOptionsModuleS
             RealOption("lb").store(&long_bond_dist_).defaultValue(0.25).hidden().description("Long bond warning distance"));
     options->addOption(
             RealOption("sb").store(&short_bond_dist_).defaultValue(0.05).hidden().description("Short bond warning distance"));
-    options->addOption(
-            EnumOption<ChainSepType>("chainsep").enumValue(ChainSepEnum).store(&enumChainSep_).description("Condition in PDB files when a new chain should be started (adding termini)"));
+    options->addOption(EnumOption<ChainSeparationType>("chainsep")
+                               .enumValue(c_chainSeparationTypeNames)
+                               .store(&chainSeparation_)
+                               .description("Condition in PDB files when a new chain should be "
+                                            "started (adding termini)"));
     options->addOption(EnumOption<MergeType>("merge")
-                               .enumValue(MergeEnum)
-                               .store(&enumMerge_)
+                               .enumValue(c_mergeTypeNames)
+                               .store(&mergeType_)
                                .description("Merge multiple chains into a single [moleculetype]"));
     options->addOption(StringOption("ff").store(&ff_).defaultValue("select").description(
             "Force field, interactive by default. Use [TT]-h[tt] for information."));
     options->addOption(
-            EnumOption<WaterType>("water").store(&enumWater_).enumValue(WaterEnum).description("Water model to use"));
+            EnumOption<WaterType>("water").store(&waterType_).enumValue(c_waterTypeNames).description("Water model to use"));
     options->addOption(BooleanOption("inter").store(&bInter_).defaultValue(false).description(
             "Set the next 8 options to interactive"));
     options->addOption(BooleanOption("ss").store(&bCysMan_).defaultValue(false).description(
@@ -1582,8 +1591,10 @@ void pdb2gmx::initOptions(IOptionsContainer* options, ICommandLineOptionsModuleS
             BooleanOption("v").store(&bVerbose_).defaultValue(false).description("Be slightly more verbose in messages"));
     options->addOption(
             RealOption("posrefc").store(&posre_fc_).defaultValue(1000).description("Force constant for position restraints"));
-    options->addOption(
-            EnumOption<VSitesType>("vsite").store(&enumVSites_).enumValue(VSitesEnum).description("Convert atoms to virtual sites"));
+    options->addOption(EnumOption<VSitesType>("vsite")
+                               .store(&vsitesType_)
+                               .enumValue(c_vsitesTypeNames)
+                               .description("Convert atoms to virtual sites"));
     options->addOption(BooleanOption("heavyh").store(&bHeavyH_).defaultValue(false).description(
             "Make hydrogen atoms heavy"));
     options->addOption(
@@ -1726,24 +1737,24 @@ int pdb2gmx::run()
             .asParagraph()
             .appendTextFormatted("Using the %s force field in directory %s", ffname_, ffdir_);
 
-    choose_watermodel(WaterEnum[enumWater_], ffdir_, &watermodel_, logger);
+    choose_watermodel(c_waterTypeNames[waterType_], ffdir_, &watermodel_, logger);
 
-    switch (enumVSites_)
+    switch (vsitesType_)
     {
-        case enVSites_none:
+        case VSitesType::None:
             bVsites_         = false;
             bVsiteAromatics_ = false;
             break;
-        case enVSites_hydrogens:
+        case VSitesType::Hydrogens:
             bVsites_         = true;
             bVsiteAromatics_ = false;
             break;
-        case enVSites_aromatics:
+        case VSitesType::Aromatics:
             bVsites_         = true;
             bVsiteAromatics_ = true;
             break;
-        default:
-            gmx_fatal(FARGS, "Internal inconsistency: VSitesEnum='%s'", VSitesEnum[enumVSites_]);
+        case VSitesType::Count:
+            gmx_fatal(FARGS, "Internal inconsistency: VSitesType='%s'", c_vsitesTypeNames[vsitesType_]);
     } /* end switch */
 
     /* Open the symbol table */
@@ -1812,7 +1823,7 @@ int pdb2gmx::run()
     GMX_LOG(logger.info).asParagraph().appendTextFormatted("Analyzing pdb file");
     int nwaterchain = 0;
 
-    modify_chain_numbers(&pdba_all, enumChainSep_, logger);
+    modify_chain_numbers(&pdba_all, chainSeparation_, logger);
 
     int nchainmerges = 0;
 
@@ -1866,7 +1877,7 @@ int pdb2gmx::run()
             bMerged         = false;
             if (i > 0 && !bWat_)
             {
-                if (!strncmp(MergeEnum[enumMerge_], "int", 3))
+                if (!strncmp(c_mergeTypeNames[mergeType_], "int", 3))
                 {
                     GMX_LOG(logger.info)
                             .asParagraph()
@@ -1885,7 +1896,7 @@ int pdb2gmx::run()
                     }
                     bMerged = (select[0] == 'y');
                 }
-                else if (!strncmp(MergeEnum[enumMerge_], "all", 3))
+                else if (!strncmp(c_mergeTypeNames[mergeType_], "all", 3))
                 {
                     bMerged = true;
                 }
index b3a3eb3f441ccb24f5acc3337c81877186e11c42..246d6610b0e4404ef02475c408f4d7820ac818fd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -45,7 +45,6 @@
 
 #include "gromacs/mdspan/extensions.h"
 #include "gromacs/utility/classhelpers.h"
-#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/real.h"
 
 namespace gmx
@@ -53,7 +52,7 @@ namespace gmx
 /*! \brief
  * The methods that determine how two densities are compared to one another.
  */
-enum class DensitySimilarityMeasureMethod
+enum class DensitySimilarityMeasureMethod : int
 {
     /*! \brief Measure similarity between densities as normalized inner product of their
      * voxel values.
@@ -89,11 +88,6 @@ enum class DensitySimilarityMeasureMethod
     Count,
 };
 
-//! Name the methods that may be used to evaluate similarity between densities
-const EnumerationArray<DensitySimilarityMeasureMethod, const char* const> c_densitySimilarityMeasureMethodNames = {
-    { "inner-product", "relative-entropy", "cross-correlation" }
-};
-
 /* Forward declaration of implementation class outside class to allow
  * choose implementation class during construction of the DensitySimilarityMeasure*/
 class DensitySimilarityMeasureImpl;
index 75d8e2d4549972d01e8c5d0143b75d78bd3debca..65e489568048e64fe1e57bfafef1b514dd2b5159 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -54,6 +54,7 @@
 #include "gromacs/options/abstractoption.h"
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/basedefinitions.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/gmxassert.h"
 
 #include "ivaluestore.h"
@@ -487,35 +488,33 @@ AbstractOptionStorage* createEnumOptionStorage(const AbstractOption& option,
 //! \{
 
 /*! \brief
- * Specifies an option that accepts enumerated string values and writes the
- * selected index into an `enum` variable.
- *
- * \tparam EnumType  Type of the variable that receives the values
- *     (can also be `int`).
- *
- * Examples:
- * \code
-   enum MyEnum { eAtom, eRes, eMol };
-   using gmx::EnumOption;
-   const char * const  allowed[] = { "atom", "residue", "molecule" };
-   MyEnum       value = eAtom; // default value
-   options.addOption(EnumOption<MyEnum>("type").enumValue(allowed).store(&value));
- * \endcode
- *
- * storeCount() is not currently implemented for this option type, and
- * providing multiple default values through an array passed to store() does
- * not work consistently in all cases.
- * In the current implementation, the values of the enum type should correspond
- * to indices in the array passed to enumValue(), i.e., be consencutive
- * starting from zero.  Only values corresponding to valid indices are accepted
- * as parameters to, e.g., defaultValue().  However, other values can be used
- * as the initial value of the variable (`value` in the above example), and
- * those will be preserved if the option is not set.
- *
- * Public methods in this class do not throw.
- *
- * \inpublicapi
- */
+* Specifies an option that accepts an EnumerationArray of string values and writes the
+* selected index into an `enum` variable.
+*
+* \tparam EnumType  DataType of the variable that receives the values
+*
+* Examples:
+* \code
+  enum class MyEnum { Atom, Res, Mol, Count } : int;
+  EnumerationArray<MyEnum, const char *> myEnumNames = { "atom", "residue", "molecule" };
+  MyEnum       value = MyEnum::Atom; // default value
+  options.addOption(EnumOption<MyEnum>("type").enumValue(myEnumNames).store(&value));
+* \endcode
+*
+* storeCount() is not currently implemented for this option type, and
+* providing multiple default values through an array passed to store() does
+* not work consistently in all cases.
+* In the current implementation, the values of the enum type should correspond
+* to indices in the array passed to enumValue(), i.e., be consecutive
+* starting from zero.  Only values corresponding to valid indices are accepted
+* as parameters to, e.g., defaultValue().  However, other values can be used
+* as the initial value of the variable (`value` in the above example), and
+* those will be preserved if the option is not set.
+*
+* Public methods in this class do not throw.
+*
+* \inpublicapi
+*/
 template<typename EnumType>
 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType>>
 {
@@ -533,6 +532,99 @@ public:
     {
     }
 
+    /*! \brief
+     * Sets the option to only accept one of a fixed set of strings.
+     *
+
+     * \param[in] values  Array of strings to accept.
+     *
+     * Also accepts prefixes of the strings; if a prefix matches more than
+     * one of the possible strings, the shortest one is used (in a tie, the
+     * first one is).
+     *
+     * The strings are copied once the option is created.
+     */
+    EnumOption& enumValue(const EnumerationArray<EnumType, const char*>& values)
+    {
+        GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
+        enumValues_      = values.data();
+        enumValuesCount_ = values.size();
+        return MyBase::me();
+    }
+
+private:
+    //! Helper function to convert default values for storage initialization.
+    static int convertToInt(const EnumType* defaultValue)
+    {
+        return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
+    }
+
+    //! Creates a EnumOptionStorage object.
+    AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override
+    {
+        // TODO: Implement storeCount() if necessary.
+        return internal::createEnumOptionStorage(*this, enumValues_, enumValuesCount_,
+                                                 convertToInt(MyBase::defaultValue()),
+                                                 convertToInt(MyBase::defaultValueIfSet()),
+                                                 std::make_unique<internal::EnumIndexStore<EnumType>>(
+                                                         MyBase::store(), MyBase::storeVector()));
+    }
+
+    const char* const* enumValues_;
+    int                enumValuesCount_;
+
+    /*! \brief
+     * Needed to initialize EnumOptionStorage from this class without
+     * otherwise unnecessary accessors.
+     */
+    friend class EnumOptionStorage;
+};
+
+/*! \brief
+* Specifies an option that accepts enumerated string values and writes the
+* selected index into an `enum` variable.
+*
+* \tparam EnumType  Type of the variable that receives the values
+*     (can also be `int`).
+*
+* Examples:
+* \code
+  enum MyEnum { eAtom, eRes, eMol };
+  using gmx::LegacyEnumOption;
+  const char * const  allowed[] = { "atom", "residue", "molecule" };
+  MyEnum       value = eAtom; // default value
+  options.addOption(LegacyEnumOption<MyEnum>("type").enumValue(allowed).store(&value));
+* \endcode
+*
+* Works exactly as EnumOption.
+*
+* This is legacy support for pargsToOptions and can be removed when it
+* is removed.  No new uses of it should be made.
+*
+* Public methods in this class do not throw.
+*
+* \inpublicapi
+*/
+template<typename EnumType>
+class LegacyEnumOption : public OptionTemplate<EnumType, LegacyEnumOption<EnumType>>
+{
+public:
+    //! OptionInfo subclass corresponding to this option type.
+    typedef EnumOptionInfo InfoType;
+
+    // This needs to be duplicated from OptionTemplate because this class
+    // is a template.
+    //! Short-hand for the base class.
+    typedef OptionTemplate<EnumType, LegacyEnumOption<EnumType>> MyBase;
+
+    //! Initializes an option with the given name.
+    explicit LegacyEnumOption(const char* name) :
+        MyBase(name),
+        enumValues_(nullptr),
+        enumValuesCount_(0)
+    {
+    }
+
     /*! \brief
      * Sets the option to only accept one of a fixed set of strings.
      *
@@ -545,7 +637,7 @@ public:
      * The strings are copied once the option is created.
      */
     template<size_t count>
-    EnumOption& enumValue(const char* const (&values)[count])
+    LegacyEnumOption& enumValue(const char* const (&values)[count])
     {
         GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
         enumValues_      = values;
@@ -564,7 +656,7 @@ public:
      *
      * \see enumValue()
      */
-    EnumOption& enumValueFromNullTerminatedArray(const char* const* values)
+    LegacyEnumOption& enumValueFromNullTerminatedArray(const char* const* values)
     {
         GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
         enumValues_      = values;
@@ -573,7 +665,7 @@ public:
     }
 
 private:
-    //! Helper function to convert default values for storate initialization.
+    //! Helper function to convert default values for storage initialization.
     static int convertToInt(const EnumType* defaultValue)
     {
         return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
@@ -600,9 +692,6 @@ private:
     friend class EnumOptionStorage;
 };
 
-//! Shorthand for an enumerated option that stores into an `int` variable.
-typedef EnumOption<int> EnumIntOption;
-
 /*! \brief
  * Wrapper class for accessing boolean option information.
  *
index 9d6d7ca1dc2282e510ee8a83e11542588ddb6c7a..80f917b5a8c1cc11d357f775e1f69cf0fc30613e 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2010-2017, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -876,21 +876,23 @@ TEST(OptionsAssignerStringTest, HandlesEnumDefaultValueFromVector)
  */
 
 //! Enum type for EnumOption tests.
-enum TestEnum
+enum class TestEnum : int
 {
-    etestNone,
-    etestTest,
-    etestValue,
-    etestNR
+    None,
+    Test,
+    Value,
+    Count
 };
+//! Set of allowed values for enum option tests.
+const gmx::EnumerationArray<TestEnum, const char*> c_testEnumNames = { { "none", "test", "value" } };
 
 TEST(OptionsAssignerEnumTest, StoresSingleValue)
 {
     gmx::Options options;
-    TestEnum     value = etestNone;
+    TestEnum     value = TestEnum::None;
     using gmx::EnumOption;
-    ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed)));
-    EXPECT_EQ(etestNone, value);
+    ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames)));
+    EXPECT_EQ(TestEnum::None, value);
 
     gmx::OptionsAssigner assigner(&options);
     EXPECT_NO_THROW(assigner.start());
@@ -900,7 +902,7 @@ TEST(OptionsAssignerEnumTest, StoresSingleValue)
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(options.finish());
 
-    EXPECT_EQ(etestTest, value);
+    EXPECT_EQ(TestEnum::Test, value);
 }
 
 TEST(OptionsAssignerEnumTest, StoresVectorValues)
@@ -909,7 +911,7 @@ TEST(OptionsAssignerEnumTest, StoresVectorValues)
     std::vector<TestEnum> values;
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
-            EnumOption<TestEnum>("p").storeVector(&values).multiValue().enumValue(c_allowed)));
+            EnumOption<TestEnum>("p").storeVector(&values).multiValue().enumValue(c_testEnumNames)));
     EXPECT_TRUE(values.empty());
 
     gmx::OptionsAssigner assigner(&options);
@@ -922,71 +924,71 @@ TEST(OptionsAssignerEnumTest, StoresVectorValues)
     EXPECT_NO_THROW(options.finish());
 
     ASSERT_EQ(2U, values.size());
-    EXPECT_EQ(etestTest, values[0]);
-    EXPECT_EQ(etestValue, values[1]);
+    EXPECT_EQ(TestEnum::Test, values[0]);
+    EXPECT_EQ(TestEnum::Value, values[1]);
 }
 
 TEST(OptionsAssignerEnumTest, HandlesInitialValueOutOfRange)
 {
     gmx::Options options;
-    TestEnum     value = etestNR;
+    TestEnum     value = TestEnum::Count;
     using gmx::EnumOption;
-    ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed)));
-    EXPECT_EQ(etestNR, value);
+    ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames)));
+    EXPECT_EQ(TestEnum::Count, value);
 
     gmx::OptionsAssigner assigner(&options);
     EXPECT_NO_THROW(assigner.start());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(options.finish());
 
-    EXPECT_EQ(etestNR, value);
+    EXPECT_EQ(TestEnum::Count, value);
 }
 
 TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValue)
 {
     gmx::Options options;
-    TestEnum     value = etestNone;
+    TestEnum     value = TestEnum::None;
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
-            EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed).defaultValue(etestTest)));
-    EXPECT_EQ(etestTest, value);
+            EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames).defaultValue(TestEnum::Test)));
+    EXPECT_EQ(TestEnum::Test, value);
 
     gmx::OptionsAssigner assigner(&options);
     EXPECT_NO_THROW(assigner.start());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(options.finish());
 
-    EXPECT_EQ(etestTest, value);
+    EXPECT_EQ(TestEnum::Test, value);
 }
 
 TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVariable)
 {
     gmx::Options options;
-    TestEnum     value = etestTest;
+    TestEnum     value = TestEnum::Test;
     using gmx::EnumOption;
-    ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed)));
-    EXPECT_EQ(etestTest, value);
+    ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames)));
+    EXPECT_EQ(TestEnum::Test, value);
 
     gmx::OptionsAssigner assigner(&options);
     EXPECT_NO_THROW(assigner.start());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(options.finish());
 
-    EXPECT_EQ(etestTest, value);
+    EXPECT_EQ(TestEnum::Test, value);
 }
 
 TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVector)
 {
     gmx::Options          options;
     std::vector<TestEnum> value;
-    value.push_back(etestNone);
-    value.push_back(etestTest);
+    value.push_back(TestEnum::None);
+    value.push_back(TestEnum::Test);
     using gmx::EnumOption;
     ASSERT_NO_THROW(options.addOption(
-            EnumOption<TestEnum>("p").storeVector(&value).valueCount(2).enumValue(c_allowed)));
+            EnumOption<TestEnum>("p").storeVector(&value).valueCount(2).enumValue(c_testEnumNames)));
     ASSERT_EQ(2U, value.size());
-    EXPECT_EQ(etestNone, value[0]);
-    EXPECT_EQ(etestTest, value[1]);
+    EXPECT_EQ(TestEnum::None, value[0]);
+    EXPECT_EQ(TestEnum::Test, value[1]);
 
     gmx::OptionsAssigner assigner(&options);
     EXPECT_NO_THROW(assigner.start());
@@ -994,8 +996,8 @@ TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVector)
     EXPECT_NO_THROW(options.finish());
 
     ASSERT_EQ(2U, value.size());
-    EXPECT_EQ(etestNone, value[0]);
-    EXPECT_EQ(etestTest, value[1]);
+    EXPECT_EQ(TestEnum::None, value[0]);
+    EXPECT_EQ(TestEnum::Test, value[1]);
 }
 
 } // namespace
index 005be26913a85e3f66e3dc0182edd8fd0f509537..7715c9142f41055fa1b69d5914bc4698c8e29635 100644 (file)
@@ -61,10 +61,10 @@ namespace
 TEST(TimeUnitManagerTest, BasicOperations)
 {
     gmx::TimeUnitManager manager;
-    EXPECT_EQ(gmx::TimeUnit_ps, manager.timeUnit());
+    EXPECT_EQ(gmx::TimeUnit::Picoseconds, manager.timeUnit());
     EXPECT_DOUBLE_EQ(1.0, manager.timeScaleFactor());
-    manager.setTimeUnit(gmx::TimeUnit_ns);
-    EXPECT_EQ(gmx::TimeUnit_ns, manager.timeUnit());
+    manager.setTimeUnit(gmx::TimeUnit::Nanoseconds);
+    EXPECT_EQ(gmx::TimeUnit::Nanoseconds, manager.timeUnit());
     EXPECT_DOUBLE_EQ(1e3, manager.timeScaleFactor());
     EXPECT_DOUBLE_EQ(1e-3, manager.inverseTimeScaleFactor());
 }
@@ -86,21 +86,21 @@ TEST(TimeUnitBehaviorTest, ScalesAssignedOptionValue)
     EXPECT_NO_THROW_GMX(assigner.finish());
 
     EXPECT_DOUBLE_EQ(1.5, value);
-    behavior.setTimeUnit(gmx::TimeUnit_ns);
+    behavior.setTimeUnit(gmx::TimeUnit::Nanoseconds);
     behavior.optionsFinishing(&options);
     EXPECT_DOUBLE_EQ(1500, value);
 
     EXPECT_NO_THROW_GMX(options.finish());
 
-    behavior.setTimeUnit(gmx::TimeUnit_us);
+    behavior.setTimeUnit(gmx::TimeUnit::Microseconds);
     behavior.optionsFinishing(&options);
     EXPECT_DOUBLE_EQ(1500000, value);
 
-    behavior.setTimeUnit(gmx::TimeUnit_fs);
+    behavior.setTimeUnit(gmx::TimeUnit::Femtoseconds);
     behavior.optionsFinishing(&options);
     EXPECT_DOUBLE_EQ(0.0015, value);
 
-    behavior.setTimeUnit(gmx::TimeUnit_ps);
+    behavior.setTimeUnit(gmx::TimeUnit::Picoseconds);
     behavior.optionsFinishing(&options);
     EXPECT_DOUBLE_EQ(1.5, value);
 }
@@ -124,7 +124,7 @@ TEST(TimeUnitBehaviorTest, DoesNotScaleDefaultValues)
     EXPECT_NO_THROW_GMX(options.finish());
 
     EXPECT_DOUBLE_EQ(2.5, value2);
-    behavior.setTimeUnit(gmx::TimeUnit_ns);
+    behavior.setTimeUnit(gmx::TimeUnit::Nanoseconds);
     behavior.optionsFinishing(&options);
     EXPECT_DOUBLE_EQ(1.5, value);
     EXPECT_DOUBLE_EQ(2.5, value2);
@@ -151,7 +151,7 @@ TEST(TimeUnitBehaviorTest, ScalesUserInputWithMultipleSources)
     EXPECT_NO_THROW_GMX(options.finish());
 
     EXPECT_DOUBLE_EQ(1.5, value);
-    behavior.setTimeUnit(gmx::TimeUnit_ns);
+    behavior.setTimeUnit(gmx::TimeUnit::Nanoseconds);
     behavior.optionsFinishing(&options);
     EXPECT_DOUBLE_EQ(1500, value);
 }
@@ -177,7 +177,7 @@ TEST(TimeUnitBehaviorTest, TimeUnitOptionWorks)
     EXPECT_NO_THROW_GMX(assigner.finish());
 
     EXPECT_DOUBLE_EQ(1.5, value);
-    EXPECT_EQ(gmx::TimeUnit_ns, behavior.timeUnit());
+    EXPECT_EQ(gmx::TimeUnit::Nanoseconds, behavior.timeUnit());
     behavior.optionsFinishing(&options);
     EXPECT_DOUBLE_EQ(1500, value);
 
index 853646a642cf3c0ccf808e9e1254e668295e3cc2..8fb7069e632576d9fee31a26c6e3d868f0223666 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, 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.
@@ -398,15 +398,8 @@ TEST_F(TreeValueSupportTest, SupportsDoubleOption)
     runTest();
 }
 
-TEST_F(TreeValueSupportTest, SupportsEnumIntOption)
-{
-    const char* const values[] = { "foo", "bar" };
-    options_.addOption(gmx::EnumIntOption("a").enumValue(values).defaultValue(0));
-    runTest();
-}
-
 //! Enum for testing EnumOption.
-enum class TestEnum
+enum class TestEnum : int
 {
     Foo,
     Bar
@@ -414,8 +407,14 @@ enum class TestEnum
 
 TEST_F(TreeValueSupportTest, SupportsEnumOption)
 {
-    const char* const values[] = { "foo", "bar" };
-    options_.addOption(gmx::EnumOption<TestEnum>("a").enumValue(values).defaultValue(TestEnum::Foo));
+    enum class TestEnum : int
+    {
+        Foo,
+        Bar,
+        Count
+    };
+    const gmx::EnumerationArray<TestEnum, const char*> testEnumNames = { { "foo", "bar" } };
+    options_.addOption(gmx::EnumOption<TestEnum>("a").enumValue(testEnumNames).defaultValue(TestEnum::Foo));
     runTest();
 }
 
index be5f88990c3179e8c5a1a74db258bc1b12c88855..0dc7a4f2d41621976641904656b9f5acdd8ec150 100644 (file)
 #include "gromacs/options/options.h"
 #include "gromacs/options/optionsvisitor.h"
 #include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/stringutil.h"
 
+namespace gmx
+{
+
 namespace
 {
 
@@ -65,45 +69,34 @@ namespace
  *
  * These must correspond to the TimeUnit enum in the header!
  */
-const char* const g_timeUnits[] = { "fs", "ps", "ns", "us", "ms", "s" };
+const EnumerationArray<TimeUnit, const char*> c_timeUnitNames = { { "fs", "ps", "ns", "us", "ms",
+                                                                    "s" } };
 /*! \brief
  * Scaling factors from each time unit to internal units (=picoseconds).
  *
  * These must correspond to the TimeUnit enum in the header!
  */
-const double g_timeScaleFactors[] = { 1e-3, 1, 1e3, 1e6, 1e9, 1e12 };
+const EnumerationArray<TimeUnit, double> c_timeUnitScaleFactors = { { 1e-3, 1, 1e3, 1e6, 1e9, 1e12 } };
 
 } // namespace
 
-namespace gmx
-{
-
-TimeUnitManager::TimeUnitManager() : timeUnit_(TimeUnit_Default) {}
+TimeUnitManager::TimeUnitManager() : timeUnit_(TimeUnit::Default) {}
 
-TimeUnitManager::TimeUnitManager(TimeUnit unit) : timeUnit_(unit)
-{
-    GMX_RELEASE_ASSERT(unit >= 0 && unit <= TimeUnit_s, "Invalid time unit");
-}
+TimeUnitManager::TimeUnitManager(TimeUnit unit) : timeUnit_(unit) {}
 
 void TimeUnitManager::setTimeUnit(TimeUnit unit)
 {
-    GMX_RELEASE_ASSERT(unit >= 0 && unit <= TimeUnit_s, "Invalid time unit");
     timeUnit_ = unit;
 }
 
 const char* TimeUnitManager::timeUnitAsString() const
 {
-    GMX_RELEASE_ASSERT(timeUnit_ >= 0 && timeUnit_ <= TimeUnit_s, "Invalid time unit");
-    return g_timeUnits[timeUnit_];
+    return c_timeUnitNames[timeUnit_];
 }
 
 double TimeUnitManager::timeScaleFactor() const
 {
-    GMX_RELEASE_ASSERT(timeUnit_ >= 0
-                               && static_cast<size_t>(timeUnit_)
-                                          < sizeof(g_timeScaleFactors) / sizeof(g_timeScaleFactors[0]),
-                       "Time unit index has become out-of-range");
-    return g_timeScaleFactors[timeUnit_];
+    return c_timeUnitScaleFactors[timeUnit_];
 }
 
 double TimeUnitManager::inverseTimeScaleFactor() const
@@ -115,11 +108,10 @@ double TimeUnitManager::inverseTimeScaleFactor() const
  * TimeUnitBehavior
  */
 
-TimeUnitBehavior::TimeUnitBehavior() : timeUnit_(TimeUnit_Default), timeUnitStore_(nullptr) {}
+TimeUnitBehavior::TimeUnitBehavior() : timeUnit_(TimeUnit::Default), timeUnitStore_(nullptr) {}
 
 void TimeUnitBehavior::setTimeUnit(TimeUnit unit)
 {
-    GMX_RELEASE_ASSERT(unit >= 0 && unit <= TimeUnit_s, "Invalid time unit");
     timeUnit_ = unit;
     if (timeUnitStore_ != nullptr)
     {
@@ -138,26 +130,32 @@ void TimeUnitBehavior::setTimeUnitFromEnvironment()
     const char* const value = std::getenv("GMXTIMEUNIT");
     if (value != nullptr)
     {
-        ArrayRef<const char* const>                 timeUnits(g_timeUnits);
-        ArrayRef<const char* const>::const_iterator i =
-                std::find(timeUnits.begin(), timeUnits.end(), std::string(value));
-        if (i == timeUnits.end())
+        TimeUnit result = TimeUnit::Count;
+        for (TimeUnit t : keysOf(c_timeUnitNames))
+        {
+            if (std::strcmp(value, c_timeUnitNames[t]) == 0)
+            {
+                result = t;
+                break;
+            }
+        }
+        if (result == TimeUnit::Count)
         {
             std::string message = formatString(
                     "Time unit provided with environment variable GMXTIMEUNIT=%s "
                     "is not recognized as a valid time unit.\n"
                     "Possible values are: %s",
-                    value, joinStrings(timeUnits, ", ").c_str());
+                    value, joinStrings(c_timeUnitNames, ", ").c_str());
             GMX_THROW(InvalidInputError(message));
         }
-        setTimeUnit(static_cast<TimeUnit>(i - timeUnits.begin()));
+        setTimeUnit(result);
     }
 }
 
 void TimeUnitBehavior::addTimeUnitOption(IOptionsContainer* options, const char* name)
 {
     options->addOption(
-            EnumOption<TimeUnit>(name).enumValue(g_timeUnits).store(&timeUnit_).description("Unit for time values"));
+            EnumOption<TimeUnit>(name).enumValue(c_timeUnitNames).store(&timeUnit_).description("Unit for time values"));
 }
 
 namespace
index 5aa9742a501a0fab982d922ff574ea7f8e7e9a5f..222771b3e28266042bdde4caeaa01611cce395b0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2018,2019,2020, 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.
@@ -43,9 +43,9 @@
 #ifndef GMX_OPTIONS_TIMEUNITMANAGER_H
 #define GMX_OPTIONS_TIMEUNITMANAGER_H
 
+#include "gromacs/fileio/oenv.h"
 #include "gromacs/options/ioptionsbehavior.h"
 #include "gromacs/utility/classhelpers.h"
-#include "gromacs/utility/gmxassert.h"
 
 namespace gmx
 {
@@ -53,27 +53,6 @@ namespace gmx
 class IOptionsContainer;
 class Options;
 
-/*! \brief
- * Time values for TimeUnitManager.
- *
- * \if internal
- * Currently, this should match with the time_unit_t enum defined in oenv.h
- * except that there is no NULL first item in this enum.
- * \endif
- *
- * \inpublicapi
- */
-enum TimeUnit
-{
-    TimeUnit_fs,                   //!< Femtoseconds.
-    TimeUnit_ps,                   //!< Picoseconds.
-    TimeUnit_ns,                   //!< Nanoseconds.
-    TimeUnit_us,                   //!< Microseconds.
-    TimeUnit_ms,                   //!< Milliseconds.
-    TimeUnit_s,                    //!< Seconds.
-    TimeUnit_Default = TimeUnit_ps //!< Default time unit.
-};
-
 /*! \brief
  * Provides common functionality for time unit conversions.
  *
@@ -103,12 +82,7 @@ public:
     explicit TimeUnitManager(TimeUnit unit);
 
     //! Returns the currently selected time unit.
-    TimeUnit timeUnit() const
-    {
-        GMX_ASSERT(timeUnit_ >= 0 && timeUnit_ <= TimeUnit_s,
-                   "Time unit index has become out-of-range");
-        return timeUnit_;
-    }
+    TimeUnit timeUnit() const { return timeUnit_; }
     //! Set a new time unit for the manager.
     void setTimeUnit(TimeUnit unit);
 
@@ -144,12 +118,7 @@ public:
     TimeUnitBehavior();
 
     //! Returns the current time unit.
-    TimeUnit timeUnit() const
-    {
-        GMX_ASSERT(timeUnit_ >= 0 && timeUnit_ <= TimeUnit_s,
-                   "Time unit index has become out-of-range");
-        return static_cast<TimeUnit>(timeUnit_);
-    }
+    TimeUnit timeUnit() const { return timeUnit_; }
     //! Sets the time unit.
     void setTimeUnit(TimeUnit unit);
 
index 21ec023f0c9589d2ce31910f14bfadb00dce230b..e6d458d89c5986e073621076c3dd613219b68f60 100644 (file)
@@ -2609,7 +2609,8 @@ void SelectionCompiler::compile(SelectionCollection* coll)
     e_poscalc_t                 post;
     size_t                      i;
     int                         flags;
-    bool bDebug = (coll->impl_->debugLevel_ >= 2 && coll->impl_->debugLevel_ != 3);
+    bool bDebug = (coll->impl_->debugLevel_ == SelectionCollection::Impl::DebugLevel::Compiled
+                   && coll->impl_->debugLevel_ == SelectionCollection::Impl::DebugLevel::Full);
 
     /* FIXME: Clean up the collection on exceptions */
 
index 4b78f5436234ed0e23ddff2ce2c160fddb607055..197f0962c941bac78aad14919340ad8a6bb6c545 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -84,7 +84,10 @@ namespace gmx
  * SelectionCollection::Impl
  */
 
-SelectionCollection::Impl::Impl() : debugLevel_(0), bExternalGroupsSet_(false), grps_(nullptr)
+SelectionCollection::Impl::Impl() :
+    debugLevel_(DebugLevel::None),
+    bExternalGroupsSet_(false),
+    grps_(nullptr)
 {
     sc_.nvars   = 0;
     sc_.varstrs = nullptr;
@@ -532,7 +535,9 @@ SelectionCollection::~SelectionCollection() {}
 
 void SelectionCollection::initOptions(IOptionsContainer* options, SelectionTypeOption selectionTypeOption)
 {
-    const char* const debug_levels[] = { "no", "basic", "compile", "eval", "full" };
+    static const EnumerationArray<Impl::DebugLevel, const char*> s_debugLevelNames = {
+        { "no", "basic", "compile", "eval", "full" }
+    };
 
     const char* const* postypes = PositionCalculationCollection::typeEnumValues;
     options->addOption(StringOption("selrpos")
@@ -552,11 +557,10 @@ void SelectionCollection::initOptions(IOptionsContainer* options, SelectionTypeO
     {
         impl_->spost_ = postypes[0];
     }
-    GMX_RELEASE_ASSERT(impl_->debugLevel_ >= 0 && impl_->debugLevel_ <= 4,
-                       "Debug level out of range");
-    options->addOption(EnumIntOption("seldebug")
-                               .hidden(impl_->debugLevel_ == 0)
-                               .enumValue(debug_levels)
+    GMX_RELEASE_ASSERT(impl_->debugLevel_ != Impl::DebugLevel::Count, "Debug level out of range");
+    options->addOption(EnumOption<Impl::DebugLevel>("seldebug")
+                               .hidden(impl_->debugLevel_ == Impl::DebugLevel::None)
+                               .enumValue(s_debugLevelNames)
                                .store(&impl_->debugLevel_)
                                .description("Print out selection trees for debugging"));
 }
@@ -586,7 +590,7 @@ void SelectionCollection::setOutputPosType(const char* type)
 
 void SelectionCollection::setDebugLevel(int debugLevel)
 {
-    impl_->debugLevel_ = debugLevel;
+    impl_->debugLevel_ = Impl::DebugLevel(debugLevel);
 }
 
 
@@ -755,7 +759,7 @@ void SelectionCollection::compile()
     {
         setIndexGroups(nullptr);
     }
-    if (impl_->debugLevel_ >= 1)
+    if (impl_->debugLevel_ != Impl::DebugLevel::None)
     {
         printTree(stderr, false);
     }
@@ -763,7 +767,7 @@ void SelectionCollection::compile()
     SelectionCompiler compiler;
     compiler.compile(this);
 
-    if (impl_->debugLevel_ >= 1)
+    if (impl_->debugLevel_ != Impl::DebugLevel::None)
     {
         std::fprintf(stderr, "\n");
         printTree(stderr, false);
@@ -772,7 +776,7 @@ void SelectionCollection::compile()
         std::fprintf(stderr, "\n");
     }
     impl_->sc_.pcc.initEvaluation();
-    if (impl_->debugLevel_ >= 1)
+    if (impl_->debugLevel_ != Impl::DebugLevel::None)
     {
         impl_->sc_.pcc.printTree(stderr);
         std::fprintf(stderr, "\n");
@@ -858,7 +862,7 @@ void SelectionCollection::evaluate(t_trxframe* fr, t_pbc* pbc)
     SelectionEvaluator evaluator;
     evaluator.evaluate(this, fr, pbc);
 
-    if (impl_->debugLevel_ >= 3)
+    if (impl_->debugLevel_ == Impl::DebugLevel::Evaluated || impl_->debugLevel_ == Impl::DebugLevel::Full)
     {
         std::fprintf(stderr, "\n");
         printTree(stderr, true);
index 28b54e9ad560d1c32dc083150bc234a5e5c82dfd..4c79e66c6f6110e4c6fae0d1564e6ad2f7e7dc2f 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2009-2016, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -163,6 +163,23 @@ public:
     SelectionTopologyProperties requiredTopologyPropertiesForPositionType(const std::string& post,
                                                                           bool forces) const;
 
+    //! Describes the available debugging levels
+    enum class DebugLevel : int
+    {
+        //! No debugging
+        None,
+        //! Print selection trees after parsing and compilation
+        Basic,
+        //! As PrintCompiled, also print intermediate compilation trees
+        Compiled,
+        //! As PrintCompiled, also print the tree after evaluation
+        Evaluated,
+        //! Combine Compiled and Evaluated
+        Full,
+        //! Ends the enumeration
+        Count
+    };
+
     //! Internal data, used for interfacing with old C code.
     gmx_ana_selcollection_t sc_;
     //! Default reference position type for selections.
@@ -171,17 +188,8 @@ public:
     std::string spost_;
     //! Atoms needed for evaluating the selections.
     gmx_ana_index_t requiredAtoms_;
-    /*! \brief
-     * Debugging level for the collection.
-     *
-     * Possible values:
-     *  - 0: no debugging
-     *  - 1: print selection trees after parsing and compilation
-     *  - 2: like 1, also print intermediate compilation trees
-     *  - 3: like 1, also print the tree after evaluation
-     *  - 4: combine 2 and 3
-     */
-    int debugLevel_;
+    //! Debugging level for the collection.
+    DebugLevel debugLevel_;
     //! Whether setIndexGroups() has been called.
     bool bExternalGroupsSet_;
     //! External index groups (can be NULL).
index c5ad76bde72c5cea3c7e80e43f3f3722e95ac51a..a83eb39777a8aece5b963f8e047c862229f4478b 100644 (file)
@@ -64,7 +64,7 @@ class TrajectoryAnalysisSettings::Impl
 public:
     //! Initializes the default values for the settings object.
     Impl() :
-        timeUnit(TimeUnit_Default),
+        timeUnit(TimeUnit::Default),
         flags(0),
         frflags(0),
         bRmPBC(true),
index 344c4ee748fec8faff2de3a1989342518091272f..f5ab6c7944e2e8e605e6226b0c8e04186b85c418 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -64,6 +64,7 @@
 #include "gromacs/trajectory/trajectoryframe.h"
 #include "gromacs/trajectoryanalysis/analysissettings.h"
 #include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/enumerationhelpers.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/stringutil.h"
@@ -237,27 +238,32 @@ private:
  */
 
 //! How to interpret the selections in -group1.
-enum Group1Type
+enum class Group1Type : int
 {
-    Group1Type_Angle,
-    Group1Type_Dihedral,
-    Group1Type_Vector,
-    Group1Type_Plane
+    Angle,
+    Dihedral,
+    Vector,
+    Plane,
+    Count
 };
 //! How to interpret the selections in -group2.
-enum Group2Type
+enum class Group2Type : int
 {
-    Group2Type_None,
-    Group2Type_Vector,
-    Group2Type_Plane,
-    Group2Type_TimeZero,
-    Group2Type_Z,
-    Group2Type_SphereNormal
+    None,
+    Vector,
+    Plane,
+    TimeZero,
+    Z,
+    SphereNormal,
+    Count
 };
 //! String values corresponding to Group1Type.
-const char* const cGroup1TypeEnum[] = { "angle", "dihedral", "vector", "plane" };
+const EnumerationArray<Group1Type, const char*> c_group1TypeEnumNames = { { "angle", "dihedral",
+                                                                            "vector", "plane" } };
 //! String values corresponding to Group2Type.
-const char* const cGroup2TypeEnum[] = { "none", "vector", "plane", "t0", "z", "sphnorm" };
+const EnumerationArray<Group2Type, const char*> c_group2TypeEnumNames = {
+    { "none", "vector", "plane", "t0", "z", "sphnorm" }
+};
 
 class Angle : public TrajectoryAnalysisModule
 {
@@ -304,8 +310,8 @@ private:
 Angle::Angle() :
     sel1info_(nullptr),
     sel2info_(nullptr),
-    g1type_(Group1Type_Angle),
-    g2type_(Group2Type_None),
+    g1type_(Group1Type::Angle),
+    g2type_(Group2Type::None),
     binWidth_(1.0),
     natoms1_(0),
     natoms2_(0)
@@ -393,10 +399,12 @@ void Angle::initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings*
                                .defaultBasename("anghist")
                                .description("Histogram of the angles"));
 
+    options->addOption(EnumOption<Group1Type>("g1")
+                               .enumValue(c_group1TypeEnumNames)
+                               .store(&g1type_)
+                               .description("Type of analysis/first vector group"));
     options->addOption(
-            EnumOption<Group1Type>("g1").enumValue(cGroup1TypeEnum).store(&g1type_).description("Type of analysis/first vector group"));
-    options->addOption(
-            EnumOption<Group2Type>("g2").enumValue(cGroup2TypeEnum).store(&g2type_).description("Type of second vector group"));
+            EnumOption<Group2Type>("g2").enumValue(c_group2TypeEnumNames).store(&g2type_).description("Type of second vector group"));
     options->addOption(
             DoubleOption("binw").store(&binWidth_).description("Binwidth for -oh in degrees"));
 
@@ -411,9 +419,9 @@ void Angle::initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings*
 
 void Angle::optionsFinished(TrajectoryAnalysisSettings* /* settings */)
 {
-    const bool bSingle = (g1type_ == Group1Type_Angle || g1type_ == Group1Type_Dihedral);
+    const bool bSingle = (g1type_ == Group1Type::Angle || g1type_ == Group1Type::Dihedral);
 
-    if (bSingle && g2type_ != Group2Type_None)
+    if (bSingle && g2type_ != Group2Type::None)
     {
         GMX_THROW(
                 InconsistentInputError("Cannot use a second group (-g2) with "
@@ -425,7 +433,7 @@ void Angle::optionsFinished(TrajectoryAnalysisSettings* /* settings */)
                 InconsistentInputError("Cannot provide a second selection "
                                        "(-group2) with -g1 angle or dihedral"));
     }
-    if (!bSingle && g2type_ == Group2Type_None)
+    if (!bSingle && g2type_ == Group2Type::None)
     {
         GMX_THROW(
                 InconsistentInputError("Should specify a second group (-g2) "
@@ -435,20 +443,20 @@ void Angle::optionsFinished(TrajectoryAnalysisSettings* /* settings */)
     // Set up the number of positions per angle.
     switch (g1type_)
     {
-        case Group1Type_Angle: natoms1_ = 3; break;
-        case Group1Type_Dihedral: natoms1_ = 4; break;
-        case Group1Type_Vector: natoms1_ = 2; break;
-        case Group1Type_Plane: natoms1_ = 3; break;
+        case Group1Type::Angle: natoms1_ = 3; break;
+        case Group1Type::Dihedral: natoms1_ = 4; break;
+        case Group1Type::Vector: natoms1_ = 2; break;
+        case Group1Type::Plane: natoms1_ = 3; break;
         default: GMX_THROW(InternalError("invalid -g1 value"));
     }
     switch (g2type_)
     {
-        case Group2Type_None: natoms2_ = 0; break;
-        case Group2Type_Vector: natoms2_ = 2; break;
-        case Group2Type_Plane: natoms2_ = 3; break;
-        case Group2Type_TimeZero: natoms2_ = 0; break;
-        case Group2Type_Z: natoms2_ = 0; break;
-        case Group2Type_SphereNormal: natoms2_ = 1; break;
+        case Group2Type::None: natoms2_ = 0; break;
+        case Group2Type::Vector: natoms2_ = 2; break;
+        case Group2Type::Plane: natoms2_ = 3; break;
+        case Group2Type::TimeZero: // Intended to fall through
+        case Group2Type::Z: natoms2_ = 0; break;
+        case Group2Type::SphereNormal: natoms2_ = 1; break;
         default: GMX_THROW(InternalError("invalid -g2 value"));
     }
     if (natoms2_ == 0 && sel2info_->isSet())
@@ -496,7 +504,7 @@ void Angle::initFromSelections(const SelectionList& sel1, const SelectionList& s
                                      "divisible by %d",
                                      static_cast<int>(g + 1), natoms2_)));
             }
-            if (g2type_ == Group2Type_SphereNormal && posCount2 != 1)
+            if (g2type_ == Group2Type::SphereNormal && posCount2 != 1)
             {
                 GMX_THROW(InconsistentInputError(
                         "The second group should contain a single position with -g2 sphnorm"));
@@ -575,10 +583,10 @@ void Angle::initAnalysis(const TrajectoryAnalysisSettings& settings, const Topol
     {
         angles_.setColumnCount(i, angleCount_[i]);
     }
-    double histogramMin = (g1type_ == Group1Type_Dihedral ? -180.0 : 0);
+    double histogramMin = (g1type_ == Group1Type::Dihedral ? -180.0 : 0);
     histogramModule_->init(histogramFromRange(histogramMin, 180.0).binWidth(binWidth_).includeAll());
 
-    if (g2type_ == Group2Type_TimeZero)
+    if (g2type_ == Group2Type::TimeZero)
     {
         vt0_.resize(sel1_.size());
         for (size_t g = 0; g < sel1_.size(); ++g)
@@ -701,8 +709,8 @@ void Angle::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryA
 
         switch (g2type_)
         {
-            case Group2Type_Z: v2[ZZ] = 1.0; break;
-            case Group2Type_SphereNormal: copy_rvec(sel2_[g].position(0).x(), c2); break;
+            case Group2Type::Z: v2[ZZ] = 1.0; break;
+            case Group2Type::SphereNormal: copy_rvec(sel2_[g].position(0).x(), c2); break;
             default:
                 // do nothing
                 break;
@@ -724,7 +732,7 @@ void Angle::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryA
             iter1.getCurrentPositions(x);
             switch (g1type_)
             {
-                case Group1Type_Angle:
+                case Group1Type::Angle:
                     if (pbc)
                     {
                         pbc_dx(pbc, x[0], x[1], v1);
@@ -737,7 +745,7 @@ void Angle::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryA
                     }
                     angle = gmx_angle(v1, v2);
                     break;
-                case Group1Type_Dihedral:
+                case Group1Type::Dihedral:
                 {
                     rvec dx[3];
                     if (pbc)
@@ -762,17 +770,17 @@ void Angle::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryA
                     }
                     break;
                 }
-                case Group1Type_Vector:
-                case Group1Type_Plane:
+                case Group1Type::Vector:
+                case Group1Type::Plane:
                     calc_vec(natoms1_, x, pbc, v1, c1);
                     switch (g2type_)
                     {
-                        case Group2Type_Vector:
-                        case Group2Type_Plane:
+                        case Group2Type::Vector:
+                        case Group2Type::Plane:
                             iter2.getCurrentPositions(x);
                             calc_vec(natoms2_, x, pbc, v2, c2);
                             break;
-                        case Group2Type_TimeZero:
+                        case Group2Type::TimeZero:
                             // FIXME: This is not parallelizable.
                             if (frnr == 0)
                             {
@@ -780,8 +788,8 @@ void Angle::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryA
                             }
                             copy_rvec(vt0_[g][n], v2);
                             break;
-                        case Group2Type_Z: c1[XX] = c1[YY] = 0.0; break;
-                        case Group2Type_SphereNormal:
+                        case Group2Type::Z: c1[XX] = c1[YY] = 0.0; break;
+                        case Group2Type::SphereNormal:
                             if (pbc)
                             {
                                 pbc_dx(pbc, c1, c2, v2);
index 41109ee5487cb015aa4aabe3c189b9a641e47358..d3f36ff5be66a3b04634c43ee48c488c714e737d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2018,2019,2020, 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.
@@ -78,25 +78,28 @@ namespace
 //! \{
 
 //! Enum value to store the selected value for `-type`.
-enum DistanceType
+enum class DistanceType : int
 {
-    eDistanceType_Min,
-    eDistanceType_Max
+    Min,
+    Max,
+    Count
 };
 
 //! Enum value to store the selected value for `-refgrouping`/`-selgrouping`.
-enum GroupType
+enum class GroupType : int
 {
-    eGroupType_All,
-    eGroupType_Residue,
-    eGroupType_Molecule,
-    eGroupType_None
+    All,
+    Residue,
+    Molecule,
+    None,
+    Count
 };
 
 //! Strings corresponding to DistanceType.
-const char* const c_distanceTypes[] = { "min", "max" };
+const EnumerationArray<DistanceType, const char*> c_distanceTypeNames = { { "min", "max" } };
 //! Strings corresponding to GroupType.
-const char* const c_groupTypes[] = { "all", "res", "mol", "none" };
+const EnumerationArray<GroupType, const char*> c_groupTypeNames = { { "all", "res", "mol",
+                                                                      "none" } };
 
 /*! \brief
  * Implements `gmx pairdist` trajectory analysis module.
@@ -165,9 +168,9 @@ private:
 
 PairDistance::PairDistance() :
     cutoff_(0.0),
-    distanceType_(eDistanceType_Min),
-    refGroupType_(eGroupType_All),
-    selGroupType_(eGroupType_All),
+    distanceType_(DistanceType::Min),
+    refGroupType_(GroupType::All),
+    selGroupType_(GroupType::All),
     refGroupCount_(0),
     maxGroupCount_(0),
     initialDist2_(0.0),
@@ -228,17 +231,17 @@ void PairDistance::initOptions(IOptionsContainer* options, TrajectoryAnalysisSet
             DoubleOption("cutoff").store(&cutoff_).description("Maximum distance to consider"));
     options->addOption(EnumOption<DistanceType>("type")
                                .store(&distanceType_)
-                               .enumValue(c_distanceTypes)
+                               .enumValue(c_distanceTypeNames)
                                .description("Type of distances to calculate"));
     options->addOption(
             EnumOption<GroupType>("refgrouping")
                     .store(&refGroupType_)
-                    .enumValue(c_groupTypes)
+                    .enumValue(c_groupTypeNames)
                     .description("Grouping of -ref positions to compute the min/max over"));
     options->addOption(
             EnumOption<GroupType>("selgrouping")
                     .store(&selGroupType_)
-                    .enumValue(c_groupTypes)
+                    .enumValue(c_groupTypeNames)
                     .description("Grouping of -sel positions to compute the min/max over"));
 
     options->addOption(SelectionOption("ref").store(&refSel_).required().description(
@@ -248,15 +251,16 @@ void PairDistance::initOptions(IOptionsContainer* options, TrajectoryAnalysisSet
 }
 
 //! Helper function to initialize the grouping for a selection.
-int initSelectionGroups(Selection* sel, const gmx_mtop_t* top, int type)
+int initSelectionGroups(Selection* sel, const gmx_mtop_t* top, GroupType type)
 {
     e_index_t indexType = INDEX_UNKNOWN;
     switch (type)
     {
-        case eGroupType_All: indexType = INDEX_ALL; break;
-        case eGroupType_Residue: indexType = INDEX_RES; break;
-        case eGroupType_Molecule: indexType = INDEX_MOL; break;
-        case eGroupType_None: indexType = INDEX_ATOM; break;
+        case GroupType::All: indexType = INDEX_ALL; break;
+        case GroupType::Residue: indexType = INDEX_RES; break;
+        case GroupType::Molecule: indexType = INDEX_MOL; break;
+        case GroupType::None: indexType = INDEX_ATOM; break;
+        case GroupType::Count: GMX_THROW(InternalError("Invalid GroupType"));
     }
     return sel->initOriginalIdsToGroup(top, indexType);
 }
@@ -280,7 +284,7 @@ void PairDistance::initAnalysis(const TrajectoryAnalysisSettings& settings, cons
     {
         AnalysisDataPlotModulePointer plotm(new AnalysisDataPlotModule(settings.plotSettings()));
         plotm->setFileName(fnDist_);
-        if (distanceType_ == eDistanceType_Max)
+        if (distanceType_ == DistanceType::Max)
         {
             plotm->setTitle("Maximum distance");
         }
@@ -310,7 +314,7 @@ void PairDistance::initAnalysis(const TrajectoryAnalysisSettings& settings, cons
     {
         initialDist2_ = cutoff_ * cutoff_;
     }
-    if (distanceType_ == eDistanceType_Max)
+    if (distanceType_ == DistanceType::Max)
     {
         initialDist2_ = 0.0;
     }
@@ -444,7 +448,7 @@ void PairDistance::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, Traj
             const int                selIndex = selPos.mappedId();
             const int                index    = selIndex * refGroupCount_ + refIndex;
             const real               r2       = pair.distance2();
-            if (distanceType_ == eDistanceType_Min)
+            if (distanceType_ == DistanceType::Min)
             {
                 if (distArray[index] > r2)
                 {
@@ -496,7 +500,7 @@ void PairDistance::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, Traj
                     // update the distance if necessary and the count.
                     if (countArray[index] < totalCount)
                     {
-                        if (distanceType_ == eDistanceType_Max)
+                        if (distanceType_ == DistanceType::Max)
                         {
                             distArray[index] = cutoff2_;
                         }
index bb2f6249198ee86fafcefdebb7dc20bfe6c9a9ae..438ba85a8704f783f062b7226fab9403d370f65a 100644 (file)
@@ -92,23 +92,27 @@ namespace
  */
 
 //! Normalization for the computed distribution.
-enum Normalization
+enum class Normalization : int
 {
-    Normalization_Rdf,
-    Normalization_NumberDensity,
-    Normalization_None
+    Rdf,
+    NumberDensity,
+    None,
+    Count
 };
 //! String values corresponding to Normalization.
-const char* const c_NormalizationEnum[] = { "rdf", "number_density", "none" };
+const EnumerationArray<Normalization, const char*> c_normalizationNames = {
+    { "rdf", "number_density", "none" }
+};
 //! Whether to compute RDF wrt. surface of the reference group.
-enum SurfaceType
+enum class SurfaceType : int
 {
-    SurfaceType_None,
-    SurfaceType_Molecule,
-    SurfaceType_Residue
+    None,
+    Molecule,
+    Residue,
+    Count
 };
 //! String values corresponding to SurfaceType.
-const char* const c_SurfaceEnum[] = { "no", "mol", "res" };
+const EnumerationArray<SurfaceType, const char*> c_surfaceTypeNames = { { "no", "mol", "res" } };
 
 /*! \brief
  * Implements `gmx rdf` trajectory analysis module.
@@ -202,14 +206,14 @@ private:
 };
 
 Rdf::Rdf() :
-    surface_(SurfaceType_None),
+    surface_(SurfaceType::None),
     pairCounts_(new AnalysisDataSimpleHistogramModule()),
     normAve_(new AnalysisDataAverageModule()),
     localTop_(nullptr),
     binwidth_(0.002),
     cutoff_(0.0),
     rmax_(0.0),
-    normalization_(Normalization_Rdf),
+    normalization_(Normalization::Rdf),
     bNormalizationSet_(false),
     bXY_(false),
     bExclusions_(false),
@@ -297,7 +301,7 @@ void Rdf::initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings* se
 
     options->addOption(DoubleOption("bin").store(&binwidth_).description("Bin width (nm)"));
     options->addOption(EnumOption<Normalization>("norm")
-                               .enumValue(c_NormalizationEnum)
+                               .enumValue(c_normalizationNames)
                                .store(&normalization_)
                                .storeIsSet(&bNormalizationSet_)
                                .description("Normalization"));
@@ -311,7 +315,7 @@ void Rdf::initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings* se
             DoubleOption("rmax").store(&rmax_).description("Largest distance (nm) to calculate"));
 
     options->addOption(EnumOption<SurfaceType>("surf")
-                               .enumValue(c_SurfaceEnum)
+                               .enumValue(c_surfaceTypeNames)
                                .store(&surface_)
                                .description("RDF with respect to the surface of the reference"));
 
@@ -323,15 +327,15 @@ void Rdf::initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings* se
 
 void Rdf::optionsFinished(TrajectoryAnalysisSettings* settings)
 {
-    if (surface_ != SurfaceType_None)
+    if (surface_ != SurfaceType::None)
     {
         settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
 
-        if (bNormalizationSet_ && normalization_ != Normalization_None)
+        if (bNormalizationSet_ && normalization_ != Normalization::None)
         {
             GMX_THROW(InconsistentInputError("-surf cannot be combined with -norm"));
         }
-        normalization_ = Normalization_None;
+        normalization_ = Normalization::None;
         if (bExclusions_)
         {
             GMX_THROW(InconsistentInputError("-surf cannot be combined with -excl"));
@@ -359,14 +363,14 @@ void Rdf::initAnalysis(const TrajectoryAnalysisSettings& settings, const Topolog
 
     normFactors_.setColumnCount(0, sel_.size() + 1);
 
-    const bool bSurface = (surface_ != SurfaceType_None);
+    const bool bSurface = (surface_ != SurfaceType::None);
     if (bSurface)
     {
         if (!refSel_.hasOnlyAtoms())
         {
             GMX_THROW(InconsistentInputError("-surf only works with -ref that consists of atoms"));
         }
-        const e_index_t type = (surface_ == SurfaceType_Molecule ? INDEX_MOL : INDEX_RES);
+        const e_index_t type = (surface_ == SurfaceType::Molecule ? INDEX_MOL : INDEX_RES);
         surfaceGroupCount_   = refSel_.initOriginalIdsToGroup(top.mtop(), type);
     }
 
@@ -600,7 +604,7 @@ void Rdf::finishAnalysis(int /*nframes*/)
     // through the dataset registration mechanism.
     AverageHistogramPointer finalRdf = pairCounts_->averager().resampleDoubleBinWidth(true);
 
-    if (normalization_ != Normalization_None)
+    if (normalization_ != Normalization::None)
     {
         // Normalize by the volume of the bins (volume of sphere segments or
         // length of circle segments).
@@ -626,7 +630,7 @@ void Rdf::finishAnalysis(int /*nframes*/)
         }
         finalRdf->scaleAllByVector(invBinVolume.data());
 
-        if (normalization_ == Normalization_Rdf)
+        if (normalization_ == Normalization::Rdf)
         {
             // Normalize by particle density.
             for (size_t g = 0; g < sel_.size(); ++g)
index 67e538f9650948011a0386778bccd666c169f181..f3aefd8c4a60863ce6ae73ea24d6e9e81ef131b8 100644 (file)
@@ -257,22 +257,26 @@ void IndexFileWriterModule::dataFinished()
  */
 
 //! How to identify residues in output files.
-enum ResidueNumbering
+enum class ResidueNumbering : int
 {
-    ResidueNumbering_ByNumber,
-    ResidueNumbering_ByIndex
+    ByNumber,
+    ByIndex,
+    Count
 };
 //! Which atoms to write out to PDB files.
-enum PdbAtomsSelection
+enum class PdbAtomsSelection : int
 {
-    PdbAtomsSelection_All,
-    PdbAtomsSelection_MaxSelection,
-    PdbAtomsSelection_Selected
+    All,
+    MaxSelection,
+    Selected,
+    Count
 };
 //! String values corresponding to ResidueNumbering.
-const char* const cResNumberEnum[] = { "number", "index" };
+const EnumerationArray<ResidueNumbering, const char*> c_residueNumberingTypeNames = { { "number",
+                                                                                        "index" } };
 //! String values corresponding to PdbAtomsSelection.
-const char* const cPDBAtomsEnum[] = { "all", "maxsel", "selected" };
+const EnumerationArray<PdbAtomsSelection, const char*> c_pdbAtomsTypeNames = { { "all", "maxsel",
+                                                                                 "selected" } };
 
 class Select : public TrajectoryAnalysisModule
 {
@@ -322,8 +326,8 @@ Select::Select() :
     bFracNorm_(false),
     bResInd_(false),
     bCumulativeLifetimes_(true),
-    resNumberType_(ResidueNumbering_ByNumber),
-    pdbAtoms_(PdbAtomsSelection_All),
+    resNumberType_(ResidueNumbering::ByNumber),
+    pdbAtoms_(PdbAtomsSelection::All),
     top_(nullptr),
     occupancyModule_(new AnalysisDataAverageModule()),
     lifetimeModule_(new AnalysisDataLifetimeModule())
@@ -482,11 +486,11 @@ void Select::initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings*
             BooleanOption("cfnorm").store(&bFracNorm_).description("Normalize by covered fraction with -os"));
     options->addOption(EnumOption<ResidueNumbering>("resnr")
                                .store(&resNumberType_)
-                               .enumValue(cResNumberEnum)
+                               .enumValue(c_residueNumberingTypeNames)
                                .description("Residue number output type with -oi and -on"));
     options->addOption(EnumOption<PdbAtomsSelection>("pdbatoms")
                                .store(&pdbAtoms_)
-                               .enumValue(cPDBAtomsEnum)
+                               .enumValue(c_pdbAtomsTypeNames)
                                .description("Atoms to write with -ofpdb"));
     options->addOption(BooleanOption("cumlt")
                                .store(&bCumulativeLifetimes_)
@@ -504,7 +508,7 @@ void Select::optionsFinished(TrajectoryAnalysisSettings* settings)
 
 void Select::initAnalysis(const TrajectoryAnalysisSettings& settings, const TopologyInformation& top)
 {
-    bResInd_ = (resNumberType_ == ResidueNumbering_ByIndex);
+    bResInd_ = (resNumberType_ == ResidueNumbering::ByIndex);
 
     for (SelectionList::iterator i = sel_.begin(); i != sel_.end(); ++i)
     {
@@ -725,14 +729,14 @@ void Select::writeOutput()
 
         switch (pdbAtoms_)
         {
-            case PdbAtomsSelection_All:
+            case PdbAtomsSelection::All:
             {
                 t_trxstatus* status = open_trx(fnPDB_.c_str(), "w");
                 write_trxframe(status, &fr, nullptr);
                 close_trx(status);
                 break;
             }
-            case PdbAtomsSelection_MaxSelection:
+            case PdbAtomsSelection::MaxSelection:
             {
                 std::set<int> atomIndicesSet;
                 for (size_t g = 0; g < sel_.size(); ++g)
@@ -746,7 +750,7 @@ void Select::writeOutput()
                 close_trx(status);
                 break;
             }
-            case PdbAtomsSelection_Selected:
+            case PdbAtomsSelection::Selected:
             {
                 std::vector<int> indices;
                 for (int i = 0; i < atoms->nr; ++i)
@@ -761,7 +765,7 @@ void Select::writeOutput()
                 close_trx(status);
                 break;
             }
-            default:
+            case PdbAtomsSelection::Count:
                 GMX_RELEASE_ASSERT(false,
                                    "Mismatch between -pdbatoms enum values and implementation");
         }
index 92d9e52ebe9fe99e8be9f04e5b9c77b223d02452..2807d5894e725cbfb732ca56cbc226fa8dc001cf 100644 (file)
@@ -208,8 +208,7 @@ void TrajectoryAnalysisRunnerCommon::Impl::initFirstFrame()
     {
         return;
     }
-    time_unit_t time_unit = static_cast<time_unit_t>(settings_.timeUnit() + 1); // NOLINT(bugprone-misplaced-widening-cast)
-    output_env_init(&oenv_, getProgramContext(), time_unit, FALSE, exvgNONE, 0);
+    output_env_init(&oenv_, getProgramContext(), settings_.timeUnit(), FALSE, XvgFormat::None, 0);
 
     int frflags = settings_.frflags();
     frflags |= TRX_NEED_X;
index 7af475e6c772c26f0df6fdaff15a0676386705d4..db884d923b61c86a3fd7e5e406a8a665ba09a7c1 100644 (file)
@@ -39,7 +39,7 @@ Other options:
            Atoms stored in the trajectory file (if not set, assume first N
            atoms)
  -xvg    <enum>             (xmgrace)
-           Plot formatting: none, xmgrace, xmgr
+           Plot formatting: xmgrace, xmgr, none
  -[no]rmpbc                 (yes)
            Make molecules whole for each frame
  -[no]pbc                   (yes)
index 3f4308cfe078d90c1455fc96c91af24b06e4f029..9d4cd52eeb04860b614f4c1b2dab611706c90ca3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -157,9 +157,15 @@ void NonbondedBenchmark::initOptions(IOptionsContainer* options, ICommandLineOpt
 
     settings->setHelpText(desc);
 
-    const char* const cNbnxmSimdStrings[]   = { "auto", "no", "4xm", "2xmm" };
-    const char* const cCombRuleStrings[]    = { "geometric", "lb", "none" };
-    const char* const cCoulombTypeStrings[] = { "ewald", "reaction-field" };
+    static const EnumerationArray<Nbnxm::BenchMarkKernels, const char*> c_nbnxmSimdStrings = {
+        { "auto", "no", "4xm", "2xmm" }
+    };
+    static const EnumerationArray<Nbnxm::BenchMarkCombRule, const char*> c_combRuleStrings = {
+        { "geometric", "lb", "none" }
+    };
+    static const EnumerationArray<Nbnxm::BenchMarkCoulomb, const char*> c_coulombTypeStrings = {
+        { "ewald", "reaction-field" }
+    };
 
     options->addOption(
             IntegerOption("size").store(&sizeFactor_).description("The system size is 3000 atoms times this value"));
@@ -167,12 +173,12 @@ void NonbondedBenchmark::initOptions(IOptionsContainer* options, ICommandLineOpt
             IntegerOption("nt").store(&benchmarkOptions_.numThreads).description("The number of OpenMP threads to use"));
     options->addOption(EnumOption<Nbnxm::BenchMarkKernels>("simd")
                                .store(&benchmarkOptions_.nbnxmSimd)
-                               .enumValue(cNbnxmSimdStrings)
+                               .enumValue(c_nbnxmSimdStrings)
                                .description("SIMD type, auto runs all supported SIMD setups or no "
                                             "SIMD when SIMD is not supported"));
     options->addOption(EnumOption<Nbnxm::BenchMarkCoulomb>("coulomb")
                                .store(&benchmarkOptions_.coulombType)
-                               .enumValue(cCoulombTypeStrings)
+                               .enumValue(c_coulombTypeStrings)
                                .description("The functional form for the Coulomb interactions"));
     options->addOption(
             BooleanOption("table")
@@ -180,7 +186,7 @@ void NonbondedBenchmark::initOptions(IOptionsContainer* options, ICommandLineOpt
                     .description("Use lookup table for Ewald correction instead of analytical"));
     options->addOption(EnumOption<Nbnxm::BenchMarkCombRule>("combrule")
                                .store(&benchmarkOptions_.ljCombinationRule)
-                               .enumValue(cCombRuleStrings)
+                               .enumValue(c_combRuleStrings)
                                .description("The LJ combination rule"));
     options->addOption(BooleanOption("halflj")
                                .store(&benchmarkOptions_.useHalfLJOptimization)
index 3b65ed95aa2fc3b5552f5aa22c23a2f7bbff3c3a..1efcc375a9030c2cc3918a3124d34eacd8423728 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -154,7 +154,7 @@ typedef std::shared_ptr<internal::TestReferenceDataImpl> TestReferenceDataImplPo
  */
 TestReferenceDataImplPointer g_referenceData;
 //! Global reference data mode set with setReferenceDataMode().
-ReferenceDataMode g_referenceDataMode = erefdataCompare;
+ReferenceDataMode g_referenceDataMode = ReferenceDataMode::Compare;
 
 //! Returns the global reference data mode.
 ReferenceDataMode getReferenceDataMode()
@@ -268,10 +268,11 @@ void checkUnusedEntries(const ReferenceDataEntry& root, const std::string& rootP
 
 void initReferenceData(IOptionsContainer* options)
 {
-    // Needs to correspond to the enum order in refdata.h.
-    const char* const refDataEnum[] = { "check", "create", "update-changed", "update-all" };
+    static const gmx::EnumerationArray<ReferenceDataMode, const char*> s_refDataNames = {
+        { "check", "create", "update-changed", "update-all" }
+    };
     options->addOption(EnumOption<ReferenceDataMode>("ref-data")
-                               .enumValue(refDataEnum)
+                               .enumValue(s_refDataNames)
                                .store(&g_referenceDataMode)
                                .description("Operation mode for tests that use reference data"));
     ::testing::UnitTest::GetInstance()->listeners().Append(new ReferenceDataTestEventListener);
@@ -296,13 +297,13 @@ TestReferenceDataImpl::TestReferenceDataImpl(ReferenceDataMode mode, bool bSelfT
 
     switch (mode)
     {
-        case erefdataCompare:
+        case ReferenceDataMode::Compare:
             if (File::exists(fullFilename_, File::throwOnError))
             {
                 compareRootEntry_ = readReferenceDataFile(fullFilename_);
             }
             break;
-        case erefdataCreateMissing:
+        case ReferenceDataMode::CreateMissing:
             if (File::exists(fullFilename_, File::throwOnError))
             {
                 compareRootEntry_ = readReferenceDataFile(fullFilename_);
@@ -313,7 +314,7 @@ TestReferenceDataImpl::TestReferenceDataImpl(ReferenceDataMode mode, bool bSelfT
                 outputRootEntry_  = ReferenceDataEntry::createRoot();
             }
             break;
-        case erefdataUpdateChanged:
+        case ReferenceDataMode::UpdateChanged:
             if (File::exists(fullFilename_, File::throwOnError))
             {
                 compareRootEntry_ = readReferenceDataFile(fullFilename_);
@@ -325,10 +326,11 @@ TestReferenceDataImpl::TestReferenceDataImpl(ReferenceDataMode mode, bool bSelfT
             outputRootEntry_          = ReferenceDataEntry::createRoot();
             updateMismatchingEntries_ = true;
             break;
-        case erefdataUpdateAll:
+        case ReferenceDataMode::UpdateAll:
             compareRootEntry_ = ReferenceDataEntry::createRoot();
             outputRootEntry_  = ReferenceDataEntry::createRoot();
             break;
+        case ReferenceDataMode::Count: GMX_THROW(InternalError("Invalid reference data mode"));
     }
 }
 
index a33069170b07ca4eb5d95f8b2e5b864177cdc023..3f681c5be350514cf77be90704ea688849415589 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, 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.
@@ -73,7 +73,7 @@ class FloatingPointTolerance;
  *
  * \ingroup module_testutils
  */
-enum ReferenceDataMode
+enum class ReferenceDataMode : int
 {
     /*! \brief
      * Compare to existing reference data.
@@ -81,36 +81,38 @@ enum ReferenceDataMode
      * If reference data does not exist, or if the test results differ from
      * those in the reference data, the test fails.
      */
-    erefdataCompare,
+    Compare,
     /*! \brief
      * Create missing reference data.
      *
      * If reference data does not exist for a test, that test behaves as if
-     * ::erefdataUpdateAll had been specified.  Tests for which reference data
-     * exists, behave like with ::erefdataCompare.
+     * ReferenceDataMode::UpdateAll had been specified.  Tests for which reference data
+     * exists, behave like with ReferenceDataMode::Compare.
      */
-    erefdataCreateMissing,
+    CreateMissing,
     /*! \brief
      * Update reference data that does not pass comparison.
      *
      * Tests utilizing reference data should always pass in this mode unless
      * there is an I/O error.
      */
-    erefdataUpdateChanged,
+    UpdateChanged,
     /*! \brief
      * Update reference data, overwriting old data.
      *
      * Tests utilizing reference data should always pass in this mode unless
      * there is an I/O error.
      */
-    erefdataUpdateAll
+    UpdateAll,
+    //! Marks the end of the enum
+    Count
 };
 
 /*! \libinternal \brief
  * Initializes reference data handling.
  *
  * Adds command-line options to \p options to set the reference data mode.
- * By default, ::erefdataCompare is used, but ``--ref-data create`` or
+ * By default, ReferenceDataMode::Compare is used, but ``--ref-data create`` or
  * ``--ref-data update`` can be used to change it.
  *
  * This function is automatically called by initTestUtils().
@@ -150,19 +152,25 @@ class TestReferenceDataImpl;
  * \code
    int functionToTest(int param);
 
+   namespace gmx
+   {
+   namespace test
+   {
    TEST(MyTest, SimpleTest)
    {
-       gmx::test::TestReferenceData data;
+       TestReferenceData data;
 
-       gmx::test::TestReferenceChecker checker(data.rootChecker());
+       TestReferenceChecker checker(data.rootChecker());
        checker.checkInteger(functionToTest(3), "ValueWith3");
        checker.checkInteger(functionToTest(5), "ValueWith5");
-       gmx::test::TestReferenceChecker compound(
+       TestReferenceChecker compound(
                checker.checkCompound("CustomCompound", "Item"));
        compound.checkInteger(function2ToTest(3), "ValueWith3");
        compound.checkInteger(function2ToTest(5), "ValueWith5");
        checker.checkInteger(functionToTest(4), "ValueWith4");
    }
+   } // namespace test
+   } // namespace gmx
  * \endcode
  *
  * If rootChecker() is never called, no comparison is done (i.e., missing
index 21744bf4bdc884ff807eefb9e0fde7416f2eb151..93bfb2f1782bac45d86e15bc45b95482c60ab9f7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 
 #include "testutils/refdata.h"
 
+namespace gmx
+{
+namespace test
+{
 namespace
 {
 
 class InteractiveSession
 {
 public:
-    explicit InteractiveSession(gmx::test::ReferenceDataMode mode) :
+    explicit InteractiveSession(ReferenceDataMode mode) :
         data_(mode),
         helper_(data_.rootChecker()),
         nextInputLine_(0)
@@ -123,17 +127,17 @@ private:
     // The latter is the output string.
     typedef std::pair<EventType, const char*> Event;
 
-    gmx::test::TestReferenceData     data_;
-    gmx::test::InteractiveTestHelper helper_;
-    std::vector<const char*>         inputLines_;
-    size_t                           nextInputLine_;
-    std::vector<Event>               events_;
+    TestReferenceData        data_;
+    InteractiveTestHelper    helper_;
+    std::vector<const char*> inputLines_;
+    size_t                   nextInputLine_;
+    std::vector<Event>       events_;
 };
 
 TEST(InteractiveTestHelperTest, ChecksSimpleSession)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n");
         session.addOutput("> ");
         session.addInput("input");
@@ -145,7 +149,7 @@ TEST(InteractiveTestHelperTest, ChecksSimpleSession)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n");
         session.addOutput("> ");
         session.addInput("input");
@@ -161,7 +165,7 @@ TEST(InteractiveTestHelperTest, ChecksSimpleSession)
 TEST(InteractiveTestHelperTest, ChecksSessionWithoutLastNewline)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n");
         session.addOutput("> ");
         session.addInput("input");
@@ -173,7 +177,7 @@ TEST(InteractiveTestHelperTest, ChecksSessionWithoutLastNewline)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n");
         session.addOutput("> ");
         session.addInput("input");
@@ -189,7 +193,7 @@ TEST(InteractiveTestHelperTest, ChecksSessionWithoutLastNewline)
 TEST(InteractiveTestHelperTest, ChecksSessionWithMissingOutput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addInput("input2");
@@ -199,7 +203,7 @@ TEST(InteractiveTestHelperTest, ChecksSessionWithMissingOutput)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addInput("input2");
@@ -213,7 +217,7 @@ TEST(InteractiveTestHelperTest, ChecksSessionWithMissingOutput)
 TEST(InteractiveTestHelperTest, ChecksSessionWithEquivalentOutput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n");
         session.addOutput("> ");
         session.addInput("input");
@@ -224,7 +228,7 @@ TEST(InteractiveTestHelperTest, ChecksSessionWithEquivalentOutput)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addOutput("Second line\n");
@@ -238,7 +242,7 @@ TEST(InteractiveTestHelperTest, ChecksSessionWithEquivalentOutput)
 TEST(InteractiveTestHelperTest, DetectsIncorrectOutput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addOutput("Second line\n> ");
@@ -247,7 +251,7 @@ TEST(InteractiveTestHelperTest, DetectsIncorrectOutput)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addOutput("Incorrect line\n> ");
@@ -260,7 +264,7 @@ TEST(InteractiveTestHelperTest, DetectsIncorrectOutput)
 TEST(InteractiveTestHelperTest, DetectsMissingOutput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addOutput("Second line\n> ");
@@ -271,7 +275,7 @@ TEST(InteractiveTestHelperTest, DetectsMissingOutput)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addInput("input2");
@@ -285,7 +289,7 @@ TEST(InteractiveTestHelperTest, DetectsMissingOutput)
 TEST(InteractiveTestHelperTest, DetectsMissingFinalOutput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addOutput("Second line\n> ");
@@ -294,7 +298,7 @@ TEST(InteractiveTestHelperTest, DetectsMissingFinalOutput)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addOutput("Second line\n> ");
@@ -306,7 +310,7 @@ TEST(InteractiveTestHelperTest, DetectsMissingFinalOutput)
 TEST(InteractiveTestHelperTest, DetectsExtraOutput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addInput("input2");
@@ -316,7 +320,7 @@ TEST(InteractiveTestHelperTest, DetectsExtraOutput)
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addOutput("First line\n> ");
         session.addInput("input");
         session.addOutput("Extra output\n> ");
@@ -331,14 +335,14 @@ TEST(InteractiveTestHelperTest, DetectsExtraOutput)
 TEST(InteractiveTestHelperTest, DetectsMissingInput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addInput("input");
         session.addInput("input2");
         session.addReadInput();
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addInputLine("input");
         session.addInputLine("input2");
         session.addReadInput();
@@ -350,14 +354,14 @@ TEST(InteractiveTestHelperTest, DetectsMissingInput)
 TEST(InteractiveTestHelperTest, DetectsExtraInput)
 {
     {
-        InteractiveSession session(gmx::test::erefdataUpdateAll);
+        InteractiveSession session(ReferenceDataMode::UpdateAll);
         session.addInput("input");
         session.addInput("input2");
         session.addReadInput();
         session.run();
     }
     {
-        InteractiveSession session(gmx::test::erefdataCompare);
+        InteractiveSession session(ReferenceDataMode::Compare);
         session.addInputLine("input");
         session.addInputLine("input2");
         session.addReadInput();
@@ -369,3 +373,5 @@ TEST(InteractiveTestHelperTest, DetectsExtraInput)
 }
 
 } // namespace
+} // namespace test
+} // namespace gmx
index f153800fbc49cec75028cc851c71ce77438c4a32..7cac1ea95ecefe30660f07ddf2574e6909fdb8b9 100644 (file)
 #include "testutils/testasserts.h"
 #include "testutils/testexceptions.h"
 
+
+namespace gmx
+{
+namespace test
+{
 namespace
 {
 
-using gmx::test::TestReferenceChecker;
-using gmx::test::TestReferenceData;
-
 TEST(ReferenceDataTest, HandlesSimpleData)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkBoolean(true, "bool");
         checker.checkInteger(1, "int");
@@ -78,7 +80,7 @@ TEST(ReferenceDataTest, HandlesSimpleData)
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkBoolean(true, "bool");
         checker.checkInteger(1, "int");
@@ -97,14 +99,14 @@ TEST(ReferenceDataTest, HandlesFloatingPointData)
     const double doubleValue = 4.0 / 3.0;
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkDouble(doubleValue, "double");
         checker.checkReal(doubleValue, "real");
         checker.checkFloat(floatValue, "float");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkDouble(doubleValue, "double");
         checker.checkReal(floatValue, "real");
@@ -116,14 +118,14 @@ TEST(ReferenceDataTest, HandlesFloatingPointData)
 TEST(ReferenceDataTest, HandlesPresenceChecks)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_TRUE(checker.checkPresent(true, "present"));
         checker.checkInteger(1, "present");
         EXPECT_FALSE(checker.checkPresent(false, "absent"));
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         // Assigned to avoid warnings about potentially uninitialized value.
         bool bRet = true;
@@ -141,13 +143,13 @@ TEST(ReferenceDataTest, HandlesPresenceChecks)
 TEST(ReferenceDataTest, HandlesStringBlockData)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkTextBlock("Line1\nLine2\n", "block");
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkTextBlock("Line1\nLine2\n", "block");
         checker.checkString("Line1\nLine2\n", "block");
@@ -163,14 +165,14 @@ TEST(ReferenceDataTest, HandlesVectorData)
     double vecd[3] = { -2.3, 1.43, 2.5 };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkVector(veci, "ivec");
         checker.checkVector(vecf, "fvec");
         checker.checkVector(vecd, "dvec");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkVector(veci, "ivec");
         checker.checkVector(vecf, "fvec");
@@ -184,12 +186,12 @@ TEST(ReferenceDataTest, HandlesSequenceData)
     const int seq[5] = { -1, 3, 5, 2, 4 };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkSequenceArray(5, seq, "seq");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkSequenceArray(5, seq, "seq");
     }
@@ -208,12 +210,12 @@ TEST(ReferenceDataTest, HandlesSequenceOfCustomData)
     const dvec seq[] = { { -3, 4, 5 }, { -2.3, 5, 0 } };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkSequence(std::begin(seq), std::end(seq), "seq", checkCustomVector);
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkSequence(std::begin(seq), std::end(seq), "seq", checkCustomVector);
     }
@@ -225,7 +227,7 @@ TEST(ReferenceDataTest, HandlesIncorrectData)
     int seq[5] = { -1, 3, 5, 2, 4 };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkDouble(0.5, "real");
@@ -233,7 +235,7 @@ TEST(ReferenceDataTest, HandlesIncorrectData)
         checker.checkSequenceArray(5, seq, "seq");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_NONFATAL_FAILURE(checker.checkInteger(2, "int"), "");
         EXPECT_NONFATAL_FAILURE(checker.checkDouble(0.3, "real"), "");
@@ -247,13 +249,13 @@ TEST(ReferenceDataTest, HandlesIncorrectData)
 TEST(ReferenceDataTest, HandlesIncorrectDataType)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkCompound("Compound", "compound");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_NONFATAL_FAILURE(checker.checkString("1", "int"), "");
         EXPECT_NONFATAL_FAILURE(checker.checkCompound("OtherCompound", "compound"), "");
@@ -266,13 +268,13 @@ TEST(ReferenceDataTest, HandlesMissingData)
     const int seq[5] = { -1, 3, 5, 2, 4 };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkSequenceArray(5, seq, "seq");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_NONFATAL_FAILURE(checker.checkInteger(1, "missing"), "");
         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "missing"), "");
@@ -287,14 +289,14 @@ TEST(ReferenceDataTest, HandlesUncheckedData)
     const int seq[5] = { -1, 3, 5, 2, 4 };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkSequenceArray(5, seq, "seq");
         checker.checkUnusedEntries();
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         EXPECT_NONFATAL_FAILURE(checker.checkUnusedEntries(), "");
@@ -307,14 +309,14 @@ TEST(ReferenceDataTest, HandlesUncheckedDataInSequence)
     const int seq[5] = { -1, 3, 5, 2, 4 };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkSequenceArray(5, seq, "seq");
         checker.checkUnusedEntries();
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(3, seq, "seq"), "");
@@ -328,7 +330,7 @@ TEST(ReferenceDataTest, HandlesUncheckedDataInSequence)
 TEST(ReferenceDataTest, HandlesUncheckedDataInCompound)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
         compound.checkInteger(1, "int1");
@@ -338,7 +340,7 @@ TEST(ReferenceDataTest, HandlesUncheckedDataInCompound)
         checker.checkUnusedEntries();
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
         compound.checkInteger(1, "int1");
@@ -353,7 +355,7 @@ TEST(ReferenceDataTest, HandlesAnys)
 {
     using gmx::Any;
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkAny(Any::create<bool>(true), "bool");
         checker.checkAny(Any::create<int>(1), "int");
@@ -361,7 +363,7 @@ TEST(ReferenceDataTest, HandlesAnys)
         checker.checkAny(Any::create<std::string>("foo"), "str");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkAny(Any::create<bool>(true), "bool");
         checker.checkAny(Any::create<int>(1), "int");
@@ -393,12 +395,12 @@ TEST(ReferenceDataTest, HandlesKeyValueTree)
 {
     gmx::KeyValueTreeObject tree = buildKeyValueTree(true);
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkKeyValueTreeObject(tree, "tree");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkKeyValueTreeObject(tree, "tree");
     }
@@ -408,12 +410,12 @@ TEST(ReferenceDataTest, HandlesKeyValueTree)
 TEST(ReferenceDataTest, HandlesKeyValueTreeExtraKey)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkKeyValueTreeObject(buildKeyValueTree(false), "tree");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_NONFATAL_FAILURE(checker.checkKeyValueTreeObject(buildKeyValueTree(true), "tree"),
                                 "");
@@ -424,12 +426,12 @@ TEST(ReferenceDataTest, HandlesKeyValueTreeExtraKey)
 TEST(ReferenceDataTest, HandlesKeyValueTreeMissingKey)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkKeyValueTreeObject(buildKeyValueTree(true), "tree");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_NONFATAL_FAILURE(checker.checkKeyValueTreeObject(buildKeyValueTree(false), "tree"),
                                 "");
@@ -441,7 +443,7 @@ TEST(ReferenceDataTest, HandlesAnysWithIncorrectValue)
 {
     using gmx::Any;
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkAny(Any::create<bool>(true), "bool");
         checker.checkAny(Any::create<int>(1), "int");
@@ -449,7 +451,7 @@ TEST(ReferenceDataTest, HandlesAnysWithIncorrectValue)
         checker.checkAny(Any::create<std::string>("foo"), "str");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<bool>(false), "bool"), "");
         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<int>(2), "int"), "");
@@ -463,14 +465,14 @@ TEST(ReferenceDataTest, HandlesAnysWithIncorrectType)
 {
     using gmx::Any;
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkAny(Any::create<bool>(true), "bool");
         checker.checkAny(Any::create<int>(1), "int");
         checker.checkAny(Any::create<double>(3.5), "real");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<int>(1), "bool"), "");
         EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<bool>(true), "int"), "");
@@ -485,7 +487,7 @@ TEST(ReferenceDataTest, HandlesMissingReferenceDataFile)
 
     EXPECT_NONFATAL_FAILURE(
             {
-                TestReferenceData    data(gmx::test::erefdataCompare);
+                TestReferenceData    data(ReferenceDataMode::Compare);
                 TestReferenceChecker checker(data.rootChecker());
                 checker.checkInteger(1, "int");
                 checker.checkDouble(0.5, "real");
@@ -499,7 +501,7 @@ TEST(ReferenceDataTest, HandlesMissingReferenceDataFile)
 TEST(ReferenceDataTest, HandlesSpecialCharactersInStrings)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         // Note that '\r' is not handled correctly in string or
         // stringblock (see the TODO in createElementContents), so
@@ -508,7 +510,7 @@ TEST(ReferenceDataTest, HandlesSpecialCharactersInStrings)
         checker.checkTextBlock("\"<'>\n&\\/;", "stringblock");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("\"<'>\n&\\/;", "string");
         checker.checkTextBlock("\"<'>\n&\\/;", "stringblock");
@@ -520,7 +522,7 @@ TEST(ReferenceDataTest, HandlesStringsWithTextAndWhitespace)
     const char* strings[] = { "  test", "test  ",   "  test  ", "the test",
                               "\ntest", "\n\ntest", "test\n",   "test\n\n" };
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         for (const auto& s : strings)
         {
@@ -529,7 +531,7 @@ TEST(ReferenceDataTest, HandlesStringsWithTextAndWhitespace)
         }
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         for (const auto& s : strings)
         {
@@ -542,21 +544,21 @@ TEST(ReferenceDataTest, HandlesStringsWithTextAndWhitespace)
 TEST(ReferenceDataTest, HandlesEmptyStrings)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("", "Empty");
         // GROMACS cannot use an empty line in a reference data String
         // until https://github.com/leethomason/tinyxml2/issues/432 is
         // resolved.
-        EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), gmx::test::TestException);
+        EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), TestException);
         checker.checkTextBlock("", "EmptyBlock");
         checker.checkTextBlock("\n", "EmptyLineBlock");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("", "Empty");
-        EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), gmx::test::TestException);
+        EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), TestException);
         checker.checkTextBlock("", "EmptyBlock");
         checker.checkTextBlock("\n", "EmptyLineBlock");
     }
@@ -574,12 +576,12 @@ TEST(ReferenceDataTest, HandlesEmbeddedCdataEndTagInTextBlock)
        don't actually depend on this behaviour, but it might be nice
        to have / know about.) */
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkTextBlock(" ]]> ", "stringblock");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkTextBlock(" ]]> ", "stringblock");
     }
@@ -591,13 +593,13 @@ TEST(ReferenceDataTest, HandlesSequenceItemIndices)
     int seq[5] = { -1, 3, 5, 2, 4 };
 
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkSequenceArray(5, seq, "seq");
         checker.checkSequenceArray(5, seq, "seq2");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         seq[0] = 2;
         EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "seq"), "seq/[0]");
@@ -612,7 +614,7 @@ TEST(ReferenceDataTest, HandlesSequenceItemIndices)
 TEST(ReferenceDataTest, HandlesMultipleChecksAgainstSameData)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("Test", "string");
         EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
@@ -620,7 +622,7 @@ TEST(ReferenceDataTest, HandlesMultipleChecksAgainstSameData)
         EXPECT_NONFATAL_FAILURE(checker.checkTextBlock("TestString2", "stringblock"), "");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("Test", "string");
         EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
@@ -633,13 +635,13 @@ TEST(ReferenceDataTest, HandlesMultipleChecksAgainstSameData)
 TEST(ReferenceDataTest, HandlesMultipleNullIds)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("Test", nullptr);
         checker.checkString("Test2", nullptr);
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("Test", nullptr);
         checker.checkString("Test2", nullptr);
@@ -651,7 +653,7 @@ TEST(ReferenceDataTest, HandlesMultipleNullIds)
 TEST(ReferenceDataTest, HandlesMultipleComparisonsAgainstNullIds)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int1");
         checker.checkString("Test", nullptr);
@@ -661,7 +663,7 @@ TEST(ReferenceDataTest, HandlesMultipleComparisonsAgainstNullIds)
         checker.checkString("Test2", nullptr);
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int1");
         checker.checkString("Test", nullptr);
@@ -681,14 +683,14 @@ TEST(ReferenceDataTest, HandlesMultipleComparisonsAgainstNullIds)
 TEST(ReferenceDataTest, HandlesReadingValues)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkUChar('A', "char");
         checker.checkInteger(1, "int");
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         EXPECT_EQ('A', checker.readUChar("char"));
         EXPECT_EQ(1, checker.readInteger("int"));
@@ -700,7 +702,7 @@ TEST(ReferenceDataTest, HandlesReadingValues)
 TEST(ReferenceDataTest, HandlesUpdateChangedWithoutChanges)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkString("Test", "string");
@@ -708,7 +710,7 @@ TEST(ReferenceDataTest, HandlesUpdateChangedWithoutChanges)
         compound.checkInteger(2, "int");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateChanged);
+        TestReferenceData    data(ReferenceDataMode::UpdateChanged);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkString("Test", "string");
@@ -716,7 +718,7 @@ TEST(ReferenceDataTest, HandlesUpdateChangedWithoutChanges)
         compound.checkInteger(2, "int");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkString("Test", "string");
@@ -728,19 +730,19 @@ TEST(ReferenceDataTest, HandlesUpdateChangedWithoutChanges)
 TEST(ReferenceDataTest, HandlesUpdateChangedWithValueChanges)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateChanged);
+        TestReferenceData    data(ReferenceDataMode::UpdateChanged);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(2, "int");
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(2, "int");
         checker.checkString("Test", "string");
@@ -750,19 +752,19 @@ TEST(ReferenceDataTest, HandlesUpdateChangedWithValueChanges)
 TEST(ReferenceDataTest, HandlesUpdateChangedWithTypeChanges)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "foo");
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateChanged);
+        TestReferenceData    data(ReferenceDataMode::UpdateChanged);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("foo", "foo");
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkString("foo", "foo");
         checker.checkString("Test", "string");
@@ -772,21 +774,21 @@ TEST(ReferenceDataTest, HandlesUpdateChangedWithTypeChanges)
 TEST(ReferenceDataTest, HandlesUpdateChangedWithCompoundChanges)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "1");
         TestReferenceChecker compound(checker.checkCompound("Compound", "2"));
         compound.checkInteger(2, "int");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateChanged);
+        TestReferenceData    data(ReferenceDataMode::UpdateChanged);
         TestReferenceChecker checker(data.rootChecker());
         TestReferenceChecker compound(checker.checkCompound("Compound", "1"));
         compound.checkInteger(2, "int");
         checker.checkString("Test", "2");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         TestReferenceChecker compound(checker.checkCompound("Compound", "1"));
         compound.checkInteger(2, "int");
@@ -797,21 +799,23 @@ TEST(ReferenceDataTest, HandlesUpdateChangedWithCompoundChanges)
 TEST(ReferenceDataTest, HandlesUpdateChangedWithRemovedEntries)
 {
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateAll);
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(1, "int");
         checker.checkString("Test", "string");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataUpdateChanged);
+        TestReferenceData    data(ReferenceDataMode::UpdateChanged);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(2, "int");
     }
     {
-        TestReferenceData    data(gmx::test::erefdataCompare);
+        TestReferenceData    data(ReferenceDataMode::Compare);
         TestReferenceChecker checker(data.rootChecker());
         checker.checkInteger(2, "int");
     }
 }
 
 } // namespace
+} // namespace test
+} // namespace gmx
index f8381a8ca681dae0c6d63544d3584030664fa1ec..c8dc14164f13d5c16c3d8776db1c19a78db26ee6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 #include "testutils/refdata.h"
 #include "testutils/testasserts.h"
 
+namespace gmx
+{
+namespace test
+{
 namespace
 {
 
-using gmx::test::checkXvgFile;
-using gmx::test::XvgMatchSettings;
-
 //! Input testing data - an inline xvg file.
 const char* const input[] = { "0     2905.86    -410.199",   "0.2     6656.67    -430.437",
                               "0.4     5262.44    -409.399", "0.6     5994.69    -405.763",
@@ -69,16 +70,16 @@ TEST(XvgTests, CreateFile)
 {
     {
         // Create new data
-        gmx::test::TestReferenceData    data(gmx::test::erefdataUpdateAll);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
         // Convert char array to a stream and add it to the checker
         gmx::StringInputStream sis(input);
         checkXvgFile(&sis, &checker, XvgMatchSettings());
     }
     {
         // Now read it back
-        gmx::test::TestReferenceData    data(gmx::test::erefdataCompare);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
+        TestReferenceData    data(ReferenceDataMode::Compare);
+        TestReferenceChecker checker(data.rootChecker());
         // Convert char array to a stream and add it to the checker
         gmx::StringInputStream sis(input);
         checkXvgFile(&sis, &checker, XvgMatchSettings());
@@ -89,8 +90,8 @@ TEST(XvgTests, CheckMissing)
 {
     {
         // Create new data
-        gmx::test::TestReferenceData    data(gmx::test::erefdataUpdateAll);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
         // Convert char array to a stream and add it to the checker
         gmx::StringInputStream sis(input);
         checkXvgFile(&sis, &checker, XvgMatchSettings());
@@ -99,9 +100,9 @@ TEST(XvgTests, CheckMissing)
         const char* const input[] = { "0     2905.86    -410.199", "0.2     6656.67    -430.437",
                                       "0.4     5262.44    -409.399" };
         // Now check with missing data
-        gmx::test::TestReferenceData    data(gmx::test::erefdataCompare);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
-        gmx::StringInputStream          sis(input);
+        TestReferenceData      data(ReferenceDataMode::Compare);
+        TestReferenceChecker   checker(data.rootChecker());
+        gmx::StringInputStream sis(input);
         EXPECT_NONFATAL_FAILURE(checkXvgFile(&sis, &checker, XvgMatchSettings()),
                                 "not used in test");
     }
@@ -111,8 +112,8 @@ TEST(XvgTests, CheckExtra)
 {
     {
         // Create new data
-        gmx::test::TestReferenceData    data(gmx::test::erefdataUpdateAll);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
         // Convert char array to a stream and add it to the checker
         gmx::StringInputStream sis(input);
         checkXvgFile(&sis, &checker, XvgMatchSettings());
@@ -123,9 +124,9 @@ TEST(XvgTests, CheckExtra)
                                       "0.8     5941.37    -408.337", "1     5869.87    -411.124",
                                       "1.2     5889.87    -413.124" };
         // Now check with missing data
-        gmx::test::TestReferenceData    data(gmx::test::erefdataCompare);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
-        gmx::StringInputStream          sis(input);
+        TestReferenceData      data(ReferenceDataMode::Compare);
+        TestReferenceChecker   checker(data.rootChecker());
+        gmx::StringInputStream sis(input);
         EXPECT_NONFATAL_FAILURE(checkXvgFile(&sis, &checker, XvgMatchSettings()), "Row6");
     }
 }
@@ -134,8 +135,8 @@ TEST(XvgTests, ReadIncorrect)
 {
     {
         // Create new data
-        gmx::test::TestReferenceData    data(gmx::test::erefdataUpdateAll);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
+        TestReferenceData    data(ReferenceDataMode::UpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
         // Convert char array to a stream and add it to the checker
         gmx::StringInputStream sis(input);
         checkXvgFile(&sis, &checker, XvgMatchSettings());
@@ -145,11 +146,13 @@ TEST(XvgTests, ReadIncorrect)
                                       "0.4     5262.44    -409.399", "0.6     5994.69    -405.763",
                                       "0.8     5941.37    -408.337", "1     5869.87    -421.124" };
         // Now check with incorrect data
-        gmx::test::TestReferenceData    data(gmx::test::erefdataCompare);
-        gmx::test::TestReferenceChecker checker(data.rootChecker());
-        gmx::StringInputStream          sis(input);
+        TestReferenceData      data(ReferenceDataMode::Compare);
+        TestReferenceChecker   checker(data.rootChecker());
+        gmx::StringInputStream sis(input);
         EXPECT_NONFATAL_FAILURE(checkXvgFile(&sis, &checker, XvgMatchSettings()), "-411");
     }
 }
 
 } // namespace
+} // namespace test
+} // namespace gmx