From fca7909e4f3f90555f7831a18089508682f067bd Mon Sep 17 00:00:00 2001 From: Mark Abraham Date: Mon, 5 Jan 2015 09:45:04 +0100 Subject: [PATCH] Add test that plain multi-simulation works 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 | 2 + src/programs/mdrun/tests/multisim.cpp | 104 +++++++++++++++ src/programs/mdrun/tests/multisimtest.cpp | 126 +++++++++++++++++++ src/programs/mdrun/tests/multisimtest.h | 97 ++++++++++++++ src/programs/mdrun/tests/replicaexchange.cpp | 118 +++-------------- 5 files changed, 343 insertions(+), 104 deletions(-) create mode 100644 src/programs/mdrun/tests/multisim.cpp create mode 100644 src/programs/mdrun/tests/multisimtest.cpp create mode 100644 src/programs/mdrun/tests/multisimtest.h diff --git a/src/programs/mdrun/tests/CMakeLists.txt b/src/programs/mdrun/tests/CMakeLists.txt index fde9b1f7be..8467cf6f5f 100644 --- a/src/programs/mdrun/tests/CMakeLists.txt +++ b/src/programs/mdrun/tests/CMakeLists.txt @@ -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 index 0000000000..7d08111210 --- /dev/null +++ b/src/programs/mdrun/tests/multisim.cpp @@ -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 + * \ingroup module_mdrun + */ +#include "gmxpre.h" + +#include "config.h" + +#include + +#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 index 0000000000..455a832019 --- /dev/null +++ b/src/programs/mdrun/tests/multisimtest.cpp @@ -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 + * \ingroup module_mdrun + */ +#include "gmxpre.h" + +#include "multisimtest.h" + +#include + +#include +#include + +#include + +#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 index 0000000000..2196fe5532 --- /dev/null +++ b/src/programs/mdrun/tests/multisimtest.h @@ -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 + * \ingroup module_mdrun + */ + +#include + +#include + +#include "gromacs/utility/uniqueptr.h" + +#include "testutils/cmdlinetest.h" + +#include "moduletest.h" + +namespace gmx +{ +namespace test +{ + +//! Convenience typedef +typedef gmx_unique_ptr::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 diff --git a/src/programs/mdrun/tests/replicaexchange.cpp b/src/programs/mdrun/tests/replicaexchange.cpp index f36005c6a4..5b581f4d8a 100644 --- a/src/programs/mdrun/tests/replicaexchange.cpp +++ b/src/programs/mdrun/tests/replicaexchange.cpp @@ -35,7 +35,7 @@ /*! \internal \file * \brief - * Tests for the mdrun replica exchange functionality + * Tests for the mdrun replica-exchange functionality * * \author Mark Abraham * \ingroup module_mdrun @@ -44,102 +44,22 @@ #include "config.h" -#include - -#include -#include - #include -#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 -- 2.22.0