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