Nektar++
StandardMatrix.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: StandardMatrix.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Interface classes for matrices
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #ifndef NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_STANDARD_MATRIX_HPP
36 #define NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_STANDARD_MATRIX_HPP
37 
39 
44 
47 
48 namespace Nektar
49 {
50 /// \brief Standard Matrix
51 /// \param DataType The type stored in each element.
52 ///
53 /// Matrices are stored in column major order to make it easier to interoperate
54 /// with Blas and Lapack.
55 template <typename DataType>
56 class NekMatrix<DataType, StandardMatrixTag> : public Matrix<DataType>
57 {
58 public:
61  typedef DataType NumberType;
62  typedef const DataType &ConstGetValueType;
63  typedef DataType GetValueType;
64 
65 public:
66  template <typename T, typename MatrixType> class iterator_impl
67  {
68  public:
69  typedef T value_type;
70 
71  template <typename Z> struct TagType
72  {
73  typedef std::forward_iterator_tag type;
74  };
75 
76  template <typename Z> struct TagType<const Z>
77  {
78  typedef std::input_iterator_tag type;
79  };
80 
82  typedef unsigned int difference_type;
83  typedef typename boost::call_traits<value_type>::reference reference;
84  typedef typename boost::call_traits<value_type>::const_reference
86  typedef typename std::remove_reference<value_type>::type *pointer;
87 
88  public:
89  iterator_impl(pointer d, pointer e, bool isEnd = false)
90  : m_data(d), m_end(e),
91  m_curRow(std::numeric_limits<unsigned int>::max()),
92  m_curColumn(std::numeric_limits<unsigned int>::max()),
93  m_matrix(NULL),
94  m_curIndex(std::numeric_limits<unsigned int>::max()),
95  m_transpose('N')
96  {
97  if (isEnd)
98  {
99  m_data = m_end;
100  }
101  }
102 
103  iterator_impl(MatrixType *m, char transpose, bool isEnd = false)
104  : m_data(NULL), m_end(NULL), m_curRow(0), m_curColumn(0),
105  m_matrix(m), m_curIndex(0), m_transpose(transpose)
106  {
107  if (isEnd)
108  {
109  m_curRow = std::numeric_limits<unsigned int>::max();
110  m_curColumn = std::numeric_limits<unsigned int>::max();
111  m_curIndex = std::numeric_limits<unsigned int>::max();
112  }
113  }
114 
115  iterator_impl(const iterator_impl<T, MatrixType> &rhs)
116  : m_data(rhs.m_data), m_end(rhs.m_end), m_curRow(rhs.m_curRow),
117  m_curColumn(rhs.m_curColumn), m_matrix(rhs.m_matrix),
118  m_curIndex(rhs.m_curIndex), m_transpose(rhs.m_transpose)
119  {
120  }
121 
122  iterator_impl<T, MatrixType> &operator=(
123  const iterator_impl<T, MatrixType> &rhs)
124  {
125  m_data = rhs.m_data;
126  m_end = rhs.m_end;
127  m_curRow = rhs.m_curRow;
128  m_curColumn = rhs.m_curColumn;
129  m_matrix = rhs.m_matrix;
130  m_curIndex = rhs.m_curIndex;
131  m_transpose = rhs.m_transpose;
132  return *this;
133  }
134 
136  {
137  if (m_data)
138  {
139  ASSERTL1(
140  m_data < m_end,
141  "Attempt to dereference matrix iterator after its end.");
142  return *m_data;
143  }
144  else
145  {
146  return m_matrix->GetPtr()[m_curIndex];
147  }
148  }
149 
151  {
152  if (m_data)
153  {
154  ASSERTL1(
155  m_data < m_end,
156  "Attempt to dereference matrix iterator after its end.");
157  return *m_data;
158  }
159  else
160  {
161  return m_matrix->GetPtr()[m_curIndex];
162  }
163  }
164 
165  /// \brief Prefix increment operator.
166  iterator_impl<T, MatrixType> &operator++()
167  {
168  if (m_data)
169  {
170  ++m_data;
171  }
172  else
173  {
174  std::tie(m_curRow, m_curColumn) =
175  m_matrix->Advance(m_curRow, m_curColumn, m_transpose);
176  if (m_curRow == std::numeric_limits<unsigned int>::max())
177  {
178  m_curIndex = m_curRow;
179  }
180  else
181  {
182  m_curIndex = m_matrix->CalculateIndex(m_curRow, m_curColumn,
183  m_transpose);
184  }
185  }
186  return *this;
187  }
188 
189  /// \postfix increment operator.
190  iterator_impl<T, MatrixType> operator++(int)
191  {
192  iterator_impl<T, MatrixType> result = *this;
193  ++(*this);
194  return result;
195  }
196 
197  bool operator==(const iterator_impl<T, MatrixType> &rhs)
198  {
199  return m_data == rhs.m_data && m_end == rhs.m_end &&
200  m_curRow == rhs.m_curRow && m_curColumn == rhs.m_curColumn &&
201  m_matrix == rhs.m_matrix && m_curIndex == rhs.m_curIndex &&
202  m_transpose == rhs.m_transpose;
203  }
204 
205  bool operator!=(const iterator_impl<T, MatrixType> &rhs)
206  {
207  return !(*this == rhs);
208  }
209 
210  private:
211  // Used when the matrix is not transposed
212  T *m_data;
213  T *m_end;
214 
215  // Used when the matrix is transposed.
216  unsigned int m_curRow;
217  unsigned int m_curColumn;
219  unsigned int m_curIndex;
221  };
222 
223 public:
224  /// \brief Creates an empty matrix.
226 
227  /// \brief Creates a rows by columns matrix.
228  /// \brief rows The number of rows in the matrix.
229  /// \brief columns The number of columns in the matrix.
231  unsigned int rows, unsigned int columns, MatrixStorage policy = eFULL,
232  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
233  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
234 
235  LIB_UTILITIES_EXPORT NekMatrix(unsigned int rows, unsigned int columns,
236  MatrixStorage policy,
237  unsigned int subDiagonals,
238  unsigned int superDiagonals,
239  unsigned int capacity);
240 
241  /// \brief Creates a rows by columns matrix.
242  /// \brief rows The number of rows in the matrix.
243  /// \brief columns The number of columns in the matrix.
244  /// \brief initValue The value used to initialize each element.
245  /// \brief policySpecificData Data the is specific to the storage type
246  /// assigned to this matrix.
247  /// Check MatrixStoragePolicy<StorageType> to see
248  /// if the StoragePolicy for this matrix has
249  /// policy specific data.
251  unsigned int rows, unsigned int columns,
252  typename boost::call_traits<DataType>::const_reference initValue,
253  MatrixStorage policy = eFULL,
254  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
255  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
256 
257  /// \brief Creates a rows by columns matrix.
258  /// \brief rows The number of rows in the matrix.
259  /// \brief columns The number of columns in the matrix.
260  /// \brief data An array of data use to initialize the matrix.
261  /// \brief policySpecificData Data the is specific to the storage type
262  /// assigned to this matrix.
263  /// Check MatrixStoragePolicy<StorageType> to see
264  /// if the StoragePolicy for this matrix has
265  /// policy specific data.
267  unsigned int rows, unsigned int columns, const DataType *data,
268  MatrixStorage policy = eFULL,
269  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
270  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
271 
272  /// \brief Creates a rows by columns matrix.
273  /// \brief rows The number of rows in the matrix.
274  /// \brief columns The number of columns in the matrix.
275  /// \brief d An array of data used to initialize the matrix. Values from d
276  /// are copied into the matrix. \brief policySpecificData Data the is
277  /// specific to the storage type assigned to this matrix.
278  /// Check MatrixStoragePolicy<StorageType> to see
279  /// if the StoragePolicy for this matrix has
280  /// policy specific data.
282  unsigned int rows, unsigned int columns,
284  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
285  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
286 
287  /// \brief Creates a rows by columns matrix.
288  /// \brief rows The number of rows in the matrix.
289  /// \brief columns The number of columns in the matrix.
290  /// \brief d An array of data used to initialize the matrix. If wrapperType
291  /// is eCopy, then
292  /// each element is copied from d to the matrix. If wrapperType is
293  /// eWrapper, then the matrix uses d directly as its matrix data
294  /// and no copies are made.
295  /// \brief policySpecificData Data the is specific to the storage type
296  /// assigned to this matrix.
297  /// Check MatrixStoragePolicy<StorageType> to see
298  /// if the StoragePolicy for this matrix has
299  /// policy specific data.
301  unsigned int rows, unsigned int columns, const Array<OneD, DataType> &d,
302  PointerWrapper wrapperType = eCopy, MatrixStorage policy = eFULL,
303  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
304  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
305 
307 
308  LIB_UTILITIES_EXPORT ThisType &operator=(const ThisType &rhs);
309 
310  LIB_UTILITIES_EXPORT ThisType &operator=(const DataType &rhs);
311 
312  template <typename InnerMatrixType>
314  {
315  BaseType::operator =(rhs);
316  m_numberOfSubDiagonals = rhs.GetNumberOfSubDiagonals();
317  m_numberOfSuperDiagonals = rhs.GetNumberOfSuperDiagonals();
318 
319  ResizeDataArrayIfNeeded();
320 
321  unsigned int requiredStorageSize = GetRequiredStorageSize();
322  DataType scale = rhs.Scale();
323 
324  DataType *lhs_array = m_data.data();
325  const DataType *rhs_array = rhs.GetRawPtr();
326 
327  for (unsigned int i = 0; i < requiredStorageSize; ++i)
328  {
329  lhs_array[i] = scale * rhs_array[i];
330  }
331 
332  return *this;
333  }
334 
335  /// \brief Returns the element value at the given row and column.
336  LIB_UTILITIES_EXPORT ConstGetValueType
337  operator()(unsigned int row, unsigned int column) const;
338 
339  class Proxy
340  {
341  public:
342  Proxy() : m_value(defaultReturnValue)
343  {
344  }
345  explicit Proxy(DataType &value) : m_value(value)
346  {
347  }
348  Proxy(const Proxy &rhs) : m_value(rhs.m_value)
349  {
350  }
351  Proxy &operator=(const Proxy &rhs)
352  {
353  m_value = rhs.m_value;
354  return *this;
355  }
356 
357  DataType &operator*()
358  {
359  return m_value;
360  }
361  const DataType &operator*() const
362  {
363  return m_value;
364  }
365  operator DataType &()
366  {
367  return m_value;
368  }
369  operator const DataType &() const
370  {
371  return m_value;
372  }
373  void operator=(const DataType &newValue)
374  {
375  if (&m_value != &defaultReturnValue)
376  {
377  m_value = newValue;
378  }
379  }
380 
381  private:
382  DataType &m_value;
383  static DataType defaultReturnValue;
384  };
385 
386  /// \brief Returns the element value at the given row and column.
387  /// \brief row The element's row.
388  /// \brief column The element's column.
389  /// \brief transpose If transpose = 'N', then the return value is element
390  /// [row, column].
391  /// If transpose = 'T', then the return value is element
392  /// [column, row].
393  LIB_UTILITIES_EXPORT ConstGetValueType operator()(unsigned int row,
394  unsigned int column,
395  char transpose) const;
396 
397  LIB_UTILITIES_EXPORT unsigned int GetRequiredStorageSize() const;
398 
399  LIB_UTILITIES_EXPORT unsigned int CalculateIndex(
400  unsigned int row, unsigned int col, const char transpose) const;
401 
402  /// \brief Returns the element value at the given row and column.
403  LIB_UTILITIES_EXPORT typename boost::call_traits<DataType>::const_reference
404  GetValue(unsigned int row, unsigned int column) const;
405 
406  /// \brief Returns the element value at the given row and column.
407  /// \brief row The element's row.
408  /// \brief column The element's column.
409  /// \brief transpose If transpose = 'N', then the return value is element
410  /// [row, column].
411  /// If transpose = 'T', then the return value is element
412  /// [column, row].
413  LIB_UTILITIES_EXPORT ConstGetValueType GetValue(unsigned int row,
414  unsigned int column,
415  char transpose) const;
416 
418 
419  /// \brief Returns the scaling used by this matrix.
420  ///
421  /// Since this matrix is not a scaled matrix, this method always returns 1.
422  LIB_UTILITIES_EXPORT DataType Scale() const;
423 
424  LIB_UTILITIES_EXPORT const DataType *GetRawPtr() const;
425 
426  typedef iterator_impl<const DataType, const ThisType> const_iterator;
427  typedef iterator_impl<DataType, ThisType> iterator;
428 
430 
431  LIB_UTILITIES_EXPORT iterator begin(char transpose);
432 
434  LIB_UTILITIES_EXPORT iterator end(char transpose);
435 
436  LIB_UTILITIES_EXPORT const_iterator begin() const;
437 
438  LIB_UTILITIES_EXPORT const_iterator begin(char transpose) const;
439 
441 
442  LIB_UTILITIES_EXPORT const_iterator end(char transpose) const;
443 
444  LIB_UTILITIES_EXPORT unsigned int GetStorageSize() const;
445 
446  // Banded matrices only.
447  // Get the specified number of sub diagonals, or calculate the
448  // number if this object has not been initialized.
449  LIB_UTILITIES_EXPORT unsigned int GetNumberOfSubDiagonals() const;
450 
451  LIB_UTILITIES_EXPORT unsigned int GetNumberOfSuperDiagonals() const;
452 
453  LIB_UTILITIES_EXPORT unsigned int CalculateNumberOfRows() const;
454 
455  /// \brief Returns true if the this matrix and rhs are equivalent.
456  ///
457  /// Two matrices are equivalent if they have the same size and each element
458  /// is the same.
460  const NekMatrix<DataType, StandardMatrixTag> &rhs) const;
461 
462  LIB_UTILITIES_EXPORT PointerWrapper GetWrapperType() const;
463 
464  LIB_UTILITIES_EXPORT std::tuple<unsigned int, unsigned int> Advance(
465  unsigned int curRow, unsigned int curColumn) const;
466 
467  LIB_UTILITIES_EXPORT std::tuple<unsigned int, unsigned int> Advance(
468  unsigned int curRow, unsigned int curColumn, char transpose) const;
469 
470  LIB_UTILITIES_EXPORT static ThisType CreateWrapper(const ThisType &rhs);
471 
472  LIB_UTILITIES_EXPORT static std::shared_ptr<ThisType> CreateWrapper(
473  const std::shared_ptr<ThisType> &rhs);
474 
475  LIB_UTILITIES_EXPORT void SetSize(unsigned int rows, unsigned int cols);
476 
477  LIB_UTILITIES_EXPORT Proxy operator()(unsigned int row,
478  unsigned int column);
479 
480  LIB_UTILITIES_EXPORT Proxy operator()(unsigned int row, unsigned int column,
481  char transpose);
482 
483  LIB_UTILITIES_EXPORT void SetValue(
484  unsigned int row, unsigned int column,
485  typename boost::call_traits<DataType>::const_reference d);
486 
487  LIB_UTILITIES_EXPORT void SetValue(
488  unsigned int row, unsigned int column,
489  typename boost::call_traits<DataType>::const_reference d,
490  char transpose);
491 
493 
494  LIB_UTILITIES_EXPORT DataType *GetRawPtr();
495 
496  LIB_UTILITIES_EXPORT DataType AbsMaxtoMinEigenValueRatio(void);
497 
498  LIB_UTILITIES_EXPORT void EigenSolve(Array<OneD, DataType> &EigValReal,
499  Array<OneD, DataType> &EigValImag,
500  Array<OneD, DataType> &EigVecs);
501 
502  LIB_UTILITIES_EXPORT void Invert();
503 
505 
506  LIB_UTILITIES_EXPORT void SwapTempAndDataBuffers();
507 
508  LIB_UTILITIES_EXPORT ThisType &operator*=(const NumberType &s);
509 
511  const;
512 
513 protected:
515  PointerWrapper wrapperType);
516 
518 
519  LIB_UTILITIES_EXPORT void RemoveExcessCapacity();
520 
521  LIB_UTILITIES_EXPORT void ResizeDataArrayIfNeeded(
522  unsigned int requiredStorageSize);
523 
524  LIB_UTILITIES_EXPORT void ResizeDataArrayIfNeeded();
525 
526  LIB_UTILITIES_EXPORT virtual
527  typename boost::call_traits<DataType>::value_type
528  v_GetValue(unsigned int row, unsigned int column) const override;
529 
530  LIB_UTILITIES_EXPORT virtual unsigned int v_GetStorageSize() const override;
531 
532  // We need to rethink class structure a little. This shouldn't be
533  // necessary.
534  LIB_UTILITIES_EXPORT virtual void v_SetValue(
535  unsigned int row, unsigned int column,
536  typename boost::call_traits<DataType>::const_reference d) override;
537 
538 private:
539  LIB_UTILITIES_EXPORT void PerformCopyConstruction(const ThisType &rhs);
540 
543 
544  // Only used by banded matrices.
547 
548  // Used during chained matrix multiplication as workspace.
550 };
551 
552 template <typename DataType>
554 
555 template <typename DataType>
558 
559 template <typename DataType>
562 } // namespace Nektar
563 
564 #endif // NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_STANDARD_MATRIX_HPP
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
#define LIB_UTILITIES_EXPORT
1D Array of constant elements with garbage collection and bounds checking.
Definition: SharedArray.hpp:58
boost::call_traits< value_type >::const_reference const_reference
bool operator!=(const iterator_impl< T, MatrixType > &rhs)
std::remove_reference< value_type >::type * pointer
boost::call_traits< value_type >::reference reference
iterator_impl< T, MatrixType > operator++(int)
\postfix increment operator.
iterator_impl< T, MatrixType > & operator++()
Prefix increment operator.
iterator_impl< T, MatrixType > & operator=(const iterator_impl< T, MatrixType > &rhs)
bool operator==(const iterator_impl< T, MatrixType > &rhs)
iterator_impl(MatrixType *m, char transpose, bool isEnd=false)
iterator_impl(const iterator_impl< T, MatrixType > &rhs)
NekMatrix< DataType, StandardMatrixTag > ThisType
static std::shared_ptr< ThisType > CreateWrapper(const std::shared_ptr< ThisType > &rhs)
iterator_impl< const DataType, const ThisType > const_iterator
iterator_impl< DataType, ThisType > iterator
ThisType & operator=(const NekMatrix< InnerMatrixType, ScaledMatrixTag > &rhs)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
bool operator==(const Array< OneD, T1 > &lhs, const Array< OneD, T2 > &rhs)
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
void NegateInPlace(NekVector< DataType > &v)
Definition: NekVector.cpp:1160
NekMatrix< typename NekMatrix< LhsDataType, LhsMatrixType >::NumberType, StandardMatrixTag > operator-(const NekMatrix< LhsDataType, LhsMatrixType > &lhs, const NekMatrix< RhsDataType, RhsMatrixType > &rhs)
PointerWrapper
Specifies if the pointer passed to a NekMatrix or NekVector is copied into an internal representation...