numerics 0.1.0
Loading...
Searching...
No Matches
ode.hpp
Go to the documentation of this file.
1/// @file ode/ode.hpp
2/// @brief ODE and symplectic integrators.
3/// @todo Add event detection, dense output, BDF methods, Rosenbrock/W-methods,
4/// and implicit Runge-Kutta schemes for stiff ODE systems.
5#pragma once
6
7#include "core/types.hpp"
8#include "core/vector.hpp"
9#include "ode/implicit.hpp"
10#include <functional>
11
12namespace num {
13
14using ODERhsFn = std::function<void(real t, const Vector& y, Vector& dydt)>;
15using AccelFn = std::function<void(const Vector& q, Vector& acc)>;
16using ObserverFn = std::function<void(real t, const Vector& y)>;
17using SympObserverFn = std::function<void(real t, const Vector& q, const Vector& v)>;
18
19struct Step {
20 real t = 0.0;
22};
23
25 real t = 0.0;
28};
29
30struct ODEResult {
32 real t = 0.0;
34 bool converged = false;
35};
36
43
44struct ODEParams {
45 real t0 = 0.0;
46 real tf = 1.0;
47 real h = 1e-3;
48 real rtol = 1e-6;
49 real atol = 1e-9;
50 idx max_steps = 1000000;
51};
52
53struct StepEnd {};
54
56 ODERhsFn f_ = nullptr;
57 Vector y_, dydt_;
58 real t_ = 0.0, t1_ = 0.0, h_ = 0.0;
59 idx steps_ = 0;
60 bool done_ = false;
61
62 void advance();
63
64public:
65 explicit EulerSteps(ODERhsFn f, Vector y0, ODEParams p);
66
67 struct iterator {
69 Step operator*() const { return {owner_->t_, owner_->y_}; }
71 owner_->advance();
72 return *this;
73 }
74 bool operator!=(StepEnd) const { return !owner_->done_; }
75 bool operator==(StepEnd) const { return owner_->done_; }
76 };
77
79 advance();
80 return {this};
81 }
82 StepEnd end() const { return {}; }
83 ODEResult run();
84};
85
86class RK4Steps {
87 ODERhsFn f_ = nullptr;
88 Vector y_, k1_, k2_, k3_, k4_, ytmp_;
89 real t_ = 0.0, t1_ = 0.0, h_ = 0.0;
90 idx steps_ = 0;
91 bool done_ = false;
92
93 void advance();
94
95public:
96 explicit RK4Steps(ODERhsFn f, Vector y0, ODEParams p);
97
98 struct iterator {
100 Step operator*() const { return {owner_->t_, owner_->y_}; }
102 owner_->advance();
103 return *this;
104 }
105 bool operator!=(StepEnd) const { return !owner_->done_; }
106 bool operator==(StepEnd) const { return owner_->done_; }
107 };
108
110 advance();
111 return {this};
112 }
113 StepEnd end() const { return {}; }
114 ODEResult run();
115};
116
118 ODERhsFn f_ = nullptr;
119 Vector y_, k1_, k2_, k3_, k4_, k5_, k6_, k7_, ytmp_, err_;
120 real t_ = 0.0, t1_ = 0.0, h_ = 0.0, rtol_ = 0.0, atol_ = 0.0;
121 idx steps_ = 0, max_steps_ = 0;
122 bool done_ = false, converged_ = true;
123
124 void advance();
125
126public:
127 explicit RK45Steps(ODERhsFn f, Vector y0, ODEParams p);
128
129 struct iterator {
131 Step operator*() const { return {owner_->t_, owner_->y_}; }
133 owner_->advance();
134 return *this;
135 }
136 bool operator!=(StepEnd) const { return !owner_->done_; }
137 bool operator==(StepEnd) const { return owner_->done_; }
138 };
139
141 advance();
142 return {this};
143 }
144 StepEnd end() const { return {}; }
145 ODEResult run();
146};
147
149 AccelFn accel_ = nullptr;
150 Vector q_, v_, a_cur_, a_next_;
151 real t_ = 0.0, t1_ = 0.0, h_ = 0.0;
152 idx steps_ = 0;
153 bool done_ = false;
154
155 void advance();
156
157public:
158 explicit VerletSteps(AccelFn accel, Vector q0, Vector v0, ODEParams p);
159
160 struct iterator {
162 SymplecticStep operator*() const { return {owner_->t_, owner_->q_, owner_->v_}; }
164 owner_->advance();
165 return *this;
166 }
167 bool operator!=(StepEnd) const { return !owner_->done_; }
168 bool operator==(StepEnd) const { return owner_->done_; }
169 };
170
172 advance();
173 return {this};
174 }
175 StepEnd end() const { return {}; }
177};
178
180 AccelFn accel_ = nullptr;
181 Vector q_, v_, acc_;
182 real t_ = 0.0, t1_ = 0.0, h_ = 0.0;
183 idx steps_ = 0;
184 bool done_ = false;
185
186 void advance();
187
188public:
189 explicit Yoshida4Steps(AccelFn accel, Vector q0, Vector v0, ODEParams p);
190
191 struct iterator {
193 SymplecticStep operator*() const { return {owner_->t_, owner_->q_, owner_->v_}; }
195 owner_->advance();
196 return *this;
197 }
198 bool operator!=(StepEnd) const { return !owner_->done_; }
199 bool operator==(StepEnd) const { return owner_->done_; }
200 };
201
203 advance();
204 return {this};
205 }
206 StepEnd end() const { return {}; }
208};
209
211 AccelFn accel_ = nullptr;
212 Vector q_, v_, a1_, a2_, a3_, a4_, qtmp_;
213 real t_ = 0.0, t1_ = 0.0, h_ = 0.0;
214 idx steps_ = 0;
215 bool done_ = false;
216
217 void advance();
218
219public:
220 explicit RK4_2ndSteps(AccelFn accel, Vector q0, Vector v0, ODEParams p);
221
222 struct iterator {
224 SymplecticStep operator*() const { return {owner_->t_, owner_->q_, owner_->v_}; }
226 owner_->advance();
227 return *this;
228 }
229 bool operator!=(StepEnd) const { return !owner_->done_; }
230 bool operator==(StepEnd) const { return owner_->done_; }
231 };
232
234 advance();
235 return {this};
236 }
237 StepEnd end() const { return {}; }
239};
240
241// Lazy-range factories
242
243EulerSteps euler(ODERhsFn f, Vector y0, ODEParams p = {});
244RK4Steps rk4(ODERhsFn f, Vector y0, ODEParams p = {});
245RK45Steps rk45(ODERhsFn f, Vector y0, ODEParams p = {});
246
247VerletSteps verlet(AccelFn accel, Vector q0, Vector v0, ODEParams p = {});
248Yoshida4Steps yoshida4(AccelFn accel, Vector q0, Vector v0, ODEParams p = {});
249RK4_2ndSteps rk4_2nd(AccelFn accel, Vector q0, Vector v0, ODEParams p = {});
250
251// High-level integrators return final state only.
252
253/// @brief Forward Euler, 1st-order, fixed step.
254ODEResult ode_euler(ODERhsFn f, Vector y0, ODEParams p = {}, ObserverFn obs = nullptr);
255
256/// @brief Classic 4th-order Runge-Kutta, fixed step.
257ODEResult ode_rk4(ODERhsFn f, Vector y0, ODEParams p = {}, ObserverFn obs = nullptr);
258
259/// @brief Adaptive Dormand-Prince RK45 with FSAL and PI step-size control.
260ODEResult ode_rk45(ODERhsFn f, Vector y0, ODEParams p = {}, ObserverFn obs = nullptr);
261
262/// @brief Velocity Verlet, 2nd-order symplectic, 1 force evaluation per step.
263SymplecticResult ode_verlet(AccelFn accel,
264 Vector q0,
265 Vector v0,
266 ODEParams p = {},
267 SympObserverFn obs = nullptr);
268
269/// @brief Yoshida 4th-order symplectic, 3 force evaluations per step.
270SymplecticResult ode_yoshida4(AccelFn accel,
271 Vector q0,
272 Vector v0,
273 ODEParams p = {},
274 SympObserverFn obs = nullptr);
275
276/// @brief RK4 for second-order systems q'' = accel(q), Nystrom form.
277/// @note Not symplectic. Prefer ode_verlet or ode_yoshida4 for long Hamiltonian
278/// runs.
279SymplecticResult ode_rk4_2nd(AccelFn accel,
280 Vector q0,
281 Vector v0,
282 ODEParams p = {},
283 SympObserverFn obs = nullptr);
284
285} // namespace num
StepEnd end() const
Definition ode.hpp:82
ODEResult run()
Definition ode.cpp:38
iterator begin()
Definition ode.hpp:78
ODEResult run()
Definition ode.cpp:223
iterator begin()
Definition ode.hpp:140
StepEnd end() const
Definition ode.hpp:144
iterator begin()
Definition ode.hpp:109
StepEnd end() const
Definition ode.hpp:113
ODEResult run()
Definition ode.cpp:86
iterator begin()
Definition ode.hpp:233
StepEnd end() const
Definition ode.hpp:237
SymplecticResult run()
Definition ode.cpp:366
SymplecticResult run()
Definition ode.cpp:265
StepEnd end() const
Definition ode.hpp:175
iterator begin()
Definition ode.hpp:171
SymplecticResult run()
Definition ode.cpp:319
iterator begin()
Definition ode.hpp:202
StepEnd end() const
Definition ode.hpp:206
Core type definitions.
Implicit time integration via a user-supplied LinearSolver.
EulerSteps euler(ODERhsFn f, Vector y0, ODEParams p={})
Definition ode.cpp:372
ODEResult ode_rk4(ODERhsFn f, Vector y0, ODEParams p={}, ObserverFn obs=nullptr)
Classic 4th-order Runge-Kutta, fixed step.
Definition ode.cpp:399
double real
Definition types.hpp:10
Yoshida4Steps yoshida4(AccelFn accel, Vector q0, Vector v0, ODEParams p={})
Definition ode.cpp:385
std::function< void(real t, const Vector &q, const Vector &v)> SympObserverFn
Definition ode.hpp:17
std::function< void(real t, const Vector &y, Vector &dydt)> ODERhsFn
Definition ode.hpp:14
SymplecticResult ode_verlet(AccelFn accel, Vector q0, Vector v0, ODEParams p={}, SympObserverFn obs=nullptr)
Velocity Verlet, 2nd-order symplectic, 1 force evaluation per step.
Definition ode.cpp:413
SymplecticResult ode_rk4_2nd(AccelFn accel, Vector q0, Vector v0, ODEParams p={}, SympObserverFn obs=nullptr)
RK4 for second-order systems q'' = accel(q), Nystrom form.
Definition ode.cpp:435
std::size_t idx
Definition types.hpp:11
std::function< void(real t, const Vector &y)> ObserverFn
Definition ode.hpp:16
constexpr real e
Definition math.hpp:44
RK4Steps rk4(ODERhsFn f, Vector y0, ODEParams p={})
Definition ode.cpp:375
BasicVector< real > Vector
Real-valued dense vector with full backend dispatch (CPU + GPU)
Definition vector.hpp:129
std::function< void(const Vector &q, Vector &acc)> AccelFn
Definition ode.hpp:15
RK4_2ndSteps rk4_2nd(AccelFn accel, Vector q0, Vector v0, ODEParams p={})
Definition ode.cpp:388
ODEResult ode_euler(ODERhsFn f, Vector y0, ODEParams p={}, ObserverFn obs=nullptr)
Forward Euler, 1st-order, fixed step.
Definition ode.cpp:392
SymplecticResult ode_yoshida4(AccelFn accel, Vector q0, Vector v0, ODEParams p={}, SympObserverFn obs=nullptr)
Yoshida 4th-order symplectic, 3 force evaluations per step.
Definition ode.cpp:424
RK45Steps rk45(ODERhsFn f, Vector y0, ODEParams p={})
Definition ode.cpp:378
VerletSteps verlet(AccelFn accel, Vector q0, Vector v0, ODEParams p={})
Definition ode.cpp:382
ODEResult ode_rk45(ODERhsFn f, Vector y0, ODEParams p={}, ObserverFn obs=nullptr)
Adaptive Dormand-Prince RK45 with FSAL and PI step-size control.
Definition ode.cpp:406
EulerSteps * owner_
Definition ode.hpp:68
bool operator==(StepEnd) const
Definition ode.hpp:75
bool operator!=(StepEnd) const
Definition ode.hpp:74
Step operator*() const
Definition ode.hpp:69
iterator & operator++()
Definition ode.hpp:70
real rtol
Definition ode.hpp:48
real atol
Definition ode.hpp:49
idx max_steps
Definition ode.hpp:50
Vector u
Definition ode.hpp:31
bool converged
Definition ode.hpp:34
Step operator*() const
Definition ode.hpp:131
RK45Steps * owner_
Definition ode.hpp:130
bool operator!=(StepEnd) const
Definition ode.hpp:136
iterator & operator++()
Definition ode.hpp:132
bool operator==(StepEnd) const
Definition ode.hpp:137
Step operator*() const
Definition ode.hpp:100
bool operator==(StepEnd) const
Definition ode.hpp:106
RK4Steps * owner_
Definition ode.hpp:99
bool operator!=(StepEnd) const
Definition ode.hpp:105
iterator & operator++()
Definition ode.hpp:101
bool operator!=(StepEnd) const
Definition ode.hpp:229
iterator & operator++()
Definition ode.hpp:225
RK4_2ndSteps * owner_
Definition ode.hpp:223
bool operator==(StepEnd) const
Definition ode.hpp:230
SymplecticStep operator*() const
Definition ode.hpp:224
real t
Definition ode.hpp:20
Vector u
Definition ode.hpp:21
bool operator!=(StepEnd) const
Definition ode.hpp:167
iterator & operator++()
Definition ode.hpp:163
VerletSteps * owner_
Definition ode.hpp:161
bool operator==(StepEnd) const
Definition ode.hpp:168
SymplecticStep operator*() const
Definition ode.hpp:162
bool operator!=(StepEnd) const
Definition ode.hpp:198
SymplecticStep operator*() const
Definition ode.hpp:193
bool operator==(StepEnd) const
Definition ode.hpp:199
iterator & operator++()
Definition ode.hpp:194
Yoshida4Steps * owner_
Definition ode.hpp:192
Dense vector storage and operations.