Improve MessageStringCollector
[alexxy/gromacs.git] / src / gromacs / utility / mdmodulesnotifiers.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 /*! \libinternal \file
36  * \brief
37  * Declares gmx::MDModulesNotifiers.
38  *
39  * \author Christian Blau <blau@kth.se>
40  * \inlibraryapi
41  * \ingroup module_utility
42  */
43
44 #ifndef GMX_UTILITY_MDMODULESNOTIFIERS_H
45 #define GMX_UTILITY_MDMODULESNOTIFIERS_H
46
47 #include <string>
48 #include <vector>
49
50 #include "gromacs/math/arrayrefwithpadding.h"
51 #include "gromacs/math/vectypes.h"
52 #include "gromacs/utility/mdmodulesnotifier.h"
53
54 struct t_commrec;
55 struct gmx_mtop_t;
56 struct warninp;
57 enum class PbcType : int;
58
59 namespace gmx
60 {
61
62 class KeyValueTreeObject;
63 class KeyValueTreeObjectBuilder;
64 class LocalAtomSetManager;
65 class MDLogger;
66 class IndexGroupsAndNames;
67 class SeparatePmeRanksPermitted;
68 struct MDModulesCheckpointReadingDataOnMaster;
69 struct MDModulesCheckpointReadingBroadcast;
70 struct MDModulesWriteCheckpointData;
71
72 /*! \libinternal \brief Check if module outputs energy to a specific field.
73  *
74  * Ensures that energy is output for this module.
75  */
76 struct MDModulesEnergyOutputToDensityFittingRequestChecker
77 {
78     //! Trigger output to density fitting energy field
79     bool energyOutputToDensityFitting_ = false;
80 };
81
82 /*! \libinternal \brief Check if QMMM module outputs energy to a specific field.
83  *
84  * Ensures that energy is output for QMMM module.
85  */
86 struct MDModulesEnergyOutputToQMMMRequestChecker
87 {
88     //! Trigger output to density fitting energy field
89     bool energyOutputToQMMM_ = false;
90 };
91
92 /*! \libinternal
93  * \brief Collect errors for the energy calculation frequency.
94  *
95  * Collect errors regarding energy calculation frequencies as strings that then
96  * may be used to issue errors.
97  *
98  * \note The mdp option "nstcalcenergy" is altered after reading the .mdp input
99  *       and only used in certain integrators, thus this class is to be used
100  *       only after all these operations are done.
101  */
102 class EnergyCalculationFrequencyErrors
103 {
104 public:
105     //! Construct by setting the energy calculation frequency
106     EnergyCalculationFrequencyErrors(int64_t energyCalculationIntervalInSteps) :
107         energyCalculationIntervalInSteps_(energyCalculationIntervalInSteps)
108     {
109     }
110     //! Return the number of steps of an energy calculation interval
111     std::int64_t energyCalculationIntervalInSteps() const
112     {
113         return energyCalculationIntervalInSteps_;
114     }
115     //! Collect error messages
116     void addError(const std::string& errorMessage) { errorMessages_.push_back(errorMessage); }
117     //! Return error messages
118     const std::vector<std::string>& errorMessages() const { return errorMessages_; }
119
120 private:
121     //! The frequency of energy calculations
122     const std::int64_t energyCalculationIntervalInSteps_;
123     //! The error messages
124     std::vector<std::string> errorMessages_;
125 };
126
127 /*! \libinternal \brief Provides the simulation time step in ps.
128  */
129 struct SimulationTimeStep
130 {
131     //! Time step (ps)
132     const double delta_t;
133 };
134
135 /*! \libinternal \brief Provides coordinates and simulation box.
136  */
137 struct CoordinatesAndBoxPreprocessed
138 {
139     ArrayRefWithPadding<RVec> coordinates_;
140     matrix                    box_;
141     PbcType                   pbc_;
142 };
143
144 /*! \libinternal \brief Mdrun input filename.
145  */
146 struct MdRunInputFilename
147 {
148     //! The name of the run input file (.tpr) as output by grompp
149     std::string mdRunFilename_;
150 };
151
152 /*! \libinternal \brief Notification for QM program input filename
153  *  provided by user as command-line argument for grompp
154  */
155 struct QMInputFileName
156 {
157     //! Flag if QM Input File has been provided by user
158     bool hasQMInputFileName_ = false;
159     //! The name of the QM Input file (.inp)
160     std::string qmInputFileName_;
161 };
162
163 /*! \libinternal
164  * \brief Group of notifers to organize that MDModules
165  * can receive callbacks they subscribe to.
166  *
167  * MDModules use members of this struct to subscribe to notifications
168  * of particular events. When the event occurs, the callback provided
169  * by a particular MDModule will be passed a parameter of the
170  * particular type they are interested in.
171  *
172  * Typically, during the setup phase, modules subscribe to notifiers
173  * that interest them by passing callbacks that expect a single parameter
174  * that describes the event. These are stored for later use. See the
175  * sequence diagram that follows:
176    \msc
177 wordwraparcs=true,
178 hscale="2";
179
180 modules [label = "mdModules:\nMDModules"],
181 notifiers [label="notifiers\nMDModulesNotifiers"],
182 notifier [label="exampleNotifier:\nBuildMDModulesNotifier\n<EventX, EventY>::type"],
183 moduleA [label="moduleA"],
184 moduleB [label="moduleB"],
185 moduleC [label="moduleC"];
186
187 modules box moduleC [label = "mdModules creates and owns moduleA, moduleB, and moduleC"];
188 modules =>> notifiers [label="creates"];
189 notifiers =>> notifier [label="creates"];
190 notifier =>> notifiers [label="returns"];
191 notifiers =>> modules [label="returns"];
192
193 modules =>> moduleA [label="provides notifiers"];
194 moduleA =>> moduleA [label="unpacks\nnotifiers.exampleNotifier"];
195 moduleA =>> notifier [label="subscribes with\ncallback(EventX&)"];
196 notifier =>> notifier [label="records subscription\nto EventX"];
197 moduleA =>> notifier [label="subscribes with\ncallback(EventY&)"];
198 notifier =>> notifier [label="records subscription\nto EventY"];
199 moduleA =>> modules [label="returns"];
200
201 modules =>> moduleB [label="provides notifiers"];
202 moduleB =>> moduleB [label="unpacks\nnotifiers.exampleNotifier"];
203 moduleA =>> notifier [label="subscribes with\ncallback(EventY&)"];
204 notifier =>> notifier [label="records subscription\nto EventY"];
205 moduleB =>> modules [label="returns"];
206
207 modules =>> moduleC [label="provides notifiers"];
208 moduleC =>> moduleC [label="unpacks and keeps\nnotifiers.exampleNotifier"];
209 moduleC =>> modules [label="returns"];
210
211    \endmsc
212
213    * When the event occurs later on, the stored callbacks are used to
214    * allow the modules to react. See the following sequence diagram,
215    * which assumes that exampleNotifier was configured as in the
216    * previous sequence diagram.
217
218    \msc
219 wordwraparcs=true,
220 hscale="2";
221
222 moduleC [label="moduleC"],
223 notifier [label="exampleNotifier:\nBuildMDModulesNotifier\n<EventX, EventY>::type"],
224 moduleA [label="moduleA"],
225 moduleB [label="moduleB"];
226
227 moduleC box moduleB [label = "Later, when ModuleC is doing work"];
228 moduleC =>> moduleC [label="generates EventX"];
229 moduleC =>> moduleC [label="generates EventY"];
230 moduleC =>> notifier [label="calls notify(eventX)"];
231 notifier =>> moduleA [label="calls callback(eventX)"];
232 moduleA =>> moduleA [label="reacts to eventX"];
233 moduleA =>> notifier [label="returns"];
234
235 notifier =>> moduleC [label="returns"];
236 moduleC =>> notifier [label="calls notify(eventY)"];
237 notifier =>> moduleA [label="calls callback(eventY)"];
238 moduleA =>> moduleA [label="reacts to eventY"];
239 moduleA =>> notifier [label="returns"];
240 notifier =>> moduleB [label="calls callback(eventY)"];
241 moduleB =>> moduleB [label="reacts to eventY"];
242 moduleB =>> notifier [label="returns"];
243 notifier =>> moduleC [label="returns"];
244    \endmsc
245  *
246  * The template arguments to the members of this struct are the
247  * parameters passed to the callback functions, one type per
248  * callback. Arguments passed as pointers are always meant to be
249  * modified, but never meant to be stored (in line with the policy
250  * everywhere else).
251  *
252  */
253 struct MDModulesNotifiers
254 {
255     /*! \brief Pre-processing callback functions.
256      * CoordinatesAndBoxPreprocessed Allows modules to access coordinates,
257      *                                box and pbc during grompp
258      * MDLogger Allows MdModule to use standard logging class for messages output
259      * warninp* Allows modules to make grompp warnings, notes and errors
260      * EnergyCalculationFrequencyErrors* allows modules to check if they match
261      *                                   their required calculation frequency
262      *                                   and add their error message if needed
263      *                                   to the collected error messages
264      * gmx_mtop_t* Allows modules to modify the topology during pre-processing
265      * IndexGroupsAndNames provides modules with atom indices and their names
266      * KeyValueTreeObjectBuilder enables writing of module internal data to
267      *                           .tpr files.
268      * QMInputFileName Allows QMMM module to know if user provided external QM input file
269      */
270     BuildMDModulesNotifier<const CoordinatesAndBoxPreprocessed&,
271                            const MDLogger&,
272                            warninp*,
273                            EnergyCalculationFrequencyErrors*,
274                            gmx_mtop_t*,
275                            const IndexGroupsAndNames&,
276                            KeyValueTreeObjectBuilder,
277                            const QMInputFileName&>::type preProcessingNotifier_;
278
279     /*! \brief Handles subscribing and calling checkpointing callback functions.
280      *
281      * MDModulesCheckpointReadingDataOnMaster provides modules with their
282      *                                        checkpointed data on the master
283      *                                        node and checkpoint file version
284      * MDModulesCheckpointReadingBroadcast provides modules with a communicator
285      *                                     and the checkpoint file version to
286      *                                     distribute their data
287      * MDModulesWriteCheckpointData provides the modules with a key-value-tree
288      *                              builder to store their checkpoint data and
289      *                              the checkpoint file version
290      */
291     BuildMDModulesNotifier<MDModulesCheckpointReadingDataOnMaster, MDModulesCheckpointReadingBroadcast, MDModulesWriteCheckpointData>::type
292             checkpointingNotifier_;
293
294     /*! \brief Handles subscribing and calling callbacks during simulation setup.
295      *
296      * const KeyValueTreeObject& provides modules with the internal data they
297      *                           wrote to .tpr files
298      * LocalAtomSetManager* enables modules to add atom indices to local atom sets
299      *                      to be managed
300      * const MDLogger& Allows MdModule to use standard logging class for messages output
301      * const gmx_mtop_t& provides the topology of the system to the modules
302      * MDModulesEnergyOutputToDensityFittingRequestChecker* enables modules to
303      *                      report if they want to write their energy output
304      *                      to the density fitting field in the energy files
305      * MDModulesEnergyOutputToQMMMRequestChecker* enables QMMM module to
306      *                      report if it want to write their energy output
307      *                      to the "Quantum En." field in the energy files
308      * SeparatePmeRanksPermitted* enables modules to report if they want
309      *                      to disable dedicated PME ranks
310      * const PbcType& provides modules with the periodic boundary condition type
311      *                that is used during the simulation
312      * const SimulationTimeStep& provides modules with the simulation time-step
313      *                           that allows them to interconvert between step
314      *                           time information
315      * const t_commrec& provides a communicator to the modules during simulation
316      *                  setup
317      * const MdRunInputFilename& Allows modules to know .tpr filename during mdrun
318      */
319     BuildMDModulesNotifier<const KeyValueTreeObject&,
320                            LocalAtomSetManager*,
321                            const MDLogger&,
322                            const gmx_mtop_t&,
323                            MDModulesEnergyOutputToDensityFittingRequestChecker*,
324                            MDModulesEnergyOutputToQMMMRequestChecker*,
325                            SeparatePmeRanksPermitted*,
326                            const PbcType&,
327                            const SimulationTimeStep&,
328                            const t_commrec&,
329                            const MdRunInputFilename&>::type simulationSetupNotifier_;
330 };
331
332 } // namespace gmx
333
334 #endif