numerics
Loading...
Searching...
No Matches
ode.hpp
Go to the documentation of this file.
1/// @file ode/ode.hpp
2/// @brief ODE time integrators: Euler, RK4, adaptive RK45 (Dormand-Prince),
3/// and symplectic Velocity Verlet / Yoshida-4 for Hamiltonian systems.
4///
5/// General ODE solvers (for dy/dt = f(t, y)):
6/// ode_euler -- forward Euler, O(h)
7/// ode_rk4 -- classic 4th-order Runge-Kutta, O(h⁴)
8/// ode_rk45 -- adaptive Dormand-Prince with PI step control, O(h⁵)
9///
10/// Symplectic integrators (for separable H(q,p) = T(p) + V(q)):
11/// ode_verlet -- velocity Verlet, 2nd-order symplectic, 1 force eval/step
12/// ode_yoshida4 -- Yoshida (1990) 4th-order symplectic, 3 force evals/step
13///
14/// All integrators accept an optional on_step callback invoked after each
15/// accepted step, enabling trajectory recording and event detection without
16/// storing the full history in the integrator itself.
17#pragma once
18
19#include "core/types.hpp"
20#include "core/vector.hpp"
21#include <functional>
22
23namespace num {
24
25// ── Callable types ────────────────────────────────────────────────────────────
26
27/// Right-hand side callable: fills dydt = f(t, y) in-place.
28using ODERhsFn = std::function<void(real t, const Vector& y, Vector& dydt)>;
29
30/// Called after each accepted step. Use to record trajectories or detect events.
31/// @param t Time at end of step
32/// @param y State at end of step
33using StepCallback = std::function<void(real t, const Vector& y)>;
34
35/// Acceleration function for symplectic integrators.
36/// Fills acc = −∇V(q) / m (generalised force per unit mass) from positions q.
37using AccelFn = std::function<void(const Vector& q, Vector& acc)>;
38
39/// Per-step callback for symplectic integrators.
40/// @param t Time at end of step
41/// @param q Generalised positions
42/// @param v Generalised velocities
43using SymplecticCallback = std::function<void(real t, const Vector& q, const Vector& v)>;
44
45// ── Result types ──────────────────────────────────────────────────────────────
46
47/// Result returned by general ODE integrators.
48struct ODEResult {
49 Vector y; ///< Final state vector
50 real t; ///< Final time
51 idx steps; ///< Number of (accepted) steps taken
52 bool converged; ///< Always true for fixed-step; false if rk45 hit max_steps
53};
54
55/// Result returned by symplectic integrators.
57 Vector q; ///< Final generalised positions
58 Vector v; ///< Final generalised velocities
59 real t; ///< Final time
60 idx steps; ///< Number of steps taken
61};
62
63// ── General ODE solvers ───────────────────────────────────────────────────────
64
65/// Forward Euler (1st order, fixed step):
66/// y_{n+1} = y_n + h · f(t_n, y_n)
68 StepCallback on_step = nullptr);
69
70/// Classic 4th-order Runge-Kutta (fixed step).
72 StepCallback on_step = nullptr);
73
74/// Adaptive Dormand-Prince RK45 with FSAL and PI step-size control.
75///
76/// Advances from t0 to t1, adjusting h so that the mixed
77/// absolute/relative error estimate stays below tolerance:
78/// err / (atol + |y|·rtol) ≤ 1
79///
80/// @param rtol Relative tolerance (default 1e-6)
81/// @param atol Absolute tolerance (default 1e-9)
82/// @param h0 Initial step-size hint (default 1e-3)
83/// @param max_steps Hard limit on accepted steps (default 1e6)
84/// @param on_step Optional callback after each accepted step
86 real rtol = 1e-6, real atol = 1e-9,
87 real h0 = 1e-3, idx max_steps = 1000000,
88 StepCallback on_step = nullptr);
89
90// ── Symplectic integrators ────────────────────────────────────────────────────
91//
92// For separable Hamiltonians H(q,p) = T(p) + V(q) only.
93// Symplectic (volume-preserving in phase space) and time-reversible —
94// energy error is bounded, not growing, over exponentially long runs.
95// Compare with RK4 which has secular O(h^4) energy drift per step.
96//
97// Both methods take q and v separately (not concatenated) and an AccelFn.
98
99/// Velocity Verlet — 2nd-order symplectic, 1 force evaluation per step.
100///
101/// Algorithm (kick-drift-kick):
102/// a_n = accel(q_n)
103/// q_{n+1} = q_n + h·v_n + h²/2 · a_n
104/// a_{n+1} = accel(q_{n+1})
105/// v_{n+1} = v_n + h/2 · (a_n + a_{n+1})
106///
107/// Acceleration is cached between steps (FSAL — first same as last).
109 real t0, real t1, real h,
110 SymplecticCallback on_step = nullptr);
111
112/// Yoshida 4th-order symplectic — 3 force evaluations per step.
113///
114/// Composes three leapfrog sub-steps with Yoshida (1990) coefficients:
115/// w₁ = 1 / (2 − ∛2), w₀ = 1 − 2w₁
116/// c₁=c₄=w₁/2, c₂=c₃=(w₀+w₁)/2, d₁=d₃=w₁, d₂=w₀
117///
118/// Drift-kick sequence per step:
119/// q += c₁h·v → v += d₁h·a(q) → q += c₂h·v → v += d₂h·a(q)
120/// → q += c₃h·v → v += d₃h·a(q) → q += c₄h·v
121///
122/// Preferred over Verlet when accuracy matters and force is cheap.
124 real t0, real t1, real h,
125 SymplecticCallback on_step = nullptr);
126
127} // namespace num
Core type definitions.
std::function< void(real t, const Vector &q, const Vector &v)> SymplecticCallback
Definition ode.hpp:43
double real
Definition types.hpp:10
std::function< void(real t, const Vector &y, Vector &dydt)> ODERhsFn
Right-hand side callable: fills dydt = f(t, y) in-place.
Definition ode.hpp:28
ODEResult ode_rk45(ODERhsFn f, Vector y0, real t0, real t1, real rtol=1e-6, real atol=1e-9, real h0=1e-3, idx max_steps=1000000, StepCallback on_step=nullptr)
Definition ode.cpp:67
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
std::size_t idx
Definition types.hpp:11
SymplecticResult ode_yoshida4(AccelFn accel, Vector q0, Vector v0, real t0, real t1, real h, SymplecticCallback on_step=nullptr)
Definition ode.cpp:195
constexpr real e
Definition math.hpp:41
SymplecticResult ode_verlet(AccelFn accel, Vector q0, Vector v0, real t0, real t1, real h, SymplecticCallback on_step=nullptr)
Definition ode.cpp:154
ODEResult ode_rk4(ODERhsFn f, Vector y0, real t0, real t1, real h, StepCallback on_step=nullptr)
Classic 4th-order Runge-Kutta (fixed step).
Definition ode.cpp:33
std::function< void(real t, const Vector &y)> StepCallback
Definition ode.hpp:33
std::function< void(const Vector &q, Vector &acc)> AccelFn
Definition ode.hpp:37
ODEResult ode_euler(ODERhsFn f, Vector y0, real t0, real t1, real h, StepCallback on_step=nullptr)
Definition ode.cpp:15
Result returned by general ODE integrators.
Definition ode.hpp:48
Vector y
Final state vector.
Definition ode.hpp:49
idx steps
Number of (accepted) steps taken.
Definition ode.hpp:51
bool converged
Always true for fixed-step; false if rk45 hit max_steps.
Definition ode.hpp:52
real t
Final time.
Definition ode.hpp:50
Result returned by symplectic integrators.
Definition ode.hpp:56
Vector v
Final generalised velocities.
Definition ode.hpp:58
Vector q
Final generalised positions.
Definition ode.hpp:57
idx steps
Number of steps taken.
Definition ode.hpp:60
real t
Final time.
Definition ode.hpp:59
Vector operations.