To include a notification for your module
* Add the function signature for the callback function to the
- `MdModulesNotifier` in `mdmodulenotification.h`,
+ `MDModulesNotifiers` in `mdmodulenotification.h`,
```C++
- registerMdModulesNotification<...,
+ BuildMDModulesNotifier<...,
YourCallbackSignature,
...,
```
(keep alphabetical order for ease of git merge)
-* Hand the notifier_ member of the MdModules Implementation class to your
+* Hand the notifier_ member of the MDModules Implementation class to your
builder createYourModule(¬ifier_)
* Add the function you want to subscribe with in the builder,
structure, changing the function signature of all checkpoint-related functions,
and write a corresponding low-level routine interacting with the XDR library.
-**The MdModule approach:** To allow for modules to write checkpoints, the legacy
+**The MDModule approach:** To allow for modules to write checkpoints, the legacy
checkpoint was extended by a KVTree. When writing to checkpoint, this tree gets
filled (via callbacks) by the single modules, and then serialized. When reading,
the KVTree gets deserialized, and then distributed to the modules which can read
##### Modular simulator design
-The MdModule checks off almost all requirements to a modularized checkpointing format.
+The MDModule checks off almost all requirements to a modularized checkpointing format.
The proposed design is therefore an evolved form of this approach. Notably, two
improvements include
* Hide the implementation details of the data structure holding the data (currently,
Checking for key existence seems rather to be a lazy way to circumvent versioning,
and is therefore discouraged.
-**Callback method:** The modular simulator and MdModules don't use the exact same
+**Callback method:** The modular simulator and MDModules don't use the exact same
way of communicating with clients. The two methods could be unified if needed.
The only _fundamental_ difference is that modular simulator clients need to identify
-with a unique key to receive their dedicated sub-data, while MdModules all read from
-and write to the same KV-tree. MdModules could be adapted to that by either requiring
+with a unique key to receive their dedicated sub-data, while MDModules all read from
+and write to the same KV-tree. MDModules could be adapted to that by either requiring
a unique key from the modules, or by using the same `CheckpointData` for all modules
-and using a single unique key (something like "MdModules") to register that object
+and using a single unique key (something like "MDModules") to register that object
with the global checkpoint.
**Performance:** One of the major differences between the new approach and the legacy
/*
* 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.
* the DensityFitting class needs access to parameters that become available
* only during simulation setup.
*
- * This class collects these parameters via MdModuleNotifications in the
+ * This class collects these parameters via MDModulesNotifiers in the
* simulation setup phase and provides a check if all necessary parameters have
* been provided.
*/
referenceDensityVoxel /= sumOfDensityData;
}
}
- /*! \brief Set the periodic boundary condition via MdModuleNotifier.
+ /*! \brief Set the periodic boundary condition via MDModuleNotifier.
*
* The pbc type is wrapped in PeriodicBoundaryConditionType to
- * allow the MdModuleNotifier to statically distinguish the callback
+ * allow the MDModuleNotifier to statically distinguish the callback
* function type from other 'int' function callbacks.
*
* \param[in] pbcType enumerates the periodic boundary condition.
/*! \brief Request to be notified during pre-processing.
*
- * \param[in] notifier allows the module to subscribe to notifications from MdModules.
+ * \param[in] notifiers allows the module to subscribe to notifications from MDModules.
*
* The density fitting code subscribes to these notifications:
* - setting atom group indices in the densityFittingOptions_ from an
* key-value-tree during pre-processing by a function taking a
* KeyValueTreeObjectBuilder as parameter
*/
- void subscribeToPreProcessingNotifications(MdModulesNotifier* notifier) override
+ void subscribeToPreProcessingNotifications(MDModulesNotifiers* notifiers) override
{
- // Callbacks for several kinds of MdModuleNotification are created
+ // Callbacks for several kinds of MDModulesNotifier are created
// and subscribed, and will be dispatched correctly at run time
// based on the type of the parameter required by the lambda.
const auto setFitGroupIndicesFunction = [this](const IndexGroupsAndNames& indexGroupsAndNames) {
densityFittingOptions_.setFitGroupIndices(indexGroupsAndNames);
};
- notifier->preProcessingNotifications_.subscribe(setFitGroupIndicesFunction);
+ notifiers->preProcessingNotifier_.subscribe(setFitGroupIndicesFunction);
// Writing internal parameters during pre-processing
const auto writeInternalParametersFunction = [this](KeyValueTreeObjectBuilder treeBuilder) {
densityFittingOptions_.writeInternalParametersToKvt(treeBuilder);
};
- notifier->preProcessingNotifications_.subscribe(writeInternalParametersFunction);
+ notifiers->preProcessingNotifier_.subscribe(writeInternalParametersFunction);
// Checking for consistency with all .mdp options
const auto checkEnergyCaluclationFrequencyFunction =
[this](EnergyCalculationFrequencyErrors* energyCalculationFrequencyErrors) {
densityFittingOptions_.checkEnergyCaluclationFrequency(energyCalculationFrequencyErrors);
};
- notifier->preProcessingNotifications_.subscribe(checkEnergyCaluclationFrequencyFunction);
+ notifiers->preProcessingNotifier_.subscribe(checkEnergyCaluclationFrequencyFunction);
}
/*! \brief Request to be notified.
* - the type of periodic boundary conditions that are used
* by taking a PeriodicBoundaryConditionType as parameter
* - the writing of checkpoint data
- * by taking a MdModulesWriteCheckpointData as parameter
+ * by taking a MDModulesWriteCheckpointData as parameter
* - the reading of checkpoint data
- * by taking a MdModulesCheckpointReadingDataOnMaster as parameter
+ * by taking a MDModulesCheckpointReadingDataOnMaster as parameter
* - the broadcasting of checkpoint data
- * by taking MdModulesCheckpointReadingBroadcast as parameter
+ * by taking MDModulesCheckpointReadingBroadcast as parameter
*/
- void subscribeToSimulationSetupNotifications(MdModulesNotifier* notifier) override
+ void subscribeToSimulationSetupNotifications(MDModulesNotifiers* notifiers) override
{
if (!densityFittingOptions_.active())
{
const auto readInternalParametersFunction = [this](const KeyValueTreeObject& tree) {
densityFittingOptions_.readInternalParametersFromKvt(tree);
};
- notifier->simulationSetupNotifications_.subscribe(readInternalParametersFunction);
+ notifiers->simulationSetupNotifier_.subscribe(readInternalParametersFunction);
// constructing local atom sets during simulation setup
const auto setLocalAtomSetFunction = [this](LocalAtomSetManager* localAtomSetManager) {
this->constructLocalAtomSet(localAtomSetManager);
};
- notifier->simulationSetupNotifications_.subscribe(setLocalAtomSetFunction);
+ notifiers->simulationSetupNotifier_.subscribe(setLocalAtomSetFunction);
// constructing local atom sets during simulation setup
const auto setPeriodicBoundaryContionsFunction = [this](const PbcType& pbc) {
this->densityFittingSimulationParameters_.setPeriodicBoundaryConditionType(pbc);
};
- notifier->simulationSetupNotifications_.subscribe(setPeriodicBoundaryContionsFunction);
+ notifiers->simulationSetupNotifier_.subscribe(setPeriodicBoundaryContionsFunction);
// setting the simulation time step
const auto setSimulationTimeStepFunction = [this](const SimulationTimeStep& simulationTimeStep) {
this->densityFittingSimulationParameters_.setSimulationTimeStep(simulationTimeStep.delta_t);
};
- notifier->simulationSetupNotifications_.subscribe(setSimulationTimeStepFunction);
+ notifiers->simulationSetupNotifier_.subscribe(setSimulationTimeStepFunction);
// adding output to energy file
const auto requestEnergyOutput =
- [this](MdModulesEnergyOutputToDensityFittingRequestChecker* energyOutputRequest) {
+ [this](MDModulesEnergyOutputToDensityFittingRequestChecker* energyOutputRequest) {
this->setEnergyOutputRequest(energyOutputRequest);
};
- notifier->simulationSetupNotifications_.subscribe(requestEnergyOutput);
+ notifiers->simulationSetupNotifier_.subscribe(requestEnergyOutput);
// writing checkpoint data
- const auto checkpointDataWriting = [this](MdModulesWriteCheckpointData checkpointData) {
+ const auto checkpointDataWriting = [this](MDModulesWriteCheckpointData checkpointData) {
forceProvider_->writeCheckpointData(checkpointData, DensityFittingModuleInfo::name_);
};
- notifier->checkpointingNotifications_.subscribe(checkpointDataWriting);
+ notifiers->checkpointingNotifier_.subscribe(checkpointDataWriting);
// reading checkpoint data
- const auto checkpointDataReading = [this](MdModulesCheckpointReadingDataOnMaster checkpointData) {
+ const auto checkpointDataReading = [this](MDModulesCheckpointReadingDataOnMaster checkpointData) {
densityFittingState_.readState(checkpointData.checkpointedData_,
DensityFittingModuleInfo::name_);
};
- notifier->checkpointingNotifications_.subscribe(checkpointDataReading);
+ notifiers->checkpointingNotifier_.subscribe(checkpointDataReading);
// broadcasting checkpoint data
- const auto checkpointDataBroadcast = [this](MdModulesCheckpointReadingBroadcast checkpointData) {
+ const auto checkpointDataBroadcast = [this](MDModulesCheckpointReadingBroadcast checkpointData) {
densityFittingState_.broadcastState(checkpointData.communicator_, checkpointData.isParallelRun_);
};
- notifier->checkpointingNotifications_.subscribe(checkpointDataBroadcast);
+ notifiers->checkpointingNotifier_.subscribe(checkpointDataBroadcast);
}
//! From IMDModule
/*! \brief Set up the local atom sets that are used by this module.
*
- * \note When density fitting is set up with MdModuleNotification in
+ * \note When density fitting is set up with MDModulesNotifier in
* the constructor, this function is called back.
*
* \param[in] localAtomSetManager the manager to add local atom sets.
/*! \brief Request energy output to energy file during simulation.
*/
- void setEnergyOutputRequest(MdModulesEnergyOutputToDensityFittingRequestChecker* energyOutputRequest)
+ void setEnergyOutputRequest(MDModulesEnergyOutputToDensityFittingRequestChecker* energyOutputRequest)
{
energyOutputRequest->energyOutputToDensityFitting_ = densityFittingOptions_.active();
}
impl_->calculateForces(forceProviderInput, forceProviderOutput);
}
-void DensityFittingForceProvider::writeCheckpointData(MdModulesWriteCheckpointData checkpointWriting,
+void DensityFittingForceProvider::writeCheckpointData(MDModulesWriteCheckpointData checkpointWriting,
const std::string& moduleName)
{
impl_->stateToCheckpoint().writeState(checkpointWriting.builder_, moduleName);
* \note The provided state to checkpoint has to change if checkpointing
* is moved before the force provider call in the MD-loop.
*/
- void writeCheckpointData(MdModulesWriteCheckpointData checkpointWriting, const std::string& moduleName);
+ void writeCheckpointData(MDModulesWriteCheckpointData checkpointWriting, const std::string& moduleName);
private:
class Impl;
void calculateForces(const ForceProviderInput& forceProviderInput,
ForceProviderOutput* forceProviderOutput) override;
- void subscribeToSimulationSetupNotifications(MdModulesNotifier* /* notifier */) override {}
- void subscribeToPreProcessingNotifications(MdModulesNotifier* /* notifier */) override {}
+ void subscribeToSimulationSetupNotifications(MDModulesNotifiers* /* notifiers */) override {}
+ void subscribeToPreProcessingNotifications(MDModulesNotifiers* /* notifiers */) override {}
private:
//! Return whether or not to apply a field
cptv_RemoveBuildMachineInformation, /**< remove functionality that makes mdrun builds non-reproducible */
cptv_ComPrevStepAsPullGroupReference, /**< Allow using COM of previous step as pull group PBC reference */
cptv_PullAverage, /**< Added possibility to output average pull force and position */
- cptv_MdModules, /**< Added checkpointing for MdModules */
+ cptv_MDModules, /**< Added checkpointing for MDModules */
cptv_ModularSimulator, /**< Added checkpointing for modular simulator */
cptv_Count /**< the total number of cptv versions */
};
return ret;
}
-static void do_cpt_mdmodules(int fileVersion,
- t_fileio* checkpointFileHandle,
- const gmx::MdModulesNotifier& mdModulesNotifier,
- FILE* outputFile)
+static void do_cpt_mdmodules(int fileVersion,
+ t_fileio* checkpointFileHandle,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ FILE* outputFile)
{
- if (fileVersion >= cptv_MdModules)
+ if (fileVersion >= cptv_MDModules)
{
gmx::FileIOXdrSerializer serializer(checkpointFileHandle);
gmx::KeyValueTreeObject mdModuleCheckpointParameterTree =
gmx::TextWriter textWriter(outputFile);
gmx::dumpKeyValueTree(&textWriter, mdModuleCheckpointParameterTree);
}
- gmx::MdModulesCheckpointReadingDataOnMaster mdModuleCheckpointReadingDataOnMaster = {
+ gmx::MDModulesCheckpointReadingDataOnMaster mdModuleCheckpointReadingDataOnMaster = {
mdModuleCheckpointParameterTree, fileVersion
};
- mdModulesNotifier.checkpointingNotifications_.notify(mdModuleCheckpointReadingDataOnMaster);
+ mdModulesNotifiers.checkpointingNotifier_.notify(mdModuleCheckpointReadingDataOnMaster);
}
}
LambdaWeightCalculation elamstats,
t_state* state,
ObservablesHistory* observablesHistory,
- const gmx::MdModulesNotifier& mdModulesNotifier,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
std::vector<gmx_file_position_t>* outputfiles,
gmx::WriteCheckpointDataHolder* modularSimulatorCheckpointData)
{
gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
}
- // Checkpointing MdModules
+ // Checkpointing MDModules
{
gmx::KeyValueTreeBuilder builder;
- gmx::MdModulesWriteCheckpointData mdModulesWriteCheckpoint = { builder.rootObject(),
+ gmx::MDModulesWriteCheckpointData mdModulesWriteCheckpoint = { builder.rootObject(),
headerContents.file_version };
- mdModulesNotifier.checkpointingNotifications_.notify(mdModulesWriteCheckpoint);
+ mdModulesNotifiers.checkpointingNotifier_.notify(mdModulesWriteCheckpoint);
auto tree = builder.build();
gmx::FileIOXdrSerializer serializer(fp);
gmx::serializeKeyValueTree(tree, &serializer);
t_state* state,
ObservablesHistory* observablesHistory,
gmx_bool reproducibilityRequested,
- const gmx::MdModulesNotifier& mdModulesNotifier,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
bool useModularSimulator)
{
{
cp_error();
}
- do_cpt_mdmodules(headerContents->file_version, fp, mdModulesNotifier, nullptr);
+ do_cpt_mdmodules(headerContents->file_version, fp, mdModulesNotifiers, nullptr);
if (headerContents->file_version >= cptv_ModularSimulator)
{
gmx::FileIOXdrSerializer serializer(fp);
t_state* state,
ObservablesHistory* observablesHistory,
gmx_bool reproducibilityRequested,
- const gmx::MdModulesNotifier& mdModulesNotifier,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
bool useModularSimulator)
{
state,
observablesHistory,
reproducibilityRequested,
- mdModulesNotifier,
+ mdModulesNotifiers,
modularSimulatorCheckpointData,
useModularSimulator);
}
if (PAR(cr))
{
gmx_bcast(sizeof(headerContents.step), &headerContents.step, cr->mpiDefaultCommunicator);
- gmx::MdModulesCheckpointReadingBroadcast broadcastCheckPointData = {
+ gmx::MDModulesCheckpointReadingBroadcast broadcastCheckPointData = {
cr->mpiDefaultCommunicator, PAR(cr), headerContents.file_version
};
- mdModulesNotifier.checkpointingNotifications_.notify(broadcastCheckPointData);
+ mdModulesNotifiers.checkpointingNotifier_.notify(broadcastCheckPointData);
}
ir->bContinuation = TRUE;
if (ir->nsteps >= 0)
{
cp_error();
}
- gmx::MdModulesNotifier mdModuleNotifier;
- do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifier, nullptr);
+ gmx::MDModulesNotifiers mdModuleNotifiers;
+ do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifiers, nullptr);
if (headerContents.file_version >= cptv_ModularSimulator)
{
// Store modular checkpoint data into modularSimulatorCheckpointData
std::vector<gmx_file_position_t> outputfiles;
ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, out, headerContents.file_version);
}
- gmx::MdModulesNotifier mdModuleNotifier;
- do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifier, out);
+ gmx::MDModulesNotifiers mdModuleNotifiers;
+ do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifiers, out);
if (headerContents.file_version >= cptv_ModularSimulator)
{
gmx::FileIOXdrSerializer serializer(fp);
namespace gmx
{
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
class KeyValueTreeObject;
class ReadCheckpointDataHolder;
class WriteCheckpointDataHolder;
KeyValueTreeObjectBuilder kvtBuilder);
/*! \libinternal
- * \brief Provides the MdModules with the checkpointed data on the master rank.
+ * \brief Provides the MDModules with the checkpointed data on the master rank.
*/
-struct MdModulesCheckpointReadingDataOnMaster
+struct MDModulesCheckpointReadingDataOnMaster
{
- //! The data of the MdModules that is stored in the checkpoint file
+ //! The data of the MDModules that is stored in the checkpoint file
const KeyValueTreeObject& checkpointedData_;
//! The version of the read ceckpoint file
int checkpointFileVersion_;
};
/*! \libinternal
- * \brief Provides the MdModules with the communication record to broadcast.
+ * \brief Provides the MDModules with the communication record to broadcast.
*/
-struct MdModulesCheckpointReadingBroadcast
+struct MDModulesCheckpointReadingBroadcast
{
//! The communicator
MPI_Comm communicator_;
int checkpointFileVersion_;
};
-/*! \libinternal \brief Writing the MdModules data to a checkpoint file.
+/*! \libinternal \brief Writing the MDModules data to a checkpoint file.
*/
-struct MdModulesWriteCheckpointData
+struct MDModulesWriteCheckpointData
{
- //! Builder for the Key-Value-Tree to store the MdModule checkpoint data
+ //! Builder for the Key-Value-Tree to store the MDModule checkpoint data
KeyValueTreeObjectBuilder builder_;
//! The version of the read file version
int checkpointFileVersion_;
LambdaWeightCalculation elamstats,
t_state* state,
ObservablesHistory* observablesHistory,
- const gmx::MdModulesNotifier& notifier,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
std::vector<gmx_file_position_t>* outputfiles,
gmx::WriteCheckpointDataHolder* modularSimulatorCheckpointData);
t_state* state,
ObservablesHistory* observablesHistory,
gmx_bool reproducibilityRequested,
- const gmx::MdModulesNotifier& mdModulesNotifier,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
bool useModularSimulator);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
- // Now that the MdModules have their options assigned from get_ir, subscribe
+ // Now that the MDModules have their options assigned from get_ir, subscribe
// to eventual notifications during pre-processing their data
mdModules.subscribeToPreProcessingNotifications();
.asParagraph()
.appendTextFormatted("checking input for internal consistency...");
}
- check_ir(mdparin, mdModules.notifier(), ir, opts, wi);
+ check_ir(mdparin, mdModules.notifiers(), ir, opts, wi);
if (ir->ld_seed == -1)
{
{
GMX_LOG(logger.info).asParagraph().appendTextFormatted("initialising group options...");
}
- do_index(mdparin, ftp2fn_null(efNDX, NFILE, fnm), &sys, bVerbose, mdModules.notifier(), ir, wi);
+ do_index(mdparin, ftp2fn_null(efNDX, NFILE, fnm), &sys, bVerbose, mdModules.notifiers(), ir, wi);
if (ir->cutoff_scheme == CutoffScheme::Verlet && ir->verletbuf_tol > 0)
{
{
gmx::KeyValueTreeBuilder internalParameterBuilder;
- mdModules.notifier().preProcessingNotifications_.notify(internalParameterBuilder.rootObject());
+ mdModules.notifiers().preProcessingNotifier_.notify(internalParameterBuilder.rootObject());
ir->internalParameters =
std::make_unique<gmx::KeyValueTreeObject>(internalParameterBuilder.build());
}
}
}
-void check_ir(const char* mdparin,
- const gmx::MdModulesNotifier& mdModulesNotifier,
- t_inputrec* ir,
- t_gromppopts* opts,
- warninp_t wi)
+void check_ir(const char* mdparin,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ t_inputrec* ir,
+ t_gromppopts* opts,
+ warninp_t wi)
/* Check internal consistency.
* NOTE: index groups are not set here yet, don't check things
* like temperature coupling group options here, but in triple_check
check_nst("nstcalcenergy", ir->nstcalcenergy, "nstenergy", &ir->nstenergy, wi);
}
- // Inquire all MdModules, if their parameters match with the energy
+ // Inquire all MDModules, if their parameters match with the energy
// calculation frequency
gmx::EnergyCalculationFrequencyErrors energyCalculationFrequencyErrors(ir->nstcalcenergy);
- mdModulesNotifier.preProcessingNotifications_.notify(&energyCalculationFrequencyErrors);
+ mdModulesNotifiers.preProcessingNotifier_.notify(&energyCalculationFrequencyErrors);
// Emit all errors from the energy calculation frequency checks
for (const std::string& energyFrequencyErrorMessage :
}
}
-void do_index(const char* mdparin,
- const char* ndx,
- gmx_mtop_t* mtop,
- bool bVerbose,
- const gmx::MdModulesNotifier& notifier,
- t_inputrec* ir,
- warninp_t wi)
+void do_index(const char* mdparin,
+ const char* ndx,
+ gmx_mtop_t* mtop,
+ bool bVerbose,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ t_inputrec* ir,
+ warninp_t wi)
{
t_blocka* defaultIndexGroups;
int natoms;
gmx::IndexGroupsAndNames defaultIndexGroupsAndNames(
*defaultIndexGroups, gmx::arrayRefFromArray(gnames, defaultIndexGroups->nr));
- notifier.preProcessingNotifications_.notify(defaultIndexGroupsAndNames);
+ mdModulesNotifiers.preProcessingNotifier_.notify(defaultIndexGroupsAndNames);
auto freezeDims = gmx::splitString(inputrecStrings->frdim);
auto freezeGroupNames = gmx::splitString(inputrecStrings->freeze);
namespace gmx
{
class MDModules;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
} // namespace gmx
struct gmx_mtop_t;
/*! \brief Clean up object that holds strings parsed from an .mdp file */
void done_inputrec_strings();
-void check_ir(const char* mdparin,
- const gmx::MdModulesNotifier& mdModulesNotifier,
- t_inputrec* ir,
- t_gromppopts* opts,
- warninp_t wi);
+void check_ir(const char* mdparin,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ t_inputrec* ir,
+ t_gromppopts* opts,
+ warninp_t wi);
/* Validate inputrec data.
* Fatal errors will be added to nerror.
*/
* function is called. Also prints the input file back to mdparout.
*/
-void do_index(const char* mdparin,
- const char* ndx,
- gmx_mtop_t* mtop,
- bool bVerbose,
- const gmx::MdModulesNotifier& notifier,
- t_inputrec* ir,
- warninp_t wi);
+void do_index(const char* mdparin,
+ const char* ndx,
+ gmx_mtop_t* mtop,
+ bool bVerbose,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ t_inputrec* ir,
+ warninp_t wi);
/* Read the index file and assign grp numbers to atoms.
*/
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,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.
get_ir(inputMdpFilename.c_str(), outputMdpFilename.c_str(), &mdModules_, &ir_, &opts_, WriteMdpHeader::no, wi_);
- check_ir(inputMdpFilename.c_str(), mdModules_.notifier(), &ir_, &opts_, wi_);
+ check_ir(inputMdpFilename.c_str(), mdModules_.notifiers(), &ir_, &opts_, wi_);
// Now check
bool failure = warning_errors_exist(wi_);
TestReferenceData data;
IMdpOptionProvider* mdpOptionProvider() override { return nullptr; }
IMDOutputProvider* outputProvider() override { return nullptr; }
void initForceProviders(ForceProviders* /* forceProviders */) override {}
- void subscribeToSimulationSetupNotifications(MdModulesNotifier* /* notifier */) override {}
- void subscribeToPreProcessingNotifications(MdModulesNotifier* /* notifier */) override {}
+ void subscribeToSimulationSetupNotifications(MDModulesNotifiers* /* notifiers */) override {}
+ void subscribeToPreProcessingNotifications(MDModulesNotifiers* /* notifiers */) override {}
};
std::unique_ptr<IMDModule> createInteractiveMolecularDynamicsModule()
* \todo Remove GMX_CONSTRAINTVIR
* \todo Write free-energy output also to energy file (after adding more tests)
*/
-EnergyOutput::EnergyOutput(ener_file* fp_ene,
- const gmx_mtop_t& mtop,
- const t_inputrec& inputrec,
- const pull_t* pull_work,
- FILE* fp_dhdl,
- bool isRerun,
- const StartingBehavior startingBehavior,
- const bool simulationsShareState,
- const MdModulesNotifier& mdModulesNotifier)
+EnergyOutput::EnergyOutput(ener_file* fp_ene,
+ const gmx_mtop_t& mtop,
+ const t_inputrec& inputrec,
+ const pull_t* pull_work,
+ FILE* fp_dhdl,
+ bool isRerun,
+ const StartingBehavior startingBehavior,
+ const bool simulationsShareState,
+ const MDModulesNotifiers& mdModulesNotifiers)
{
const char* ener_nm[F_NRE];
static const char* vir_nm[] = { "Vir-XX", "Vir-XY", "Vir-XZ", "Vir-YX", "Vir-YY",
bEner_[F_ORIRESDEV] = (gmx_mtop_ftype_count(mtop, F_ORIRES) > 0);
bEner_[F_COM_PULL] = ((inputrec.bPull && pull_have_potential(*pull_work)) || inputrec.bRot);
- MdModulesEnergyOutputToDensityFittingRequestChecker mdModulesAddOutputToDensityFittingFieldRequest;
- mdModulesNotifier.simulationSetupNotifications_.notify(&mdModulesAddOutputToDensityFittingFieldRequest);
+ MDModulesEnergyOutputToDensityFittingRequestChecker mdModulesAddOutputToDensityFittingFieldRequest;
+ mdModulesNotifiers.simulationSetupNotifier_.notify(&mdModulesAddOutputToDensityFittingFieldRequest);
bEner_[F_DENSITYFITTING] = mdModulesAddOutputToDensityFittingFieldRequest.energyOutputToDensityFitting_;
{
class Awh;
class Constraints;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
enum class StartingBehavior;
} // namespace gmx
* \param[in] isRerun Is this is a rerun instead of the simulations.
* \param[in] startingBehavior Run starting behavior.
* \param[in] simulationsShareState Tells whether the physical state is shared over simulations
- * \param[in] mdModulesNotifier Notifications to MD modules.
+ * \param[in] mdModulesNotifiers Notifications to MD modules.
*/
- EnergyOutput(ener_file* fp_ene,
- const gmx_mtop_t& mtop,
- const t_inputrec& inputrec,
- const pull_t* pull_work,
- FILE* fp_dhdl,
- bool isRerun,
- StartingBehavior startingBehavior,
- bool simulationsShareState,
- const MdModulesNotifier& mdModulesNotifier);
+ EnergyOutput(ener_file* fp_ene,
+ const gmx_mtop_t& mtop,
+ const t_inputrec& inputrec,
+ const pull_t* pull_work,
+ FILE* fp_dhdl,
+ bool isRerun,
+ StartingBehavior startingBehavior,
+ bool simulationsShareState,
+ const MDModulesNotifiers& mdModulesNotifiers);
~EnergyOutput();
struct gmx_mdoutf
{
- t_fileio* fp_trn;
- t_fileio* fp_xtc;
- gmx_tng_trajectory_t tng;
- gmx_tng_trajectory_t tng_low_prec;
- int x_compression_precision; /* only used by XTC output */
- ener_file_t fp_ene;
- const char* fn_cpt;
- gmx_bool bKeepAndNumCPT;
- IntegrationAlgorithm eIntegrator;
- gmx_bool bExpanded;
- LambdaWeightCalculation elamstats;
- int simulation_part;
- FILE* fp_dhdl;
- int natoms_global;
- int natoms_x_compressed;
- const SimulationGroups* groups; /* for compressed position writing */
- gmx_wallcycle_t wcycle;
- rvec* f_global;
- gmx::IMDOutputProvider* outputProvider;
- const gmx::MdModulesNotifier* mdModulesNotifier;
- bool simulationsShareState;
- MPI_Comm mastersComm;
+ t_fileio* fp_trn;
+ t_fileio* fp_xtc;
+ gmx_tng_trajectory_t tng;
+ gmx_tng_trajectory_t tng_low_prec;
+ int x_compression_precision; /* only used by XTC output */
+ ener_file_t fp_ene;
+ const char* fn_cpt;
+ gmx_bool bKeepAndNumCPT;
+ IntegrationAlgorithm eIntegrator;
+ gmx_bool bExpanded;
+ LambdaWeightCalculation elamstats;
+ int simulation_part;
+ FILE* fp_dhdl;
+ int natoms_global;
+ int natoms_x_compressed;
+ const SimulationGroups* groups; /* for compressed position writing */
+ gmx_wallcycle_t wcycle;
+ rvec* f_global;
+ gmx::IMDOutputProvider* outputProvider;
+ const gmx::MDModulesNotifiers* mdModulesNotifiers;
+ bool simulationsShareState;
+ MPI_Comm mastersComm;
};
-gmx_mdoutf_t init_mdoutf(FILE* fplog,
- int nfile,
- const t_filenm fnm[],
- const gmx::MdrunOptions& mdrunOptions,
- const t_commrec* cr,
- gmx::IMDOutputProvider* outputProvider,
- const gmx::MdModulesNotifier& mdModulesNotifier,
- const t_inputrec* ir,
- const gmx_mtop_t& top_global,
- const gmx_output_env_t* oenv,
- gmx_wallcycle_t wcycle,
- const gmx::StartingBehavior startingBehavior,
- bool simulationsShareState,
- const gmx_multisim_t* ms)
+gmx_mdoutf_t init_mdoutf(FILE* fplog,
+ int nfile,
+ const t_filenm fnm[],
+ const gmx::MdrunOptions& mdrunOptions,
+ const t_commrec* cr,
+ gmx::IMDOutputProvider* outputProvider,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ const t_inputrec* ir,
+ const gmx_mtop_t& top_global,
+ const gmx_output_env_t* oenv,
+ gmx_wallcycle_t wcycle,
+ const gmx::StartingBehavior startingBehavior,
+ bool simulationsShareState,
+ const gmx_multisim_t* ms)
{
gmx_mdoutf_t of;
const char * appendMode = "a+", *writeMode = "w+", *filemode;
}
outputProvider->initOutput(fplog, nfile, fnm, restartWithAppending, oenv);
- of->mdModulesNotifier = &mdModulesNotifier;
+ of->mdModulesNotifiers = &mdModulesNotifiers;
/* Set up atom counts so they can be passed to actual
trajectory-writing routines later. Also, XTC writing needs
double t,
t_state* state,
ObservablesHistory* observablesHistory,
- const gmx::MdModulesNotifier& mdModulesNotifier,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
gmx::WriteCheckpointDataHolder* modularSimulatorCheckpointData,
bool applyMpiBarrierBeforeRename,
MPI_Comm mpiBarrierCommunicator)
elamstats,
state,
observablesHistory,
- mdModulesNotifier,
+ mdModulesNotifiers,
&outputfiles,
modularSimulatorCheckpointData);
t,
state_global,
observablesHistory,
- *(of->mdModulesNotifier),
+ *(of->mdModulesNotifiers),
modularSimulatorCheckpointData,
of->simulationsShareState,
of->mastersComm);
{
enum class StartingBehavior;
class IMDOutputProvider;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
struct MdrunOptions;
class WriteCheckpointDataHolder;
} // namespace gmx
* Returns a pointer to a data structure with all output file pointers
* and names required by mdrun.
*/
-gmx_mdoutf_t init_mdoutf(FILE* fplog,
- int nfile,
- const t_filenm fnm[],
- const gmx::MdrunOptions& mdrunOptions,
- const t_commrec* cr,
- gmx::IMDOutputProvider* outputProvider,
- const gmx::MdModulesNotifier& mdModulesNotifier,
- const t_inputrec* ir,
- const gmx_mtop_t& mtop,
- const gmx_output_env_t* oenv,
- gmx_wallcycle_t wcycle,
- gmx::StartingBehavior startingBehavior,
- bool simulationsShareState,
- const gmx_multisim_t* ms);
+gmx_mdoutf_t init_mdoutf(FILE* fplog,
+ int nfile,
+ const t_filenm fnm[],
+ const gmx::MdrunOptions& mdrunOptions,
+ const t_commrec* cr,
+ gmx::IMDOutputProvider* outputProvider,
+ const gmx::MDModulesNotifiers& mdModulesNotifiers,
+ const t_inputrec* ir,
+ const gmx_mtop_t& mtop,
+ const gmx_output_env_t* oenv,
+ gmx_wallcycle_t wcycle,
+ gmx::StartingBehavior startingBehavior,
+ bool simulationsShareState,
+ const gmx_multisim_t* ms);
/*! \brief Getter for file pointer */
ener_file_t mdoutf_get_fp_ene(gmx_mdoutf_t of);
inputrec_.ref_p[YY][XX] = 1.0;
}
- MdModulesNotifier mdModulesNotifier;
+ MDModulesNotifiers mdModulesNotifiers;
std::unique_ptr<EnergyOutput> energyOutput =
std::make_unique<EnergyOutput>(energyFile_,
mtop_,
parameters.isRerun,
StartingBehavior::NewSimulation,
false,
- mdModulesNotifier);
+ mdModulesNotifiers);
// Add synthetic data for a single step
double testValue = 10.0;
class Constraints;
class MdrunScheduleWorkload;
class IMDOutputProvider;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
class ImdSession;
class MDLogger;
class MDAtoms;
gmx_enfrot* enforcedRotation,
BoxDeformation* deform,
IMDOutputProvider* outputProvider,
- const MdModulesNotifier& mdModulesNotifier,
+ const MDModulesNotifiers& mdModulesNotifiers,
t_inputrec* inputrec,
ImdSession* imdSession,
pull_t* pull_work,
enforcedRotation(enforcedRotation),
deform(deform),
outputProvider(outputProvider),
- mdModulesNotifier(mdModulesNotifier),
+ mdModulesNotifiers(mdModulesNotifiers),
inputrec(inputrec),
imdSession(imdSession),
pull_work(pull_work),
BoxDeformation* deform;
//! Handles writing output files.
IMDOutputProvider* outputProvider;
- //! Handles notifications to MdModules for checkpoint writing
- const MdModulesNotifier& mdModulesNotifier;
+ //! Handles notifications to MDModules for checkpoint writing
+ const MDModulesNotifiers& mdModulesNotifiers;
//! Contains user input mdp options. Note: The const-ness is casted away in a few instances, see #3854.
const t_inputrec* inputrec;
//! The Interactive Molecular Dynamics session.
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
ir,
top_global,
oenv,
false,
startingBehavior,
simulationsShareState,
- mdModulesNotifier);
+ mdModulesNotifiers);
gstat = global_stat_init(ir);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,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.
* \note The notifier must be constructed before the modules and shall
* not be destructed before the modules are destructed.
*/
- MdModulesNotifier notifier_;
+ MDModulesNotifiers notifiers_;
std::unique_ptr<IMDModule> densityFitting_;
std::unique_ptr<IMDModule> field_;
void MDModules::subscribeToPreProcessingNotifications()
{
- impl_->densityFitting_->subscribeToPreProcessingNotifications(&impl_->notifier_);
+ impl_->densityFitting_->subscribeToPreProcessingNotifications(&impl_->notifiers_);
}
void MDModules::subscribeToSimulationSetupNotifications()
{
- impl_->densityFitting_->subscribeToSimulationSetupNotifications(&impl_->notifier_);
+ impl_->densityFitting_->subscribeToSimulationSetupNotifications(&impl_->notifiers_);
}
void MDModules::add(std::shared_ptr<gmx::IMDModule> module)
impl_->modules_.emplace_back(std::move(module));
}
-const MdModulesNotifier& MDModules::notifier()
+const MDModulesNotifiers& MDModules::notifiers()
{
- return impl_->notifier_;
+ return impl_->notifiers_;
}
} // namespace gmx
class IKeyValueTreeTransformRules;
class IMDModule;
class IMDOutputProvider;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
/*! \libinternal \brief
* Manages the collection of all modules used for mdrun.
*/
ForceProviders* initForceProviders();
- /*! \brief Subscribe MdModules to simulation setup notifications.
+ /*! \brief Subscribe MDModules to simulation setup notifications.
*
- * Allows MdModules to subscribe to notifications that are called back
+ * Allows MDModules to subscribe to notifications that are called back
* during the set up of an MD simulation, after the options were
* assigned to the modules.
*/
void subscribeToSimulationSetupNotifications();
- /*! \brief Subscribe MdModules to notifications during pre-processing.
+ /*! \brief Subscribe MDModules to notifications during pre-processing.
*
- * Allows MdModules to subscribe to notifications that are called back
+ * Allows MDModules to subscribe to notifications that are called back
* during pre processing an MD simulation, after the options were
* assigned to the modules.
*/
*/
void add(std::shared_ptr<IMDModule> module);
- /*! \brief Return a handle to the callbacks.
+ /*! \brief Return a handle to the notifiers used for callbacks between modules.
*/
- const MdModulesNotifier& notifier();
+ const MDModulesNotifiers& notifiers();
private:
class Impl;
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
ir,
top_global,
oenv,
true,
StartingBehavior::NewSimulation,
simulationsShareState,
- mdModulesNotifier);
+ mdModulesNotifiers);
gstat = global_stat_init(ir);
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
inputrec,
top_global,
nullptr,
false,
StartingBehavior::NewSimulation,
simulationsShareState,
- mdModulesNotifier);
+ mdModulesNotifiers);
/* Print to log file */
print_em_start(fplog, cr, walltime_accounting, wcycle, CG);
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
inputrec,
top_global,
nullptr,
false,
StartingBehavior::NewSimulation,
simulationsShareState,
- mdModulesNotifier);
+ mdModulesNotifiers);
const int start = 0;
const int end = mdatoms->homenr;
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
inputrec,
top_global,
nullptr,
false,
StartingBehavior::NewSimulation,
simulationsShareState,
- mdModulesNotifier);
+ mdModulesNotifiers);
/* Print to log file */
print_em_start(fplog, cr, walltime_accounting, wcycle, SD);
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
inputrec,
top_global,
nullptr,
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
ir,
top_global,
oenv,
true,
StartingBehavior::NewSimulation,
simulationsShareState,
- mdModulesNotifier);
+ mdModulesNotifiers);
gstat = global_stat_init(ir);
// TODO: Error handling
mdModules_->assignOptionsToModules(*inputrec->params, nullptr);
- // now that the MdModules know their options, they know which callbacks to sign up to
+ // now that the MDModules know their options, they know which callbacks to sign up to
mdModules_->subscribeToSimulationSetupNotifications();
- const auto& mdModulesNotifier = mdModules_->notifier().simulationSetupNotifications_;
+ const auto& setupNotifier = mdModules_->notifiers().simulationSetupNotifier_;
if (inputrec->internalParameters != nullptr)
{
- mdModulesNotifier.notify(*inputrec->internalParameters);
+ setupNotifier.notify(*inputrec->internalParameters);
}
if (fplog != nullptr)
SeparatePmeRanksPermitted separatePmeRanksPermitted;
/* Permit MDModules to notify whether they want to use PME-only ranks */
- mdModulesNotifier.notify(&separatePmeRanksPermitted);
+ setupNotifier.notify(&separatePmeRanksPermitted);
/* If simulation is not using PME then disable PME-only ranks */
if (!(EEL_PME(inputrec->coulombtype) || EVDW_PME(inputrec->vdwtype)))
globalState.get(),
&observablesHistory,
mdrunOptions.reproducible,
- mdModules_->notifier(),
+ mdModules_->notifiers(),
modularSimulatorCheckpointData.get(),
useModularSimulator);
// TODO: (#3652) Synchronize filesystem state, SimulationInput contents, and program
t_nrnb nrnb;
if (thisRankHasDuty(cr, DUTY_PP))
{
- mdModulesNotifier.notify(*cr);
- mdModulesNotifier.notify(&atomSets);
- mdModulesNotifier.notify(mtop);
- mdModulesNotifier.notify(inputrec->pbcType);
- mdModulesNotifier.notify(SimulationTimeStep{ inputrec->delta_t });
+ setupNotifier.notify(*cr);
+ setupNotifier.notify(&atomSets);
+ setupNotifier.notify(mtop);
+ setupNotifier.notify(inputrec->pbcType);
+ setupNotifier.notify(SimulationTimeStep{ inputrec->delta_t });
/* Initiate forcerecord */
fr = std::make_unique<t_forcerec>();
fr->forceProviders = mdModules_->initForceProviders();
static_cast<int>(filenames.size()), filenames.data(), inputrec.get(), fr.get()));
simulatorBuilder.add(ReplicaExchangeParameters(replExParams));
simulatorBuilder.add(InteractiveMD(imdSession.get()));
- simulatorBuilder.add(SimulatorModules(mdModules_->outputProvider(), mdModules_->notifier()));
+ simulatorBuilder.add(SimulatorModules(mdModules_->outputProvider(), mdModules_->notifiers()));
simulatorBuilder.add(CenterOfMassPulling(pull_work));
// Todo move to an MDModule
simulatorBuilder.add(IonSwapping(swap));
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2020, by the GROMACS development team, led by
+ * Copyright (c) 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.
t_state* state,
ObservablesHistory* observablesHistory,
bool reproducibilityRequested,
- const MdModulesNotifier& mdModulesNotifier,
+ const MDModulesNotifiers& mdModulesNotifiers,
gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
const bool useModularSimulator)
{
state,
observablesHistory,
reproducibilityRequested,
- mdModulesNotifier,
+ mdModulesNotifiers,
modularSimulatorCheckpointData,
useModularSimulator);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2020, by the GROMACS development team, led by
+ * Copyright (c) 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.
* SimulationInput implementation.
*
* \todo Consider refactoring to decouple the checkpoint facility from its consumers
- * (state, observablesHistory, mdModulesNotifier, and parts of ir).
+ * (state, observablesHistory, mdModulesNotifiers, and parts of ir).
*
* \warning It is the caller’s responsibility to make sure that
* preconditions are satisfied for the parameter objects.
t_state* state,
ObservablesHistory* observablesHistory,
bool reproducibilityRequested,
- const MdModulesNotifier& notifier,
+ const MDModulesNotifiers& notifiers,
gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
bool useModularSimulator);
/*
* 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.
constraintsParam_->enforcedRotation,
boxDeformation_->deform,
simulatorModules_->outputProvider,
- simulatorModules_->mdModulesNotifier,
+ simulatorModules_->mdModulesNotifiers,
legacyInput_->inputrec,
interactiveMD_->imdSession,
centerOfMassPulling_->pull_work,
constraintsParam_->enforcedRotation,
boxDeformation_->deform,
simulatorModules_->outputProvider,
- simulatorModules_->mdModulesNotifier,
+ simulatorModules_->mdModulesNotifiers,
legacyInput_->inputrec,
interactiveMD_->imdSession,
centerOfMassPulling_->pull_work,
class MembedHolder;
class MDAtoms;
class MDLogger;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
struct MdrunOptions;
class ReadCheckpointDataHolder;
enum class StartingBehavior;
class SimulatorModules
{
public:
- SimulatorModules(IMDOutputProvider* mdOutputProvider, const MdModulesNotifier& notifier) :
+ SimulatorModules(IMDOutputProvider* mdOutputProvider, const MDModulesNotifiers& notifiers) :
outputProvider(mdOutputProvider),
- mdModulesNotifier(notifier)
+ mdModulesNotifiers(notifiers)
{
}
- IMDOutputProvider* outputProvider;
- const MdModulesNotifier& mdModulesNotifier;
+ IMDOutputProvider* outputProvider;
+ const MDModulesNotifiers& mdModulesNotifiers;
};
class CenterOfMassPulling
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,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.
class ForceProviders;
class IMDOutputProvider;
class IMdpOptionProvider;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
/*! \libinternal \brief
* Extension module for \Gromacs simulations.
//! Initializes force providers from this module.
virtual void initForceProviders(ForceProviders* forceProviders) = 0;
//! Subscribe to simulation setup notifications
- virtual void subscribeToSimulationSetupNotifications(MdModulesNotifier* notifier) = 0;
+ virtual void subscribeToSimulationSetupNotifications(MDModulesNotifiers* notifiers) = 0;
//! Subscribe to pre processing notifications
- virtual void subscribeToPreProcessingNotifications(MdModulesNotifier* notifier) = 0;
+ virtual void subscribeToPreProcessingNotifications(MDModulesNotifiers* notifiers) = 0;
};
} // namespace gmx
const Constraints* constr,
FILE* fplog,
t_fcdata* fcd,
- const MdModulesNotifier& mdModulesNotifier,
+ const MDModulesNotifiers& mdModulesNotifiers,
bool isMasterRank,
ObservablesHistory* observablesHistory,
StartingBehavior startingBehavior,
constr_(constr),
fplog_(fplog),
fcd_(fcd),
- mdModulesNotifier_(mdModulesNotifier),
+ mdModulesNotifiers_(mdModulesNotifiers),
groups_(&globalTopology.groups),
observablesHistory_(observablesHistory),
simulationsShareState_(simulationsShareState)
false,
startingBehavior_,
simulationsShareState_,
- mdModulesNotifier_);
+ mdModulesNotifiers_);
if (!isMasterRank_)
{
class ParrinelloRahmanBarostat;
class StatePropagatorData;
class VelocityScalingTemperatureCoupling;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
//! Function type for elements contributing energy
using EnergyContribution = std::function<real(Step, Time)>;
const Constraints* constr,
FILE* fplog,
t_fcdata* fcd,
- const MdModulesNotifier& mdModulesNotifier,
+ const MDModulesNotifiers& mdModulesNotifiers,
bool isMasterRank,
ObservablesHistory* observablesHistory,
StartingBehavior startingBehavior,
FILE* fplog_;
//! Helper struct for force calculations.
t_fcdata* fcd_;
- //! Notification to MD modules
- const MdModulesNotifier& mdModulesNotifier_;
+ //! Notifiers to MD modules
+ const MDModulesNotifiers& mdModulesNotifiers_;
//! Global topology groups
const SimulationGroups* groups_;
//! History of simulation observables.
legacySimulatorData->constr,
legacySimulatorData->fplog,
legacySimulatorData->fr->fcdata.get(),
- legacySimulatorData->mdModulesNotifier,
+ legacySimulatorData->mdModulesNotifiers,
MASTER(legacySimulatorData->cr),
legacySimulatorData->observablesHistory,
legacySimulatorData->startingBehavior,
legacySimulatorData_->mdrunOptions,
legacySimulatorData_->cr,
legacySimulatorData_->outputProvider,
- legacySimulatorData_->mdModulesNotifier,
+ legacySimulatorData_->mdModulesNotifiers,
legacySimulatorData_->inputrec,
legacySimulatorData_->top_global,
legacySimulatorData_->oenv,
const MdrunOptions& mdrunOptions,
const t_commrec* cr,
gmx::IMDOutputProvider* outputProvider,
- const MdModulesNotifier& mdModulesNotifier,
+ const MDModulesNotifiers& mdModulesNotifiers,
const t_inputrec* inputrec,
const gmx_mtop_t& top_global,
const gmx_output_env_t* oenv,
mdrunOptions,
cr,
outputProvider,
- mdModulesNotifier,
+ mdModulesNotifiers,
inputrec,
top_global,
oenv,
namespace gmx
{
class IMDOutputProvider;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
struct MdrunOptions;
enum class StartingBehavior;
const MdrunOptions& mdrunOptions,
const t_commrec* cr,
IMDOutputProvider* outputProvider,
- const MdModulesNotifier& mdModulesNotifier,
+ const MDModulesNotifiers& mdModulesNotifiers,
const t_inputrec* inputrec,
const gmx_mtop_t& top_global,
const gmx_output_env_t* oenv,
return newModule;
}
-void RestraintMDModule::subscribeToSimulationSetupNotifications(MdModulesNotifier* /*notifier*/) {}
+void RestraintMDModule::subscribeToSimulationSetupNotifications(MDModulesNotifiers* /*notifiers*/)
+{
+}
-void RestraintMDModule::subscribeToPreProcessingNotifications(MdModulesNotifier* /*notifier*/) {}
+void RestraintMDModule::subscribeToPreProcessingNotifications(MDModulesNotifiers* /*notifiers*/) {}
// private constructor to implement static create() method.
RestraintMDModule::RestraintMDModule(std::unique_ptr<RestraintMDModuleImpl> restraint) :
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2018,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.
// Forward declaration to allow opaque pointer to library internal class.
class RestraintMDModuleImpl;
-struct MdModulesNotifier;
+struct MDModulesNotifiers;
/*! \libinternal \ingroup module_restraint
* \brief MDModule wrapper for Restraint implementations.
void initForceProviders(ForceProviders* forceProviders) override;
//! Subscribe to simulation setup notifications
- void subscribeToSimulationSetupNotifications(MdModulesNotifier* notifier) override;
+ void subscribeToSimulationSetupNotifications(MDModulesNotifiers* notifiers) override;
//! Subscribe to pre processing notifications
- void subscribeToPreProcessingNotifications(MdModulesNotifier* notifier) override;
+ void subscribeToPreProcessingNotifications(MDModulesNotifiers* notifiers) override;
private:
/*!
IMdpOptionProvider* mdpOptionProvider() override { return nullptr; }
IMDOutputProvider* outputProvider() override { return nullptr; }
void initForceProviders(ForceProviders* /* forceProviders */) override {}
- void subscribeToSimulationSetupNotifications(MdModulesNotifier* /* notifier */) override {}
- void subscribeToPreProcessingNotifications(MdModulesNotifier* /* notifier */) override {}
+ void subscribeToSimulationSetupNotifications(MDModulesNotifiers* /* notifiers */) override {}
+ void subscribeToPreProcessingNotifications(MDModulesNotifiers* /* notifiers */) override {}
};
std::unique_ptr<IMDModule> createSwapCoordinatesModule()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2020, by the GROMACS development team, led by
+ * Copyright (c) 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.
*/
/*! \libinternal \file
* \brief
- * Declares gmx::MdModuleNotification.
+ * Declares gmx::MDModulesNotifier.
*
* \author Christian Blau <blau@kth.se>
* \inlibraryapi
namespace gmx
{
-/*! \libinternal \brief
- * Subscribe and trigger notification functions.
- *
- * Extends MdModuleNotificationBase with new notification function and routine
- * to subscribe new listeners.
- *
- * To create a class of this type that provides callbacks, e.g., for events
- * EventA, and EventB use registerMdModuleNotification<EventA, EventB>::type.
+/*! \libinternal
+ * \brief Organizes notifications about an event of interest to modules.
+ *
+ * An object of this type permits modules to subscribe to the
+ * corresponding event. The template types of this type encode what
+ * information is available when the event occurs. Modules \c
+ * subscribe() by providing a callback function that accepts a single
+ * parameter of such an event type. The code that handles that event
+ * has the responsibilty to call \c notify() afterwards. The
+ * subscribed modules then receive the callback with the requested
+ * event type as an argument.
+ *
+ * See gmx::MDModulesNotifiers for sequence diagrams for an example.
+ *
+ * This suits scenarios where several objects are built (or re-built)
+ * and one or more modules need to know when one or more of such
+ * objects are available (or updated), so they can adapt their
+ * internal state accordingly. Examples include responding to loading
+ * input data, or to changes related to a recurring process like
+ * checkpointing or partitioning. The coupling between these modules
+ * is now expressed indirectly. This improves the modularity and
+ * testability of those modules.
+ *
+ * The implementation provides the necessary flexibility to be
+ * parameterized with multiple event types and provide \c callback()
+ * and \b notify() methods corresponding to each related event. This
+ * is done by inheriting from a series of base classes, each of which
+ * handles a single type of event. BuildMDModulesNotifier implements
+ * the details. To create a class of this type that provides two
+ * events with callbacks that receive respectively types TypeA and
+ * TypeB, use BuildMDModulesNotifier<TypeA, TypeB>::type.
*
* \tparam CallParameter of the function to be notified
- * \tparam MdModuleNotificationBase class to be extended with a notification
+ * \tparam MDModulesNotifierBase class to be extended with a notification
* with CallParameter
*
- * \note All added subscribers are required to out-live the MdModuleNotification
+ * \note All added subscribers are required to out-live the MDModulesNotifier
*
*/
-template<class CallParameter, class MdModuleNotificationBase>
-class MdModuleNotification : public MdModuleNotificationBase
+template<class CallParameter, class MDModulesNotifierBase>
+class MDModulesNotifier : public MDModulesNotifierBase
{
public:
//! Make base class notification trigger available to this class
- using MdModuleNotificationBase::notify;
+ using MDModulesNotifierBase::notify;
//! Make base class subscription available to this class
- using MdModuleNotificationBase::subscribe;
+ using MDModulesNotifierBase::subscribe;
- /*! \brief Trigger the subscribed notifications.
+ /*! \brief Notifies subscribers of the event described by \c
+ * callbackParameter.
+ *
* \param[in] callParameter of the function to be called back
*/
void notify(CallParameter callParameter) const
}
/*! \brief
- * Add callback function to be called when notification is triggered.
- *
- * Notifications are distinguished by their call signature.
+ * Add callback function to be called when \c notify() is called
*
- * \param[in] callBackFunction to be called from this class
+ * \param[in] callBackFunction to be called
*/
void subscribe(std::function<void(CallParameter)> callBackFunction)
{
};
/*! \internal
- * \brief Aide to avoid nested MdModuleNotification definition.
+ * \brief Aide to avoid nested MDModulesNotifier definition.
*
* Instead of
- * MdModuleNotification<CallParameterA, MdModuleNotification<CallParameterB, etc ... >>
+ * MDModulesNotifier<CallParameterA, MDModulesNotifier<CallParameterB, etc ... >>
* this allows to write
- * registerMdModuleNotification<CallParameterA, CallParameterB, ...>::type
+ * BuildMDModulesNotifier<CallParameterA, CallParameterB, ...>::type
*
- * \tparam CallParameter all the event types to be registered
+ * \tparam CallParameter all the callback types to be registered
*/
template<class... CallParameter>
-struct registerMdModuleNotification;
+struct BuildMDModulesNotifier;
/*! \internal \brief Template specialization to end parameter unpacking recursion.
*/
template<>
-struct registerMdModuleNotification<>
+struct BuildMDModulesNotifier<>
{
/*! \internal
- * \brief Do nothing but be base class of MdModuleNotification.
+ * \brief Do nothing but be base class of MDModulesNotifier.
*
- * Required so that using MdModuleNotificationBase::notify and
- * MdModuleNotificationBase::subscribe are valid in derived class.
+ * Required so that using MDModulesNotifierBase::notify and
+ * MDModulesNotifierBase::subscribe are valid in derived class.
*/
class NoCallParameter
{
public:
- //! Do nothing but provide MdModuleNotification::notify to derived class
+ //! Do nothing but provide MDModulesNotifier::notify to derived class
void notify() {}
- //! Do nothing but provide MdModuleNotification::subscribe to derived class
+ //! Do nothing but provide MDModulesNotifier::subscribe to derived class
void subscribe() {}
};
/*! \brief Defines a type if no notifications are managed.
*
- * This ensures that code works with MdModuleCallParameterManagement that
+ * This ensures that code works with MDModuleCallParameterManagement that
* does not manage any notifications.
*/
using type = NoCallParameter;
};
/*! \libinternal
- * \brief Template specialization to assemble MdModuleNotification.
+ * \brief Template specialization to assemble MDModulesNotifier.
*
- * Assembly of MdModuleNotification is performed by recursively taking off the
+ * Assembly of MDModulesNotifier is performed by recursively taking off the
* front of the CallParameter parameter pack and constructing the nested type
- * definition of MdModuleNotification base classes.
+ * definition of MDModulesNotifier base classes.
*
* \tparam CurrentCallParameter front of the template parameter pack
- * \tparam CallParameter rest of the event types
+ * \tparam CallParameter rest of the callback types
*/
template<class CurrentCallParameter, class... CallParameter>
-struct registerMdModuleNotification<CurrentCallParameter, CallParameter...>
+struct BuildMDModulesNotifier<CurrentCallParameter, CallParameter...>
{
// private:
//! The next type with rest of the arguments with the front parameter removed.
- using next_type = typename registerMdModuleNotification<CallParameter...>::type;
- //! The type of the MdModuleNotification
- using type = MdModuleNotification<CurrentCallParameter, next_type>;
+ using next_type = typename BuildMDModulesNotifier<CallParameter...>::type;
+ //! The type of the MDModulesNotifier
+ using type = MDModulesNotifier<CurrentCallParameter, next_type>;
};
} // namespace gmx
*/
/*! \libinternal \file
* \brief
- * Declares gmx::MdModulesNotifier.
+ * Declares gmx::MDModulesNotifiers.
*
* \author Christian Blau <blau@kth.se>
* \inlibraryapi
class LocalAtomSetManager;
class IndexGroupsAndNames;
class SeparatePmeRanksPermitted;
-struct MdModulesCheckpointReadingDataOnMaster;
-struct MdModulesCheckpointReadingBroadcast;
-struct MdModulesWriteCheckpointData;
+struct MDModulesCheckpointReadingDataOnMaster;
+struct MDModulesCheckpointReadingBroadcast;
+struct MDModulesWriteCheckpointData;
/*! \libinternal \brief Check if module outputs energy to a specific field.
*
* Ensures that energy is output for this module.
*/
-struct MdModulesEnergyOutputToDensityFittingRequestChecker
+struct MDModulesEnergyOutputToDensityFittingRequestChecker
{
//! Trigger output to density fitting energy field
bool energyOutputToDensityFitting_ = false;
};
/*! \libinternal
- * \brief Collection of callbacks to MDModules at differnt run-times.
+ * \brief Group of notifers to organize that MDModules
+ * can receive callbacks they subscribe to.
*
- * MDModules use members of this struct to sign up for callback functionality.
- *
- * The members of the struct represent callbacks at these run-times:
- *
- * When pre-processing the simulation data
- * When reading and writing check-pointing data
- * When setting up simulation after reading in the tpr file
+ * MDModules use members of this struct to subscribe to notifications
+ * of particular events. When the event occurs, the callback provided
+ * by a particular MDModule will be passed a parameter of the
+ * particular type they are interested in.
*
+ * Typically, during the setup phase, modules subscribe to notifiers
+ * that interest them by passing callbacks that expect a single parameter
+ * that describes the event. These are stored for later use. See the
+ * sequence diagram that follows:
\msc
- wordwraparcs=true,
- hscale="2";
-
- runner [label="runner:\nMdrunner"],
- CallParameter [label = "eventA:\nCallParameter"],
- MOD [label = "mdModules_:\nMdModules"],
- ModuleA [label="moduleA"],
- ModuleB [label="moduleB"],
- MdModuleNotification [label="notifier_:\nMdModuleNotification"];
-
- MOD box MdModuleNotification [label = "mdModules_ owns notifier_ and moduleA/B"];
- MOD =>> ModuleA [label="instantiates(notifier_)"];
- ModuleA =>> MdModuleNotification [label="subscribe(otherfunc)"];
- ModuleA =>> MOD;
- MOD =>> ModuleB [label="instantiates(notifier_)"];
- ModuleB =>> MdModuleNotification [label="subscribe(func)"];
- ModuleB =>> MOD;
- runner =>> CallParameter [label="instantiate"];
- CallParameter =>> runner ;
- runner =>> MOD [label="notify(eventA)"];
- MOD =>> MdModuleNotification [label="notify(eventA)"];
- MdModuleNotification =>> ModuleA [label="notify(eventA)"];
- ModuleA -> ModuleA [label="func(eventA)"];
- MdModuleNotification =>> ModuleB [label="notify(eventA)"];
- ModuleB -> ModuleB [label="otherfunc(eventA)"];
+wordwraparcs=true,
+hscale="2";
+
+modules [label = "mdModules:\nMDModules"],
+notifiers [label="notifiers\nMDModulesNotifiers"],
+notifier [label="exampleNotifier:\nBuildMDModulesNotifier\n<EventX, EventY>::type"],
+moduleA [label="moduleA"],
+moduleB [label="moduleB"],
+moduleC [label="moduleC"];
+
+modules box moduleC [label = "mdModules creates and owns moduleA, moduleB, and moduleC"];
+modules =>> notifiers [label="creates"];
+notifiers =>> notifier [label="creates"];
+notifier =>> notifiers [label="returns"];
+notifiers =>> modules [label="returns"];
+
+modules =>> moduleA [label="provides notifiers"];
+moduleA =>> moduleA [label="unpacks\nnotifiers.exampleNotifier"];
+moduleA =>> notifier [label="subscribes with\ncallback(EventX&)"];
+notifier =>> notifier [label="records subscription\nto EventX"];
+moduleA =>> notifier [label="subscribes with\ncallback(EventY&)"];
+notifier =>> notifier [label="records subscription\nto EventY"];
+moduleA =>> modules [label="returns"];
+
+modules =>> moduleB [label="provides notifiers"];
+moduleB =>> moduleB [label="unpacks\nnotifiers.exampleNotifier"];
+moduleA =>> notifier [label="subscribes with\ncallback(EventY&)"];
+notifier =>> notifier [label="records subscription\nto EventY"];
+moduleB =>> modules [label="returns"];
+
+modules =>> moduleC [label="provides notifiers"];
+moduleC =>> moduleC [label="unpacks and keeps\nnotifiers.exampleNotifier"];
+moduleC =>> modules [label="returns"];
\endmsc
+
+ * When the event occurs later on, the stored callbacks are used to
+ * allow the modules to react. See the following sequence diagram,
+ * which assumes that exampleNotifier was configured as in the
+ * previous sequence diagram.
+
+ \msc
+wordwraparcs=true,
+hscale="2";
+
+moduleC [label="moduleC"],
+notifier [label="exampleNotifier:\nBuildMDModulesNotifier\n<EventX, EventY>::type"],
+moduleA [label="moduleA"],
+moduleB [label="moduleB"];
+
+moduleC box moduleB [label = "Later, when ModuleC is doing work"];
+moduleC =>> moduleC [label="generates EventX"];
+moduleC =>> moduleC [label="generates EventY"];
+moduleC =>> notifier [label="calls notify(eventX)"];
+notifier =>> moduleA [label="calls callback(eventX)"];
+moduleA =>> moduleA [label="reacts to eventX"];
+moduleA =>> notifier [label="returns"];
+
+notifier =>> moduleC [label="returns"];
+moduleC =>> notifier [label="calls notify(eventY)"];
+notifier =>> moduleA [label="calls callback(eventY)"];
+moduleA =>> moduleA [label="reacts to eventY"];
+moduleA =>> notifier [label="returns"];
+notifier =>> moduleB [label="calls callback(eventY)"];
+moduleB =>> moduleB [label="reacts to eventY"];
+moduleB =>> notifier [label="returns"];
+notifier =>> moduleC [label="returns"];
+ \endmsc
*
- * The template arguments to the members of this struct directly reflect
- * the callback function signature. Arguments passed as pointers are always
- * meant to be modified, but never meant to be stored (in line with the policy
+ * The template arguments to the members of this struct are the
+ * parameters passed to the callback functions, one type per
+ * callback. Arguments passed as pointers are always meant to be
+ * modified, but never meant to be stored (in line with the policy
* everywhere else).
+ *
*/
-struct MdModulesNotifier
+struct MDModulesNotifiers
{
- /*! \brief Pre-processing callback functions.
+ /*! \brief Handles subscribing and calling pre-processing callback functions.
*
* EnergyCalculationFrequencyErrors* allows modules to check if they match
* their required calculation frequency
* KeyValueTreeObjectBuilder enables writing of module internal data to
* .tpr files.
*/
- registerMdModuleNotification<EnergyCalculationFrequencyErrors*, IndexGroupsAndNames, KeyValueTreeObjectBuilder>::type preProcessingNotifications_;
+ BuildMDModulesNotifier<EnergyCalculationFrequencyErrors*, IndexGroupsAndNames, KeyValueTreeObjectBuilder>::type preProcessingNotifier_;
- /*! \brief Checkpointing callback functions.
+ /*! \brief Handles subscribing and calling checkpointing callback functions.
*
- * MdModulesCheckpointReadingDataOnMaster provides modules with their
+ * MDModulesCheckpointReadingDataOnMaster provides modules with their
* checkpointed data on the master
* node and checkpoint file version
- * MdModulesCheckpointReadingBroadcast provides modules with a communicator
+ * MDModulesCheckpointReadingBroadcast provides modules with a communicator
* and the checkpoint file version to
* distribute their data
- * MdModulesWriteCheckpointData provides the modules with a key-value-tree
+ * MDModulesWriteCheckpointData provides the modules with a key-value-tree
* builder to store their checkpoint data and
* the checkpoint file version
*/
- registerMdModuleNotification<MdModulesCheckpointReadingDataOnMaster,
- MdModulesCheckpointReadingBroadcast,
- MdModulesWriteCheckpointData>::type checkpointingNotifications_;
+ BuildMDModulesNotifier<MDModulesCheckpointReadingDataOnMaster, MDModulesCheckpointReadingBroadcast, MDModulesWriteCheckpointData>::type
+ checkpointingNotifier_;
- /*! \brief Callbacks during simulation setup.
+ /*! \brief Handles subscribing and calling callbacks during simulation setup.
*
* const KeyValueTreeObject& provides modules with the internal data they
* wrote to .tpr files
* LocalAtomSetManager* enables modules to add atom indices to local atom sets
* to be managed
* const gmx_mtop_t& provides the topology of the system to the modules
- * MdModulesEnergyOutputToDensityFittingRequestChecker* enables modules to
+ * MDModulesEnergyOutputToDensityFittingRequestChecker* enables modules to
* report if they want to write their energy output
* to the density fitting field in the energy files
* SeparatePmeRanksPermitted* enables modules to report if they want
* const t_commrec& provides a communicator to the modules during simulation
* setup
*/
- registerMdModuleNotification<const KeyValueTreeObject&,
- LocalAtomSetManager*,
- const gmx_mtop_t&,
- MdModulesEnergyOutputToDensityFittingRequestChecker*,
- SeparatePmeRanksPermitted*,
- const PbcType&,
- const SimulationTimeStep&,
- const t_commrec&>::type simulationSetupNotifications_;
+ BuildMDModulesNotifier<const KeyValueTreeObject&,
+ LocalAtomSetManager*,
+ const gmx_mtop_t&,
+ MDModulesEnergyOutputToDensityFittingRequestChecker*,
+ SeparatePmeRanksPermitted*,
+ const PbcType&,
+ const SimulationTimeStep&,
+ const t_commrec&>::type simulationSetupNotifier_;
};
} // namespace gmx
*/
/*! \internal \file
* \brief
- * Tests MdModuleNotification
+ * Tests MDModulesNotifier
*
* \author Christian Blau <blau@kth.se>
* \ingroup module_utility
bool notifiedEventA_ = false;
};
-TEST(MDModuleNotificationTest, addConsumer)
+TEST(MDModulesNotifierTest, AddConsumer)
{
- registerMdModuleNotification<EventA>::type notifications;
- EventACallee eventACallee;
+ BuildMDModulesNotifier<EventA>::type notifier;
+ EventACallee eventACallee;
EXPECT_FALSE(eventACallee.notifiedEventA());
- notifications.subscribe([&eventACallee](EventA eventA) { eventACallee.callback(eventA); });
- notifications.notify(EventA{});
+ notifier.subscribe([&eventACallee](EventA eventA) { eventACallee.callback(eventA); });
+ notifier.notify(EventA{});
EXPECT_TRUE(eventACallee.notifiedEventA());
}
-TEST(MDModuleNotificationTest, addConsumerWithPointerParameter)
+TEST(MDModulesNotifierTest, AddConsumerWithPointerParameter)
{
- registerMdModuleNotification<EventB*>::type notifications;
- EventBCallee eventBCallee;
+ BuildMDModulesNotifier<EventB*>::type notifier;
+ EventBCallee eventBCallee;
EXPECT_FALSE(eventBCallee.notifiedEventB());
- notifications.subscribe([&eventBCallee](EventB* eventB) { eventBCallee.callback(eventB); });
+ notifier.subscribe([&eventBCallee](EventB* eventB) { eventBCallee.callback(eventB); });
EventB* eventBPointer = nullptr;
- notifications.notify(eventBPointer);
+ notifier.notify(eventBPointer);
EXPECT_TRUE(eventBCallee.notifiedEventB());
}
-TEST(MDModuleNotificationTest, addTwoDifferentConsumers)
+TEST(MDModulesNotifierTest, AddTwoDifferentConsumers)
{
- registerMdModuleNotification<EventA, EventB*>::type notifications;
- EventBCallee eventBCallee;
- EventACallee eventACallee;
+ BuildMDModulesNotifier<EventA, EventB*>::type notifier;
+ EventBCallee eventBCallee;
+ EventACallee eventACallee;
EXPECT_FALSE(eventACallee.notifiedEventA());
EXPECT_FALSE(eventBCallee.notifiedEventB());
- notifications.subscribe([&eventBCallee](EventB* eventB) { eventBCallee.callback(eventB); });
- notifications.subscribe([&eventACallee](EventA eventA) { eventACallee.callback(eventA); });
+ notifier.subscribe([&eventBCallee](EventB* eventB) { eventBCallee.callback(eventB); });
+ notifier.subscribe([&eventACallee](EventA eventA) { eventACallee.callback(eventA); });
EventB* eventBPointer = nullptr;
- notifications.notify(eventBPointer);
+ notifier.notify(eventBPointer);
EXPECT_FALSE(eventACallee.notifiedEventA());
EXPECT_TRUE(eventBCallee.notifiedEventB());
- notifications.notify(EventA{});
+ notifier.notify(EventA{});
EXPECT_TRUE(eventACallee.notifiedEventA());
EXPECT_TRUE(eventBCallee.notifiedEventB());
}
-TEST(MDModuleNotificationTest, consumerOfTwoResources)
+TEST(MDModulesNotifierTest, AddConsumerOfTwoResources)
{
- registerMdModuleNotification<EventA, EventB*>::type notifications;
+ BuildMDModulesNotifier<EventA, EventB*>::type notifier;
EventAandBCallee callee;
EXPECT_FALSE(callee.notifiedEventA());
// requires a template parameter here, because call is ambiguous otherwise
- notifications.subscribe([&callee](EventA msg) { callee.callback(msg); });
- notifications.subscribe([&callee](EventB* msg) { callee.notify(msg); });
+ notifier.subscribe([&callee](EventA msg) { callee.callback(msg); });
+ notifier.subscribe([&callee](EventB* msg) { callee.notify(msg); });
EventB* eventBp = nullptr;
- notifications.notify(eventBp);
+ notifier.notify(eventBp);
EXPECT_FALSE(callee.notifiedEventA());
EXPECT_TRUE(callee.notifiedEventB());
- notifications.notify(EventA{});
+ notifier.notify(EventA{});
EXPECT_TRUE(callee.notifiedEventA());
EXPECT_TRUE(callee.notifiedEventB());