numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
error_tolerances.h
Go to the documentation of this file.
1/*
2 * Copyright 2022 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <cmath>
23#include <variant>
24
30
31namespace num_collect::ode {
32
33namespace impl {
34
40template <base::concepts::real_scalar Scalar>
41constexpr Scalar default_tol_rel_error = static_cast<Scalar>(1e-6);
42
48template <base::concepts::real_scalar Scalar>
49constexpr Scalar default_tol_abs_error = static_cast<Scalar>(1e-6);
50
51} // namespace impl
52
58template <typename Variable>
60
66template <base::concepts::real_scalar_dense_vector Variable>
67class error_tolerances<Variable> {
68public:
70 using variable_type = Variable;
71
73 using scalar_type = typename variable_type::Scalar;
74
79 : tol_rel_error_(impl::default_tol_rel_error<scalar_type>),
80 tol_abs_error_(impl::default_tol_abs_error<scalar_type>) {}
81
90 [[nodiscard]] auto check(const variable_type& variable,
91 const variable_type& error) const -> bool {
92 class evaluator {
93 public:
94 evaluator(const variable_type& variable, const variable_type& error)
95 : variable_(variable), error_(error) {}
96
97 [[nodiscard]] auto operator()(const scalar_type& tol_rel_error,
98 const scalar_type& tol_abs_error) const -> bool {
99 return (error_.array().abs() <=
100 (tol_rel_error * variable_.array().abs() + tol_abs_error))
101 .all();
102 }
103
104 [[nodiscard]] auto operator()(const variable_type& tol_rel_error,
105 const scalar_type& tol_abs_error) const -> bool {
106 return (error_.array().abs() <=
107 (tol_rel_error.array() * variable_.array().abs() +
108 tol_abs_error))
109 .all();
110 }
111
112 [[nodiscard]] auto operator()(const scalar_type& tol_rel_error,
113 const variable_type& tol_abs_error) const -> bool {
114 return (error_.array().abs() <=
115 (tol_rel_error * variable_.array().abs() +
116 tol_abs_error.array()))
117 .all();
118 }
119
120 [[nodiscard]] auto operator()(const variable_type& tol_rel_error,
121 const variable_type& tol_abs_error) const -> bool {
122 return (error_.array().abs() <=
123 (tol_rel_error.array() * variable_.array().abs() +
124 tol_abs_error.array()))
125 .all();
126 }
127
128 private:
129 const variable_type& variable_;
130 const variable_type& error_;
131 };
132
133 evaluator eval{variable, error};
134 return std::visit(eval, tol_rel_error_, tol_abs_error_);
135 }
136
144 [[nodiscard]] auto calc_norm(const variable_type& variable,
145 const variable_type& error) const -> scalar_type {
146 class evaluator {
147 public:
148 evaluator(const variable_type& variable, const variable_type& error)
149 : variable_(variable), error_(error) {}
150
151 [[nodiscard]] auto operator()(const scalar_type& tol_rel_error,
152 const scalar_type& tol_abs_error) const -> scalar_type {
153 using std::sqrt;
154 return sqrt((error_.array() /
155 (tol_rel_error * variable_.array().abs() +
156 tol_abs_error))
157 .abs2()
158 .sum() /
159 static_cast<scalar_type>(variable_.size()));
160 }
161
162 [[nodiscard]] auto operator()(const variable_type& tol_rel_error,
163 const scalar_type& tol_abs_error) const -> scalar_type {
164 using std::sqrt;
165 return sqrt(
166 (error_.array() /
167 (tol_rel_error.array() * variable_.array().abs() +
168 tol_abs_error))
169 .abs2()
170 .sum() /
171 static_cast<scalar_type>(variable_.size()));
172 }
173
174 [[nodiscard]] auto operator()(const scalar_type& tol_rel_error,
175 const variable_type& tol_abs_error) const -> scalar_type {
176 using std::sqrt;
177 return sqrt((error_.array() /
178 (tol_rel_error * variable_.array().abs() +
179 tol_abs_error.array()))
180 .abs2()
181 .sum() /
182 static_cast<scalar_type>(variable_.size()));
183 }
184
185 [[nodiscard]] auto operator()(const variable_type& tol_rel_error,
186 const variable_type& tol_abs_error) const -> scalar_type {
187 using std::sqrt;
188 return sqrt(
189 (error_.array() /
190 (tol_rel_error.array() * variable_.array().abs() +
191 tol_abs_error.array()))
192 .abs2()
193 .sum() /
194 static_cast<scalar_type>(variable_.size()));
195 }
196
197 private:
198 const variable_type& variable_;
199 const variable_type& error_;
200 };
201
202 evaluator eval{variable, error};
203 return std::visit(eval, tol_rel_error_, tol_abs_error_);
204 }
205
213 NUM_COLLECT_PRECONDITION(val >= static_cast<scalar_type>(0),
214 "Tolerance of relative error must be a non-negative value.");
215 tol_rel_error_ = val;
216 return *this;
217 }
218
227 (val.array() >= static_cast<scalar_type>(0)).all(),
228 "Tolerance of relative error must be non-negative values.");
229 tol_rel_error_ = val;
230 return *this;
231 }
232
240 NUM_COLLECT_PRECONDITION(val >= static_cast<scalar_type>(0),
241 "Tolerance of absolute error must be a non-negative value.");
242 tol_abs_error_ = val;
243 return *this;
244 }
245
254 (val.array() >= static_cast<scalar_type>(0)).all(),
255 "Tolerance of absolute error must be non-negative values.");
256 tol_abs_error_ = val;
257 return *this;
258 }
259
260private:
262 using variant_type = std::variant<scalar_type, variable_type>;
263
266
269};
270
276template <base::concepts::real_scalar Variable>
277class error_tolerances<Variable> {
278public:
280 using variable_type = Variable;
281
284
289 : tol_rel_error_(impl::default_tol_rel_error<scalar_type>),
290 tol_abs_error_(impl::default_tol_abs_error<scalar_type>) {}
291
300 [[nodiscard]] auto check(const variable_type& variable,
301 const variable_type& error) const -> bool {
302 using std::abs;
303 return abs(error) <= tol_rel_error_ * abs(variable) + tol_abs_error_;
304 }
305
313 [[nodiscard]] auto calc_norm(const variable_type& variable,
314 const variable_type& error) const -> scalar_type {
315 using std::abs;
316 return abs(error / (tol_rel_error_ * abs(variable) + tol_abs_error_));
317 }
318
326 NUM_COLLECT_PRECONDITION(val >= static_cast<scalar_type>(0),
327 "Tolerance of relative error must be a non-negative value.");
328 tol_rel_error_ = val;
329 return *this;
330 }
331
339 NUM_COLLECT_PRECONDITION(val >= static_cast<scalar_type>(0),
340 "Tolerance of absolute error must be a non-negative value.");
341 tol_abs_error_ = val;
342 return *this;
343 }
344
345private:
348
351};
352
353} // namespace num_collect::ode
variant_type tol_abs_error_
Tolerance of absolute error.
variable_type tol_rel_error_
Tolerance of relative error.
auto tol_abs_error(const variable_type &val) -> error_tolerances &
Set the tolerance of absolute error.
variant_type tol_rel_error_
Tolerance of relative error.
auto check(const variable_type &variable, const variable_type &error) const -> bool
Check whether the given error satisfies tolerances.
std::variant< scalar_type, variable_type > variant_type
Type of variant used for tolerances.
auto calc_norm(const variable_type &variable, const variable_type &error) const -> scalar_type
Calculate the norm of the error determined by tolerances.
auto tol_rel_error(const scalar_type &val) -> error_tolerances &
Set the tolerance of relative error.
auto tol_abs_error(const scalar_type &val) -> error_tolerances &
Set the tolerance of absolute error.
typename variable_type::Scalar scalar_type
Type of scalars.
variable_type tol_abs_error_
Tolerance of absolute error.
auto tol_rel_error(const variable_type &val) -> error_tolerances &
Set the tolerance of relative error.
Class of error tolerances hairer1993.
Definition of exceptions.
Definition of macros for logging.
constexpr Scalar default_tol_rel_error
Default tolerance of relative errors.
constexpr Scalar default_tol_abs_error
Default tolerance of absolute errors.
Namespace of solvers of ordinary differential equations (ODE).
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of real_scalar concept.
Definition of real_scalar_dense_vector concept.