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