Merge commit d30f2cb6 from release-2020 into master
[alexxy/gromacs.git] / src / gromacs / modularsimulator / modularsimulatorinterfaces.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2019,2020, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \defgroup module_modularsimulator The modular simulator
36  * \ingroup group_mdrun
37  * \brief
38  * The modular simulator improves extensibility, adds Monte Carlo capabilities,
39  * promotes data locality and communication via interfaces, supports
40  * multi-stepping integrators, and paves the way for some task parallelism.
41  *
42  * For more information, see page_modularsimulator
43  * \todo Can we link to `docs/doxygen/lib/modularsimulator.md`?
44  *
45  * \author Pascal Merz <pascal.merz@me.com>
46  */
47 /*! \libinternal \file
48  * \brief
49  * Declares the main interfaces used by the modular simulator
50  *
51  * \author Pascal Merz <pascal.merz@me.com>
52  * \ingroup module_modularsimulator
53  */
54 #ifndef GMX_MODULARSIMULATOR_MODULARSIMULATORINTERFACES_H
55 #define GMX_MODULARSIMULATOR_MODULARSIMULATORINTERFACES_H
56
57 #include <functional>
58 #include <memory>
59
60 #include "gromacs/utility/basedefinitions.h"
61
62 struct gmx_localtop_t;
63 struct gmx_mdoutf;
64 class t_state;
65
66 namespace gmx
67 {
68 template<class Signaller>
69 class SignallerBuilder;
70 class NeighborSearchSignaller;
71 class LastStepSignaller;
72 class LoggingSignaller;
73 class EnergySignaller;
74
75 //! \addtogroup module_modularsimulator
76 //! \{
77
78 // This will make signatures more legible
79 //! Step number
80 using Step = int64_t;
81 //! Simulation time
82 using Time = double;
83
84 //! The function type that can be scheduled to be run during the simulator run
85 typedef std::function<void()> SimulatorRunFunction;
86 //! Pointer to the function type that can be scheduled to be run during the simulator run
87 typedef std::unique_ptr<SimulatorRunFunction> SimulatorRunFunctionPtr;
88
89 //! The function type that allows to register run functions
90 typedef std::function<void(SimulatorRunFunctionPtr)> RegisterRunFunction;
91 //! Pointer to the function type that allows to register run functions
92 typedef std::unique_ptr<RegisterRunFunction> RegisterRunFunctionPtr;
93
94 /*! \libinternal
95  * \brief The general interface for elements of the modular simulator
96  *
97  * Setup and teardown are run once at the beginning of the simulation
98  * (after all elements were set up, before the first step) and at the
99  * end of the simulation (after the last step, before elements are
100  * destructed), respectively. `registerRun` is periodically called
101  * during the run, at which point elements can decide to register one
102  * or more run functions to be run at a specific time / step. Registering
103  * more than one function is especially valuable for collective elements
104  * consisting of more than one single element.
105  */
106 class ISimulatorElement
107 {
108 public:
109     /*! \brief Query whether element wants to run at step / time
110      *
111      * Element can register one or more functions to be run at that step through
112      * the registration pointer.
113      */
114     virtual void scheduleTask(Step, Time, const RegisterRunFunctionPtr&) = 0;
115     //! Method guaranteed to be called after construction, before simulator run
116     virtual void elementSetup() = 0;
117     //! Method guaranteed to be called after simulator run, before deconstruction
118     virtual void elementTeardown() = 0;
119     //! Standard virtual destructor
120     virtual ~ISimulatorElement() = default;
121 };
122
123 /*! \libinternal
124  * \brief The general Signaller interface
125  *
126  * Signallers are run at the beginning of Simulator steps, informing
127  * their clients about the upcoming step. This allows clients to
128  * decide if they need to be activated at this time step, and what
129  * functions they will have to run. Examples for signallers
130  * include the neighbor-search signaller (informs its clients when a
131  * neighbor-searching step is about to happen) or the logging
132  * signaller (informs its clients when a logging step is about to
133  * happen).
134  *
135  * We expect all signallers to accept registration from clients, but
136  * different signallers might handle that differently, so we don't
137  * include this in the interface.
138  */
139 class ISignaller
140 {
141 public:
142     //! Function run before every step of scheduling
143     virtual void signal(Step, Time) = 0;
144     //! Method guaranteed to be called after construction, before simulator run
145     virtual void signallerSetup() = 0;
146     //! Standard virtual destructor
147     virtual ~ISignaller() = default;
148 };
149
150 //! The function type that can be registered to signallers for callback
151 typedef std::function<void(Step, Time)> SignallerCallback;
152 //! Pointer to the function type that can be registered to signallers for callback
153 typedef std::unique_ptr<SignallerCallback> SignallerCallbackPtr;
154
155 /*! \libinternal
156  * \brief Interface for clients of the NeighborSearchSignaller
157  *
158  * Defining registerNSCallback allows clients to register an arbitrary callback
159  * for notification by the signaller.
160  */
161 class INeighborSearchSignallerClient
162 {
163 public:
164     //! @cond
165     // (doxygen doesn't like these...)
166     //! Allow builder of NeighborSearchSignaller to ask for callback registration
167     friend class SignallerBuilder<NeighborSearchSignaller>;
168     //! @endcond
169     //! Standard virtual destructor
170     virtual ~INeighborSearchSignallerClient() = default;
171
172 protected:
173     //! Return callback to NeighborSearchSignaller
174     virtual SignallerCallbackPtr registerNSCallback() = 0;
175 };
176
177 /*! \libinternal
178  * \brief Interface for clients of the LastStepSignaller
179  *
180  * Defining registerLastStepCallback allows clients to register an arbitrary callback
181  * for notification by the signaller.
182  */
183 class ILastStepSignallerClient
184 {
185 public:
186     //! @cond
187     // (doxygen doesn't like these...)
188     //! Allow builder of LastStepSignaller to ask for callback registration
189     friend class SignallerBuilder<LastStepSignaller>;
190     //! @endcond
191     //! Standard virtual destructor
192     virtual ~ILastStepSignallerClient() = default;
193
194 protected:
195     //! Return callback to LastStepSignaller
196     virtual SignallerCallbackPtr registerLastStepCallback() = 0;
197 };
198
199 /*! \libinternal
200  * \brief Interface for clients of the LoggingSignaller
201  *
202  * Defining registerLoggingCallback allows clients to register an arbitrary callback
203  * for notification by the signaller.
204  */
205 class ILoggingSignallerClient
206 {
207 public:
208     //! @cond
209     // (doxygen doesn't like these...)
210     //! Allow builder of LoggingSignaller to ask for callback registration
211     friend class SignallerBuilder<LoggingSignaller>;
212     //! @endcond
213     //! Standard virtual destructor
214     virtual ~ILoggingSignallerClient() = default;
215
216 protected:
217     //! Return callback to LoggingSignaller
218     virtual SignallerCallbackPtr registerLoggingCallback() = 0;
219 };
220
221 //! The energy events signalled by the EnergySignaller
222 enum class EnergySignallerEvent
223 {
224     EnergyCalculationStep,
225     VirialCalculationStep,
226     FreeEnergyCalculationStep
227 };
228
229 /*! \libinternal
230  * \brief Interface for clients of the EnergySignaller
231  *
232  * Defining registerEnergyCallback allows clients to register an arbitrary callback
233  * for notification by the signaller for every EnergySignallerEvent separately.
234  */
235 class IEnergySignallerClient
236 {
237 public:
238     //! @cond
239     // (doxygen doesn't like these...)
240     //! Allow builder of EnergySignaller to ask for callback registration
241     friend class SignallerBuilder<EnergySignaller>;
242     //! @endcond
243     //! Standard virtual destructor
244     virtual ~IEnergySignallerClient() = default;
245
246 protected:
247     //! Return callback to EnergySignaller
248     virtual SignallerCallbackPtr registerEnergyCallback(EnergySignallerEvent) = 0;
249 };
250
251 //! The trajectory writing events
252 enum class TrajectoryEvent
253 {
254     StateWritingStep,
255     EnergyWritingStep
256 };
257
258 /*! \libinternal
259  * \brief Interface for signaller clients of the TrajectoryElement
260  *
261  * Defining registerTrajectorySignallerCallback allows clients to register an arbitrary
262  * callback for notification by the signaller for every TrajectoryEvent separately.
263  */
264 class ITrajectorySignallerClient
265 {
266 public:
267     //! @cond
268     // (doxygen doesn't like these...)
269     //! Allow builder of TrajectoryElement to ask for callback registration
270     friend class TrajectoryElementBuilder;
271     //! @endcond
272     //! Standard virtual destructor
273     virtual ~ITrajectorySignallerClient() = default;
274
275 protected:
276     //! Return callback to TrajectoryElement
277     virtual SignallerCallbackPtr registerTrajectorySignallerCallback(TrajectoryEvent) = 0;
278 };
279
280 /* Trajectory writing clients are handed a pointer to the output file handler,
281  * allowing them to write their own trajectory contribution.
282  *
283  * As trajectory writing and log writing cannot currently be separated for the
284  * energy, clients also get informed whether this is a trajectory-writing step
285  * and / or a log-writing step.
286  */
287 //! Function type for trajectory writing clients
288 typedef std::function<void(gmx_mdoutf*, Step, Time, bool, bool)> ITrajectoryWriterCallback;
289 //! Pointer to the function type for trajectory writing clients
290 typedef std::unique_ptr<ITrajectoryWriterCallback> ITrajectoryWriterCallbackPtr;
291
292 /*! \libinternal
293  * \brief Interface for writer clients of the TrajectoryElement
294  *
295  * Defining registerTrajectoryWriterCallback allows clients to register an arbitrary
296  * callback called by the TrajectoryElement when trajectory writing happens.
297  *
298  * Setup and teardown methods allow clients to perform tasks with a valid output pointer.
299  */
300 class ITrajectoryWriterClient
301 {
302 public:
303     //! @cond
304     // (doxygen doesn't like these...)
305     //! Allow TrajectoryElement to ask for callback registration
306     friend class TrajectoryElement;
307     //! @endcond
308     //! Standard virtual destructor
309     virtual ~ITrajectoryWriterClient() = default;
310
311 protected:
312     //! Setup method with valid output pointer.
313     virtual void trajectoryWriterSetup(gmx_mdoutf* outf) = 0;
314     //! Teardown method with valid output pointer.
315     virtual void trajectoryWriterTeardown(gmx_mdoutf* outf) = 0;
316
317     //! Return callback to TrajectoryElement
318     virtual ITrajectoryWriterCallbackPtr registerTrajectoryWriterCallback(TrajectoryEvent) = 0;
319 };
320
321 /*! \libinternal
322  * \brief Client requiring read access to the local topology
323  *
324  */
325 class ITopologyHolderClient
326 {
327 public:
328     //! @cond
329     // (doxygen doesn't like these...)
330     //! Allow TopologyHolder to set new topology
331     friend class TopologyHolder;
332     //! @endcond
333     //! Standard virtual destructor
334     virtual ~ITopologyHolderClient() = default;
335
336 protected:
337     //! Pass pointer to new local topology
338     virtual void setTopology(const gmx_localtop_t*) = 0;
339 };
340
341 /*! \libinternal
342  * \brief Client that needs to store data during checkpointing
343  *
344  * The current checkpointing helper uses the legacy t_state object to collect
345  * the data to be checkpointed. Clients get queried for their contributions
346  * using pointers to t_state objects.
347  * \todo Add checkpoint reading
348  * \todo Evolve this to a model in which the checkpoint helper passes a file
349  *       pointer rather than a t_state object, and the clients are responsible
350  *       to read / write.
351  */
352 class ICheckpointHelperClient
353 {
354 public:
355     //! @cond
356     // (doxygen doesn't like these...)
357     //! Allow CheckpointHelper to interact
358     friend class CheckpointHelper;
359     //! @endcond
360     //! Standard virtual destructor
361     virtual ~ICheckpointHelperClient() = default;
362
363 protected:
364     //! Write checkpoint
365     virtual void writeCheckpoint(t_state* localState, t_state* globalState) = 0;
366 };
367 //! /}
368 } // namespace gmx
369
370 #endif // GMX_MODULARSIMULATOR_MODULARSIMULATORINTERFACES_H