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.
dense_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_DENSE_HOUSEHOLDER_QR_H_INCLUDED)
14 #define KRATOS_DENSE_HOUSEHOLDER_QR_H_INCLUDED
15 
16 // External includes
17 #include "amgcl/detail/qr.hpp"
18 
19 // Project includes
20 #include "dense_qr_decomposition.h"
21 
22 namespace Kratos {
23 
26 
30 
34 
38 
42 
43 template <class TDenseSpaceType>
45 {
46 public:
47 
50 
53 
54  using DataType = typename TDenseSpaceType::DataType;
57  using AMGCLQRType = amgcl::detail::QR<DataType>;
58 
62 
64 
65  virtual ~DenseHouseholderQRDecomposition() = default;
66 
70 
71 
75 
81  static std::string Name()
82  {
83  return "dense_householder_qr_decomposition";
84  }
85 
92  void Compute(MatrixType& rInputMatrix) override
93  {
94  // Set input data
95  // Note that we need a copy as QR decomposition is modifying the input
96  mpA = &rInputMatrix;
97  DataType *p_0_0 = &((*mpA)(0,0));
98  const std::size_t m = rInputMatrix.size1();
99  const std::size_t n = rInputMatrix.size2();
100 
101  // Compute the Householder QR decomposition
102  mHouseholderQR.compute(m, n, p_0_0);
103  }
104 
113  void Compute(
114  MatrixType& rInputMatrix,
115  MatrixType& rMatrixQ,
116  MatrixType& rMatrixR) override
117  {
118  // Set input data
119  // Note that we need a copy as QR decomposition is modifying the input
120  mpA = &rInputMatrix;
121  DataType *p_0_0 = &((*mpA)(0,0));
122  const std::size_t m = rInputMatrix.size1();
123  const std::size_t n = rInputMatrix.size2();
124 
125  // Compute the Householder QR decomposition
126  mHouseholderQR.factorize(m, n, p_0_0);
127 
128  // Check sizes and fill Q values
129  if (rMatrixQ.size1() != m || rMatrixQ.size2() != n) {
130  rMatrixQ.resize(m,n,false);
131  }
132  for (std::size_t i = 0; i < m; ++i) {
133  for (std::size_t j = 0; j < n; ++j) {
134  rMatrixQ(i,j) = mHouseholderQR.Q(i,j);
135  }
136  }
137 
138  // Check sizes and fill R values
139  MatrixR(rMatrixR);
140  }
141 
148  void Solve(
149  MatrixType& rB,
150  MatrixType& rX) const override
151  {
152  // Check that QR decomposition has been already computed
153  KRATOS_ERROR_IF(!mpA) << "QR decomposition not computed yet. Please call 'Compute' before 'Solve'." << std::endl;
154 
155  // Set input data
156  DataType* p_A_0_0 = &((*mpA)(0,0));
157  const std::size_t m = mpA->size1();
158  const std::size_t n = mpA->size2();
159 
160  // Check output matrix size
161  const std::size_t l = rB.size2();
162  if (rX.size1() != n || rX.size2() != l) {
163  rX.resize(n, l, false);
164  }
165 
166  // Call the QR solve method for each column
167  VectorType aux_B_col(l);
168  VectorType aux_X_col(l);
169  const bool qr_computed = true;
170  auto storage_order = amgcl::detail::storage_order::row_major;
171  for (std::size_t i_col = 0; i_col < l; ++i_col) {
172  TDenseSpaceType::GetColumn(i_col, rB, aux_B_col);
173  TDenseSpaceType::GetColumn(i_col, rX, aux_X_col);
174  DataType* p_b_0 = &(aux_B_col(0));
175  DataType* p_x_0 = &(aux_X_col(0));
176  const_cast<AMGCLQRType&>(mHouseholderQR).solve(m, n, p_A_0_0, p_b_0, p_x_0, storage_order, qr_computed);
177  TDenseSpaceType::SetColumn(i_col, rX, aux_X_col);
178  }
179  }
180 
187  void Solve(
188  const VectorType& rB,
189  VectorType& rX) const override
190  {
191  // Check that QR decomposition has been already computed
192  KRATOS_ERROR_IF(!mpA) << "QR decomposition not computed yet. Please call 'Compute' before 'Solve'." << std::endl;
193 
194  // Set input data
195  DataType* p_b_0 = &((const_cast<VectorType&>(rB))(0));
196  DataType* p_x_0 = &(rX(0));
197  DataType *p_A_0_0 = &((*mpA)(0,0));
198  const std::size_t m = mpA->size1();
199  const std::size_t n = mpA->size2();
200 
201  // Check output vector size
202  if (rX.size() != n) {
203  rX.resize(n, false);
204  }
205 
206  // Call the QR solve method
207  const bool qr_computed = true;
208  auto storage_order = amgcl::detail::storage_order::row_major;
209  const_cast<AMGCLQRType&>(mHouseholderQR).solve(m, n, p_A_0_0, p_b_0, p_x_0, storage_order, qr_computed);
210  }
211 
217  void MatrixQ(MatrixType& rMatrixQ) const override
218  {
219  // We intentionally avoid to implement this method as it requires to call the factorize of QR include
220  // Otherwise we would need to always do the factorize call, which is more expensive than the simpler compute one
221  KRATOS_ERROR << "This method is not implemented. Please use the 'Compute' interface with Q and R return." << std::endl;
222  }
223 
229  void MatrixR(MatrixType& rMatrixR) const override
230  {
231  // Check that QR has been already computed
232  KRATOS_ERROR_IF(!mpA) << "QR decomposition not computed yet. Please call 'Compute' before 'MatrixR'." << std::endl;
233 
234  // Check input size
235  const std::size_t n = mpA->size2();
236  if (rMatrixR.size1() != n || rMatrixR.size2() != n) {
237  rMatrixR.resize(n,n,false);
238  }
239 
240  // Get R values from QR util
241  for (std::size_t i = 0; i < n; ++i) {
242  for (std::size_t j = 0; j < n; ++j) {
243  rMatrixR(i,j) = mHouseholderQR.R(i,j);
244  }
245  }
246  }
247 
253  void MatrixP(MatrixType& rMatrixP) const override
254  {
255  KRATOS_ERROR << "Householder QR decomposition does not implement the P matrix return" << std::endl;
256  }
257 
263  std::size_t Rank() const override
264  {
265  KRATOS_ERROR << "Householder QR decomposition is not rank revealing." << std::endl;
266  }
267 
273  void PrintInfo(std::ostream &rOStream) const override
274  {
275  rOStream << "Decomposition <" << Name() << "> finished.";
276  }
277 
281 
282 
286 
287 
291 
292 
296 
297 
299 private:
302 
303 
307 
308  AMGCLQRType mHouseholderQR;
309 
310  MatrixType* mpA = nullptr;
311 
315 
316 
320 
321 
325 
326 
330 
331 
335 
336 
340 
341 
343 };
344 
347 
348 
352 
353 
355 } // namespace Kratos
356 
357 #endif // defined(KRATOS_DENSE_HOUSEHOLDER_QR_H_INCLUDED)
Definition: dense_householder_qr_decomposition.h:45
typename TDenseSpaceType::MatrixType MatrixType
Definition: dense_householder_qr_decomposition.h:56
void MatrixR(MatrixType &rMatrixR) const override
Upper triangular matrix getter If computed, this method sets the upper triangular matrix in the provi...
Definition: dense_householder_qr_decomposition.h:229
typename TDenseSpaceType::VectorType VectorType
Definition: dense_householder_qr_decomposition.h:55
void Solve(const VectorType &rB, VectorType &rX) const override
Solves the problem Ax=b Being A the input matrix, this method solves the problem Ax = b.
Definition: dense_householder_qr_decomposition.h:187
void MatrixP(MatrixType &rMatrixP) const override
Pivoting matrix getter If computed, this method sets the pivoting matrix.
Definition: dense_householder_qr_decomposition.h:253
KRATOS_CLASS_POINTER_DEFINITION(DenseHouseholderQRDecomposition)
Definition of the shared pointer of the class.
static std::string Name()
Name of the QR Returns a string containing the name of the current QR decomposition.
Definition: dense_householder_qr_decomposition.h:81
virtual ~DenseHouseholderQRDecomposition()=default
void PrintInfo(std::ostream &rOStream) const override
QR information Outputs the QR class information.
Definition: dense_householder_qr_decomposition.h:273
void Compute(MatrixType &rInputMatrix) override
Compute the QR Computes the QR Decomposition (QR) of the given imput matrix Note that the input matri...
Definition: dense_householder_qr_decomposition.h:92
std::size_t Rank() const override
Rank of the provided array Calculates and returns the rank of the array decomposed with the QR.
Definition: dense_householder_qr_decomposition.h:263
void Solve(MatrixType &rB, MatrixType &rX) const override
Solves the problem Ax=b Being A the input matrix, this method solves the problem Ax = b.
Definition: dense_householder_qr_decomposition.h:148
typename TDenseSpaceType::DataType DataType
Definition: dense_householder_qr_decomposition.h:54
void Compute(MatrixType &rInputMatrix, MatrixType &rMatrixQ, MatrixType &rMatrixR) override
Compute the QR Computes the QR (QR) of the given input matrix Note that the input matrix is modidifed...
Definition: dense_householder_qr_decomposition.h:113
amgcl::detail::QR< DataType > AMGCLQRType
Definition: dense_householder_qr_decomposition.h:57
void MatrixQ(MatrixType &rMatrixQ) const override
Unitary matrix getter If computed, this method sets the unitary matrix in the provided array.
Definition: dense_householder_qr_decomposition.h:217
Definition: dense_qr_decomposition.h:44
#define KRATOS_ERROR
Definition: exception.h:161
#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
def solve(A, rhs)
Definition: ode_solve.py:303
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int j
Definition: quadrature.py:648
int m
Definition: run_marine_rain_substepping.py:8
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17