preCICE v3.1.2
Loading...
Searching...
No Matches
ResidualSumPreconditioner.cpp
Go to the documentation of this file.
2#include <algorithm>
3#include <cmath>
6#include "utils/IntraComm.hpp"
7#include "utils/assertion.hpp"
8
10
12 int maxNonConstTimeWindows)
13 : Preconditioner(maxNonConstTimeWindows)
14{
15}
16
24
25void ResidualSumPreconditioner::_update_(bool timeWindowComplete,
26 const Eigen::VectorXd &oldValues,
27 const Eigen::VectorXd &res)
28{
29 if (not timeWindowComplete) {
31
32 double sum = 0.0;
33
34 int offset = 0;
35 for (size_t k = 0; k < _subVectorSizes.size(); k++) {
36 Eigen::VectorXd part = Eigen::VectorXd::Zero(_subVectorSizes[k]);
37 for (size_t i = 0; i < _subVectorSizes[k]; i++) {
38 part(i) = res(i + offset);
39 }
40 norms[k] = utils::IntraComm::dot(part, part);
41 sum += norms[k];
42 offset += _subVectorSizes[k];
43 norms[k] = std::sqrt(norms[k]);
44 }
45 sum = std::sqrt(sum);
47 math::equals(sum, 0.0),
48 "All residual sub-vectors in the residual-sum preconditioner are numerically zero ( sum = {}). "
49 "This indicates that the data values exchanged between two successive iterations did not change. "
50 "The simulation may be unstable, e.g. produces NAN values. Please check the data values exchanged "
51 "between the solvers is not identical between iterations. The preconditioner scaling factors were "
52 "not updated in this iteration and the scaling factors determined in the previous iteration were used.",
53 sum);
54
55 for (size_t k = 0; k < _subVectorSizes.size(); k++) {
57 _residualSum[k] += norms[k] / sum;
58
61 "A sub-vector in the residual-sum preconditioner became numerically zero ( sub-vector = {}). "
62 "If this occurred in the second iteration and the initial-relaxation factor is equal to 1.0, "
63 "check if the coupling data values of one solver is zero in the first iteration. "
64 "The preconditioner scaling factors were not updated for this iteration and the scaling factors "
65 "determined in the previous iteration were used.",
66 _residualSum[k]);
67 }
68
69 offset = 0;
70 for (size_t k = 0; k < _subVectorSizes.size(); k++) {
71 if (not math::equals(_residualSum[k], 0.0)) {
72 for (size_t i = 0; i < _subVectorSizes[k]; i++) {
73 _weights[i + offset] = 1 / _residualSum[k];
74 _invWeights[i + offset] = _residualSum[k];
75 }
76 PRECICE_DEBUG("preconditioner scaling factor[{}] = {}", k, 1 / _residualSum[k]);
77 }
78 offset += _subVectorSizes[k];
79 }
80
81 _requireNewQR = true;
82 } else {
83 for (size_t k = 0; k < _subVectorSizes.size(); k++) {
84 _residualSum[k] = 0.0;
85 }
86 }
87}
88
89} // namespace precice::acceleration::impl
#define PRECICE_WARN_IF(condition,...)
Definition LogMacros.hpp:21
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:64
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:95
Interface for preconditioner variants that can be applied to quasi-Newton acceleration schemes.
std::vector< size_t > _subVectorSizes
Sizes of each sub-vector, i.e. each coupling data.
virtual void initialize(std::vector< size_t > &svs)
initialize the preconditioner
std::vector< double > _invWeights
Inverse weights (for efficiency reasons)
std::vector< double > _weights
Weights used to scale the matrix V and the residual.
bool _requireNewQR
True if a QR decomposition from scratch is necessary.
virtual void initialize(std::vector< size_t > &svs)
initialize the preconditioner
virtual void _update_(bool timeWindowComplete, const Eigen::VectorXd &oldValues, const Eigen::VectorXd &res)
Update the scaling after every FSI iteration.
static double dot(const Eigen::VectorXd &vec1, const Eigen::VectorXd &vec2)
constexpr bool equals(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares two Eigen::MatrixBase for equality up to tolerance.
constexpr double NUMERICAL_ZERO_DIFFERENCE
T resize(T... args)
T size(T... args)
T sqrt(T... args)