2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2020,2021, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * \brief Tests for checkpoint writing sanity checks
39 * Checks that final checkpoint is equal to final trajectory output.
41 * \author Pascal Merz <pascal.merz@me.com>
42 * \ingroup module_mdrun_integration_tests
48 #include "gromacs/utility/strconvert.h"
49 #include "gromacs/utility/stringutil.h"
51 #include "testutils/simulationdatabase.h"
53 #include "moduletest.h"
54 #include "simulatorcomparison.h"
55 #include "trajectoryreader.h"
62 class CheckpointCoordinatesSanityChecks :
63 public MdrunTestFixture,
64 public ::testing::WithParamInterface<std::tuple<std::string, std::string, std::string, std::string>>
67 void runSimulation(MdpFieldValues mdpFieldValues,
69 const std::string& trrFileName,
70 const std::string& cptFileName)
72 mdpFieldValues["nsteps"] = toString(numSteps);
73 // Trajectories have the initial and the last frame
74 mdpFieldValues["nstxout"] = toString(numSteps);
75 mdpFieldValues["nstvout"] = toString(numSteps);
76 mdpFieldValues["nstfout"] = toString(0);
79 runner_.useStringAsMdpFile(prepareMdpFileContents(mdpFieldValues));
83 runner_.fullPrecisionTrajectoryFileName_ = trrFileName;
84 runMdrun(&runner_, { { "-cpo", cptFileName } });
87 static void compareCptAndTrr(const std::string& trrFileName,
88 const std::string& cptFileName,
89 const TrajectoryComparison& trajectoryComparison)
91 TrajectoryFrameReader trrReader(trrFileName);
92 TrajectoryFrameReader cptReader(cptFileName);
93 // Checkpoint has at least one frame
94 EXPECT_TRUE(cptReader.readNextFrame());
95 // Trajectory has at least two frames
96 EXPECT_TRUE(trrReader.readNextFrame());
97 EXPECT_NO_THROW(trrReader.frame());
98 EXPECT_TRUE(trrReader.readNextFrame());
100 // Now compare frames
101 trajectoryComparison(cptReader.frame(), trrReader.frame());
103 // Files had exactly 1 / 2 frames
104 EXPECT_FALSE(cptReader.readNextFrame());
105 EXPECT_FALSE(trrReader.readNextFrame());
109 TEST_P(CheckpointCoordinatesSanityChecks, WithinTolerances)
111 const auto& params = GetParam();
112 const auto& simulationName = std::get<0>(params);
113 const auto& integrator = std::get<1>(params);
114 const auto& temperatureCoupling = std::get<2>(params);
115 const auto& pressureCoupling = std::get<3>(params);
117 // Specify how trajectory frame matching must work.
118 TrajectoryFrameMatchSettings trajectoryMatchSettings{ true,
121 ComparisonConditions::MustCompare,
122 ComparisonConditions::MustCompare,
123 ComparisonConditions::NoComparison,
124 MaxNumFrames::compareAllFrames() };
125 if (integrator == "md-vv")
127 // When using md-vv and modular simulator, the velocities are expected to be off by
128 // 1/2 dt between checkpoint (top of the loop) and trajectory (full time step state)
129 trajectoryMatchSettings.velocitiesComparison = ComparisonConditions::NoComparison;
131 const TrajectoryTolerances trajectoryTolerances{
132 defaultRealTolerance(), defaultRealTolerance(), defaultRealTolerance(), defaultRealTolerance()
135 const auto mdpFieldValues =
136 prepareMdpFieldValues(simulationName, integrator, temperatureCoupling, pressureCoupling);
137 runner_.useTopGroAndNdxFromDatabase(simulationName);
139 const auto cptFileName = fileManager_.getTemporaryFilePath(".cpt");
140 const auto trrFileName = fileManager_.getTemporaryFilePath(".trr");
142 SCOPED_TRACE(formatString(
143 "Checking the sanity of the checkpointed coordinates using system '%s' "
144 "with integrator '%s', '%s' temperature coupling, and '%s' pressure coupling ",
145 simulationName.c_str(),
147 temperatureCoupling.c_str(),
148 pressureCoupling.c_str()));
150 SCOPED_TRACE("End of trajectory sanity");
151 // Running a few steps - we expect the checkpoint to be equal
152 // to the final configuration
153 runSimulation(mdpFieldValues, 16, trrFileName, cptFileName);
154 compareCptAndTrr(trrFileName, cptFileName, { trajectoryMatchSettings, trajectoryTolerances });
158 INSTANTIATE_TEST_SUITE_P(CheckpointCoordinatesAreSane,
159 CheckpointCoordinatesSanityChecks,
160 ::testing::Combine(::testing::Values("spc2"),
161 ::testing::Values("md", "md-vv"),
162 ::testing::Values("no"),
163 ::testing::Values("no")));
165 INSTANTIATE_TEST_SUITE_P(DISABLED_CheckpointCoordinatesAreSane,
166 CheckpointCoordinatesSanityChecks,
167 ::testing::Combine(::testing::Values("spc2"),
168 ::testing::Values("md", "md-vv"),
169 ::testing::Values("no"),
170 ::testing::Values("no")));
174 } // namespace gmx::test