1 /**
2  *  @file Array.h Header file for class Cantera::Array2D
3  */
4 
5 // This file is part of Cantera. See License.txt in the top-level directory or
6 // at https://cantera.org/license.txt for license and copyright information.
7 
8 #ifndef CT_ARRAY_H
9 #define CT_ARRAY_H
10 
11 #include "ct_defs.h"
12 #include <iostream>
13 
14 namespace Cantera
15 {
16 
17 //!  A class for 2D arrays stored in column-major (Fortran-compatible) form.
18 /*!
19  * In this form, the data entry for an n row, m col matrix is
20  *
21  *       index = i + (n-1) * j
22  *
23  * where
24  *
25  *     J(i,j) = data_start + index
26  *         i = row
27  *         j = column
28  */
29 class Array2D
30 {
31 public:
32     //! Type definition for the iterator class that is can be used by Array2D
33     //! types.
34     /*!
35      * This is just equal to vector_fp::iterator.
36      */
37     typedef vector_fp::iterator iterator;
38 
39     //! Type definition for the const_iterator class that is can be used by
40     //! Array2D types.
41     /*!
42      * This is just equal to vector_fp::const_iterator.
43      */
44     typedef vector_fp::const_iterator const_iterator;
45 
46     /**
47      * Default constructor. Create an empty array.
48      */
49     Array2D();
50 
51     //! Constructor.
52     /*!
53      * Create an \c m by \c n array, and initialize all elements to \c v.
54      *
55      * @param m   Number of rows
56      * @param n   Number of columns
57      * @param v   Default fill value. The default is 0.0
58      */
59     Array2D(const size_t m, const size_t n, const double v=0.0);
60 
61     //! Constructor.
62     /*!
63      * Create an \c m by \c n array, initialized with the contents of the array
64      * \c values.
65      *
66      * @param m   Number of rows
67      * @param n   Number of columns
68      * @param values Initial values of the array. Must be of length m*n, and
69      *     stored in column-major order.
70      */
71     Array2D(const size_t m, const size_t n, const double* values);
72 
73     Array2D(const Array2D& y);
74 
~Array2D()75     virtual ~Array2D() {}
76 
77     Array2D& operator=(const Array2D& y);
78 
79     //! Resize the array, and fill the new entries with 'v'
80     /*!
81      * @param n  This is the number of rows
82      * @param m  This is the number of columns in the new matrix
83      * @param v  Default fill value -> defaults to zero.
84      */
85     void resize(size_t n, size_t m, double v=0.0);
86 
87     //! Append a column to the existing matrix using a std vector
88     /*!
89      * This operation will add a column onto the existing matrix.
90      *
91      * @param c  This vector is the entries in the column to be added. It must
92      *           have a length equal to m_nrows or greater.
93      */
94     void appendColumn(const vector_fp& c);
95 
96     //! Append a column to the existing matrix
97     /*!
98      * This operation will add a column onto the existing matrix.
99      *
100      * @param c  This vector of doubles is the entries in the column to be
101      *           added. It must have a length equal to m_nrows or greater.
102      */
103     void appendColumn(const double* const c);
104 
105     //! Set the nth row to array rw
106     /*!
107      * @param  n   Index of the row to be changed
108      * @param  rw  Vector for the row. Must have a length of m_ncols.
109      */
110     void setRow(size_t n, const double* const rw);
111 
112     //! Get the nth row and return it in a vector
113     /*!
114      * @param n    Index of the row to be returned.
115      * @param rw   Return Vector for the operation. Must have a length of
116      *             m_ncols.
117      */
118     void getRow(size_t n, double* const rw);
119 
120     //! Set the values in column m to those in array col
121     /*!
122      * A(i,m) = col(i)
123      *
124      * @param m   Column to set
125      * @param col pointer to a col vector. Vector must have a length of m_nrows.
126      */
127     void setColumn(size_t m, double* const col);
128 
129     //! Get the values in column m
130     /*!
131      * col(i) =  A(i,m)
132      *
133      * @param m    Column to set
134      * @param col  pointer to a col vector that will be returned
135      */
136     void getColumn(size_t m, double* const col);
137 
138     //! Set all of the entries to zero
zero()139     void zero() {
140         m_data.assign(m_data.size(), 0.0);
141     }
142 
143     //! Allows setting elements using the syntax A(i,j) = x.
144     /*!
145      *  @param  i            row index
146      *  @param  j            column index.
147      *  @returns a reference to A(i,j) which may be assigned.
148      */
operator()149     doublereal& operator()(size_t i, size_t j) {
150         return value(i,j);
151     }
152 
153     //! Allows retrieving elements using the syntax x = A(i,j).
154     /*!
155      * @param i   Index for the row to be retrieved
156      * @param j   Index for the column to be retrieved.
157      * @returns the value of the matrix entry
158      */
operator()159     doublereal operator()(size_t i, size_t j) const {
160         return value(i,j);
161     }
162 
163     //! Returns a changeable reference to position in the matrix
164     /*!
165      * Returns a reference to the matrix's (i,j) element. This may be used as an
166      * L value.
167      *
168      * @param i   The row index
169      * @param j   The column index
170      * @returns a changeable reference to the matrix entry
171      */
value(size_t i,size_t j)172     doublereal& value(size_t i, size_t j) {
173         return m_data[m_nrows*j + i];
174     }
175 
176     //! Returns the value of a single matrix entry
177     /*!
178      * Returns the value of the matrix position (i,j) element.
179      *
180      * @param i   The row index
181      * @param j   The column index
182      */
value(size_t i,size_t j)183     doublereal value(size_t i, size_t j) const {
184         return m_data[m_nrows*j + i];
185     }
186 
187     /// Number of rows
nRows()188     size_t nRows() const {
189         return m_nrows;
190     }
191 
192     /// Number of columns
nColumns()193     size_t nColumns() const {
194         return m_ncols;
195     }
196 
197     /// Return an iterator pointing to the first element
begin()198     iterator begin() {
199         return m_data.begin();
200     }
201 
202     /// Return an iterator pointing past the last element
end()203     iterator end() {
204         return m_data.end();
205     }
206 
207     /// Return a const iterator pointing to the first element
begin()208     const_iterator begin() const {
209         return m_data.begin();
210     }
211 
212     /// Return a const iterator pointing to past the last element
end()213     const_iterator end() const {
214         return m_data.end();
215     }
216 
217     /// Return a reference to the data vector
data()218     vector_fp& data() {
219         return m_data;
220     }
221 
222     /// Return a const reference to the data vector
data()223     const vector_fp& data() const {
224         return m_data;
225     }
226 
227     //! Return a pointer to the top of column j, columns are contiguous
228     //! in memory
229     /*!
230      * @param j   Value of the column
231      * @returns a pointer to the top of the column
232      */
ptrColumn(size_t j)233     doublereal* ptrColumn(size_t j) {
234         return &m_data[m_nrows*j];
235     }
236 
237     //! Return a const pointer to the top of column j, columns are contiguous
238     //! in memory
239     /*!
240      * @param j   Value of the column
241      * @returns a const pointer to the top of the column
242      */
ptrColumn(size_t j)243     const doublereal* ptrColumn(size_t j) const {
244         return &m_data[m_nrows*j];
245     }
246 
247 protected:
248     //! Data stored in a single array
249     vector_fp m_data;
250 
251     //! Number of rows
252     size_t m_nrows;
253 
254     //! Number of columns
255     size_t m_ncols;
256 };
257 
258 //! Output the current contents of the Array2D object
259 /*!
260  * Example of usage:
261  *        s << m << endl;
262  *
263  * @param s   Reference to the ostream to write to
264  * @param m   Object of type Array2D that you are querying
265  * @returns a reference to the ostream.
266  */
267 std::ostream& operator<<(std::ostream& s, const Array2D& m);
268 
269 //! Overload the times equals operator for multiplication of a matrix and a
270 //! scalar.
271 /*!
272  * Scaled every element of the matrix by the scalar input
273  *
274  * @param m   Matrix
275  * @param a   scalar
276  */
277 void operator*=(Array2D& m, double a);
278 
279 }
280 
281 #endif
282