Special Relativity in Financial Modeling 1.0.0
Lorentz transforms, spacetime classification, and geodesic price paths for quantitative finance
Loading...
Searching...
No Matches
geodesic_solver.hpp
Go to the documentation of this file.
1#pragma once
2/**
3 * @file geodesic_solver.hpp
4 * @brief RK4 geodesic integrator on a spacetime manifold (AGT-13 / SRFM)
5 *
6 * Module: src/geodesic/
7 * Owner: AGT-13 (Adversarial hardening) — 2026-03-01
8 *
9 * Responsibility
10 * --------------
11 * Numerically integrate the geodesic equation:
12 *
13 * d²x^λ/dτ² + Γ^λ_μν (dx^μ/dτ)(dx^ν/dτ) = 0
14 *
15 * using a 4th-order Runge-Kutta scheme.
16 *
17 * Key property (tested by property suite):
18 * On the flat Minkowski metric (all Γ = 0) the solution is a straight line.
19 * Geodesic deviation after 100 RK4 steps is < 1e-8 from the linear prediction.
20 *
21 * Design Constraints
22 * ------------------
23 * • Must always terminate (no unbounded loops; step count is bounded).
24 * • RK4 must not produce NaN even for extreme initial conditions.
25 * • All fallible operations return std::optional.
26 * • noexcept throughout.
27 *
28 * NOT Responsible For
29 * • Adaptive step-size control.
30 * • Parallelisation across multiple geodesics.
31 * • Non-metric coupling terms (e.g. electromagnetic).
32 */
33
34#include <array>
35#include <cmath>
36#include <optional>
37
38#include "../manifold/spacetime_manifold.hpp"
39
40namespace srfm::geodesic {
41
42using manifold::MetricTensor;
43using manifold::DIM;
46
47// ── GeodesicState ─────────────────────────────────────────────────────────────
48
49/**
50 * @brief State of a particle on a geodesic: position x^μ and 4-velocity u^μ.
51 *
52 * The 8-dimensional phase space (x, u) is what RK4 advances each step.
53 */
55 std::array<double, DIM> x{}; ///< Position x^μ (μ = 0…3)
56 std::array<double, DIM> u{}; ///< 4-velocity u^μ = dx^μ/dτ
57
58 /// True iff all position and velocity components are finite.
59 [[nodiscard]] bool is_finite() const noexcept;
60};
61
62// ── GeodesicSolver ────────────────────────────────────────────────────────────
63
64/**
65 * @brief Integrates geodesic equations using the classical RK4 method.
66 *
67 * The Christoffel symbols are evaluated once per step from the supplied
68 * metric (constant-metric approximation, valid for small step sizes dτ).
69 *
70 * @example
71 * @code
72 * GeodesicSolver solver;
73 * GeodesicState init{{0,0,0,0}, {1,0,0,0}}; // at rest, proper-time flow
74 * auto metric = MetricTensor::minkowski();
75 * auto final_state = solver.solve(init, metric, 100, 0.01);
76 * // final_state->x[0] ≈ 1.0 (advanced 1 unit of proper time)
77 * @endcode
78 */
80public:
81 GeodesicSolver() noexcept = default;
82
83 /**
84 * @brief Integrate the geodesic equation for `steps` RK4 steps.
85 *
86 * At each step, Christoffel symbols are computed from `metric` at the
87 * current position. For a constant (flat) metric this is equivalent to
88 * evaluating at the origin: Γ = 0, giving straight-line trajectories.
89 *
90 * Safety guarantees:
91 * • Returns std::nullopt if initial state is non-finite.
92 * • Returns std::nullopt if any intermediate state becomes non-finite.
93 * • Never loops more than `steps` times.
94 * • `steps` is clamped to [1, 100'000] to prevent runaway.
95 * • `dt` (dτ) is clamped to [1e-8, 1.0] to prevent instability.
96 *
97 * @param initial Initial (x, u) state.
98 * @param metric Background metric tensor (treated as constant in space).
99 * @param steps Number of RK4 integration steps.
100 * @param dt Proper-time step size dτ.
101 * @return Final GeodesicState after integration, or std::nullopt on error.
102 */
103 [[nodiscard]] std::optional<GeodesicState>
104 solve(const GeodesicState& initial,
105 const MetricTensor& metric,
106 int steps,
107 double dt) const noexcept;
108};
109
110} // namespace srfm::geodesic
GeodesicSolver() noexcept=default
constexpr int NUM_CHRISTOFFEL
Total Christoffel symbols: DIM³ = 64.
constexpr int DIM
Number of spacetime dimensions.
constexpr int christoffel_index(int lambda, int mu, int nu) noexcept
Pack (λ, μ, ν) into flat index in [0, 64).
State of a particle on a geodesic: position x^μ and 4-velocity u^μ.
std::array< double, DIM > u
4-velocity u^μ = dx^μ/dτ
bool is_finite() const noexcept
True iff all position and velocity components are finite.
std::array< double, DIM > x
Position x^μ (μ = 0…3)
Symmetric 4×4 spacetime metric tensor g_{μν}.