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