OGS 6.2.1-97-g73d1aeda3
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  {
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 
42 
44  const GlobalVector& minus_delta_x, GlobalVector const& x)
45 {
46  if ((!_dof_table) || (!_mesh))
47  {
48  OGS_FATAL("D.o.f. table or mesh have not been set.");
49  }
50 
51  for (unsigned global_component = 0; global_component < _abstols.size();
52  ++global_component)
53  {
54  // TODO short cut if tol <= 0.0
55  auto error_dx = norm(minus_delta_x, global_component, _norm_type,
56  *_dof_table, *_mesh);
57  auto norm_x =
58  norm(x, global_component, _norm_type, *_dof_table, *_mesh);
59 
60  INFO(
61  "Convergence criterion, component %u: |dx|=%.4e, |x|=%.4e, "
62  "|dx|/|x|=%.4e",
63  error_dx, global_component, norm_x,
64  (norm_x == 0. ? std::numeric_limits<double>::quiet_NaN()
65  : (error_dx / norm_x)));
66  }
67 }
68 
69 
71  const GlobalVector& residual)
72 {
73  if ((!_dof_table) || (!_mesh))
74  {
75  OGS_FATAL("D.o.f. table or mesh have not been set.");
76  }
77 
78  bool satisfied_abs = true;
79  // Make sure that in the first iteration the relative residual tolerance is
80  // not satisfied.
81  bool satisfied_rel = !_is_first_iteration;
82 
83  for (unsigned global_component = 0; global_component < _abstols.size();
84  ++global_component)
85  {
86  // TODO short cut if tol <= 0.0
87  auto norm_res = norm(residual, global_component, _norm_type,
88  *_dof_table, *_mesh);
89 
90  if (_is_first_iteration) {
91  INFO("Convergence criterion, component %u: |r0|=%.4e", global_component, norm_res);
92  _residual_norms_0[global_component] = norm_res;
93  } else {
94  auto const norm_res0 = _residual_norms_0[global_component];
95  INFO(
96  "Convergence criterion, component %u: |r|=%.4e, |r0|=%.4e, "
97  "|r|/|r0|=%.4e",
98  global_component, norm_res, norm_res0,
99  (norm_res0 == 0. ? std::numeric_limits<double>::quiet_NaN()
100  : (norm_res / norm_res0)));
101  }
102 
103  satisfied_abs = satisfied_abs && norm_res < _abstols[global_component];
104  satisfied_rel =
105  satisfied_rel &&
106  checkRelativeTolerance(_reltols[global_component], norm_res,
107  _residual_norms_0[global_component]);
108  }
109 
110  _satisfied = _satisfied && (satisfied_abs || satisfied_rel);
111 }
112 
114  const LocalToGlobalIndexMap& dof_table, MeshLib::Mesh const& mesh)
115 {
116  _dof_table = &dof_table;
117  _mesh = &mesh;
118 
120  static_cast<int>(_abstols.size()))
121  {
122  OGS_FATAL(
123  "The number of components in the DOF table and the number of "
124  "tolerances given do not match.");
125  }
126 }
127 
128 std::unique_ptr<ConvergenceCriterionPerComponentResidual>
130  const BaseLib::ConfigTree& config)
131 {
133  config.checkConfigParameter("type", "PerComponentResidual");
134 
135  auto abstols =
137  config.getConfigParameterOptional<std::vector<double>>("abstols");
138  auto reltols =
140  config.getConfigParameterOptional<std::vector<double>>("reltols");
141  auto const norm_type_str =
143  config.getConfigParameter<std::string>("norm_type");
144 
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  abstols = std::vector<double>(reltols->size());
153  } else if (!reltols) {
154  reltols = std::vector<double>(abstols->size());
155  }
156 
157  auto const norm_type = MathLib::convertStringToVecNormType(norm_type_str);
158 
159  if (norm_type == MathLib::VecNormType::INVALID)
160  {
161  OGS_FATAL("Unknown vector norm type `%s'.", norm_type_str.c_str());
162  }
163 
164  return std::make_unique<ConvergenceCriterionPerComponentResidual>(
165  std::move(*abstols), std::move(*reltols), norm_type);
166 }
167 
168 } // namespace 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:63
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