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
46namespace 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,
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,
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:208
#define LIB_UTILITIES_EXPORT
1D Array of constant elements with garbage collection and bounds checking.
Definition: SharedArray.hpp:56
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:112
static void DoSsptri(const char &uplo, const int &n, const double *ap, const int *ipiv, double *work, int &info)
Invert a real packed-symmetric matrix problem.
Definition: Lapack.hpp:162
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:248
static void DoSgetri(const int &n, double *a, const int &lda, const int *ipiv, double *wk, const int &lwk, int &info)
General matrix inverse.
Definition: Lapack.hpp:277
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:307
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)