Add checkpointing for MdModules
[alexxy/gromacs.git] / src / gromacs / modularsimulator / trajectoryelement.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 /*! \libinternal
36  * \brief Declares the trajectory element for the modular simulator
37  *
38  * \author Pascal Merz <pascal.merz@me.com>
39  * \ingroup module_modularsimulator
40  */
41
42 #ifndef GMX_MODULARSIMULATOR_TRAJECTORYELEMENT_H
43 #define GMX_MODULARSIMULATOR_TRAJECTORYELEMENT_H
44
45 #include <vector>
46
47 #include "gromacs/compat/pointers.h"
48
49 #include "modularsimulatorinterfaces.h"
50
51 struct gmx_mtop_t;
52 struct gmx_output_env_t;
53 struct gmx_wallcycle;
54 struct t_commrec;
55 struct t_filenm;
56 struct t_inputrec;
57
58 namespace gmx
59 {
60 class IMDOutputProvider;
61 struct MdModulesNotifier;
62 struct MdrunOptions;
63 enum class StartingBehavior;
64
65 //! \addtogroup module_modularsimulator
66 //! \{
67
68 /*! \libinternal
69  * \brief Trajectory element signals and handles trajectory writing
70  *
71  * The trajectory element is both a signaller and a simulator element.
72  *
73  * During signalling phase, it checks whether the current step is a writing
74  * step for either the energy or the state (position, velocity, forces)
75  * trajectory. It then notifies the signaller clients of the upcoming step.
76  *
77  * For the simulator run, the element registers a run function at trajectory
78  * writing steps. Trajectory writing is done using a client system - the
79  * element only prepares the output struct, and passes it to the clients who
80  * write their part of the trajectory.
81  */
82 class TrajectoryElement :
83     public ISimulatorElement,
84     public ISignaller,
85     public ILastStepSignallerClient
86 {
87     public:
88         friend class TrajectoryElementBuilder;
89
90         /*
91          * Methods for the signaller part of the element
92          */
93
94         /*! \brief Prepare signaller
95          *
96          * Check that necessary registration was done
97          */
98         void signallerSetup() override;
99
100         /*! \brief Run the signaller at a specific step / time
101          *
102          * Informs clients when energy or state will be written.
103          *
104          * @param step           The current time step
105          * @param time           The current time
106          */
107         void signal(Step step, Time time) override;
108
109         /*
110          * Methods for the trajectory writing part of the element
111          */
112
113         /*! \brief Prepare trajectory writer
114          *
115          * During setup, the trajectory writer will query the writer clients for
116          * their callbacks. It will also call the setup methods of the different
117          * clients. To be ran before the main simulator run, but after all clients
118          * were registered.
119          */
120         void elementSetup() override;
121
122         /*! \brief Register run function for step / time
123          *
124          * Registers a trajectory writing function if the current step / time is
125          * either a state or energy writing step, as defined by the signaller
126          *
127          * @param step                 The step number
128          * @param time                 The time
129          * @param registerRunFunction  Function allowing to register a run function
130          */
131         void scheduleTask(
132             Step step, Time time,
133             const RegisterRunFunctionPtr &registerRunFunction) override;
134
135         /*! \brief Teardown trajectory writer
136          *
137          * During teardown, the trajectory writer will call the teardown
138          * methods of the clients and perform some additional clean-up.
139          * To be ran after the main simulator run.
140          */
141         void elementTeardown() override;
142
143     private:
144         //! Constructor
145         TrajectoryElement(
146             std::vector<SignallerCallbackPtr> signalEnergyCallbacks,
147             std::vector<SignallerCallbackPtr> signalStateCallbacks,
148             std::vector<ITrajectoryWriterClient*> writerClients,
149             FILE *fplog, int nfile, const t_filenm fnm[],
150             const MdrunOptions &mdrunOptions,
151             const t_commrec *cr,
152             IMDOutputProvider *outputProvider,
153             const MdModulesNotifier &mdModulesNotifier,
154             const t_inputrec *inputrec, gmx_mtop_t *top_global,
155             const gmx_output_env_t *oenv, gmx_wallcycle *wcycle,
156             StartingBehavior startingBehavior);
157
158         //! The next energy writing step
159         Step writeEnergyStep_;
160         //! The next state writing step
161         Step writeStateStep_;
162
163         //! The output object
164         gmx_mdoutf *outf_;
165
166         /*
167          * Signaller
168          */
169         //! Output frequencies
170         //! {
171         const int nstxout_;
172         const int nstvout_;
173         const int nstfout_;
174         const int nstxoutCompressed_;
175         const int tngBoxOut_;
176         const int tngLambdaOut_;
177         const int tngBoxOutCompressed_;
178         const int tngLambdaOutCompressed_;
179         const int nstenergy_;
180         //! }
181
182         //! Callbacks to signal events
183         //! {
184         std::vector<SignallerCallbackPtr> signalEnergyCallbacks_;
185         std::vector<SignallerCallbackPtr> signalStateCallbacks_;
186         //! }
187
188         /*
189          * Last step client
190          */
191         Step lastStep_;
192         bool lastStepRegistrationDone_;
193         //! ILastStepSignallerClient implementation
194         SignallerCallbackPtr registerLastStepCallback() override;
195
196         /*
197          * Trajectory writing
198          */
199         //! The trajectory writing clients
200         std::vector<ITrajectoryWriterClient*> writerClients_;
201
202         //! Callbacks to write trajectory
203         //! {
204         std::vector<ITrajectoryWriterCallbackPtr> runStateCallbacks_;
205         std::vector<ITrajectoryWriterCallbackPtr> runEnergyCallbacks_;
206         //! }
207
208         //! The writing function - calls the clients to get their contributions
209         void write(Step step, Time time, bool writeState, bool writeEnergy);
210 };
211
212 /*! \libinternal
213  * \brief Build the `TrajectoryElement`
214  *
215  * This builder allows clients to register with the trajectory element, either
216  * as signaller clients or as writer clients. The builder then builds the
217  * element.
218  */
219 class TrajectoryElementBuilder final
220 {
221     public:
222         //! Allows clients to register to the signaller
223         void registerSignallerClient(
224             compat::not_null<ITrajectorySignallerClient*> client);
225
226         //! Allows clients to register as trajectory writers
227         void registerWriterClient(
228             compat::not_null<ITrajectoryWriterClient*> client);
229
230         //! Build the TrajectoryElement
231         template <typename ... Args>
232         std::unique_ptr<TrajectoryElement> build(Args && ... args);
233
234     private:
235         //! List of signaller clients
236         std::vector<ITrajectorySignallerClient*> signallerClients_;
237         //! List of writer clients
238         std::vector<ITrajectoryWriterClient*>    writerClients_;
239 };
240
241 //! /}
242
243 template<typename ... Args>
244 std::unique_ptr<TrajectoryElement> TrajectoryElementBuilder::build(Args && ... args)
245 {
246     std::vector<SignallerCallbackPtr> signalEnergyCallbacks;
247     std::vector<SignallerCallbackPtr> signalStateCallbacks;
248     // Allow clients to register their callbacks
249     for (auto &client : signallerClients_)
250     {
251         // don't register nullptr
252         if (auto energyCallback = client->registerTrajectorySignallerCallback(TrajectoryEvent::energyWritingStep))
253         {
254             signalEnergyCallbacks.emplace_back(std::move(energyCallback));
255         }
256         if (auto stateCallback = client->registerTrajectorySignallerCallback(TrajectoryEvent::stateWritingStep))
257         {
258             signalStateCallbacks.emplace_back(std::move(stateCallback));
259         }
260     }
261     // NOLINTNEXTLINE(modernize-make-unique): make_unique does not work with private constructor
262     return std::unique_ptr<TrajectoryElement>(
263             new TrajectoryElement(
264                     std::move(signalEnergyCallbacks),
265                     std::move(signalStateCallbacks),
266                     std::move(writerClients_),
267                     std::forward<Args>(args) ...));
268 }
269
270 }      // namespace gmx
271
272 #endif // GMX_MODULARSIMULATOR_TRAJECTORYELEMENT_H