YourCallbackSignature argument();
mdModules_.notifier().notify(argument);
```
+
+Storing non-mdp option module parameters
+----------------------------------------
+
+Some mdrun modules want to store data that is non-mdp input, e.g., the result of
+computation during setup. Atom indices of index groups are one example:
+they are evaluated from strings during grompp time and stored as list of
+integers in the run input file. During the mdrun setup the information to
+evaluate the index groups is no longer available.
+
+To store parameters, subscribe to the `KeyValueTreeBuilder*` notification that
+provides a handle to a KeyValueTreeBuilder that allows adding own information to
+that tree.
+
+To restore parameters, subscribe to the `const KeyValueTreeObject &`
+notification that returns the tree that is build by the KeyValueTreeBuilder*.
* in this enumeration, and write code below that does the right thing
* according to the value of file_version.
*/
-enum tpxv {
+enum tpxv
+{
tpxv_ComputationalElectrophysiology = 96, /**< support for ion/water position swaps (computational electrophysiology) */
tpxv_Use64BitRandomSeed, /**< change ld_seed from int to int64_t */
tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, /**< potentials for supporting coarse-grained force fields */
tpxv_AcceleratedWeightHistogram, /**< sampling with accelerated weight histogram method (AWH) */
tpxv_RemoveImplicitSolvation, /**< removed support for implicit solvation */
tpxv_PullPrevStepCOMAsReference, /**< Enabled using the COM of the pull group of the last frame as reference for PBC */
- tpxv_MimicQMMM, /**< Inroduced support for MiMiC QM/MM interface */
+ tpxv_MimicQMMM, /**< Introduced support for MiMiC QM/MM interface */
tpxv_PullAverage, /**< Added possibility to output average pull force and position */
+ tpxv_GenericInternalParameters, /**< Added internal parameters for mdrun modules*/
tpxv_Count /**< the total number of tpxv versions */
};
{
ir->params = new gmx::KeyValueTreeObject(paramsBuilder.build());
}
+
+ if (file_version >= tpxv_GenericInternalParameters)
+ {
+ if (serializer->reading())
+ {
+ ir->internalParameters = std::make_unique<gmx::KeyValueTreeObject>(gmx::deserializeKeyValueTree(serializer));
+ }
+ else
+ {
+ GMX_RELEASE_ASSERT(ir->internalParameters != nullptr,
+ "Parameters should be present when writing inputrec");
+ gmx::serializeKeyValueTree(*ir->internalParameters, serializer);
+ }
+ }
}
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/futil.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/keyvaluetreebuilder.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/snprintf.h"
}
}
+ // Add the md modules internal parameters that are not mdp options
+ // e.g., atom indices
+
+ {
+ gmx::KeyValueTreeBuilder internalParameterBuilder;
+ mdModules.notifier().notify(&internalParameterBuilder);
+ ir->internalParameters = std::make_unique<gmx::KeyValueTreeObject>(internalParameterBuilder.build());
+ }
+
if (bVerbose)
{
fprintf(stderr, "writing run input file...\n");
static void bc_inputrec(const t_commrec *cr, t_inputrec *inputrec)
{
+ // Make sure to destruct all previously set internal parameters properly
+ // before the block_bc on the inputrec overwrites them.
+ // They are expected to be null anyway, but we can't guarantee this here.
+ if (!SIMMASTER(cr))
+ {
+ // will call destructor on previously set parameters upon leaving this block
+ std::unique_ptr<gmx::KeyValueTreeObject> previouslySetInternalParametersOnNonMaster;
+ inputrec->internalParameters.swap(previouslySetInternalParametersOnNonMaster);
+ }
// Note that this overwrites pointers in inputrec, so all pointer fields
// Must be initialized separately below.
block_bc(cr, *inputrec);
{
gmx::InMemorySerializer serializer;
gmx::serializeKeyValueTree(*inputrec->params, &serializer);
+ gmx::serializeKeyValueTree(*inputrec->internalParameters, &serializer);
std::vector<char> buffer = serializer.finishAndGetBuffer();
size_t size = buffer.size();
block_bc(cr, size);
}
else
{
- // block_bc() above overwrites the old pointer, so set it to a
+ // block_bc() of inputrec above overwrites the old pointer, so set it to a
// reasonable value in case code below throws.
inputrec->params = nullptr;
std::vector<char> buffer;
gmx::InMemoryDeserializer serializer(buffer, false);
inputrec->params = new gmx::KeyValueTreeObject(
gmx::deserializeKeyValueTree(&serializer));
+ // release is required because internalParameters' destructor will fail
+ // if block_bc() of inputrec overwrites the internalParameters pointer with garbage
+ auto gmx_unused releasedGarbagePointer = inputrec->internalParameters.release();
+ inputrec->internalParameters = std::make_unique<gmx::KeyValueTreeObject>(
+ gmx::deserializeKeyValueTree(&serializer));
}
bc_grpopts(cr, &(inputrec->opts));
class IKeyValueTreeTransformRules;
class IMDOutputProvider;
class KeyValueTreeObject;
+class KeyValueTreeBuilder;
class IMDModule;
class LocalAtomSetManager;
//! Register callback function types for MDModules
using notifier_type = registerMdModuleNotification<
CommunicationIsSetup,
+ KeyValueTreeBuilder*,
+ const KeyValueTreeObject &,
LocalAtomSetManager *
>::type;
#include "gromacs/utility/filestream.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/gmxmpi.h"
+#include "gromacs/utility/keyvaluetree.h"
#include "gromacs/utility/logger.h"
#include "gromacs/utility/loggerbuilder.h"
#include "gromacs/utility/physicalnodecommunicator.h"
// TODO: Error handling
mdModules_->assignOptionsToModules(*inputrec->params, nullptr);
+ if (inputrec->internalParameters != nullptr)
+ {
+ mdModules_->notifier().notify(*inputrec->internalParameters);
+ }
if (fplog != nullptr)
{
//! KVT object that contains input parameters converted to the new style.
gmx::KeyValueTreeObject *params;
+
+ //! KVT for storing simulation parameters that are not part of the mdp file.
+ std::unique_ptr<gmx::KeyValueTreeObject> internalParameters;
};
int ir_optimal_nstcalcenergy(const t_inputrec *ir);