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}