#include <stdio.h>
#include <string.h>
+#include <cstdlib>
+
#include "gromacs/commandline/filenm.h"
#include "gromacs/commandline/pargs.h"
-#include "gromacs/fileio/readinp.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/mdlib/main.h"
#include "gromacs/mdlib/mdrun.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/utility/arraysize.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/smalloc.h"
#include "mdrun_main.h"
+#include "repl_ex.h"
#include "runner.h"
/*! \brief Return whether either of the command-line parameters that
//! Implements C-style main function for mdrun
int gmx_mdrun(int argc, char *argv[])
+{
+ gmx::Mdrunner runner;
+ return runner.mainFunction(argc, argv);
+}
+
+namespace gmx
+{
+
+int Mdrunner::mainFunction(int argc, char *argv[])
{
const char *desc[] = {
"[THISMODULE] is the main computational chemistry engine",
"The option [TT]-pforce[tt] is useful when you suspect a simulation",
"crashes due to too large forces. With this option coordinates and",
"forces of atoms with a force larger than a certain value will",
- "be printed to stderr.",
+ "be printed to stderr. It will also terminate the run when non-finite",
+ "forces are present.",
"[PAR]",
"Checkpoints containing the complete state of the system are written",
"at regular intervals (option [TT]-cpt[tt]) to the file [TT]-cpo[tt],",
"[PAR]",
"When [TT]mdrun[tt] is started with MPI, it does not run niced by default."
};
- t_commrec *cr;
- t_filenm fnm[] = {
- { efTPR, NULL, NULL, ffREAD },
- { efTRN, "-o", NULL, ffWRITE },
- { efCOMPRESSED, "-x", NULL, ffOPTWR },
- { efCPT, "-cpi", NULL, ffOPTRD | ffALLOW_MISSING },
- { efCPT, "-cpo", NULL, ffOPTWR },
- { efSTO, "-c", "confout", ffWRITE },
- { efEDR, "-e", "ener", ffWRITE },
- { efLOG, "-g", "md", ffWRITE },
- { efXVG, "-dhdl", "dhdl", ffOPTWR },
- { efXVG, "-field", "field", ffOPTWR },
- { efXVG, "-table", "table", ffOPTRD },
- { efXVG, "-tablep", "tablep", ffOPTRD },
- { efXVG, "-tableb", "table", ffOPTRDMULT },
- { efTRX, "-rerun", "rerun", ffOPTRD },
- { efXVG, "-tpi", "tpi", ffOPTWR },
- { efXVG, "-tpid", "tpidist", ffOPTWR },
- { efEDI, "-ei", "sam", ffOPTRD },
- { efXVG, "-eo", "edsam", ffOPTWR },
- { efXVG, "-devout", "deviatie", ffOPTWR },
- { efXVG, "-runav", "runaver", ffOPTWR },
- { efXVG, "-px", "pullx", ffOPTWR },
- { efXVG, "-pf", "pullf", ffOPTWR },
- { efXVG, "-ro", "rotation", ffOPTWR },
- { efLOG, "-ra", "rotangles", ffOPTWR },
- { efLOG, "-rs", "rotslabs", ffOPTWR },
- { efLOG, "-rt", "rottorque", ffOPTWR },
- { efMTX, "-mtx", "nm", ffOPTWR },
- { efRND, "-multidir", NULL, ffOPTRDMULT},
- { efDAT, "-membed", "membed", ffOPTRD },
- { efTOP, "-mp", "membed", ffOPTRD },
- { efNDX, "-mn", "membed", ffOPTRD },
- { efXVG, "-if", "imdforces", ffOPTWR },
- { efXVG, "-swap", "swapions", ffOPTWR }
- };
- const int NFILE = asize(fnm);
- /* Command line options ! */
+ /* Command line option parameters, with their default values */
gmx_bool bDDBondCheck = TRUE;
gmx_bool bDDBondComm = TRUE;
gmx_bool bTunePME = TRUE;
- gmx_bool bVerbose = FALSE;
gmx_bool bRerunVSite = FALSE;
gmx_bool bConfout = TRUE;
gmx_bool bReproducible = FALSE;
gmx_bool bIMDterm = FALSE;
gmx_bool bIMDpull = FALSE;
- int npme = -1;
- int nstlist = 0;
- int nmultisim = 0;
- int nstglobalcomm = -1;
- int repl_ex_nst = 0;
- int repl_ex_seed = -1;
- int repl_ex_nex = 0;
- int nstepout = 100;
- int resetstep = -1;
- gmx_int64_t nsteps = -2; /* the value -2 means that the mdp option will be used */
- int imdport = 8888; /* can be almost anything, 8888 is easy to remember */
-
- rvec realddxyz = {0, 0, 0};
- const char *ddrank_opt[ddrankorderNR+1] =
- { NULL, "interleave", "pp_pme", "cartesian", NULL };
- const char *dddlb_opt[] =
- { NULL, "auto", "no", "yes", NULL };
- const char *thread_aff_opt[threadaffNR+1] =
- { NULL, "auto", "on", "off", NULL };
- const char *nbpu_opt[] =
- { NULL, "auto", "cpu", "gpu", "gpu_cpu", NULL };
- real rdd = 0.0, rconstr = 0.0, dlb_scale = 0.8, pforce = -1;
- char *ddcsx = NULL, *ddcsy = NULL, *ddcsz = NULL;
- real cpt_period = 15.0, max_hours = -1;
+ /* Command line options */
+ rvec realddxyz = {0, 0, 0};
+ const char *ddrank_opt_choices[ddrankorderNR+1] =
+ { nullptr, "interleave", "pp_pme", "cartesian", nullptr };
+ const char *dddlb_opt_choices[] =
+ { nullptr, "auto", "no", "yes", nullptr };
+ const char *thread_aff_opt_choices[threadaffNR+1] =
+ { nullptr, "auto", "on", "off", nullptr };
+ const char *nbpu_opt_choices[] =
+ { nullptr, "auto", "cpu", "gpu", "gpu_cpu", nullptr };
gmx_bool bTryToAppendFiles = TRUE;
gmx_bool bKeepAndNumCPT = FALSE;
gmx_bool bResetCountersHalfWay = FALSE;
- gmx_output_env_t *oenv = NULL;
+ const char *gpuIdTaskAssignment = "";
- /* Non transparent initialization of a complex gmx_hw_opt_t struct.
- * But unfortunately we are not allowed to call a function here,
- * since declarations follow below.
- */
- gmx_hw_opt_t hw_opt = {
- 0, 0, 0, 0, threadaffSEL, 0, 0,
- { NULL, FALSE, 0, NULL }
- };
-
- t_pargs pa[] = {
+ t_pargs pa[] = {
{ "-dd", FALSE, etRVEC, {&realddxyz},
"Domain decomposition grid, 0 is optimize" },
- { "-ddorder", FALSE, etENUM, {ddrank_opt},
+ { "-ddorder", FALSE, etENUM, {ddrank_opt_choices},
"DD rank order" },
{ "-npme", FALSE, etINT, {&npme},
"Number of separate ranks to be used for PME, -1 is guess" },
"Number of OpenMP threads per MPI rank to start (0 is guess)" },
{ "-ntomp_pme", FALSE, etINT, {&hw_opt.nthreads_omp_pme},
"Number of OpenMP threads per MPI rank to start (0 is -ntomp)" },
- { "-pin", FALSE, etENUM, {thread_aff_opt},
+ { "-pin", FALSE, etENUM, {thread_aff_opt_choices},
"Whether mdrun should try to set thread affinities" },
{ "-pinoffset", FALSE, etINT, {&hw_opt.core_pinning_offset},
"The lowest logical core number to which mdrun should pin the first thread" },
{ "-pinstride", FALSE, etINT, {&hw_opt.core_pinning_stride},
"Pinning distance in logical cores for threads, use 0 to minimize the number of threads per physical core" },
- { "-gpu_id", FALSE, etSTR, {&hw_opt.gpu_opt.gpu_id},
+ { "-gpu_id", FALSE, etSTR, {&gpuIdTaskAssignment},
"List of GPU device id-s to use, specifies the per-node PP rank to GPU mapping" },
{ "-ddcheck", FALSE, etBOOL, {&bDDBondCheck},
"Check for all bonded interactions with DD" },
"The maximum distance for bonded interactions with DD (nm), 0 is determine from initial coordinates" },
{ "-rcon", FALSE, etREAL, {&rconstr},
"Maximum distance for P-LINCS (nm), 0 is estimate" },
- { "-dlb", FALSE, etENUM, {dddlb_opt},
+ { "-dlb", FALSE, etENUM, {dddlb_opt_choices},
"Dynamic load balancing (with DD)" },
{ "-dds", FALSE, etREAL, {&dlb_scale},
"Fraction in (0,1) by whose reciprocal the initial DD cell size will be increased in order to "
"load balancing." },
{ "-gcom", FALSE, etINT, {&nstglobalcomm},
"Global communication frequency" },
- { "-nb", FALSE, etENUM, {&nbpu_opt},
+ { "-nb", FALSE, etENUM, {&nbpu_opt_choices},
"Calculate non-bonded interactions on" },
- { "-nstlist", FALSE, etINT, {&nstlist},
+ { "-nstlist", FALSE, etINT, {&nstlist_cmdline},
"Set nstlist when using a Verlet buffer tolerance (0 is guess)" },
{ "-tunepme", FALSE, etBOOL, {&bTunePME},
"Optimize PME load between PP/PME ranks or GPU/CPU (only with the Verlet cut-off scheme)" },
"Keep and number checkpoint files" },
{ "-append", FALSE, etBOOL, {&bTryToAppendFiles},
"Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names" },
- { "-nsteps", FALSE, etINT64, {&nsteps},
+ { "-nsteps", FALSE, etINT64, {&nsteps_cmdline},
"Run this number of steps, overrides .mdp file option (-1 means infinite, -2 means use mdp option, smaller is invalid)" },
{ "-maxh", FALSE, etREAL, {&max_hours},
"Terminate after 0.99 times this time (hours)" },
{ "-multi", FALSE, etINT, {&nmultisim},
"Do multiple simulations in parallel" },
- { "-replex", FALSE, etINT, {&repl_ex_nst},
+ { "-replex", FALSE, etINT, {&replExParams.exchangeInterval},
"Attempt replica exchange periodically with this period (steps)" },
- { "-nex", FALSE, etINT, {&repl_ex_nex},
+ { "-nex", FALSE, etINT, {&replExParams.numExchanges},
"Number of random exchanges to carry out each exchange interval (N^3 is one suggestion). -nex zero or not specified gives neighbor replica exchange." },
- { "-reseed", FALSE, etINT, {&repl_ex_seed},
+ { "-reseed", FALSE, etINT, {&replExParams.randomSeed},
"Seed for replica exchange, -1 is generate a seed" },
{ "-imdport", FALSE, etINT, {&imdport},
"HIDDENIMD listening port" },
{ "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
"HIDDENReset the cycle counters after half the number of steps or halfway [TT]-maxh[tt]" }
};
- unsigned long Flags;
- ivec ddxyz;
- int dd_rank_order;
- gmx_bool bDoAppendFiles, bStartFromCpt;
- FILE *fplog;
- int rc;
- char **multidir = NULL;
+ gmx_bool bDoAppendFiles, bStartFromCpt;
+ int rc;
+ char **multidir = nullptr;
cr = init_commrec();
}
*/
- if (!parse_common_args(&argc, argv, PCA_Flags, NFILE, fnm, asize(pa), pa,
- asize(desc), desc, 0, NULL, &oenv))
+ if (!parse_common_args(&argc, argv, PCA_Flags, nfile, fnm, asize(pa), pa,
+ asize(desc), desc, 0, nullptr, &oenv))
{
+ sfree(cr);
return 0;
}
+ // Handle the option that permits the user to select a GPU task
+ // assignment, which could be in an environment variable (so that
+ // there is a way to customize it, when using MPI in heterogeneous
+ // contexts).
+ {
+ // TODO Argument parsing can't handle std::string. We should
+ // fix that by changing the parsing, once more of the roles of
+ // handling, validating and implementing defaults for user
+ // command-line options have been seperated.
+ hw_opt.gpuIdTaskAssignment = gpuIdTaskAssignment;
+ const char *env = getenv("GMX_GPU_ID");
+ if (env != nullptr)
+ {
+ if (!hw_opt.gpuIdTaskAssignment.empty())
+ {
+ gmx_fatal(FARGS, "GMX_GPU_ID and -gpu_id can not be used at the same time");
+ }
+ hw_opt.gpuIdTaskAssignment = env;
+ }
+ }
- dd_rank_order = nenum(ddrank_opt);
+ dd_rank_order = nenum(ddrank_opt_choices);
- hw_opt.thread_affinity = nenum(thread_aff_opt);
+ hw_opt.thread_affinity = nenum(thread_aff_opt_choices);
/* now check the -multi and -multidir option */
- if (opt2bSet("-multidir", NFILE, fnm))
+ if (opt2bSet("-multidir", nfile, fnm))
{
if (nmultisim > 0)
{
gmx_fatal(FARGS, "mdrun -multi and -multidir options are mutually exclusive.");
}
- nmultisim = opt2fns(&multidir, "-multidir", NFILE, fnm);
+ nmultisim = opt2fns(&multidir, "-multidir", nfile, fnm);
}
- if (repl_ex_nst != 0 && nmultisim < 2)
+ if (replExParams.exchangeInterval != 0 && nmultisim < 2)
{
gmx_fatal(FARGS, "Need at least two replicas for replica exchange (option -multi)");
}
- if (repl_ex_nex < 0)
+ if (replExParams.numExchanges < 0)
{
gmx_fatal(FARGS, "Replica exchange number of exchanges needs to be positive");
}
if (nmultisim >= 1)
{
#if !GMX_THREAD_MPI
- init_multisystem(cr, nmultisim, multidir, NFILE, fnm);
+ init_multisystem(cr, nmultisim, multidir, nfile, fnm);
#else
gmx_fatal(FARGS, "mdrun -multi or -multidir are not supported with the thread-MPI library. "
"Please compile GROMACS with a proper external MPI library.");
#endif
}
- if (!opt2bSet("-cpi", NFILE, fnm))
+ if (!opt2bSet("-cpi", nfile, fnm))
{
// 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.
}
}
- handleRestart(cr, bTryToAppendFiles, NFILE, fnm, &bDoAppendFiles, &bStartFromCpt);
+ handleRestart(cr, bTryToAppendFiles, nfile, fnm, &bDoAppendFiles, &bStartFromCpt);
- Flags = opt2bSet("-rerun", NFILE, fnm) ? MD_RERUN : 0;
+ Flags = opt2bSet("-rerun", nfile, fnm) ? MD_RERUN : 0;
Flags = Flags | (bDDBondCheck ? MD_DDBONDCHECK : 0);
Flags = Flags | (bDDBondComm ? MD_DDBONDCOMM : 0);
Flags = Flags | (bTunePME ? MD_TUNEPME : 0);
there instead. */
if (MASTER(cr) && !bDoAppendFiles)
{
- gmx_log_open(ftp2fn(efLOG, NFILE, fnm), cr,
+ gmx_log_open(ftp2fn(efLOG, nfile, fnm), cr,
Flags & MD_APPENDFILES, &fplog);
}
else
{
- fplog = NULL;
+ fplog = nullptr;
}
ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
- rc = gmx::mdrunner(&hw_opt, fplog, cr, NFILE, fnm, oenv, bVerbose,
- nstglobalcomm, ddxyz, dd_rank_order, npme, rdd, rconstr,
- dddlb_opt[0], dlb_scale, ddcsx, ddcsy, ddcsz,
- nbpu_opt[0], nstlist,
- nsteps, nstepout, resetstep,
- nmultisim, repl_ex_nst, repl_ex_nex, repl_ex_seed,
- pforce, cpt_period, max_hours, imdport, Flags);
+ dddlb_opt = dddlb_opt_choices[0];
+ nbpu_opt = nbpu_opt_choices[0];
+ rc = mdrunner();
/* Log file has to be closed in mdrunner if we are appending to it
(fplog not set here) */
return rc;
}
+
+} // namespace