use crate::{
dde::{DDE, numerical_method::DelayNumericalMethod, solve_dde},
error::Error,
interpolate::Interpolation,
solout::*,
solution::Solution,
traits::{Real, State},
};
#[derive(Clone, Debug)] pub struct DDEProblem<'a, const L: usize, T, Y, F, H>
where
T: Real,
Y: State<T>,
F: DDE<L, T, Y>,
H: Fn(T) -> Y,
{
pub dde: &'a F, pub t0: T, pub tf: T, pub y0: Y, pub phi: H, }
impl<'a, const L: usize, T, Y, F, H> DDEProblem<'a, L, T, Y, F, H>
where
T: Real,
Y: State<T>,
F: DDE<L, T, Y>,
H: Fn(T) -> Y + Clone, {
pub fn new(dde: &'a F, t0: T, tf: T, y0: Y, phi: H) -> Self {
DDEProblem {
dde,
t0,
tf,
y0,
phi,
}
}
pub fn solve<S>(&self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: DelayNumericalMethod<L, T, Y, H> + Interpolation<T, Y>,
H: Clone, {
let mut default_solout = DefaultSolout::new(); solve_dde(
solver,
self.dde,
self.t0,
self.tf,
&self.y0,
self.phi.clone(),
&mut default_solout,
)
}
pub fn solout<O: Solout<T, Y>>(
&'a self,
solout: &'a mut O,
) -> DDEProblemMutRefSoloutPair<'a, L, T, Y, F, H, O> {
DDEProblemMutRefSoloutPair::new(self, solout)
}
pub fn even(&self, dt: T) -> DDEProblemSoloutPair<'_, L, T, Y, F, H, EvenSolout<T>> {
let even_solout = EvenSolout::new(dt, self.t0, self.tf); DDEProblemSoloutPair::new(self, even_solout)
}
pub fn dense(&self, n: usize) -> DDEProblemSoloutPair<'_, L, T, Y, F, H, DenseSolout> {
let dense_solout = DenseSolout::new(n); DDEProblemSoloutPair::new(self, dense_solout)
}
pub fn t_eval(
&self,
points: impl AsRef<[T]>,
) -> DDEProblemSoloutPair<'_, L, T, Y, F, H, TEvalSolout<T>> {
let t_eval_solout = TEvalSolout::new(points, self.t0, self.tf); DDEProblemSoloutPair::new(self, t_eval_solout)
}
pub fn crossing(
&self,
component_idx: usize,
threshhold: T,
direction: CrossingDirection,
) -> DDEProblemSoloutPair<'_, L, T, Y, F, H, CrossingSolout<T>> {
let crossing_solout =
CrossingSolout::new(component_idx, threshhold).with_direction(direction); DDEProblemSoloutPair::new(self, crossing_solout)
}
pub fn hyperplane_crossing<Y1>(
&self,
point: Y1,
normal: Y1,
extractor: fn(&Y) -> Y1,
direction: CrossingDirection,
) -> DDEProblemSoloutPair<'_, L, T, Y, F, H, HyperplaneCrossingSolout<T, Y1, Y>>
where
Y1: State<T>,
{
let solout =
HyperplaneCrossingSolout::new(point, normal, extractor).with_direction(direction);
DDEProblemSoloutPair::new(self, solout)
}
pub fn event<E>(
&self,
event: &'a E,
) -> DDEProblemSoloutPair<'_, L, T, Y, F, H, EventSolout<'_, T, Y, E>>
where
E: Event<T, Y>,
{
let solout = EventSolout::new(event, self.t0, self.tf);
DDEProblemSoloutPair::new(self, solout)
}
}
pub struct DDEProblemMutRefSoloutPair<'a, const L: usize, T, Y, F, H, O>
where
T: Real,
Y: State<T>,
F: DDE<L, T, Y>,
H: Fn(T) -> Y,
O: Solout<T, Y>,
{
pub problem: &'a DDEProblem<'a, L, T, Y, F, H>, pub solout: &'a mut O, }
impl<'a, const L: usize, T, Y, F, H, O> DDEProblemMutRefSoloutPair<'a, L, T, Y, F, H, O>
where
T: Real,
Y: State<T>,
F: DDE<L, T, Y>,
H: Fn(T) -> Y + Clone, O: Solout<T, Y>,
{
pub fn new(problem: &'a DDEProblem<L, T, Y, F, H>, solout: &'a mut O) -> Self {
DDEProblemMutRefSoloutPair { problem, solout }
}
pub fn solve<S>(&mut self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: DelayNumericalMethod<L, T, Y, H> + Interpolation<T, Y>,
{
solve_dde(
solver,
self.problem.dde,
self.problem.t0,
self.problem.tf,
&self.problem.y0,
self.problem.phi.clone(),
self.solout,
)
}
}
#[derive(Clone, Debug)]
pub struct DDEProblemSoloutPair<'a, const L: usize, T, Y, F, H, O>
where
T: Real,
Y: State<T>,
F: DDE<L, T, Y>,
H: Fn(T) -> Y,
O: Solout<T, Y>,
{
pub problem: &'a DDEProblem<'a, L, T, Y, F, H>,
pub solout: O,
}
impl<'a, const L: usize, T, Y, F, H, O> DDEProblemSoloutPair<'a, L, T, Y, F, H, O>
where
T: Real,
Y: State<T>,
F: DDE<L, T, Y>,
H: Fn(T) -> Y + Clone,
O: Solout<T, Y>,
{
pub fn new(problem: &'a DDEProblem<L, T, Y, F, H>, solout: O) -> Self {
DDEProblemSoloutPair { problem, solout }
}
pub fn solve<S>(mut self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: DelayNumericalMethod<L, T, Y, H> + Interpolation<T, Y>,
{
solve_dde(
solver,
self.problem.dde,
self.problem.t0,
self.problem.tf,
&self.problem.y0,
self.problem.phi.clone(),
&mut self.solout,
)
}
pub fn event<E>(
self,
event: &'a E,
) -> DDEProblemSoloutPair<'a, L, T, Y, F, H, EventWrappedSolout<'a, T, Y, O, E>>
where
E: Event<T, Y>,
{
let wrapped = EventWrappedSolout::new(self.solout, event, self.problem.t0, self.problem.tf);
DDEProblemSoloutPair {
problem: self.problem,
solout: wrapped,
}
}
}