{
// We allow this element to be added multiple times to the call list, but we only want one
// actual element built
- static thread_local ISimulatorElement* vvComputeGlobalsElement = nullptr;
- if (!builderHelper->elementIsStored(vvComputeGlobalsElement))
+ static const std::string key("vvComputeGlobalsElement");
+
+ const std::optional<std::any> cachedValue = builderHelper->getStoredValue(key);
+
+ if (cachedValue)
+ {
+ return std::any_cast<ISimulatorElement*>(cachedValue.value());
+ }
+ else
{
- vvComputeGlobalsElement = builderHelper->storeElement(
+ ISimulatorElement* vvComputeGlobalsElement = builderHelper->storeElement(
std::make_unique<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerlet>>(
statePropagatorData, energyData, freeEnergyPerturbationData,
globalCommunicationHelper->simulationSignals(),
vvComputeGlobalsElement);
globalCommunicationHelper->setCheckBondedInteractionsCallback(
castedElement->getCheckNumberOfBondedInteractionsCallback());
+ builderHelper->storeValue(key, vvComputeGlobalsElement);
+ return vvComputeGlobalsElement;
}
- return vvComputeGlobalsElement;
}
} // namespace gmx
* \param freeEnergyPerturbationData Pointer to the \c FreeEnergyPerturbationData object
* \param globalCommunicationHelper Pointer to the \c GlobalCommunicationHelper object
*
+ * \throws std::bad_any_cast on internal error in VelocityVerlet algorithm builder.
+ * \throws std::bad_alloc when out of memory.
+ *
* \return Pointer to the element to be added. Element needs to have been stored using \c storeElement
*/
static ISimulatorElement* getElementPointerImpl(LegacySimulatorData* legacySimulatorData,
return builder_->elementExists(element);
}
+std::optional<std::any> ModularSimulatorAlgorithmBuilderHelper::getStoredValue(const std::string& key) const
+{
+ const auto iter = values_.find(key);
+ if (iter == values_.end())
+ {
+ return std::nullopt;
+ }
+ else
+ {
+ return iter->second;
+ }
+}
+
void ModularSimulatorAlgorithmBuilderHelper::registerThermostat(
std::function<void(const PropagatorThermostatConnection&)> registrationFunction)
{
#ifndef GROMACS_MODULARSIMULATOR_SIMULATORALGORITHM_H
#define GROMACS_MODULARSIMULATOR_SIMULATORALGORITHM_H
+#include <any>
+#include <map>
+#include <optional>
#include <string>
+#include <typeinfo>
#include "gromacs/mdrun/isimulator.h"
#include "gromacs/mdtypes/state.h"
+#include "gromacs/utility/exceptions.h"
#include "checkpointhelper.h"
#include "domdechelper.h"
ISimulatorElement* storeElement(std::unique_ptr<ISimulatorElement> element);
//! Check if an element is stored in the ModularSimulatorAlgorithmBuilder
bool elementIsStored(const ISimulatorElement* element) const;
+ //! Set arbitrary data in the ModularSimulatorAlgorithmBuilder. Helpful for stateful elements.
+ template<typename ValueType>
+ void storeValue(const std::string& key, const ValueType& value);
+ //! Get previously stored data. Returns std::nullopt if key is not found.
+ std::optional<std::any> getStoredValue(const std::string& key) const;
//! Register a thermostat that accepts propagator registrations
void registerThermostat(std::function<void(const PropagatorThermostatConnection&)> registrationFunction);
//! Register a barostat that accepts propagator registrations
private:
//! Pointer to the associated ModularSimulatorAlgorithmBuilder
ModularSimulatorAlgorithmBuilder* builder_;
+ std::map<std::string, std::any> values_;
};
/*!\internal
checkpointHelperBuilder_.registerClient(castOrNull<ICheckpointHelperClient, Element>(element));
}
+
+template<typename ValueType>
+void ModularSimulatorAlgorithmBuilderHelper::storeValue(const std::string& key, const ValueType& value)
+{
+ values_[key] = std::any(value);
+}
+
+
} // namespace gmx
#endif // GROMACS_MODULARSIMULATOR_SIMULATORALGORITHM_H
class Builder;
private:
- //! Constant reference to the global topolgy
+ //! Constant reference to the global topology
const gmx_mtop_t& globalTopology_;
//! Pointer to the currently valid local topology
std::unique_ptr<gmx_localtop_t> localTopology_;