#include "gromacs/mdtypes/pullhistory.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/mdtypes/swaphistory.h"
+#include "gromacs/modularsimulator/modularsimulator.h"
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/baseversion.h"
static CheckpointHeaderContents read_checkpoint_data(t_fileio* fp,
t_state* state,
- std::vector<gmx_file_position_t>* outputfiles)
+ std::vector<gmx_file_position_t>* outputfiles,
+ gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData)
{
CheckpointHeaderContents headerContents;
do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, &headerContents);
do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifier, nullptr);
if (headerContents.file_version >= cptv_ModularSimulator)
{
- // In the scope of the current function, we can just throw away the content
- // of the modular checkpoint, but we need to read it to move the file pointer
- gmx::FileIOXdrSerializer serializer(fp);
- gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
- modularSimulatorCheckpointData.deserialize(&serializer);
+ // Store modular checkpoint data into modularSimulatorCheckpointData
+ gmx::FileIOXdrSerializer serializer(fp);
+ modularSimulatorCheckpointData->deserialize(&serializer);
}
ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
if (ret)
{
t_state state;
std::vector<gmx_file_position_t> outputfiles;
- CheckpointHeaderContents headerContents = read_checkpoint_data(fp, &state, &outputfiles);
+ gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
+ CheckpointHeaderContents headerContents =
+ read_checkpoint_data(fp, &state, &outputfiles, &modularSimulatorCheckpointData);
+ if (headerContents.isModularSimulatorCheckpoint)
+ {
+ gmx::ModularSimulator::readCheckpointToTrxFrame(fr, &modularSimulatorCheckpointData, headerContents);
+ return;
+ }
fr->natoms = state.natoms;
fr->bStep = TRUE;
CheckpointHeaderContents read_checkpoint_simulation_part_and_filenames(t_fileio* fp,
std::vector<gmx_file_position_t>* outputfiles)
{
- t_state state;
- CheckpointHeaderContents headerContents = read_checkpoint_data(fp, &state, outputfiles);
+ t_state state;
+ gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
+ CheckpointHeaderContents headerContents =
+ read_checkpoint_data(fp, &state, outputfiles, &modularSimulatorCheckpointData);
if (gmx_fio_close(fp) != 0)
{
gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/state.h"
+#include "gromacs/trajectory/trajectoryframe.h"
#include "modularsimulator.h"
#include "simulatoralgorithm.h"
} // namespace
template<CheckpointDataOperation operation>
-void FreeEnergyPerturbationData::Element::doCheckpointData(CheckpointData<operation>* checkpointData)
+void FreeEnergyPerturbationData::doCheckpointData(CheckpointData<operation>* checkpointData)
{
checkpointVersion(checkpointData, "FreeEnergyPerturbationData version", c_currentVersion);
- checkpointData->scalar("current FEP state", &freeEnergyPerturbationData_->currentFEPState_);
- checkpointData->arrayRef("lambda vector",
- makeCheckpointArrayRef<operation>(freeEnergyPerturbationData_->lambda_));
+ checkpointData->scalar("current FEP state", ¤tFEPState_);
+ checkpointData->arrayRef("lambda vector", makeCheckpointArrayRef<operation>(lambda_));
}
void FreeEnergyPerturbationData::Element::saveCheckpointState(std::optional<WriteCheckpointData> checkpointData,
{
if (MASTER(cr))
{
- doCheckpointData<CheckpointDataOperation::Write>(&checkpointData.value());
+ freeEnergyPerturbationData_->doCheckpointData<CheckpointDataOperation::Write>(
+ &checkpointData.value());
}
}
{
if (MASTER(cr))
{
- doCheckpointData<CheckpointDataOperation::Read>(&checkpointData.value());
+ freeEnergyPerturbationData_->doCheckpointData<CheckpointDataOperation::Read>(
+ &checkpointData.value());
}
if (DOMAINDECOMP(cr))
{
const std::string& FreeEnergyPerturbationData::Element::clientID()
{
- return identifier_;
+ return FreeEnergyPerturbationData::checkpointID();
}
FreeEnergyPerturbationData::Element::Element(FreeEnergyPerturbationData* freeEnergyPerturbationElement,
return freeEnergyPerturbationData->element();
}
+void FreeEnergyPerturbationData::readCheckpointToTrxFrame(t_trxframe* trxFrame,
+ std::optional<ReadCheckpointData> readCheckpointData)
+{
+ if (readCheckpointData)
+ {
+ FreeEnergyPerturbationData freeEnergyPerturbationData;
+ freeEnergyPerturbationData.doCheckpointData(&readCheckpointData.value());
+ trxFrame->lambda = freeEnergyPerturbationData.lambda_[efptFEP];
+ trxFrame->fep_state = freeEnergyPerturbationData.currentFEPState_;
+ }
+ else
+ {
+ trxFrame->lambda = 0;
+ trxFrame->fep_state = 0;
+ }
+ trxFrame->bLambda = true;
+}
+
+const std::string& FreeEnergyPerturbationData::checkpointID()
+{
+ static const std::string identifier = "FreeEnergyPerturbationData";
+ return identifier;
+}
+
} // namespace gmx
#include "modularsimulatorinterfaces.h"
struct t_inputrec;
+struct t_trxframe;
namespace gmx
{
//! Get pointer to element (whose lifetime is managed by this)
Element* element();
+ //! Read everything that can be stored in t_trxframe from a checkpoint file
+ static void readCheckpointToTrxFrame(t_trxframe* trxFrame,
+ std::optional<ReadCheckpointData> readCheckpointData);
+ //! CheckpointHelper identifier
+ static const std::string& checkpointID();
+
private:
+ //! Default constructor - only used internally
+ FreeEnergyPerturbationData() = default;
//! Update the lambda values
void updateLambdas(Step step);
+ //! Helper function to read from / write to CheckpointData
+ template<CheckpointDataOperation operation>
+ void doCheckpointData(CheckpointData<operation>* checkpointData);
//! The element
std::unique_ptr<Element> element_;
FreeEnergyPerturbationData* freeEnergyPerturbationData_;
//! Whether lambda values are non-static
const bool lambdasChange_;
-
-
- //! CheckpointHelper identifier
- const std::string identifier_ = "FreeEnergyPerturbationElement";
- //! Helper function to read from / write to CheckpointData
- template<CheckpointDataOperation operation>
- void doCheckpointData(CheckpointData<operation>* checkpointData);
};
} // namespace gmx
#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_load_balancing.h"
#include "gromacs/ewald/pme_pp.h"
+#include "gromacs/fileio/checkpoint.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/listed_forces/listed_forces.h"
#include "gromacs/mdlib/checkpointhandler.h"
#include "gromacs/nbnxm/nbnxm.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
+#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/int64_to_int.h"
#include "computeglobalselement.h"
#include "constraintelement.h"
}
}
+void ModularSimulator::readCheckpointToTrxFrame(t_trxframe* fr,
+ ReadCheckpointDataHolder* readCheckpointDataHolder,
+ const CheckpointHeaderContents& checkpointHeaderContents)
+{
+ GMX_RELEASE_ASSERT(checkpointHeaderContents.isModularSimulatorCheckpoint,
+ "ModularSimulator::readCheckpointToTrxFrame can only read checkpoints "
+ "written by modular simulator.");
+ fr->bStep = true;
+ fr->step =
+ int64_to_int(checkpointHeaderContents.step, "conversion of checkpoint to trajectory");
+ fr->bTime = true;
+ fr->time = checkpointHeaderContents.t;
+
+ fr->bAtoms = false;
+
+ StatePropagatorData::readCheckpointToTrxFrame(
+ fr, readCheckpointDataHolder->checkpointData(StatePropagatorData::checkpointID()));
+ if (readCheckpointDataHolder->keyExists(FreeEnergyPerturbationData::checkpointID()))
+ {
+ FreeEnergyPerturbationData::readCheckpointToTrxFrame(
+ fr, readCheckpointDataHolder->checkpointData(FreeEnergyPerturbationData::checkpointID()));
+ }
+ else
+ {
+ FreeEnergyPerturbationData::readCheckpointToTrxFrame(fr, std::nullopt);
+ }
+}
+
} // namespace gmx
#include "gromacs/mdrun/isimulator.h"
+struct CheckpointHeaderContents;
struct t_fcdata;
+struct t_trxframe;
namespace gmx
{
bool doEssentialDynamics,
bool doMembed);
+ //! Read everything that can be stored in t_trxframe from a checkpoint file
+ static void readCheckpointToTrxFrame(t_trxframe* fr,
+ ReadCheckpointDataHolder* readCheckpointDataHolder,
+ const CheckpointHeaderContents& checkpointHeaderContents);
+
// Only builder can construct
friend class SimulatorBuilder;
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/atoms.h"
#include "gromacs/topology/topology.h"
+#include "gromacs/trajectory/trajectoryframe.h"
#include "freeenergyperturbationdata.h"
#include "modularsimulator.h"
} // namespace
template<CheckpointDataOperation operation>
-void StatePropagatorData::Element::doCheckpointData(CheckpointData<operation>* checkpointData,
- const t_commrec* cr)
+void StatePropagatorData::doCheckpointData(CheckpointData<operation>* checkpointData)
+{
+ checkpointVersion(checkpointData, "StatePropagatorData version", c_currentVersion);
+ checkpointData->scalar("numAtoms", &totalNumAtoms_);
+
+ if (operation == CheckpointDataOperation::Read)
+ {
+ xGlobal_.resizeWithPadding(totalNumAtoms_);
+ vGlobal_.resizeWithPadding(totalNumAtoms_);
+ }
+
+ checkpointData->arrayRef("positions", makeCheckpointArrayRef<operation>(xGlobal_));
+ checkpointData->arrayRef("velocities", makeCheckpointArrayRef<operation>(vGlobal_));
+ checkpointData->tensor("box", box_);
+ checkpointData->scalar("ddpCount", &ddpCount_);
+ checkpointData->scalar("ddpCountCgGl", &ddpCountCgGl_);
+ checkpointData->arrayRef("cgGl", makeCheckpointArrayRef<operation>(cgGl_));
+}
+
+void StatePropagatorData::Element::saveCheckpointState(std::optional<WriteCheckpointData> checkpointData,
+ const t_commrec* cr)
{
- ArrayRef<RVec> xGlobalRef;
- ArrayRef<RVec> vGlobalRef;
if (DOMAINDECOMP(cr))
{
- if (MASTER(cr))
- {
- xGlobalRef = statePropagatorData_->xGlobal_;
- vGlobalRef = statePropagatorData_->vGlobal_;
- }
- if (operation == CheckpointDataOperation::Write)
- {
- dd_collect_vec(cr->dd, statePropagatorData_->ddpCount_, statePropagatorData_->ddpCountCgGl_,
- statePropagatorData_->cgGl_, statePropagatorData_->x_, xGlobalRef);
- dd_collect_vec(cr->dd, statePropagatorData_->ddpCount_, statePropagatorData_->ddpCountCgGl_,
- statePropagatorData_->cgGl_, statePropagatorData_->v_, vGlobalRef);
- }
+ // Collect state from all ranks into global vectors
+ dd_collect_vec(cr->dd, statePropagatorData_->ddpCount_, statePropagatorData_->ddpCountCgGl_,
+ statePropagatorData_->cgGl_, statePropagatorData_->x_,
+ statePropagatorData_->xGlobal_);
+ dd_collect_vec(cr->dd, statePropagatorData_->ddpCount_, statePropagatorData_->ddpCountCgGl_,
+ statePropagatorData_->cgGl_, statePropagatorData_->v_,
+ statePropagatorData_->vGlobal_);
}
else
{
- xGlobalRef = statePropagatorData_->x_;
- vGlobalRef = statePropagatorData_->v_;
+ // Everything is local - copy local vectors into global ones
+ statePropagatorData_->xGlobal_.resizeWithPadding(statePropagatorData_->totalNumAtoms());
+ statePropagatorData_->vGlobal_.resizeWithPadding(statePropagatorData_->totalNumAtoms());
+ std::copy(statePropagatorData_->x_.begin(), statePropagatorData_->x_.end(),
+ statePropagatorData_->xGlobal_.begin());
+ std::copy(statePropagatorData_->v_.begin(), statePropagatorData_->v_.end(),
+ statePropagatorData_->vGlobal_.begin());
}
if (MASTER(cr))
{
- GMX_ASSERT(checkpointData, "Master needs a valid pointer to a CheckpointData object");
- checkpointVersion(checkpointData, "StatePropagatorData version", c_currentVersion);
-
- checkpointData->arrayRef("positions", makeCheckpointArrayRef<operation>(xGlobalRef));
- checkpointData->arrayRef("velocities", makeCheckpointArrayRef<operation>(vGlobalRef));
- checkpointData->tensor("box", statePropagatorData_->box_);
- checkpointData->scalar("ddpCount", &statePropagatorData_->ddpCount_);
- checkpointData->scalar("ddpCountCgGl", &statePropagatorData_->ddpCountCgGl_);
- checkpointData->arrayRef("cgGl", makeCheckpointArrayRef<operation>(statePropagatorData_->cgGl_));
+ statePropagatorData_->doCheckpointData<CheckpointDataOperation::Write>(&checkpointData.value());
}
}
-void StatePropagatorData::Element::saveCheckpointState(std::optional<WriteCheckpointData> checkpointData,
- const t_commrec* cr)
-{
- doCheckpointData<CheckpointDataOperation::Write>(
- checkpointData ? &checkpointData.value() : nullptr, cr);
-}
-
/*!
* \brief Update the legacy global state
*
void StatePropagatorData::Element::restoreCheckpointState(std::optional<ReadCheckpointData> checkpointData,
const t_commrec* cr)
{
- doCheckpointData<CheckpointDataOperation::Read>(checkpointData ? &checkpointData.value() : nullptr, cr);
+ if (MASTER(cr))
+ {
+ statePropagatorData_->doCheckpointData<CheckpointDataOperation::Read>(&checkpointData.value());
+ }
// Copy data to global state to be distributed by DD at setup stage
if (DOMAINDECOMP(cr) && MASTER(cr))
statePropagatorData_->ddpCount_, statePropagatorData_->ddpCountCgGl_,
statePropagatorData_->cgGl_);
}
+ // Everything is local - copy global vectors to local ones
+ if (!DOMAINDECOMP(cr))
+ {
+ statePropagatorData_->x_.resizeWithPadding(statePropagatorData_->totalNumAtoms_);
+ statePropagatorData_->v_.resizeWithPadding(statePropagatorData_->totalNumAtoms_);
+ std::copy(statePropagatorData_->xGlobal_.begin(), statePropagatorData_->xGlobal_.end(),
+ statePropagatorData_->x_.begin());
+ std::copy(statePropagatorData_->vGlobal_.begin(), statePropagatorData_->vGlobal_.end(),
+ statePropagatorData_->v_.begin());
+ }
}
const std::string& StatePropagatorData::Element::clientID()
{
- return identifier_;
+ return StatePropagatorData::checkpointID();
}
void StatePropagatorData::Element::trajectoryWriterTeardown(gmx_mdoutf* gmx_unused outf)
return statePropagatorData->element();
}
+void StatePropagatorData::readCheckpointToTrxFrame(t_trxframe* trxFrame, ReadCheckpointData readCheckpointData)
+{
+ StatePropagatorData statePropagatorData;
+ statePropagatorData.doCheckpointData(&readCheckpointData);
+
+ trxFrame->natoms = statePropagatorData.totalNumAtoms_;
+ trxFrame->bX = true;
+ trxFrame->x = makeRvecArray(statePropagatorData.xGlobal_, statePropagatorData.totalNumAtoms_);
+ trxFrame->bV = true;
+ trxFrame->v = makeRvecArray(statePropagatorData.vGlobal_, statePropagatorData.totalNumAtoms_);
+ trxFrame->bF = false;
+ trxFrame->bBox = true;
+ copy_mat(statePropagatorData.box_, trxFrame->box);
+}
+
+const std::string& StatePropagatorData::checkpointID()
+{
+ static const std::string identifier = "StatePropagatorData";
+ return identifier;
+}
+
} // namespace gmx
struct t_inputrec;
class t_state;
struct t_mdatoms;
+struct t_trxframe;
namespace gmx
{
//! Initial set up for the associated element
void setup();
+ //! Read everything that can be stored in t_trxframe from a checkpoint file
+ static void readCheckpointToTrxFrame(t_trxframe* trxFrame, ReadCheckpointData readCheckpointData);
+ //! CheckpointHelper identifier
+ static const std::string& checkpointID();
+
//! \cond
// (doxygen doesn't like these)
// Classes which need access to legacy state
//! \endcond
private:
+ //! Default constructor - only used internally
+ StatePropagatorData() = default;
//! The total number of atoms in the system
int totalNumAtoms_;
//! The local number of atoms
//! OMP helper to move x_ to previousX_
void copyPosition(int start, int end);
+ //! Helper function to read from / write to CheckpointData
+ template<CheckpointDataOperation operation>
+ void doCheckpointData(CheckpointData<operation>* checkpointData);
+
// Access to legacy state
//! Get a deep copy of the current state in legacy format
std::unique_ptr<t_state> localState();
//! ITrajectoryWriterClient implementation
std::optional<ITrajectoryWriterCallback> registerTrajectoryWriterCallback(TrajectoryEvent event) override;
- //! CheckpointHelper identifier
- const std::string identifier_ = "StatePropagatorData";
- //! Helper function to read from / write to CheckpointData
- template<CheckpointDataOperation operation>
- void doCheckpointData(CheckpointData<operation>* checkpointData, const t_commrec* cr);
-
//! ILastStepSignallerClient implementation (used for final output only)
std::optional<SignallerCallback> registerLastStepCallback() override;
gmx_add_gtest_executable(${exename}
CPP_SOURCE_FILES
+ checkpoint.cpp
exactcontinuation.cpp
grompp.cpp
initialconstraints.cpp
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, 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 checkpoint writing sanity checks
+ *
+ * Checks that final checkpoint is equal to final trajectory output.
+ *
+ * \author Pascal Merz <pascal.merz@me.com>
+ * \ingroup module_mdrun_integration_tests
+ */
+#include "gmxpre.h"
+
+#include "config.h"
+
+#include "gromacs/utility/strconvert.h"
+#include "gromacs/utility/stringutil.h"
+
+#include "testutils/simulationdatabase.h"
+
+#include "moduletest.h"
+#include "simulatorcomparison.h"
+#include "trajectoryreader.h"
+
+namespace gmx::test
+{
+namespace
+{
+
+class CheckpointCoordinatesSanityChecks :
+ public MdrunTestFixture,
+ public ::testing::WithParamInterface<std::tuple<std::string, std::string, std::string, std::string>>
+{
+public:
+ void runSimulation(MdpFieldValues mdpFieldValues,
+ int numSteps,
+ const std::string& trrFileName,
+ const std::string& cptFileName)
+ {
+ mdpFieldValues["nsteps"] = toString(numSteps);
+ // Trajectories have the initial and the last frame
+ mdpFieldValues["nstxout"] = toString(numSteps);
+ mdpFieldValues["nstvout"] = toString(numSteps);
+ mdpFieldValues["nstfout"] = toString(0);
+
+ // Run grompp
+ runner_.useStringAsMdpFile(prepareMdpFileContents(mdpFieldValues));
+ runGrompp(&runner_);
+
+ // Do first mdrun
+ runner_.fullPrecisionTrajectoryFileName_ = trrFileName;
+ runMdrun(&runner_, { { "-cpo", cptFileName } });
+ }
+
+ static void compareCptAndTrr(const std::string& trrFileName,
+ const std::string& cptFileName,
+ const TrajectoryComparison& trajectoryComparison)
+ {
+ TrajectoryFrameReader trrReader(trrFileName);
+ TrajectoryFrameReader cptReader(cptFileName);
+ // Checkpoint has at least one frame
+ EXPECT_TRUE(cptReader.readNextFrame());
+ // Trajectory has at least two frames
+ EXPECT_TRUE(trrReader.readNextFrame());
+ EXPECT_NO_THROW(trrReader.frame());
+ EXPECT_TRUE(trrReader.readNextFrame());
+
+ // Now compare frames
+ trajectoryComparison(cptReader.frame(), trrReader.frame());
+
+ // Files had exactly 1 / 2 frames
+ EXPECT_FALSE(cptReader.readNextFrame());
+ EXPECT_FALSE(trrReader.readNextFrame());
+ }
+};
+
+TEST_P(CheckpointCoordinatesSanityChecks, WithinTolerances)
+{
+ const auto& params = GetParam();
+ const auto& simulationName = std::get<0>(params);
+ const auto& integrator = std::get<1>(params);
+ const auto& temperatureCoupling = std::get<2>(params);
+ const auto& pressureCoupling = std::get<3>(params);
+
+ // Specify how trajectory frame matching must work.
+ TrajectoryFrameMatchSettings trajectoryMatchSettings{ true,
+ true,
+ true,
+ ComparisonConditions::MustCompare,
+ ComparisonConditions::MustCompare,
+ ComparisonConditions::NoComparison,
+ MaxNumFrames::compareAllFrames() };
+ if (integrator == "md-vv")
+ {
+ // When using md-vv and modular simulator, the velocities are expected to be off by
+ // 1/2 dt between checkpoint (top of the loop) and trajectory (full time step state)
+ trajectoryMatchSettings.velocitiesComparison = ComparisonConditions::NoComparison;
+ }
+ const TrajectoryTolerances trajectoryTolerances{ defaultRealTolerance(), defaultRealTolerance(),
+ defaultRealTolerance(), defaultRealTolerance() };
+
+ const auto mdpFieldValues =
+ prepareMdpFieldValues(simulationName, integrator, temperatureCoupling, pressureCoupling);
+ runner_.useTopGroAndNdxFromDatabase(simulationName);
+ // Set file names
+ const auto cptFileName = fileManager_.getTemporaryFilePath(".cpt");
+ const auto trrFileName = fileManager_.getTemporaryFilePath(".trr");
+
+ SCOPED_TRACE(formatString(
+ "Checking the sanity of the checkpointed coordinates using system '%s' "
+ "with integrator '%s', '%s' temperature coupling, and '%s' pressure coupling ",
+ simulationName.c_str(), integrator.c_str(), temperatureCoupling.c_str(),
+ pressureCoupling.c_str()));
+
+ SCOPED_TRACE("End of trajectory sanity");
+ // Running a few steps - we expect the checkpoint to be equal
+ // to the final configuration
+ runSimulation(mdpFieldValues, 16, trrFileName, cptFileName);
+ compareCptAndTrr(trrFileName, cptFileName, { trajectoryMatchSettings, trajectoryTolerances });
+}
+
+#if !GMX_GPU_OPENCL
+INSTANTIATE_TEST_CASE_P(CheckpointCoordinatesAreSane,
+ CheckpointCoordinatesSanityChecks,
+ ::testing::Combine(::testing::Values("spc2"),
+ ::testing::Values("md", "md-vv"),
+ ::testing::Values("no"),
+ ::testing::Values("no")));
+#else
+INSTANTIATE_TEST_CASE_P(DISABLED_CheckpointCoordinatesAreSane,
+ CheckpointCoordinatesSanityChecks,
+ ::testing::Combine(::testing::Values("spc2"),
+ ::testing::Values("md", "md-vv"),
+ ::testing::Values("no"),
+ ::testing::Values("no")));
+#endif
+
+} // namespace
+} // namespace gmx::test