Merge remote-tracking branch 'origin/release-4-6'
[alexxy/gromacs.git] / src / gromacs / analysisdata / arraydata.h
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11  * Copyright (c) 2001-2009, The GROMACS development team,
12  * check out http://www.gromacs.org for more information.
13
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \file
32  * \brief
33  * Declares gmx::AbstractAnalysisArrayData and gmx::AnalysisArrayData.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inpublicapi
37  * \ingroup module_analysisdata
38  */
39 #ifndef GMX_ANALYSISDATA_ARRAYDATA_H
40 #define GMX_ANALYSISDATA_ARRAYDATA_H
41
42 #include <vector>
43
44 #include "../utility/gmxassert.h"
45
46 #include "abstractdata.h"
47 #include "dataframe.h"
48
49 namespace gmx
50 {
51
52 /*! \brief
53  * Abstract base class for data objects that present in-memory data.
54  *
55  * This class implements a subclass of AbstractAnalysisData that presents an
56  * in-memory array through the AbstractAnalysisData interface.  Subclasses
57  * should initialize the in-memory array through the provided protected member
58  * functions.  This class provides public accessor methods for read access to
59  * the data.
60  *
61  * Public accessor methods in this class do not throw, but assert if data is
62  * accessed before it is available.
63  *
64  * \todo
65  * Add methods to take full advantage of AnalysisDataValue features.
66  *
67  * \inlibraryapi
68  * \ingroup module_analysisdata
69  */
70 class AbstractAnalysisArrayData : public AbstractAnalysisData
71 {
72     public:
73         virtual ~AbstractAnalysisArrayData();
74
75         /*! \brief
76          * Returns the number of rows in the data array.
77          *
78          * This function is identical to frameCount(), except that frameCount()
79          * returns 0 before valuesReady() has been called.
80          */
81         int rowCount() const { return _nrows; }
82         //! Returns true if values have been allocated.
83         bool isAllocated() const { return !_value.empty(); }
84         //! Returns the x value of the first frame.
85         real xstart() const { return _xstart; }
86         //! Returns the step between frame x values.
87         real xstep() const { return _xstep; }
88         //! Returns the x value of a row.
89         real xvalue(int row) const
90         {
91             GMX_ASSERT(row >= 0 && row < rowCount(), "Row index out of range");
92             return xstart() + row * xstep();
93         }
94         //! Returns a given array element.
95         real value(int row, int col) const
96         {
97             GMX_ASSERT(row >= 0 && row < rowCount(), "Row index out of range");
98             GMX_ASSERT(col >= 0 && col < columnCount(), "Column index out of range");
99             GMX_ASSERT(isAllocated(), "Data array not allocated");
100             return _value[row * columnCount() + col].value();
101         }
102
103     protected:
104         /*! \brief
105          * Initializes an empty array data object.
106          *
107          * \throws std::bad_alloc if out of memory.
108          */
109         AbstractAnalysisArrayData();
110
111         /*! \brief
112          * Sets the number of columns in the data array.
113          *
114          * \param[in] ncols  Number of columns in the data.
115          *
116          * Cannot be called after allocateValues().
117          *
118          * See AbstractAnalysisData::setColumnCount() for exception behavior.
119          */
120         void setColumnCount(int ncols);
121         /*! \brief
122          * Sets the number of rows in the data array.
123          *
124          * \param[in] nrows  Number of rows in the data.
125          *
126          * Cannot be called after allocateValues().
127          *
128          * Does not throw.
129          */
130         void setRowCount(int nrows);
131         /*! \brief
132          * Allocates memory for the values.
133          *
134          * \throws std::bad_alloc if memory allocation fails.
135          *
136          * setColumnCount() and setRowCount() must have been called.
137          *
138          * Strong exception safety guarantee.
139          */
140         void allocateValues();
141         /*! \brief
142          * Sets the values reported as x values for frames.
143          *
144          * \param[in] start  x value for the first frame.
145          * \param[in] step   Step between x values of successive frames.
146          *
147          * Must not be called after valuesReady().
148          *
149          * Does not throw.
150          */
151         void setXAxis(real start, real step);
152         //! Returns a reference to a given array element.
153         real &value(int row, int col)
154         {
155             GMX_ASSERT(row >= 0 && row < rowCount(), "Row index out of range");
156             GMX_ASSERT(col >= 0 && col < columnCount(), "Column index out of range");
157             GMX_ASSERT(isAllocated(), "Data array not allocated");
158             return _value[row * columnCount() + col].value();
159         }
160         /*! \brief
161          * Sets the value of an element in the array.
162          *
163          * \param[in] row  Zero-based row index for the value.
164          * \param[in] col  Zero-based column index for the value.
165          * \param[in] val  Value to set in the given location.
166          *
167          * Does not throw.
168          */
169         void setValue(int row, int col, real val)
170         {
171             value(row, col) = val;
172         }
173         /*! \brief
174          * Notifies modules of the data.
175          *
176          * \throws    unspecified Any exception thrown by attached data modules
177          *      in data notification methods.
178          *
179          * This function should be called once the values in the array
180          * have been initialized.  The values should not be changed after this
181          * function has been called.
182          */
183         void valuesReady();
184
185         /*! \brief
186          * Copies the contents into a new object.
187          *
188          * \param[in]     src  Object to copy data from.
189          * \param[in,out] dest Empty array data object to copy data to.
190          * \throws std::bad_alloc if memory allocation for \p dest fails.
191          *
192          * \p dest should not have previous contents.
193          */
194         static void copyContents(const AbstractAnalysisArrayData *src,
195                                  AbstractAnalysisArrayData *dest);
196
197     private:
198         virtual AnalysisDataFrameRef tryGetDataFrameInternal(int index) const;
199         virtual bool requestStorageInternal(int nframes);
200
201         int                  _nrows;
202         std::vector<AnalysisDataValue> _value;
203         real                 _xstart;
204         real                 _xstep;
205         bool                 _bReady;
206
207         // Copy and assign disallowed by base.
208 };
209
210 /*! \brief
211  * Simple in-memory data array.
212  *
213  * This class is a simple alternative to AnalysisData for in-memory data arrays
214  * that are constructed in-place.
215  *
216  * Public accessor methods in this class do not throw, but assert if data is
217  * accessed before it is available.
218  *
219  * \if libapi
220  * This class exposes the protected functions of AbstractAnalysisArrayData for
221  * users.
222  * \endif
223  *
224  * \inpublicapi
225  * \ingroup module_analysisdata
226  */
227 class AnalysisArrayData : public AbstractAnalysisArrayData
228 {
229     public:
230         /*! \brief
231          * Initializes an empty array data object.
232          *
233          * \throws std::bad_alloc if out of memory.
234          */
235         AnalysisArrayData() {}
236
237         // TODO: These statements cause Doxygen to generate confusing
238         // documentation.
239         using AbstractAnalysisArrayData::setColumnCount;
240         using AbstractAnalysisArrayData::setRowCount;
241         using AbstractAnalysisArrayData::allocateValues;
242         using AbstractAnalysisArrayData::setXAxis;
243         using AbstractAnalysisArrayData::value;
244         using AbstractAnalysisArrayData::setValue;
245         using AbstractAnalysisArrayData::valuesReady;
246
247         // Copy and assign disallowed by base.
248 };
249
250 } // namespace gmx
251
252 #endif