Add Flake8 linting to gmxapi tests.
[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, 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  * These functions have a standard implementation to allow clients not to implement
300  * them if no setup / teardown is needed.
301  */
302 class ITrajectoryWriterClient
303 {
304 public:
305     //! @cond
306     // (doxygen doesn't like these...)
307     //! Allow TrajectoryElement to ask for callback registration
308     friend class TrajectoryElement;
309     //! @endcond
310     //! Standard virtual destructor
311     virtual ~ITrajectoryWriterClient() = default;
312
313 protected:
314     //! Setup method with valid output pointer.
315     virtual void trajectoryWriterSetup(gmx_mdoutf* outf) = 0;
316     //! Teardown method with valid output pointer.
317     virtual void trajectoryWriterTeardown(gmx_mdoutf* outf) = 0;
318
319     //! Return callback to TrajectoryElement
320     virtual ITrajectoryWriterCallbackPtr registerTrajectoryWriterCallback(TrajectoryEvent) = 0;
321 };
322
323 /*! \libinternal
324  * \brief Client requiring read access to the local topology
325  *
326  */
327 class ITopologyHolderClient
328 {
329 public:
330     //! @cond
331     // (doxygen doesn't like these...)
332     //! Allow TopologyHolder to set new topology
333     friend class TopologyHolder;
334     //! @endcond
335     //! Standard virtual destructor
336     virtual ~ITopologyHolderClient() = default;
337
338 protected:
339     //! Pass pointer to new local topology
340     virtual void setTopology(const gmx_localtop_t*) = 0;
341 };
342
343 /*! \libinternal
344  * \brief Client that needs to store data during checkpointing
345  *
346  * The current checkpointing helper uses the legacy t_state object to collect
347  * the data to be checkpointed. Clients get queried for their contributions
348  * using pointers to t_state objects.
349  * \todo Add checkpoint reading
350  * \todo Evolve this to a model in which the checkpoint helper passes a file
351  *       pointer rather than a t_state object, and the clients are responsible
352  *       to read / write.
353  */
354 class ICheckpointHelperClient
355 {
356 public:
357     //! @cond
358     // (doxygen doesn't like these...)
359     //! Allow CheckpointHelper to interact
360     friend class CheckpointHelper;
361     //! @endcond
362     //! Standard virtual destructor
363     virtual ~ICheckpointHelperClient() = default;
364
365 protected:
366     //! Write checkpoint
367     virtual void writeCheckpoint(t_state* localState, t_state* globalState) = 0;
368 };
369 //! /}
370 } // namespace gmx
371
372 #endif // GMX_MODULARSIMULATOR_MODULARSIMULATORINTERFACES_H