Skip to main content

diffurch/loc/
propagation.rs

1use crate::{EventCall, State, StateFnMut};
2
3use super::*;
4
5/// Detection method marker for detecting that a delayed argument function has crossed a value in
6/// the state discontinuity list [State::disco].
7pub struct Propagation;
8
9///
10pub struct Propagator<const N: usize, Alpha: StateFnMut<N, Output = f64>> {
11    /// Delayed argument function
12    pub alpha: Alpha,
13    /// index into state disco queue
14    pub disco_idx: usize,
15    /// how order of discontinuity increases after this propagation
16    ///
17    /// 1 corresponds to retarded delay,
18    /// 0 corresponds to neutral delay
19    pub smoothing_order: usize,
20    /// the time of propagated discontinuity from last detection
21    pub propagated_t: f64,
22    /// the order of propagated discontinuity from last detection
23    pub propagated_order: usize,
24}
25
26impl<const N: usize, Alpha: StateFnMut<N, Output = f64>> Propagator<N, Alpha> {
27    /// Constructs a new Propagator object with provided values for `alpha` and
28    /// `smoothing_order` and sets `disco_idx: 0`, `propagated_t: f64::NAN`,
29    /// `propagated_order: usize::MAX`
30    pub fn new(alpha: Alpha, smoothing_order: usize) -> Self {
31        Self {
32            alpha,
33            disco_idx: 0,
34            smoothing_order,
35            propagated_t: f64::NAN,
36            propagated_order: usize::MAX,
37        }
38    }
39}
40
41impl<const N: usize, Alpha: StateFnMut<N, Output = f64>> StateFnMut<N> for Propagator<N, Alpha> {
42    type Output = f64;
43
44    fn eval(&mut self, state: &impl State<N>) -> Self::Output {
45        self.alpha.eval(state) - self.propagated_t
46    }
47
48    fn eval_prev(&mut self, state: &impl State<N>) -> Self::Output {
49        self.alpha.eval_prev(state) - self.propagated_t
50    }
51
52    fn eval_at(&mut self, state: &impl State<N>, t: f64) -> Self::Output {
53        self.alpha.eval_at(state, t) - self.propagated_t
54    }
55}
56
57impl<const N: usize, Alpha: StateFnMut<N, Output = f64>, L> Detect<N>
58    for Loc<Propagator<N, Alpha>, Propagation, L>
59{
60    fn detect(&mut self, state: &impl State<N>) -> bool {
61        let alpha_prev = self.0.alpha.eval_prev(state);
62        let alpha_curr = self.0.alpha.eval(state);
63        // println!("Delay: {}, Time: {} -> {}, Delayed: {alpha_prev} -> {alpha_curr}", state.t() - alpha_curr, state.t_prev(), state.t());
64
65        if alpha_prev < alpha_curr {
66            // get first t_disco > alpha_prev
67            while let Some((t_disco, _)) = state.disco_seq().get(self.0.disco_idx)
68                && *t_disco <= alpha_prev
69            {
70                self.0.disco_idx += 1;
71            }
72            while self.0.disco_idx > 0
73                && let Some((t_disco, _)) = state.disco_seq().get(self.0.disco_idx - 1)
74                && *t_disco > alpha_prev
75            {
76                self.0.disco_idx -= 1;
77            }
78
79            // check for t_disco < alpha_curr
80            if let Some((t_disco, order_disco)) = state.disco_seq().get(self.0.disco_idx)
81                && *t_disco <= alpha_curr
82            {
83                // println!("\tCrossing: {t_disco}");
84                self.0.propagated_t = *t_disco;
85                self.0.propagated_order = *order_disco;
86                return true;
87            }
88        } else {
89            todo!();
90        }
91
92        // while let Some((t_disco, _)) = state.disco().get(self.0.disco_idx + 1)
93        //     && *t_disco < alpha_prev
94        // {
95        //     self.0.disco_idx += 1;
96        // }
97        // if let Some((t_disco, _)) = state.disco().get(self.0.disco_idx + 1)
98        //     && alpha_curr > *t_disco
99        // {
100        //     self.0.propagated_t = *t_disco;
101        //     return true;
102        // }
103        //
104        // while let Some((t_disco, _)) = state.disco().get(self.0.disco_idx)
105        //     && *t_disco > alpha_prev
106        // {
107        //     self.0.disco_idx -= 1;
108        // }
109        // if let Some((t_disco, _)) = state.disco().get(self.0.disco_idx)
110        //     && alpha_curr < *t_disco
111        // {
112        //     self.0.propagated_t = *t_disco;
113        //     return true;
114        // }
115
116        false
117    }
118}
119
120impl<const N: usize, Alpha: StateFnMut<N, Output = f64>, L> EventCall<N>
121    for Loc<Propagator<N, Alpha>, Propagation, L>
122{
123    fn call(&mut self, state: &mut impl State<N>) {
124        let new_order = self.0.propagated_order + self.0.smoothing_order;
125        if new_order < state.interpolation_order() {
126            let t = state.t();
127            state.disco_seq_mut().push_back((t, new_order))
128        }
129    }
130}