From 6fc7218725f35789a8a3f309bd22ee7b539b3c9b Mon Sep 17 00:00:00 2001 From: Berk Hess Date: Wed, 2 Sep 2020 15:27:23 +0000 Subject: [PATCH] Enable splitting of listed interaction calculation This replaces the ListedForces unique_ptr in t_forcerec by a vector of unique_ptr and adds a selection mechanism for bonded interactions. Also moved the t_fcdata storage out of ListedForces into t_forcerec because we need only one instance. --- src/gromacs/domdec/mdsetup.cpp | 5 +- src/gromacs/listed_forces/listed_forces.cpp | 102 ++++++++++++++---- src/gromacs/listed_forces/listed_forces.h | 62 ++++++++--- src/gromacs/mdlib/force.cpp | 10 +- src/gromacs/mdlib/forcerec.cpp | 13 ++- src/gromacs/mdlib/sim_util.cpp | 18 +++- src/gromacs/mdrun/md.cpp | 4 +- src/gromacs/mdrun/mimic.cpp | 3 +- src/gromacs/mdrun/minimize.cpp | 18 ++-- src/gromacs/mdrun/rerun.cpp | 3 +- src/gromacs/mdrun/runner.cpp | 4 +- src/gromacs/mdtypes/forcerec.h | 10 +- src/gromacs/mdtypes/simulation_workload.h | 2 - .../modularsimulator/modularsimulator.cpp | 7 +- .../modularsimulator/simulatoralgorithm.cpp | 2 +- src/gromacs/topology/ifunc.cpp | 31 ++++-- src/gromacs/topology/ifunc.h | 6 +- 17 files changed, 210 insertions(+), 90 deletions(-) diff --git a/src/gromacs/domdec/mdsetup.cpp b/src/gromacs/domdec/mdsetup.cpp index 6a8559217f..90f28d18a7 100644 --- a/src/gromacs/domdec/mdsetup.cpp +++ b/src/gromacs/domdec/mdsetup.cpp @@ -127,7 +127,10 @@ void mdAlgorithmsSetupAtomData(const t_commrec* cr, make_local_shells(cr, mdatoms, shellfc); } - fr->listedForces->setup(top->idef, fr->natoms_force, fr->gpuBonded != nullptr); + for (auto& listedForces : fr->listedForces) + { + listedForces.setup(top->idef, fr->natoms_force, fr->gpuBonded != nullptr); + } if (EEL_PME(fr->ic->eeltype) && (cr->duty & DUTY_PME)) { diff --git a/src/gromacs/listed_forces/listed_forces.cpp b/src/gromacs/listed_forces/listed_forces.cpp index c35a06a895..9548ba4433 100644 --- a/src/gromacs/listed_forces/listed_forces.cpp +++ b/src/gromacs/listed_forces/listed_forces.cpp @@ -81,17 +81,78 @@ #include "manage_threading.h" #include "utilities.h" -ListedForces::ListedForces(const int numEnergyGroups, const int numThreads, FILE* fplog) : +ListedForces::ListedForces(const gmx_ffparams_t& ffparams, + const int numEnergyGroups, + const int numThreads, + const InteractionSelection interactionSelection, + FILE* fplog) : + idefSelection_(ffparams), threading_(std::make_unique(numThreads, numEnergyGroups, fplog)), - fcdata_(std::make_unique()) + interactionSelection_(interactionSelection) { } +ListedForces::ListedForces(ListedForces&& o) noexcept = default; + ListedForces::~ListedForces() = default; -void ListedForces::setup(const InteractionDefinitions& idef, const int numAtomsForce, const bool useGpu) +//! Copies the selection interactions from \p idefSrc to \p idef +static void selectInteractions(InteractionDefinitions* idef, + const InteractionDefinitions& idefSrc, + const ListedForces::InteractionSelection interactionSelection) { - idef_ = &idef; + const bool selectPairs = + interactionSelection.test(static_cast(ListedForces::InteractionGroup::Pairs)); + const bool selectDihedrals = + interactionSelection.test(static_cast(ListedForces::InteractionGroup::Dihedrals)); + const bool selectRest = + interactionSelection.test(static_cast(ListedForces::InteractionGroup::Rest)); + + for (int ftype = 0; ftype < F_NRE; ftype++) + { + const t_interaction_function& ifunc = interaction_function[ftype]; + if (ifunc.flags & IF_BOND) + { + bool assign = false; + if (ifunc.flags & IF_PAIR) + { + assign = selectPairs; + } + else if (ifunc.flags & IF_DIHEDRAL) + { + assign = selectDihedrals; + } + else + { + assign = selectRest; + } + if (assign) + { + idef->il[ftype] = idefSrc.il[ftype]; + } + else + { + idef->il[ftype].clear(); + } + } + } +} + +void ListedForces::setup(const InteractionDefinitions& domainIdef, const int numAtomsForce, const bool useGpu) +{ + if (interactionSelection_.all()) + { + // Avoid the overhead of copying all interaction lists by simply setting the reference to the domain idef + idef_ = &domainIdef; + } + else + { + idef_ = &idefSelection_; + + selectInteractions(&idefSelection_, domainIdef, interactionSelection_); + + idefSelection_.ilsort = domainIdef.ilsort; + } setup_bonded_threading(threading_.get(), numAtomsForce, useGpu, *idef_); @@ -478,13 +539,12 @@ static void calcBondedForces(const InteractionDefinitions& idef, } } -bool ListedForces::haveRestraints() const +bool ListedForces::haveRestraints(const t_fcdata& fcdata) const { - GMX_ASSERT(fcdata_, "Need valid fcdata"); - GMX_ASSERT(fcdata_->orires && fcdata_->disres, "NMR restraints objects should be set up"); + GMX_ASSERT(fcdata.orires && fcdata.disres, "NMR restraints objects should be set up"); - return (!idef_->il[F_POSRES].empty() || !idef_->il[F_FBPOSRES].empty() - || fcdata_->orires->nr > 0 || fcdata_->disres->nres > 0); + return (!idef_->il[F_POSRES].empty() || !idef_->il[F_FBPOSRES].empty() || fcdata.orires->nr > 0 + || fcdata.disres->nres > 0); } bool ListedForces::haveCpuBondeds() const @@ -492,9 +552,9 @@ bool ListedForces::haveCpuBondeds() const return threading_->haveBondeds; } -bool ListedForces::haveCpuListedForces() const +bool ListedForces::haveCpuListedForces(const t_fcdata& fcdata) const { - return haveCpuBondeds() || haveRestraints(); + return haveCpuBondeds() || haveRestraints(fcdata); } namespace @@ -625,6 +685,7 @@ void ListedForces::calculate(struct gmx_wallcycle* wcycle, const gmx_multisim_t* ms, const rvec x[], gmx::ArrayRef xWholeMolecules, + t_fcdata* fcdata, history_t* hist, gmx::ForceOutputs* forceOutputs, const t_forcerec* fr, @@ -636,16 +697,15 @@ void ListedForces::calculate(struct gmx_wallcycle* wcycle, int* global_atom_index, const gmx::StepWorkload& stepWork) { - if (!stepWork.computeListedForces) + if (interactionSelection_.none() || !stepWork.computeListedForces) { return; } - const InteractionDefinitions& idef = *idef_; - t_fcdata& fcdata = *fcdata_; + const InteractionDefinitions& idef = *idef_; t_pbc pbc_full; /* Full PBC is needed for position restraints */ - if (haveRestraints()) + if (haveRestraints(*fcdata)) { if (!idef.il[F_POSRES].empty() || !idef.il[F_FBPOSRES].empty()) { @@ -671,24 +731,24 @@ void ListedForces::calculate(struct gmx_wallcycle* wcycle, } /* Do pre force calculation stuff which might require communication */ - if (fcdata.orires->nr > 0) + if (fcdata->orires->nr > 0) { GMX_ASSERT(!xWholeMolecules.empty(), "Need whole molecules for orienation restraints"); enerd->term[F_ORIRESDEV] = calc_orires_dev( ms, idef.il[F_ORIRES].size(), idef.il[F_ORIRES].iatoms.data(), idef.iparams.data(), - md, xWholeMolecules, x, fr->bMolPBC ? pbc : nullptr, fcdata.orires, hist); + md, xWholeMolecules, x, fr->bMolPBC ? pbc : nullptr, fcdata->orires, hist); } - if (fcdata.disres->nres > 0) + if (fcdata->disres->nres > 0) { calc_disres_R_6(cr, ms, idef.il[F_DISRES].size(), idef.il[F_DISRES].iatoms.data(), x, - fr->bMolPBC ? pbc : nullptr, fcdata.disres, hist); + fr->bMolPBC ? pbc : nullptr, fcdata->disres, hist); } wallcycle_sub_stop(wcycle, ewcsRESTRAINTS); } calc_listed(wcycle, idef, threading_.get(), x, forceOutputs, fr, pbc, enerd, nrnb, lambda, md, - &fcdata, global_atom_index, stepWork); + fcdata, global_atom_index, stepWork); /* Check if we have to determine energy differences * at foreign lambda's. @@ -718,7 +778,7 @@ void ListedForces::calculate(struct gmx_wallcycle* wcycle, } calc_listed_lambda(idef, threading_.get(), x, fr, pbc, forceBufferLambda_, shiftForceBufferLambda_, &(enerd->foreign_grpp), enerd->foreign_term, - dvdl, nrnb, lam_i, md, &fcdata, global_atom_index); + dvdl, nrnb, lam_i, md, fcdata, global_atom_index); sum_epot(enerd->foreign_grpp, enerd->foreign_term); const double dvdlSum = std::accumulate(std::begin(dvdl), std::end(dvdl), 0.); std::fill(std::begin(dvdl), std::end(dvdl), 0.0); diff --git a/src/gromacs/listed_forces/listed_forces.h b/src/gromacs/listed_forces/listed_forces.h index d821973fc3..51df97c71a 100644 --- a/src/gromacs/listed_forces/listed_forces.h +++ b/src/gromacs/listed_forces/listed_forces.h @@ -71,7 +71,10 @@ #include +#include + #include "gromacs/math/vectypes.h" +#include "gromacs/topology/idef.h" #include "gromacs/topology/ifunc.h" #include "gromacs/utility/arrayref.h" #include "gromacs/utility/basedefinitions.h" @@ -84,7 +87,6 @@ struct gmx_grppairener_t; struct gmx_localtop_t; struct gmx_multisim_t; class history_t; -class InteractionDefinitions; struct t_commrec; struct t_fcdata; struct t_forcerec; @@ -120,28 +122,59 @@ BondedFunction bondedFunction(int ftype); /*! \libinternal * \brief Class for calculating listed interactions, uses OpenMP parallelization + * + * Listed interactions can be divided over multiple instances of ListedForces + * using the selection flags passed to the constructor. */ class ListedForces { public: + //! Enum for selecting groups of listed interaction types + enum class InteractionGroup : int + { + Pairs, //!< Pair interactions + Dihedrals, //!< Dihedrals, including cmap + Rest, //!< All listed interactions that are not any of the above + Count //!< The number of items above + }; + + //! Type for specifying selections of groups of interaction types + using InteractionSelection = std::bitset(InteractionGroup::Count)>; + + //! Returns a selection with all listed interaction types selected + static InteractionSelection interactionSelectionAll() + { + InteractionSelection is; + return is.flip(); + } + /*! \brief Constructor * + * \param[in] ffparams The force field parameters * \param[in] numEnergyGroups The number of energy groups, used for storage of pair energies * \param[in] numThreads The number of threads used for computed listed interactions + * \param[in] interactionSelection Select of interaction groups through bits set * \param[in] fplog Log file for printing env.var. override, can be nullptr */ - ListedForces(int numEnergyGroups, int numThreads, FILE* fplog); + ListedForces(const gmx_ffparams_t& ffparams, + int numEnergyGroups, + int numThreads, + InteractionSelection interactionSelection, + FILE* fplog); + + //! Move constructor, default, but in the source file to hide implementation classes + ListedForces(ListedForces&& o) noexcept; //! Destructor which is actually default but in the source file to hide implementation classes ~ListedForces(); /*! \brief Copy the listed interactions from \p idef and set up the thread parallelization * - * \param[in] idef The idef with all listed interactions to be computed on this rank + * \param[in] domainIdef Interaction definitions for all listed interactions to be computed on this domain/rank * \param[in] numAtomsForce Force are, potentially, computed for atoms 0 to \p numAtomsForce * \param[in] useGpu Whether a GPU is used to compute (part of) the listed interactions */ - void setup(const InteractionDefinitions& idef, int numAtomsForce, bool useGpu); + void setup(const InteractionDefinitions& domainIdef, int numAtomsForce, bool useGpu); /*! \brief Do all aspects of energy and force calculations for mdrun * on the set of listed interactions @@ -156,6 +189,7 @@ public: const gmx_multisim_t* ms, const rvec x[], gmx::ArrayRef xWholeMolecules, + t_fcdata* fcdata, history_t* hist, gmx::ForceOutputs* forceOutputs, const t_forcerec* fr, @@ -175,30 +209,26 @@ public: * NOTE: the current implementation returns true if there are position restraints * or any bonded interactions computed on the CPU. */ - bool haveCpuListedForces() const; + bool haveCpuListedForces(const t_fcdata& fcdata) const; //! Returns true if there are position, distance or orientation restraints - bool haveRestraints() const; - - //! Returns a reference to the force calculation data - const t_fcdata& fcdata() const { return *fcdata_; } - - //! Returns a reference to the force calculation data - t_fcdata& fcdata() { return *fcdata_; } + bool haveRestraints(const t_fcdata& fcdata) const; private: - //! The interaction definitions + //! Pointer to the interaction definitions InteractionDefinitions const* idef_ = nullptr; + //! Interaction defintions used for storing selections + InteractionDefinitions idefSelection_; //! Thread parallelization setup, unique_ptr to avoid declaring bonded_threading_t std::unique_ptr threading_; - //! Data for bonded tables and NMR restraining, needs to be refactored - std::unique_ptr fcdata_; + //! Tells which interactions to select for computation + const InteractionSelection interactionSelection_; //! Force buffer for free-energy forces std::vector forceBufferLambda_; //! Shift force buffer for free-energy forces std::vector shiftForceBufferLambda_; - GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(ListedForces); + GMX_DISALLOW_COPY_AND_ASSIGN(ListedForces); }; #endif diff --git a/src/gromacs/mdlib/force.cpp b/src/gromacs/mdlib/force.cpp index 6805a79454..1aa00226b6 100644 --- a/src/gromacs/mdlib/force.cpp +++ b/src/gromacs/mdlib/force.cpp @@ -138,9 +138,9 @@ void do_force_lowlevel(t_forcerec* fr, t_pbc pbc; /* Check whether we need to take into account PBC in listed interactions. */ - ListedForces& listedForces = *fr->listedForces; - const auto needPbcForListedForces = - fr->bMolPBC && stepWork.computeListedForces && listedForces.haveCpuListedForces(); + ListedForces& listedForces = fr->listedForces[0]; + const auto needPbcForListedForces = fr->bMolPBC && stepWork.computeListedForces + && listedForces.haveCpuListedForces(*fr->fcdata); if (needPbcForListedForces) { /* Since all atoms are in the rectangular or triclinic unit-cell, @@ -149,8 +149,8 @@ void do_force_lowlevel(t_forcerec* fr, set_pbc_dd(&pbc, fr->pbcType, DOMAINDECOMP(cr) ? cr->dd->numCells : nullptr, TRUE, box); } - listedForces.calculate(wcycle, box, ir->fepvals, cr, ms, x, xWholeMolecules, hist, - forceOutputs, fr, &pbc, enerd, nrnb, lambda, md, + listedForces.calculate(wcycle, box, ir->fepvals, cr, ms, x, xWholeMolecules, fr->fcdata.get(), + hist, forceOutputs, fr, &pbc, enerd, nrnb, lambda, md, DOMAINDECOMP(cr) ? cr->dd->globalAtomIndices.data() : nullptr, stepWork); } diff --git a/src/gromacs/mdlib/forcerec.cpp b/src/gromacs/mdlib/forcerec.cpp index 7e7ab9702d..54446643e3 100644 --- a/src/gromacs/mdlib/forcerec.cpp +++ b/src/gromacs/mdlib/forcerec.cpp @@ -1259,18 +1259,16 @@ void init_forcerec(FILE* fp, make_wall_tables(fp, ir, tabfn, &mtop->groups, fr); } - /* Initialize the thread working data for bonded interactions */ - fr->listedForces = std::make_unique( - mtop->groups.groups[SimulationAtomGroupType::EnergyOutput].size(), - gmx_omp_nthreads_get(emntBonded), fp); + fr->fcdata = std::make_unique(); if (!tabbfnm.empty()) { - t_fcdata& fcdata = fr->listedForces->fcdata(); + t_fcdata& fcdata = *fr->fcdata; // Need to catch std::bad_alloc // TODO Don't need to catch this here, when merging with master branch try { + //! \todo move these tables into a separate struct and store reference in ListedForces fcdata.bondtab = make_bonded_tables(fp, F_TABBONDS, F_TABBONDSNC, mtop, tabbfnm, "b"); fcdata.angletab = make_bonded_tables(fp, F_TABANGLES, -1, mtop, tabbfnm, "a"); fcdata.dihtab = make_bonded_tables(fp, F_TABDIHS, -1, mtop, tabbfnm, "d"); @@ -1287,6 +1285,11 @@ void init_forcerec(FILE* fp, } } + /* Initialize the thread working data for bonded interactions */ + fr->listedForces.emplace_back( + mtop->ffparams, mtop->groups.groups[SimulationAtomGroupType::EnergyOutput].size(), + gmx_omp_nthreads_get(emntBonded), ListedForces::interactionSelectionAll(), fp); + // QM/MM initialization if requested if (ir->bQMMM) { diff --git a/src/gromacs/mdlib/sim_util.cpp b/src/gromacs/mdlib/sim_util.cpp index dda01b711f..7b0c7c7e9c 100644 --- a/src/gromacs/mdlib/sim_util.cpp +++ b/src/gromacs/mdlib/sim_util.cpp @@ -851,10 +851,20 @@ static DomainLifetimeWorkload setupDomainLifetimeWorkload(const t_inputrec& // Note that haveSpecialForces is constant over the whole run domainWork.haveSpecialForces = haveSpecialForces(inputrec, *fr.forceProviders, pull_work, stepWork.computeForces, ed); - domainWork.haveCpuBondedWork = fr.listedForces->haveCpuBondeds(); - domainWork.haveGpuBondedWork = ((fr.gpuBonded != nullptr) && fr.gpuBonded->haveInteractions()); - domainWork.haveRestraintsWork = fr.listedForces->haveRestraints(); - domainWork.haveCpuListedForceWork = fr.listedForces->haveCpuListedForces(); + domainWork.haveCpuListedForceWork = false; + domainWork.haveCpuBondedWork = false; + for (const auto& listedForces : fr.listedForces) + { + if (listedForces.haveCpuListedForces(*fr.fcdata)) + { + domainWork.haveCpuListedForceWork = true; + } + if (listedForces.haveCpuBondeds()) + { + domainWork.haveCpuBondedWork = true; + } + } + domainWork.haveGpuBondedWork = ((fr.gpuBonded != nullptr) && fr.gpuBonded->haveInteractions()); // Note that haveFreeEnergyWork is constant over the whole run domainWork.haveFreeEnergyWork = (fr.efep != efepNO && mdatoms.nPerturbed != 0); // We assume we have local force work if there are CPU diff --git a/src/gromacs/mdrun/md.cpp b/src/gromacs/mdrun/md.cpp index ac08b56afc..e924f43e4d 100644 --- a/src/gromacs/mdrun/md.cpp +++ b/src/gromacs/mdrun/md.cpp @@ -260,7 +260,7 @@ void gmx::LegacySimulator::do_md() const bool doSimulatedAnnealing = initSimulatedAnnealing(ir, &upd); const bool useReplicaExchange = (replExParams.exchangeInterval > 0); - const t_fcdata& fcdata = fr->listedForces->fcdata(); + const t_fcdata& fcdata = *fr->fcdata; bool simulationsShareState = false; int nstSignalComm = nstglobalcomm; @@ -1530,7 +1530,7 @@ void gmx::LegacySimulator::do_md() { energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, do_dr, do_or, do_log ? fplog : nullptr, step, t, - &fr->listedForces->fcdata(), awh.get()); + fr->fcdata.get(), awh.get()); } if (ir->bPull) diff --git a/src/gromacs/mdrun/mimic.cpp b/src/gromacs/mdrun/mimic.cpp index 29d846b851..188522b43f 100644 --- a/src/gromacs/mdrun/mimic.cpp +++ b/src/gromacs/mdrun/mimic.cpp @@ -527,8 +527,7 @@ void gmx::LegacySimulator::do_mimic() EnergyOutput::printAnnealingTemperatures(do_log ? fplog : nullptr, groups, &(ir->opts)); energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, do_dr, do_or, - do_log ? fplog : nullptr, step, t, - &fr->listedForces->fcdata(), awh); + do_log ? fplog : nullptr, step, t, fr->fcdata.get(), awh); if (do_per_step(step, ir->nstlog)) { diff --git a/src/gromacs/mdrun/minimize.cpp b/src/gromacs/mdrun/minimize.cpp index 7e6b030e3c..e4f94ab0ea 100644 --- a/src/gromacs/mdrun/minimize.cpp +++ b/src/gromacs/mdrun/minimize.cpp @@ -1128,7 +1128,7 @@ void LegacySimulator::do_cg() EnergyOutput::printHeader(fplog, step, step); energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), TRUE, FALSE, FALSE, fplog, step, - step, &fr->listedForces->fcdata(), nullptr); + step, fr->fcdata.get(), nullptr); } /* Estimate/guess the initial stepsize */ @@ -1546,7 +1546,7 @@ void LegacySimulator::do_cg() } energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, FALSE, FALSE, do_log ? fplog : nullptr, step, step, - &fr->listedForces->fcdata(), nullptr); + fr->fcdata.get(), nullptr); } /* Send energies and positions to the IMD client if bIMD is TRUE. */ @@ -1590,7 +1590,7 @@ void LegacySimulator::do_cg() /* Write final energy file entries */ energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), !do_ene, FALSE, FALSE, !do_log ? fplog : nullptr, step, step, - &fr->listedForces->fcdata(), nullptr); + fr->fcdata.get(), nullptr); } } @@ -1778,7 +1778,7 @@ void LegacySimulator::do_lbfgs() EnergyOutput::printHeader(fplog, step, step); energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), TRUE, FALSE, FALSE, fplog, step, - step, &fr->listedForces->fcdata(), nullptr); + step, fr->fcdata.get(), nullptr); } /* Set the initial step. @@ -2271,7 +2271,7 @@ void LegacySimulator::do_lbfgs() } energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, FALSE, FALSE, do_log ? fplog : nullptr, step, step, - &fr->listedForces->fcdata(), nullptr); + fr->fcdata.get(), nullptr); } /* Send x and E to IMD client, if bIMD is TRUE. */ @@ -2313,8 +2313,8 @@ void LegacySimulator::do_lbfgs() if (!do_ene || !do_log) /* Write final energy file entries */ { energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), !do_ene, FALSE, FALSE, - !do_log ? fplog : nullptr, step, step, - &fr->listedForces->fcdata(), nullptr); + !do_log ? fplog : nullptr, step, step, fr->fcdata.get(), + nullptr); } /* Print some stuff... */ @@ -2477,8 +2477,8 @@ void LegacySimulator::do_steep() const bool do_dr = do_per_step(steps_accepted, inputrec->nstdisreout); const bool do_or = do_per_step(steps_accepted, inputrec->nstorireout); - energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), TRUE, do_dr, do_or, fplog, - count, count, &fr->listedForces->fcdata(), nullptr); + energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), TRUE, do_dr, do_or, + fplog, count, count, fr->fcdata.get(), nullptr); fflush(fplog); } } diff --git a/src/gromacs/mdrun/rerun.cpp b/src/gromacs/mdrun/rerun.cpp index 8f85eb8227..12dcb98b7b 100644 --- a/src/gromacs/mdrun/rerun.cpp +++ b/src/gromacs/mdrun/rerun.cpp @@ -607,8 +607,7 @@ void gmx::LegacySimulator::do_rerun() EnergyOutput::printAnnealingTemperatures(do_log ? fplog : nullptr, groups, &(ir->opts)); energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, do_dr, do_or, - do_log ? fplog : nullptr, step, t, - &fr->listedForces->fcdata(), awh); + do_log ? fplog : nullptr, step, t, fr->fcdata.get(), awh); if (do_per_step(step, ir->nstlog)) { diff --git a/src/gromacs/mdrun/runner.cpp b/src/gromacs/mdrun/runner.cpp index 1d1676206b..8bc7dc71f6 100644 --- a/src/gromacs/mdrun/runner.cpp +++ b/src/gromacs/mdrun/runner.cpp @@ -1388,8 +1388,8 @@ int Mdrunner::mdrunner() opt2fn("-tablep", filenames.size(), filenames.data()), opt2fns("-tableb", filenames.size(), filenames.data()), pforce); // Dirty hack, for fixing disres and orires should be made mdmodules - fr->listedForces->fcdata().disres = disresdata; - fr->listedForces->fcdata().orires = oriresdata; + fr->fcdata->disres = disresdata; + fr->fcdata->orires = oriresdata; // Save a handle to device stream manager to use elsewhere in the code // TODO: Forcerec is not a correct place to store it. diff --git a/src/gromacs/mdtypes/forcerec.h b/src/gromacs/mdtypes/forcerec.h index ea81170069..b48bd0910d 100644 --- a/src/gromacs/mdtypes/forcerec.h +++ b/src/gromacs/mdtypes/forcerec.h @@ -56,6 +56,7 @@ struct bonded_threading_t; class DeviceContext; class DispersionCorrection; class ListedForces; +struct t_fcdata; struct t_forcetable; struct t_QMMMrec; @@ -298,8 +299,13 @@ struct t_forcerec real userreal3 = 0; real userreal4 = 0; - /* The listed forces calculation data */ - std::unique_ptr listedForces; + /* Data for special listed force calculations */ + std::unique_ptr fcdata; + + // The listed forces calculation data, 1 entry or multiple entries with multiple time stepping + std::vector listedForces; + + static constexpr size_t c_listedForcesFast = 0; /* TODO: Replace the pointer by an object once we got rid of C */ gmx::GpuBonded* gpuBonded = nullptr; diff --git a/src/gromacs/mdtypes/simulation_workload.h b/src/gromacs/mdtypes/simulation_workload.h index 5dfe43c333..8f75ba7436 100644 --- a/src/gromacs/mdtypes/simulation_workload.h +++ b/src/gromacs/mdtypes/simulation_workload.h @@ -113,8 +113,6 @@ public: bool haveGpuBondedWork = false; //! Whether the current nstlist step-range has bonded work to run on he CPU. bool haveCpuBondedWork = false; - //! Whether the current nstlist step-range has restraints work to run on he CPU. - bool haveRestraintsWork = false; //! Whether the current nstlist step-range has listed forces work to run on he CPU. // Note: currently this is haveCpuBondedWork | haveRestraintsWork bool haveCpuListedForceWork = false; diff --git a/src/gromacs/modularsimulator/modularsimulator.cpp b/src/gromacs/modularsimulator/modularsimulator.cpp index dbb04d3fb5..5604a8dec2 100644 --- a/src/gromacs/modularsimulator/modularsimulator.cpp +++ b/src/gromacs/modularsimulator/modularsimulator.cpp @@ -358,10 +358,9 @@ ModularSimulator::ModularSimulator(std::unique_ptr legacySi void ModularSimulator::checkInputForDisabledFunctionality() { - isInputCompatible(true, legacySimulatorData_->inputrec, - legacySimulatorData_->mdrunOptions.rerun, *legacySimulatorData_->top_global, - legacySimulatorData_->ms, legacySimulatorData_->replExParams, - &legacySimulatorData_->fr->listedForces->fcdata(), + isInputCompatible(true, legacySimulatorData_->inputrec, legacySimulatorData_->mdrunOptions.rerun, + *legacySimulatorData_->top_global, legacySimulatorData_->ms, + legacySimulatorData_->replExParams, legacySimulatorData_->fr->fcdata.get(), opt2bSet("-ei", legacySimulatorData_->nfile, legacySimulatorData_->fnm), legacySimulatorData_->membed != nullptr); if (legacySimulatorData_->observablesHistory->edsamHistory) diff --git a/src/gromacs/modularsimulator/simulatoralgorithm.cpp b/src/gromacs/modularsimulator/simulatoralgorithm.cpp index 25d5e018c8..44886b83ca 100644 --- a/src/gromacs/modularsimulator/simulatoralgorithm.cpp +++ b/src/gromacs/modularsimulator/simulatoralgorithm.cpp @@ -408,7 +408,7 @@ ModularSimulatorAlgorithmBuilder::ModularSimulatorAlgorithmBuilder( statePropagatorData_.get(), freeEnergyPerturbationData_.get(), legacySimulatorData->top_global, legacySimulatorData->inputrec, legacySimulatorData->mdAtoms, legacySimulatorData->enerd, legacySimulatorData->ekind, legacySimulatorData->constr, - legacySimulatorData->fplog, &legacySimulatorData->fr->listedForces->fcdata(), + legacySimulatorData->fplog, legacySimulatorData->fr->fcdata.get(), legacySimulatorData->mdModulesNotifier, MASTER(legacySimulatorData->cr), legacySimulatorData->observablesHistory, legacySimulatorData->startingBehavior); } diff --git a/src/gromacs/topology/ifunc.cpp b/src/gromacs/topology/ifunc.cpp index e6b4028814..0be9b8bb1e 100644 --- a/src/gromacs/topology/ifunc.cpp +++ b/src/gromacs/topology/ifunc.cpp @@ -45,9 +45,9 @@ str, lstr, (nra), (nrpa), (nrpb), IF_BOND \ } -#define def_bondedz(str, lstr, nra, nrpa, nrpb) \ - { \ - str, lstr, (nra), (nrpa), (nrpb), IF_BOND | IF_LIMZERO \ +#define def_pair(str, lstr, nra, nrpa, nrpb) \ + { \ + str, lstr, (nra), (nrpa), (nrpb), IF_BOND | IF_PAIR | IF_LIMZERO \ } #define def_bondedt(str, lstr, nra, nrpa, nrpb) \ @@ -65,6 +65,16 @@ str, lstr, (nra), (nrpa), (nrpb), IF_BOND | IF_ATYPE \ } +#define def_dihedral(str, lstr, nra, nrpa, nrpb) \ + { \ + str, lstr, (nra), (nrpa), (nrpb), IF_BOND | IF_DIHEDRAL \ + } + +#define def_dihedral_tabulated(str, lstr, nra, nrpa, nrpb) \ + { \ + str, lstr, (nra), (nrpa), (nrpb), IF_BOND | IF_DIHEDRAL | IF_TABULATED \ + } + #define def_bond(str, lstr, nra, nrpa, nrpb) \ { \ str, lstr, (nra), (nrpa), (nrpb), IF_BOND | IF_CHEMBOND | IF_BTYPE \ @@ -118,15 +128,16 @@ const t_interaction_function interaction_function[F_NRE] = { def_bonded("CROSS_BOND_BOND", "Bond-Cross", 3, 3, 0), def_bonded("CROSS_BOND_ANGLE", "BA-Cross", 3, 4, 0), def_angle("UREY_BRADLEY", "U-B", 3, 4, 4), def_angle("QANGLES", "Quartic Angles", 3, 6, 0), def_bondedt("TABANGLES", "Tab. Angles", 3, 2, 2), - def_bonded("PDIHS", "Proper Dih.", 4, 3, 3), def_bonded("RBDIHS", "Ryckaert-Bell.", 4, 6, 6), - def_bonded("RESTRDIHS", "Restricted Dih.", 4, 2, 2), def_bonded("CBTDIHS", "CBT Dih.", 4, 6, 6), - def_bonded("FOURDIHS", "Fourier Dih.", 4, 4, 4), def_bonded("IDIHS", "Improper Dih.", 4, 2, 2), - def_bonded("PIDIHS", "Improper Dih.", 4, 3, 3), def_bondedt("TABDIHS", "Tab. Dih.", 4, 2, 2), - def_bonded("CMAP", "CMAP Dih.", 5, -1, -1), def_nofc("GB12", "GB 1-2 Pol. (unused)"), + def_dihedral("PDIHS", "Proper Dih.", 4, 3, 3), def_dihedral("RBDIHS", "Ryckaert-Bell.", 4, 6, 6), + def_dihedral("RESTRDIHS", "Restricted Dih.", 4, 2, 2), + def_dihedral("CBTDIHS", "CBT Dih.", 4, 6, 6), def_dihedral("FOURDIHS", "Fourier Dih.", 4, 4, 4), + def_dihedral("IDIHS", "Improper Dih.", 4, 2, 2), def_dihedral("PIDIHS", "Improper Dih.", 4, 3, 3), + def_dihedral_tabulated("TABDIHS", "Tab. Dih.", 4, 2, 2), + def_dihedral("CMAP", "CMAP Dih.", 5, -1, -1), def_nofc("GB12", "GB 1-2 Pol. (unused)"), def_nofc("GB13", "GB 1-3 Pol. (unused)"), def_nofc("GB14", "GB 1-4 Pol. (unused)"), def_nofc("GBPOL", "GB Polarization (unused)"), def_nofc("NPSOLVATION", "Nonpolar Sol. (unused)"), - def_bondedz("LJ14", "LJ-14", 2, 2, 2), def_nofc("COUL14", "Coulomb-14"), - def_bondedz("LJC14_Q", "LJC-14 q", 2, 5, 0), def_bondedz("LJC_NB", "LJC Pairs NB", 2, 4, 0), + def_pair("LJ14", "LJ-14", 2, 2, 2), def_nofc("COUL14", "Coulomb-14"), + def_pair("LJC14_Q", "LJC-14 q", 2, 5, 0), def_pair("LJC_NB", "LJC Pairs NB", 2, 4, 0), def_nb("LJ_SR", "LJ (SR)", 2, 2), def_nb("BHAM", "Buck.ham (SR)", 2, 3), def_nofc("LJ_LR", "LJ (unused)"), def_nofc("BHAM_LR", "B.ham (unused)"), def_nofc("DISPCORR", "Disper. corr."), def_nofc("COUL_SR", "Coulomb (SR)"), diff --git a/src/gromacs/topology/ifunc.h b/src/gromacs/topology/ifunc.h index 584c57f0b7..0ac9c0c327 100644 --- a/src/gromacs/topology/ifunc.h +++ b/src/gromacs/topology/ifunc.h @@ -75,8 +75,10 @@ constexpr unsigned int IF_CONSTRAINT = 1 << 2; constexpr unsigned int IF_CHEMBOND = 1 << 3; constexpr unsigned int IF_BTYPE = 1 << 4; constexpr unsigned int IF_ATYPE = 1 << 5; -constexpr unsigned int IF_TABULATED = 1 << 6; -constexpr unsigned int IF_LIMZERO = 1 << 7; +constexpr unsigned int IF_DIHEDRAL = 1 << 6; +constexpr unsigned int IF_PAIR = 1 << 7; +constexpr unsigned int IF_TABULATED = 1 << 8; +constexpr unsigned int IF_LIMZERO = 1 << 9; /* These flags tell to some of the routines what can be done with this * item in the list. * With IF_BOND a bonded interaction will be calculated. -- 2.22.0