Skip to main content

pathwise_geo/scheme/
euler.rs

1use crate::sde::ManifoldSDE;
2use cartan_core::Manifold;
3use pathwise_core::state::Increment;
4
5/// Geodesic Euler-Maruyama on a Riemannian manifold.
6/// x_{n+1} = Exp_{x_n}( f(x_n,t)*dt + g(x_n,t)*dW )
7/// Strong order 0.5. Keeps state exactly on the manifold by using the
8/// Riemannian exponential map after each step.
9pub struct GeodesicEuler;
10
11impl GeodesicEuler {
12    /// Advance x by one step of geodesic Euler-Maruyama.
13    ///
14    /// Computes the tangent displacement f(x,t)*dt + g(x,t)*dW and
15    /// maps it back to the manifold via Exp_x. Since all v0.1 cartan
16    /// manifolds are complete, Exp is total and always succeeds.
17    pub fn step<M, D, G>(
18        &self,
19        sde: &ManifoldSDE<M, D, G>,
20        x: &M::Point,
21        t: f64,
22        dt: f64,
23        inc: &Increment<f64>,
24    ) -> M::Point
25    where
26        M: Manifold,
27        D: Fn(&M::Point, f64) -> M::Tangent + Send + Sync,
28        G: Fn(&M::Point, f64) -> M::Tangent + Send + Sync,
29    {
30        let f = (sde.drift)(x, t);
31        let g = (sde.diffusion)(x, t);
32        // f * dt + g * dW, using cartan-core Tangent's Mul<Real> and Add bounds.
33        let tangent = f * dt + g * inc.dw;
34        sde.manifold.exp(x, &tangent)
35    }
36}