preCICE v3.3.0
Loading...
Searching...
No Matches
Preconditioner.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <Eigen/Core>
4#include <numeric>
5#include <vector>
6
9#include "logging/Logger.hpp"
10#include "utils/assertion.hpp"
11
13
24public:
25 Preconditioner(int maxNonConstTimeWindows)
26 : _maxNonConstTimeWindows(maxNonConstTimeWindows)
27 {
28 }
29
31 virtual ~Preconditioner() = default;
32
38 {
40
41 _subVectorSizes = svs;
42
43 // Compute offsets of each subvector
44 _subVectorOffsets.resize(_subVectorSizes.size(), 0);
46
47 size_t N = std::accumulate(_subVectorSizes.begin(), _subVectorSizes.end(), static_cast<std::size_t>(0));
48
49 // cannot do this already in the constructor as the size is unknown at that point
50 _weights.resize(N, 1.0);
51 _invWeights.resize(N, 1.0);
52 }
53
58 void apply(Eigen::MatrixXd &M, bool transpose)
59 {
61 if (transpose) {
62 PRECICE_DEBUG_IF((int) _weights.size() != M.cols(), "The number of columns of the matrix {} and weights size {} mismatched.", M.rows(), _weights.size());
63
64 int validCols = std::min(static_cast<int>(M.cols()), (int) _weights.size());
65 for (int i = 0; i < validCols; i++) {
66 for (int j = 0; j < M.rows(); j++) {
67 M(j, i) *= _weights[i];
68 }
69 }
70 } else {
71 PRECICE_DEBUG_IF((int) _weights.size() != M.rows(), "The number of rows of the matrix {} and weights size {} mismatched.", M.rows(), _weights.size());
72
73 int validRows = std::min(static_cast<int>(M.rows()), (int) _weights.size());
74 for (int i = 0; i < M.cols(); i++) {
75 for (int j = 0; j < validRows; j++) {
76 M(j, i) *= _weights[j];
77 }
78 }
79 }
80 }
81
86 void revert(Eigen::MatrixXd &M, bool transpose)
87 {
89 // PRECICE_ASSERT(_needsGlobalWeights);
90 if (transpose) {
91 PRECICE_DEBUG_IF((int) _weights.size() != M.cols(), "The number of columns of the matrix {} and weights size {} mismatched.", M.cols(), _weights.size());
92
93 int validCols = std::min(static_cast<int>(M.cols()), (int) _weights.size());
94 for (int i = 0; i < validCols; i++) {
95 for (int j = 0; j < M.rows(); j++) {
96 M(j, i) *= _invWeights[i];
97 }
98 }
99 } else {
100 PRECICE_DEBUG_IF((int) _weights.size() != M.rows(), "The number of rows of the matrix {} and weights size {} mismatched.", M.rows(), _weights.size());
101
102 int validRows = std::min(static_cast<int>(M.rows()), (int) _weights.size());
103 for (int i = 0; i < M.cols(); i++) {
104 for (int j = 0; j < validRows; j++) {
105 M(j, i) *= _invWeights[j];
106 }
107 }
108 }
109 }
110
112 void apply(Eigen::MatrixXd &M)
113 {
115 PRECICE_DEBUG_IF((int) _weights.size() != M.rows(), "The number of rows of the matrix {} and weights size {} mismatched.", M.rows(), _weights.size());
116
117 // scale matrix M
118 int validRows = std::min(static_cast<int>(M.rows()), (int) _weights.size());
119 for (int i = 0; i < M.cols(); i++) {
120 for (int j = 0; j < validRows; j++) {
121 M(j, i) *= _weights[j];
122 }
123 }
124 }
125
127 void apply(Eigen::VectorXd &v)
128 {
130 PRECICE_DEBUG_IF((int) _weights.size() != v.size(), "The vector size {} and weights size {} mismatched.", v.size(), _weights.size());
131
132 // scale vector
133 int validSize = std::min(static_cast<int>(v.size()), (int) _weights.size());
134 for (int j = 0; j < validSize; j++) {
135 v[j] *= _weights[j];
136 }
137 }
138
140 void revert(Eigen::MatrixXd &M)
141 {
143 PRECICE_DEBUG_IF((int) _weights.size() != M.rows(), "The number of rows of the matrix {} and weights size {} mismatched.", M.rows(), _weights.size());
144
145 // scale matrix M
146 int validRows = std::min(static_cast<int>(M.rows()), (int) _weights.size());
147 for (int i = 0; i < M.cols(); i++) {
148 for (int j = 0; j < validRows; j++) {
149 M(j, i) *= _invWeights[j];
150 }
151 }
152 }
153
155 void revert(Eigen::VectorXd &v)
156 {
158 PRECICE_DEBUG_IF((int) _weights.size() != v.size(), "The vector size {} and weights size {} mismatched.", v.size(), _weights.size());
159
160 // revert vector scaling
161 int validSize = std::min(static_cast<int>(v.size()), (int) _weights.size());
162 for (int j = 0; j < validSize; j++) {
163 v[j] *= _invWeights[j];
164 }
165 }
166
172 void update(bool timeWindowComplete, const Eigen::VectorXd &oldValues, const Eigen::VectorXd &res)
173 {
175
176 // if number of allowed non-const time windows is exceeded, do not update weights
177 if (_frozen)
178 return;
179
180 // increment number of time windows that has been scaled with changing preconditioning weights
181 if (timeWindowComplete) {
184 _frozen = true;
185 }
186
187 // type specific update functionality
188 _update_(timeWindowComplete, oldValues, res);
189 }
190
193 {
195 return _requireNewQR;
196 }
197
200 {
201 _requireNewQR = false;
202 }
203
205 {
206 return _weights;
207 }
208
209 bool isConst()
210 {
211 return _frozen;
212 }
213
214protected:
217
220
223
226
231
234
236 bool _requireNewQR = false;
237
239 bool _frozen = false;
240
246 virtual void _update_(bool timeWindowComplete, const Eigen::VectorXd &oldValues, const Eigen::VectorXd &res) = 0;
247
248private:
249 logging::Logger _log{"acceleration::Preconditioner"};
250};
251
252} // namespace precice::acceleration::impl
#define PRECICE_DEBUG_IF(condition,...)
Definition LogMacros.hpp:63
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
T accumulate(T... args)
void apply(Eigen::MatrixXd &M, bool transpose)
Apply preconditioner to matrix.
void revert(Eigen::MatrixXd &M, bool transpose)
Apply inverse preconditioner to matrix.
int _nbNonConstTimeWindows
Counts the number of completed time windows with a non-const weighting.
std::vector< size_t > _subVectorSizes
Sizes of each sub-vector, i.e. each coupling data.
void newQRfulfilled()
to tell the preconditioner that QR-decomposition has been recomputed
void update(bool timeWindowComplete, const Eigen::VectorXd &oldValues, const Eigen::VectorXd &res)
Update the scaling after every FSI iteration and require a new QR decomposition (if necessary)
virtual void _update_(bool timeWindowComplete, const Eigen::VectorXd &oldValues, const Eigen::VectorXd &res)=0
Update the scaling after every FSI iteration and require a new QR decomposition (if necessary)
virtual void initialize(std::vector< size_t > &svs)
initialize the preconditioner
virtual ~Preconditioner()=default
Destructor, empty.
void revert(Eigen::MatrixXd &M)
To transform balanced values back to physical values. Matrix version.
std::vector< double > _invWeights
Inverse weights (for efficiency reasons)
bool requireNewQR()
returns true if a QR decomposition from scratch is necessary
int _maxNonConstTimeWindows
maximum number of non-const time windows, i.e., after this number of time windows,...
std::vector< double > _weights
Weights used to scale the matrix V and the residual.
void revert(Eigen::VectorXd &v)
To transform balanced values back to physical values. Vector version.
std::vector< size_t > _subVectorOffsets
Offsets of each sub-vector in concatenated data, i.e. each coupling data.
bool _requireNewQR
True if a QR decomposition from scratch is necessary.
void apply(Eigen::VectorXd &v)
To transform physical values to balanced values. Vector version.
void apply(Eigen::MatrixXd &M)
To transform physical values to balanced values. Matrix version.
bool _frozen
True if _nbNonConstTimeWindows >= _maxNonConstTimeWindows, i.e., preconditioner is not updated any mo...
This class provides a lightweight logger.
Definition Logger.hpp:17
T min(T... args)
T partial_sum(T... args)