dfd822757383f65e560152299ba479bca17bce53
[alexxy/gromacs.git] / src / gromacs / coordinateio / coordinatefile.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2019, 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 /*! \file
36  * \brief
37  * CoordinateFile takes care of opening files and writing output to them.
38  *
39  * \author
40  * \inpublicapi
41  * \ingroup module_coordinateio
42  */
43 #ifndef GMX_COORDINATEIO_COORDINATEFILE_H
44 #define GMX_COORDINATEIO_COORDINATEFILE_H
45
46 #include <algorithm>
47 #include <utility>
48
49 #include "gromacs/coordinateio/ioutputadapter.h"
50 #include "gromacs/coordinateio/outputadaptercontainer.h"
51 #include "gromacs/fileio/filetypes.h"
52 #include "gromacs/fileio/trxio.h"
53 #include "gromacs/selection/selection.h"
54 #include "gromacs/topology/mtop_util.h"
55 #include "gromacs/topology/topology.h"
56
57 namespace gmx
58 {
59
60 class TrajectoryFrameWriter;
61 struct OutputRequirements;
62
63 /*! \brief
64  * Factory function for TrajectoryFrameWriter.
65  *
66  * Used to initialize a new instance of TrajectoryFrameWriter with the user supplied information
67  * for writing trajectory data to disk. Information needed is the file type, file name
68  * corresponding to the type, if available topology information and selection information.
69  *
70  * If supplied, the modules contained within \p adapters are registered on
71  * the TrajectoryFrameWriter if possible.
72  *
73  * The factory function is responsible for the initial santity checks concerning file types and
74  * availability of topology information, with the registration of modules being the second part.
75  *
76  * \param[in] top                    Pointer to full topology or null.
77  * \param[in] sel                    Reference to global selection used to construct the object.
78  * \param[in] filename               Name of new output file, used to deduce file type.
79  * \param[in] atoms                  Smart Pointer to atoms data or null.
80  * \param[in] requirements           Container for settings obtained to specify which
81  *                                   OutputAdapters should be registered.
82  * \throws    InconsistentInputError When user input and requirements don't match.
83  */
84 std::unique_ptr<TrajectoryFrameWriter> createTrajectoryFrameWriter(const gmx_mtop_t*  top,
85                                                                    const Selection&   sel,
86                                                                    const std::string& filename,
87                                                                    AtomsDataPtr       atoms,
88                                                                    OutputRequirements requirements);
89
90 /*!\brief
91  * Low level method to take care of only file opening and closing.
92  *
93  * \inpublicapi
94  * \ingroup module_coordinateio
95  *
96  */
97 class TrajectoryFileOpener
98 {
99 public:
100     /*! \brief
101      * Constructor, taking all arguments needed to open valid coordinate files of any type.
102      *
103      * \param[in] name Name of the file to create.
104      * \param[in] filetype Internal filetype to know which kind we are going to have.
105      * \param[in] sel Reference to selection of atoms to write. Needs to be valid for
106      *                longer than the lifetime of the object created here.
107      * \param[in] mtop Topology used to create TNG output. Needs to be valid for longer
108      *                 than the object created here.
109      */
110     TrajectoryFileOpener(const std::string& name, int filetype, const Selection& sel, const gmx_mtop_t* mtop) :
111         outputFileName_(name),
112         outputFile_(nullptr),
113         filetype_(filetype),
114         sel_(sel),
115         mtop_(mtop)
116     {
117     }
118
119     /*! \brief
120      * Closes new trajectory file after finishing the writing to it.
121      */
122     ~TrajectoryFileOpener();
123
124     /*! \brief
125      * Get access to initialized output file object.
126      *
127      * Performs lazy initialization if needed.
128      */
129     t_trxstatus* outputFile();
130
131 private:
132     //! Name for the new coordinate file.
133     std::string outputFileName_;
134
135     //! File pointer to the coordinate file being written.
136     t_trxstatus* outputFile_;
137
138     //! Storage of file type for determing what kind of file will be written to disk.
139     int filetype_;
140
141     /*! \brief
142      * Selection of atoms to write out.
143      *
144      * Currently, CoordinateFile expects that the lifetime of the selection is longer
145      * than that of itself, and that the selection remains unchanged during this lifetime.
146      * A better approach will be to pass the selection to it and expect it to
147      * manage the lifetime instead.
148      */
149     const Selection& sel_;
150
151     //! Pointer to topology information if available.
152     const gmx_mtop_t* mtop_;
153 };
154
155 /*!\brief
156  * Writes coordinate frames to a sink, e.g. a trajectory file.
157  *
158  * Writes all frames passed to the trajectory file handle it
159  * manages. It can use IOutputAdapter modules to transform the
160  * frame data before writing. If any transform modules are used,
161  * makes a deep copy of the frame contents.
162  *
163  * \inpublicapi
164  * \ingroup module_coordinateio
165  *
166  */
167 class TrajectoryFrameWriter
168 {
169 public:
170     friend std::unique_ptr<TrajectoryFrameWriter> createTrajectoryFrameWriter(const gmx_mtop_t* top,
171                                                                               const Selection&  sel,
172                                                                               const std::string& filename,
173                                                                               AtomsDataPtr atoms,
174                                                                               OutputRequirements requirements);
175
176     /*! \brief
177      * Writes the input frame, after applying any IOutputAdapters.
178      *
179      * \param[in] framenumber Number of frame being currently processed.
180      * \param[in] input View of the constant t_trxframe object provided by the
181      *                  method that calls the output manager.
182      */
183     void prepareAndWriteFrame(int framenumber, const t_trxframe& input);
184
185 private:
186     /*! \brief
187      * Creates fully initialized object.
188      *
189      * \param[in] name Name of the file to create.
190      * \param[in] filetype Internal filetype to know which kind we are going to have.
191      * \param[in] sel Reference to selection of atoms to write. Needs to be valid for
192      *                longer than the lifetime of the object created here.
193      * \param[in] mtop Topology used to create TNG output. Needs to be valid for longer
194      *                 than the object created here.
195      * \param[in] adapters Container of methods that can modify the information written
196      *                     to the new file.
197      */
198     TrajectoryFrameWriter(const std::string&     name,
199                           int                    filetype,
200                           const Selection&       sel,
201                           const gmx_mtop_t*      mtop,
202                           OutputAdapterContainer adapters) :
203         file_(name, filetype, sel, mtop),
204         outputAdapters_(std::move(adapters))
205     {
206     }
207
208     //! Underlying object for open/writing to file.
209     TrajectoryFileOpener file_;
210
211     //! Storage for list of output adapters.
212     OutputAdapterContainer outputAdapters_;
213
214     //! Local storage for modified positions.
215     std::vector<RVec> localX_;
216     //! Local storage for modified velocities.
217     std::vector<RVec> localV_;
218     //! Local storage for modified forces.
219     std::vector<RVec> localF_;
220     //! Local storage for modified indices.
221     std::vector<int> localIndex_;
222 };
223
224 //! Smart pointer to manage the TrajectoryFrameWriter object.
225 using TrajectoryFrameWriterPointer = std::unique_ptr<TrajectoryFrameWriter>;
226
227 } // namespace gmx
228
229 #endif