1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
use std::marker::PhantomData; use ndarray::prelude::*; use super::traits::{EOM, TimeEvolution}; pub mod markers { pub struct EulerMarker {} pub struct RK4Marker {} } pub struct Explicit<F: EOM<D>, D: Dimension, Marker> { f: F, dt: f64, phantom_dim: PhantomData<D>, phantom_marker: PhantomData<Marker>, } impl<F: EOM<D>, D: Dimension, Marker> Explicit<F, D, Marker> { pub fn new(f: F, dt: f64) -> Self { Explicit { f: f, dt: dt, phantom_dim: PhantomData, phantom_marker: PhantomData, } } } impl<F: EOM<D>, D: Dimension> TimeEvolution<D> for Explicit<F, D, markers::EulerMarker> { #[inline(always)] fn iterate(&self, x: RcArray<f64, D>) -> RcArray<f64, D> { let fx = self.f.rhs(x.clone()); x + fx * self.dt } } impl<F: EOM<D>, D: Dimension> TimeEvolution<D> for Explicit<F, D, markers::RK4Marker> { #[inline(always)] fn iterate(&self, x: RcArray<f64, D>) -> RcArray<f64, D> { let mut l = x.clone(); l = self.f.rhs(l); let k1 = l.clone(); l = (0.5 * self.dt) * l + &x; l = self.f.rhs(l); let k2 = l.clone(); l = (0.5 * self.dt) * l + &x; l = self.f.rhs(l); let k3 = l.clone(); l = self.dt * l + &x; l = self.f.rhs(l); x + (self.dt / 6.0) * (k1 + 2.0 * (k2 + k3) + l) } } pub fn euler<F: EOM<D>, D: Dimension>(f: F, dt: f64) -> Explicit<F, D, markers::EulerMarker> { Explicit::new(f, dt) } pub fn rk4<F: EOM<D>, D: Dimension>(f: F, dt: f64) -> Explicit<F, D, markers::RK4Marker> { Explicit::new(f, dt) }