KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
eigen_dense_column_pivoting_householder_qr_decomposition.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Ruben Zorrilla
11 //
12 
13 #if !defined(KRATOS_EIGEN_DENSE_COLUMN_PIVOTING_HOUSEHOLDER_QR_H_INCLUDED)
14 #define KRATOS_EIGEN_DENSE_COLUMN_PIVOTING_HOUSEHOLDER_QR_H_INCLUDED
15 
16 // External includes
17 #include <Eigen/QR>
18 
19 // Project includes
20 #include "includes/define.h"
21 #include "linear_solvers_define.h"
23 
24 namespace Kratos {
25 
28 
32 
36 
40 
44 
45 template<class TDenseSpace>
47 {
48 public:
49 
52 
55 
56  typedef typename TDenseSpace::DataType DataType;
59 
62 
66 
68 
72 
73 
77 
78  static std::string Name()
79  {
80  return "dense_column_pivoting_householder_qr_decomposition";
81  }
82 
83  void Compute(MatrixType& rInputMatrix) override
84  {
85  // Householder QR requires m >= n
86  const std::size_t m = rInputMatrix.size1();
87  const std::size_t n = rInputMatrix.size2();
88  KRATOS_ERROR_IF(m < n) << "Householder QR decomposition requires m >= n. Input matrix size is (" << m << "," << n << ")." << std::endl;
89 
90  // Compute the Householder QR decomposition
91  // Note that the QR is computed when constructing the pointer
92  Eigen::Map<EigenMatrix> eigen_input_matrix_map(rInputMatrix.data().begin(), m, n);
93  mpColPivHouseholderQR = Kratos::make_unique<Eigen::ColPivHouseholderQR<Eigen::Ref<EigenMatrix>>>(eigen_input_matrix_map);
94  }
95 
96  void Compute(
97  MatrixType& rInputMatrix,
98  MatrixType& rMatrixQ,
99  MatrixType& rMatrixR) override
100  {
101  Compute(rInputMatrix);
102  MatrixQ(rMatrixQ);
103  MatrixR(rMatrixR);
104  }
105 
106  void Solve(
107  MatrixType& rB,
108  MatrixType& rX) const override
109  {
110  // Check that QR decomposition has been already computed
111  KRATOS_ERROR_IF(!mpColPivHouseholderQR) << "QR decomposition not computed yet. Please call 'Compute' before 'Solve'." << std::endl;
112 
113  // Check output matrix size
114  std::size_t n = rB.size2();
115  const std::size_t rank = Rank();
116  if (rX.size1() != rank || rX.size2() != n) {
117  rX.resize(rank,n,false);
118  }
119 
120  // Solve the problem Ax = b
121  Eigen::Map<EigenMatrix> eigen_x_map(rX.data().begin(), rank, n);
122  Eigen::Map<EigenMatrix> eigen_rhs_map(rB.data().begin(), rB.size1(), n);
123  eigen_x_map = mpColPivHouseholderQR->solve(eigen_rhs_map);
124  }
125 
126  void Solve(
127  const VectorType& rB,
128  VectorType& rX) const override
129  {
130  // Check that QR decomposition has been already computed
131  KRATOS_ERROR_IF(!mpColPivHouseholderQR) << "QR decomposition not computed yet. Please call 'Compute' before 'Solve'." << std::endl;
132 
133  // Check output matrix size
134  const std::size_t rank = Rank();
135  if (rX.size() != rank) {
136  rX.resize(rank,false);
137  }
138 
139  // Solve the problem Ax = b
140  Eigen::Map<EigenMatrix> eigen_x_map(rX.data().begin(), rank, 1);
141  Eigen::Map<EigenMatrix> eigen_rhs_map(const_cast<VectorType&>(rB).data().begin(), rB.size(), 1);
142  eigen_x_map = mpColPivHouseholderQR->solve(eigen_rhs_map);
143  }
144 
145  void MatrixQ(MatrixType& rMatrixQ) const override
146  {
147  // Check that QR decomposition has been already computed
148  KRATOS_ERROR_IF(!mpColPivHouseholderQR) << "QR decomposition not computed yet. Please call 'Compute' before 'MatrixQ'." << std::endl;
149 
150  // Set the thin Q to be returned
151  const std::size_t Q_rows = mpColPivHouseholderQR->householderQ().rows();
152  const std::size_t rank = Rank();
153  if (rMatrixQ.size1() != Q_rows || rMatrixQ.size2() != rank) {
154  rMatrixQ.resize(Q_rows,rank,false);
155  }
156 
157  // Get the thin unitary matrix Q from the complete one
158  // Note that Eigen stores it not as matrix type but as a sequence of Householder transformations (householderQ())
159  Eigen::Map<EigenMatrix> thin_Q(rMatrixQ.data().begin(), Q_rows, rank);
160  thin_Q = EigenMatrix::Identity(Q_rows,rank);
161  thin_Q = mpColPivHouseholderQR->householderQ() * thin_Q;
162  }
163 
164  void MatrixR(MatrixType& rMatrixR) const override
165  {
166  // Check that QR decomposition has been already computed
167  KRATOS_ERROR_IF(!mpColPivHouseholderQR) << "QR decomposition not computed yet. Please call 'Compute' before 'MatrixR'." << std::endl;
168 
169  // Set the matrix R to be returned
170  const std::size_t rank = Rank();
171  if (rMatrixR.size1() != rank || rMatrixR.size2() != rank) {
172  rMatrixR.resize(rank,rank,false);
173  }
174 
175  // Get the upper triangular matrix
176  // Note that we specify Eigen to return the upper triangular part as the bottom part are auxiliary internal values
177  Eigen::Map<EigenMatrix> matrix_R_map(rMatrixR.data().begin(), rank, rank);
178  matrix_R_map = mpColPivHouseholderQR->matrixR().topLeftCorner(rank, rank).template triangularView<Eigen::Upper>();
179  }
180 
181  void MatrixP(MatrixType& rMatrixP) const override
182  {
183  // Check that QR decomposition has been already computed
184  KRATOS_ERROR_IF(!mpColPivHouseholderQR) << "QR decomposition not computed yet. Please call 'Compute' before 'MatrixP'." << std::endl;
185 
186  // Get the permutation matrix
187  const auto& r_P = mpColPivHouseholderQR->colsPermutation();
188  const std::size_t m = r_P.rows();
189  const std::size_t n = r_P.cols();
190 
191  // Output the permutation matrix
192  if (rMatrixP.size1() != m || rMatrixP.size2() != n) {
193  rMatrixP.resize(m,n,false);
194  }
195  Eigen::Map<EigenMatrix> matrix_P_map(rMatrixP.data().begin(), m, n);
196  matrix_P_map = r_P;
197  }
198 
199  std::size_t Rank() const override
200  {
201  // Check that QR decomposition has been already computed
202  KRATOS_ERROR_IF(!mpColPivHouseholderQR) << "QR decomposition not computed yet. Please call 'Compute' before 'Rank'." << std::endl;
203 
204  return mpColPivHouseholderQR->rank();
205  }
206 
207  void PrintInfo(std::ostream &rOStream) const override
208  {
209  rOStream << "EigenDecomposition <" << Name() << "> finished.";
210  }
211 
215 
216 
220 
221 
225 
226 
230 
231 
233 private:
236 
237 
241 
242  std::unique_ptr<Eigen::ColPivHouseholderQR<Eigen::Ref<EigenMatrix>>> mpColPivHouseholderQR = std::unique_ptr<Eigen::ColPivHouseholderQR<Eigen::Ref<EigenMatrix>>>(nullptr);
243 
247 
248 
252 
253 
257 
258 
262 
263 
267 
268 
272 
273 
275 };
276 
279 
280 
284 
285 
287 } // namespace Kratos
288 
289 #endif // defined(KRATOS_EIGEN_DENSE_COLUMN_PIVOTING_HOUSEHOLDER_QR_H_INCLUDED)
Definition: dense_qr_decomposition.h:44
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:47
void MatrixP(MatrixType &rMatrixP) const override
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:181
TDenseSpace::DataType DataType
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:56
std::size_t Rank() const override
Rank of the provided array Calculates and returns the rank of the array decomposed with the QR.
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:199
static std::string Name()
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:78
void Solve(const VectorType &rB, VectorType &rX) const override
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:126
TDenseSpace::MatrixType MatrixType
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:58
void MatrixQ(MatrixType &rMatrixQ) const override
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:145
Kratos::EigenDynamicMatrix< DataType > EigenMatrix
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:61
void MatrixR(MatrixType &rMatrixR) const override
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:164
Kratos::EigenDynamicVector< DataType > EigenVector
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:60
void Compute(MatrixType &rInputMatrix, MatrixType &rMatrixQ, MatrixType &rMatrixR) override
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:96
TDenseSpace::VectorType VectorType
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:57
void Compute(MatrixType &rInputMatrix) override
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:83
void Solve(MatrixType &rB, MatrixType &rX) const override
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:106
void PrintInfo(std::ostream &rOStream) const override
QR information Outputs the QR class information.
Definition: eigen_dense_column_pivoting_householder_qr_decomposition.h:207
KRATOS_CLASS_POINTER_DEFINITION(EigenDenseColumnPivotingHouseholderQRDecomposition)
Definition of the shared pointer of the class.
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
Vector VectorType
Definition: geometrical_transformation_utilities.h:56
Matrix MatrixType
Definition: geometrical_transformation_utilities.h:55
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
Eigen::Matrix< _Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > EigenDynamicMatrix
Definition: linear_solvers_define.h:32
Eigen::Matrix< _Scalar, Eigen::Dynamic, 1 > EigenDynamicVector
Definition: linear_solvers_define.h:33
data
Definition: mesh_to_mdpa_converter.py:59
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int m
Definition: run_marine_rain_substepping.py:8