riccaticpp
Loading...
Searching...
No Matches
solver.hpp
Go to the documentation of this file.
1#ifndef INCLUDE_RICCATI_SOLVER_HPP
2#define INCLUDE_RICCATI_SOLVER_HPP
3
5#include <riccati/memory.hpp>
7#include <riccati/utils.hpp>
8#include <Eigen/Dense>
9#include <algorithm>
10#include <functional>
11#include <complex>
12#include <cmath>
13#include <vector>
14
15namespace pybind11 {
16class object;
17}
18
19namespace riccati {
20
21template <
22 typename SolverInfo, typename Scalar,
23 std::enable_if_t<!std::is_same<typename std::decay_t<SolverInfo>::funtype,
24 pybind11::object>::value>* = nullptr>
25inline auto gamma(SolverInfo&& info, const Scalar& x) {
26 return info.gamma_fun_(x);
27}
28
29template <
30 typename SolverInfo, typename Scalar,
31 std::enable_if_t<!std::is_same<typename std::decay_t<SolverInfo>::funtype,
32 pybind11::object>::value>* = nullptr>
33inline auto omega(SolverInfo&& info, const Scalar& x) {
34 return info.omega_fun_(x);
35}
36
37// OmegaFun / GammaFun take in a scalar and return a scalar
38template <typename OmegaFun, typename GammaFun, typename Scalar_,
39 typename Integral_,
40 typename Allocator = arena_allocator<Scalar_, arena_alloc>>
42 public:
43 using Scalar = Scalar_;
44 using Integral = Integral_;
45 using complex_t = std::complex<Scalar>;
49 using funtype = std::decay_t<OmegaFun>;
50 // Frequency function
51 OmegaFun omega_fun_;
52 // Friction function
53 GammaFun gamma_fun_;
54
55 Allocator alloc_;
56 // Number of nodes and diff matrices
58 // Differentiation matrices and Vectors of Chebyshev nodes
59 std::vector<std::tuple<Integral, matrixd_t, vectord_t>> chebyshev_;
60 // Lengths of node vectors
63
76
78 // Clenshaw-Curtis quadrature weights
80
91 // (Number of Chebyshev nodes - 1) to use for computing Riccati steps.
93 // (Number of Chebyshev nodes - 1) to use for estimating Riccati stepsizes.
95
96 private:
97 inline auto build_chebyshev(Integral nini, Integral n_nodes, Integral n,
98 Integral p) {
99 std::vector<std::tuple<Integral, matrixd_t, vectord_t>> res;
100 res.reserve(n_nodes + 1);
101 // Compute Chebyshev nodes and differentiation matrices
102 bool n_found = false;
103 bool p_found = false;
104 for (Integral i = 0; i <= n_nodes; ++i) {
105 auto it_v = nini * std::pow(2, i);
106 n_found = n_found || (it_v == n);
107 p_found = p_found || (it_v == p);
108 auto cheb_v = chebyshev<Scalar>(it_v);
109 res.emplace_back(it_v, std::move(cheb_v.first), std::move(cheb_v.second));
110 }
111 if (!n_found) {
112 auto cheb_v = chebyshev<Scalar>(n);
113 res.emplace_back(n, std::move(cheb_v.first), std::move(cheb_v.second));
114 }
115 if (!p_found && n != p) {
116 auto cheb_v = chebyshev<Scalar>(p);
117 res.emplace_back(p, std::move(cheb_v.first), std::move(cheb_v.second));
118 }
119 std::sort(res.begin(), res.end(),
120 [](auto& a, auto& b) { return std::get<0>(a) < std::get<0>(b); });
121 return res;
122 }
123
124 public:
142 template <typename OmegaFun_, typename GammaFun_, typename Allocator_>
143 SolverInfo(OmegaFun_&& omega_fun, GammaFun_&& gamma_fun, Allocator_&& alloc,
144 Integral nini, Integral nmax, Integral n, Integral p)
145 : omega_fun_(std::forward<OmegaFun_>(omega_fun)),
146 gamma_fun_(std::forward<GammaFun_>(gamma_fun)),
147 alloc_(std::forward<Allocator_>(alloc)),
148 n_nodes_(log2(nmax / nini) + 1),
149 chebyshev_(build_chebyshev(nini, n_nodes_, n, p)),
150 n_idx_(std::distance(
151 chebyshev_.begin(),
152 std::find_if(chebyshev_.begin(), chebyshev_.end(),
153 [n](auto& x) { return std::get<0>(x) == n; }))),
154 p_idx_(std::distance(
155 chebyshev_.begin(),
156 std::find_if(chebyshev_.begin(), chebyshev_.end(),
157 [p](auto& x) { return std::get<0>(x) == p; }))),
159 p, pi<Scalar>() / (2.0 * p),
160 pi<Scalar>() * (1.0 - (1.0 / (2.0 * p))))
161 .array())
162 .cos()
163 .matrix()),
164 L_(interpolate(this->xp(), xp_interp_, dummy_allocator{})),
167 nini_(nini),
168 nmax_(nmax),
169 n_(n),
170 p_(p) {}
171
172 template <typename OmegaFun_, typename GammaFun_>
173 SolverInfo(OmegaFun_&& omega_fun, GammaFun_&& gamma_fun, Integral nini,
174 Integral nmax, Integral n, Integral p)
175 : omega_fun_(std::forward<OmegaFun_>(omega_fun)),
176 gamma_fun_(std::forward<GammaFun_>(gamma_fun)),
177 alloc_(),
178 n_nodes_(log2(nmax / nini) + 1),
179 chebyshev_(build_chebyshev(nini, n_nodes_, n, p)),
180 n_idx_(std::distance(
181 chebyshev_.begin(),
182 std::find_if(chebyshev_.begin(), chebyshev_.end(),
183 [n](auto& x) { return std::get<0>(x) == n; }))),
184 p_idx_(std::distance(
185 chebyshev_.begin(),
186 std::find_if(chebyshev_.begin(), chebyshev_.end(),
187 [p](auto& x) { return std::get<0>(x) == p; }))),
189 p, pi<Scalar>() / (2.0 * p),
190 pi<Scalar>() * (1.0 - (1.0 / (2.0 * p))))
191 .array())
192 .cos()
193 .matrix()),
194 L_(interpolate(this->xp(), xp_interp_, dummy_allocator{})),
197 nini_(nini),
198 nmax_(nmax),
199 n_(n),
200 p_(p) {}
201
202 void mem_info() {
203#ifdef RICCATI_DEBUG
204 auto* mem = alloc_.alloc_;
205 std::cout << "mem info: " << std::endl;
206 std::cout << "blocks_ size: " << mem->blocks_.size() << std::endl;
207 std::cout << "sizes_ size: " << mem->sizes_.size() << std::endl;
208 std::cout << "cur_block_: " << mem->cur_block_ << std::endl;
209 std::cout << "cur_block_end_: " << mem->cur_block_end_ << std::endl;
210 std::cout << "next_loc_: " << mem->next_loc_ << std::endl;
211#endif
212 }
213
214 RICCATI_ALWAYS_INLINE const auto& Dn() const noexcept {
215 return std::get<1>(chebyshev_[n_idx_]);
216 }
217 RICCATI_ALWAYS_INLINE const auto& Dn(std::size_t idx) const noexcept {
218 return std::get<1>(chebyshev_[idx]);
219 }
220
227 RICCATI_ALWAYS_INLINE const auto& xn() const noexcept {
228 return std::get<2>(chebyshev_[n_idx_]);
229 }
230
237 RICCATI_ALWAYS_INLINE const auto& xp() const noexcept {
238 return std::get<2>(chebyshev_[p_idx_]);
239 }
240
241 RICCATI_ALWAYS_INLINE const auto& xp_interp() const noexcept {
242 return xp_interp_;
243 }
244
250 RICCATI_ALWAYS_INLINE const auto& L() const noexcept { return L_; }
251};
252
272template <typename Scalar, typename OmegaFun, typename Allocator,
273 typename GammaFun, typename Integral>
274inline auto make_solver(OmegaFun&& omega_fun, GammaFun&& gamma_fun,
275 Allocator&& alloc, Integral nini, Integral nmax,
276 Integral n, Integral p) {
277 return SolverInfo<std::decay_t<OmegaFun>, std::decay_t<GammaFun>, Scalar,
278 Integral, std::decay_t<Allocator>>(
279 std::forward<OmegaFun>(omega_fun), std::forward<GammaFun>(gamma_fun),
280 std::forward<Allocator>(alloc), nini, nmax, n, p);
281}
282
283} // namespace riccati
284
285#endif
matrixd_t integration_matrix_
Definition solver.hpp:81
std::vector< std::tuple< Integral, matrixd_t, vectord_t > > chebyshev_
Definition solver.hpp:59
RICCATI_ALWAYS_INLINE const auto & xp() const noexcept
Definition solver.hpp:237
SolverInfo(OmegaFun_ &&omega_fun, GammaFun_ &&gamma_fun, Allocator_ &&alloc, Integral nini, Integral nmax, Integral n, Integral p)
Construct a new Solver Info object.
Definition solver.hpp:143
vectord_t quadwts_
Definition solver.hpp:79
Allocator alloc_
Definition solver.hpp:55
SolverInfo(OmegaFun_ &&omega_fun, GammaFun_ &&gamma_fun, Integral nini, Integral nmax, Integral n, Integral p)
Definition solver.hpp:173
RICCATI_ALWAYS_INLINE const auto & Dn(std::size_t idx) const noexcept
Definition solver.hpp:217
GammaFun gamma_fun_
Definition solver.hpp:53
RICCATI_ALWAYS_INLINE const auto & Dn() const noexcept
Definition solver.hpp:214
vectord_t xp_interp_
Definition solver.hpp:75
matrix_t< Scalar > matrixd_t
Definition solver.hpp:46
Integral_ Integral
Definition solver.hpp:44
vector_t< Scalar > vectord_t
Definition solver.hpp:48
Integral n_nodes_
Definition solver.hpp:57
std::decay_t< OmegaFun > funtype
Definition solver.hpp:49
RICCATI_ALWAYS_INLINE const auto & xp_interp() const noexcept
Definition solver.hpp:241
RICCATI_ALWAYS_INLINE const auto & xn() const noexcept
Definition solver.hpp:227
vector_t< complex_t > vectorc_t
Definition solver.hpp:47
RICCATI_ALWAYS_INLINE const auto & L() const noexcept
Definition solver.hpp:250
std::complex< Scalar > complex_t
Definition solver.hpp:45
OmegaFun omega_fun_
Definition solver.hpp:51
#define RICCATI_ALWAYS_INLINE
Definition macros.hpp:57
auto array(T x)
Definition utils.hpp:201
RICCATI_ALWAYS_INLINE auto quad_weights(Integral n)
Calculates Clenshaw-Curtis quadrature weights.
RICCATI_ALWAYS_INLINE auto integration_matrix(Integral n)
Constructs a Chebyshev integration matrix.
Eigen::Matrix< Scalar, -1, -1 > matrix_t
Definition utils.hpp:48
auto make_solver(OmegaFun &&omega_fun, GammaFun &&gamma_fun, Allocator &&alloc, Integral nini, Integral nmax, Integral n, Integral p)
Construct a new Solver Info object.
Definition solver.hpp:274
auto gamma(SolverInfo &&info, const Scalar &x)
Definition solver.hpp:25
auto omega(SolverInfo &&info, const Scalar &x)
Definition solver.hpp:33
auto cos(T x)
Definition utils.hpp:171
Eigen::Matrix< Scalar, -1, 1 > vector_t
Definition utils.hpp:50
constexpr T pi()
Definition utils.hpp:63
RICCATI_ALWAYS_INLINE auto chebyshev(Integral n)
Computes the Chebyshev differentiation matrix and Chebyshev nodes.
auto matrix(T x)
Definition utils.hpp:211
RICCATI_ALWAYS_INLINE auto interpolate(Vec1 &&s, Vec2 &&t, Allocator &&alloc)
Creates an interpolation matrix from an array of source nodes to target nodes.