Nektar++
MatrixFuncs.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: MatrixFuncs.h
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: Matrix functions that depend on storage policy. Putting
32 // methods in these separate classes makes it easier to use them from
33 // normal, scaled, and block matrices.
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 
37 #ifndef NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_MATRIX_FUNCS_H
38 #define NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_MATRIX_FUNCS_H
39 
43 #include <limits>
44 #include <tuple>
45 
46 namespace Nektar
47 {
49 {
50  /// \brief Calculates and returns the storage size required.
51  ///
52  /// This method assumes that the matrix will be used with LU factorizationa
53  /// and allocates additional storage as appropriate.
54  static unsigned int GetRequiredStorageSize(unsigned int totalRows,
55  unsigned int totalColumns,
56  unsigned int subDiags,
57  unsigned int superDiags);
58 
59  static unsigned int CalculateNumberOfDiags(unsigned int totalRows,
60  unsigned int diags);
61 
62  static unsigned int CalculateNumberOfRows(unsigned int totalRows,
63  unsigned int subDiags,
64  unsigned int superDiags);
65 
66  static unsigned int CalculateIndex(unsigned int totalRows,
67  unsigned int totalColumns,
68  unsigned int row, unsigned int column,
69  unsigned int sub, unsigned int super);
70 
71  static std::tuple<unsigned int, unsigned int> Advance(
72  const unsigned int totalRows, const unsigned int totalColumns,
73  const unsigned int curRow, const unsigned int curColumn);
74 };
75 
77 {
78 
79  static unsigned int GetRequiredStorageSize(unsigned int rows,
80  unsigned int columns);
81  static unsigned int CalculateIndex(unsigned int totalRows,
82  unsigned int totalColumns,
83  unsigned int curRow,
84  unsigned int curColumn);
85 
86  static std::tuple<unsigned int, unsigned int> Advance(
87  const unsigned int totalRows, const unsigned int totalColumns,
88  const unsigned int curRow, const unsigned int curColumn);
89 
90  template <typename DataType>
91  static void Invert(unsigned int rows, unsigned int columns,
92  Array<OneD, DataType> &data, const char transpose)
93  {
94  ASSERTL0(rows == columns, "Only square matrices can be inverted.");
95  ASSERTL0(transpose == 'N',
96  "Only untransposed matrices may be inverted.");
97 
98  int m = rows;
99  int n = columns;
100  int info = 0;
101  Array<OneD, int> ipivot(n);
102  Array<OneD, DataType> work(n);
103 
104  if (std::is_floating_point<DataType>::value)
105  {
106  switch (sizeof(DataType))
107  {
108  case sizeof(NekDouble):
109  break;
110  case sizeof(NekSingle):
111  break;
112  default:
113  ASSERTL0(
114  false,
115  "Invert DataType is neither NekDouble nor NekSingle");
116  break;
117  }
118  }
119  else
120  {
121  ASSERTL0(false,
122  "FullMatrixFuncs::Invert DataType is not floating point");
123  }
124 
125  Lapack::DoSgetrf(m, n, data.get(), m, ipivot.get(), info);
126 
127  if (info < 0)
128  {
129  std::string message =
130  "ERROR: The " + std::to_string(-info) +
131  "th parameter had an illegal parameter for dgetrf";
132  ASSERTL0(false, message.c_str());
133  }
134  else if (info > 0)
135  {
136  std::string message = "ERROR: Element u_" + std::to_string(info) +
137  std::to_string(info) + " is 0 from dgetrf";
138  ASSERTL0(false, message.c_str());
139  }
140 
141  Lapack::DoSgetri(n, data.get(), n, ipivot.get(), work.get(), n, info);
142 
143  if (info < 0)
144  {
145  std::string message =
146  "ERROR: The " + std::to_string(-info) +
147  "th parameter had an illegal parameter for dgetri";
148  ASSERTL0(false, message.c_str());
149  }
150  else if (info > 0)
151  {
152  std::string message = "ERROR: Element u_" + std::to_string(info) +
153  std::to_string(info) + " is 0 from dgetri";
154  ASSERTL0(false, message.c_str());
155  }
156  }
157 
158  template <typename DataType>
159  static void EigenSolve(unsigned int n, const Array<OneD, const DataType> &A,
160  Array<OneD, DataType> &EigValReal,
161  Array<OneD, DataType> &EigValImag,
162  Array<OneD, DataType> &EigVecs)
163  {
164  int lda = n, info = 0;
165  DataType dum;
166  char uplo = 'N';
167 
168  if (EigVecs.size() != 0) // calculate Right Eigen Vectors
169  {
170  int lwork = 4 * lda;
171  Array<OneD, DataType> work(4 * lda);
172  char lrev = 'V';
173  Lapack::DoSgeev(uplo, lrev, lda, A.get(), lda, EigValReal.get(),
174  EigValImag.get(), &dum, 1, EigVecs.get(), lda,
175  &work[0], lwork, info);
176  }
177  else
178  {
179  int lwork = 3 * lda;
180  Array<OneD, DataType> work(3 * lda);
181  char lrev = 'N';
182  Lapack::DoSgeev(uplo, lrev, lda, A.get(), lda, EigValReal.get(),
183  EigValImag.get(), &dum, 1, &dum, 1, &work[0], lwork,
184  info);
185  }
186  ASSERTL0(info == 0, "Info is not zero");
187  }
188 };
189 
191 {
192  static unsigned int GetRequiredStorageSize(unsigned int rows,
193  unsigned int columns);
194 };
195 
197  : public TriangularMatrixFuncs
198 {
199  static unsigned int CalculateIndex(unsigned int curRow,
200  unsigned int curColumn);
201 
202  static std::tuple<unsigned int, unsigned int> Advance(
203  const unsigned int totalRows, const unsigned int totalColumns,
204  const unsigned int curRow, const unsigned int curColumn);
205 };
206 
208  : public TriangularMatrixFuncs
209 {
210  static unsigned int CalculateIndex(unsigned int totalColumns,
211  unsigned int curRow,
212  unsigned int curColumn);
213 
214  static std::tuple<unsigned int, unsigned int> Advance(
215  const unsigned int totalRows, const unsigned int totalColumns,
216  const unsigned int curRow, const unsigned int curColumn,
217  char transpose = 'N');
218 };
219 
220 /// \internal
221 /// Symmetric matrices use upper triangular packed storage.
223 {
225 
226  static unsigned int CalculateIndex(unsigned int curRow,
227  unsigned int curColumn);
228 
229  template <typename DataType>
230  static void Invert(unsigned int rows, unsigned int columns,
231  Array<OneD, DataType> &data)
232  {
233  ASSERTL0(rows == columns, "Only square matrices can be inverted.");
234 
235  int n = columns;
236  int info = 0;
237  Array<OneD, int> ipivot(n);
238  Array<OneD, DataType> work(n);
239 
240  Lapack::DoSsptrf('U', n, data.get(), ipivot.get(), info);
241 
242  if (info < 0)
243  {
244  std::string message =
245  "ERROR: The " + std::to_string(-info) +
246  "th parameter had an illegal parameter for dsptrf";
247  ASSERTL0(false, message.c_str());
248  }
249  else if (info > 0)
250  {
251  std::string message = "ERROR: Element u_" + std::to_string(info) +
252  std::to_string(info) + " is 0 from dsptrf";
253  ASSERTL0(false, message.c_str());
254  }
255 
256  Lapack::DoSsptri('U', n, data.get(), ipivot.get(), work.get(), info);
257 
258  if (info < 0)
259  {
260  std::string message =
261  "ERROR: The " + std::to_string(-info) +
262  "th parameter had an illegal parameter for dsptri";
263  ASSERTL0(false, message.c_str());
264  }
265  else if (info > 0)
266  {
267  std::string message = "ERROR: Element u_" + std::to_string(info) +
268  std::to_string(info) + " is 0 from dsptri";
269  ASSERTL0(false, message.c_str());
270  }
271  }
272 
273  static std::tuple<unsigned int, unsigned int> Advance(
274  const unsigned int totalRows, const unsigned int totalColumns,
275  const unsigned int curRow, const unsigned int curColumn);
276 };
277 
279 {
280  static std::tuple<unsigned int, unsigned int> Advance(
281  const unsigned int totalRows, const unsigned int totalColumns,
282  const unsigned int curRow, const unsigned int curColumn);
283 
284  template <typename DataType>
285  static void Invert(unsigned int rows, unsigned int columns,
286  Array<OneD, DataType> &data)
287  {
288  ASSERTL0(rows == columns, "Only square matrices can be inverted.");
289  for (unsigned int i = 0; i < rows; ++i)
290  {
291  data[i] = 1.0 / data[i];
292  }
293  }
294 
295  static unsigned int GetRequiredStorageSize(unsigned int rows,
296  unsigned int columns);
297 
298  static unsigned int CalculateIndex(unsigned int row, unsigned int col);
299 };
300 
302 {
303  static unsigned int GetRequiredStorageSize(unsigned int rows,
304  unsigned int columns,
305  unsigned int nSubSuperDiags);
306 };
307 
310 {
311 };
312 
315 {
316 };
317 
318 /// \internal
319 /// Symmetric banded matrices use upper triangular banded packed storage.
322 {
324 
325  static unsigned int CalculateIndex(unsigned int curRow,
326  unsigned int curColumn,
327  unsigned int nSuperDiags);
328 };
329 
330 } // namespace Nektar
331 
332 #endif // NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_MATRIX_FUNCS_H
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define LIB_UTILITIES_EXPORT
1D Array of constant elements with garbage collection and bounds checking.
Definition: SharedArray.hpp:58
size_type size() const
Returns the array's size.
static void DoSsptrf(const char &uplo, const int &n, double *ap, int *ipiv, int &info)
factor a real packed-symmetric matrix using Bunch-Kaufman pivoting.
Definition: Lapack.hpp:150
static void DoSsptri(const char &uplo, const int &n, const double *ap, const int *ipiv, double *work, int &info)
Invert a real symmetric matrix problem.
Definition: Lapack.hpp:199
static void DoSgetrf(const int &m, const int &n, double *a, const int &lda, int *ipiv, int &info)
General matrix LU factorisation.
Definition: Lapack.hpp:267
static void DoSgetri(const int &n, double *a, const int &lda, const int *ipiv, double *wk, const int &lwk, int &info)
Generate matrix inverse.
Definition: Lapack.hpp:296
static void DoSgeev(const char &uplo, const char &lrev, const int &n, const double *a, const int &lda, double *wr, double *wi, double *rev, const int &ldr, double *lev, const int &ldv, double *work, const int &lwork, int &info)
Solve general real matrix eigenproblem.
Definition: Lapack.hpp:326
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
static void Invert(unsigned int rows, unsigned int columns, Array< OneD, DataType > &data)
Definition: MatrixFuncs.h:285
static void EigenSolve(unsigned int n, const Array< OneD, const DataType > &A, Array< OneD, DataType > &EigValReal, Array< OneD, DataType > &EigValImag, Array< OneD, DataType > &EigVecs)
Definition: MatrixFuncs.h:159
static void Invert(unsigned int rows, unsigned int columns, Array< OneD, DataType > &data, const char transpose)
Definition: MatrixFuncs.h:91
static void Invert(unsigned int rows, unsigned int columns, Array< OneD, DataType > &data)
Definition: MatrixFuncs.h:230
static unsigned int GetRequiredStorageSize(unsigned int rows, unsigned int columns, unsigned int nSubSuperDiags)
static unsigned int GetRequiredStorageSize(unsigned int rows, unsigned int columns)