diff --git a/src/gromacs/CMakeLists.txt b/src/gromacs/CMakeLists.txt index a650842ff1..c89f07895d 100644 --- a/src/gromacs/CMakeLists.txt +++ b/src/gromacs/CMakeLists.txt @@ -87,6 +87,7 @@ add_subdirectory(commandline) add_subdirectory(domdec) add_subdirectory(ewald) add_subdirectory(fft) +add_subdirectory(fhmd) add_subdirectory(gpu_utils) add_subdirectory(hardware) add_subdirectory(linearalgebra) diff --git a/src/gromacs/fhmd/CMakeLists.txt b/src/gromacs/fhmd/CMakeLists.txt new file mode 100644 index 0000000000..01fa1a9e9f --- /dev/null +++ b/src/gromacs/fhmd/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB FHMD_SOURCES_CPP *.cpp) +set(FHMD_SOURCES_CPP ${FHMD_SOURCES_CPP} PARENT_SCOPE) +set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${FHMD_SOURCES_CPP} PARENT_SCOPE) + +#if (BUILD_TESTING) +# add_subdirectory(tests) +#endif() diff --git a/src/gromacs/fhmd/fhmd.cpp b/src/gromacs/fhmd/fhmd.cpp new file mode 100644 index 0000000000..dc3b85cd33 --- /dev/null +++ b/src/gromacs/fhmd/fhmd.cpp @@ -0,0 +1,248 @@ +#include "gmxpre.h" + +#include "fhmd.h" + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "gromacs/domdec/localatomset.h" +#include "gromacs/domdec/localatomsetmanager.h" +#include "gromacs/fhmd/fhmdImpl.h" +#include "gromacs/fhmd/fhmdInputParameters.h" +#include "gromacs/fileio/checkpoint.h" +#include "gromacs/math/units.h" +#include "gromacs/math/vec.h" +#include "gromacs/math/vectypes.h" +#include "gromacs/mdrunutility/mdmodulesnotifiers.h" +#include "gromacs/mdtypes/commrec.h" +#include "gromacs/mdtypes/iforceprovider.h" +#include "gromacs/mdtypes/imdmodule.h" +#include "gromacs/mdtypes/imdoutputprovider.h" +#include "gromacs/mdtypes/imdpoptionprovider.h" +#include "gromacs/mdtypes/inputrec.h" +#include "gromacs/mdtypes/md_enums.h" +#include "gromacs/mdtypes/mdatom.h" +#include "gromacs/options/basicoptions.h" +#include "gromacs/options/options.h" +#include "gromacs/options/optionsection.h" +#include "gromacs/pbcutil/pbc.h" +#include "gromacs/selection/indexutil.h" +#include "gromacs/topology/topology.h" +#include "gromacs/utility/arrayref.h" +#include "gromacs/utility/basedefinitions.h" +#include "gromacs/utility/fatalerror.h" +#include "gromacs/utility/keyvaluetreebuilder.h" +#include "gromacs/utility/keyvaluetreetransform.h" +#include "gromacs/utility/listoflists.h" +#include "gromacs/utility/strconvert.h" + +namespace gmx +{ + + +/*! \brief + * FHMD module + */ +class FHMD final : public IMDModule, public IMdpOptionProvider, public IMDOutputProvider +{ +public: + FHMD() = default; + + + // From IMDModule + IMdpOptionProvider* mdpOptionProvider() override { return this; } + IMDOutputProvider* outputProvider() override { return this; } + + void initOutput(FILE* fplog, int nfile, const t_filenm fnm[], bool bAppendFiles, const gmx_output_env_t* oenv) override; + + void finishOutput() override; + + /*! \brief + * Builds the underlying ForceProvider implementation, passes collected parameters to it + */ + void initForceProviders(ForceProviders* forceProviders) override + { + printf("[EXAMPLE] Considering constructing the FHMD module?\n"); + + isFHMDActive_ = fhmdParameters_.fhmdEnabled_; + + if (isFHMDActive_) + { + printf("[EXAMPLE] FHMD active, constructing the module\n"); + + if (!isNotifiedOfPBCType_) + { + gmx_fatal(FARGS, + "!!! Trying to initialize the FHMD module, but have not yet " + "been notified of all the relevant simulation setup variables. Internal " + "programming error."); + } + + this->impl_ = std::make_unique(fhmdParameters_, pbcType_); + forceProviders->addAlternativeUpdateStepProvider(this->impl_.get()); + } + } + + // From IMdpOptionProvider + void initMdpTransform(IKeyValueTreeTransformRules* transform) override; + void initMdpOptions(IOptionsContainerWithSections* options) override; + void buildMdpOutput(KeyValueTreeObjectBuilder* builder) const override; + + void subscribeToSimulationSetupNotifications(MDModulesNotifiers* notifier) override; + + //! No preprocessing events are subscribed currently. + void subscribeToPreProcessingNotifications(MDModulesNotifiers* notifier) override; + +private: + constexpr static const int versionNumber = 1; + + //! Whether the FHMD underlying implementation need to be set-up + bool isFHMDActive_ = false; + + //! FHMD parameters extracted from the MDP file + FhmdInputParameters fhmdParameters_; + + //! The PBC type has been notified to this module + bool isNotifiedOfPBCType_ = false; + //! PBC type + PbcType pbcType_; + + std::unique_ptr impl_; +}; + + +::std::unique_ptr createFHMDModule() +{ + return std::make_unique(); +} + + +void FHMD::initMdpTransform(IKeyValueTreeTransformRules* transform) +{ + const auto& stringIdentityTransform = [](std::string s) { return s; }; + + transform->addRule().from("/fhmd-enabled").to("/fhmd-enabled").transformWith(&fromStdString); + + transform->addRule() + .from("/fhmd-some-string-parameter") + .to("/fhmd-some-string-parameter") + .transformWith(stringIdentityTransform); + + transform->addRule() + .from("/fhmd-some-real-parameter") + .to("/fhmd-some-real-parameter") + .transformWith(&fromStdString); +} + +void FHMD::initMdpOptions(IOptionsContainerWithSections* options) +{ + + options->addOption(BooleanOption("fhmd-enabled").store(&fhmdParameters_.fhmdEnabled_)); + options->addOption( + StringOption("fhmd-some-string-parameter").store(&fhmdParameters_.someStringParameter_)); + + options->addOption(RealOption("fhmd-some-real-parameter").store(&fhmdParameters_.someRealParameter_)); +} + +void FHMD::buildMdpOutput(KeyValueTreeObjectBuilder* builder) const +{ + const char* const comment[] = { "\n; Parameters for the FHMD module\n" }; + builder->addValue("comment-fhmd", joinStrings(comment, "\n")); + + + builder->addValue("fhmd-enabled", fhmdParameters_.fhmdEnabled_); + + builder->addValue("fhmd-some-string-parameter", fhmdParameters_.someStringParameter_); + builder->addValue("fhmd-some-real-parameter", fhmdParameters_.someRealParameter_); +} + +void FHMD::subscribeToSimulationSetupNotifications(MDModulesNotifiers* notifier) +{ + + if (!fhmdParameters_.fhmdEnabled_) + { + return; + } + + // Get notified of PBC type during setup + const auto readPBCType = [this](const PbcType& pbcType) + { + printf("[EXAMPLE] We are notified of the PBC type\n"); + pbcType_ = pbcType; + isNotifiedOfPBCType_ = true; + }; + notifier->simulationSetupNotifier_.subscribe(readPBCType); + + + // Be notified when simulation is interrupted and checkpoint data is written + const auto checkpointDataWriting = [this](MDModulesWriteCheckpointData checkpointData) + { + if (fhmdParameters_.fhmdEnabled_) + { + impl_->writeCheckpointData(checkpointData); + } + }; + notifier->checkpointingNotifier_.subscribe(checkpointDataWriting); + + + // Be notified when simulation is restarting from checkpoint + // Note: does not supports multiple MPI nodes + const auto checkpointDataReading = [this](MDModulesCheckpointReadingDataOnMain checkpointData) + { + if (fhmdParameters_.fhmdEnabled_) + { + impl_->readCheckpointData(checkpointData.checkpointedData_); + } + }; + notifier->checkpointingNotifier_.subscribe(checkpointDataReading); +} + +void FHMD::subscribeToPreProcessingNotifications(MDModulesNotifiers* /*notifiers*/) +{ + + if (!fhmdParameters_.fhmdEnabled_) + { + return; + } +} + + +/*! \brief + * Initializes file output from a simulation run. + * + * \param[in] fplog File pointer for log messages + * \param[in] nfile Number of files + * \param[in] fnm Array of filenames and properties + * \param[in] bAppendFiles Whether or not we should append to files + * \param[in] oenv The output environment for xvg files + */ +void FHMD::initOutput(FILE* fplog, + int gmx_unused nfile, + const t_filenm gmx_unused fnm[], + bool gmx_unused bAppendFiles, + const gmx_unused gmx_output_env_t* oenv) +{ + printf("[EXAMPLE] We writing to the MD log, and possibly opening our own file\n"); + + fprintf(fplog, "FHMD module %s (v%d)\n", fhmdParameters_.fhmdEnabled_ ? "enabled" : "disabled", versionNumber); + if (fhmdParameters_.fhmdEnabled_) + { + fprintf(fplog, + "Output some stuff that is relevant to your method and would benefit from being in " + "the log file: %d %4.6f\n", + 42, + 12.6664); + } +} + +void FHMD::finishOutput() +{ + printf("[EXAMPLE] We are closing the file we opened in FHMD::initOutput, if we had open any\n"); +}; + +} // namespace gmx diff --git a/src/gromacs/fhmd/fhmd.h b/src/gromacs/fhmd/fhmd.h new file mode 100644 index 0000000000..8ee443f691 --- /dev/null +++ b/src/gromacs/fhmd/fhmd.h @@ -0,0 +1,35 @@ + +/*! \libinternal + * \defgroup module_fhmd FHMD (Fluctuating Hydrodynamics / Molecular Dynamics) module + * \ingroup group_mdrun + * + * \brief + * + * + */ + +#ifndef GROMACS_FHMD_H +#define GROMACS_FHMD_H + + +#include "config.h" + +#include + +#include "gromacs/utility/real.h" + +namespace gmx +{ + +class IMDModule; + +/*! \brief + * Creates a module allowing \Gromacs to do FHMD + * + */ +std::unique_ptr createFHMDModule(); + +} // namespace gmx + + +#endif // GROMACS_FHMD_H diff --git a/src/gromacs/fhmd/fhmdImpl.cpp b/src/gromacs/fhmd/fhmdImpl.cpp new file mode 100644 index 0000000000..18f9c16a4d --- /dev/null +++ b/src/gromacs/fhmd/fhmdImpl.cpp @@ -0,0 +1,45 @@ + +#include "fhmdImpl.h" + +#include "fhmdInputParameters.h" + +gmx::FHMDModule::FHMDImpl::FHMDImpl(const gmx::FhmdInputParameters& fhmdParameters, PbcType pbcType) : + pbcType_(pbcType) +{ + printf("[EXAMPLE] Doing FHMD module construction and initialization!!\n"); + param1_ = fhmdParameters.someStringParameter_; + param2_ = fhmdParameters.someRealParameter_; + printf("[EXAMPLE] Param1 = %s\n", param1_.c_str()); + printf("[EXAMPLE] Param2 = %20.10f\n", param2_); + + conservedQuantity1_ = 28.0; +} +void gmx::FHMDModule::FHMDImpl::performAlternativeUpdateStep(gmx::UpdateStepData* updateStepData) +{ + printf("[EXAMPLE] Doing the custom FHMD coordinate update here!!\n"); + + (void)updateStepData->cr; + (void)updateStepData->step; + (void)updateStepData->homenr; + (void)updateStepData->x; + (void)updateStepData->v; +} +void gmx::FHMDModule::FHMDImpl::writeCheckpointData(gmx::MDModulesWriteCheckpointData checkpointData) +{ + printf("[EXAMPLE] Writing FHMD data to checkpoint!!\n"); + + std::string currentkey; + + currentkey = "conserved-quantity-1"; + checkpointData.builder_.addValue(currentkey, conservedQuantity1_); +} + +void gmx::FHMDModule::FHMDImpl::readCheckpointData(const gmx::KeyValueTreeObject& checkpointData) +{ + printf("[EXAMPLE] Reading FHMD data from checkpoint!!\n"); + + std::string currentkey; + + currentkey = "conserved-quantity-1"; + conservedQuantity1_ = checkpointData[currentkey].cast(); +} diff --git a/src/gromacs/fhmd/fhmdImpl.h b/src/gromacs/fhmd/fhmdImpl.h new file mode 100644 index 0000000000..24bbdee77e --- /dev/null +++ b/src/gromacs/fhmd/fhmdImpl.h @@ -0,0 +1,51 @@ + +#ifndef GROMACS_FHMDIMPL_H +#define GROMACS_FHMDIMPL_H + +#include "config.h" + +#include + +#include "gromacs/domdec/localatomset.h" +#include "gromacs/fileio/checkpoint.h" +#include "gromacs/mdtypes/commrec.h" +#include "gromacs/mdtypes/iforceprovider.h" +#include "gromacs/mdtypes/imdmodule.h" +#include "gromacs/mdtypes/md_enums.h" + +struct gmx_mtop_t; +struct t_inputrec; + +namespace gmx +{ +struct FhmdInputParameters; +}; + +namespace gmx::FHMDModule +{ + + +class FHMDImpl : public IAlternativeUpdateStepProvider +{ +public: + FHMDImpl(const gmx::FhmdInputParameters& fhmdParameters, PbcType pbcType); + void performAlternativeUpdateStep(UpdateStepData* updateStepData) override; + + //! Write all necessary internal state to checkpoint file + void writeCheckpointData(gmx::MDModulesWriteCheckpointData checkpointData); + + //! Re-init internal state from checkpointed data + void readCheckpointData(const gmx::KeyValueTreeObject& checkpointData); + +private: + PbcType pbcType_; + + std::string param1_; + real param2_; + + real conservedQuantity1_; +}; + +} // namespace gmx::FHMDModule + +#endif // GROMACS_FHMDIMPL_H diff --git a/src/gromacs/fhmd/fhmdInputParameters.h b/src/gromacs/fhmd/fhmdInputParameters.h new file mode 100644 index 0000000000..2805916868 --- /dev/null +++ b/src/gromacs/fhmd/fhmdInputParameters.h @@ -0,0 +1,42 @@ +#ifndef GROMACS_FHMDPARAMETERS_H +#define GROMACS_FHMDPARAMETERS_H + + + +#include "config.h" + +#include + +#include "gromacs/utility/real.h" + + +namespace gmx +{ + + +/*! \internal + * \brief Input parameters needed for FHMD, defined in MDP file + */ +struct FhmdInputParameters +{ + struct defaults + { + // Disabled by default + static constexpr bool fhmdEnabled_ = false; + + //! According to Example et al., 12.4 is a good value for blahblahblah + static constexpr real someRealParameter_ = 12.45552; + }; + //! Whether the ChargePen module is enabled + bool fhmdEnabled_ = defaults::fhmdEnabled_; + + //! Some parameter in string form + std::string someStringParameter_; + + //! Some value the method cares about (real number) + real someRealParameter_ = defaults::someRealParameter_; +}; + +} // namespace gmx + +#endif // GROMACS_FHMDPARAMETERS_H diff --git a/src/gromacs/mdrun/md.cpp b/src/gromacs/mdrun/md.cpp index debac21dfe..bab41171bb 100644 --- a/src/gromacs/mdrun/md.cpp +++ b/src/gromacs/mdrun/md.cpp @@ -117,6 +117,7 @@ #include "gromacs/mdtypes/forcebuffers.h" #include "gromacs/mdtypes/forcerec.h" #include "gromacs/mdtypes/group.h" +#include "gromacs/mdtypes/iforceprovider.h" #include "gromacs/mdtypes/inputrec.h" #include "gromacs/mdtypes/interaction_const.h" #include "gromacs/mdtypes/md_enums.h" @@ -1423,7 +1424,7 @@ void gmx::LegacySimulator::do_md() copy_mat(state->box, lastbox); dvdl_constr = 0; - + if (!useGpuForUpdate) { wallcycle_start(wcycle, WallCycleCounter::Update); @@ -1461,7 +1462,7 @@ void gmx::LegacySimulator::do_md() &pressureCouplingMu, &parrinelloRahmanM); } - + if (EI_VV(ir->eI)) { GMX_ASSERT(!useGpuForUpdate, "GPU update is not supported with VVAK integrator."); @@ -1590,21 +1591,33 @@ void gmx::LegacySimulator::do_md() (simulationWork.useMts && step % ir->mtsLevels[1].stepFactor == 0) ? f.view().forceMtsCombinedWithPadding() : f.view().forceWithPadding(); - upd.update_coords(*ir, - step, - md->homenr, - md->havePartiallyFrozenAtoms, - md->ptype, - md->invmass, - md->invMassPerDim, - state, - forceCombined, - &fcdata, - ekind, - parrinelloRahmanM, - etrtPOSITION, - cr, - constr != nullptr); + + if(fr->forceProviders->hasAlternativeUpdateStepProvider()) { + printf("[EXAMPLE] calling into our routine.\n"); + UpdateStepData updateStepData; + updateStepData.cr = cr; + updateStepData.step = step; + updateStepData.homenr = md->homenr; + updateStepData.x = &(state->x); + updateStepData.v = &(state->v); + fr->forceProviders->doAlternativeUpdateStep(&updateStepData); + } else { + upd.update_coords(*ir, + step, + md->homenr, + md->havePartiallyFrozenAtoms, + md->ptype, + md->invmass, + md->invMassPerDim, + state, + forceCombined, + &fcdata, + ekind, + parrinelloRahmanM, + etrtPOSITION, + cr, + constr != nullptr); + } wallcycle_stop(wcycle, WallCycleCounter::Update); diff --git a/src/gromacs/mdrun/mdmodules.cpp b/src/gromacs/mdrun/mdmodules.cpp index 5221ff025c..c855ea31f3 100644 --- a/src/gromacs/mdrun/mdmodules.cpp +++ b/src/gromacs/mdrun/mdmodules.cpp @@ -40,6 +40,7 @@ #include "gromacs/applied_forces/densityfitting/densityfitting.h" #include "gromacs/applied_forces/electricfield.h" #include "gromacs/applied_forces/qmmm/qmmm.h" +#include "gromacs/fhmd/fhmd.h" #include "gromacs/imd/imd.h" #include "gromacs/mdrunutility/mdmodulesnotifiers.h" #include "gromacs/mdtypes/iforceprovider.h" @@ -65,6 +66,7 @@ public: Impl() : densityFitting_(DensityFittingModuleInfo::create()), field_(createElectricFieldModule()), + fhmd_(createFHMDModule()), imd_(createInteractiveMolecularDynamicsModule()), qmmm_(QMMMModuleInfo::create()), swapCoordinates_(createSwapCoordinatesModule()) @@ -76,6 +78,7 @@ public: // Create a section for applied-forces modules auto appliedForcesOptions = options->addSection(OptionSection("applied-forces")); field_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions); + fhmd_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions); densityFitting_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions); qmmm_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions); // In future, other sections would also go here. @@ -85,11 +88,13 @@ public: void initOutput(FILE* fplog, int nfile, const t_filenm fnm[], bool bAppendFiles, const gmx_output_env_t* oenv) override { field_->outputProvider()->initOutput(fplog, nfile, fnm, bAppendFiles, oenv); + fhmd_->outputProvider()->initOutput(fplog, nfile, fnm, bAppendFiles, oenv); densityFitting_->outputProvider()->initOutput(fplog, nfile, fnm, bAppendFiles, oenv); } void finishOutput() override { field_->outputProvider()->finishOutput(); + fhmd_->outputProvider()->finishOutput(); densityFitting_->outputProvider()->finishOutput(); } @@ -102,6 +107,7 @@ public: std::unique_ptr densityFitting_; std::unique_ptr field_; + std::unique_ptr fhmd_; std::unique_ptr forceProviders_; std::unique_ptr imd_; std::unique_ptr qmmm_; @@ -127,6 +133,7 @@ void MDModules::initMdpTransform(IKeyValueTreeTransformRules* rules) { auto appliedForcesScope = rules->scopedTransform("/applied-forces"); impl_->field_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules()); + impl_->fhmd_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules()); impl_->densityFitting_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules()); impl_->qmmm_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules()); } @@ -134,6 +141,7 @@ void MDModules::initMdpTransform(IKeyValueTreeTransformRules* rules) void MDModules::buildMdpOutput(KeyValueTreeObjectBuilder* builder) { impl_->field_->mdpOptionProvider()->buildMdpOutput(builder); + impl_->fhmd_->mdpOptionProvider()->buildMdpOutput(builder); impl_->densityFitting_->mdpOptionProvider()->buildMdpOutput(builder); impl_->qmmm_->mdpOptionProvider()->buildMdpOutput(builder); } @@ -171,6 +179,7 @@ ForceProviders* MDModules::initForceProviders() "Force providers initialized multiple times"); impl_->forceProviders_ = std::make_unique(); impl_->field_->initForceProviders(impl_->forceProviders_.get()); + impl_->fhmd_->initForceProviders(impl_->forceProviders_.get()); impl_->densityFitting_->initForceProviders(impl_->forceProviders_.get()); impl_->qmmm_->initForceProviders(impl_->forceProviders_.get()); for (auto&& module : impl_->modules_) @@ -182,12 +191,14 @@ ForceProviders* MDModules::initForceProviders() void MDModules::subscribeToPreProcessingNotifications() { + impl_->fhmd_->subscribeToPreProcessingNotifications(&impl_->notifiers_); impl_->densityFitting_->subscribeToPreProcessingNotifications(&impl_->notifiers_); impl_->qmmm_->subscribeToPreProcessingNotifications(&impl_->notifiers_); } void MDModules::subscribeToSimulationSetupNotifications() { + impl_->fhmd_->subscribeToSimulationSetupNotifications(&impl_->notifiers_); impl_->densityFitting_->subscribeToSimulationSetupNotifications(&impl_->notifiers_); impl_->qmmm_->subscribeToSimulationSetupNotifications(&impl_->notifiers_); } diff --git a/src/gromacs/mdtypes/iforceprovider.cpp b/src/gromacs/mdtypes/iforceprovider.cpp index 650d32e8c4..5117de4942 100644 --- a/src/gromacs/mdtypes/iforceprovider.cpp +++ b/src/gromacs/mdtypes/iforceprovider.cpp @@ -45,6 +45,7 @@ #include #include "gromacs/utility/arrayref.h" +#include "gromacs/utility/fatalerror.h" using namespace gmx; @@ -52,6 +53,7 @@ class ForceProviders::Impl { public: std::vector providers_; + std::vector alternativeUpdateStepProviders_; }; ForceProviders::ForceProviders() : impl_(new Impl) {} @@ -63,6 +65,16 @@ void ForceProviders::addForceProvider(gmx::IForceProvider* provider) impl_->providers_.push_back(provider); } +void ForceProviders::addAlternativeUpdateStepProvider(gmx::IAlternativeUpdateStepProvider* provider) { + static bool alreadyAnAlternativeUpdateProvider = false; + if(!alreadyAnAlternativeUpdateProvider) { + impl_->alternativeUpdateStepProviders_.push_back(provider); + } else { + gmx_fatal(FARGS, "An alternative update step provider was already registered"); + } +} + + bool ForceProviders::hasForceProvider() const { return !impl_->providers_.empty(); @@ -76,3 +88,14 @@ void ForceProviders::calculateForces(const ForceProviderInput& forceProviderInpu provider->calculateForces(forceProviderInput, forceProviderOutput); } } +bool gmx::ForceProviders::hasAlternativeUpdateStepProvider() const +{ + return !impl_->alternativeUpdateStepProviders_.empty(); +} + +void ForceProviders::doAlternativeUpdateStep(UpdateStepData* updateStepData) const +{ + GMX_RELEASE_ASSERT(impl_->alternativeUpdateStepProviders_.size() == 1, "Not exactly 1 alternative update provider"); + impl_->alternativeUpdateStepProviders_[0]->performAlternativeUpdateStep(updateStepData); +} + diff --git a/src/gromacs/mdtypes/iforceprovider.h b/src/gromacs/mdtypes/iforceprovider.h index 71bd3b02b2..f4870b9b8e 100644 --- a/src/gromacs/mdtypes/iforceprovider.h +++ b/src/gromacs/mdtypes/iforceprovider.h @@ -47,6 +47,7 @@ #include +#include "gromacs/gpu_utils/hostallocator.h" #include "gromacs/math/vec.h" #include "gromacs/utility/arrayref.h" #include "gromacs/utility/gmxassert.h" @@ -177,6 +178,30 @@ protected: ~IForceProvider() {} }; + +struct UpdateStepData { + const t_commrec* cr; + int64_t step; + int homenr; + const PaddedHostVector* x; + const PaddedHostVector* v; +}; + +class IAlternativeUpdateStepProvider +{ +public: + /*! \brief + * Computes forces. + * + * \param[in] forceProviderInput struct that collects input data for the force providers + * \param[in,out] forceProviderOutput struct that collects output data of the force providers + */ + virtual void performAlternativeUpdateStep(UpdateStepData* updateStepData) = 0; + +protected: + ~IAlternativeUpdateStepProvider() {} +}; + /*! \libinternal \brief * Evaluates forces from a collection of gmx::IForceProvider. * @@ -194,6 +219,11 @@ public: */ void addForceProvider(gmx::IForceProvider* provider); + void addAlternativeUpdateStepProvider(gmx::IAlternativeUpdateStepProvider* provider); + + //! Whether there are modules added. + bool hasAlternativeUpdateStepProvider() const; + //! Whether there are modules added. bool hasForceProvider() const; @@ -201,6 +231,9 @@ public: void calculateForces(const gmx::ForceProviderInput& forceProviderInput, gmx::ForceProviderOutput* forceProviderOutput) const; + //! Computes forces. + void doAlternativeUpdateStep(UpdateStepData* updateStepData) const; + private: class Impl;