Cantera  2.0
Array.h
Go to the documentation of this file.
1 /**
2  * @file Array.h
3  * Header file for class Array2D
4  */
5 // Copyright 2001 California Institute of Technology
6 
7 
8 #ifndef CT_ARRAY_H
9 #define CT_ARRAY_H
10 
11 #include "ct_defs.h"
12 #include "ctexceptions.h"
13 #include "utilities.h"
14 
15 #include <cstring>
16 
17 namespace Cantera
18 {
19 
20 
21 
22 //! A class for 2D arrays stored in column-major
23 //! (Fortran-compatible) form.
24 /*!
25  * In this form, the data entry for an n row, m col
26  * matrix is
27  * index = i + (n-1) * j
28  * where
29  * J(i,j) = data_start + index
30  * i = row
31  * j = column
32  */
33 class Array2D
34 {
35 
36 public:
37 
38  //! Type definition for the iterator class that is
39  //! can be used by Array2D types.
40  /*!
41  * this is just equal to vector_fp iterator.
42  */
43  typedef vector_fp::iterator iterator;
44 
45 
46  //! Type definition for the const_iterator class that is
47  //! can be used by Array2D types.
48  /*!
49  * this is just equal to vector_fp const_iterator.
50  */
51  typedef vector_fp::const_iterator const_iterator;
52 
53  /**
54  * Default constructor. Create an empty array.
55  */
56  Array2D() :
57  m_data(0),
58  m_nrows(0),
59  m_ncols(0) {
60  }
61 
62  //! Constructor.
63  /*!
64  * Create an \c m by \c n array, and initialize
65  * all elements to \c v.
66  *
67  * @param m Number of rows
68  * @param n Number of columns
69  * @param v Default fill value. The default is 0.0
70  */
71  Array2D(const size_t m, const size_t n, const doublereal v = 0.0)
72  : m_data(0), m_nrows(m), m_ncols(n) {
73  m_data.resize(n*m);
74  std::fill(m_data.begin(), m_data.end(), v);
75  }
76 
77  //! Constructor.
78  /*!
79  * Create an \c m by \c n array, initialized with the contents
80  * of the array \c values.
81  *
82  * @param m Number of rows
83  * @param n Number of columns
84  * @param values Initial values of the array. Must be of length m*n,
85  * and stored in column-major order.
86  */
87  Array2D(const size_t m, const size_t n, const doublereal* values)
88  : m_data(0), m_nrows(m), m_ncols(n) {
89  m_data.resize(n*m);
90  std::copy(values, values + m_nrows*m_ncols, m_data.begin());
91  }
92 
93  //! Copy constructor
94  /*!
95  * @param y Array2D to make the copy from
96  */
97  Array2D(const Array2D& y) :
98  m_data(0),
99  m_nrows(0),
100  m_ncols(0) {
101  m_nrows = y.m_nrows;
102  m_ncols = y.m_ncols;
103  m_data.resize(m_nrows*m_ncols);
104  m_data = y.m_data;
105  }
106 
107  //! assignment operator
108  /*!
109  * @param y Array2D to get the values from
110  */
111  Array2D& operator=(const Array2D& y) {
112  if (&y == this) {
113  return *this;
114  }
115  m_nrows = y.m_nrows;
116  m_ncols = y.m_ncols;
117  m_data.resize(m_nrows*m_ncols);
118  m_data = y.m_data;
119  return *this;
120  }
121 
122  //! Resize the array, and fill the new entries with 'v'
123  /*!
124  * @param n This is the number of rows
125  * @param m This is the number of columns in the new matrix
126  * @param v Default fill value -> defaults to zero.
127  */
128  void resize(size_t n, size_t m, doublereal v = 0.0) {
129  m_nrows = n;
130  m_ncols = m;
131  m_data.resize(n*m, v);
132  }
133 
134  //! Copy the data from one array into another without doing any checking
135  /*!
136  * This differs from the assignment operator as no resizing is done and memcpy() is used.
137  * @param y Array to be copied
138  */
139  void copyData(const Array2D& y) {
140  size_t n = sizeof(doublereal) * m_nrows * m_ncols;
141  (void) memcpy(DATA_PTR(m_data), y.ptrColumn(0), n);
142  }
143 
144  //! Append a column to the existing matrix using a std vector
145  /*!
146  * This operation will add a column onto the existing matrix.
147  *
148  * @param c This vector<doublereal> is the entries in the
149  * column to be added. It must have a length
150  * equal to m_nrows or greater.
151  */
152  void appendColumn(const vector_fp& c) {
153  m_ncols++;
154  m_data.resize(m_nrows*m_ncols);
155  size_t m;
156  for (m = 0; m < m_nrows; m++) {
157  value(m_ncols, m) = c[m];
158  }
159  }
160 
161  //! Append a column to the existing matrix
162  /*!
163  * This operation will add a column onto the existing matrix.
164  *
165  * @param c This vector of doubles is the entries in the
166  * column to be added. It must have a length
167  * equal to m_nrows or greater.
168  */
169  void appendColumn(const doublereal* const c) {
170  m_ncols++;
171  m_data.resize(m_nrows*m_ncols);
172  size_t m;
173  for (m = 0; m < m_nrows; m++) {
174  value(m_ncols, m) = c[m];
175  }
176  }
177 
178  //! Set the nth row to array rw
179  /*!
180  * @param n Index of the row to be changed
181  * @param rw Vector for the row. Must have a length of m_ncols.
182  */
183  void setRow(size_t n, const doublereal* const rw) {
184  for (size_t j = 0; j < m_ncols; j++) {
185  m_data[m_nrows*j + n] = rw[j];
186  }
187  }
188 
189  //! Get the nth row and return it in a vector
190  /*!
191  * @param n Index of the row to be returned.
192  * @param rw Return Vector for the operation.
193  * Must have a length of m_ncols.
194  */
195  void getRow(size_t n, doublereal* const rw) {
196  for (size_t j = 0; j < m_ncols; j++) {
197  rw[j] = m_data[m_nrows*j + n];
198  }
199  }
200 
201  //! Set the values in column m to those in array col
202  /*!
203  * A(i,m) = col(i)
204  *
205  * @param m Column to set
206  * @param col pointer to a col vector. Vector
207  * must have a length of m_nrows.
208  */
209  void setColumn(size_t m, doublereal* const col) {
210  for (size_t i = 0; i < m_nrows; i++) {
211  m_data[m_nrows*m + i] = col[i];
212  }
213  }
214 
215  //! Get the values in column m
216  /*!
217  * col(i) = A(i,m)
218  *
219  * @param m Column to set
220  * @param col pointer to a col vector that will be returned
221  */
222  void getColumn(size_t m, doublereal* const col) {
223  for (size_t i = 0; i < m_nrows; i++) {
224  col[i] = m_data[m_nrows*m + i];
225  }
226  }
227 
228  /**
229  * Destructor. Does nothing, since no memory allocated on the
230  * heap.
231  */
232  virtual ~Array2D() {}
233 
234  //! Evaluate z = a*x + y.
235  /*!
236  * This function evaluates the AXPY operation, and stores
237  * the result in the object's Array2D object.
238  * It's assumed that all 3 objects have the same dimensions,
239  * but no error checking is done.
240  *
241  * @param a scalar to multiply x with
242  * @param x First Array2D object to be used
243  * @param y Second Array2D object to be used
244  *
245  */
246  void axpy(doublereal a, const Array2D& x, const Array2D& y) {
247  iterator b = begin();
248  const_iterator xb = x.begin();
249  const_iterator yb = y.begin();
250  for (; b != end(); ++b, ++xb, ++yb) {
251  *b = a*(*xb) + *yb;
252  }
253  }
254 
255  //! Set all of the entries to zero
256  inline void zero() {
257  size_t nn = m_nrows * m_ncols;
258  if (nn > 0) {
259  /*
260  * Using memset is the fastest way to zero a contiguous
261  * section of memory.
262  */
263  (void) memset((void*) &m_data[0], 0, nn * sizeof(doublereal));
264  }
265  }
266 
267  //! Allows setting elements using the syntax A(i,j) = x.
268  /*!
269  * @param i row index
270  * @param j column index.
271  *
272  * @return Returns a reference to A(i,j) which may be assigned.
273  */
274  doublereal& operator()(size_t i, size_t j) {
275  return value(i,j);
276  }
277 
278 
279  //! Allows retrieving elements using the syntax x = A(i,j).
280  /*!
281  * @param i Index for the row to be retrieved
282  * @param j Index for the column to be retrieved.
283  *
284  * @return Returns the value of the matrix entry
285  */
286  doublereal operator()(size_t i, size_t j) const {
287  return value(i,j);
288  }
289 
290  //! Returns a changeable reference to position in the matrix
291  /*!
292  * This is a key entry. Returns a reference to the matrixes (i,j)
293  * element. This may be used as an L value.
294  *
295  * @param i The row index
296  * @param j The column index
297  *
298  * @return Returns a changeable reference to the matrix entry
299  */
300  doublereal& value(size_t i, size_t j) {
301  return m_data[m_nrows*j + i];
302  }
303 
304  //! Returns the value of a single matrix entry
305  /*!
306  * This is a key entry. Returns the value of the matrix position (i,j)
307  * element.
308  *
309  * @param i The row index
310  * @param j The column index
311  */
312  doublereal value(size_t i, size_t j) const {
313  return m_data[m_nrows*j + i];
314  }
315 
316  /// Number of rows
317  size_t nRows() const {
318  return m_nrows;
319  }
320 
321  /// Number of columns
322  size_t nColumns() const {
323  return m_ncols;
324  }
325 
326  /// Return an iterator pointing to the first element
328  return m_data.begin();
329  }
330 
331  /// Return an iterator pointing past the last element
333  return m_data.end();
334  }
335 
336  /// Return a const iterator pointing to the first element
338  return m_data.begin();
339  }
340 
341  /// Return a const iterator pointing to past the last element
342  const_iterator end() const {
343  return m_data.end();
344  }
345 
346  /// Return a reference to the data vector
348  return m_data;
349  }
350 
351  /// Return a const reference to the data vector
352  const vector_fp& data() const {
353  return m_data;
354  }
355 
356  //! Return a pointer to the top of column j, columns are contiguous
357  //! in memory
358  /*!
359  * @param j Value of the column
360  *
361  * @return Returns a pointer to the top of the column
362  */
363  doublereal* ptrColumn(size_t j) {
364  return &(m_data[m_nrows*j]);
365  }
366 
367  //! Return a const pointer to the top of column j, columns are contiguous
368  //! in memory
369  /*!
370  * @param j Value of the column
371  *
372  * @return Returns a const pointer to the top of the column
373  */
374  const doublereal* ptrColumn(size_t j) const {
375  return &(m_data[m_nrows*j]);
376  }
377 
378 protected:
379 
380  //! Data stored in a single array
382 
383  //! Number of rows
384  size_t m_nrows;
385 
386  //! Number of columns
387  size_t m_ncols;
388 };
389 
390 //! Output the current contents of the Array2D object
391 /*!
392  * Example of usage:
393  * s << m << endl;
394  *
395  * @param s Reference to the ostream to write to
396  * @param m Object of type Array2D that you are querying
397  *
398  * @return Returns a reference to the ostream.
399  */
400 inline std::ostream& operator<<(std::ostream& s, const Array2D& m)
401 {
402  size_t nr = m.nRows();
403  size_t nc = m.nColumns();
404  size_t i,j;
405  for (i = 0; i < nr; i++) {
406  for (j = 0; j < nc; j++) {
407  s << m(i,j) << ", ";
408  }
409  s << std::endl;
410  }
411  return s;
412 }
413 
414 //! Overload the times equals operator for multiplication
415 //! of a matrix and a scalar.
416 /*!
417  * Scaled every element of the matrix by the scalar input
418  *
419  * @param m Matrix
420  * @param a scalar
421  */
422 inline void operator*=(Array2D& m, doublereal a)
423 {
424  scale(m.begin(), m.end(), m.begin(), a);
425 }
426 
427 //! Overload the plus equals operator for addition
428 //! of one matrix with another
429 /*!
430  * Adds each element of the second matrix into the first
431  * matrix
432  *
433  * @param x First matrix
434  * @param y Second matrix, which is a const
435  */
436 inline void operator+=(Array2D& x, const Array2D& y)
437 {
438  sum_each(x.begin(), x.end(), y.begin());
439 }
440 
441 }
442 
443 #endif