Implement PME solve in SYCL
[alexxy/gromacs.git] / src / gromacs / ewald / tests / pmesolvetest.cpp
index 07f31629f6317c136379dd135a59135675946af7..c8ea1bff1240ded7d5f06553d523529368557964 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 #include "gromacs/utility/stringutil.h"
 
 #include "testutils/refdata.h"
+#include "testutils/test_hardware_environment.h"
 #include "testutils/testasserts.h"
 
 #include "pmetestcommon.h"
-#include "testhardwarecontexts.h"
 
 namespace gmx
 {
@@ -75,8 +75,21 @@ class PmeSolveTest : public ::testing::TestWithParam<SolveInputParameters>
 public:
     PmeSolveTest() = default;
 
+    //! Sets the programs once
+    static void SetUpTestSuite()
+    {
+        s_pmeTestHardwareContexts    = createPmeTestHardwareContextList();
+        g_allowPmeWithSyclForTesting = true; // We support PmeSolve with SYCL
+    }
+
+    static void TearDownTestSuite()
+    {
+        // Revert the value back.
+        g_allowPmeWithSyclForTesting = false;
+    }
+
     //! The test
-    void runTest()
+    static void runTest()
     {
         /* Getting the input */
         Matrix3x3                    box;
@@ -95,29 +108,30 @@ public:
         inputRec.nky         = gridSize[YY];
         inputRec.nkz         = gridSize[ZZ];
         inputRec.pme_order   = 4;
-        inputRec.coulombtype = eelPME;
+        inputRec.coulombtype = CoulombInteractionType::Pme;
         inputRec.epsilon_r   = epsilon_r;
         switch (method)
         {
             case PmeSolveAlgorithm::Coulomb: break;
 
-            case PmeSolveAlgorithm::LennardJones: inputRec.vdwtype = evdwPME; break;
+            case PmeSolveAlgorithm::LennardJones: inputRec.vdwtype = VanDerWaalsType::Pme; break;
 
             default: GMX_THROW(InternalError("Unknown PME solver"));
         }
 
         TestReferenceData refData;
-        for (const auto& context : getPmeTestEnv()->getHardwareContexts())
+        for (const auto& pmeTestHardwareContext : s_pmeTestHardwareContexts)
         {
-            CodePath   codePath = context->codePath();
-            const bool supportedInput =
-                    pmeSupportsInputForMode(*getPmeTestEnv()->hwinfo(), &inputRec, codePath);
+            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(pmeInitEmpty(&inputRec, codePath, nullptr, nullptr, nullptr, box,
-                                              ewaldCoeff_q, ewaldCoeff_lj),
-                                 NotImplementedError);
+                EXPECT_THROW_GMX(
+                        pmeInitWrapper(&inputRec, codePath, nullptr, nullptr, nullptr, box, ewaldCoeff_q, ewaldCoeff_lj),
+                        NotImplementedError);
                 continue;
             }
 
@@ -133,22 +147,31 @@ public:
                 {
                     /* Describing the test*/
                     SCOPED_TRACE(formatString(
-                            "Testing solving (%s, %s, %s energy/virial) with %s %sfor PME grid "
+                            "Testing solving (%s, %s, %s energy/virial) on %s for PME grid "
                             "size %d %d %d, Ewald coefficients %g %g",
                             (method == PmeSolveAlgorithm::LennardJones) ? "Lennard-Jones" : "Coulomb",
-                            gridOrdering.second.c_str(), computeEnergyAndVirial ? "with" : "without",
-                            codePathToString(codePath), context->description().c_str(),
-                            gridSize[XX], gridSize[YY], gridSize[ZZ], ewaldCoeff_q, ewaldCoeff_lj));
+                            gridOrdering.second.c_str(),
+                            computeEnergyAndVirial ? "with" : "without",
+                            pmeTestHardwareContext->description().c_str(),
+                            gridSize[XX],
+                            gridSize[YY],
+                            gridSize[ZZ],
+                            ewaldCoeff_q,
+                            ewaldCoeff_lj));
 
                     /* Running the test */
-                    PmeSafePointer pmeSafe = pmeInitEmpty(
-                            &inputRec, codePath, context->deviceContext(), context->deviceStream(),
-                            context->pmeGpuProgram(), box, ewaldCoeff_q, ewaldCoeff_lj);
+                    PmeSafePointer pmeSafe = pmeInitWrapper(&inputRec,
+                                                            codePath,
+                                                            pmeTestHardwareContext->deviceContext(),
+                                                            pmeTestHardwareContext->deviceStream(),
+                                                            pmeTestHardwareContext->pmeGpuProgram(),
+                                                            box,
+                                                            ewaldCoeff_q,
+                                                            ewaldCoeff_lj);
                     pmeSetComplexGrid(pmeSafe.get(), codePath, gridOrdering.first, nonZeroGridValues);
                     const real cellVolume = box[0] * box[4] * box[8];
                     // FIXME - this is box[XX][XX] * box[YY][YY] * box[ZZ][ZZ], should be stored in the PME structure
-                    pmePerformSolve(pmeSafe.get(), codePath, method, cellVolume, gridOrdering.first,
-                                    computeEnergyAndVirial);
+                    pmePerformSolve(pmeSafe.get(), codePath, method, cellVolume, gridOrdering.first, computeEnergyAndVirial);
                     pmeFinalizeTest(pmeSafe.get(), codePath);
 
                     /* Check the outputs */
@@ -176,7 +199,8 @@ public:
                     const uint64_t splineModuliDoublePrecisionUlps =
                             getSplineModuliDoublePrecisionUlps(inputRec.pme_order + 1);
                     auto gridTolerance = relativeToleranceAsPrecisionDependentUlp(
-                            gridValuesMagnitude, gridUlpToleranceFactor * c_splineModuliSinglePrecisionUlps,
+                            gridValuesMagnitude,
+                            gridUlpToleranceFactor * c_splineModuliSinglePrecisionUlps,
                             gridUlpToleranceFactor * splineModuliDoublePrecisionUlps);
                     gridValuesChecker.setDefaultTolerance(gridTolerance);
 
@@ -215,7 +239,8 @@ public:
                         // TODO This factor is arbitrary, do a proper error-propagation analysis
                         uint64_t energyUlpToleranceFactor = gridUlpToleranceFactor * 2;
                         auto     energyTolerance = relativeToleranceAsPrecisionDependentUlp(
-                                energyMagnitude, energyUlpToleranceFactor * c_splineModuliSinglePrecisionUlps,
+                                energyMagnitude,
+                                energyUlpToleranceFactor * c_splineModuliSinglePrecisionUlps,
                                 energyUlpToleranceFactor * splineModuliDoublePrecisionUlps);
                         TestReferenceChecker energyChecker(checker);
                         energyChecker.setDefaultTolerance(energyTolerance);
@@ -226,7 +251,8 @@ public:
                         // TODO This factor is arbitrary, do a proper error-propagation analysis
                         uint64_t virialUlpToleranceFactor = energyUlpToleranceFactor * 2;
                         auto     virialTolerance = relativeToleranceAsPrecisionDependentUlp(
-                                virialMagnitude, virialUlpToleranceFactor * c_splineModuliSinglePrecisionUlps,
+                                virialMagnitude,
+                                virialUlpToleranceFactor * c_splineModuliSinglePrecisionUlps,
                                 virialUlpToleranceFactor * splineModuliDoublePrecisionUlps);
                         TestReferenceChecker virialChecker(
                                 checker.checkCompound("Matrix", "Virial"));
@@ -244,8 +270,12 @@ public:
             }
         }
     }
+
+    static std::vector<std::unique_ptr<PmeTestHardwareContext>> s_pmeTestHardwareContexts;
 };
 
+std::vector<std::unique_ptr<PmeTestHardwareContext>> PmeSolveTest::s_pmeTestHardwareContexts;
+
 /*! \brief Test for PME solving */
 TEST_P(PmeSolveTest, ReproducesOutputs)
 {
@@ -299,50 +329,50 @@ const auto c_inputEwaldCoeff_lj = ::testing::Values(0.7);
 const auto c_inputMethods = ::testing::Values(PmeSolveAlgorithm::Coulomb, PmeSolveAlgorithm::LennardJones);
 
 //! Instantiation of the PME solving test
-INSTANTIATE_TEST_CASE_P(SaneInput,
-                        PmeSolveTest,
-                        ::testing::Combine(c_inputBoxes,
-                                           c_inputGridSizes,
-                                           c_inputGrids,
-                                           c_inputEpsilon_r,
-                                           c_inputEwaldCoeff_q,
-                                           c_inputEwaldCoeff_lj,
-                                           c_inputMethods));
+INSTANTIATE_TEST_SUITE_P(SaneInput,
+                         PmeSolveTest,
+                         ::testing::Combine(c_inputBoxes,
+                                            c_inputGridSizes,
+                                            c_inputGrids,
+                                            c_inputEpsilon_r,
+                                            c_inputEwaldCoeff_q,
+                                            c_inputEwaldCoeff_lj,
+                                            c_inputMethods));
 
 //! A few more instances to check that different ewaldCoeff_q actually affects results of the Coulomb solver
-INSTANTIATE_TEST_CASE_P(DifferentEwaldCoeffQ,
-                        PmeSolveTest,
-                        ::testing::Combine(c_inputBoxes,
-                                           c_inputGridSizes,
-                                           c_inputGrids,
-                                           c_inputEpsilon_r,
-                                           ::testing::Values(0.4),
-                                           c_inputEwaldCoeff_lj,
-                                           ::testing::Values(PmeSolveAlgorithm::Coulomb)));
+INSTANTIATE_TEST_SUITE_P(DifferentEwaldCoeffQ,
+                         PmeSolveTest,
+                         ::testing::Combine(c_inputBoxes,
+                                            c_inputGridSizes,
+                                            c_inputGrids,
+                                            c_inputEpsilon_r,
+                                            ::testing::Values(0.4),
+                                            c_inputEwaldCoeff_lj,
+                                            ::testing::Values(PmeSolveAlgorithm::Coulomb)));
 
 //! A few more instances to check that different ewaldCoeff_lj actually affects results of the Lennard-Jones solver.
 //! The value has to be approximately larger than 1 / (box dimensions) to have a meaningful output grid.
 //! Previous value of 0.3 caused one of the grid cells to be less or greater than GMX_FLOAT_MIN, depending on the architecture.
-INSTANTIATE_TEST_CASE_P(DifferentEwaldCoeffLJ,
-                        PmeSolveTest,
-                        ::testing::Combine(c_inputBoxes,
-                                           c_inputGridSizes,
-                                           c_inputGrids,
-                                           c_inputEpsilon_r,
-                                           c_inputEwaldCoeff_q,
-                                           ::testing::Values(2.35),
-                                           ::testing::Values(PmeSolveAlgorithm::LennardJones)));
+INSTANTIATE_TEST_SUITE_P(DifferentEwaldCoeffLJ,
+                         PmeSolveTest,
+                         ::testing::Combine(c_inputBoxes,
+                                            c_inputGridSizes,
+                                            c_inputGrids,
+                                            c_inputEpsilon_r,
+                                            c_inputEwaldCoeff_q,
+                                            ::testing::Values(2.35),
+                                            ::testing::Values(PmeSolveAlgorithm::LennardJones)));
 
 //! A few more instances to check that different epsilon_r actually affects results of all solvers
-INSTANTIATE_TEST_CASE_P(DifferentEpsilonR,
-                        PmeSolveTest,
-                        ::testing::Combine(c_inputBoxes,
-                                           c_inputGridSizes,
-                                           c_inputGrids,
-                                           testing::Values(1.9),
-                                           c_inputEwaldCoeff_q,
-                                           c_inputEwaldCoeff_lj,
-                                           c_inputMethods));
+INSTANTIATE_TEST_SUITE_P(DifferentEpsilonR,
+                         PmeSolveTest,
+                         ::testing::Combine(c_inputBoxes,
+                                            c_inputGridSizes,
+                                            c_inputGrids,
+                                            testing::Values(1.9),
+                                            c_inputEwaldCoeff_q,
+                                            c_inputEwaldCoeff_lj,
+                                            c_inputMethods));
 
 } // namespace
 } // namespace test