Add test that plain multi-simulation works
authorMark Abraham <mark.j.abraham@gmail.com>
Mon, 5 Jan 2015 08:45:04 +0000 (09:45 +0100)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Tue, 3 Mar 2015 11:18:41 +0000 (12:18 +0100)
Refactored replica-exchange tests so that we can test
multi-simulation and replica-exchange separately with
little duplication.

Noted TODO that mdrun -multidir is not tested

Change-Id: Ib531d81103adc2a5b1757ef685c0e23960febdb2

src/programs/mdrun/tests/CMakeLists.txt
src/programs/mdrun/tests/multisim.cpp [new file with mode: 0644]
src/programs/mdrun/tests/multisimtest.cpp [new file with mode: 0644]
src/programs/mdrun/tests/multisimtest.h [new file with mode: 0644]
src/programs/mdrun/tests/replicaexchange.cpp

index fde9b1f7be96d541f31d320cde76689825d04713..8467cf6f5fff3323c6bd3ebd889f02a3c280f6c0 100644 (file)
@@ -61,6 +61,8 @@ gmx_build_unit_test(
     ${testname}
     ${exename}
     # files with code for tests
+    multisim.cpp
+    multisimtest.cpp
     replicaexchange.cpp
     # files with code for test fixtures
     moduletest.cpp
diff --git a/src/programs/mdrun/tests/multisim.cpp b/src/programs/mdrun/tests/multisim.cpp
new file mode 100644 (file)
index 0000000..7d08111
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * 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.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+
+/*! \internal \file
+ * \brief
+ * Tests for the mdrun multi-simulation functionality
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_mdrun
+ */
+#include "gmxpre.h"
+
+#include "config.h"
+
+#include <gtest/gtest.h>
+
+#include "multisimtest.h"
+
+namespace gmx
+{
+namespace test
+{
+
+/* This test ensures mdrun can run multi-simulations.  It runs one
+ * simulation per MPI rank.
+ *
+ * TODO Preferably, we could test that mdrun correctly refuses to run
+ * multi-simulation unless compiled with real MPI with more than one
+ * rank 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.
+ *
+ * Strictly, this test does not need to be parameterized, but
+ * conditionally disabling it with respect to GMX_LIB_MPI is easier if
+ * it is parameterized. */
+TEST_P(MultiSimTest, ExitsNormally)
+{
+    if (size_ <= 1)
+    {
+        /* Can't test multi-sim without multiple ranks. */
+        return;
+    }
+
+    const char *pcoupl = GetParam();
+    organizeMdpFile(pcoupl);
+    /* Call grompp on every rank - the standard callGrompp() only runs
+       grompp on rank 0. */
+    EXPECT_EQ(0, runner_.callGromppOnThisRank());
+
+    // mdrun names the files without the rank suffix
+    runner_.tprFileName_ = mdrunTprFileName_;
+    ASSERT_EQ(0, runner_.callMdrun(*mdrunCaller_));
+}
+
+/* Note, not all preprocessor implementations nest macro expansions
+   the same way / at all, if we would try to duplicate less code. */
+#ifdef GMX_LIB_MPI
+INSTANTIATE_TEST_CASE_P(InNvt, MultiSimTest,
+                            ::testing::Values("pcoupl = no"));
+#else
+// Test needs real MPI to run
+INSTANTIATE_TEST_CASE_P(DISABLED_InNvt, MultiSimTest,
+                            ::testing::Values("pcoupl = no"));
+#endif
+
+} // namespace
+} // namespace
diff --git a/src/programs/mdrun/tests/multisimtest.cpp b/src/programs/mdrun/tests/multisimtest.cpp
new file mode 100644 (file)
index 0000000..455a832
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * 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.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+
+/*! \internal \file
+ * \brief
+ * Tests for the mdrun multi-simulation functionality
+ *
+ * \todo Test mdrun -multidir also
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_mdrun
+ */
+#include "gmxpre.h"
+
+#include "multisimtest.h"
+
+#include <cmath>
+
+#include <algorithm>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/utility/basenetwork.h"
+#include "gromacs/utility/real.h"
+#include "gromacs/utility/stringutil.h"
+
+#include "testutils/cmdlinetest.h"
+
+#include "moduletest.h"
+
+namespace gmx
+{
+namespace test
+{
+
+MultiSimTest::MultiSimTest() : size_(gmx_node_num()),
+                               rank_(gmx_node_rank()),
+                               mdrunCaller_(new CommandLine)
+{
+    runner_.mdpInputFileName_  = fileManager_.getTemporaryFilePath(formatString("input%d.mdp", rank_));
+    runner_.mdpOutputFileName_ = fileManager_.getTemporaryFilePath(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(formatString("topol%d.tpr", rank_));
+    mdrunTprFileName_    = fileManager_.getTemporaryFilePath("topol.tpr");
+
+    runner_.useTopGroAndNdxFromDatabase("spc2");
+
+    mdrunCaller_->append("mdrun_mpi");
+    mdrunCaller_->addOption("-multi", size_);
+}
+
+void MultiSimTest::organizeMdpFile(const char *controlVariable)
+{
+    const real  baseTemperature = 298;
+    const real  basePressure    = 1;
+    std::string mdpFileContents =
+        formatString("nsteps = 2\n"
+                     "nstlog = 1\n"
+                     "nstcalcenergy = 1\n"
+                     "tcoupl = v-rescale\n"
+                     "tc-grps = System\n"
+                     "tau-t = 1\n"
+                     "ref-t = %f\n"
+                     // pressure coupling (if active)
+                     "tau-p = 1\n"
+                     "ref-p = %f\n"
+                     "compressibility = 4.5e-5\n"
+                     // velocity generation
+                     "gen-vel = yes\n"
+                     "gen-temp = %f\n"
+                     // control variable specification
+                     "%s\n",
+                     baseTemperature + 0.0001*rank_,
+                     basePressure * std::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)),
+                     controlVariable);
+    runner_.useStringAsMdpFile(mdpFileContents);
+}
+
+} // namespace
+} // namespace
diff --git a/src/programs/mdrun/tests/multisimtest.h b/src/programs/mdrun/tests/multisimtest.h
new file mode 100644 (file)
index 0000000..2196fe5
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * 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.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+#ifndef GMX_MDRUN_TESTS_MULTISIMTEST_H
+#define GMX_MDRUN_TESTS_MULTISIMTEST_H
+
+/*! \internal \file
+ * \brief
+ * Declares test fixture for the mdrun multi-simulation functionality
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_mdrun
+ */
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/utility/uniqueptr.h"
+
+#include "testutils/cmdlinetest.h"
+
+#include "moduletest.h"
+
+namespace gmx
+{
+namespace test
+{
+
+//! Convenience typedef
+typedef gmx_unique_ptr<CommandLine>::type CommandLinePointer;
+
+class MultiSimTest : public gmx::test::ParameterizedMdrunTestFixture
+{
+    public:
+        //! Constructor
+        MultiSimTest();
+
+        /*! \brief Organize the .mdp file for this rank
+         *
+         * For testing multi-simulation, this .mdp file is more
+         * complicated than it needs to be, but it does little harm,
+         * and doing it this way allows this function to be re-used
+         * for testing replica-exchange.
+         *
+         * \param controlVariable Allows parameterization to work with
+         * T, P or (later) lambda as the control variable, by passing a
+         * string with "mdp-param = value" such that different paths
+         * in init_replica_exchange() are followed.
+         */
+        void organizeMdpFile(const char *controlVariable);
+
+        //! Number of MPI ranks
+        int                size_;
+        //! MPI rank of this process
+        int                rank_;
+        //! Object for building the mdrun command line
+        CommandLinePointer mdrunCaller_;
+        //! Name of .tpr file to be used by mdrun
+        std::string        mdrunTprFileName_;
+};
+
+} // namespace
+} // namespace
+
+#endif
index f36005c6a4ee96d22190e688c609b5a36a09ff7d..5b581f4d8a4c45c401662960c33ccb80ab9fd692 100644 (file)
@@ -35,7 +35,7 @@
 
 /*! \internal \file
  * \brief
- * Tests for the mdrun replica exchange functionality
+ * Tests for the mdrun replica-exchange functionality
  *
  * \author Mark Abraham <mark.j.abraham@gmail.com>
  * \ingroup module_mdrun
 
 #include "config.h"
 
-#include <math.h>
-
-#include <algorithm>
-#include <iostream>
-
 #include <gtest/gtest.h>
 
-#include "gromacs/utility/basenetwork.h"
-#include "gromacs/utility/path.h"
-#include "gromacs/utility/real.h"
-#include "gromacs/utility/stringutil.h"
-#include "programs/mdrun/mdrun_main.h"
-
-#include "testutils/cmdlinetest.h"
+#include "multisimtest.h"
 
-#include "moduletest.h"
-
-namespace
+namespace gmx
 {
-
-/*! \brief
- * Test fixture for replica exchange
- */
-class ReplicaExchangeTest : public gmx::test::ParameterizedMdrunTestFixture
+namespace test
 {
-    public:
-        //! Constructor
-        ReplicaExchangeTest() : size_(gmx_node_num()),
-                                rank_(gmx_node_rank())
-        {
-            mdrunCaller_.append("mdrun_mpi");
-        }
-
-        /*! \brief Organize the .mdp file for this rank
-         *
-         * \param controlVariable Allows parameterization to work with
-         * T, P or (later) lamda as the control variable, by passing a
-         * string with "mdp-param = value" such that different paths
-         * in init_replica_exchange() are followed.
-         */
-        void organizeMdpFile(const char *controlVariable)
-        {
-            const real  baseTemperature = 298;
-            const real  basePressure    = 1;
-            std::string mdpFileContents =
-                gmx::formatString
-                    ("nsteps = 2\n"
-                    "nstlog = 1\n"
-                    "nstcalcenergy = 1\n"
-                    "tcoupl = v-rescale\n"
-                    "tc-grps = System\n"
-                    "tau-t = 1\n"
-                    "ref-t = %f\n"
-                    // pressure coupling (if active)
-                    "tau-p = 1\n"
-                    "ref-p = %f\n"
-                    "compressibility = 4.5e-5\n"
-                    // velocity generation
-                    "gen-vel = yes\n"
-                    "gen-temp = %f\n"
-                    // control variable specification
-                    "%s\n",
-                    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)),
-                    controlVariable);
-            runner_.useStringAsMdpFile(mdpFileContents);
-        }
 
-        //! Number of MPI ranks
-        int                    size_;
-        //! MPI rank of this process
-        int                    rank_;
-        //! Object for building the mdrun command line
-        gmx::test::CommandLine mdrunCaller_;
-};
+//! Convenience typedef
+typedef MultiSimTest ReplicaExchangeTest;
 
 /* This test ensures mdrun can run NVT REMD under the supported
  * 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, 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. */
+ * See also comments about MultiSimTest */
 TEST_P(ReplicaExchangeTest, ExitsNormally)
 {
     if (size_ <= 1)
@@ -148,31 +68,20 @@ TEST_P(ReplicaExchangeTest, ExitsNormally)
         return;
     }
 
-    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");
     /* Call grompp on every rank - the standard callGrompp() only runs
        grompp on rank 0. */
     EXPECT_EQ(0, runner_.callGromppOnThisRank());
 
-    runner_.tprFileName_ = fileManager_.getTemporaryFilePath("topol.tpr");
-    mdrunCaller_.addOption("-multi", size_);
-    mdrunCaller_.addOption("-replex", 1);
-    ASSERT_EQ(0, runner_.callMdrun(mdrunCaller_));
+    // mdrun names the files without the rank suffix
+    runner_.tprFileName_ = mdrunTprFileName_;
+    mdrunCaller_->addOption("-replex", 1);
+    ASSERT_EQ(0, runner_.callMdrun(*mdrunCaller_));
 }
 
+/* Note, not all preprocessor implementations nest macro expansions
+   the same way / at all, if we would try to duplicate less code. */
 #ifdef GMX_LIB_MPI
 INSTANTIATE_TEST_CASE_P(WithDifferentControlVariables, ReplicaExchangeTest,
                             ::testing::Values("pcoupl = no", "pcoupl = Berendsen"));
@@ -182,3 +91,4 @@ INSTANTIATE_TEST_CASE_P(DISABLED_WithDifferentControlVariables, ReplicaExchangeT
 #endif
 
 } // namespace
+} // namespace