riccaticpp
Loading...
Searching...
No Matches
stepsize.hpp
Go to the documentation of this file.
1#ifndef INCLUDE_RICCATI_STEPSIZE_HPP
2#define INCLUDE_RICCATI_STEPSIZE_HPP
3
4#include <riccati/utils.hpp>
5
6namespace riccati {
26template <typename SolverInfo, typename FloatingPoint>
27inline FloatingPoint choose_nonosc_stepsize(SolverInfo&& info, FloatingPoint x0,
28 FloatingPoint h,
29 FloatingPoint epsilon_h) {
30 auto ws = omega(info, riccati::scale(info.xp(), x0, h));
31 if (ws.maxCoeff() > (1.0 + epsilon_h) / std::abs(h)) {
32 return choose_nonosc_stepsize(info, x0, static_cast<FloatingPoint>(h / 2.0),
33 epsilon_h);
34 } else {
35 return h;
36 }
37}
38
63template <typename SolverInfo, typename FloatingPoint>
64inline auto choose_osc_stepsize(SolverInfo&& info, FloatingPoint x0,
65 FloatingPoint h, FloatingPoint epsilon_h) {
66 auto t = eval(info.alloc_, riccati::scale(info.xp_interp(), x0, h));
67 auto s = eval(info.alloc_, riccati::scale(info.xp(), x0, h));
68 // TODO: Use a memory arena for these
69 auto ws = omega(info, s).eval();
70 auto gs = gamma(info, s).eval();
71 auto omega_analytic = eval(info.alloc_, omega(info, t));
72 auto omega_estimate = info.L() * ws;
73 auto gamma_analytic = eval(info.alloc_, gamma(info, t));
74 auto gamma_estimate = info.L() * gs;
75 FloatingPoint max_omega_err
76 = (((omega_estimate - omega_analytic).array() / omega_analytic.array())
77 .abs())
78 .maxCoeff();
79 FloatingPoint max_gamma_err
80 = (((gamma_estimate - gamma_analytic).array() / gamma_analytic.array())
81 .abs())
82 .maxCoeff();
83 FloatingPoint max_err = std::max(max_omega_err, max_gamma_err);
84 if (max_err <= epsilon_h) {
85 if (info.p_ != info.n_) {
86 auto xn_scaled = eval(info.alloc_, riccati::scale(info.xn(), x0, h));
87 ws = omega(info, xn_scaled);
88 gs = gamma(info, xn_scaled);
89 }
90 return std::make_tuple(h, ws, gs);
91 } else {
92 auto h_scaling = static_cast<FloatingPoint>(std::min(
93 0.7, 0.9 * std::pow(epsilon_h / max_err, (1.0 / (info.p_ - 1.0)))));
94 return choose_osc_stepsize(info, x0, h * h_scaling, epsilon_h);
95 }
96}
97
98} // namespace riccati
99#endif
FloatingPoint choose_nonosc_stepsize(SolverInfo &&info, FloatingPoint x0, FloatingPoint h, FloatingPoint epsilon_h)
Definition stepsize.hpp:27
auto eval(arena_allocator< T, arena_alloc > &arena, const Expr &expr) noexcept
auto gamma(SolverInfo &&info, const Scalar &x)
Definition solver.hpp:25
auto choose_osc_stepsize(SolverInfo &&info, FloatingPoint x0, FloatingPoint h, FloatingPoint epsilon_h)
Chooses an appropriate step size for the Riccati step based on the accuracy of Chebyshev interpolatio...
Definition stepsize.hpp:64
auto omega(SolverInfo &&info, const Scalar &x)
Definition solver.hpp:33
auto scale(Vector &&x, Scalar x0, Scalar h)
Scales and shifts a vector of Chebyshev nodes.
Definition utils.hpp:40