#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/multipletimestepping.h"
#include "gromacs/mdtypes/nblist.h"
+#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/nbnxm/nbnxm.h"
#include "gromacs/pbcutil/ishift.h"
#include "gromacs/pbcutil/pbc.h"
void init_forcerec(FILE* fplog,
const gmx::MDLogger& mdlog,
+ const gmx::SimulationWorkload& simulationWork,
t_forcerec* forcerec,
const t_inputrec& inputrec,
const gmx_mtop_t& mtop,
/* 1-4 interaction electrostatics */
forcerec->fudgeQQ = mtop.ffparams.fudgeQQ;
- // Multiple time stepping
- forcerec->useMts = inputrec.useMts;
-
- if (forcerec->useMts)
+ if (simulationWork.useMts)
{
GMX_ASSERT(gmx::checkMtsRequirements(inputrec).empty(),
"All MTS requirements should be met here");
|| inputrec.bRot || inputrec.bIMD;
const bool haveDirectVirialContributionsSlow =
EEL_FULL(interactionConst->eeltype) || EVDW_PME(interactionConst->vdwtype);
- for (int i = 0; i < (forcerec->useMts ? 2 : 1); i++)
+ for (int i = 0; i < (simulationWork.useMts ? 2 : 1); i++)
{
bool haveDirectVirialContributions =
- (((!forcerec->useMts || i == 0) && haveDirectVirialContributionsFast)
- || ((!forcerec->useMts || i == 1) && haveDirectVirialContributionsSlow));
+ (((!simulationWork.useMts || i == 0) && haveDirectVirialContributionsFast)
+ || ((!simulationWork.useMts || i == 1) && haveDirectVirialContributionsSlow));
forcerec->forceHelperBuffers.emplace_back(haveDirectVirialContributions);
}
}
/* Initialize the thread working data for bonded interactions */
- if (forcerec->useMts)
+ if (simulationWork.useMts)
{
// Add one ListedForces object for each MTS level
bool isFirstLevel = true;
{
class MDLogger;
class PhysicalNodeCommunicator;
+class SimulationWorkload;
} // namespace gmx
/*! \brief Create nonbonded parameter lists
* \param[in] fplog File for printing
* \param[in] mdlog File for printing
* \param[out] forcerec The forcerec
+ * \param[in] simulationWork Simulation workload flags
* \param[in] inputrec Inputrec structure
* \param[in] mtop Molecular topology
* \param[in] commrec Communication structures
*/
void init_forcerec(FILE* fplog,
const gmx::MDLogger& mdlog,
+ const gmx::SimulationWorkload& simulationWork,
t_forcerec* forcerec,
const t_inputrec& inputrec,
const gmx_mtop_t& mtop,
flags.useGpuXHalo = simulationWork.useGpuHaloExchange;
flags.useGpuFHalo = simulationWork.useGpuHaloExchange && flags.useGpuFBufferOps;
flags.haveGpuPmeOnThisRank = simulationWork.useGpuPme && rankHasPmeDuty && flags.computeSlowForces;
+ flags.combineMtsForcesBeforeHaloExchange =
+ (flags.computeForces && simulationWork.useMts && flags.computeSlowForces
+ && flags.useOnlyMtsCombinedForceBuffer
+ && !(flags.computeVirial || simulationWork.useGpuNonbonded || flags.haveGpuPmeOnThisRank));
return flags;
}
*/
static int getLocalAtomCount(const gmx_domdec_t* dd, const t_mdatoms& mdatoms, bool havePPDomainDecomposition)
{
- GMX_ASSERT(!(havePPDomainDecomposition && (dd == nullptr)), "Can't have PP decomposition with dd uninitialized!");
+ GMX_ASSERT(!(havePPDomainDecomposition && (dd == nullptr)),
+ "Can't have PP decomposition with dd uninitialized!");
return havePPDomainDecomposition ? dd_numAtomsZones(*dd) : mdatoms.homenr;
}
// Force output for MTS combined forces, only set at level1 MTS steps
std::optional<ForceOutputs> forceOutMts =
- (fr->useMts && stepWork.computeSlowForces)
+ (simulationWork.useMts && stepWork.computeSlowForces)
? std::optional(setupForceOutputs(&fr->forceHelperBuffers[1],
forceView->forceMtsCombinedWithPadding(),
domainWork,
: std::nullopt;
ForceOutputs* forceOutMtsLevel1 =
- fr->useMts ? (stepWork.computeSlowForces ? &forceOutMts.value() : nullptr) : &forceOutMtsLevel0;
+ simulationWork.useMts ? (stepWork.computeSlowForces ? &forceOutMts.value() : nullptr)
+ : &forceOutMtsLevel0;
const bool nonbondedAtMtsLevel1 = runScheduleWork->simulationWork.computeNonbondedAtMtsLevel1;
set_pbc_dd(&pbc, fr->pbcType, DOMAINDECOMP(cr) ? cr->dd->numCells : nullptr, TRUE, box);
}
- for (int mtsIndex = 0; mtsIndex < (fr->useMts && stepWork.computeSlowForces ? 2 : 1); mtsIndex++)
+ for (int mtsIndex = 0; mtsIndex < (simulationWork.useMts && stepWork.computeSlowForces ? 2 : 1);
+ mtsIndex++)
{
ListedForces& listedForces = fr->listedForces[mtsIndex];
ForceOutputs& forceOut = (mtsIndex == 0 ? forceOutMtsLevel0 : *forceOutMtsLevel1);
/* Combining the forces for multiple time stepping before the halo exchange, when possible,
* avoids an extra halo exchange (when DD is used) and post-processing step.
*/
- const bool combineMtsForcesBeforeHaloExchange =
- (stepWork.computeForces && fr->useMts && stepWork.computeSlowForces && stepWork.useOnlyMtsCombinedForceBuffer
- && !(stepWork.computeVirial || simulationWork.useGpuNonbonded || stepWork.haveGpuPmeOnThisRank));
- if (combineMtsForcesBeforeHaloExchange)
+ if (stepWork.combineMtsForcesBeforeHaloExchange)
{
combineMtsForces(getLocalAtomCount(cr->dd, *mdatoms, havePPDomainDecomposition(cr)),
force.unpaddedArrayRef(),
// Without MTS or with MTS at slow steps with uncombined forces we need to
// communicate the fast forces
- if (!fr->useMts || !combineMtsForcesBeforeHaloExchange)
+ if (!simulationWork.useMts || !stepWork.combineMtsForcesBeforeHaloExchange)
{
dd_move_f(cr->dd, &forceOutMtsLevel0.forceWithShiftForces(), wcycle);
}
// With MTS we need to communicate the slow or combined (in forceOutMtsLevel1) forces
- if (fr->useMts && stepWork.computeSlowForces)
+ if (simulationWork.useMts && stepWork.computeSlowForces)
{
dd_move_f(cr->dd, &forceOutMtsLevel1->forceWithShiftForces(), wcycle);
}
dd_force_flop_stop(cr->dd, nrnb);
}
- const bool haveCombinedMtsForces = (stepWork.computeForces && fr->useMts && stepWork.computeSlowForces
- && combineMtsForcesBeforeHaloExchange);
+ const bool haveCombinedMtsForces = (stepWork.computeForces && simulationWork.useMts && stepWork.computeSlowForces
+ && stepWork.combineMtsForcesBeforeHaloExchange);
if (stepWork.computeForces)
{
postProcessForceWithShiftForces(
nrnb, wcycle, box, x.unpaddedArrayRef(), &forceOutMtsLevel0, vir_force, *mdatoms, *fr, vsite, stepWork);
- if (fr->useMts && stepWork.computeSlowForces && !haveCombinedMtsForces)
+ if (simulationWork.useMts && stepWork.computeSlowForces && !haveCombinedMtsForces)
{
postProcessForceWithShiftForces(
nrnb, wcycle, box, x.unpaddedArrayRef(), forceOutMtsLevel1, vir_force, *mdatoms, *fr, vsite, stepWork);
postProcessForces(
cr, step, nrnb, wcycle, box, x.unpaddedArrayRef(), &forceOutCombined, vir_force, mdatoms, fr, vsite, stepWork);
- if (fr->useMts && stepWork.computeSlowForces && !haveCombinedMtsForces)
+ if (simulationWork.useMts && stepWork.computeSlowForces && !haveCombinedMtsForces)
{
postProcessForces(
cr, step, nrnb, wcycle, box, x.unpaddedArrayRef(), forceOutMtsLevel1, vir_force, mdatoms, fr, vsite, stepWork);
gmx_localtop_t top(top_global.ffparams);
- ForceBuffers f(fr->useMts,
+ ForceBuffers f(simulationWork.useMts,
((useGpuForNonbonded && useGpuForBufferOps) || useGpuForUpdate)
? PinningPolicy::PinnedIfSupported
: PinningPolicy::CannotBePinned);
force_flags = (GMX_FORCE_STATECHANGED | ((inputrecDynamicBox(ir)) ? GMX_FORCE_DYNAMICBOX : 0)
| GMX_FORCE_ALLFORCES | (bCalcVir ? GMX_FORCE_VIRIAL : 0)
| (bCalcEner ? GMX_FORCE_ENERGY : 0) | (bDoFEP ? GMX_FORCE_DHDL : 0));
- if (fr->useMts && !do_per_step(step, ir->nstfout))
+ if (simulationWork.useMts && !do_per_step(step, ir->nstfout))
{
// TODO: merge this with stepWork.useOnlyMtsCombinedForceBuffer
force_flags |= GMX_FORCE_DO_NOT_NEED_NORMAL_FORCE;
* Using that acceleration would result in a virial with the slow
* force contribution would be a factor mtsFactor too large.
*/
- if (fr->useMts && bCalcVir && constr != nullptr)
+ if (simulationWork.useMts && bCalcVir && constr != nullptr)
{
upd.update_for_constraint_virial(*ir,
md->homenr,
}
ArrayRefWithPadding<const RVec> forceCombined =
- (fr->useMts && step % ir->mtsLevels[1].stepFactor == 0)
+ (simulationWork.useMts && step % ir->mtsLevels[1].stepFactor == 0)
? f.view().forceMtsCombinedWithPadding()
: f.view().forceWithPadding();
upd.update_coords(*ir,
state,
upd.xp()->arrayRefWithPadding(),
&dvdl_constr,
- bCalcVir && !fr->useMts,
+ bCalcVir && !simulationWork.useMts,
shake_vir);
upd.update_sd_second_half(*ir,
fr->forceProviders = mdModules_->initForceProviders();
init_forcerec(fplog,
mdlog,
+ runScheduleWork.simulationWork,
fr.get(),
*inputrec,
mtop,
real userreal3 = 0;
real userreal4 = 0;
- /* Tells whether we use multiple time stepping, computing some forces less frequently */
- bool useMts = false;
-
/* Data for special listed force calculations */
std::unique_ptr<t_fcdata> fcdata;
bool useGpuFHalo = false;
//! Whether GPU PME work is compute this step (can be false also on fast steps with MTS)
bool haveGpuPmeOnThisRank = false;
+ //! Whether to combine the forces for multiple time stepping before the halo exchange
+ bool combineMtsForcesBeforeHaloExchange = false;
};
/*! \libinternal
bool useGpuDirectCommunication = false;
//! If there is an Ewald surface (dipole) term to compute
bool haveEwaldSurfaceContribution = false;
+ //! Whether to use multiple time stepping
+ bool useMts = false;
};
class MdrunScheduleWorkload
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020,2021, 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.
simulationWorkload.useGpuDirectCommunication =
devFlags.enableGpuHaloExchange || devFlags.enableGpuPmePPComm;
simulationWorkload.haveEwaldSurfaceContribution = haveEwaldSurfaceContribution(inputrec);
+ simulationWorkload.useMts = inputrec.useMts;
return simulationWorkload;
}