OGS 6.1.0-1721-g6382411ad
ConvergenceCriterionPerComponentResidual.cpp
Go to the documentation of this file.
1 
11 #include <logog/include/logog.hpp>
12 
13 #include "BaseLib/ConfigTree.h"
16 
17 namespace NumLib
18 {
21  std::vector<double>&& absolute_tolerances,
22  std::vector<double>&& relative_tolerances,
23  const MathLib::VecNormType norm_type)
25  _abstols(std::move(absolute_tolerances)),
26  _reltols(std::move(relative_tolerances)),
27  _residual_norms_0(_abstols.size())
28 {
29  if (_abstols.size() != _reltols.size())
30  OGS_FATAL(
31  "The number of absolute and relative tolerances given must be the "
32  "same.");
33 
34  if (_abstols.empty())
35  OGS_FATAL("The given tolerances vector is empty.");
36 }
37 
38 
40  const GlobalVector& minus_delta_x, GlobalVector const& x)
41 {
42  if ((!_dof_table) || (!_mesh))
43  OGS_FATAL("D.o.f. table or mesh have not been set.");
44 
45  for (unsigned global_component = 0; global_component < _abstols.size();
46  ++global_component)
47  {
48  // TODO short cut if tol <= 0.0
49  auto error_dx = norm(minus_delta_x, global_component, _norm_type,
50  *_dof_table, *_mesh);
51  auto norm_x =
52  norm(x, global_component, _norm_type, *_dof_table, *_mesh);
53 
54  INFO(
55  "Convergence criterion, component %u: |dx|=%.4e, |x|=%.4e, "
56  "|dx|/|x|=%.4e",
57  error_dx, global_component, norm_x,
58  (norm_x == 0. ? std::numeric_limits<double>::quiet_NaN()
59  : (error_dx / norm_x)));
60  }
61 }
62 
63 
65  const GlobalVector& residual)
66 {
67  if ((!_dof_table) || (!_mesh))
68  OGS_FATAL("D.o.f. table or mesh have not been set.");
69 
70  bool satisfied_abs = true;
71  // Make sure that in the first iteration the relative residual tolerance is
72  // not satisfied.
73  bool satisfied_rel = !_is_first_iteration;
74 
75  for (unsigned global_component = 0; global_component < _abstols.size();
76  ++global_component)
77  {
78  // TODO short cut if tol <= 0.0
79  auto norm_res = norm(residual, global_component, _norm_type,
80  *_dof_table, *_mesh);
81 
82  if (_is_first_iteration) {
83  INFO("Convergence criterion, component %u: |r0|=%.4e", global_component, norm_res);
84  _residual_norms_0[global_component] = norm_res;
85  } else {
86  auto const norm_res0 = _residual_norms_0[global_component];
87  INFO(
88  "Convergence criterion, component %u: |r|=%.4e, |r0|=%.4e, "
89  "|r|/|r0|=%.4e",
90  global_component, norm_res, norm_res0,
91  (norm_res0 == 0. ? std::numeric_limits<double>::quiet_NaN()
92  : (norm_res / norm_res0)));
93  }
94 
95  satisfied_abs = satisfied_abs && norm_res < _abstols[global_component];
96  satisfied_rel =
97  satisfied_rel &&
98  checkRelativeTolerance(_reltols[global_component], norm_res,
99  _residual_norms_0[global_component]);
100  }
101 
102  _satisfied = _satisfied && (satisfied_abs || satisfied_rel);
103 }
104 
106  const LocalToGlobalIndexMap& dof_table, MeshLib::Mesh const& mesh)
107 {
108  _dof_table = &dof_table;
109  _mesh = &mesh;
110 
112  static_cast<int>(_abstols.size()))
113  OGS_FATAL(
114  "The number of components in the DOF table and the number of "
115  "tolerances given do not match.");
116 }
117 
118 std::unique_ptr<ConvergenceCriterionPerComponentResidual>
120  const BaseLib::ConfigTree& config)
121 {
123  config.checkConfigParameter("type", "PerComponentResidual");
124 
125  auto abstols =
127  config.getConfigParameterOptional<std::vector<double>>("abstols");
128  auto reltols =
130  config.getConfigParameterOptional<std::vector<double>>("reltols");
131  auto const norm_type_str =
133  config.getConfigParameter<std::string>("norm_type");
134 
135  if ((!abstols) && (!reltols))
136  OGS_FATAL(
137  "At least one of absolute or relative tolerance has to be "
138  "specified.");
139  if (!abstols) {
140  abstols = std::vector<double>(reltols->size());
141  } else if (!reltols) {
142  reltols = std::vector<double>(abstols->size());
143  }
144 
145  auto const norm_type = MathLib::convertStringToVecNormType(norm_type_str);
146 
147  if (norm_type == MathLib::VecNormType::INVALID)
148  OGS_FATAL("Unknown vector norm type `%s'.", norm_type_str.c_str());
149 
150  return std::make_unique<ConvergenceCriterionPerComponentResidual>(
151  std::move(*abstols), std::move(*reltols), norm_type);
152 }
153 
154 } // NumLib
std::unique_ptr< ConvergenceCriterionPerComponentResidual > createConvergenceCriterionPerComponentResidual(const BaseLib::ConfigTree &config)
VecNormType
Norm type. Not declared as class type in order to use the members as integers.
Definition: LinAlgEnums.h:20
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.
ConvergenceCriterionPerComponentResidual(std::vector< double > &&absolute_tolerances, std::vector< double > &&relative_tolerances, const MathLib::VecNormType norm_type)
T getConfigParameter(std::string const &param) const
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
void checkConfigParameter(std::string const &param, T const &value) const
bool checkRelativeTolerance(const double reltol, const double numerator, const double denominator)
boost::optional< T > getConfigParameterOptional(std::string const &param) const
#define OGS_FATAL(fmt,...)
Definition: Error.h:71
const MathLib::VecNormType _norm_type
double norm(GlobalVector const &x, unsigned const global_component, MathLib::VecNormType norm_type, LocalToGlobalIndexMap const &dof_table, MeshLib::Mesh const &mesh)
VecNormType convertStringToVecNormType(const std::string &str)
convert string to VecNormType
Definition: LinAlgEnums.cpp:28