Use ObservablesReducer for check of DD bonded interaction count.
[alexxy/gromacs.git] / src / gromacs / modularsimulator / statepropagatordata.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 state 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_STATEPROPAGATORDATA_H
45 #define GMX_MODULARSIMULATOR_STATEPROPAGATORDATA_H
46
47 #include "gromacs/gpu_utils/hostallocator.h"
48 #include "gromacs/math/paddedvector.h"
49 #include "gromacs/math/vectypes.h"
50 #include "gromacs/mdtypes/checkpointdata.h"
51 #include "gromacs/mdtypes/forcebuffers.h"
52 #include "gromacs/utility/keyvaluetree.h"
53
54 #include "modularsimulatorinterfaces.h"
55 #include "topologyholder.h"
56
57 struct gmx_mdoutf;
58 enum class PbcType : int;
59 struct t_commrec;
60 struct t_inputrec;
61 class t_state;
62 struct t_mdatoms;
63 struct t_trxframe;
64
65 namespace gmx
66 {
67 enum class CheckpointDataOperation;
68 enum class ConstraintVariable;
69 class EnergyData;
70 class FreeEnergyPerturbationData;
71 class GlobalCommunicationHelper;
72 class LegacySimulatorData;
73 class ModularSimulatorAlgorithmBuilderHelper;
74 class ObservablesReducer;
75
76 /*! \internal
77  * \ingroup module_modularsimulator
78  * \brief StatePropagatorData and associated data
79  *
80  * The `StatePropagatorData` contains a little more than the pure
81  * statistical-physical micro state, namely the positions,
82  * velocities, forces, and box matrix, as well as a backup of
83  * the positions and box of the last time step. While it takes
84  * part in the simulator loop via its member class `Element`
85  * to be able to backup positions /
86  * boxes and save the current state if needed, it's main purpose
87  * is to offer access to its data via getter methods. All elements
88  * reading or writing to this data need a pointer to the
89  * `StatePropagatorData` and need to request their data explicitly. This
90  * will later simplify the understanding of data dependencies
91  * between elements.
92  *
93  * Note that the `StatePropagatorData` can be converted to and from the
94  * legacy `t_state` object. This is useful when dealing with
95  * functionality which has not yet been adapted to use the new
96  * data approach - of the elements currently implemented, only
97  * domain decomposition, PME load balancing, and the initial
98  * constraining are using this.
99  */
100 class StatePropagatorData final
101 {
102 public:
103     //! Constructor
104     StatePropagatorData(int                numAtoms,
105                         FILE*              fplog,
106                         const t_commrec*   cr,
107                         t_state*           globalState,
108                         t_state*           localState,
109                         bool               useGPU,
110                         bool               canMoleculesBeDistributedOverPBC,
111                         bool               writeFinalConfiguration,
112                         const std::string& finalConfigurationFilename,
113                         const t_inputrec*  inputrec,
114                         const t_mdatoms*   mdatoms,
115                         const gmx_mtop_t&  globalTop);
116
117     //! Destructor (allows forward declaration of internal type)
118     ~StatePropagatorData();
119
120     // Allow access to state
121     //! Get write access to position vector
122     ArrayRefWithPadding<RVec> positionsView();
123     //! Get read access to position vector
124     ArrayRefWithPadding<const RVec> constPositionsView() const;
125     //! Get write access to previous position vector
126     ArrayRefWithPadding<RVec> previousPositionsView();
127     //! Get read access to previous position vector
128     ArrayRefWithPadding<const RVec> constPreviousPositionsView() const;
129     //! Get write access to velocity vector
130     ArrayRefWithPadding<RVec> velocitiesView();
131     //! Get read access to velocity vector
132     ArrayRefWithPadding<const RVec> constVelocitiesView() const;
133     //! Get write access to force vector
134     ForceBuffersView& forcesView();
135     //! Get read access to force vector
136     const ForceBuffersView& constForcesView() const;
137     //! Get pointer to box
138     rvec* box();
139     //! Get const pointer to box
140     const rvec* constBox() const;
141     //! Get pointer to previous box
142     rvec* previousBox();
143     //! Get const pointer to previous box
144     const rvec* constPreviousBox() const;
145     //! Get the local number of atoms
146     int localNumAtoms() const;
147     //! Get the total number of atoms
148     int totalNumAtoms() const;
149
150     //! The element taking part in the simulator loop
151     class Element;
152     //! Get pointer to element (whose lifetime is managed by this)
153     Element* element();
154     //! Initial set up for the associated element
155     void setup();
156
157     //! Update the reference temperature
158     void updateReferenceTemperature(ArrayRef<const real>                temperatures,
159                                     ReferenceTemperatureChangeAlgorithm algorithm);
160     //! Helper class handling reference temperature change
161     class ReferenceTemperatureHelper;
162
163     //! Read everything that can be stored in t_trxframe from a checkpoint file
164     static void readCheckpointToTrxFrame(t_trxframe* trxFrame, ReadCheckpointData readCheckpointData);
165     //! CheckpointHelper identifier
166     static const std::string& checkpointID();
167
168     //! \cond
169     // (doxygen doesn't like these)
170     // Classes which need access to legacy state
171     friend class DomDecHelper;
172     //! \endcond
173
174 private:
175     //! Default constructor - only used internally
176     StatePropagatorData() = default;
177     //! The total number of atoms in the system
178     int totalNumAtoms_;
179     //! The local number of atoms
180     int localNAtoms_;
181     //! The position vector
182     PaddedHostVector<RVec> x_;
183     //! The position vector of the previous step
184     PaddedHostVector<RVec> previousX_;
185     //! The velocity vector
186     PaddedHostVector<RVec> v_;
187     //! The force vector
188     ForceBuffers f_;
189     //! The box matrix
190     matrix box_;
191     //! The box matrix of the previous step
192     matrix previousBox_;
193     //! The DD partitioning count
194     int ddpCount_;
195     //! The DD partitioning count for index_gl
196     int ddpCountCgGl_;
197     //! The global cg number of the local cgs
198     std::vector<int> cgGl_;
199
200     //! The global position vector
201     PaddedHostVector<RVec> xGlobal_;
202     //! The global position vector of the previous step
203     PaddedHostVector<RVec> previousXGlobal_;
204     //! The global velocity vector
205     PaddedHostVector<RVec> vGlobal_;
206     //! The global force vector
207     PaddedHostVector<RVec> fGlobal_;
208
209     //! The element
210     std::unique_ptr<Element> element_;
211     //! Instance of reference temperature helper
212     std::unique_ptr<ReferenceTemperatureHelper> referenceTemperatureHelper_;
213
214     //! Move x_ to previousX_
215     void copyPosition();
216     //! OMP helper to move x_ to previousX_
217     void copyPosition(int start, int end);
218
219     //! Helper function to read from / write to CheckpointData
220     template<CheckpointDataOperation operation>
221     void doCheckpointData(CheckpointData<operation>* checkpointData);
222
223     // Access to legacy state
224     //! Give ownership of local state resources in legacy format
225     t_state* localState();
226     //! Take ownership of local state resources in legacy format
227     void setLocalState(t_state* state);
228     /*! \brief Deep copy the local state into the provided copy and
229      * return it
230      *
231      * In order to minimize reallocations, this function takes as a sink
232      * a local state object owned by the caller, copies the current local
233      * state into it, and returns the same object via a move.
234      */
235     std::unique_ptr<t_state> copyLocalState(std::unique_ptr<t_state> copy);
236     //! Get a pointer to the global state
237     t_state* globalState();
238     //! Get a force pointer
239     ForceBuffers* forcePointer();
240
241     //! Whether we're doing VV and need to reset velocities after the first half step
242     bool vvResetVelocities_;
243     //! Velocities backup for VV
244     PaddedHostVector<RVec> velocityBackup_;
245     //! Function resetting the velocities
246     void resetVelocities();
247
248     //! Whether planned total number of steps was reached (used for final output only)
249     bool isRegularSimulationEnd_;
250     //! The signalled last step (used for final output only)
251     Step lastStep_;
252
253     // Access to ISimulator data
254     //! Full simulation state (only non-nullptr on master rank).
255     t_state* globalState_;
256     //! Local simulation state
257     t_state* localState_;
258 };
259
260 /*! \internal
261  * \ingroup module_modularsimulator
262  * \brief Element for StatePropagatorData
263  *
264  * The `StatePropagatorData::Element` takes part in the simulator run, as it might
265  * have to save a valid state at the right moment during the
266  * integration. Placing the StatePropagatorData::Element correctly is the
267  * duty of the simulator builder - this might be automatized later
268  * if we have enough meta-data of the variables (i.e., if
269  * `StatePropagatorData` knows at which time the variables currently are,
270  * and can decide when a valid state (full-time step of all
271  * variables) is reached. The `StatePropagatorData::Element` is also a client of
272  * both the trajectory signaller and writer - it will save a
273  * state for later writeout during the simulator step if it
274  * knows that trajectory writing will occur later in the step,
275  * and it knows how to write to file given a file pointer by
276  * the `TrajectoryElement`. It is also responsible to store
277  * the state for checkpointing.
278  *
279  */
280 class StatePropagatorData::Element final :
281     public ISimulatorElement,
282     public ITrajectoryWriterClient,
283     public ITrajectorySignallerClient,
284     public ICheckpointHelperClient,
285     public ILastStepSignallerClient
286 {
287 public:
288     //! Constructor
289     Element(StatePropagatorData* statePropagatorData,
290             FILE*                fplog,
291             const t_commrec*     cr,
292             int                  nstxout,
293             int                  nstvout,
294             int                  nstfout,
295             int                  nstxout_compressed,
296             bool                 canMoleculesBeDistributedOverPBC,
297             bool                 writeFinalConfiguration,
298             std::string          finalConfigurationFilename,
299             const t_inputrec*    inputrec,
300             const gmx_mtop_t&    globalTop);
301
302     /*! \brief Register run function for step / time
303      *
304      * This needs to be called during the integration part of the simulator,
305      * at the moment at which the state is at a full time step. Positioning
306      * this element is the responsibility of the programmer writing the
307      * integration algorithm! If the current step is a trajectory writing
308      * step, StatePropagatorData will save a backup for later writeout.
309      *
310      * This is also the place at which the current state becomes the previous
311      * state.
312      *
313      * \param step                 The step number
314      * \param time                 The time
315      * \param registerRunFunction  Function allowing to register a run function
316      */
317     void scheduleTask(Step step, Time time, const RegisterRunFunction& registerRunFunction) override;
318
319     /*! \brief Backup starting velocities
320      *
321      * This is only needed for vv, where the first (velocity) half step is only
322      * used to compute the constraint virial, but the velocities need to be reset
323      * after.
324      * TODO: There must be a more elegant solution to this!
325      */
326     void elementSetup() override;
327
328     //! No element teardown needed
329     void elementTeardown() override {}
330
331     //! Set free energy data
332     void setFreeEnergyPerturbationData(FreeEnergyPerturbationData* freeEnergyPerturbationData);
333
334     //! ICheckpointHelperClient write checkpoint implementation
335     void saveCheckpointState(std::optional<WriteCheckpointData> checkpointData, const t_commrec* cr) override;
336     //! ICheckpointHelperClient read checkpoint implementation
337     void restoreCheckpointState(std::optional<ReadCheckpointData> checkpointData, const t_commrec* cr) override;
338     //! ICheckpointHelperClient key implementation
339     const std::string& clientID() override;
340
341     /*! \brief Factory method implementation
342      *
343      * \param legacySimulatorData  Pointer allowing access to simulator level data
344      * \param builderHelper  ModularSimulatorAlgorithmBuilder helper object
345      * \param statePropagatorData  Pointer to the \c StatePropagatorData object
346      * \param energyData  Pointer to the \c EnergyData object
347      * \param freeEnergyPerturbationData  Pointer to the \c FreeEnergyPerturbationData object
348      * \param globalCommunicationHelper   Pointer to the \c GlobalCommunicationHelper object
349      * \param observablesReducer          Pointer to the \c ObservablesReducer object
350      *
351      * \return  Pointer to the element to be added. Element needs to have been stored using \c storeElement
352      */
353     static ISimulatorElement* getElementPointerImpl(LegacySimulatorData* legacySimulatorData,
354                                                     ModularSimulatorAlgorithmBuilderHelper* builderHelper,
355                                                     StatePropagatorData*        statePropagatorData,
356                                                     EnergyData*                 energyData,
357                                                     FreeEnergyPerturbationData* freeEnergyPerturbationData,
358                                                     GlobalCommunicationHelper* globalCommunicationHelper,
359                                                     ObservablesReducer*        observablesReducer);
360
361 private:
362     //! Pointer to the associated StatePropagatorData
363     StatePropagatorData* statePropagatorData_;
364
365     //! The position writeout frequency
366     const int nstxout_;
367     //! The velocity writeout frequency
368     const int nstvout_;
369     //! The force writeout frequency
370     const int nstfout_;
371     //! The compressed position writeout frequency
372     const int nstxout_compressed_;
373
374     //! Pointer to keep a backup of the state for later writeout
375     std::unique_ptr<t_state> localStateBackup_;
376     /*! \brief Whether the contents of localStateBackup_ are logically valid
377      *
378      * This ensures that we don't make a second backup without consuming the
379      * first. */
380     bool localStateBackupValid_ = false;
381     //! Step at which next writeout occurs
382     Step writeOutStep_;
383     //! Backup current state
384     void saveState();
385
386     //! ITrajectorySignallerClient implementation
387     std::optional<SignallerCallback> registerTrajectorySignallerCallback(TrajectoryEvent event) override;
388
389     //! ITrajectoryWriterClient implementation
390     std::optional<ITrajectoryWriterCallback> registerTrajectoryWriterCallback(TrajectoryEvent event) override;
391
392     //! ILastStepSignallerClient implementation (used for final output only)
393     std::optional<SignallerCallback> registerLastStepCallback() override;
394
395     //! Callback writing the state to file
396     void write(gmx_mdoutf* outf, Step step, Time time);
397
398     // TODO: Clarify relationship to data objects and find a more robust alternative to raw pointers (#3583)
399     //! Pointer to the free energy perturbation data (for trajectory writing only)
400     FreeEnergyPerturbationData* freeEnergyPerturbationData_;
401
402     //! No trajectory writer setup needed
403     void trajectoryWriterSetup(gmx_mdoutf gmx_unused* outf) override {}
404     //! Trajectory writer teardown - write final coordinates
405     void trajectoryWriterTeardown(gmx_mdoutf* outf) override;
406     //! A dummy CheckpointData - remove when we stop using the legacy trajectory writing function
407     WriteCheckpointDataHolder dummyCheckpointDataHolder_;
408
409     //! Whether planned total number of steps was reached (used for final output only)
410     bool isRegularSimulationEnd_;
411     //! The signalled last step (used for final output only)
412     Step lastStep_;
413     //! Whether system can have molecules distributed over PBC boundaries (used for final output only)
414     const bool canMoleculesBeDistributedOverPBC_;
415     //! Whether system has molecules self-interacting through PBC (used for final output only)
416     const bool systemHasPeriodicMolecules_;
417     //! The PBC type (used for final output only)
418     const PbcType pbcType_;
419     //! The (planned) last step - determines whether final configuration is written (used for final output only)
420     const Step lastPlannedStep_;
421     //! Whether final configuration was chosen in mdrun options (used for final output only)
422     const bool writeFinalConfiguration_;
423     //! The filename of the final configuration file (used for final output only)
424     const std::string finalConfigurationFilename_;
425
426     // Access to ISimulator data
427     //! Handles logging.
428     FILE* fplog_;
429     //! Handles communication.
430     const t_commrec* cr_;
431     //! Full system topology.
432     const gmx_mtop_t& top_global_;
433 };
434
435 } // namespace gmx
436
437 #endif // GMX_MODULARSIMULATOR_STATEPROPAGATORDATA_H