domdec -> mdlib
domdec -> pulling
fileio -> gmxlib
+
+# This can go away once restart handling is consolidated in handleRestart
+fileio -> mdrunutility
+
mdlib -> essentialdynamics
mdlib -> imd
mdlib -> ewald
return nullptr;
}
+ StartingBehavior startingBehavior = handleRestart(options_.cr,
+ options_.ms,
+ options_.mdrunOptions.appendingBehavior,
+ ssize(options_.filenames),
+ options_.filenames.data());
if (MASTER(options_.cr))
{
options_.logFileGuard = openLogFile(ftp2fn(efLOG,
options_.filenames.size(),
options_.filenames.data()),
- options_.mdrunOptions.continuationOptions.appendFiles);
+ startingBehavior == StartingBehavior::RestartWithAppending);
}
auto simulationContext = createSimulationContext(options_.cr);
auto builder = MdrunnerBuilder(std::move(mdModules),
compat::not_null<decltype( &simulationContext)>(&simulationContext));
- builder.addSimulationMethod(options_.mdrunOptions, options_.pforce);
+ builder.addSimulationMethod(options_.mdrunOptions, options_.pforce, startingBehavior);
builder.addDomainDecomposition(options_.domdecOptions);
// \todo pass by value
builder.addNonBonded(options_.nbpu_opt_choices[0]);
#include "gromacs/mdlib/groupcoord.h"
#include "gromacs/mdlib/stat.h"
#include "gromacs/mdlib/update.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/edsamhistory.h"
#include "gromacs/mdtypes/inputrec.h"
* gmx make_edi can be used to create an .edi input file.
*/
static std::unique_ptr<gmx::EssentialDynamics> ed_open(
- int natoms,
- ObservablesHistory *oh,
- const char *ediFileName,
- const char *edoFileName,
- gmx_bool bAppend,
- const gmx_output_env_t *oenv,
- const t_commrec *cr)
+ int natoms,
+ ObservablesHistory *oh,
+ const char *ediFileName,
+ const char *edoFileName,
+ const gmx::StartingBehavior startingBehavior,
+ const gmx_output_env_t *oenv,
+ const t_commrec *cr)
{
auto edHandle = std::make_unique<gmx::EssentialDynamics>();
auto ed = edHandle->getLegacyED();
init_edsamstate(*ed, EDstate);
/* The master opens the ED output file */
- if (bAppend)
+ if (startingBehavior == gmx::StartingBehavior::RestartWithAppending)
{
ed->edo = gmx_fio_fopen(edoFileName, "a+");
}
/* Init routine for ED and flooding. Calls init_edi in a loop for every .edi-cycle
* contained in the input file, creates a NULL terminated list of t_edpar structures */
std::unique_ptr<gmx::EssentialDynamics> init_edsam(
- const gmx::MDLogger &mdlog,
- const char *ediFileName,
- const char *edoFileName,
- const gmx_mtop_t *mtop,
- const t_inputrec *ir,
- const t_commrec *cr,
- gmx::Constraints *constr,
- const t_state *globalState,
- ObservablesHistory *oh,
- const gmx_output_env_t *oenv,
- gmx_bool bAppend)
+ const gmx::MDLogger &mdlog,
+ const char *ediFileName,
+ const char *edoFileName,
+ const gmx_mtop_t *mtop,
+ const t_inputrec *ir,
+ const t_commrec *cr,
+ gmx::Constraints *constr,
+ const t_state *globalState,
+ ObservablesHistory *oh,
+ const gmx_output_env_t *oenv,
+ const gmx::StartingBehavior startingBehavior)
{
int i, avindex;
rvec *x_pbc = nullptr; /* positions of the whole MD system with pbc removed */
"gmx grompp and the related .mdp options may change also.");
/* Open input and output files, allocate space for ED data structure */
- auto edHandle = ed_open(mtop->natoms, oh, ediFileName, edoFileName, bAppend, oenv, cr);
+ auto edHandle = ed_open(mtop->natoms, oh, ediFileName, edoFileName, startingBehavior, oenv, cr);
auto ed = edHandle->getLegacyED();
GMX_RELEASE_ASSERT(constr != nullptr, "Must have valid constraints object");
constr->saveEdsamPointer(ed);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, 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.
namespace gmx
{
+enum class StartingBehavior;
class Constraints;
class EssentialDynamics
{
* \param globalState The global state, only used on the master rank.
* \param oh The observables history container.
* \param oenv The output environment information.
- * \param bAppend Append to existing output files?
+ * \param startingBehavior Describes whether this is a restart appending to output files
*
* \returns A pointer to the ED data structure.
*/
const t_state *globalState,
ObservablesHistory *oh,
const gmx_output_env_t *oenv,
- gmx_bool bAppend);
+ gmx::StartingBehavior startingBehavior);
/*! \brief Make a selection of the home atoms for the ED groups.
*
#include "gromacs/math/vec.h"
#include "gromacs/math/vecdump.h"
#include "gromacs/math/vectypes.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/awh_correlation_history.h"
#include "gromacs/mdtypes/awh_history.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/energyhistory.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/mdtypes/observableshistory.h"
#include "gromacs/mdtypes/pullhistory.h"
#include "gromacs/mdtypes/state.h"
int eIntegrator,
int *init_fep_state,
CheckpointHeaderContents *headerContents,
- t_state *state, gmx_bool *bReadEkin,
+ t_state *state,
ObservablesHistory *observablesHistory,
- gmx_bool bAppendOutputFiles, gmx_bool bForceAppend,
+ const gmx::StartingBehavior startingBehavior,
+ const gmx::AppendingBehavior appendingBehavior,
gmx_bool reproducibilityRequested)
{
t_fileio *fp;
fp = gmx_fio_open(fn, "r");
do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, headerContents);
- if (bAppendOutputFiles &&
+ if (appendingBehavior == gmx::AppendingBehavior::Appending &&
headerContents->file_version >= 13 && headerContents->double_prec != GMX_DOUBLE)
{
gmx_fatal(FARGS, "Output file appending requested, but the code and checkpoint file precision (single/double) don't match");
// because we still need to compute a checksum for it. Otherwise
// we report to the new log file about the checkpoint file that we
// are reading from.
- FILE *fplog = bAppendOutputFiles ? nullptr : gmx_fio_getfp(logfio);
+ FILE *fplog = (startingBehavior == gmx::StartingBehavior::RestartWithAppending) ? nullptr : gmx_fio_getfp(logfio);
if (fplog)
{
fprintf(fplog, "\n");
{
cp_error();
}
- *bReadEkin = (((headerContents->flags_eks & (1<<eeksEKINH)) != 0) ||
- ((headerContents->flags_eks & (1<<eeksEKINF)) != 0) ||
- ((headerContents->flags_eks & (1<<eeksEKINO)) != 0) ||
- (((headerContents->flags_eks & (1<<eeksEKINSCALEF)) |
- (headerContents->flags_eks & (1<<eeksEKINSCALEH)) |
- (headerContents->flags_eks & (1<<eeksVSCALE))) != 0));
+ state->ekinstate.hasReadEkinState = (((headerContents->flags_eks & (1<<eeksEKINH)) != 0) ||
+ ((headerContents->flags_eks & (1<<eeksEKINF)) != 0) ||
+ ((headerContents->flags_eks & (1<<eeksEKINO)) != 0) ||
+ (((headerContents->flags_eks & (1<<eeksEKINSCALEF)) |
+ (headerContents->flags_eks & (1<<eeksEKINSCALEH)) |
+ (headerContents->flags_eks & (1<<eeksVSCALE))) != 0));
if (headerContents->flags_enh && observablesHistory->energyHistory == nullptr)
{
* All files are md5sum checked such that we can be sure that
* we do not truncate other (maybe imprortant) files.
*/
- if (bAppendOutputFiles)
+ if (startingBehavior == gmx::StartingBehavior::RestartWithAppending)
{
if (outputfiles.empty())
{
const gmx_file_position_t &logOutputFile = outputfiles[0];
if (!GMX_FAHCORE)
{
- lockLogFile(fplog, logfio, logOutputFile.filename, bForceAppend);
+ lockLogFile(fplog, logfio, logOutputFile.filename,
+ appendingBehavior == gmx::AppendingBehavior::Appending);
checkOutputFile(logfio, logOutputFile);
if (gmx_fio_seek(logfio, logOutputFile.offset))
void load_checkpoint(const char *fn, t_fileio *logfio,
const t_commrec *cr, const ivec dd_nc,
t_inputrec *ir, t_state *state,
- gmx_bool *bReadEkin,
ObservablesHistory *observablesHistory,
- gmx_bool bAppend, gmx_bool bForceAppend,
+ const gmx::StartingBehavior startingBehavior,
+ const gmx::AppendingBehavior appendingBehavior,
gmx_bool reproducibilityRequested)
{
CheckpointHeaderContents headerContents;
cr, dd_nc,
ir->eI, &(ir->fepvals->init_fep_state),
&headerContents,
- state, bReadEkin, observablesHistory,
- bAppend, bForceAppend,
+ state, observablesHistory,
+ startingBehavior,
+ appendingBehavior,
reproducibilityRequested);
}
if (PAR(cr))
{
gmx_bcast(sizeof(headerContents.step), &headerContents.step, cr);
- gmx_bcast(sizeof(*bReadEkin), bReadEkin, cr);
}
ir->bContinuation = TRUE;
// TODO Should the following condition be <=? Currently if you
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, 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.
class t_state;
struct t_trxframe;
+namespace gmx
+{
+enum class AppendingBehavior;
+enum class StartingBehavior;
+}
+
/* the name of the environment variable to disable fsync failure checks with */
#define GMX_IGNORE_FSYNC_FAILURE_ENV "GMX_IGNORE_FSYNC_FAILURE"
* The master node reads the file
* and communicates all the modified number of steps,
* but not the state itself.
- * When bAppend is set, lock the log file and truncate the existing output
+ * When appending, lock the log file and truncate the existing output
* files so they can be appended.
- * With bAppend and bForceAppend: truncate anyhow if the system does not
+ * When appending is explicitly requested, truncate anyhow if the system does not
* support file locking.
* With reproducibilityRequested warns about version, build, #ranks differences.
*/
void load_checkpoint(const char *fn, t_fileio *logfio,
const t_commrec *cr, const ivec dd_nc,
t_inputrec *ir, t_state *state,
- gmx_bool *bReadEkin,
ObservablesHistory *observablesHistory,
- gmx_bool bAppend, gmx_bool bForceAppend,
+ gmx::StartingBehavior startingBehavior,
+ gmx::AppendingBehavior appendingBehavior,
gmx_bool reproducibilityRequested);
/* Read everything that can be stored in t_trxframe from a checkpoint file */
#include "gromacs/mdlib/groupcoord.h"
#include "gromacs/mdlib/sighandler.h"
#include "gromacs/mdlib/stat.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/imdmodule.h"
void openOutputFile(const char *fn,
int nat_total,
const gmx_output_env_t *oenv,
- const ContinuationOptions &continuationOptions);
+ StartingBehavior startingBehavior);
/*! \brief Creates the molecule start-end position array of molecules in the IMD group. */
void prepareMoleculesInImdGroup(const gmx_mtop_t *top_global);
/*! \brief Removes shifts of molecules diffused outside of the box. */
void
-ImdSession::Impl::openOutputFile(const char *fn,
- int nat_total,
- const gmx_output_env_t *oenv,
- const ContinuationOptions &continuationOptions)
+ImdSession::Impl::openOutputFile(const char *fn,
+ int nat_total,
+ const gmx_output_env_t *oenv,
+ const gmx::StartingBehavior startingBehavior)
{
/* Open log file of applied IMD forces if requested */
if (!fn || !oenv)
}
/* If we append to an existing file, all the header information is already there */
- if (continuationOptions.appendFiles)
+ if (startingBehavior == StartingBehavior::RestartWithAppending)
{
outf = gmx_fio_fopen(fn, "a+");
}
}
std::unique_ptr<ImdSession>
-makeImdSession(const t_inputrec *ir,
- const t_commrec *cr,
- gmx_wallcycle *wcycle,
- gmx_enerdata_t *enerd,
- const gmx_multisim_t *ms,
- const gmx_mtop_t *top_global,
- const MDLogger &mdlog,
- const rvec x[],
- int nfile,
- const t_filenm fnm[],
- const gmx_output_env_t *oenv,
- const MdrunOptions &mdrunOptions)
+makeImdSession(const t_inputrec *ir,
+ const t_commrec *cr,
+ gmx_wallcycle *wcycle,
+ gmx_enerdata_t *enerd,
+ const gmx_multisim_t *ms,
+ const gmx_mtop_t *top_global,
+ const MDLogger &mdlog,
+ const rvec x[],
+ int nfile,
+ const t_filenm fnm[],
+ const gmx_output_env_t *oenv,
+ const ImdOptions &options,
+ const gmx::StartingBehavior startingBehavior)
{
std::unique_ptr<ImdSession> session(new ImdSession(mdlog));
auto impl = session->impl_.get();
return session;
}
- const auto &options = mdrunOptions.imdOptions;
-
bool createSession = false;
/* It seems we have a .tpr file that defines an IMD group and thus allows IMD connections.
* Check whether we can actually provide the IMD functionality for this setting: */
/* We might need to open an output file for IMD forces data */
if (MASTER(cr))
{
- impl->openOutputFile(opt2fn("-if", nfile, fnm), nat_total, oenv, mdrunOptions.continuationOptions);
+ impl->openOutputFile(opt2fn("-if", nfile, fnm), nat_total, oenv, startingBehavior);
}
/* Make sure that we operate with a valid atom index array for the IMD atoms */
namespace gmx
{
+enum class StartingBehavior;
class IMDModule;
class ImdSession;
class InteractiveMolecularDynamics;
class MDLogger;
+struct ImdOptions;
struct MdrunOptions;
/*! \brief
* \param nfile Number of files.
* \param fnm Struct containing file names etc.
* \param oenv Output options.
- * \param mdrunOptions Options for mdrun.
+ * \param options Options for interactive MD.
+ * \param startingBehavior Describes whether this is a restart appending to output files
*/
std::unique_ptr<ImdSession>
-makeImdSession(const t_inputrec *ir,
- const t_commrec *cr,
- gmx_wallcycle *wcycle,
- gmx_enerdata_t *enerd,
- const gmx_multisim_t *ms,
- const gmx_mtop_t *top_global,
- const MDLogger &mdlog,
- const rvec x[],
- int nfile, const t_filenm fnm[], const gmx_output_env_t *oenv,
- const MdrunOptions &mdrunOptions);
+makeImdSession(const t_inputrec *ir,
+ const t_commrec *cr,
+ gmx_wallcycle *wcycle,
+ gmx_enerdata_t *enerd,
+ const gmx_multisim_t *ms,
+ const gmx_mtop_t *top_global,
+ const MDLogger &mdlog,
+ const rvec x[],
+ int nfile,
+ const t_filenm fnm[],
+ const gmx_output_env_t *oenv,
+ const ImdOptions &options,
+ StartingBehavior startingBehavior);
class ImdSession
{
int nfile,
const t_filenm fnm[],
const gmx_output_env_t *oenv,
- const MdrunOptions &mdrunOptions);
+ const ImdOptions &options,
+ StartingBehavior startingBehavior);
};
} // namespace gmx
#include "gromacs/fileio/xvgr.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/trajectory_writing.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/imdoutputprovider.h"
#include "gromacs/mdtypes/inputrec.h"
const t_commrec *cr,
gmx::IMDOutputProvider *outputProvider,
const t_inputrec *ir, gmx_mtop_t *top_global,
- const gmx_output_env_t *oenv, gmx_wallcycle_t wcycle)
+ const gmx_output_env_t *oenv, gmx_wallcycle_t wcycle,
+ const gmx::StartingBehavior startingBehavior)
{
gmx_mdoutf_t of;
const char *appendMode = "a+", *writeMode = "w+", *filemode;
- gmx_bool bAppendFiles, bCiteTng = FALSE;
+ gmx_bool bCiteTng = FALSE;
int i;
+ bool restartWithAppending = (startingBehavior == gmx::StartingBehavior::RestartWithAppending);
snew(of, 1);
if (MASTER(cr))
{
- bAppendFiles = mdrunOptions.continuationOptions.appendFiles;
-
of->bKeepAndNumCPT = mdrunOptions.checkpointOptions.keepAndNumberCheckpointFiles;
- filemode = bAppendFiles ? appendMode : writeMode;
+ filemode = restartWithAppending ? appendMode : writeMode;
if (EI_DYNAMICS(ir->eI) &&
ir->nstxout_compressed > 0)
(ir->fepvals->separate_dhdl_file == esepdhdlfileYES ) &&
EI_DYNAMICS(ir->eI))
{
- if (bAppendFiles)
+ if (restartWithAppending)
{
of->fp_dhdl = gmx_fio_fopen(opt2fn("-dhdl", nfile, fnm), filemode);
}
}
}
- outputProvider->initOutput(fplog, nfile, fnm, bAppendFiles, oenv);
+ outputProvider->initOutput(fplog, nfile, fnm, restartWithAppending, oenv);
/* Set up atom counts so they can be passed to actual
trajectory-writing routines later. Also, XTC writing needs
namespace gmx
{
+enum class StartingBehavior;
class IMDOutputProvider;
struct MdrunOptions;
}
const t_inputrec *ir,
gmx_mtop_t *mtop,
const gmx_output_env_t *oenv,
- gmx_wallcycle_t wcycle);
+ gmx_wallcycle_t wcycle,
+ gmx::StartingBehavior startingBehavior);
/*! \brief Getter for file pointer */
ener_file_t mdoutf_get_fp_ene(gmx_mdoutf_t of);
ekinstate->ekinscalef_nhc.resize(ekinstate->ekin_n);
ekinstate->ekinscaleh_nhc.resize(ekinstate->ekin_n);
ekinstate->vscale_nhc.resize(ekinstate->ekin_n);
- ekinstate->dekindl = 0;
- ekinstate->mvcos = 0;
+ ekinstate->dekindl = 0;
+ ekinstate->mvcos = 0;
+ ekinstate->hasReadEkinState = false;
}
void update_ekinstate(ekinstate_t *ekinstate, const gmx_ekindata_t *ekind)
namespace gmx
{
+enum class StartingBehavior;
class BoxDeformation;
class Constraints;
class PpForceWorkload;
const gmx_output_env_t *oenv;
//! Contains command-line options to mdrun.
const MdrunOptions &mdrunOptions;
+ //! Whether the simulation will start afresh, or restart with/without appending.
+ StartingBehavior startingBehavior;
//! Handles virtual sites.
gmx_vsite_t *vsite;
//! Handles constraints.
}
#endif
- if (!opt2bSet("-cpi",
- ssize(filenames), filenames.data()))
+ if (!opt2parg_bSet("-append", asize(pa), pa))
{
- // If we are not starting from a checkpoint we never allow files to be appended
- // to, since that has caused a ton of strange behaviour and bugs in the past.
- if (opt2parg_bSet("-append", asize(pa), pa))
+ mdrunOptions.appendingBehavior = AppendingBehavior::Auto;
+ }
+ else
+ {
+ if (opt2parg_bool("-append", asize(pa), pa))
{
- // If the user explicitly used the -append option, explain that it is not possible.
- gmx_fatal(FARGS, "GROMACS can only append to files when restarting from a checkpoint.");
+ mdrunOptions.appendingBehavior = AppendingBehavior::Appending;
}
else
{
- // If the user did not say anything explicit, just disable appending.
- bTryToAppendFiles = FALSE;
+ mdrunOptions.appendingBehavior = AppendingBehavior::NoAppending;
}
}
- ContinuationOptions &continuationOptions = mdrunOptions.continuationOptions;
-
- continuationOptions.appendFilesOptionSet = opt2parg_bSet("-append", asize(pa), pa);
-
- handleRestart(cr, ms, bTryToAppendFiles,
- ssize(filenames),
- filenames.data(),
- &continuationOptions.appendFiles,
- &continuationOptions.startedFromCheckpoint);
-
mdrunOptions.rerun = opt2bSet("-rerun",
ssize(filenames),
filenames.data());
//! Print a warning if any force is larger than this (in kJ/mol nm).
real pforce = -1;
+ //! The value of the -append option
+ bool appendOption = true;
+
/*! \brief Output context for writing text files
*
* \todo Clarify initialization, ownership, and lifetime. */
{ nullptr, "auto", "cpu", "gpu", nullptr };
const char *bonded_opt_choices[5] =
{ nullptr, "auto", "cpu", "gpu", nullptr };
- gmx_bool bTryToAppendFiles = TRUE;
const char *gpuIdsAvailable = "";
const char *userGpuTaskAssignment = "";
"Checkpoint interval (minutes)" },
{ "-cpnum", FALSE, etBOOL, {&mdrunOptions.checkpointOptions.keepAndNumberCheckpointFiles},
"Keep and number checkpoint files" },
- { "-append", FALSE, etBOOL, {&bTryToAppendFiles},
+ { "-append", FALSE, etBOOL, {&appendOption},
"Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names" },
{ "-nsteps", FALSE, etINT64, {&mdrunOptions.numStepsCommandline},
"Run this number of steps, overrides .mdp file option (-1 means infinite, -2 means use mdp option, smaller is invalid)" },
#include "gromacs/mdlib/update.h"
#include "gromacs/mdlib/vcm.h"
#include "gromacs/mdlib/vsite.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdrunutility/printtime.h"
#include "gromacs/mdtypes/awh_history.h"
top_global,
ir, cr, constr,
state_global, observablesHistory,
- oenv, mdrunOptions.continuationOptions.appendFiles);
+ oenv,
+ startingBehavior);
}
initialize_lambdas(fplog, *ir, MASTER(cr), &state_global->fep_state, state_global->lambda, lam0);
Update upd(ir, deform);
bool doSimulatedAnnealing = initSimulatedAnnealing(ir, &upd);
- if (!mdrunOptions.continuationOptions.appendFiles)
+ if (startingBehavior != StartingBehavior::RestartWithAppending)
{
pleaseCiteCouplingAlgorithms(fplog, *ir);
}
init_nrnb(nrnb);
- gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, ir, top_global, oenv, wcycle);
+ gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, ir, top_global, oenv, wcycle,
+ startingBehavior);
gmx::EnergyOutput energyOutput;
energyOutput.prepare(mdoutf_get_fp_ene(outf), top_global, ir, pull_work, mdoutf_get_fp_dhdl(outf));
update_mdatoms(mdatoms, state->lambda[efptMASS]);
- const ContinuationOptions &continuationOptions = mdrunOptions.continuationOptions;
- bool startingFromCheckpoint = continuationOptions.startedFromCheckpoint;
-
if (ir->bExpanded)
{
/* Check nstexpanded here, because the grompp check was broken */
{
gmx_fatal(FARGS, "With expanded ensemble, nstexpanded should be a multiple of nstcalcenergy");
}
- init_expanded_ensemble(startingFromCheckpoint, ir, state->dfhist);
+ init_expanded_ensemble(startingBehavior != StartingBehavior::NewSimulation,
+ ir, state->dfhist);
}
if (MASTER(cr))
{
- if (startingFromCheckpoint)
+ if (startingBehavior != StartingBehavior::NewSimulation)
{
/* Restore from energy history if appending to output files */
- if (continuationOptions.appendFiles)
+ if (startingBehavior == StartingBehavior::RestartWithAppending)
{
/* If no history is available (because a checkpoint is from before
* it was written) make a new one later, otherwise restore it.
energyOutput.fillEnergyHistory(observablesHistory->energyHistory.get());
}
- preparePrevStepPullCom(ir, pull_work, mdatoms, state, state_global, cr, startingFromCheckpoint);
+ preparePrevStepPullCom(ir, pull_work, mdatoms, state, state_global, cr,
+ startingBehavior != StartingBehavior::NewSimulation);
// TODO: Remove this by converting AWH into a ForceProvider
- auto awh = prepareAwhModule(fplog, *ir, state_global, cr, ms, startingFromCheckpoint,
+ auto awh = prepareAwhModule(fplog, *ir, state_global, cr, ms, startingBehavior != StartingBehavior::NewSimulation,
shellfc != nullptr,
opt2fn("-awh", nfile, fnm), pull_work);
*/
bStopCM = (ir->comm_mode != ecmNO && !ir->bContinuation);
- if (continuationOptions.haveReadEkin)
+ // When restarting from a checkpoint, it can be appropriate to
+ // initialize ekind from quantities in the checkpoint. Otherwise,
+ // compute_globals must initialize ekind before the simulation
+ // starts/restarts. However, only the master rank knows what was
+ // found in the checkpoint file, so we have to communicate in
+ // order to coordinate the restart.
+ //
+ // TODO Consider removing this communication if/when checkpoint
+ // reading directly follows .tpr reading, because all ranks can
+ // agree on hasReadEkinState at that time.
+ bool hasReadEkinState = MASTER(cr) ? state_global->ekinstate.hasReadEkinState : false;
+ if (PAR(cr))
+ {
+ gmx_bcast(sizeof(hasReadEkinState), &hasReadEkinState, cr);
+ }
+ if (hasReadEkinState)
{
restore_ekinstate_from_state(cr, ekind, &state_global->ekinstate);
}
cglo_flags = (CGLO_INITIALIZATION | CGLO_TEMPERATURE | CGLO_GSTAT
| (EI_VV(ir->eI) ? CGLO_PRESSURE : 0)
| (EI_VV(ir->eI) ? CGLO_CONSTRAINT : 0)
- | (continuationOptions.haveReadEkin ? CGLO_READEKIN : 0));
+ | (hasReadEkinState ? CGLO_READEKIN : 0));
bSumEkinhOld = FALSE;
}
/* Calculate the initial half step temperature, and save the ekinh_old */
- if (!continuationOptions.startedFromCheckpoint)
+ if (startingBehavior == StartingBehavior::NewSimulation)
{
for (i = 0; (i < ir->opts.ngtc); i++)
{
bFirstStep = TRUE;
/* Skip the first Nose-Hoover integration when we get the state from tpx */
- bInitStep = !startingFromCheckpoint || EI_VV(ir->eI);
+ bInitStep = startingBehavior == StartingBehavior::NewSimulation || EI_VV(ir->eI);
bSumEkinhOld = FALSE;
bExchanged = FALSE;
bNeedRepartition = FALSE;
bDoDHDL = do_per_step(step, ir->fepvals->nstdhdl);
bDoFEP = ((ir->efep != efepNO) && do_per_step(step, nstfep));
bDoExpanded = (do_per_step(step, ir->expandedvals->nstexpanded)
- && (ir->bExpanded) && (step > 0) && (!startingFromCheckpoint));
+ && (ir->bExpanded) && (step > 0) &&
+ (startingBehavior == StartingBehavior::NewSimulation));
}
bDoReplEx = (useReplicaExchange && (step > 0) && !bLastStep &&
* Note that the || bLastStep can result in non-exact continuation
* beyond the last step. But we don't consider that to be an issue.
*/
- do_log = do_per_step(step, ir->nstlog) || (bFirstStep && !startingFromCheckpoint) || bLastStep;
+ do_log =
+ (do_per_step(step, ir->nstlog) ||
+ (bFirstStep && startingBehavior == StartingBehavior::NewSimulation) ||
+ bLastStep);
do_verbose = mdrunOptions.verbose &&
(step % mdrunOptions.verboseStepPrintInterval == 0 || bFirstStep || bLastStep);
ddBalanceRegionHandler);
}
- if (EI_VV(ir->eI) && !startingFromCheckpoint)
+ if (EI_VV(ir->eI) && startingBehavior == StartingBehavior::NewSimulation)
/* ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
{
rvec *vbuf = nullptr;
/* TODO This is only needed when we're about to write
* a checkpoint, because we use it after the restart
* (in a kludge?). But what should we be doing if
- * startingFromCheckpoint or bInitStep are true? */
+ * the startingBehavior is NewSimulation or bInitStep are true? */
if (inputrecNptTrotter(ir) || inputrecNphTrotter(ir))
{
copy_mat(shake_vir, state->svir_prev);
bInteractiveMDstep = imdSession->run(step, bNS, state->box, state->x.rvec_array(), t);
/* kludge -- virial is lost with restart for MTTK NPT control. Must reload (saved earlier). */
- if (startingFromCheckpoint && (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)))
+ if (startingBehavior != StartingBehavior::NewSimulation &&
+ (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)))
{
copy_mat(state->svir_prev, shake_vir);
copy_mat(state->fvir_prev, force_vir);
bFirstStep = FALSE;
bInitStep = FALSE;
- startingFromCheckpoint = false;
/* ####### SET VARIABLES FOR NEXT ITERATION IF THEY STILL NEED IT ###### */
/* With all integrators, except VV, we need to retain the pressure
#include "gromacs/mdlib/update.h"
#include "gromacs/mdlib/vcm.h"
#include "gromacs/mdlib/vsite.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdrunutility/printtime.h"
#include "gromacs/mdtypes/awh_history.h"
initialize_lambdas(fplog, *ir, MASTER(cr), &state_global->fep_state, state_global->lambda, lam0);
init_nrnb(nrnb);
- gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, ir, top_global, oenv, wcycle);
+ gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, ir, top_global, oenv, wcycle,
+ StartingBehavior::NewSimulation);
gmx::EnergyOutput energyOutput;
energyOutput.prepare(mdoutf_get_fp_ene(outf), top_global, ir, pull_work, mdoutf_get_fp_dhdl(outf), true);
#include "gromacs/mdlib/trajectory_writing.h"
#include "gromacs/mdlib/update.h"
#include "gromacs/mdlib/vsite.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/printtime.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/inputrec.h"
state_global, top_global, s_min, &top,
nrnb, fr, &graph, mdAtoms, &gstat,
vsite, constr, nullptr);
- gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle);
+ gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle,
+ StartingBehavior::NewSimulation);
gmx::EnergyOutput energyOutput;
energyOutput.prepare(mdoutf_get_fp_ene(outf), top_global, inputrec, pull_work, nullptr);
state_global, top_global, &ems, &top,
nrnb, fr, &graph, mdAtoms, &gstat,
vsite, constr, nullptr);
- gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle);
+ gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle,
+ StartingBehavior::NewSimulation);
gmx::EnergyOutput energyOutput;
energyOutput.prepare(mdoutf_get_fp_ene(outf), top_global, inputrec, pull_work, nullptr);
state_global, top_global, s_try, &top,
nrnb, fr, &graph, mdAtoms, &gstat,
vsite, constr, nullptr);
- gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle);
+ gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle,
+ StartingBehavior::NewSimulation);
gmx::EnergyOutput energyOutput;
energyOutput.prepare(mdoutf_get_fp_ene(outf), top_global, inputrec, pull_work, nullptr);
state_global, top_global, &state_work, &top,
nrnb, fr, &graph, mdAtoms, &gstat,
vsite, constr, &shellfc);
- gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle);
+ gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, inputrec, top_global, nullptr, wcycle,
+ StartingBehavior::NewSimulation);
std::vector<int> atom_index = get_atom_index(top_global);
std::vector<gmx::RVec> fneg(atom_index.size(), {0, 0, 0});
#include "gromacs/mdlib/update.h"
#include "gromacs/mdlib/vcm.h"
#include "gromacs/mdlib/vsite.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdrunutility/printtime.h"
#include "gromacs/mdtypes/awh_history.h"
initialize_lambdas(fplog, *ir, MASTER(cr), &state_global->fep_state, state_global->lambda, lam0);
init_nrnb(nrnb);
- gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, ir, top_global, oenv, wcycle);
+ gmx_mdoutf *outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, ir, top_global, oenv, wcycle,
+ StartingBehavior::NewSimulation);
gmx::EnergyOutput energyOutput;
energyOutput.prepare(mdoutf_get_fp_ene(outf), top_global, ir, pull_work, mdoutf_get_fp_dhdl(outf), true);
#include "gromacs/mdlib/stophandler.h"
#include "gromacs/mdrun/mdmodules.h"
#include "gromacs/mdrun/simulationcontext.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/logging.h"
#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdrunutility/printtime.h"
newRunner.replExParams = replExParams;
newRunner.pforce = pforce;
newRunner.ms = ms;
+ newRunner.startingBehavior = startingBehavior;
newRunner.stopHandlerBuilder_ = std::make_unique<StopHandlerBuilder>(*stopHandlerBuilder_);
threadMpiMdrunnerAccessBarrier();
// to check that the old log file matches what the checkpoint file
// expects. Otherwise, we should start to write log output now if
// there is a file ready for it.
- if (logFileHandle != nullptr && !mdrunOptions.continuationOptions.appendFiles)
+ if (logFileHandle != nullptr && startingBehavior != StartingBehavior::RestartWithAppending)
{
fplog = gmx_fio_getfp(logFileHandle);
}
ObservablesHistory observablesHistory = {};
- ContinuationOptions &continuationOptions = mdrunOptions.continuationOptions;
-
- if (continuationOptions.startedFromCheckpoint)
+ if (startingBehavior != StartingBehavior::NewSimulation)
{
- /* Check if checkpoint file exists before doing continuation.
- * This way we can use identical input options for the first and subsequent runs...
- */
- gmx_bool bReadEkin;
-
load_checkpoint(opt2fn_master("-cpi", filenames.size(), filenames.data(), cr),
logFileHandle,
cr, domdecOptions.numCells,
inputrec, globalState.get(),
- &bReadEkin, &observablesHistory,
- continuationOptions.appendFiles,
- continuationOptions.appendFilesOptionSet,
+ &observablesHistory,
+ startingBehavior,
+ mdrunOptions.appendingBehavior,
mdrunOptions.reproducible);
- if (bReadEkin)
- {
- continuationOptions.haveReadEkin = true;
- }
-
- if (continuationOptions.appendFiles && logFileHandle)
+ if (startingBehavior == StartingBehavior::RestartWithAppending && logFileHandle)
{
// Now we can start normal logging to the truncated log file.
fplog = gmx_fio_getfp(logFileHandle);
{
init_pull_output_files(pull_work,
filenames.size(), filenames.data(), oenv,
- continuationOptions);
+ startingBehavior);
}
}
globalState.get(),
&mtop,
oenv,
- mdrunOptions);
+ mdrunOptions,
+ startingBehavior);
}
t_swap *swap = nullptr;
swap = init_swapcoords(fplog, inputrec,
opt2fn_master("-swap", filenames.size(), filenames.data(), cr),
&mtop, globalState.get(), &observablesHistory,
- cr, &atomSets, oenv, mdrunOptions);
+ cr, &atomSets, oenv, mdrunOptions,
+ startingBehavior);
}
/* Let makeConstraints know whether we have essential dynamics constraints.
/* Set up interactive MD (IMD) */
auto imdSession = makeImdSession(inputrec, cr, wcycle, &enerd, ms, &mtop, mdlog,
MASTER(cr) ? globalState->x.rvec_array() : nullptr,
- filenames.size(), filenames.data(), oenv, mdrunOptions);
+ filenames.size(), filenames.data(), oenv, mdrunOptions.imdOptions,
+ startingBehavior);
if (DOMAINDECOMP(cr))
{
fplog, cr, ms, mdlog, static_cast<int>(filenames.size()), filenames.data(),
oenv,
mdrunOptions,
+ startingBehavior,
vsite.get(), constr.get(),
enforcedRotation ? enforcedRotation->getLegacyEnfrot() : nullptr,
deform.get(),
~BuilderImplementation();
BuilderImplementation &setExtraMdrunOptions(const MdrunOptions &options,
- real forceWarningThreshold);
+ real forceWarningThreshold,
+ StartingBehavior startingBehavior);
void addDomdec(const DomdecOptions &options);
//! Print a warning if any force is larger than this (in kJ/mol nm).
real forceWarningThreshold_ = -1;
+ //! Whether the simulation will start afresh, or restart with/without appending.
+ StartingBehavior startingBehavior_ = StartingBehavior::NewSimulation;
+
//! The modules that comprise the functionality of mdrun.
std::unique_ptr<MDModules> mdModules_;
Mdrunner::BuilderImplementation::~BuilderImplementation() = default;
Mdrunner::BuilderImplementation &
-Mdrunner::BuilderImplementation::setExtraMdrunOptions(const MdrunOptions &options,
- real forceWarningThreshold)
+Mdrunner::BuilderImplementation::setExtraMdrunOptions(const MdrunOptions &options,
+ const real forceWarningThreshold,
+ const StartingBehavior startingBehavior)
{
mdrunOptions_ = options;
forceWarningThreshold_ = forceWarningThreshold;
+ startingBehavior_ = startingBehavior;
return *this;
}
GMX_ASSERT(context_, "Bug found. It should not be possible to call build() without a valid context.");
- newRunner.mdrunOptions = mdrunOptions_;
- newRunner.domdecOptions = domdecOptions_;
+ newRunner.mdrunOptions = mdrunOptions_;
+ newRunner.pforce = forceWarningThreshold_;
+ newRunner.startingBehavior = startingBehavior_;
+ newRunner.domdecOptions = domdecOptions_;
// \todo determine an invariant to check or confirm that all gmx_hw_opt_t objects are valid
newRunner.hw_opt = hardwareOptions_;
MdrunnerBuilder::~MdrunnerBuilder() = default;
-MdrunnerBuilder &MdrunnerBuilder::addSimulationMethod(const MdrunOptions &options,
- real forceWarningThreshold)
+MdrunnerBuilder &MdrunnerBuilder::addSimulationMethod(const MdrunOptions &options,
+ real forceWarningThreshold,
+ const StartingBehavior startingBehavior)
{
- impl_->setExtraMdrunOptions(options, forceWarningThreshold);
+ impl_->setExtraMdrunOptions(options, forceWarningThreshold, startingBehavior);
return *this;
}
#include "gromacs/hardware/hw_info.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdrun/mdmodules.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
//! \brief Non-owning handle to multi-simulation handler.
gmx_multisim_t *ms = nullptr;
+ //! Whether the simulation will start afresh, or restart with/without appending.
+ StartingBehavior startingBehavior = StartingBehavior::NewSimulation;
+
/*!
* \brief Handle to restraints manager for the current process.
*
*
* \param options structure to copy
* \param forceWarningThreshold Print a warning if any force is larger than this (in kJ/mol nm) (default -1)
+ * \param startingBehavior Whether the simulation will start afresh, or restart with/without appending.
*
* \internal
* \todo Map these parameters to more appropriate encapsulating types.
* Find a better way to indicate "unspecified" than a magic value of the parameter type.
*/
MdrunnerBuilder &addSimulationMethod(const MdrunOptions &options,
- real forceWarningThreshold);
+ real forceWarningThreshold,
+ StartingBehavior startingBehavior);
/*!
* \brief Set the domain decomposition module.
#include "gromacs/gmxlib/network.h"
#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdtypes/commrec.h"
+#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
+namespace gmx
+{
+namespace
+{
+
/*! \brief Search for \p fnm_cp in fnm and return true iff found
*
* \todo This could be implemented sanely with a for loop. */
-static gmx_bool exist_output_file(const char *fnm_cp, int nfile, const t_filenm fnm[])
+gmx_bool exist_output_file(const char *fnm_cp, int nfile, const t_filenm fnm[])
{
int i;
* to be able to rename the logfile correctly.
* When file appending is requested, checks which output files are present,
* and issue a fatal error if some are not.
- * Upon return, bAddPart will tell whether the simulation part
- * needs to be added to the output file name, i.e. when we are doing checkpoint
- * continuation without appending.
*
* This routine cannot print tons of data, since it is called before
* the log file is opened. */
-static void
+StartingBehavior
read_checkpoint_data(const char *filename, int *simulation_part,
t_commrec *cr,
- gmx_bool bTryToAppendFiles,
+ const bool appendingBehaviorAutoOrAppend,
int nfile, const t_filenm fnm[],
- const char *part_suffix,
- gmx_bool *bAddPart,
- bool *bDoAppendFiles)
+ const char *part_suffix)
{
t_fileio *fp;
char *fn, suf_up[STRLEN];
- *bDoAppendFiles = FALSE;
+ StartingBehavior startingBehavior = StartingBehavior::RestartWithoutAppending;
if (SIMMASTER(cr))
{
/* We have already warned the user that no checkpoint file existed before, don't
* need to do it again
*/
+ startingBehavior = StartingBehavior::NewSimulation;
}
else
{
simulation_part,
&outputfiles);
- if (bTryToAppendFiles)
+ if (appendingBehaviorAutoOrAppend)
{
std::size_t nexist = 0;
for (const auto &outputfile : outputfiles)
}
if (nexist == outputfiles.size())
{
- *bDoAppendFiles = bTryToAppendFiles;
+ startingBehavior = StartingBehavior::RestartWithAppending;
}
else
{
}
}
- if (*bDoAppendFiles)
+ if (startingBehavior == StartingBehavior::RestartWithAppending)
{
if (outputfiles.empty())
{
{
gmx_fatal(FARGS, "File appending requested, but the log file is not the first file listed in the checkpoint file");
}
- /* Set bAddPart to whether the suffix string '.part' is present
- * in the log file name.
- */
+ // Choose no appending based on whether the suffix
+ // string '.part' is present in the log file name.
strcpy(suf_up, part_suffix);
upstring(suf_up);
- *bAddPart = (strstr(fn, part_suffix) != nullptr ||
- strstr(fn, suf_up) != nullptr);
+ if ((strstr(fn, part_suffix) != nullptr ||
+ strstr(fn, suf_up) != nullptr))
+ {
+ startingBehavior = StartingBehavior::RestartWithoutAppending;
+ }
}
}
}
{
// Make sure all settings are in sync
gmx_bcast(sizeof(*simulation_part), simulation_part, cr);
-
- if (*simulation_part > 0 && bTryToAppendFiles)
- {
- gmx_bcast(sizeof(*bDoAppendFiles), bDoAppendFiles, cr);
- gmx_bcast(sizeof(*bAddPart), bAddPart, cr);
- }
+ gmx_bcast(sizeof(startingBehavior), &startingBehavior, cr);
}
+
+ return startingBehavior;
}
+} // namespace
+
/* This routine cannot print tons of data, since it is called before the log file is opened. */
-void
-handleRestart(t_commrec *cr,
- const gmx_multisim_t *ms,
- gmx_bool bTryToAppendFiles,
- const int NFILE,
- t_filenm fnm[],
- bool *bDoAppendFiles,
- bool *bStartFromCpt)
+StartingBehavior
+handleRestart(t_commrec *cr,
+ const gmx_multisim_t *ms,
+ const AppendingBehavior appendingBehavior,
+ const int nfile,
+ t_filenm fnm[])
{
- gmx_bool bAddPart;
- int sim_part, sim_part_fn;
- const char *part_suffix = ".part";
- FILE *fpmulti;
-
+ int sim_part, sim_part_fn;
+ const char *part_suffix = ".part";
+ FILE *fpmulti;
+ StartingBehavior startingBehavior = StartingBehavior::NewSimulation;
/* Check if there is ANY checkpoint file available */
sim_part = 1;
sim_part_fn = sim_part;
- if (opt2bSet("-cpi", NFILE, fnm))
+ if (opt2bSet("-cpi", nfile, fnm))
{
- bAddPart = !bTryToAppendFiles;
+ const char *checkpointFilename = MASTER(cr) ? opt2fn("-cpi", nfile, fnm) : nullptr;
+ startingBehavior =
+ read_checkpoint_data(checkpointFilename,
+ &sim_part_fn, cr,
+ (appendingBehavior != AppendingBehavior::NoAppending),
+ nfile, fnm,
+ part_suffix);
- read_checkpoint_data(opt2fn_master("-cpi", NFILE, fnm, cr),
- &sim_part_fn, cr,
- bTryToAppendFiles, NFILE, fnm,
- part_suffix, &bAddPart, bDoAppendFiles);
if (sim_part_fn == 0 && isMasterSimMasterRank(ms, MASTER(cr)))
{
fprintf(stdout, "No previous checkpoint file present with -cpi option, assuming this is a new run.\n");
check_multi_int(fpmulti, ms, sim_part, "simulation part", TRUE);
}
}
- else
- {
- *bDoAppendFiles = false;
- bAddPart = false;
- }
- *bStartFromCpt = sim_part > 1;
-
- if (!*bDoAppendFiles)
- {
- sim_part_fn = sim_part;
- }
-
- if (bAddPart)
+ if (startingBehavior == StartingBehavior::RestartWithoutAppending)
{
char suffix[STRLEN];
/* Rename all output files (except checkpoint files) */
/* create new part name first (zero-filled) */
- sprintf(suffix, "%s%04d", part_suffix, sim_part_fn);
+ sprintf(suffix, "%s%04d", part_suffix, sim_part);
- add_suffix_to_output_names(fnm, NFILE, suffix);
+ add_suffix_to_output_names(fnm, nfile, suffix);
if (isMasterSimMasterRank(ms, MASTER(cr)))
{
fprintf(stdout, "Checkpoint file is from part %d, new output files will be suffixed '%s'.\n", sim_part-1, suffix);
}
}
+
+ return startingBehavior;
}
+
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019, 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.
struct t_commrec;
struct t_filenm;
+namespace gmx
+{
+
+enum class AppendingBehavior;
+
+//! Enumeration for describing how mdrun is (re)starting
+enum class StartingBehavior
+{
+ //! Restarting with appending, if a checkpoint is supplied and other conditions are met.
+ RestartWithAppending,
+ //! Restarting without appending, when a checkpoint is supplied.
+ RestartWithoutAppending,
+ //! Not restarting
+ NewSimulation
+};
+
/*! \brief Handle startup of mdrun, particularly regarding -cpi and -append
*
* If there is a checkpoint file, then prepare to start from that
- * state. If restarting from a checkpoint file and appending is requested with
- * tryToAppendFiles, we will set doAppendFiles to true on return if all files
- * were found correctly. If some files are not found when appending should be
- * done, we will instead issue a fatal error to avoid unintentional problems.
+ * state. If possible/required, do so with appending. If some files
+ * are not found when appending should be done, we will instead issue
+ * a fatal error to avoid unintentional problems.
*
- * If there is no checkpoint file, we assume it is the first part of a new run,
- * and in this case we silently set doAppendFiles to false on return.
+ * If there is no checkpoint file, we return a value to indicate a new
+ * simulation is starting.
*
* On return, \p fnm is updated with suffix strings for part numbers if we are
- * doing a restart from checkpoint and are not appending. The routine also does
- * communication to coordinate behaviour between all ranks of a simulation,
- * and/or simulations.
+ * doing a restart from checkpoint and are not appending.
+ *
+ * The routine also does communication to coordinate behaviour between
+ * all ranks of a simulation, and/or simulations.
*
* \param[in] cr Communication structure
* \param[in] ms Handles multi-simulations.
- * \param[in] bTryToAppendFiles Whether appending is requested (from mdrun)
- * \param[in] NFILE Size of fnm struct
+ * \param[in] appendingBehavior User choice for appending
+ * \param[in] nfile Size of fnm struct
* \param[inout] fnm Filename parameters to mdrun
- * \param[out] bDoAppendFiles True on return if we will do appending.
- * Note that the routine will generate a fatal
- * error for some scenarios where appending is
- * requested but the necessary files not found.
- * \param[out] bStartFromCpt True on return if we found the checkpoint
- * and will use it to restart.
+ * \returns Whether the simulation will restart, perhaps with appending.
*/
-void handleRestart(t_commrec *cr,
- const gmx_multisim_t *ms,
- gmx_bool bTryToAppendFiles,
- int NFILE,
- t_filenm fnm[],
- bool *bDoAppendFiles,
- bool *bStartFromCpt);
+StartingBehavior
+handleRestart(t_commrec *cr,
+ const gmx_multisim_t *ms,
+ AppendingBehavior appendingBehavior,
+ int nfile,
+ t_filenm fnm[]);
+
+} // namespace gmx
#endif
namespace gmx
{
-//! \internal \brief Options and settings for continuing from checkpoint
-struct ContinuationOptions
+//! Enumeration for mdrun appending behavior
+enum class AppendingBehavior
{
- //! True if we are continuing from a checkpoint and should append output files
- bool appendFiles = false;
- //! True if the -append option was explicitly set by the user (either to true of false
- bool appendFilesOptionSet = false;
- //! True if we started from a checkpoint file
- bool startedFromCheckpoint = false;
- //! True if we read the kinetic energy from checkpoint file
- bool haveReadEkin = false;
+ //! Append only if user command-line and file input is correct
+ Auto,
+ //! Must append
+ Appending,
+ //! Must not append
+ NoAppending
};
//! \internal \brief Options for writing checkpoint files
gmx_bool reproducible = FALSE;
//! Write confout.gro at the end of the run
gmx_bool writeConfout = TRUE;
- //! Options for continuing a simulation from a checkpoint file
- ContinuationOptions continuationOptions;
+ //! User option for appending.
+ AppendingBehavior appendingBehavior = AppendingBehavior::Auto;
//! Options for checkpointing th simulation
CheckpointOptions checkpointOptions;
//! Number of steps to run, -2 is use inputrec, -1 is infinite
std::vector<double> vscale_nhc; //!< Nose-Hoover velocity scaling factors
real dekindl; //!< dEkin/dlambda, with free-energy
real mvcos; //!< Cosine(z) component of the momentum, for viscosity calculations
+ /*! \brief Whether KE terms have been read from the checkpoint.
+ *
+ * Only used for managing whether the call to compute_globals
+ * before we enter the MD loop should compute these quantities
+ * fresh, or not. */
+ bool hasReadEkinState;
};
/*! \brief Free-energy sampling history struct
#include "gromacs/fileio/gmxfio.h"
#include "gromacs/fileio/xvgr.h"
#include "gromacs/math/vec.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/mdtypes/observableshistory.h"
#include "gromacs/mdtypes/pullhistory.h"
static FILE *open_pull_out(const char *fn, struct pull_t *pull,
const gmx_output_env_t *oenv,
gmx_bool bCoord,
- const gmx::ContinuationOptions &continuationOptions)
+ const bool restartWithAppending)
{
FILE *fp;
int nsets, m;
char **setname, buf[50];
- if (continuationOptions.appendFiles)
+ if (restartWithAppending)
{
fp = gmx_fio_fopen(fn, "a+");
}
return fp;
}
-void init_pull_output_files(pull_t *pull,
- int nfile,
- const t_filenm fnm[],
- const gmx_output_env_t *oenv,
- const gmx::ContinuationOptions &continuationOptions)
+void init_pull_output_files(pull_t *pull,
+ int nfile,
+ const t_filenm fnm[],
+ const gmx_output_env_t *oenv,
+ const gmx::StartingBehavior startingBehavior)
{
/* Check for px and pf filename collision, if we are writing
both files */
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
+ bool restartWithAppending = startingBehavior == gmx::StartingBehavior::RestartWithAppending;
if ((pull->params.nstxout != 0) &&
(pull->params.nstfout != 0) &&
(px_filename == pf_filename))
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
pull->out_x = open_pull_out(px_appended.c_str(), pull, oenv,
- TRUE, continuationOptions);
+ TRUE, restartWithAppending);
pull->out_f = open_pull_out(pf_appended.c_str(), pull, oenv,
- FALSE, continuationOptions);
+ FALSE, restartWithAppending);
return;
}
else
if (pull->params.nstxout != 0)
{
pull->out_x = open_pull_out(opt2fn("-px", nfile, fnm), pull, oenv,
- TRUE, continuationOptions);
+ TRUE, restartWithAppending);
}
if (pull->params.nstfout != 0)
{
pull->out_f = open_pull_out(opt2fn("-pf", nfile, fnm), pull, oenv,
- FALSE, continuationOptions);
+ FALSE, restartWithAppending);
}
}
namespace gmx
{
-struct ContinuationOptions;
+enum class StartingBehavior;
}
/*! \brief Set up and open the pull output files, when requested.
* \param nfile Number of files.
* \param fnm Standard filename struct.
* \param oenv Output options.
- * \param continuationOptions Options for continuing from checkpoint file
+ * \param startingBehavior Describes whether this is a restart appending to output files
*/
-void init_pull_output_files(pull_t *pull,
- int nfile,
- const t_filenm fnm[],
- const gmx_output_env_t *oenv,
- const gmx::ContinuationOptions &continuationOptions);
+void init_pull_output_files(pull_t *pull,
+ int nfile,
+ const t_filenm fnm[],
+ const gmx_output_env_t *oenv,
+ gmx::StartingBehavior startingBehavior);
/*! \brief Print the pull output (x and/or f)
*
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/groupcoord.h"
#include "gromacs/mdlib/stat.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
//! Allocation size of in & outbuf
int mpi_bufsize = 0;
//! If true, append output files
- gmx_bool appendFiles = false;
+ gmx_bool restartWithAppending = false;
//! Used to skip first output when appending to avoid duplicate entries in rotation outfiles
gmx_bool bOut = false;
//! Stores working data per group
{
FILE *fp;
- if (er->appendFiles)
+ if (er->restartWithAppending)
{
fp = gmx_fio_fopen(fn, "a");
}
char *LegendStr = nullptr;
const t_rot *rot = er->rot;
- if (er->appendFiles)
+ if (er->restartWithAppending)
{
fp = gmx_fio_fopen(fn, "a");
}
char buf[100];
const t_rot *rot = er->rot;
- if (er->appendFiles)
+ if (er->restartWithAppending)
{
fp = gmx_fio_fopen(fn, "a");
}
FILE *fp;
const t_rot *rot = er->rot;
- if (er->appendFiles)
+ if (er->restartWithAppending)
{
fp = gmx_fio_fopen(fn, "a");
}
std::unique_ptr<gmx::EnforcedRotation>
init_rot(FILE *fplog, t_inputrec *ir, int nfile, const t_filenm fnm[],
const t_commrec *cr, gmx::LocalAtomSetManager * atomSets, const t_state *globalState, gmx_mtop_t *mtop, const gmx_output_env_t *oenv,
- const gmx::MdrunOptions &mdrunOptions)
+ const gmx::MdrunOptions &mdrunOptions,
+ const gmx::StartingBehavior startingBehavior)
{
int nat_max = 0; /* Size of biggest rotation group */
rvec *x_pbc = nullptr; /* Space for the pbc-correct atom positions */
auto enforcedRotation = std::make_unique<gmx::EnforcedRotation>();
gmx_enfrot *er = enforcedRotation->getLegacyEnfrot();
// TODO When this module implements IMdpOptions, the ownership will become more clear.
- er->rot = ir->rot;
- er->appendFiles = mdrunOptions.continuationOptions.appendFiles;
+ er->rot = ir->rot;
+ er->restartWithAppending = (startingBehavior == gmx::StartingBehavior::RestartWithAppending);
/* When appending, skip first output to avoid duplicate entries in the data files */
- if (er->appendFiles)
+ if (er->restartWithAppending)
{
er->bOut = FALSE;
}
nat_max = std::max(nat_max, erg->rotg->nat);
init_rot_group(fplog, cr, erg, x_pbc, mtop, mdrunOptions.verbose, er->out_slabs, MASTER(cr) ? globalState->box : nullptr, ir,
- !er->appendFiles); /* Do not output the reference centers
- * again if we are appending */
+ !er->restartWithAppending); /* Do not output the reference centers
+ * again if we are appending */
}
++groupIndex;
}
namespace gmx
{
+enum class StartingBehavior;
class LocalAtomSetManager;
struct MdrunOptions;
* \param mtop Molecular topology.
* \param oenv Needed to open the rotation output xvgr file.
* \param mdrunOptions Options for mdrun.
+ * \param startingBehavior Describes whether this is a restart appending to output files
* \return An enforced rotation module.
*/
std::unique_ptr<gmx::EnforcedRotation>
init_rot(FILE *fplog, t_inputrec *ir, int nfile, const t_filenm fnm[],
const t_commrec *cr, gmx::LocalAtomSetManager * atomSets, const t_state *globalState, gmx_mtop_t *mtop, const gmx_output_env_t *oenv,
- const gmx::MdrunOptions &mdrunOptions);
+ const gmx::MdrunOptions &mdrunOptions,
+ gmx::StartingBehavior startingBehavior);
/*! \brief Calculates the enforced rotation potential(s).
*
#include "gromacs/gmxlib/network.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/groupcoord.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/imdmodule.h"
#include "gromacs/mdtypes/inputrec.h"
static void detect_flux_per_channel_init(
t_swap *s,
swaphistory_t *swapstate,
- gmx_bool bStartFromCpt)
+ const bool isRestart)
{
t_swapgrp *g;
swapstateIons_t *gs;
/******************************************************/
/* Channel and domain history for the individual ions */
/******************************************************/
- if (bStartFromCpt) /* set the pointers right */
+ if (isRestart) /* set the pointers right */
{
g->comp_from = gs->comp_from;
g->channel_label = gs->channel_label;
for (size_t i = 0; i < g->atomset.numAtomsGlobal()/g->apm; i++)
{
g->comp_now[i] = eDomainNotset;
- if (!bStartFromCpt)
+ if (!isRestart)
{
g->comp_from[i] = eDomainNotset;
g->channel_label[i] = eChHistPassedNone;
g->nCylBoth = 0;
}
- if (bStartFromCpt)
+ if (isRestart)
{
fprintf(stderr, "%s Copying channel fluxes from checkpoint file data\n", SwS);
}
for (int ic = 0; ic < eChanNR; ic++)
{
fprintf(stderr, "%s Channel %d flux history for ion type %s (charge %g): ", SwS, ic, g->molname, g->q);
- if (bStartFromCpt)
+ if (isRestart)
{
g->fluxfromAtoB[ic] = gs->fluxfromAtoB[ic];
}
t_swap *init_swapcoords(
- FILE *fplog,
- const t_inputrec *ir,
- const char *fn,
- gmx_mtop_t *mtop,
- const t_state *globalState,
- ObservablesHistory *oh,
- t_commrec *cr,
- gmx::LocalAtomSetManager *atomSets,
- const gmx_output_env_t *oenv,
- const gmx::MdrunOptions &mdrunOptions)
+ FILE *fplog,
+ const t_inputrec *ir,
+ const char *fn,
+ gmx_mtop_t *mtop,
+ const t_state *globalState,
+ ObservablesHistory *oh,
+ t_commrec *cr,
+ gmx::LocalAtomSetManager *atomSets,
+ const gmx_output_env_t *oenv,
+ const gmx::MdrunOptions &mdrunOptions,
+ const gmx::StartingBehavior startingBehavior)
{
t_swapgrp *g;
swapstateIons_t *gs;
- gmx_bool bAppend, bStartFromCpt;
swaphistory_t *swapstate = nullptr;
if ( (PAR(cr)) && !DOMAINDECOMP(cr) )
gmx_fatal(FARGS, "Position swapping is only implemented for domain decomposition!");
}
- bAppend = mdrunOptions.continuationOptions.appendFiles;
- bStartFromCpt = mdrunOptions.continuationOptions.startedFromCheckpoint;
-
auto sc = ir->swap;
auto s = new t_swap();
sc->nAverage = 1; /* averaging makes no sense for reruns */
}
- if (MASTER(cr) && !bAppend)
+ if (MASTER(cr) && startingBehavior == gmx::StartingBehavior::NewSimulation)
{
fprintf(fplog, "\nInitializing ion/water position exchanges\n");
please_cite(fplog, "Kutzner2011b");
* chosen for an exchange can be made whole. */
snew(s->pbc, 1);
+ bool restartWithAppending = (startingBehavior == gmx::StartingBehavior::RestartWithAppending);
if (MASTER(cr))
{
if (bVerbose)
{
- fprintf(stderr, "%s Opening output file %s%s\n", SwS, fn, bAppend ? " for appending" : "");
+ fprintf(stderr, "%s Opening output file %s%s\n", SwS, fn, restartWithAppending ? " for appending" : "");
}
- s->fpout = gmx_fio_fopen(fn, bAppend ? "a" : "w" );
+ s->fpout = gmx_fio_fopen(fn, restartWithAppending ? "a" : "w" );
- if (!bAppend)
+ if (!restartWithAppending)
{
xvgr_header(s->fpout, "Molecule counts", "Time (ps)", "counts", exvggtXNY, oenv);
/* xc has the correct PBC representation for the two channels, so we do
* not need to correct for that */
get_center(g->xc, g->m, g->atomset.numAtomsGlobal(), g->center);
- if (!bAppend)
+ if (!restartWithAppending)
{
fprintf(s->fpout, "# %s group %s-center %5f nm\n", eSwapFixedGrp_names[j],
DimStr[s->swapdim], g->center[s->swapdim]);
}
}
- if (!bAppend)
+ if (!restartWithAppending)
{
if ( (0 != sc->bulkOffset[eCompA]) || (0 != sc->bulkOffset[eCompB]) )
{
/* Get the initial particle concentrations and let the other nodes know */
if (MASTER(cr))
{
- if (bStartFromCpt)
+ if (startingBehavior != gmx::StartingBehavior::NewSimulation)
{
get_initial_ioncounts_from_cpt(ir, s, swapstate, cr, bVerbose);
}
}
/* Prepare (further) checkpoint writes ... */
- if (bStartFromCpt)
+ if (startingBehavior != gmx::StartingBehavior::NewSimulation)
{
/* Consistency check */
if (swapstate->nAverage != sc->nAverage)
{
fprintf(stderr, "%s Requested charge imbalance is Q(A) - Q(B) = %g e.\n", SwS, s->deltaQ);
}
- if (!bAppend)
+ if (!restartWithAppending)
{
fprintf(s->fpout, "# Requested charge imbalance is Q(A)-Q(B) = %g e.\n", s->deltaQ);
}
}
/* Initialize arrays that keep track of through which channel the ions go */
- detect_flux_per_channel_init(s, swapstate, bStartFromCpt);
+ detect_flux_per_channel_init(s, swapstate, startingBehavior != gmx::StartingBehavior::NewSimulation);
/* We need to print the legend if we open this file for the first time. */
- if (MASTER(cr) && !bAppend)
+ if (MASTER(cr) && !restartWithAppending)
{
print_ionlist_legend(ir, s, oenv);
}
namespace gmx
{
+enum class StartingBehavior;
class IMDModule;
class LocalAtomSetManager;
struct MdrunOptions;
* \param[in] atomSets Manager tending to swap atom indices.
* \param[in] oenv Needed to open the swap output XVGR file.
* \param[in] mdrunOptions Options for mdrun.
+ * \param[in] startingBehavior Describes whether this is a restart appending to output files
*/
t_swap *init_swapcoords(
FILE *fplog,
t_commrec *cr,
gmx::LocalAtomSetManager *atomSets,
const gmx_output_env_t *oenv,
- const gmx::MdrunOptions &mdrunOptions);
+ const gmx::MdrunOptions &mdrunOptions,
+ gmx::StartingBehavior startingBehavior);
/*! \brief Finalizes ion / water position swapping, if it was active.
#include "gromacs/mdrun/legacymdrunoptions.h"
#include "gromacs/mdrun/runner.h"
#include "gromacs/mdrun/simulationcontext.h"
+#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/logging.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/utility/arrayref.h"
return 0;
}
+ StartingBehavior startingBehavior = handleRestart(options.cr,
+ options.ms,
+ options.mdrunOptions.appendingBehavior,
+ ssize(options.filenames),
+ options.filenames.data());
if (MASTER(options.cr))
{
options.logFileGuard = openLogFile(ftp2fn(efLOG,
options.filenames.size(),
options.filenames.data()),
- options.mdrunOptions.continuationOptions.appendFiles);
+ startingBehavior == StartingBehavior::RestartWithAppending);
}
/* The SimulationContext is a resource owned by the client code.
*/
auto builder = MdrunnerBuilder(std::move(mdModules),
compat::not_null<decltype( &simulationContext)>(&simulationContext));
- builder.addSimulationMethod(options.mdrunOptions, options.pforce);
+ builder.addSimulationMethod(options.mdrunOptions, options.pforce, startingBehavior);
builder.addDomainDecomposition(options.domdecOptions);
// \todo pass by value
builder.addNonBonded(options.nbpu_opt_choices[0]);