use crate::{EventCall, State, StateFnMut};
use super::*;
pub struct Propagation;
pub struct Propagator<const N: usize, Alpha: StateFnMut<N, Output = f64>> {
pub alpha: Alpha,
pub disco_idx: usize,
pub smoothing_order: usize,
pub propagated_t: f64,
pub propagated_order: usize,
}
impl<const N: usize, Alpha: StateFnMut<N, Output = f64>> Propagator<N, Alpha> {
pub fn new(alpha: Alpha, smoothing_order: usize) -> Self {
Self {
alpha,
disco_idx: 0,
smoothing_order,
propagated_t: f64::NAN,
propagated_order: usize::MAX,
}
}
}
impl<const N: usize, Alpha: StateFnMut<N, Output = f64>> StateFnMut<N> for Propagator<N, Alpha> {
type Output = f64;
fn eval(&mut self, state: &impl State<N>) -> Self::Output {
self.alpha.eval(state) - self.propagated_t
}
fn eval_prev(&mut self, state: &impl State<N>) -> Self::Output {
self.alpha.eval_prev(state) - self.propagated_t
}
fn eval_at(&mut self, state: &impl State<N>, t: f64) -> Self::Output {
self.alpha.eval_at(state, t) - self.propagated_t
}
}
impl<const N: usize, Alpha: StateFnMut<N, Output = f64>, L> Detect<N>
for Loc<Propagator<N, Alpha>, Propagation, L>
{
fn detect(&mut self, state: &impl State<N>) -> bool {
let alpha_prev = self.0.alpha.eval_prev(state);
let alpha_curr = self.0.alpha.eval(state);
if alpha_prev < alpha_curr {
while let Some((t_disco, _)) = state.disco_seq().get(self.0.disco_idx)
&& *t_disco <= alpha_prev
{
self.0.disco_idx += 1;
}
while self.0.disco_idx > 0
&& let Some((t_disco, _)) = state.disco_seq().get(self.0.disco_idx - 1)
&& *t_disco > alpha_prev
{
self.0.disco_idx -= 1;
}
if let Some((t_disco, order_disco)) = state.disco_seq().get(self.0.disco_idx)
&& *t_disco <= alpha_curr
{
self.0.propagated_t = *t_disco;
self.0.propagated_order = *order_disco;
return true;
}
} else {
todo!();
}
false
}
}
impl<const N: usize, Alpha: StateFnMut<N, Output = f64>, L> EventCall<N>
for Loc<Propagator<N, Alpha>, Propagation, L>
{
fn call(&mut self, state: &mut impl State<N>) {
let new_order = self.0.propagated_order + self.0.smoothing_order;
if new_order < state.interpolation_order() {
let t = state.t();
state.disco_seq_mut().push_back((t, new_order))
}
}
}