Loading [MathJax]/extensions/tex2jax.js
OGS
ConvergenceCriterionPerComponentResidual.cpp
Go to the documentation of this file.
1
12
13#include "BaseLib/ConfigTree.h"
14#include "BaseLib/Logging.h"
18
19namespace NumLib
20{
23 std::vector<double>&& absolute_tolerances,
24 std::vector<double>&& relative_tolerances,
25 std::vector<double>&& damping_alpha,
26 bool damping_alpha_switch,
27 const MathLib::VecNormType norm_type)
29 _abstols(std::move(absolute_tolerances)),
30 _reltols(std::move(relative_tolerances)),
31 _residual_norms_0(_abstols.size()),
32 _damping_alpha(std::move(damping_alpha)),
33 _damping_alpha_switch(damping_alpha_switch)
34{
35 if (_abstols.size() != _reltols.size())
36 {
37 OGS_FATAL(
38 "The number of absolute and relative tolerances given must be the "
39 "same.");
40 }
41
42 if (_abstols.empty())
43 {
44 OGS_FATAL("The given tolerances vector is empty.");
45 }
46}
47
49 const GlobalVector& minus_delta_x, GlobalVector const& x)
50{
51 if (!_dof_table)
52 {
53 OGS_FATAL("D.o.f. table has not been set.");
54 }
55
56 for (unsigned global_component = 0; global_component < _abstols.size();
57 ++global_component)
58 {
59 // TODO short cut if tol <= 0.0
60 auto error_dx =
61 norm(minus_delta_x, global_component, _norm_type, *_dof_table);
62 auto norm_x = norm(x, global_component, _norm_type, *_dof_table);
63
64 INFO(
65 "Convergence criterion, component {:d}: |dx|={:.4e}, |x|={:.4e}, "
66 "|dx|/|x|={:.4e}",
67 global_component, error_dx, norm_x,
68 (norm_x == 0. ? std::numeric_limits<double>::quiet_NaN()
69 : (error_dx / norm_x)));
70 }
71}
72
74 const GlobalVector& residual)
75{
76 if (!_dof_table)
77 {
78 OGS_FATAL("D.o.f. table has not been set.");
79 }
80
81 for (unsigned global_component = 0; global_component < _abstols.size();
82 ++global_component)
83 {
84 // TODO short cut if tol <= 0.0
85 auto norm_res =
86 norm(residual, global_component, _norm_type, *_dof_table);
87
89 {
90 INFO("Convergence criterion, component {:d}: |r0|={:.4e}",
91 global_component, norm_res);
92 _residual_norms_0[global_component] = norm_res;
93 }
94 else
95 {
96 auto const norm_res0 = _residual_norms_0[global_component];
97 INFO(
98 "Convergence criterion, component {:d}: |r|={:.4e}, "
99 "|r0|={:.4e}, |r|/|r0|={:.4e}",
100 global_component, norm_res, norm_res0,
101 (norm_res0 == 0. ? std::numeric_limits<double>::quiet_NaN()
102 : (norm_res / norm_res0)));
103 }
104
105 bool const satisfied_abs = norm_res < _abstols[global_component];
106 // Make sure that in the first iteration the relative residual tolerance
107 // is not satisfied.
108 bool const satisfied_rel =
110 checkRelativeTolerance(_reltols[global_component], norm_res,
111 _residual_norms_0[global_component]);
112 _satisfied = _satisfied && (satisfied_abs || satisfied_rel);
113 }
114}
115
117 const GlobalVector& minus_delta_x, GlobalVector const& x,
118 double damping_orig)
119{
120 if ((!_dof_table) || (!_mesh))
121 {
122 OGS_FATAL("D.o.f. table or mesh have not been set.");
123 }
124
126 double damping_final = 1;
127 for (unsigned global_component = 0;
128 global_component < _damping_alpha.size();
129 ++global_component)
130 {
131 auto const& ms = _dof_table->getMeshSubset(global_component);
132 assert(ms.getMeshID() == _mesh->getID());
133 DBUG("Non-negative damping for component: {:d} alpha: {:g}",
134 global_component, _damping_alpha[global_component]);
135 for (auto const& l :
137 {
138 auto index = _dof_table->getGlobalIndex(l, global_component);
139 damping_final = std::min(
140 damping_final,
141 damping_orig / std::max(1.0, (minus_delta_x.get(index) *
142 _damping_alpha[global_component] /
143 x.get(index))));
144 }
145 }
146 DBUG("Final damping value due to non-negative damping: {:g}",
147 damping_final);
148 return damping_final;
149}
150
152 const LocalToGlobalIndexMap& dof_table, MeshLib::Mesh const& mesh)
153{
154 _dof_table = &dof_table;
155 _mesh = &mesh;
156
158 static_cast<int>(_abstols.size()))
159 {
160 OGS_FATAL(
161 "The number of components in the DOF table and the number of "
162 "tolerances given do not match.");
163 }
164}
165
166std::unique_ptr<ConvergenceCriterionPerComponentResidual>
168 const BaseLib::ConfigTree& config)
169{
171 config.checkConfigParameter("type", "PerComponentResidual");
172
173 auto abstols =
175 config.getConfigParameterOptional<std::vector<double>>("abstols");
176 auto reltols =
178 config.getConfigParameterOptional<std::vector<double>>("reltols");
179 auto damping_alpha =
181 config.getConfigParameterOptional<std::vector<double>>("damping_alpha");
182 auto const norm_type_str =
184 config.getConfigParameter<std::string>("norm_type");
185
186 bool damping_alpha_switch = true;
187 if ((!abstols) && (!reltols))
188 {
189 OGS_FATAL(
190 "At least one of absolute or relative tolerance has to be "
191 "specified.");
192 }
193 if (!abstols)
194 {
195 abstols = std::vector<double>(reltols->size());
196 }
197 else if (!reltols)
198 {
199 reltols = std::vector<double>(abstols->size());
200 }
201 if (!damping_alpha)
202 {
203 damping_alpha = std::vector<double>(abstols->size(), 0.0);
204 damping_alpha_switch = false;
205 }
206
207 auto const norm_type = MathLib::convertStringToVecNormType(norm_type_str);
208
209 if (norm_type == MathLib::VecNormType::INVALID)
210 {
211 OGS_FATAL("Unknown vector norm type `{:s}'.", norm_type_str);
212 }
213
214 return std::make_unique<ConvergenceCriterionPerComponentResidual>(
215 std::move(*abstols), std::move(*reltols), std::move(*damping_alpha),
216 damping_alpha_switch, norm_type);
217}
218
219} // namespace NumLib
#define OGS_FATAL(...)
Definition Error.h:26
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:30
std::optional< T > getConfigParameterOptional(std::string const &param) const
T getConfigParameter(std::string const &param) const
void checkConfigParameter(std::string const &param, std::string_view const value) const
Global vector based on Eigen vector.
Definition EigenVector.h:25
double get(IndexType rowId) const
get entry
Definition EigenVector.h:58
std::size_t getID() const
Get id of the mesh.
Definition Mesh.h:123
ConvergenceCriterionPerComponentResidual(std::vector< double > &&absolute_tolerances, std::vector< double > &&relative_tolerances, std::vector< double > &&damping_alpha, bool daming_alpha_switch, const MathLib::VecNormType norm_type)
double getDampingFactor(GlobalVector const &minus_delta_x, GlobalVector const &x, double damping_orig) override
void setDOFTable(const LocalToGlobalIndexMap &dof_table, MeshLib::Mesh const &mesh) override
Sets the d.o.f. table used to extract data for a specific component.
void checkResidual(const GlobalVector &residual) override
Check if the residual satisfies the convergence criterion.
void checkDeltaX(const GlobalVector &minus_delta_x, GlobalVector const &x) override
const MathLib::VecNormType _norm_type
GlobalIndexType getGlobalIndex(MeshLib::Location const &l, int const variable_id, int const component_id) const
MeshLib::MeshSubset const & getMeshSubset(int const variable_id, int const component_id) const
void setLocalAccessibleVector(PETScVector const &x)
Definition LinAlg.cpp:27
VecNormType convertStringToVecNormType(const std::string &str)
convert string to VecNormType
auto meshLocations(Mesh const &mesh, MeshItemType const item_type)
Definition Mesh.h:238
bool checkRelativeTolerance(const double reltol, const double numerator, const double denominator)
std::unique_ptr< ConvergenceCriterionPerComponentResidual > createConvergenceCriterionPerComponentResidual(const BaseLib::ConfigTree &config)
double norm(GlobalVector const &x, unsigned const global_component, MathLib::VecNormType norm_type, LocalToGlobalIndexMap const &dof_table)