The densityfitting code is activated by adding it to the MDModules.
Moved the MdModuleNotifications to mdrunutility to break cyclic module
dependencies between mdrun and applied_forces via MdModules and
DensityFittingModuleInfo.
Observe that this patch changes the default .mdp output. Updated
reference data accordingly. Note that the changes in .mdp output
lead to "check mdp file differences" warning in the regression tests.
refs #2283
Change-Id: I93c0dd85285cac3f9e94d2dfc7c7fcc434aa81db
During setup and simulation, modules receive required information like topologies
and local atom sets by subscribing to callback functions.
-To include a notification for your module,
+To include a notification for your module
-* Add the function signature for the callback function to the `notifier_type`
- in the MdModules class
+* Add the function signature for the callback function to the
+ `MdModulesNotifier` in `mdmodulenotification.h`,
```C++
- notifier_type = registerMdModuleNotification<...,
+ registerMdModulesNotification<...,
YourCallbackSignature,
...,
```
* Add the function you want to subscribe with in the builder,
`notifier->subscribe(yourFunction)`
-
+
* To subscribe class member functions of your module, you can use lambda expressions
```C++
- notifier->subscribe([modulePointer = yourModule.get()]
+ notifier->notifier_.subscribe([modulePointer = yourModule.get()]
(YourCallbackSignature argument){modulePointer(argument);});
```
```C++
YourCallbackSignature argument();
- mdModules_.notifier().notify(argument);
+ mdModules_.notifier().notifier_.notify(argument);
```
Storing non-mdp option module parameters
#include "densityfitting.h"
+#include "gromacs/mdrunutility/mdmodulenotification.h"
#include "gromacs/mdtypes/imdmodule.h"
#include "densityfittingforceprovider.h"
class DensityFitting final : public IMDModule
{
public:
- DensityFitting() = default;
+ /*! \brief Construct the density fitting module.
+ * Allow the module to subscribe to notifications from MdModules
+ */
+ explicit DensityFitting(MdModulesNotifier * /*notifier*/){}
//! From IMDModule; this class provides the mdpOptions itself
IMdpOptionProvider *mdpOptionProvider() override { return &densityFittingOptions_; }
} // namespace
-std::unique_ptr<IMDModule> DensityFittingModuleInfo::create()
+std::unique_ptr<IMDModule> DensityFittingModuleInfo::create(MdModulesNotifier * notifier)
{
- return std::unique_ptr<IMDModule>(new DensityFitting());
+ return std::make_unique<DensityFitting>(notifier);
}
const std::string DensityFittingModuleInfo::name_ = "density-guided-simulation";
{
class IMDModule;
+struct MdModulesNotifier;
/*! \libinternal \brief Information about the density fitting module.
*
* Fitting an all-atom structure into an experimental cryo-EM density map is a
* typical application.
*/
- static std::unique_ptr<IMDModule> create();
+ static std::unique_ptr<IMDModule> create(MdModulesNotifier * notifier);
//! The name of the module
static const std::string name_;
};
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(AppliedForcesUnitTest applied_forces-test
+ densityfitting.cpp
densityfittingoptions.cpp
densityfittingamplitudelookup.cpp
electricfield.cpp
#include "gromacs/gmxlib/network.h"
#include "gromacs/math/paddedvector.h"
#include "gromacs/math/vec.h"
+#include "gromacs/mdrunutility/mdmodulenotification.h"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/mdtypes/iforceprovider.h"
TEST(DensityFittingTest, ForceOnSingleOption)
{
- auto densityFittingModule(DensityFittingModuleInfo::create());
+ MdModulesNotifier notifier;
+ auto densityFittingModule(DensityFittingModuleInfo::create(¬ifier));
// Prepare MDP inputs
KeyValueTreeBuilder mdpValueBuilder;
#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdlib/vsite.h"
#include "gromacs/mdrun/mdmodules.h"
+#include "gromacs/mdrunutility/mdmodulenotification.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/nblist.h"
{
gmx::KeyValueTreeBuilder internalParameterBuilder;
- mdModules.notifier().notify(&internalParameterBuilder);
+ mdModules.notifier().notifier_.notify(&internalParameterBuilder);
ir->internalParameters = std::make_unique<gmx::KeyValueTreeObject>(internalParameterBuilder.build());
}
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/calc_verletbuf.h"
#include "gromacs/mdrun/mdmodules.h"
+#include "gromacs/mdrunutility/mdmodulenotification.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/pull_params.h"
void do_index(const char* mdparin, const char *ndx,
gmx_mtop_t *mtop,
bool bVerbose,
- const gmx::MDModules::notifier_type ¬ifier,
+ const gmx::MdModulesNotifier ¬ifier,
t_inputrec *ir,
warninp_t wi)
{
gmx::IndexGroupsAndNames defaultIndexGroupsAndNames(
*defaultIndexGroups, gmx::arrayRefFromArray(gnames, defaultIndexGroups->nr));
- notifier.notify(defaultIndexGroupsAndNames);
+ notifier.notifier_.notify(defaultIndexGroupsAndNames);
auto accelerations = gmx::splitString(is->acc);
auto accelerationGroupNames = gmx::splitString(is->accgrps);
#include "gromacs/fileio/readinp.h"
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdrun/mdmodules.h"
#include "gromacs/utility/real.h"
namespace gmx
{
class MDModules;
+struct MdModulesNotifier;
}
struct gmx_mtop_t;
const char *ndx,
gmx_mtop_t *mtop,
bool bVerbose,
- const gmx::MDModules::notifier_type ¬ifier,
+ const gmx::MdModulesNotifier ¬ifier,
t_inputrec *ir,
warninp_t wi);
/* Read the index file and assign grp numbers to atoms.
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 1.2 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 3.7 7.5 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 3.7 2 6.5 1
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
electric-field-x = 0 0 0 0
electric-field-y = 0 0 0 0
electric-field-z = 0 0 0 0
+density-guided-simulation-active = false
</String>
</ReferenceData>
#include <memory>
+#include "gromacs/applied_forces/densityfitting.h"
#include "gromacs/applied_forces/electricfield.h"
#include "gromacs/imd/imd.h"
+#include "gromacs/mdrunutility/mdmodulenotification.h"
#include "gromacs/mdtypes/iforceprovider.h"
#include "gromacs/mdtypes/imdmodule.h"
#include "gromacs/mdtypes/imdoutputprovider.h"
public:
Impl()
- : field_(createElectricFieldModule()),
+ : densityFitting_(DensityFittingModuleInfo::create(¬ifier_)),
+ field_(createElectricFieldModule()),
imd_(createInteractiveMolecularDynamicsModule()),
swapCoordinates_(createSwapCoordinatesModule())
{
// Create a section for applied-forces modules
auto appliedForcesOptions = options->addSection(OptionSection("applied-forces"));
field_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions);
+ densityFitting_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions);
// In future, other sections would also go here.
}
bool bAppendFiles, const gmx_output_env_t *oenv) override
{
field_->outputProvider()->initOutput(fplog, nfile, fnm, bAppendFiles, oenv);
+ densityFitting_->outputProvider()->initOutput(fplog, nfile, fnm, bAppendFiles, oenv);
}
void finishOutput() override
{
field_->outputProvider()->finishOutput();
+ densityFitting_->outputProvider()->finishOutput();
}
+ std::unique_ptr<IMDModule> densityFitting_;
std::unique_ptr<IMDModule> field_;
std::unique_ptr<ForceProviders> forceProviders_;
std::unique_ptr<IMDModule> imd_;
std::vector< std::shared_ptr<IMDModule> > modules_;
//! Manages resources and notifies the MD modules when available
- MDModules::notifier_type notifier_;
+ MdModulesNotifier notifier_;
};
MDModules::MDModules() : impl_(new Impl)
{
auto appliedForcesScope = rules->scopedTransform("/applied-forces");
impl_->field_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules());
+ impl_->densityFitting_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules());
}
void MDModules::buildMdpOutput(KeyValueTreeObjectBuilder *builder)
{
impl_->field_->mdpOptionProvider()->buildMdpOutput(builder);
+ impl_->densityFitting_->mdpOptionProvider()->buildMdpOutput(builder);
}
void MDModules::assignOptionsToModules(const KeyValueTreeObject ¶ms,
"Force providers initialized multiple times");
impl_->forceProviders_ = std::make_unique<ForceProviders>();
impl_->field_->initForceProviders(impl_->forceProviders_.get());
+ impl_->densityFitting_->initForceProviders(impl_->forceProviders_.get());
for (auto && module : impl_->modules_)
{
module->initForceProviders(impl_->forceProviders_.get());
impl_->modules_.emplace_back(std::move(module));
}
-const MDModules::notifier_type &MDModules::notifier()
+const MdModulesNotifier &MDModules::notifier()
{
return impl_->notifier_;
}
#ifndef GMX_MDRUN_MDMODULES_H
#define GMX_MDRUN_MDMODULES_H
-#include "gromacs/mdrun/mdmodulenotification.h"
#include "gromacs/utility/classhelpers.h"
struct ForceProviders;
class KeyValueTreeObject;
class IKeyValueTreeErrorHandler;
class IKeyValueTreeTransformRules;
-class IMDOutputProvider;
-class KeyValueTreeObject;
-class KeyValueTreeBuilder;
class IMDModule;
-class LocalAtomSetManager;
-class IndexGroupsAndNames;
-
-/*! \libinternal \brief
- * \brief Signals that the communication record is set up and provides this record.
- */
-struct CommunicationIsSetup
-{
- //! The communication record that is set up.
- const t_commrec &communicationRecord_;
-};
-
+class IMDOutputProvider;
+struct MdModulesNotifier;
/*! \libinternal \brief
* Manages the collection of all modules used for mdrun.
MDModules();
~MDModules();
- //! Register callback function types for MDModules
- using notifier_type = registerMdModuleNotification<
- CommunicationIsSetup,
- IndexGroupsAndNames,
- KeyValueTreeBuilder*,
- const KeyValueTreeObject &,
- LocalAtomSetManager *
- >::type;
-
/*! \brief
* Initializes a transform from mdp values to sectioned options.
*
* MDModules should not change after some point, we should move this
* to a builder class.
*/
- void add(std::shared_ptr<gmx::IMDModule> module);
+ void add(std::shared_ptr<IMDModule> module);
/*! \brief Return a handle to the callbacks.
*/
- const notifier_type ¬ifier();
+ const MdModulesNotifier ¬ifier();
private:
class Impl;
#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdlib/sighandler.h"
#include "gromacs/mdlib/stophandler.h"
-#include "gromacs/mdrun/mdmodulenotification.h"
#include "gromacs/mdrun/mdmodules.h"
#include "gromacs/mdrun/simulationcontext.h"
#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/logging.h"
+#include "gromacs/mdrunutility/mdmodulenotification.h"
#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdrunutility/printtime.h"
#include "gromacs/mdrunutility/threadaffinity.h"
// TODO: Error handling
mdModules_->assignOptionsToModules(*inputrec->params, nullptr);
+ const auto &mdModulesNotifier = mdModules_->notifier().notifier_;
+
if (inputrec->internalParameters != nullptr)
{
- mdModules_->notifier().notify(*inputrec->internalParameters);
+ mdModulesNotifier.notify(*inputrec->internalParameters);
}
if (fplog != nullptr)
useGpuForNonbonded || (emulateGpuNonbonded == EmulateGpuNonbonded::Yes), *hwinfo->cpuInfo);
LocalAtomSetManager atomSets;
-
if (PAR(cr) && !(EI_TPI(inputrec->eI) ||
inputrec->eI == eiNM))
{
&mtop, inputrec,
box, positionsFromStatePointer(globalState.get()),
&atomSets);
- mdModules_->notifier().notify(&atomSets);
+ mdModulesNotifier.notify(&atomSets);
// Note that local state still does not exist yet.
}
else
t_nrnb nrnb;
if (thisRankHasDuty(cr, DUTY_PP))
{
- mdModules_->notifier().notify(CommunicationIsSetup {*cr});
+ mdModulesNotifier.notify(*cr);
/* Initiate forcerecord */
fr = new t_forcerec;
fr->forceProviders = mdModules_->initForceProviders();
*
* \author Christian Blau <blau@kth.se>
* \inlibraryapi
- * \ingroup module_mdrun
+ * \ingroup module_mdrunutility
*/
-#ifndef GMX_MDRUN_MDMODULENOTIFICATION_H
-#define GMX_MDRUN_MDMODULENOTIFICATION_H
+#ifndef GMX_MDRUNUTILITY_MDMODULENOTIFICATION_H
+#define GMX_MDRUNUTILITY_MDMODULENOTIFICATION_H
#include <functional>
#include <vector>
using type = MdModuleNotification<CurrentCallParameter, next_type>;
};
+class KeyValueTreeObject;
+class KeyValueTreeBuilder;
+class LocalAtomSetManager;
+class IndexGroupsAndNames;
+
+struct MdModulesNotifier
+{
+//! Register callback function types for MdModule
+ registerMdModuleNotification<
+ const t_commrec &,
+ IndexGroupsAndNames,
+ KeyValueTreeBuilder *,
+ const KeyValueTreeObject &,
+ LocalAtomSetManager *>::type notifier_;
+};
+
} // namespace gmx
#endif
#include <gmock/gmock.h>
-#include "gromacs/mdrun/mdmodulenotification.h"
+#include "gromacs/mdrunutility/mdmodulenotification.h"
namespace gmx
{