OGS
ConvergenceCriterionResidual.cpp
Go to the documentation of this file.
1 
12 
13 #include "BaseLib/ConfigTree.h"
14 #include "BaseLib/Logging.h"
15 #include "MathLib/LinAlg/LinAlg.h"
16 
17 namespace NumLib
18 {
20  std::optional<double>&& absolute_tolerance,
21  std::optional<double>&& relative_tolerance,
22  const MathLib::VecNormType norm_type)
23  : ConvergenceCriterion(norm_type),
24  _abstol(std::move(absolute_tolerance)),
25  _reltol(std::move(relative_tolerance))
26 {
27  if ((!_abstol) && (!_reltol))
28  {
29  OGS_FATAL(
30  "At least one of absolute or relative tolerance has to be "
31  "specified.");
32  }
33 }
34 
36  const GlobalVector& minus_delta_x, GlobalVector const& x)
37 {
38  auto error_dx = MathLib::LinAlg::norm(minus_delta_x, _norm_type);
39  auto norm_x = MathLib::LinAlg::norm(x, _norm_type);
40 
41  INFO("Convergence criterion: |dx|={:.4e}, |x|={:.4e}, |dx|/|x|={:.4e}",
42  error_dx, norm_x,
43  (norm_x == 0. ? std::numeric_limits<double>::quiet_NaN()
44  : (error_dx / norm_x)));
45 }
46 
48 {
49  auto norm_res = MathLib::LinAlg::norm(residual, _norm_type);
50 
52  {
53  INFO("Convergence criterion: |r0|={:.4e}", norm_res);
54  _residual_norm_0 = norm_res;
55  }
56  else
57  {
59  (_residual_norm_0 < std::numeric_limits<double>::epsilon())
60  ? norm_res
62  if (_residual_norm_0 < std::numeric_limits<double>::epsilon())
63  {
64  INFO("Convergence criterion: |r|={:.4e} |r0|={:.4e}", norm_res,
66  }
67  else
68  {
69  INFO(
70  "Convergence criterion: |r|={:.4e} |r0|={:.4e} |r|/|r0|={:.4e}",
71  norm_res, _residual_norm_0,
72  (_residual_norm_0 == 0.
73  ? std::numeric_limits<double>::quiet_NaN()
74  : (norm_res / _residual_norm_0)));
75  }
76  }
77 
78  bool satisfied_abs = false;
79  bool satisfied_rel = false;
80 
81  if (_abstol)
82  {
83  satisfied_abs = norm_res < *_abstol;
84  }
86  {
87  satisfied_rel =
89  }
90 
91  _satisfied = _satisfied && (satisfied_abs || satisfied_rel);
92 }
93 
94 std::unique_ptr<ConvergenceCriterionResidual>
96 {
98  config.checkConfigParameter("type", "Residual");
99 
101  auto abstol = config.getConfigParameterOptional<double>("abstol");
103  auto reltol = config.getConfigParameterOptional<double>("reltol");
104  auto const norm_type_str =
106  config.getConfigParameter<std::string>("norm_type");
107  auto const norm_type = MathLib::convertStringToVecNormType(norm_type_str);
108 
109  if (norm_type == MathLib::VecNormType::INVALID)
110  {
111  OGS_FATAL("Unknown vector norm type `{:s}'.", norm_type_str);
112  }
113 
114  return std::make_unique<ConvergenceCriterionResidual>(
115  std::move(abstol), std::move(reltol), norm_type);
116 }
117 
118 } // namespace NumLib
#define OGS_FATAL(...)
Definition: Error.h:26
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void checkConfigParameter(std::string const &param, T const &value) const
std::optional< T > getConfigParameterOptional(std::string const &param) const
T getConfigParameter(std::string const &param) const
Global vector based on Eigen vector.
Definition: EigenVector.h:26
void checkResidual(const GlobalVector &residual) override
Check if the residual satisfies the convergence criterion.
ConvergenceCriterionResidual(std::optional< double > &&absolute_tolerance, std::optional< double > &&relative_tolerance, const MathLib::VecNormType norm_type)
void checkDeltaX(const GlobalVector &minus_delta_x, GlobalVector const &x) override
const MathLib::VecNormType _norm_type
double norm(MatrixOrVector const &x, MathLib::VecNormType type)
Definition: LinAlg.h:88
VecNormType
Norm type. Not declared as class type in order to use the members as integers.
Definition: LinAlgEnums.h:22
VecNormType convertStringToVecNormType(const std::string &str)
convert string to VecNormType
Definition: LinAlgEnums.cpp:32
bool checkRelativeTolerance(const double reltol, const double numerator, const double denominator)
std::unique_ptr< ConvergenceCriterionResidual > createConvergenceCriterionResidual(const BaseLib::ConfigTree &config)