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