Run replica-exchange tests with MPI enabled
authorMark Abraham <mark.j.abraham@gmail.com>
Sun, 4 Jan 2015 12:32:16 +0000 (13:32 +0100)
committerMark Abraham <mark.j.abraham@gmail.com>
Mon, 2 Mar 2015 08:56:13 +0000 (09:56 +0100)
Replica exchange only works with real MPI and at least two ranks. This
can now be handled by ctest, so we can run such tests automatically.
The other integration tests run in MPI mode, but do not place any
requirements upon the number of ranks, so they continue to run in the
usual way.

Fixed the replica-exchange integration tests so that they actually do
run. Changed tests to use mdrun -multi because it is easier to write
the tests that way. (Using mdrun -multidir is problematic, because
grompp needs to write the .tpr file in the subdirectories. When using
mdrun -multi, the only issue is that the name of the .tpr file for
grompp and mdrun is different, because the latter will append the MPI
rank.)

Fixed member variables to conform to naming convention.

Refs #1587

Change-Id: I11dc06f3aac81a80d679b036aef24762e9eec819

src/programs/mdrun/tests/CMakeLists.txt
src/programs/mdrun/tests/replicaexchange.cpp

index 2a4e642bc383c4036d1b177940cc95eadb4539dd..fde9b1f7be96d541f31d320cde76689825d04713 100644 (file)
@@ -40,7 +40,6 @@ gmx_build_unit_test(
     ${exename}
     # files with code for tests
     rerun.cpp
-    replicaexchange.cpp
     trajectory_writing.cpp
     compressed_x_output.cpp
     swapcoords.cpp
@@ -54,3 +53,22 @@ gmx_register_integration_test(
     ${testname}
     ${exename}
     )
+
+set(testname "MdrunMpiTests")
+set(exename "mdrun-mpi-test")
+
+gmx_build_unit_test(
+    ${testname}
+    ${exename}
+    # files with code for tests
+    replicaexchange.cpp
+    # files with code for test fixtures
+    moduletest.cpp
+    # pseudo-library for code for mdrun
+    $<TARGET_OBJECTS:mdrun_objlib>
+    )
+gmx_register_mpi_integration_test(
+    ${testname}
+    ${exename}
+    2
+    )
index 37d9e02c124b3288e4772dc4145eabdc28a930a2..f36005c6a4ee96d22190e688c609b5a36a09ff7d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -47,6 +47,7 @@
 #include <math.h>
 
 #include <algorithm>
+#include <iostream>
 
 #include <gtest/gtest.h>
 
@@ -70,46 +71,10 @@ class ReplicaExchangeTest : public gmx::test::ParameterizedMdrunTestFixture
 {
     public:
         //! Constructor
-        ReplicaExchangeTest() : size(gmx_node_num()),
-                                rank(gmx_node_rank())
+        ReplicaExchangeTest() : size_(gmx_node_num()),
+                                rank_(gmx_node_rank())
         {
-            mdrunCaller.append("mdrun_mpi");
-        }
-
-        /*! \brief Organize the -multidir directories for the test.
-         *
-         * These are created inside the temporary directory for the
-         * test case, and added to the eventual mdrun command
-         * line. The temporary directory for the call to grompp by
-         * this rank is set to the appropriate -multidir directory, so
-         * the grompp output files go to the right place. */
-        void organizeMultidir()
-        {
-            mdrunCaller.append("-multidir");
-
-            std::string futureTestTempDirectory;
-            for (int i = 0; i != size; ++i)
-            {
-                std::string replicaTempDirectory =
-                    gmx::formatString("%s/multidir_%d",
-                                      fileManager_.getOutputTempDirectory(), i);
-                mdrunCaller.append(replicaTempDirectory);
-
-                if (rank == i)
-                {
-                    gmx::Directory::create(replicaTempDirectory);
-                    futureTestTempDirectory = std::string(replicaTempDirectory);
-                }
-            }
-            fileManager_.setOutputTempDirectory(futureTestTempDirectory);
-
-            /* Prepare grompp output filenames inside the new
-               temporary directory */
-            runner_.mdpInputFileName_  = fileManager_.getTemporaryFilePath("input.mdp");
-            runner_.mdpOutputFileName_ = fileManager_.getTemporaryFilePath("output.mdp");
-            runner_.tprFileName_       = fileManager_.getTemporaryFilePath(".tpr");
-
-            mdrunCaller.addOption("-deffnm", fileManager_.getTestSpecificFileNameRoot());
+            mdrunCaller_.append("mdrun_mpi");
         }
 
         /*! \brief Organize the .mdp file for this rank
@@ -141,46 +106,60 @@ class ReplicaExchangeTest : public gmx::test::ParameterizedMdrunTestFixture
                     "gen-temp = %f\n"
                     // control variable specification
                     "%s\n",
-                    baseTemperature + 0.0001*rank,
-                    basePressure * pow(1.01, rank),
+                    baseTemperature + 0.0001*rank_,
+                    basePressure * pow(1.01, rank_),
                     /* Set things up so that the initial KE decreases
                        with increasing replica number, so that the
                        (identical) starting PE decreases on the first
                        step more for the replicas with higher number,
                        which will tend to force replica exchange to
                        occur. */
-                    std::max(baseTemperature - 10 * rank, real(0)),
+                    std::max(baseTemperature - 10 * rank_, real(0)),
                     controlVariable);
             runner_.useStringAsMdpFile(mdpFileContents);
         }
 
-        //! MPI process set size
-        int                    size;
+        //! Number of MPI ranks
+        int                    size_;
         //! MPI rank of this process
-        int                    rank;
+        int                    rank_;
         //! Object for building the mdrun command line
-        gmx::test::CommandLine mdrunCaller;
+        gmx::test::CommandLine mdrunCaller_;
 };
 
 /* This test ensures mdrun can run NVT REMD under the supported
- * conditions.
+ * conditions. It runs one replica per MPI rank.
  *
  * TODO Preferably, we could test that mdrun correctly refuses to run
  * replica exchange unless under real MPI with more than one rank
- * available. However, those cases trigger an error that is currently
- * fatal to mdrun and also to the test binary. So, in the meantime we
- * must not test those cases. This is done via disabling the test, so
- * that there is a reminder that it is disabled. There's no elegant
- * way to conditionally disable a test. */
+ * available. However, if we just call mdrun blindly, those cases
+ * trigger an error that is currently fatal to mdrun and also to the
+ * test binary. So, in the meantime we must not test those cases. If
+ * there is no MPI, we disable the test, so that there is a reminder
+ * that it is disabled. There's no elegant way to conditionally
+ * disable a test at run time, so currently there is no feedback if
+ * only one rank is available. However, the test harness knows
+ * to run this test with more than one rank. */
 TEST_P(ReplicaExchangeTest, ExitsNormally)
 {
-    if (size <= 1)
+    if (size_ <= 1)
     {
         /* Can't test replica exchange without multiple ranks. */
         return;
     }
 
-    organizeMultidir();
+    runner_.mdpInputFileName_  = fileManager_.getTemporaryFilePath(gmx::formatString("input%d.mdp", rank_));
+    runner_.mdpOutputFileName_ = fileManager_.getTemporaryFilePath(gmx::formatString("output%d.mdp", rank_));
+
+    /* grompp needs to name the .tpr file so that when mdrun appends
+       the MPI rank, it will find the right file. If we just used
+       "%d.tpr" then \c TestFileManager prefixes that with an
+       underscore. Then, there is no way for mdrun to be told the
+       right name, because if you add the underscore manually, you get
+       a second one from \c TestFileManager. However, it's easy to
+       just start the suffix with "topol" in both cases. */
+    runner_.tprFileName_ = fileManager_.getTemporaryFilePath(gmx::formatString("topol%d.tpr", rank_));
+
     const char *pcoupl = GetParam();
     organizeMdpFile(pcoupl);
     runner_.useTopGroAndNdxFromDatabase("spc2");
@@ -188,8 +167,10 @@ TEST_P(ReplicaExchangeTest, ExitsNormally)
        grompp on rank 0. */
     EXPECT_EQ(0, runner_.callGromppOnThisRank());
 
-    mdrunCaller.addOption("-replex", 1);
-    ASSERT_EQ(0, gmx_mdrun(mdrunCaller.argc(), mdrunCaller.argv()));
+    runner_.tprFileName_ = fileManager_.getTemporaryFilePath("topol.tpr");
+    mdrunCaller_.addOption("-multi", size_);
+    mdrunCaller_.addOption("-replex", 1);
+    ASSERT_EQ(0, runner_.callMdrun(mdrunCaller_));
 }
 
 #ifdef GMX_LIB_MPI