Improve docs and naming for MdModulesNotifiers
[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,2020,2021, 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 /*! \internal \file
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  * This header is only used within the modular simulator module
42  */
43
44 #ifndef GMX_MODULARSIMULATOR_TRAJECTORYELEMENT_H
45 #define GMX_MODULARSIMULATOR_TRAJECTORYELEMENT_H
46
47 #include <vector>
48
49 #include "gromacs/compat/pointers.h"
50
51 #include "modularsimulatorinterfaces.h"
52
53 struct gmx_mtop_t;
54 struct gmx_output_env_t;
55 struct gmx_wallcycle;
56 struct t_commrec;
57 struct t_filenm;
58 struct t_inputrec;
59
60 namespace gmx
61 {
62 class IMDOutputProvider;
63 struct MDModulesNotifiers;
64 struct MdrunOptions;
65 enum class StartingBehavior;
66
67 /*! \internal
68  * \ingroup module_modularsimulator
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 final : public ISimulatorElement, public ILoggingSignallerClient, public ITrajectorySignallerClient
83 {
84 public:
85     friend class TrajectoryElementBuilder;
86     //! Get the box writeout frequency for TNG
87     [[nodiscard]] int tngBoxOut() const;
88     //! Get the lambda writeout frequency for TNG
89     [[nodiscard]] int tngLambdaOut() const;
90     //! Get the compressed box writeout frequency for TNG
91     [[nodiscard]] int tngBoxOutCompressed() const;
92     //! Get the compressed lambda writeout frequency for TNG
93     [[nodiscard]] int tngLambdaOutCompressed() const;
94
95     /*! \brief Prepare trajectory writer
96      *
97      * During setup, the trajectory writer will query the writer clients for
98      * their callbacks. It will also call the setup methods of the different
99      * clients. To be run before the main simulator run, but after all clients
100      * were registered.
101      */
102     void elementSetup() override;
103
104     /*! \brief Register run function for step / time
105      *
106      * Registers a trajectory writing function if the current step / time is
107      * either a state or energy writing step, as defined by the signaller
108      *
109      * \param step                 The step number
110      * \param time                 The time
111      * \param registerRunFunction  Function allowing to register a run function
112      */
113     void scheduleTask(Step step, Time time, const RegisterRunFunction& registerRunFunction) override;
114
115     /*! \brief Teardown trajectory writer
116      *
117      * During teardown, the trajectory writer will call the teardown
118      * methods of the clients and perform some additional clean-up.
119      * To be run after the main simulator run.
120      */
121     void elementTeardown() override;
122
123     //! \cond
124     // (doxygen doesn't like these...)
125     //! Allow CheckpointHelper to use outf_ (TODO: Can we improve this?)
126     friend class CheckpointHelper;
127     //! \endcond
128
129 private:
130     //! Constructor
131     TrajectoryElement(std::vector<ITrajectoryWriterClient*> writerClients,
132                       FILE*                                 fplog,
133                       int                                   nfile,
134                       const t_filenm                        fnm[],
135                       const MdrunOptions&                   mdrunOptions,
136                       const t_commrec*                      cr,
137                       IMDOutputProvider*                    outputProvider,
138                       const MDModulesNotifiers&             mdModulesNotifiers,
139                       const t_inputrec*                     inputrec,
140                       const gmx_mtop_t&                     top_global,
141                       const gmx_output_env_t*               oenv,
142                       gmx_wallcycle*                        wcycle,
143                       StartingBehavior                      startingBehavior,
144                       bool                                  simulationsSharingState);
145
146     //! The next energy writing step
147     Step writeEnergyStep_;
148     //! The next state writing step
149     Step writeStateStep_;
150     //! The next communicated log writing step
151     Step writeLogStep_;
152
153     //! The output object
154     gmx_mdoutf* outf_;
155
156     //! ILoggingSignallerClient implementation
157     std::optional<SignallerCallback> registerLoggingCallback() override;
158     //! ITrajectorySignallerClient implementation
159     std::optional<SignallerCallback> registerTrajectorySignallerCallback(TrajectoryEvent event) override;
160
161     /*
162      * Trajectory writing
163      */
164     //! The trajectory writing clients
165     std::vector<ITrajectoryWriterClient*> writerClients_;
166
167     //! Callbacks to write trajectory
168     //! {
169     std::vector<ITrajectoryWriterCallback> runStateCallbacks_;
170     std::vector<ITrajectoryWriterCallback> runEnergyCallbacks_;
171     //! }
172
173     //! The writing function - calls the clients to get their contributions
174     void write(Step step, Time time, bool writeState, bool writeEnergy, bool writeLog);
175 };
176
177 /*! \internal
178  * \ingroup module_modularsimulator
179  * \brief Build the `TrajectoryElement`
180  *
181  * This builder allows clients to register with the trajectory element
182  * as writer clients. The builder then builds the trajectory element.
183  */
184 class TrajectoryElementBuilder final
185 {
186 public:
187     //! Allows clients to register as trajectory writers
188     void registerWriterClient(ITrajectoryWriterClient* client);
189
190     //! Build the TrajectoryElement
191     template<typename... Args>
192     std::unique_ptr<TrajectoryElement> build(Args&&... args);
193
194 private:
195     //! List of writer clients
196     std::vector<ITrajectoryWriterClient*> writerClients_;
197     //! The state of the builder
198     ModularSimulatorBuilderState state_ = ModularSimulatorBuilderState::AcceptingClientRegistrations;
199 };
200
201 template<typename... Args>
202 std::unique_ptr<TrajectoryElement> TrajectoryElementBuilder::build(Args&&... args)
203 {
204     state_ = ModularSimulatorBuilderState::NotAcceptingClientRegistrations;
205     // NOLINTNEXTLINE(modernize-make-unique): make_unique does not work with private constructor
206     return std::unique_ptr<TrajectoryElement>(
207             new TrajectoryElement(std::move(writerClients_), std::forward<Args>(args)...));
208 }
209
210 } // namespace gmx
211
212 #endif // GMX_MODULARSIMULATOR_TRAJECTORYELEMENT_H