preCICE v3.2.0
Loading...
Searching...
No Matches
SVDFactorization.hpp
Go to the documentation of this file.
1#pragma once
2/*
3 * SVDFactorization.hpp
4 *
5 * Created on: Feb 5, 2016
6 * Author: Klaudius Scheufele
7 */
8
9#ifndef PRECICE_NO_MPI
10
11#include <Eigen/Core>
12#include <Eigen/Dense>
13#include <string>
14
18#include "logging/Logger.hpp"
20
21// ------- CLASS DEFINITION
22
24
30public:
31 // Eigen
32 typedef Eigen::MatrixXd Matrix;
33 typedef Eigen::VectorXd Vector;
34
39 double eps,
40 PtrPreconditioner preconditioner);
41
45 virtual ~SVDFactorization() = default;
46
52 template <typename Derived1, typename Derived2>
53 void update(
54 const Eigen::MatrixBase<Derived1> &A,
55 const Eigen::MatrixBase<Derived2> &B)
56 {
64 if (_initialSVD) {
65 PRECICE_ASSERT(A.rows() == _rowsA, A.rows(), _rowsA);
66 PRECICE_ASSERT(B.rows() == _rowsB, B.rows(), _rowsB);
67 } else {
68 PRECICE_ASSERT(A.cols() == B.cols(), A.cols(), B.cols());
69 _rowsA = A.rows();
70 _rowsB = B.rows();
71 _cols = 0;
72 _psi = Matrix::Zero(_rowsA, 0);
73 _phi = Matrix::Zero(_rowsB, 0);
74 _sigma = Vector::Zero(0);
75 }
76
79 Matrix Atil(_psi.cols(), A.cols()); // Atil is of size (K_bar x m)
80
81 // Atil := \psi^T *A
82 // local computation of \psi^T * A and allreduce_sum to Atil (global), stored local on each proc
83 _parMatrixOps->multiply(_psi.transpose(), A, Atil, (int) _psi.cols(), _globalRowsA, (int) A.cols());
84
85 // Ptil := (I-\psi\psi^T)A
86 // Atil is local on each proc, thus fully local computation, embarrassingly parallel
87 Matrix Ptil = A - _psi * Atil;
88
89 // compute orthogonal basis P of Ptil, i.e., QR-dec (P, R_A) = QR(Ptil)
90 Matrix P, R_A;
92
95 Matrix Btil(_phi.cols(), B.cols()); // Btil is of size (K_bar x m)
96 // Btil := \phi^T *B
97 _parMatrixOps->multiply(_phi.transpose(), B, Btil, (int) _phi.cols(), _globalRowsB, (int) B.cols());
98 // Qtil := (I-\phi\phi^T)B
99 Matrix Qtil = B - _phi * Btil;
100
101 // compute orthogonal basis Q of Qtil, i.e., QR-dec (Q, R_B) = QR(Qtil)
102 Matrix Q, R_B;
104
105 // e_orthModes.stop(true);
106
115 Matrix K = Matrix::Zero(_psi.cols() + R_A.rows(), _psi.cols() + R_B.rows());
116 Matrix K_A(_psi.cols() + R_A.rows(), Atil.cols());
117 Matrix K_B(_phi.cols() + R_B.rows(), Btil.cols());
118
119 for (int i = 0; i < _sigma.size(); i++)
120 K(i, i) = _sigma(i);
121
122 K_A.block(0, 0, Atil.rows(), Atil.cols()) = Atil;
123 K_A.block(Atil.rows(), 0, R_A.rows(), R_A.cols()) = R_A;
124 K_B.block(0, 0, Btil.rows(), Btil.cols()) = Btil;
125 K_B.block(Btil.rows(), 0, R_B.rows(), R_B.cols()) = R_B;
126 K += K_A * K_B.transpose();
127
128 // compute svd of K
129 Eigen::JacobiSVD<Matrix> svd(K, Eigen::ComputeThinU | Eigen::ComputeThinV);
130 _sigma = svd.singularValues();
131 auto &psiPrime = svd.matrixU();
132 auto &phiPrime = svd.matrixV();
133 // e_matK.stop(true);
134
137 Matrix rotLeft(_rowsA, _psi.cols() + P.cols());
138 Matrix rotRight(_rowsB, _phi.cols() + Q.cols());
139
140 rotLeft.block(0, 0, _rowsA, _psi.cols()) = _psi;
141 rotLeft.block(0, _psi.cols(), _rowsA, P.cols()) = P;
142 rotRight.block(0, 0, _rowsB, _phi.cols()) = _phi;
143 rotRight.block(0, _phi.cols(), _rowsB, Q.cols()) = Q;
144
145 // [\psi,P] is distributed block-row wise, but \psiPrime is local on each proc, hence local mult.
146 _psi = rotLeft * psiPrime;
147 _phi = rotRight * phiPrime;
148
149 // e_rot.stop(true);
150
153 _cols = _sigma.size();
154
155 int waste = 0;
156 for (int i = 0; i < (int) _sigma.size(); i++) {
157 if (_sigma(i) < _sigma(0) * _truncationEps) {
158 _cols = i;
159 waste = _sigma.size() - i;
160 break;
161 }
162 }
163 _waste += waste;
164
165 _psi.conservativeResize(_rowsA, _cols);
166 _phi.conservativeResize(_rowsB, _cols);
167 _sigma.conservativeResize(_cols);
168 PRECICE_ASSERT(_sigma(0) >= 0.0);
169 PRECICE_DEBUG("SVD factorization of Jacobian is truncated to {} DOFs. Cut off {} DOFs", _cols, waste);
170
171 _initialSVD = true;
172 }
173
178 void initialize(PtrParMatrixOps parMatOps, int globalRowsA, int globalRowsB);
179
183 void reset();
184
188 Matrix &matrixPsi();
189
194
198 Matrix &matrixPhi();
199
201 int cols();
202
204 Rank rank();
205
207 int getWaste();
208
210 void setThreshold(double eps);
211
213 double getThreshold();
214
216 // void applyPreconditioner();
217
219 // void revertPreconditioner();
220
221 void setPrecondApplied(bool b);
222
224 void setApplyFilterQR(bool b, double eps = 1e-3);
225
226 // bool isPrecondApplied();
227
228 bool isSVDinitialized();
229
232
233private:
246 void computeQRdecomposition(Matrix const &A, int globalRows, Matrix &Q, Matrix &R);
247
248 logging::Logger _log{"acceleration::SVDFactorization"};
249
252
255
260
262 int _rowsA = 0;
263
265 int _rowsB = 0;
266
268 int _cols = 0;
269
272
275
276 // Total number of truncated modes after last call to method getWaste()
277 int _waste = 0;
278
281
283 double _epsQR2 = 1e-3;
284
287
289 bool _initialized = false;
290
292 bool _initialSVD = false;
293
294 bool _applyFilterQR = false;
295};
296
297} // namespace precice::acceleration::impl
298
299#endif /* PRECICE_NO_MPI */
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
int _cols
Number of columns, i.e., rank of the truncated svd.
virtual ~SVDFactorization()=default
Destructor, empty.
PtrParMatrixOps _parMatrixOps
: object for parallel matrix operations, i.e., parallel mat-mat/ mat-vec multiplications
void setApplyFilterQR(bool b, double eps=1e-3)
: enables or disables an additional QR-2 filter for the QR-decomposition
double _truncationEps
Truncation parameter for the updated SVD decomposition.
int _rowsB
Number of rows of second multiplicator (on each proc, i.e., local)
bool _initialSVD
true, if at least one update has been made, i.e., the number of rows is known and a initial rank is g...
void initialize(PtrParMatrixOps parMatOps, int globalRowsA, int globalRowsB)
: initializes the updated SVD factorization, i.e., sets the object for parallel matrix-matrix operati...
double getThreshold()
: returns the truncation threshold for the SVD
bool _preconditionerApplied
true if the preconditioner has been applied appropriate to the updated SVD decomposition
void setThreshold(double eps)
: sets the threshold for the truncation of the SVD factorization
Matrix _psi
: SVD factorization of the matrix J = _psi * _sigma * _phi^T
void setPrecondApplied(bool b)
: applies the preconditioner to the factorized and truncated representation of the Jacobian matrix
Matrix & matrixPhi()
: returns a matrix representation of the orthogonal matrix Phi, A = Psi * Sigma * Phi^T
Vector & singularValues()
: returns a matrix representation of the orthogonal matrix Sigma, A = Psi * Sigma * Phi^T
void reset()
: resets the SVD factorization
Rank rank()
: returns the rank of the truncated SVD factorization
int _globalRowsB
Number of global rows of second multiplicator, i.e., sum of _rows for all procs.
double _epsQR2
Threshold for the QR2 filter for the QR decomposition.
int _globalRowsA
Number of global rows of first multiplicator, i.e., sum of _rows for all procs.
void setfstream(std::fstream *stream)
Optional file-stream for logging output.
Matrix & matrixPsi()
: returns a matrix representation of the orthogonal matrix Psi, A = Psi * Sigma * Phi^bs
bool _initialized
true, if ParallelMatrixOperations object is set, i.e., initialized
void update(const Eigen::MatrixBase< Derived1 > &A, const Eigen::MatrixBase< Derived2 > &B)
: updates the SVD decomposition with the rank-1 update A*B^T, i.e., _psi * _sigma * _phi^T + A*B^T an...
int cols()
: returns the number of columns in the QR-decomposition
SVDFactorization(double eps, PtrPreconditioner preconditioner)
Constructor.
void computeQRdecomposition(Matrix const &A, int globalRows, Matrix &Q, Matrix &R)
: computes the QR decomposition of a matrix A of type A = PSI^T*A \in R^(rank x n)
PtrPreconditioner _preconditioner
: preconditioner for least-squares system if vectorial system is used.
int getWaste()
: returns the total number of truncated modes since last call to this method
int _rowsA
Number of rows of first multiplicator (on each proc, i.e., local)
This class provides a lightweight logger.
Definition Logger.hpp:17
std::shared_ptr< Preconditioner > PtrPreconditioner
std::shared_ptr< ParallelMatrixOperations > PtrParMatrixOps
int Rank
Definition Types.hpp:37