1 #ifndef HARMONICRESTRAINT_ENSEMBLEPOTENTIAL_H
2 #define HARMONICRESTRAINT_ENSEMBLEPOTENTIAL_H
5 * \brief Provide restrained ensemble MD potential for GROMACS plugin.
7 * The restraint implemented here uses a facility provided by gmxapi to perform averaging of some
8 * array data across an ensemble of simulations. Simpler pair restraints can use less of this
11 * Contains a lot of boiler plate that is being generalized and migrate out of this file, but other
12 * pair restraints can be implemented by following the example in this and ``ensemblepotential.cpp``.
13 * The ``CMakeLists.txt`` file will need to be updated if you add additional source files, and
14 * ``src/pythonmodule/export_plugin.cpp`` will need to be updated if you add or change the name of
17 * \author M. Eric Irrgang <ericirrgang@gmail.com>
25 #include "gmxapi/gromacsfwd.h"
26 #include "gmxapi/session.h"
27 #include "gmxapi/md/mdmodule.h"
29 #include "gromacs/restraint/restraintpotential.h"
30 #include "gromacs/utility/basedefinitions.h"
31 #include "gromacs/utility/real.h"
33 #include "sessionresources.h"
38 // Histogram for a single restrained pair.
39 using PairHist
= std::vector
<double>;
41 struct ensemble_input_param_type
43 /// distance histogram parameters
47 /// Flat-bottom potential boundaries.
51 /// Experimental reference distribution.
52 PairHist experimental
{};
54 /// Number of samples to store during each window.
55 unsigned int nSamples
{0};
56 double samplePeriod
{0};
58 /// Number of windows to use for smoothing histogram updates.
59 unsigned int nWindows
{0};
61 /// Harmonic force coefficient
63 /// Smoothing factor: width of Gaussian interpolation for histogram
68 // \todo We should be able to automate a lot of the parameter setting stuff
69 // by having the developer specify a map of parameter names and the corresponding type, but that could get tricky.
70 // The statically compiled fast parameter structure would be generated with a recursive variadic template
71 // the way a tuple is. ref https://eli.thegreenplace.net/2014/variadic-templates-in-c/
73 std::unique_ptr
<ensemble_input_param_type
>
74 makeEnsembleParams(size_t nbins
,
78 const std::vector
<double>& experimental
,
79 unsigned int nSamples
,
81 unsigned int nWindows
,
86 * \brief a residue-pair bias calculator for use in restrained-ensemble simulations.
88 * Applies a force between two sites according to the difference between an experimentally observed
89 * site pair distance distribution and the distance distribution observed earlier in the simulation
90 * trajectory. The sampled distribution is averaged from the previous `nwindows` histograms from all
91 * ensemble members. Each window contains a histogram populated with `nsamples` distances recorded at
92 * `sample_period` step intervals.
95 * During a the window_update_period steps of a window, the potential applied is a harmonic function of
96 * the difference between the sampled and experimental histograms. At the beginning of the window, this
97 * difference is found and a Gaussian blur is applied.
99 class EnsemblePotential
102 using input_param_type
= ensemble_input_param_type
;
104 /* No default constructor. Parameters must be provided. */
105 EnsemblePotential() = delete;
108 * \brief Constructor called by the wrapper code to produce a new instance.
110 * This constructor is called once per simulation per GROMACS process. Note that until
111 * gmxapi 0.0.8 there is only one instance per simulation in a thread-MPI simulation.
115 explicit EnsemblePotential(const input_param_type
& params
);
118 * \brief Deprecated constructor taking a parameter list.
124 * \param experimental
126 * \param samplePeriod
131 EnsemblePotential(size_t nbins
,
135 PairHist experimental
,
136 unsigned int nSamples
,
138 unsigned int nWindows
,
143 * \brief Evaluates the pair restraint potential.
145 * In parallel simulations, the gmxapi framework does not make guarantees about where or
146 * how many times this function is called. It should be simple and stateless; it should not
147 * update class member data (see ``ensemblepotential.cpp``. For a more controlled API hook
148 * and to manage state in the object, use ``callback()``.
150 * \param v position of the site for which force is being calculated.
151 * \param v0 reference site (other member of the pair).
152 * \param t current simulation time (ps).
153 * \return container for force and potential energy data.
155 // Implementation note for the future: If dispatching this virtual function is not fast
156 // enough, the compiler may be able to better optimize a free
157 // function that receives the current restraint as an argument.
158 gmx::PotentialPointData
calculate(gmx::Vector v
,
160 gmx_unused
double t
);
163 * \brief An update function to be called on the simulation master rank/thread periodically by the Restraint framework.
165 * Defining this function in a plugin potential is optional. If the function is defined,
166 * the restraint framework calls this function (on the first rank only in a parallel simulation) before calling calculate().
168 * The callback may use resources provided by the Session in the callback to perform updates
169 * to the local or global state of an ensemble of simulations. Future gmxapi releases will
170 * include additional optimizations, allowing call-back frequency to be expressed, and more
171 * general Session resources, as well as more flexible call signatures.
173 void callback(gmx::Vector v
,
176 const Resources
& resources
);
179 /// Width of bins (distance) in histogram
183 /// Flat-bottom potential boundaries.
186 /// Smoothed historic distribution for this restraint. An element of the array of restraints in this simulation.
187 // Was `hij` in earlier code.
189 PairHist experimental_
;
191 /// Number of samples to store during each window.
192 unsigned int nSamples_
;
193 unsigned int currentSample_
;
194 double samplePeriod_
;
195 double nextSampleTime_
;
196 /// Accumulated list of samples during a new window.
197 std::vector
<double> distanceSamples_
;
199 /// Number of windows to use for smoothing histogram updates.
201 size_t currentWindow_
;
202 double windowStartTime_
;
203 double nextWindowUpdateTime_
;
204 /// The history of nwindows histograms for this restraint.
205 std::vector
<std::unique_ptr
<plugin::Matrix
<double>>> windows_
;
207 /// Harmonic force coefficient
209 /// Smoothing factor: width of Gaussian interpolation for histogram
214 * \brief Use EnsemblePotential to implement a RestraintPotential
216 * This is boiler plate that will be templated and moved.
218 class EnsembleRestraint
: public ::gmx::IRestraintPotential
, private EnsemblePotential
221 using EnsemblePotential::input_param_type
;
223 EnsembleRestraint(std::vector
<int> sites
,
224 const input_param_type
& params
,
225 std::shared_ptr
<Resources
> resources
227 EnsemblePotential(params
),
228 sites_
{std::move(sites
)},
229 resources_
{std::move(resources
)}
232 ~EnsembleRestraint() override
= default;
235 * \brief Implement required interface of gmx::IRestraintPotential
237 * \return list of configured site indices.
239 * \todo remove to template header
240 * \todo abstraction of site references
242 std::vector
<int> sites() const override
248 * \brief Implement the interface gmx::IRestraintPotential
250 * Dispatch to calculate() method.
252 * \param r1 coordinate of first site
253 * \param r2 reference coordinate (second site)
254 * \param t simulation time
255 * \return calculated force and energy
257 * \todo remove to template header.
259 gmx::PotentialPointData
evaluate(gmx::Vector r1
,
269 * \brief An update function to be called on the simulation master rank/thread periodically by the Restraint framework.
271 * Implements optional override of gmx::IRestraintPotential::update
273 * This boilerplate will disappear into the Restraint template in an upcoming gmxapi release.
275 void update(gmx::Vector v
,
279 // Todo: use a callback period to mostly bypass this and avoid excessive mutex locking.
287 * \brief Implement the binding protocol that allows access to Session resources.
289 * The client receives a non-owning pointer to the session and cannot extent the life of the session. In
290 * the future we can use a more formal handle mechanism.
292 * \param session pointer to the current session
294 void bindSession(gmxapi::SessionResources
* session
) override
296 resources_
->setSession(session
);
299 void setResources(std::unique_ptr
<Resources
>&& resources
)
301 resources_
= std::move(resources
);
305 std::vector
<int> sites_
;
306 // double callbackPeriod_;
307 // double nextCallback_;
308 std::shared_ptr
<Resources
> resources_
;
312 // Important: Just declare the template instantiation here for client code.
313 // We will explicitly instantiate a definition in the .cpp file where the input_param_type is defined.
315 class RestraintModule
<EnsembleRestraint
>;
317 } // end namespace plugin
319 #endif //HARMONICRESTRAINT_ENSEMBLEPOTENTIAL_H