Squash SYCL DeviceContext and DeviceStream
[alexxy/gromacs.git] / src / gromacs / analysisdata / datamodule.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
5  * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \file
37  * \brief
38  * Declares gmx::IAnalysisDataModule and related convenience classes.
39  *
40  * \author Teemu Murtola <teemu.murtola@gmail.com>
41  * \inlibraryapi
42  * \ingroup module_analysisdata
43  */
44 #ifndef GMX_ANALYSISDATA_DATAMODULE_H
45 #define GMX_ANALYSISDATA_DATAMODULE_H
46
47 namespace gmx
48 {
49
50 class AbstractAnalysisData;
51 class AnalysisDataFrameHeader;
52 class AnalysisDataParallelOptions;
53 class AnalysisDataPointSetRef;
54
55 /*! \brief
56  * Interface for a module that gets notified whenever data is added.
57  *
58  * The interface provides one method (flags()) that describes features of
59  * data objects the module supports.  Only most common features are included
60  * in the flags; custom checks can be implemented in the dataStarted() and/or
61  * parallelDataStarted() methods (see below).
62  * All other methods in the interface are callbacks that are called by the
63  * data object to which the module is attached to describe the data.
64  * See \ref module_analysisdata for an overview of the notifications the
65  * modules receive, and \ref page_analysisdata for overview of the terminology.
66  *
67  * Concrete modules typically do not directly derive from this interface, but
68  * from either AnalysisDataModuleSerial or AnalysisDataModuleParallel.
69  * Both these classes implement one of dataStarted()/parallelDataStarted() by
70  * forwarding the calls to the other method of this pair.  This allows the
71  * module to only implement the initialization once, without needing to worry
72  * how to correctly handle both cases.
73  *
74  * Currently, if the module throws an exception, it requires the analysis tool
75  * to terminate, since AbstractAnalysisData will be left in a state where it
76  * is not possible to continue processing.  See a related todo item in
77  * AbstractAnalysisData.
78  *
79  * \inlibraryapi
80  * \ingroup module_analysisdata
81  */
82 class IAnalysisDataModule
83 {
84 public:
85     /*! \brief
86      * Possible flags for flags().
87      */
88     enum Flag
89     {
90         //! The module can process multipoint data.
91         efAllowMultipoint = 1 << 0,
92         //! The module does not make sense for non-multipoint data.
93         efOnlyMultipoint = 1 << 1,
94         //! The module can process data with more than one column.
95         efAllowMulticolumn = 1 << 2,
96         //! The module can process data with missing points.
97         efAllowMissing = 1 << 3,
98         //! The module can process data with multiple data sets.
99         efAllowMultipleDataSets = 1 << 4
100     };
101
102     virtual ~IAnalysisDataModule() {}
103
104     /*! \brief
105      * Returns properties supported by the module.
106      *
107      * The return value of this method should not change after the module
108      * has been added to a data (this responsibility can, and in most cases
109      * must, be delegated to the user of the module).
110      *
111      * The purpose of this method is to remove the need for common checks
112      * for data compatibility in the classes that implement the interface.
113      * Instead, AbstractAnalysisData performs these checks based on the
114      * flags provided.
115      *
116      * Does not throw.
117      */
118     virtual int flags() const = 0;
119
120     /*! \brief
121      * Called (once) when the data has been set up properly.
122      *
123      * \param[in] data  Data object to which the module is added.
124      * \throws    APIError if the provided data is not compatible.
125      * \throws    unspecified  Can throw any exception required by the
126      *      implementing class to report errors.
127      *
128      * When the data is ready, either this method or parallelDataStarted()
129      * is called, depending on the nature of the input data.  If this
130      * method is called, the input data will always present the frames in
131      * sequential order.
132      *
133      * The data to which the module is attached is passed as an argument
134      * to provide access to properties of the data for initialization
135      * and/or validation.  The module can also call
136      * AbstractAnalysisData::requestStorage() if needed.
137      *
138      * This is the only place where the module gets access to the data;
139      * if properties of the data are required later, the module should
140      * store them internally.  It is guaranteed that the data properties
141      * (column count, whether it's multipoint) do not change once this
142      * method has been called.
143      *
144      * Notice that \p data will be a proxy object if the module is added as
145      * a column module, not the data object for which
146      * AbstractAnalysisData::addColumnModule() was called.
147      */
148     virtual void dataStarted(AbstractAnalysisData* data) = 0;
149     /*! \brief
150      * Called (once) for parallel data when the data has been set up.
151      *
152      * \param[in] data     Data object to which the module is added.
153      * \param[in] options  Parallelization properties of the input data.
154      * \returns   true if the module can process the input in
155      *      non-sequential order.
156      * \throws    APIError if the provided data is not compatible.
157      * \throws    unspecified  Can throw any exception required by the
158      *      implementing class to report errors.
159      *
160      * This method is called instead of dataStarted() if the input data has
161      * the capability to present data in non-sequential order.
162      * If the method returns true, then the module accepts this and frame
163      * notification methods may be called in that non-sequential order.
164      * If the method returns false, then the frame notification methods are
165      * called in sequential order, as if dataStarted() had been called.
166      *
167      * See dataStarted() for general information on initializing the data.
168      * That applies to this method as well, with the exception that calling
169      * AbstractAnalysisData::requestStorage() is currently not very well
170      * supported (or rather, accessing the requested storage doesn't work).
171      */
172     virtual bool parallelDataStarted(AbstractAnalysisData*              data,
173                                      const AnalysisDataParallelOptions& options) = 0;
174     /*! \brief
175      * Called at the start of each data frame.
176      *
177      * \param[in] frame  Header information for the frame that is starting.
178      * \throws    unspecified  Can throw any exception required by the
179      *      implementing class to report errors.
180      */
181     virtual void frameStarted(const AnalysisDataFrameHeader& frame) = 0;
182     /*! \brief
183      * Called one or more times during each data frame.
184      *
185      * \param[in] points  Set of points added (also provides access to
186      *      frame-level data).
187      * \throws    APIError if the provided data is not compatible.
188      * \throws    unspecified  Can throw any exception required by the
189      *      implementing class to report errors.
190      *
191      * Can be called once or multiple times for a frame.  For all data
192      * objects currently implemented in the library (and all objects that
193      * will use AnalysisDataStorage for internal implementation), it is
194      * called exactly once for each frame if the data is not multipoint,
195      * but currently this restriction is not enforced.
196      */
197     virtual void pointsAdded(const AnalysisDataPointSetRef& points) = 0;
198     /*! \brief
199      * Called when a data frame is finished.
200      *
201      * \param[in] header  Header information for the frame that is ending.
202      * \throws    unspecified  Can throw any exception required by the
203      *      implementing class to report errors.
204      */
205     virtual void frameFinished(const AnalysisDataFrameHeader& header) = 0;
206     /*! \brief
207      * Called in sequential order for each frame after they are finished.
208      *
209      * \param[in] frameIndex   Index of the next finished frame.
210      * \throws    unspecified  Can throw any exception required by the
211      *      implementing class to report errors.
212      *
213      * This method is called after frameFinished(), but with an additional
214      * constraint that it is always called in serial and with an increasing
215      * \p frameIndex.  Parallel data modules need this to serialize their
216      * data for downstream serial modules; AnalysisDataModuleSerial provides
217      * an empty implementation, as there frameFinished() can be used for
218      * the same purpose.
219      */
220     virtual void frameFinishedSerial(int frameIndex) = 0;
221     /*! \brief
222      * Called (once) when no more data is available.
223      *
224      * \throws    unspecified  Can throw any exception required by the
225      *      implementing class to report errors.
226      */
227     virtual void dataFinished() = 0;
228 };
229
230 /*! \brief
231  * Convenience base class for serial analysis data modules.
232  *
233  * Implements the parallelDataStarted() method such that initialization is
234  * always forwarded to dataStarted(), and the module always behaves as serial
235  * (parallelDataStarted() returns false).
236  *
237  * \inlibraryapi
238  * \ingroup module_analysisdata
239  */
240 class AnalysisDataModuleSerial : public IAnalysisDataModule
241 {
242 public:
243     ~AnalysisDataModuleSerial() override {}
244
245     int flags() const override = 0;
246
247     void dataStarted(AbstractAnalysisData* data) override              = 0;
248     void frameStarted(const AnalysisDataFrameHeader& frame) override   = 0;
249     void pointsAdded(const AnalysisDataPointSetRef& points) override   = 0;
250     void frameFinished(const AnalysisDataFrameHeader& header) override = 0;
251     void dataFinished() override                                       = 0;
252
253 private:
254     bool parallelDataStarted(AbstractAnalysisData* data, const AnalysisDataParallelOptions& options) override;
255     void frameFinishedSerial(int /*frameIndex*/) override {}
256 };
257
258 /*! \brief
259  * Convenience base class for parallel analysis data modules.
260  *
261  * Implements the dataStarted() method such that initialization is always done
262  * in parallelDataStarted().  dataStarted() calls are forwarded to
263  * parallelDataStarted() using a dummy serial AnalysisDataParallelOptions.
264  *
265  * \inlibraryapi
266  * \ingroup module_analysisdata
267  */
268 class AnalysisDataModuleParallel : public IAnalysisDataModule
269 {
270 public:
271     ~AnalysisDataModuleParallel() override {}
272
273     int flags() const override = 0;
274
275     bool parallelDataStarted(AbstractAnalysisData*              data,
276                              const AnalysisDataParallelOptions& options) override = 0;
277     void frameStarted(const AnalysisDataFrameHeader& frame) override              = 0;
278     void pointsAdded(const AnalysisDataPointSetRef& points) override              = 0;
279     void frameFinished(const AnalysisDataFrameHeader& header) override            = 0;
280     void frameFinishedSerial(int index) override                                  = 0;
281     void dataFinished() override                                                  = 0;
282
283 private:
284     void dataStarted(AbstractAnalysisData* data) override;
285 };
286
287 } // namespace gmx
288
289 #endif