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