numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
embedded_solver.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 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 <limits>
24#include <optional>
25#include <type_traits> // IWYU pragma: keep
26
30#include "num_collect/constants/one.h" // IWYU pragma: keep
31#include "num_collect/constants/zero.h" // IWYU pragma: keep
40#include "num_collect/util/is_eigen_vector.h" // IWYU pragma: keep
41
42namespace num_collect::ode {
43
50template <concepts::embedded_formula Formula,
51 concepts::step_size_controller StepSizeController =
52 pi_step_size_controller<Formula>>
54 : public solver_base<embedded_solver<Formula, StepSizeController>,
55 Formula> {
56public:
59
61 using base_type =
63
64 using typename base_type::formula_type;
65 using typename base_type::problem_type;
66 using typename base_type::scalar_type;
67 using typename base_type::variable_type;
68
70 using step_size_controller_type = StepSizeController;
71
72 static_assert(std::is_same_v<formula_type,
73 typename step_size_controller_type::formula_type>);
74
76 static constexpr index_type lesser_order = formula_type::lesser_order;
77
78 using base_type::base_type;
81
84 time_ = time;
86 steps_ = 0;
87
89
90 if (step_size_) {
92 "Using user-specified initial step size {}.", *step_size_);
93 } else {
95 this->logger(), "Automatically calculate initial step size.");
97 this->problem(), time_, variable_,
98 step_size_controller_.limits(),
99 step_size_controller_.tolerances());
101 "Automatically selected initial step size {}.", *step_size_);
102 }
103 }
104
106 void step() {
108 "Step size is not set yet. You may forget to call init "
109 "function.");
110
112
113 formula().step_embedded(
115 constexpr index_type max_retry = 10000; // safe guard
116 for (index_type i = 0; i < max_retry; ++i) {
118 if (step_size_controller_.check_and_calc_next(
121 ++steps_;
123 return;
124 }
125 formula().step_embedded(
127 }
128 }
129
133 const {
134 iteration_logger.template append<index_type>(
135 "Steps", &this_type::steps);
136 iteration_logger.template append<scalar_type>("Time", &this_type::time);
137 iteration_logger.template append<scalar_type>(
138 "StepSize", &this_type::last_step_size);
139 iteration_logger.template append<scalar_type>(
140 "EstError", &this_type::error_norm);
141 }
142
144 [[nodiscard]] auto time() const -> scalar_type { return time_; }
145
147 [[nodiscard]] auto variable() const -> const variable_type& {
148 return variable_;
149 }
150
152 [[nodiscard]] auto step_size() const -> scalar_type {
153 if (!step_size_) {
154 return std::numeric_limits<scalar_type>::quiet_NaN();
155 }
156 return step_size_.value();
157 }
158
164 [[nodiscard]] auto last_step_size() const -> scalar_type {
165 return last_step_size_;
166 }
167
173 [[nodiscard]] auto error_norm() const -> scalar_type {
174 return norm(error_);
175 }
176
178 [[nodiscard]] auto steps() const -> index_type { return steps_; }
179
182 NUM_COLLECT_PRECONDITION(val > static_cast<scalar_type>(0),
183 this->logger(), "Step size must be a positive value.");
184 step_size_ = val;
185 return *this;
186 }
187
195 }
196
202 [[nodiscard]] auto step_size_controller() const
203 -> const step_size_controller_type& {
205 }
206
214 -> embedded_solver& {
215 step_size_controller_.tolerances(val);
216 if constexpr (requires(formula_type& formula,
218 formula.tolerances(val);
219 }) {
220 formula().tolerances(val);
221 }
222 return *this;
223 }
224
225private:
232 [[nodiscard]] static auto norm(const variable_type& var) -> scalar_type {
233 if constexpr (is_eigen_vector_v<variable_type>) {
234 return var.norm();
235 } else {
236 using std::abs;
237 return abs(var);
238 }
239 }
240
243
246
248 std::optional<scalar_type> step_size_{};
249
251 scalar_type last_step_size_{std::numeric_limits<scalar_type>::quiet_NaN()};
252
255
258
261
264};
265
266} // namespace num_collect::ode
auto logger() const noexcept -> const num_collect::logging::logger &
Access to the logger.
Class of solvers of ODEs using embedded formulas.
static auto norm(const variable_type &var) -> scalar_type
Get the norm of a variable.
std::optional< scalar_type > step_size_
Step size used in the next step.
auto step_size() const -> scalar_type
Get the step size.
static constexpr index_type lesser_order
Order of lesser coefficients of this formula.
Formula formula_type
Type of formula.
Definition solver_base.h:41
StepSizeController step_size_controller_type
Type of the controller of step sizes.
typename problem_type::variable_type variable_type
Type of variables.
Definition solver_base.h:47
void step()
Compute the variable of the next step.
auto problem() -> problem_type &
Get the problem.
step_size_controller_type step_size_controller_
Controller of step sizes.
auto time() const -> scalar_type
Get the current time.
auto variable() const -> const variable_type &
Get the current variable.
auto tolerances(const error_tolerances< variable_type > &val) -> embedded_solver &
Set the error tolerances.
variable_type prev_variable_
Previous variable.
auto step_size(scalar_type val) -> this_type &
Set the step size.
auto error_norm() const -> scalar_type
Get the estimate of error in the current variable.
auto last_step_size() const -> scalar_type
Get the step size used in the last step.
auto step_size_controller() const -> const step_size_controller_type &
Access the controller of step sizes.
auto step_size_controller() -> step_size_controller_type &
Access the controller of step sizes.
scalar_type last_step_size_
Step size used in the last step.
variable_type error_
Estimate of error.
typename problem_type::scalar_type scalar_type
Type of scalars.
Definition solver_base.h:50
index_type steps_
Number of steps.
void configure_iteration_logger(logging::iterations::iteration_logger< this_type > &iteration_logger) const
Configure an iteration logger.
auto formula() -> formula_type &
Get the formula.
auto steps() const -> index_type
Get the number of steps.
void init(scalar_type time, const variable_type &variable)
Initialize.
Class of error tolerances hairer1993.
Class to calculate initial step sizes hairer1993.
auto calculate(problem_type &problem, const scalar_type &initial_time, const variable_type &initial_variable, const step_size_limits< scalar_type > &limits, const error_tolerances< variable_type > &tolerances) const -> scalar_type
Calculate the initial step size.
Base class of solvers of ODEs.
Definition solver_base.h:38
Formula formula_type
Type of formula.
Definition solver_base.h:41
typename formula_type::problem_type problem_type
Type of problem.
Definition solver_base.h:44
typename problem_type::variable_type variable_type
Type of variables.
Definition solver_base.h:47
auto problem() -> problem_type &
Get the problem.
typename problem_type::scalar_type scalar_type
Type of scalars.
Definition solver_base.h:50
auto formula() -> formula_type &
Get the formula.
Definition of embedded_formula concept.
Definition of error_tolerances class.
Definition of exceptions.
Definition of index_type type.
Definition of initial_step_size_calculator class.
Definition of is_eigen_vector class.
Definition of iteration_logger class.
Definition of macros for logging.
#define NUM_COLLECT_LOG_TRACE(LOGGER,...)
Write a trace log.
#define NUM_COLLECT_LOG_DEBUG(LOGGER,...)
Write a debug log.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
Namespace of solvers of ordinary differential equations (ODE).
constexpr bool is_eigen_vector_v
Get whether a type is a Eigen's vector.
Definition of one.
Definition of pi_step_size_controller class.
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 solver_base class.
Definition of step_size_controller concept.
Definition of zero.