OGS
ConvergenceCriterionPerComponentDeltaX.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <limits>
7
9#include "BaseLib/Logging.h"
11#include "MeshLib/MeshSubset.h"
14
15namespace NumLib
16{
18 std::vector<double>&& absolute_tolerances,
19 std::vector<double>&& relative_tolerances,
20 std::vector<double>&& damping_alpha,
21 bool damping_alpha_switch,
22 const MathLib::VecNormType norm_type)
24 _abstols(std::move(absolute_tolerances)),
25 _reltols(std::move(relative_tolerances)),
26 _damping_alpha(std::move(damping_alpha)),
27 _damping_alpha_switch(damping_alpha_switch)
28{
29 if (_abstols.size() != _reltols.size())
30 {
31 OGS_FATAL(
32 "The number of absolute and relative tolerances given must be the "
33 "same.");
34 }
35
36 if (_abstols.empty())
37 {
38 OGS_FATAL("The given tolerances vector is empty.");
39 }
40}
41
43 const GlobalVector& minus_delta_x, GlobalVector const& x)
44{
45 if (!_dof_table)
46 {
47 OGS_FATAL("D.o.f. table has not been set.");
48 }
49
50 for (unsigned global_component = 0; global_component < _abstols.size();
51 ++global_component)
52 {
53 // TODO short cut if tol <= 0.0
54 auto error_dx =
55 norm(minus_delta_x, global_component, _norm_type, *_dof_table);
56 auto norm_x = norm(x, global_component, _norm_type, *_dof_table);
57
58 INFO(
59 "Convergence criterion, component {:d}: |dx|={:.4e}, |x|={:.4e}, "
60 "|dx|/|x|={:.4e}",
61 global_component, error_dx, norm_x,
62 (norm_x == 0. ? std::numeric_limits<double>::quiet_NaN()
63 : (error_dx / norm_x)));
64
65 bool const satisfied_abs = error_dx < _abstols[global_component];
66 bool const satisfied_rel = checkRelativeTolerance(
67 _reltols[global_component], error_dx, norm_x);
68
69 _satisfied = _satisfied && (satisfied_abs || satisfied_rel);
70 }
71}
72
74 const GlobalVector& minus_delta_x, GlobalVector const& x,
75 double damping_orig)
76{
77 if (!_dof_table)
78 {
79 OGS_FATAL("D.o.f. table has not been set.");
80 }
81
83 double damping_final = 1;
84 for (unsigned global_component = 0;
85 global_component < _damping_alpha.size();
86 ++global_component)
87 {
88 auto const& ms = _dof_table->getMeshSubset(global_component);
89 assert(ms.getMeshID() == _mesh->getID());
90 DBUG("Non-negative damping for component: {:d} alpha: {:g}",
91 global_component, _damping_alpha[global_component]);
92 for (auto const& l :
94 {
95 auto index = _dof_table->getGlobalIndex(l, global_component);
96 damping_final = std::min(
97 damping_final,
98 damping_orig / std::max(1.0, (minus_delta_x.get(index) *
99 _damping_alpha[global_component] /
100 x.get(index))));
101 }
102 }
103 DBUG("Final damping value due to non-negative damping: {:g}",
104 damping_final);
105 return damping_final;
106}
107
109 const LocalToGlobalIndexMap& dof_table, MeshLib::Mesh const& mesh)
110{
111 _dof_table = &dof_table;
112 _mesh = &mesh;
113
114 if (_dof_table->getNumberOfGlobalComponents() !=
115 static_cast<int>(_abstols.size()))
116 {
117 OGS_FATAL(
118 "The number of components in the DOF table ({:d}) and the number "
119 "of tolerances given ({:d}) do not match.",
120 _dof_table->getNumberOfGlobalComponents(),
121 static_cast<int>(_abstols.size()));
122 }
123}
124
125std::unique_ptr<ConvergenceCriterionPerComponentDeltaX>
127{
129 config.checkConfigParameter("type", "PerComponentDeltaX");
130
131 auto abstols =
133 config.getConfigParameterOptional<std::vector<double>>("abstols");
134 auto reltols =
136 config.getConfigParameterOptional<std::vector<double>>("reltols");
137 auto damping_alpha =
139 config.getConfigParameterOptional<std::vector<double>>("damping_alpha");
140 auto const norm_type_str =
142 config.getConfigParameter<std::string>("norm_type");
143
144 bool damping_alpha_switch = true;
145 if ((!abstols) && (!reltols))
146 {
147 OGS_FATAL(
148 "At least one of absolute or relative tolerance has to be "
149 "specified.");
150 }
151 if (!abstols)
152 {
153 abstols = std::vector<double>(reltols->size());
154 }
155 else if (!reltols)
156 {
157 reltols = std::vector<double>(abstols->size());
158 }
159 if (!damping_alpha)
160 {
161 damping_alpha = std::vector<double>(abstols->size(), 0.0);
162 damping_alpha_switch = false;
163 }
164
165 auto const norm_type = MathLib::convertStringToVecNormType(norm_type_str);
166
167 if (norm_type == MathLib::VecNormType::INVALID)
168 {
169 OGS_FATAL("Unknown vector norm type `{:s}'.", norm_type_str);
170 }
171
172 return std::make_unique<ConvergenceCriterionPerComponentDeltaX>(
173 std::move(*abstols), std::move(*reltols), std::move(*damping_alpha),
174 damping_alpha_switch, norm_type);
175}
176
177} // namespace NumLib
#define OGS_FATAL(...)
Definition Error.h:19
MathLib::EigenVector GlobalVector
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
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
double get(IndexType rowId) const
get entry
Definition EigenVector.h:52
ConvergenceCriterionPerComponentDeltaX(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(const GlobalVector &minus_delta_x, GlobalVector const &x, double damping_orig) override
void checkDeltaX(const GlobalVector &minus_delta_x, GlobalVector const &x) 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.
ConvergenceCriterionPerComponent(const MathLib::VecNormType norm_type)
const MathLib::VecNormType _norm_type
void setLocalAccessibleVector(PETScVector const &x)
Definition LinAlg.cpp:20
VecNormType convertStringToVecNormType(const std::string &str)
convert string to VecNormType
auto meshLocations(Mesh const &mesh, MeshItemType const item_type)
Definition Mesh.h:227
bool checkRelativeTolerance(const double reltol, const double numerator, const double denominator)
std::unique_ptr< ConvergenceCriterionPerComponentDeltaX > createConvergenceCriterionPerComponentDeltaX(const BaseLib::ConfigTree &config)
double norm(GlobalVector const &x, unsigned const global_component, MathLib::VecNormType norm_type, LocalToGlobalIndexMap const &dof_table)