builder->add<StatePropagatorData::Element>();
if (legacySimulatorData_->inputrec->etc == TemperatureCoupling::VRescale)
{
- builder->add<VRescaleThermostat>(-1, VRescaleThermostatUseFullStepKE::No);
+ builder->add<VRescaleThermostat>(-1,
+ VRescaleThermostatUseFullStepKE::No,
+ PropagatorTag("LeapFrogPropagator"));
}
- builder->add<Propagator<IntegrationStep::LeapFrog>>(legacySimulatorData_->inputrec->delta_t,
- RegisterWithThermostat::True,
- RegisterWithBarostat::True);
+ builder->add<Propagator<IntegrationStep::LeapFrog>>(PropagatorTag("LeapFrogPropagator"),
+ legacySimulatorData_->inputrec->delta_t);
if (legacySimulatorData_->constr)
{
builder->add<ConstraintsElement<ConstraintVariable::Positions>>();
builder->add<EnergyData::Element>();
if (legacySimulatorData_->inputrec->epc == PressureCoupling::ParrinelloRahman)
{
- builder->add<ParrinelloRahmanBarostat>(-1);
+ builder->add<ParrinelloRahmanBarostat>(-1, PropagatorTag("LeapFrogPropagator"));
}
}
}
time step of PositionsOnly.
The propagators also allow to implement temperature and pressure coupling
-schemes by offering (templated) scaling of the velocities.
+schemes by offering (templated) scaling of the velocities. In order to
+link temperature / pressure coupling objects to the propagators, the
+propagator objects have a tag (of strong type `PropagatorTag`). The
+temperature and pressure coupling objects can then connect to the
+matching propagator by comparing their target tag to the different
+propagators. Giving the propagators their tags and informing the
+temperature and pressure coupling algorithms which propagator they are
+connecting to is in the responsibility of the simulation algorithm
+builder.
#### `CompositeSimulatorElement`
The composite simulator element takes a list of elements and implements
if (legacySimulatorData_->inputrec->etc == TemperatureCoupling::VRescale
|| legacySimulatorData_->inputrec->etc == TemperatureCoupling::Berendsen)
{
- builder->add<VelocityScalingTemperatureCoupling>(
- -1, UseFullStepKE::No, ReportPreviousStepConservedEnergy::No);
+ builder->add<VelocityScalingTemperatureCoupling>(-1,
+ UseFullStepKE::No,
+ ReportPreviousStepConservedEnergy::No,
+ PropagatorTag("LeapFrogPropagator"));
}
- builder->add<Propagator<IntegrationStep::LeapFrog>>(legacySimulatorData_->inputrec->delta_t,
- RegisterWithThermostat::True,
- RegisterWithBarostat::True);
+ builder->add<Propagator<IntegrationStep::LeapFrog>>(
+ PropagatorTag("LeapFrogPropagator"), legacySimulatorData_->inputrec->delta_t);
if (legacySimulatorData_->constr)
{
builder->add<ConstraintsElement<ConstraintVariable::Positions>>();
builder->add<EnergyData::Element>();
if (legacySimulatorData_->inputrec->epc == PressureCoupling::ParrinelloRahman)
{
- builder->add<ParrinelloRahmanBarostat>(-1);
+ builder->add<ParrinelloRahmanBarostat>(-1, PropagatorTag("LeapFrogPropagator"));
}
}
else if (legacySimulatorData_->inputrec->eI == IntegrationAlgorithm::VV)
// The velocity verlet integration algorithm
builder->add<ForceElement>();
builder->add<Propagator<IntegrationStep::VelocitiesOnly>>(
- 0.5 * legacySimulatorData_->inputrec->delta_t,
- RegisterWithThermostat::False,
- RegisterWithBarostat::True);
+ PropagatorTag("VelocityHalfStep"), 0.5 * legacySimulatorData_->inputrec->delta_t);
if (legacySimulatorData_->constr)
{
builder->add<ConstraintsElement<ConstraintVariable::Velocities>>();
|| legacySimulatorData_->inputrec->etc == TemperatureCoupling::Berendsen)
{
builder->add<VelocityScalingTemperatureCoupling>(
- 0, UseFullStepKE::Yes, ReportPreviousStepConservedEnergy::Yes);
+ 0,
+ UseFullStepKE::Yes,
+ ReportPreviousStepConservedEnergy::Yes,
+ PropagatorTag("VelocityHalfAndPositionFullStep"));
}
builder->add<Propagator<IntegrationStep::VelocityVerletPositionsAndVelocities>>(
- legacySimulatorData_->inputrec->delta_t,
- RegisterWithThermostat::True,
- RegisterWithBarostat::False);
+ PropagatorTag("VelocityHalfAndPositionFullStep"), legacySimulatorData_->inputrec->delta_t);
if (legacySimulatorData_->constr)
{
builder->add<ConstraintsElement<ConstraintVariable::Positions>>();
builder->add<EnergyData::Element>();
if (legacySimulatorData_->inputrec->epc == PressureCoupling::ParrinelloRahman)
{
- builder->add<ParrinelloRahmanBarostat>(-1);
+ builder->add<ParrinelloRahmanBarostat>(-1, PropagatorTag("VelocityHalfStep"));
}
}
else
/*
* 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.
//! Generic callback to the propagator
typedef std::function<void(Step)> PropagatorCallback;
+/*! \internal
+ * \brief Strong type used to name propagators
+ */
+struct PropagatorTag
+{
+ //! Explicit constructor
+ explicit PropagatorTag(std::string_view name) : name_(name) {}
+ //! Can be used as string
+ operator const std::string&() const { return name_; }
+ //! Equality operator
+ bool operator==(const PropagatorTag& other) const { return name_ == other.name_; }
+ //! Inequality operator
+ bool operator!=(const PropagatorTag& other) const { return name_ != other.name_; }
+
+private:
+ //! The name of the propagator
+ const std::string name_;
+};
+
/*! \internal
* \brief Information needed to connect a propagator to a thermostat
*/
std::function<ArrayRef<real>()> getViewOnVelocityScaling;
//! Function variable for callback.
std::function<PropagatorCallback()> getVelocityScalingCallback;
+ //! The tag of the creating propagator
+ PropagatorTag tag;
};
/*! \internal
std::function<ArrayRef<rvec>()> getViewOnPRScalingMatrix;
//! Function variable for callback.
std::function<PropagatorCallback()> getPRScalingCallback;
+ //! The tag of the creating propagator
+ PropagatorTag tag;
};
//! /}
energyData->setParrinelloRahamnBarostat(this);
}
-void ParrinelloRahmanBarostat::connectWithPropagator(const PropagatorBarostatConnection& connectionData)
+void ParrinelloRahmanBarostat::connectWithMatchingPropagator(const PropagatorBarostatConnection& connectionData,
+ const PropagatorTag& propagatorTag)
{
- scalingTensor_ = connectionData.getViewOnPRScalingMatrix();
- propagatorCallback_ = connectionData.getPRScalingCallback();
+ if (connectionData.tag == propagatorTag)
+ {
+ scalingTensor_ = connectionData.getViewOnPRScalingMatrix();
+ propagatorCallback_ = connectionData.getPRScalingCallback();
+ }
}
void ParrinelloRahmanBarostat::scheduleTask(Step step,
throw MissingElementConnectionError(
"Parrinello-Rahman barostat was not connected to a propagator.\n"
"Connection to a propagator element is needed to scale the velocities.\n"
- "Use connectWithPropagator(...) before building the ModularSimulatorAlgorithm "
+ "Use connectWithMatchingPropagator(...) before building the "
+ "ModularSimulatorAlgorithm "
"object.");
}
EnergyData* energyData,
FreeEnergyPerturbationData gmx_unused* freeEnergyPerturbationData,
GlobalCommunicationHelper gmx_unused* globalCommunicationHelper,
- int offset)
+ int offset,
+ const PropagatorTag& propagatorTag)
{
auto* element = builderHelper->storeElement(std::make_unique<ParrinelloRahmanBarostat>(
legacySimulatorData->inputrec->nstpcouple,
legacySimulatorData->inputrec,
legacySimulatorData->mdAtoms));
auto* barostat = static_cast<ParrinelloRahmanBarostat*>(element);
- builderHelper->registerBarostat([barostat](const PropagatorBarostatConnection& connection) {
- barostat->connectWithPropagator(connection);
+ builderHelper->registerBarostat([barostat, propagatorTag](const PropagatorBarostatConnection& connection) {
+ barostat->connectWithMatchingPropagator(connection, propagatorTag);
});
return element;
}
/*
* 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.
[[nodiscard]] real conservedEnergyContribution() const;
//! Connect this to propagator
- void connectWithPropagator(const PropagatorBarostatConnection& connectionData);
+ void connectWithMatchingPropagator(const PropagatorBarostatConnection& connectionData,
+ const PropagatorTag& propagatorTag);
//! ICheckpointHelperClient write checkpoint implementation
void saveCheckpointState(std::optional<WriteCheckpointData> checkpointData, const t_commrec* cr) override;
* \param energyData Pointer to the \c EnergyData object
* \param freeEnergyPerturbationData Pointer to the \c FreeEnergyPerturbationData object
* \param globalCommunicationHelper Pointer to the \c GlobalCommunicationHelper object
+ * \param propagatorTag Tag of the propagator to connect to
* \param offset The step offset at which the barostat is applied
*
* \return Pointer to the element to be added. Element needs to have been stored using \c storeElement
*/
- static ISimulatorElement* getElementPointerImpl(LegacySimulatorData* legacySimulatorData,
- ModularSimulatorAlgorithmBuilderHelper* builderHelper,
- StatePropagatorData* statePropagatorData,
- EnergyData* energyData,
- FreeEnergyPerturbationData* freeEnergyPerturbationData,
- GlobalCommunicationHelper* globalCommunicationHelper,
- int offset);
+ static ISimulatorElement*
+ getElementPointerImpl(LegacySimulatorData* legacySimulatorData,
+ ModularSimulatorAlgorithmBuilderHelper* builderHelper,
+ StatePropagatorData* statePropagatorData,
+ EnergyData* energyData,
+ FreeEnergyPerturbationData gmx_unused* freeEnergyPerturbationData,
+ GlobalCommunicationHelper gmx_unused* globalCommunicationHelper,
+ int offset,
+ const PropagatorTag& propagatorTag);
private:
//! The frequency at which the barostat is applied
/*
* 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.
EnergyData gmx_unused* energyData,
FreeEnergyPerturbationData gmx_unused* freeEnergyPerturbationData,
GlobalCommunicationHelper gmx_unused* globalCommunicationHelper,
- double timestep,
- RegisterWithThermostat registerWithThermostat,
- RegisterWithBarostat registerWithBarostat)
+ const PropagatorTag& propagatorTag,
+ double timestep)
{
- auto* element = builderHelper->storeElement(std::make_unique<Propagator<algorithm>>(
+ auto* element = builderHelper->storeElement(std::make_unique<Propagator<algorithm>>(
timestep, statePropagatorData, legacySimulatorData->mdAtoms, legacySimulatorData->wcycle));
- if (registerWithThermostat == RegisterWithThermostat::True)
- {
- auto* propagator = static_cast<Propagator<algorithm>*>(element);
- builderHelper->registerWithThermostat(
- { [propagator](int num) { propagator->setNumVelocityScalingVariables(num); },
- [propagator]() { return propagator->viewOnVelocityScaling(); },
- [propagator]() { return propagator->velocityScalingCallback(); } });
- }
- if (registerWithBarostat == RegisterWithBarostat::True)
- {
- auto* propagator = static_cast<Propagator<algorithm>*>(element);
- builderHelper->registerWithBarostat(
- { [propagator]() { return propagator->viewOnPRScalingMatrix(); },
- [propagator]() { return propagator->prScalingCallback(); } });
- }
+ auto* propagator = static_cast<Propagator<algorithm>*>(element);
+ builderHelper->registerWithThermostat(
+ { [propagator](int num) { propagator->setNumVelocityScalingVariables(num); },
+ [propagator]() { return propagator->viewOnVelocityScaling(); },
+ [propagator]() { return propagator->velocityScalingCallback(); },
+ propagatorTag });
+ builderHelper->registerWithBarostat(
+ { [propagator]() { return propagator->viewOnPRScalingMatrix(); },
+ [propagator]() { return propagator->prScalingCallback(); },
+ propagatorTag });
return element;
}
/*
* 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.
//! \addtogroup module_modularsimulator
//! \{
-//! Whether built propagator should be registered with thermostat
-enum class RegisterWithThermostat
-{
- True,
- False
-};
-//! Whether built propagator should be registered with barostat
-enum class RegisterWithBarostat
-{
- True,
- False
-};
-
/*! \brief The different integration types we know about
*
* PositionsOnly:
* \param energyData Pointer to the \c EnergyData object
* \param freeEnergyPerturbationData Pointer to the \c FreeEnergyPerturbationData object
* \param globalCommunicationHelper Pointer to the \c GlobalCommunicationHelper object
+ * \param propagatorTag The name of the propagator to simplify connection
* \param timestep The time step the propagator uses
- * \param registerWithThermostat Whether this propagator should be registered with the thermostat
- * \param registerWithBarostat Whether this propagator should be registered with the barostat
*
* \return Pointer to the element to be added. Element needs to have been stored using \c storeElement
*/
EnergyData* energyData,
FreeEnergyPerturbationData* freeEnergyPerturbationData,
GlobalCommunicationHelper* globalCommunicationHelper,
- double timestep,
- RegisterWithThermostat registerWithThermostat,
- RegisterWithBarostat registerWithBarostat);
+ const PropagatorTag& propagatorTag,
+ double timestep);
private:
//! The actual propagation
}
}
-void VelocityScalingTemperatureCoupling::connectWithPropagator(const PropagatorThermostatConnection& connectionData)
+void VelocityScalingTemperatureCoupling::connectWithMatchingPropagator(const PropagatorThermostatConnection& connectionData,
+ const PropagatorTag& propagatorTag)
{
- temperatureCouplingImpl_->connectWithPropagator(connectionData, numTemperatureGroups_);
- propagatorCallback_ = connectionData.getVelocityScalingCallback();
+ if (connectionData.tag == propagatorTag)
+ {
+ temperatureCouplingImpl_->connectWithPropagator(connectionData, numTemperatureGroups_);
+ propagatorCallback_ = connectionData.getVelocityScalingCallback();
+ }
}
void VelocityScalingTemperatureCoupling::elementSetup()
throw MissingElementConnectionError(
"Velocity scaling temperature coupling was not connected to a propagator.\n"
"Connection to a propagator element is needed to scale the velocities.\n"
- "Use connectWithPropagator(...) before building the ModularSimulatorAlgorithm "
+ "Use connectWithMatchingPropagator(...) before building the "
+ "ModularSimulatorAlgorithm "
"object.");
}
}
LegacySimulatorData* legacySimulatorData,
ModularSimulatorAlgorithmBuilderHelper* builderHelper,
StatePropagatorData gmx_unused* statePropagatorData,
- EnergyData gmx_unused* energyData,
+ EnergyData* energyData,
FreeEnergyPerturbationData gmx_unused* freeEnergyPerturbationData,
GlobalCommunicationHelper gmx_unused* globalCommunicationHelper,
int offset,
UseFullStepKE useFullStepKE,
- ReportPreviousStepConservedEnergy reportPreviousStepConservedEnergy)
+ ReportPreviousStepConservedEnergy reportPreviousStepConservedEnergy,
+ const PropagatorTag& propagatorTag)
{
// Element is now owned by the caller of this method, who will handle lifetime (see ModularSimulatorAlgorithm)
auto* element = builderHelper->storeElement(std::make_unique<VelocityScalingTemperatureCoupling>(
legacySimulatorData->inputrec->etc));
auto* thermostat = static_cast<VelocityScalingTemperatureCoupling*>(element);
// Capturing pointer is safe because lifetime is handled by caller
- builderHelper->registerThermostat([thermostat](const PropagatorThermostatConnection& connection) {
- thermostat->connectWithPropagator(connection);
- });
+ builderHelper->registerThermostat(
+ [thermostat, propagatorTag](const PropagatorThermostatConnection& connection) {
+ thermostat->connectWithMatchingPropagator(connection, propagatorTag);
+ });
return element;
}
[[nodiscard]] real conservedEnergyContribution() const;
//! Connect this to propagator
- void connectWithPropagator(const PropagatorThermostatConnection& connectionData);
+ void connectWithMatchingPropagator(const PropagatorThermostatConnection& connectionData,
+ const PropagatorTag& propagatorTag);
//! ICheckpointHelperClient write checkpoint implementation
void saveCheckpointState(std::optional<WriteCheckpointData> checkpointData, const t_commrec* cr) override;
* \param energyData Pointer to the \c EnergyData object
* \param freeEnergyPerturbationData Pointer to the \c FreeEnergyPerturbationData object
* \param globalCommunicationHelper Pointer to the \c GlobalCommunicationHelper object
+ * \param propagatorTag Tag of the propagator to connect to
* \param offset The step offset at which the thermostat is applied
* \param useFullStepKE Whether full step or half step KE is used
* \param reportPreviousStepConservedEnergy Report the previous or the current step conserved energy
GlobalCommunicationHelper* globalCommunicationHelper,
int offset,
UseFullStepKE useFullStepKE,
- ReportPreviousStepConservedEnergy reportPreviousStepConservedEnergy);
+ ReportPreviousStepConservedEnergy reportPreviousStepConservedEnergy,
+ const PropagatorTag& propagatorTag);
private:
//! The frequency at which the thermostat is applied