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}