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/real.h"
32 #include "sessionresources.h"
37 // Histogram for a single restrained pair.
38 using PairHist
= std::vector
<double>;
40 struct ensemble_input_param_type
42 /// distance histogram parameters
46 /// Flat-bottom potential boundaries.
50 /// Experimental reference distribution.
51 PairHist experimental
{};
53 /// Number of samples to store during each window.
54 unsigned int nSamples
{0};
55 double samplePeriod
{0};
57 /// Number of windows to use for smoothing histogram updates.
58 unsigned int nWindows
{0};
60 /// Harmonic force coefficient
62 /// Smoothing factor: width of Gaussian interpolation for histogram
67 // \todo We should be able to automate a lot of the parameter setting stuff
68 // by having the developer specify a map of parameter names and the corresponding type, but that could get tricky.
69 // The statically compiled fast parameter structure would be generated with a recursive variadic template
70 // the way a tuple is. ref https://eli.thegreenplace.net/2014/variadic-templates-in-c/
72 std::unique_ptr
<ensemble_input_param_type
>
73 makeEnsembleParams(size_t nbins
,
77 const std::vector
<double>& experimental
,
78 unsigned int nSamples
,
80 unsigned int nWindows
,
85 * \brief a residue-pair bias calculator for use in restrained-ensemble simulations.
87 * Applies a force between two sites according to the difference between an experimentally observed
88 * site pair distance distribution and the distance distribution observed earlier in the simulation
89 * trajectory. The sampled distribution is averaged from the previous `nwindows` histograms from all
90 * ensemble members. Each window contains a histogram populated with `nsamples` distances recorded at
91 * `sample_period` step intervals.
94 * During a the window_update_period steps of a window, the potential applied is a harmonic function of
95 * the difference between the sampled and experimental histograms. At the beginning of the window, this
96 * difference is found and a Gaussian blur is applied.
98 class EnsemblePotential
101 using input_param_type
= ensemble_input_param_type
;
103 /* No default constructor. Parameters must be provided. */
104 EnsemblePotential() = delete;
107 * \brief Constructor called by the wrapper code to produce a new instance.
109 * This constructor is called once per simulation per GROMACS process. Note that until
110 * gmxapi 0.0.8 there is only one instance per simulation in a thread-MPI simulation.
114 explicit EnsemblePotential(const input_param_type
& params
);
117 * \brief Deprecated constructor taking a parameter list.
123 * \param experimental
125 * \param samplePeriod
130 EnsemblePotential(size_t nbins
,
134 PairHist experimental
,
135 unsigned int nSamples
,
137 unsigned int nWindows
,
142 * \brief Evaluates the pair restraint potential.
144 * In parallel simulations, the gmxapi framework does not make guarantees about where or
145 * how many times this function is called. It should be simple and stateless; it should not
146 * update class member data (see ``ensemblepotential.cpp``. For a more controlled API hook
147 * and to manage state in the object, use ``callback()``.
149 * \param v position of the site for which force is being calculated.
150 * \param v0 reference site (other member of the pair).
151 * \param t current simulation time (ps).
152 * \return container for force and potential energy data.
154 // Implementation note for the future: If dispatching this virtual function is not fast
155 // enough, the compiler may be able to better optimize a free
156 // function that receives the current restraint as an argument.
157 gmx::PotentialPointData
calculate(gmx::Vector v
,
159 gmx_unused
double t
);
162 * \brief An update function to be called on the simulation master rank/thread periodically by the Restraint framework.
164 * Defining this function in a plugin potential is optional. If the function is defined,
165 * the restraint framework calls this function (on the first rank only in a parallel simulation) before calling calculate().
167 * The callback may use resources provided by the Session in the callback to perform updates
168 * to the local or global state of an ensemble of simulations. Future gmxapi releases will
169 * include additional optimizations, allowing call-back frequency to be expressed, and more
170 * general Session resources, as well as more flexible call signatures.
172 void callback(gmx::Vector v
,
175 const Resources
& resources
);
178 /// Width of bins (distance) in histogram
182 /// Flat-bottom potential boundaries.
185 /// Smoothed historic distribution for this restraint. An element of the array of restraints in this simulation.
186 // Was `hij` in earlier code.
188 PairHist experimental_
;
190 /// Number of samples to store during each window.
191 unsigned int nSamples_
;
192 unsigned int currentSample_
;
193 double samplePeriod_
;
194 double nextSampleTime_
;
195 /// Accumulated list of samples during a new window.
196 std::vector
<double> distanceSamples_
;
198 /// Number of windows to use for smoothing histogram updates.
200 size_t currentWindow_
;
201 double windowStartTime_
;
202 double nextWindowUpdateTime_
;
203 /// The history of nwindows histograms for this restraint.
204 std::vector
<std::unique_ptr
<plugin::Matrix
<double>>> windows_
;
206 /// Harmonic force coefficient
208 /// Smoothing factor: width of Gaussian interpolation for histogram
213 * \brief Use EnsemblePotential to implement a RestraintPotential
215 * This is boiler plate that will be templated and moved.
217 class EnsembleRestraint
: public ::gmx::IRestraintPotential
, private EnsemblePotential
220 using EnsemblePotential::input_param_type
;
222 EnsembleRestraint(std::vector
<int> sites
,
223 const input_param_type
& params
,
224 std::shared_ptr
<Resources
> resources
226 EnsemblePotential(params
),
227 sites_
{std::move(sites
)},
228 resources_
{std::move(resources
)}
231 ~EnsembleRestraint() override
= default;
234 * \brief Implement required interface of gmx::IRestraintPotential
236 * \return list of configured site indices.
238 * \todo remove to template header
239 * \todo abstraction of site references
241 std::vector
<int> sites() const override
247 * \brief Implement the interface gmx::IRestraintPotential
249 * Dispatch to calculate() method.
251 * \param r1 coordinate of first site
252 * \param r2 reference coordinate (second site)
253 * \param t simulation time
254 * \return calculated force and energy
256 * \todo remove to template header.
258 gmx::PotentialPointData
evaluate(gmx::Vector r1
,
268 * \brief An update function to be called on the simulation master rank/thread periodically by the Restraint framework.
270 * Implements optional override of gmx::IRestraintPotential::update
272 * This boilerplate will disappear into the Restraint template in an upcoming gmxapi release.
274 void update(gmx::Vector v
,
278 // Todo: use a callback period to mostly bypass this and avoid excessive mutex locking.
286 * \brief Implement the binding protocol that allows access to Session resources.
288 * The client receives a non-owning pointer to the session and cannot extent the life of the session. In
289 * the future we can use a more formal handle mechanism.
291 * \param session pointer to the current session
293 void bindSession(gmxapi::SessionResources
* session
) override
295 resources_
->setSession(session
);
298 void setResources(std::unique_ptr
<Resources
>&& resources
)
300 resources_
= std::move(resources
);
304 std::vector
<int> sites_
;
305 // double callbackPeriod_;
306 // double nextCallback_;
307 std::shared_ptr
<Resources
> resources_
;
311 // Important: Just declare the template instantiation here for client code.
312 // We will explicitly instantiate a definition in the .cpp file where the input_param_type is defined.
314 class RestraintModule
<EnsembleRestraint
>;
316 } // end namespace plugin
318 #endif //HARMONICRESTRAINT_ENSEMBLEPOTENTIAL_H