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
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

use ndarray::*;
use ndarray_linalg::*;
use super::traits::*;

pub struct TimeSeries<'a, TEO, S>
    where S: DataMut,
          TEO: TimeEvolution + 'a
{
    state: ArrayBase<S, TEO::Dim>,
    buf: TEO::Buffer,
    teo: &'a TEO,
}

pub fn time_series<'a, TEO, S>(x0: ArrayBase<S, TEO::Dim>, teo: &'a TEO) -> TimeSeries<'a, TEO, S>
    where S: DataMut,
          TEO: TimeEvolution
{
    TimeSeries {
        state: x0,
        buf: teo.new_buffer(),
        teo: teo,
    }
}

impl<'a, TEO, A, S> TimeSeries<'a, TEO, S>
    where A: Scalar,
          S: DataMut<Elem = A> + DataClone,
          TEO: TimeEvolution<Scalar = A>
{
    pub fn iterate(&mut self) {
        self.teo.iterate(&mut self.state, &mut self.buf);
    }
}

impl<'a, TEO, A, S> Iterator for TimeSeries<'a, TEO, S>
    where A: Scalar,
          S: DataMut<Elem = A> + DataClone,
          TEO: TimeEvolution<Scalar = A>
{
    type Item = ArrayBase<S, TEO::Dim>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iterate();
        Some(self.state.clone())
    }
}


/// N-step adaptor
///
/// ```rust
/// use eom::*;
/// let teo = explicit::rk4(ode::Lorenz63::default(), 0.01);
/// let nstep = nstep(teo, 10);
/// ```
pub struct NStep<TEO> {
    teo: TEO,
    n: usize,
}

pub fn nstep<TEO>(teo: TEO, n: usize) -> NStep<TEO> {
    NStep { teo, n }
}

impl<TEO> ModelSpec for NStep<TEO>
    where TEO: ModelSpec
{
    type Scalar = TEO::Scalar;
    type Dim = TEO::Dim;

    fn model_size(&self) -> <Self::Dim as Dimension>::Pattern {
        self.teo.model_size()
    }
}

impl<TEO> TimeStep for NStep<TEO>
    where TEO: TimeStep
{
    type Time = TEO::Time;

    fn get_dt(&self) -> Self::Time {
        self.teo.get_dt() * into_scalar(self.n as f64)
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.teo.set_dt(dt / into_scalar(self.n as f64));
    }
}

impl<TEO> BufferSpec for NStep<TEO>
    where TEO: BufferSpec
{
    type Buffer = TEO::Buffer;
    fn new_buffer(&self) -> Self::Buffer {
        self.teo.new_buffer()
    }
}

impl<TEO> TimeEvolution for NStep<TEO>
    where TEO: TimeEvolution
{
    fn iterate<'a, S>(&self,
                      x: &'a mut ArrayBase<S, TEO::Dim>,
                      mut buf: &mut Self::Buffer)
                      -> &'a mut ArrayBase<S, TEO::Dim>
        where S: DataMut<Elem = TEO::Scalar>
    {
        for _ in 0..self.n {
            self.teo.iterate(x, buf);
        }
        x
    }
}