Refactor PME tests for better usability
[alexxy/gromacs.git] / src / gromacs / ewald / tests / pmesplinespreadtest.cpp
index 67ea564d330fb3a3eb5cf0f809cd8949596bbea2..db97f313bdcd45452dbce5bf81b18d5f43b50440 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -37,6 +37,7 @@
  * Implements PME spline computation and charge spreading tests.
  *
  * \author Aleksei Iupinov <a.yupinov@gmail.com>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
  * \ingroup module_ewald
  */
 
@@ -50,6 +51,7 @@
 #include "gromacs/utility/stringutil.h"
 
 #include "testutils/refdata.h"
+#include "testutils/test_hardware_environment.h"
 #include "testutils/testasserts.h"
 
 #include "pmetestcommon.h"
@@ -61,301 +63,333 @@ namespace test
 namespace
 {
 
+//! A couple of valid inputs for grid sizes
+std::vector<IVec> const c_inputGridSizes{ IVec{ 16, 12, 14 }, IVec{ 19, 17, 11 } };
+
 //! PME spline and spread code path being tested
-enum class PmeSplineAndSpreadOptions
+enum class SplineAndSpreadOptions
 {
     SplineOnly,
     SpreadOnly,
-    SplineAndSpreadUnified
+    SplineAndSpreadUnified,
+    Count
+};
+
+struct TestSystem
+{
+    CoordinatesVector coordinates;
+    ChargesVector     charges;
 };
 
-/*! \brief Convenience typedef of input parameters - unit cell box, PME interpolation order, grid dimensions,
- * particle coordinates, particle charges
+const std::unordered_map<std::string, TestSystem> c_testSystems = {
+    { "1 atom", { CoordinatesVector{ { 5.59F, 1.37F, 0.95F } }, ChargesVector{ 4.95F } } },
+    { "2 atoms",
+      { CoordinatesVector{
+                // 2 box lengths in x
+                { 16.0F, 1.02F, 0.22F },
+                { 0.034F, 1.65F, 0.22F },
+        },
+        ChargesVector{ {
+                3.11F,
+                3.97F,
+        } } } },
+    { "13 atoms",
+      { CoordinatesVector{
+                { 0.33F, 0.92F, 1.56F },
+                { 1.16F, 0.75F, 0.39F },
+                { 0.5F, 1.63F, 1.14F },
+                // > 2 box lengths in x
+                { 16.0001F, 1.52F, 1.19F },
+                // > 2 box lengths in z
+                { 1.43F, 1.1F, 4.1F },
+                // negative x
+                { -1.08F, 1.19F, 0.08F },
+                { 1.6F, 0.93F, 0.53F },
+                // negative y
+                { 1.32F, -1.48F, 0.16F },
+                { 0.87F, 0.0F, 0.33F },
+                // > 2 box lengths in y, negative z
+                { 0.95F, 7.7F, -0.48F },
+                { 1.23F, 0.91F, 0.68F },
+                { 0.19F, 1.45F, 0.94F },
+                { 1.28F, 0.46F, 0.38F },
+        },
+        ChargesVector{ 1.08F, 2.09F, 1.1F, 4.13F, 3.31F, 2.8F, 5.83F, 5.09F, 6.1F, 2.86F, 0.24F, 5.76F, 5.19F } } },
+};
+
+/* Valid input instances */
+
+/*! \brief Convenience typedef of input parameters - unit cell box, PME interpolation order, grid
+ * dimensions, particle coordinates, particle charges
  * TODO: consider inclusion of local grid offsets/sizes or PME nodes counts to test the PME DD
  */
-typedef std::tuple<Matrix3x3, int, IVec, CoordinatesVector, ChargesVector> SplineAndSpreadInputParameters;
+typedef std::tuple<std::string, int, IVec, std::string> SplineAndSpreadInputParameters;
+
+//! Help GoogleTest name our test cases
+std::string nameOfTest(const testing::TestParamInfo<SplineAndSpreadInputParameters>& info)
+{
+    std::string testName = formatString(
+            "box_%s_"
+            "order_%d_"
+            "grid_%d_%d_%d_"
+            "system_%s",
+            std::get<0>(info.param).c_str(),
+            std::get<1>(info.param),
+            std::get<2>(info.param)[XX],
+            std::get<2>(info.param)[YY],
+            std::get<2>(info.param)[ZZ],
+            std::get<3>(info.param).c_str());
+
+    // Note that the returned names must be unique and may use only
+    // alphanumeric ASCII characters. It's not supposed to contain
+    // underscores (see the GoogleTest FAQ
+    // why-should-test-suite-names-and-test-names-not-contain-underscore),
+    // but doing so works for now, is likely to remain so, and makes
+    // such test names much more readable.
+    testName = replaceAll(testName, "-", "_");
+    testName = replaceAll(testName, ".", "_");
+    testName = replaceAll(testName, " ", "_");
+    return testName;
+}
+
+const char* enumValueToString(SplineAndSpreadOptions enumValue)
+{
+    static constexpr gmx::EnumerationArray<SplineAndSpreadOptions, const char*> s_splineAndSpreadOptionsNames = {
+        "spline computation",
+        "charge spreading",
+        "spline computation and charge spreading (fused)",
+    };
+    return s_splineAndSpreadOptionsNames[enumValue];
+}
 
 /*! \brief Test fixture for testing both atom spline parameter computation and charge spreading.
  * These 2 stages of PME are tightly coupled in the code.
  */
-class PmeSplineAndSpreadTest : public ::testing::TestWithParam<SplineAndSpreadInputParameters>
+class SplineAndSpreadTest : public ::testing::TestWithParam<SplineAndSpreadInputParameters>
 {
-    public:
-        //! Default constructor
-        PmeSplineAndSpreadTest() = default;
-        //! The test
-        void runTest()
+public:
+    SplineAndSpreadTest() = default;
+
+    static void SetUpTestSuite()
+    {
+        s_pmeTestHardwareContexts    = createPmeTestHardwareContextList();
+        g_allowPmeWithSyclForTesting = true; // We support PmeSplineAndSpread with SYCL
+    }
+
+    static void TearDownTestSuite()
+    {
+        // Revert the value back.
+        g_allowPmeWithSyclForTesting = false;
+    }
+
+    //! The test
+    static void runTest()
+    {
+        /* Getting the input */
+        int         pmeOrder;
+        IVec        gridSize;
+        std::string boxName, testSystemName;
+
+        std::tie(boxName, pmeOrder, gridSize, testSystemName) = GetParam();
+        Matrix3x3                box                          = c_inputBoxes.at(boxName);
+        const CoordinatesVector& coordinates = c_testSystems.at(testSystemName).coordinates;
+        const ChargesVector&     charges     = c_testSystems.at(testSystemName).charges;
+        const size_t             atomCount   = coordinates.size();
+
+        /* Storing the input where it's needed */
+        t_inputrec inputRec;
+        inputRec.nkx         = gridSize[XX];
+        inputRec.nky         = gridSize[YY];
+        inputRec.nkz         = gridSize[ZZ];
+        inputRec.pme_order   = pmeOrder;
+        inputRec.coulombtype = CoulombInteractionType::Pme;
+        inputRec.epsilon_r   = 1.0;
+
+        // There is a subtle problem with multiple comparisons against same reference data:
+        // The subsequent (GPU) spreading runs at one point didn't actually copy the output grid
+        // into the proper buffer, but the reference data was already marked as checked
+        // (hasBeenChecked_) by the CPU run, so nothing failed. For now we will manually track that
+        // the count of the grid entries is the same on each run. This is just a hack for a single
+        // specific output though. What would be much better TODO is to split different codepaths
+        // into separate tests, while making them use the same reference files.
+        bool   gridValuesSizeAssigned = false;
+        size_t previousGridValuesSize;
+
+        TestReferenceData refData;
+        for (const auto& pmeTestHardwareContext : s_pmeTestHardwareContexts)
         {
-            /* Getting the input */
-            Matrix3x3               box;
-            int                     pmeOrder;
-            IVec                    gridSize;
-            CoordinatesVector       coordinates;
-            ChargesVector           charges;
-
-            std::tie(box, pmeOrder, gridSize, coordinates, charges) = GetParam();
-            const size_t atomCount = coordinates.size();
-
-            /* Storing the input where it's needed */
-            t_inputrec inputRec;
-            inputRec.nkx         = gridSize[XX];
-            inputRec.nky         = gridSize[YY];
-            inputRec.nkz         = gridSize[ZZ];
-            inputRec.pme_order   = pmeOrder;
-            inputRec.coulombtype = eelPME;
-            inputRec.epsilon_r   = 1.0;
-
-            TestReferenceData                                      refData;
-
-            const std::map<CodePath, std::string>                  modesToTest   = {{CodePath::CPU, "CPU"},
-                                                                                    {CodePath::CUDA, "CUDA"}};
-
-            const std::map<PmeSplineAndSpreadOptions, std::string> optionsToTest = {{PmeSplineAndSpreadOptions::SplineAndSpreadUnified, "spline computation and charge spreading (fused)"},
-                                                                                    {PmeSplineAndSpreadOptions::SplineOnly, "spline computation"},
-                                                                                    {PmeSplineAndSpreadOptions::SpreadOnly, "charge spreading"}};
-
-            // There is a subtle problem with multiple comparisons against same reference data:
-            // The subsequent (GPU) spreading runs at one point didn't actually copy the output grid into the proper buffer,
-            // but the reference data was already marked as checked (hasBeenChecked_) by the CPU run, so nothing failed.
-            // For now we will manually track that the count of the grid entries is the same on each run.
-            // This is just a hack for a single specific output though.
-            // What would be much better TODO is to split different codepaths into separate tests,
-            // while making them use the same reference files.
-            bool   gridValuesSizeAssigned = false;
-            size_t previousGridValuesSize;
-
-            for (const auto &mode : modesToTest)
+            pmeTestHardwareContext->activate();
+            CodePath   codePath       = pmeTestHardwareContext->codePath();
+            const bool supportedInput = pmeSupportsInputForMode(
+                    *getTestHardwareEnvironment()->hwinfo(), &inputRec, codePath);
+            if (!supportedInput)
+            {
+                /* Testing the failure for the unsupported input */
+                EXPECT_THROW_GMX(pmeInitWrapper(&inputRec, codePath, nullptr, nullptr, nullptr, box),
+                                 NotImplementedError);
+                continue;
+            }
+
+            for (SplineAndSpreadOptions option : EnumerationWrapper<SplineAndSpreadOptions>())
             {
-                const bool supportedInput = pmeSupportsInputForMode(&inputRec, mode.first);
-                if (!supportedInput)
+                /* Describing the test uniquely in case it fails */
+
+                SCOPED_TRACE(
+                        formatString("Testing %s on %s for PME grid size %d %d %d"
+                                     ", order %d, %zu atoms",
+                                     enumValueToString(option),
+                                     pmeTestHardwareContext->description().c_str(),
+                                     gridSize[XX],
+                                     gridSize[YY],
+                                     gridSize[ZZ],
+                                     pmeOrder,
+                                     atomCount));
+
+                /* Running the test */
+
+                PmeSafePointer                          pmeSafe = pmeInitWrapper(&inputRec,
+                                                        codePath,
+                                                        pmeTestHardwareContext->deviceContext(),
+                                                        pmeTestHardwareContext->deviceStream(),
+                                                        pmeTestHardwareContext->pmeGpuProgram(),
+                                                        box);
+                std::unique_ptr<StatePropagatorDataGpu> stateGpu =
+                        (codePath == CodePath::GPU)
+                                ? makeStatePropagatorDataGpu(*pmeSafe.get(),
+                                                             pmeTestHardwareContext->deviceContext(),
+                                                             pmeTestHardwareContext->deviceStream())
+                                : nullptr;
+
+                pmeInitAtoms(pmeSafe.get(), stateGpu.get(), codePath, coordinates, charges);
+
+                const bool computeSplines = (option == SplineAndSpreadOptions::SplineOnly)
+                                            || (option == SplineAndSpreadOptions::SplineAndSpreadUnified);
+                const bool spreadCharges = (option == SplineAndSpreadOptions::SpreadOnly)
+                                           || (option == SplineAndSpreadOptions::SplineAndSpreadUnified);
+
+                if (!computeSplines)
+                {
+                    // Here we should set up the results of the spline computation so that the spread can run.
+                    // What is lazy and works is running the separate spline so that it will set it up for us:
+                    pmePerformSplineAndSpread(pmeSafe.get(), codePath, true, false);
+                    // We know that it is tested in another iteration.
+                    // TODO: Clean alternative: read and set the reference gridline indices, spline params
+                }
+
+                pmePerformSplineAndSpread(pmeSafe.get(), codePath, computeSplines, spreadCharges);
+                pmeFinalizeTest(pmeSafe.get(), codePath);
+
+                /* Outputs correctness check */
+                /* All tolerances were picked empirically for single precision on CPU */
+
+                TestReferenceChecker rootChecker(refData.rootChecker());
+
+                const auto maxGridSize = std::max(std::max(gridSize[XX], gridSize[YY]), gridSize[ZZ]);
+                const auto ulpToleranceSplineValues = 4 * (pmeOrder - 2) * maxGridSize;
+                /* 4 is a modest estimate for amount of operations; (pmeOrder - 2) is a number of iterations;
+                 * maxGridSize is inverse of the smallest positive fractional coordinate (which are interpolated by the splines).
+                 */
+
+                if (computeSplines)
                 {
-                    /* Testing the failure for the unsupported input */
-                    EXPECT_THROW(pmeInitAtoms(&inputRec, mode.first, nullptr, coordinates, charges, box), NotImplementedError);
-                    continue;
+                    const char* dimString[] = { "X", "Y", "Z" };
+
+                    /* Spline values */
+                    SCOPED_TRACE(formatString("Testing spline values with tolerance of %d",
+                                              ulpToleranceSplineValues));
+                    TestReferenceChecker splineValuesChecker(
+                            rootChecker.checkCompound("Splines", "Values"));
+                    splineValuesChecker.setDefaultTolerance(
+                            relativeToleranceAsUlp(1.0, ulpToleranceSplineValues));
+                    for (int i = 0; i < DIM; i++)
+                    {
+                        auto splineValuesDim =
+                                pmeGetSplineData(pmeSafe.get(), codePath, PmeSplineDataType::Values, i);
+                        splineValuesChecker.checkSequence(
+                                splineValuesDim.begin(), splineValuesDim.end(), dimString[i]);
+                    }
+
+                    /* Spline derivatives */
+                    const auto ulpToleranceSplineDerivatives = 4 * ulpToleranceSplineValues;
+                    /* 4 is just a wild guess since the derivatives are deltas of neighbor spline values which could differ greatly */
+                    SCOPED_TRACE(formatString("Testing spline derivatives with tolerance of %d",
+                                              ulpToleranceSplineDerivatives));
+                    TestReferenceChecker splineDerivativesChecker(
+                            rootChecker.checkCompound("Splines", "Derivatives"));
+                    splineDerivativesChecker.setDefaultTolerance(
+                            relativeToleranceAsUlp(1.0, ulpToleranceSplineDerivatives));
+                    for (int i = 0; i < DIM; i++)
+                    {
+                        auto splineDerivativesDim = pmeGetSplineData(
+                                pmeSafe.get(), codePath, PmeSplineDataType::Derivatives, i);
+                        splineDerivativesChecker.checkSequence(
+                                splineDerivativesDim.begin(), splineDerivativesDim.end(), dimString[i]);
+                    }
+
+                    /* Particle gridline indices */
+                    auto gridLineIndices = pmeGetGridlineIndices(pmeSafe.get(), codePath);
+                    rootChecker.checkSequence(
+                            gridLineIndices.begin(), gridLineIndices.end(), "Gridline indices");
                 }
 
-                const auto contextsToTest = pmeEnv->getHardwareContexts(mode.first);
-                for (const auto &context : contextsToTest)
+                if (spreadCharges)
                 {
-                    for (const auto &option : optionsToTest)
+                    /* The wrapped grid */
+                    SparseRealGridValuesOutput nonZeroGridValues = pmeGetRealGrid(pmeSafe.get(), codePath);
+                    TestReferenceChecker gridValuesChecker(
+                            rootChecker.checkCompound("NonZeroGridValues", "RealSpaceGrid"));
+                    const auto ulpToleranceGrid =
+                            2 * ulpToleranceSplineValues
+                            * static_cast<int>(ceil(sqrt(static_cast<real>(atomCount))));
+                    /* 2 is empiric; sqrt(atomCount) assumes all the input charges may spread onto the same cell */
+                    SCOPED_TRACE(formatString("Testing grid values with tolerance of %d", ulpToleranceGrid));
+                    if (!gridValuesSizeAssigned)
+                    {
+                        previousGridValuesSize = nonZeroGridValues.size();
+                        gridValuesSizeAssigned = true;
+                    }
+                    else
                     {
-                        /* Describing the test uniquely in case it fails */
-
-                        SCOPED_TRACE(formatString("Testing %s with %s %sfor PME grid size %d %d %d"
-                                                  ", order %d, %zu atoms",
-                                                  option.second.c_str(), mode.second.c_str(),
-                                                  context.getDescription().c_str(),
-                                                  gridSize[XX], gridSize[YY], gridSize[ZZ],
-                                                  pmeOrder,
-                                                  atomCount));
-
-                        /* Running the test */
-
-                        PmeSafePointer pmeSafe = pmeInitAtoms(&inputRec, mode.first, context.getDeviceInfo(), coordinates, charges, box);
-
-                        const bool     computeSplines = (option.first == PmeSplineAndSpreadOptions::SplineOnly) || (option.first == PmeSplineAndSpreadOptions::SplineAndSpreadUnified);
-                        const bool     spreadCharges  = (option.first == PmeSplineAndSpreadOptions::SpreadOnly) || (option.first == PmeSplineAndSpreadOptions::SplineAndSpreadUnified);
-
-                        if (!computeSplines)
-                        {
-                            // Here we should set up the results of the spline computation so that the spread can run.
-                            // What is lazy and works is running the separate spline so that it will set it up for us:
-                            pmePerformSplineAndSpread(pmeSafe.get(), mode.first, true, false);
-                            // We know that it is tested in another iteration.
-                            // TODO: Clean alternative: read and set the reference gridline indices, spline params
-                        }
-
-                        pmePerformSplineAndSpread(pmeSafe.get(), mode.first, computeSplines, spreadCharges);
-                        pmeFinalizeTest(pmeSafe.get(), mode.first);
-
-                        /* Outputs correctness check */
-                        /* All tolerances were picked empirically for single precision on CPU */
-
-                        TestReferenceChecker rootChecker(refData.rootChecker());
-
-                        const auto           maxGridSize              = std::max(std::max(gridSize[XX], gridSize[YY]), gridSize[ZZ]);
-                        const auto           ulpToleranceSplineValues = 2 * (pmeOrder - 2) * maxGridSize;
-                        /* 2 is empiric, the rest follows from the amount of operations */
-
-                        if (computeSplines)
-                        {
-                            const char *dimString[] = { "X", "Y", "Z" };
-
-                            /* Spline values */
-                            SCOPED_TRACE(formatString("Testing spline values with tolerance of %ld", ulpToleranceSplineValues));
-                            TestReferenceChecker splineValuesChecker(rootChecker.checkCompound("Splines", "Values"));
-                            splineValuesChecker.setDefaultTolerance(getSplineTolerance(ulpToleranceSplineValues));
-                            for (int i = 0; i < DIM; i++)
-                            {
-                                auto splineValuesDim = pmeGetSplineData(pmeSafe.get(), mode.first, PmeSplineDataType::Values, i);
-                                splineValuesChecker.checkSequence(splineValuesDim.begin(), splineValuesDim.end(), dimString[i]);
-                            }
-
-                            /* Spline derivatives */
-                            const auto ulpToleranceSplineDerivatives = 4 * ulpToleranceSplineValues;
-                            /* 4 is just a wild guess since the derivatives are deltas of neighbor spline values which could differ greatly */
-                            SCOPED_TRACE(formatString("Testing spline derivatives with tolerance of %ld", ulpToleranceSplineDerivatives));
-                            TestReferenceChecker splineDerivativesChecker(rootChecker.checkCompound("Splines", "Derivatives"));
-                            splineDerivativesChecker.setDefaultTolerance(getSplineTolerance(ulpToleranceSplineDerivatives));
-                            for (int i = 0; i < DIM; i++)
-                            {
-                                auto splineDerivativesDim = pmeGetSplineData(pmeSafe.get(), mode.first, PmeSplineDataType::Derivatives, i);
-                                splineDerivativesChecker.checkSequence(splineDerivativesDim.begin(), splineDerivativesDim.end(), dimString[i]);
-                            }
-
-                            /* Particle gridline indices */
-                            auto gridLineIndices = pmeGetGridlineIndices(pmeSafe.get(), mode.first);
-                            rootChecker.checkSequence(gridLineIndices.begin(), gridLineIndices.end(), "Gridline indices");
-                        }
-
-                        if (spreadCharges)
-                        {
-                            /* The wrapped grid */
-                            SparseRealGridValuesOutput nonZeroGridValues = pmeGetRealGrid(pmeSafe.get(), mode.first);
-                            TestReferenceChecker       gridValuesChecker(rootChecker.checkCompound("NonZeroGridValues", "RealSpaceGrid"));
-                            const auto                 ulpToleranceGrid = 2 * ulpToleranceSplineValues * (int)(ceil(sqrt(atomCount)));
-                            /* 2 is empiric; sqrt(atomCount) assumes all the input charges may spread onto the same cell */
-                            SCOPED_TRACE(formatString("Testing grid values with tolerance of %ld", ulpToleranceGrid));
-                            if (!gridValuesSizeAssigned)
-                            {
-                                previousGridValuesSize = nonZeroGridValues.size();
-                                gridValuesSizeAssigned = true;
-                            }
-                            else
-                            {
-                                EXPECT_EQ(previousGridValuesSize, nonZeroGridValues.size());
-                            }
-
-                            gridValuesChecker.setDefaultTolerance(getSplineTolerance(ulpToleranceGrid));
-                            for (const auto &point : nonZeroGridValues)
-                            {
-                                gridValuesChecker.checkReal(point.second, point.first.c_str());
-                            }
-                        }
+                        EXPECT_EQ(previousGridValuesSize, nonZeroGridValues.size());
+                    }
+
+                    gridValuesChecker.setDefaultTolerance(relativeToleranceAsUlp(1.0, ulpToleranceGrid));
+                    for (const auto& point : nonZeroGridValues)
+                    {
+                        gridValuesChecker.checkReal(point.second, point.first.c_str());
                     }
                 }
             }
         }
+    }
+
+    static std::vector<std::unique_ptr<PmeTestHardwareContext>> s_pmeTestHardwareContexts;
 };
 
+std::vector<std::unique_ptr<PmeTestHardwareContext>> SplineAndSpreadTest::s_pmeTestHardwareContexts;
+
 
 /*! \brief Test for spline parameter computation and charge spreading. */
-TEST_P(PmeSplineAndSpreadTest, ReproducesOutputs)
+TEST_P(SplineAndSpreadTest, WorksWith)
 {
-    EXPECT_NO_THROW(runTest());
+    EXPECT_NO_THROW_GMX(runTest());
 }
 
-/* Valid input instances */
-
-//! A couple of valid inputs for boxes.
-static std::vector<Matrix3x3> const c_sampleBoxes
-{
-    // normal box
-    Matrix3x3 {{
-                   8.0f, 0.0f, 0.0f,
-                   0.0f, 3.4f, 0.0f,
-                   0.0f, 0.0f, 2.0f
-               }},
-    // triclinic box
-    Matrix3x3 {{
-                   7.0f, 0.0f, 0.0f,
-                   0.0f, 4.1f, 0.0f,
-                   3.5f, 2.0f, 12.2f
-               }},
-};
-
-//! A couple of valid inputs for grid sizes.
-static std::vector<IVec> const c_sampleGridSizes
-{
-    IVec {
-        16, 12, 14
-    },
-    IVec {
-        19, 17, 11
-    }
-};
-
-//! Random charges
-static std::vector<real> const c_sampleChargesFull
-{
-    4.95f, 3.11f, 3.97f, 1.08f, 2.09f, 1.1f, 4.13f, 3.31f, 2.8f, 5.83f, 5.09f, 6.1f, 2.86f, 0.24f, 5.76f, 5.19f, 0.72f
-};
-//! 1 charge
-static auto const c_sampleCharges1 = ChargesVector::fromVector(c_sampleChargesFull.begin(), c_sampleChargesFull.begin() + 1);
-//! 2 charges
-static auto const c_sampleCharges2 = ChargesVector::fromVector(c_sampleChargesFull.begin() + 1, c_sampleChargesFull.begin() + 3);
-//! 13 charges
-static auto const c_sampleCharges13 = ChargesVector::fromVector(c_sampleChargesFull.begin() + 3, c_sampleChargesFull.begin() + 16);
-
-//! Random coordinate vectors
-static CoordinatesVector const c_sampleCoordinatesFull
-{
-    {
-        5.59f, 1.37f, 0.95f
-    }, {
-        16.0f, 1.02f, 0.22f      // 2 box lengths in x
-    }, {
-        0.034f, 1.65f, 0.22f
-    }, {
-        0.33f, 0.92f, 1.56f
-    }, {
-        1.16f, 0.75f, 0.39f
-    }, {
-        0.5f, 1.63f, 1.14f
-    }, {
-        16.0001f, 1.52f, 1.19f  // > 2 box lengths in x
-    }, {
-        1.43f, 1.1f, 4.1f       // > 2 box lengths in z
-    }, {
-        -1.08f, 1.19f, 0.08f    // negative x
-    }, {
-        1.6f, 0.93f, 0.53f
-    }, {
-        1.32f, -1.48f, 0.16f    // negative y
-    }, {
-        0.87f, 0.0f, 0.33f
-    }, {
-        0.95f, 7.7f, -0.48f     // > 2 box lengths in y, negative z
-    }, {
-        1.23f, 0.91f, 0.68f
-    }, {
-        0.19f, 1.45f, 0.94f
-    }, {
-        1.28f, 0.46f, 0.38f
-    }, {
-        1.21f, 0.23f, 1.0f
-    }
-};
-//! 1 coordinate vector
-static CoordinatesVector const c_sampleCoordinates1(c_sampleCoordinatesFull.begin(), c_sampleCoordinatesFull.begin() + 1);
-//! 2 coordinate vectors
-static CoordinatesVector const c_sampleCoordinates2(c_sampleCoordinatesFull.begin() + 1, c_sampleCoordinatesFull.begin() + 3);
-//! 13 coordinate vectors
-static CoordinatesVector const c_sampleCoordinates13(c_sampleCoordinatesFull.begin() + 3, c_sampleCoordinatesFull.begin() + 16);
-
-//! moved out from instantiantions for readability
-auto c_inputBoxes     = ::testing::ValuesIn(c_sampleBoxes);
-//! moved out from instantiantions for readability
-auto c_inputPmeOrders = ::testing::Range(3, 5 + 1);
-//! moved out from instantiantions for readability
-auto c_inputGridSizes = ::testing::ValuesIn(c_sampleGridSizes);
-
-/*! \brief Instantiation of the test with valid input and 1 atom */
-INSTANTIATE_TEST_CASE_P(SaneInput1, PmeSplineAndSpreadTest, ::testing::Combine(c_inputBoxes, c_inputPmeOrders, c_inputGridSizes,
-                                                                                   ::testing::Values(c_sampleCoordinates1),
-                                                                                   ::testing::Values(c_sampleCharges1)
-                                                                               ));
-
-/*! \brief Instantiation of the test with valid input and 2 atoms */
-INSTANTIATE_TEST_CASE_P(SaneInput2, PmeSplineAndSpreadTest, ::testing::Combine(c_inputBoxes, c_inputPmeOrders, c_inputGridSizes,
-                                                                                   ::testing::Values(c_sampleCoordinates2),
-                                                                                   ::testing::Values(c_sampleCharges2)
-                                                                               ));
-/*! \brief Instantiation of the test with valid input and 13 atoms */
-INSTANTIATE_TEST_CASE_P(SaneInput13, PmeSplineAndSpreadTest, ::testing::Combine(c_inputBoxes, c_inputPmeOrders, c_inputGridSizes,
-                                                                                    ::testing::Values(c_sampleCoordinates13),
-                                                                                    ::testing::Values(c_sampleCharges13)
-                                                                                ));
-}
-}
-}
+//! Moved out from instantiations for readability
+const auto c_inputBoxNames = ::testing::Values("rect", "tric");
+//! Moved out from instantiations for readability
+const auto c_inputGridNames = ::testing::Values("first", "second");
+//! Moved out from instantiations for readability
+const auto c_inputTestSystemNames = ::testing::Values("1 atom", "2 atoms", "13 atoms");
+
+INSTANTIATE_TEST_SUITE_P(Pme,
+                         SplineAndSpreadTest,
+                         ::testing::Combine(c_inputBoxNames,
+                                            ::testing::ValuesIn(c_inputPmeOrders),
+                                            ::testing::ValuesIn(c_inputGridSizes),
+                                            c_inputTestSystemNames),
+                         nameOfTest);
+
+} // namespace
+} // namespace test
+} // namespace gmx