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 with
54  /// 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 
67  template<typename T, typename MatrixType>
68  class iterator_impl
69  {
70  public:
71  typedef T value_type;
72 
73  template<typename Z>
74  struct TagType
75  {
76  typedef std::forward_iterator_tag type;
77  };
78 
79  template<typename Z>
80  struct TagType<const Z>
81  {
82  typedef std::input_iterator_tag type;
83  };
84 
86  typedef unsigned int difference_type;
87  typedef typename boost::call_traits<value_type>::reference reference;
88  typedef typename boost::call_traits<value_type>::const_reference const_reference;
89  typedef typename std::remove_reference<value_type>::type* pointer;
90 
91  public:
92  iterator_impl(pointer d, pointer e, bool isEnd = false) :
93  m_data(d),
94  m_end(e),
95  m_curRow(std::numeric_limits<unsigned int>::max()),
96  m_curColumn(std::numeric_limits<unsigned int>::max()),
97  m_matrix(NULL),
98  m_curIndex(std::numeric_limits<unsigned int>::max()),
99  m_transpose('N')
100  {
101  if( isEnd )
102  {
103  m_data = m_end;
104  }
105  }
106 
107  iterator_impl(MatrixType* m, char transpose, bool isEnd = false) :
108  m_data(NULL),
109  m_end(NULL),
110  m_curRow(0),
111  m_curColumn(0),
112  m_matrix(m),
113  m_curIndex(0),
114  m_transpose(transpose)
115  {
116  if( isEnd )
117  {
118  m_curRow = std::numeric_limits<unsigned int>::max();
119  m_curColumn = std::numeric_limits<unsigned int>::max();
120  m_curIndex = std::numeric_limits<unsigned int>::max();
121  }
122  }
123 
124  iterator_impl(const iterator_impl<T, MatrixType>& rhs) :
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  {
133  }
134 
135  iterator_impl<T, MatrixType>& operator=(const iterator_impl<T, MatrixType>& rhs)
136  {
137  m_data = rhs.m_data;
138  m_end = rhs.m_end;
139  m_curRow = rhs.m_curRow;
140  m_curColumn = rhs.m_curColumn;
141  m_matrix = rhs.m_matrix;
142  m_curIndex = rhs.m_curIndex;
143  m_transpose = rhs.m_transpose;
144  return *this;
145  }
146 
147  reference operator*()
148  {
149  if( m_data )
150  {
151  ASSERTL1(m_data < m_end, "Attempt to dereference matrix iterator after its end.");
152  return *m_data;
153  }
154  else
155  {
156  return m_matrix->GetPtr()[m_curIndex];
157  }
158  }
159 
160  const_reference operator*() const
161  {
162  if( m_data )
163  {
164  ASSERTL1(m_data < m_end, "Attempt to dereference matrix iterator after its end.");
165  return *m_data;
166  }
167  else
168  {
169  return m_matrix->GetPtr()[m_curIndex];
170  }
171  }
172 
173  /// \brief Prefix increment operator.
174  iterator_impl<T, MatrixType>& operator++()
175  {
176  if( m_data )
177  {
178  ++m_data;
179  }
180  else
181  {
182  std::tie(m_curRow, m_curColumn) =
183  m_matrix->Advance(m_curRow, m_curColumn, m_transpose);
184  if( m_curRow == std::numeric_limits<unsigned int>::max() )
185  {
186  m_curIndex = m_curRow;
187  }
188  else
189  {
190  m_curIndex = m_matrix->CalculateIndex(m_curRow, m_curColumn, m_transpose);
191  }
192  }
193  return *this;
194  }
195 
196  /// \postfix increment operator.
197  iterator_impl<T, MatrixType> operator++(int)
198  {
199  iterator_impl<T, MatrixType> result = *this;
200  ++(*this);
201  return result;
202  }
203 
204  bool operator==(const iterator_impl<T, MatrixType>& rhs)
205  {
206  return m_data == rhs.m_data &&
207  m_end == rhs.m_end &&
208  m_curRow == rhs.m_curRow &&
209  m_curColumn == rhs.m_curColumn &&
210  m_matrix == rhs.m_matrix &&
211  m_curIndex == rhs.m_curIndex &&
212  m_transpose == rhs.m_transpose;
213  }
214 
215  bool operator!=(const iterator_impl<T, MatrixType>& rhs)
216  {
217  return !(*this == rhs);
218  }
219 
220  private:
221  // Used when the matrix is not transposed
222  T* m_data;
223  T* m_end;
224 
225  // Used when the matrix is transposed.
226  unsigned int m_curRow;
227  unsigned int m_curColumn;
229  unsigned int m_curIndex;
231  };
232 
233  public:
234  /// \brief Creates an empty matrix.
236 
237  /// \brief Creates a rows by columns matrix.
238  /// \brief rows The number of rows in the matrix.
239  /// \brief columns The number of columns in the matrix.
240  LIB_UTILITIES_EXPORT NekMatrix(unsigned int rows, unsigned int columns, MatrixStorage policy = eFULL,
241  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
242  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
243 
244  LIB_UTILITIES_EXPORT NekMatrix(unsigned int rows, unsigned int columns,
245  MatrixStorage policy,
246  unsigned int subDiagonals,
247  unsigned int superDiagonals,
248  unsigned int capacity);
249 
250  /// \brief Creates a rows by columns matrix.
251  /// \brief rows The number of rows in the matrix.
252  /// \brief columns The number of columns in the matrix.
253  /// \brief initValue The value used to initialize each element.
254  /// \brief policySpecificData Data the is specific to the storage type assigned to this matrix.
255  /// Check MatrixStoragePolicy<StorageType> to see if the StoragePolicy
256  /// for this matrix has policy specific data.
257  LIB_UTILITIES_EXPORT NekMatrix(unsigned int rows, unsigned int columns, typename boost::call_traits<DataType>::const_reference initValue,
258  MatrixStorage policy = eFULL,
259  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
260  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
261 
262  /// \brief Creates a rows by columns matrix.
263  /// \brief rows The number of rows in the matrix.
264  /// \brief columns The number of columns in the matrix.
265  /// \brief data An array of data use to initialize the matrix.
266  /// \brief policySpecificData Data the is specific to the storage type assigned to this matrix.
267  /// Check MatrixStoragePolicy<StorageType> to see if the StoragePolicy
268  /// for this matrix has policy specific data.
269  LIB_UTILITIES_EXPORT NekMatrix(unsigned int rows, unsigned int columns, const DataType* data,
270  MatrixStorage policy = eFULL,
271  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
272  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
273 
274  /// \brief Creates a rows by columns matrix.
275  /// \brief rows The number of rows in the matrix.
276  /// \brief columns The number of columns in the matrix.
277  /// \brief d An array of data used to initialize the matrix. Values from d are copied into the matrix.
278  /// \brief policySpecificData Data the is specific to the storage type assigned to this matrix.
279  /// Check MatrixStoragePolicy<StorageType> to see if the StoragePolicy
280  /// for this matrix has policy specific data.
281  LIB_UTILITIES_EXPORT NekMatrix(unsigned int rows, unsigned int columns, const Array<OneD, const DataType>& d,
282  MatrixStorage policy = eFULL,
283  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
284  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
285 
286  /// \brief Creates a rows by columns matrix.
287  /// \brief rows The number of rows in the matrix.
288  /// \brief columns The number of columns in the matrix.
289  /// \brief d An array of data used to initialize the matrix. If wrapperType is eCopy, then
290  /// each element is copied from d to the matrix. If wrapperType is eWrapper, then
291  /// the matrix uses d directly as its matrix data and no copies are made.
292  /// \brief policySpecificData Data the is specific to the storage type assigned to this matrix.
293  /// Check MatrixStoragePolicy<StorageType> to see if the StoragePolicy
294  /// for this matrix has policy specific data.
295  LIB_UTILITIES_EXPORT NekMatrix(unsigned int rows, unsigned int columns, const Array<OneD, DataType>& d, PointerWrapper wrapperType = eCopy,
296  MatrixStorage policy = eFULL,
297  unsigned int subDiagonals = std::numeric_limits<unsigned int>::max(),
298  unsigned int superDiagonals = std::numeric_limits<unsigned int>::max());
299 
300  LIB_UTILITIES_EXPORT NekMatrix(const ThisType& rhs);
301 
302  LIB_UTILITIES_EXPORT ThisType& operator=(const ThisType& rhs);
303 
304  template<typename InnerMatrixType>
306  {
307  BaseType::operator=(rhs);
308  m_numberOfSubDiagonals = rhs.GetNumberOfSubDiagonals();
309  m_numberOfSuperDiagonals = rhs.GetNumberOfSuperDiagonals();
310 
311  ResizeDataArrayIfNeeded();
312 
313  unsigned int requiredStorageSize = GetRequiredStorageSize();
314  DataType scale = rhs.Scale();
315 
316  DataType* lhs_array = m_data.data();
317  const DataType* rhs_array = rhs.GetRawPtr();
318 
319  for(unsigned int i = 0; i < requiredStorageSize; ++i)
320  {
321  lhs_array[i] = scale*rhs_array[i];
322  }
323 
324  return *this;
325 
326  }
327 
328 
329  /// \brief Returns the element value at the given row and column.
330  LIB_UTILITIES_EXPORT ConstGetValueType operator()(unsigned int row, unsigned int column) const;
331 
332  class Proxy
333  {
334  public:
335  Proxy() : m_value(defaultReturnValue) {}
336  explicit Proxy(DataType& value) : m_value(value) {}
337  Proxy(const Proxy& rhs) : m_value(rhs.m_value) {}
338  Proxy& operator=(const Proxy& rhs)
339  {
340  m_value = rhs.m_value;
341  return *this;
342  }
343 
344  DataType& operator*() { return m_value; }
345  const DataType& operator*() const { return m_value; }
346  operator DataType&() { return m_value; }
347  operator const DataType&() const { return m_value; }
348  void operator=(const DataType& newValue)
349  {
350  if( &m_value != &defaultReturnValue )
351  {
352  m_value = newValue;
353  }
354  }
355 
356  private:
357  DataType& m_value;
358  static DataType defaultReturnValue;
359  };
360 
361  /// \brief Returns the element value at the given row and column.
362  /// \brief row The element's row.
363  /// \brief column The element's column.
364  /// \brief transpose If transpose = 'N', then the return value is element [row, column].
365  /// If transpose = 'T', then the return value is element [column, row].
366  LIB_UTILITIES_EXPORT ConstGetValueType operator()(unsigned int row, unsigned int column, char transpose) const;
367 
368  LIB_UTILITIES_EXPORT unsigned int GetRequiredStorageSize() const;
369 
370  LIB_UTILITIES_EXPORT unsigned int CalculateIndex(unsigned int row, unsigned int col, const char transpose) const;
371 
372  /// \brief Returns the element value at the given row and column.
373  LIB_UTILITIES_EXPORT typename boost::call_traits<DataType>::const_reference GetValue(unsigned int row, unsigned int column) const;
374 
375  /// \brief Returns the element value at the given row and column.
376  /// \brief row The element's row.
377  /// \brief column The element's column.
378  /// \brief transpose If transpose = 'N', then the return value is element [row, column].
379  /// If transpose = 'T', then the return value is element [column, row].
380  LIB_UTILITIES_EXPORT ConstGetValueType GetValue(unsigned int row, unsigned int column, char transpose) const;
381 
383 
384  /// \brief Returns the scaling used by this matrix.
385  ///
386  /// Since this matrix is not a scaled matrix, this method always returns 1.
387  LIB_UTILITIES_EXPORT DataType Scale() const;
388 
389  LIB_UTILITIES_EXPORT const DataType* GetRawPtr() const;
390 
391  typedef iterator_impl<const DataType, const ThisType> const_iterator;
392  typedef iterator_impl<DataType, ThisType> iterator;
393 
394  LIB_UTILITIES_EXPORT iterator begin();
395 
396  LIB_UTILITIES_EXPORT iterator begin(char transpose);
397 
398  LIB_UTILITIES_EXPORT iterator end();
399  LIB_UTILITIES_EXPORT iterator end(char transpose);
400 
401  LIB_UTILITIES_EXPORT const_iterator begin() const;
402 
403  LIB_UTILITIES_EXPORT const_iterator begin(char transpose) const;
404 
405  LIB_UTILITIES_EXPORT const_iterator end() const;
406 
407  LIB_UTILITIES_EXPORT const_iterator end(char transpose) const;
408 
409 
410  LIB_UTILITIES_EXPORT unsigned int GetStorageSize() const;
411 
412  // Banded matrices only.
413  // Get the specified number of sub diagonals, or calculate the
414  // number if this object has not been initialized.
415  LIB_UTILITIES_EXPORT unsigned int GetNumberOfSubDiagonals() const;
416 
417  LIB_UTILITIES_EXPORT unsigned int GetNumberOfSuperDiagonals() const;
418 
419  LIB_UTILITIES_EXPORT unsigned int CalculateNumberOfRows() const;
420 
421  /// \brief Returns true if the this matrix and rhs are equivalent.
422  ///
423  /// Two matrices are equivalent if they have the same size and each element
424  /// is the same.
426 
427  LIB_UTILITIES_EXPORT PointerWrapper GetWrapperType() const;
428 
429  LIB_UTILITIES_EXPORT std::tuple<unsigned int, unsigned int>
430  Advance(unsigned int curRow, unsigned int curColumn) const;
431 
432  LIB_UTILITIES_EXPORT std::tuple<unsigned int, unsigned int>
433  Advance(unsigned int curRow, unsigned int curColumn, char transpose) const;
434 
435  LIB_UTILITIES_EXPORT static ThisType CreateWrapper(const ThisType& rhs);
436 
437  LIB_UTILITIES_EXPORT static std::shared_ptr<ThisType> CreateWrapper(const std::shared_ptr<ThisType>& rhs);
438 
439  LIB_UTILITIES_EXPORT void SetSize(unsigned int rows, unsigned int cols);
440 
441  LIB_UTILITIES_EXPORT Proxy operator()(unsigned int row, unsigned int column);
442 
443 
444  LIB_UTILITIES_EXPORT Proxy operator()(unsigned int row, unsigned int column, char transpose);
445 
446  LIB_UTILITIES_EXPORT void SetValue(unsigned int row, unsigned int column, typename boost::call_traits<DataType>::const_reference d);
447 
448  LIB_UTILITIES_EXPORT void SetValue(unsigned int row, unsigned int column, typename boost::call_traits<DataType>::const_reference d, char transpose);
449 
451 
452  LIB_UTILITIES_EXPORT DataType* GetRawPtr();
453 
454 
455 
456  LIB_UTILITIES_EXPORT NekDouble AbsMaxtoMinEigenValueRatio(void);
457 
458  LIB_UTILITIES_EXPORT void EigenSolve(Array<OneD, NekDouble> &EigValReal,
459  Array<OneD, NekDouble> &EigValImag,
461 
462  LIB_UTILITIES_EXPORT void Invert();
463 
465 
466  LIB_UTILITIES_EXPORT void SwapTempAndDataBuffers();
467 
468  LIB_UTILITIES_EXPORT ThisType& operator*=(const NumberType& s);
469 
471 
472  protected:
473  LIB_UTILITIES_EXPORT NekMatrix(const ThisType& rhs, PointerWrapper wrapperType);
474 
476 
477  LIB_UTILITIES_EXPORT void RemoveExcessCapacity();
478 
479  LIB_UTILITIES_EXPORT void ResizeDataArrayIfNeeded(unsigned int requiredStorageSize);
480 
481  LIB_UTILITIES_EXPORT void ResizeDataArrayIfNeeded();
482 
483 
484  private:
485  LIB_UTILITIES_EXPORT void PerformCopyConstruction(const ThisType& rhs);
486 
487  LIB_UTILITIES_EXPORT virtual typename boost::call_traits<DataType>::value_type v_GetValue(unsigned int row, unsigned int column) const;
488 
489  LIB_UTILITIES_EXPORT virtual unsigned int v_GetStorageSize() const ;
490 
491  // We need to rethink class structure a little. This shouldn't be necessary.
492  LIB_UTILITIES_EXPORT virtual void v_SetValue(unsigned int row, unsigned int column, typename boost::call_traits<DataType>::const_reference d);
493 
496 
497  // Only used by banded matrices.
500 
501  // Used during chained matrix multiplication as workspace.
503  };
504 
505 
506  template<typename DataType>
508 
509  template<typename DataType>
512 
513  template<typename DataType>
515 }
516 
517 #endif //NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_STANDARD_MATRIX_HPP
iterator_impl< const DataType, const ThisType > const_iterator
static Array< OneD, NekDouble > NullNekDouble1DArray
bool operator!=(const iterator_impl< T, MatrixType > &rhs)
STL namespace.
bool operator==(const Array< OneD, NekDouble > &lhs, const Array< OneD, NekDouble > &rhs)
boost::call_traits< value_type >::const_reference const_reference
boost::call_traits< value_type >::reference reference
NekMatrix< DataType, StandardMatrixTag > ThisType
ThisType & operator=(const NekMatrix< InnerMatrixType, ScaledMatrixTag > &rhs)
iterator_impl< T, MatrixType > operator++(int)
increment operator.
#define LIB_UTILITIES_EXPORT
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
double NekDouble
PointerWrapper
Specifies if the pointer passed to a NekMatrix or NekVector is copied into an internal representation...
iterator_impl(MatrixType *m, char transpose, bool isEnd=false)
NekMatrix< typename NekMatrix< LhsDataType, LhsMatrixType >::NumberType, StandardMatrixTag > operator-(const NekMatrix< LhsDataType, LhsMatrixType > &lhs, const NekMatrix< RhsDataType, RhsMatrixType > &rhs)
iterator_impl< DataType, ThisType > iterator
std::remove_reference< value_type >::type * pointer
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs
iterator_impl< T, MatrixType > & operator++()
Prefix increment operator.
1D Array of constant elements with garbage collection and bounds checking.
Definition: SharedArray.hpp:57
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
void NegateInPlace(NekVector< DataType > &v)
Definition: NekVector.cpp:959
iterator_impl(const iterator_impl< T, MatrixType > &rhs)
iterator_impl< T, MatrixType > & operator=(const iterator_impl< T, MatrixType > &rhs)
bool operator==(const iterator_impl< T, MatrixType > &rhs)