use crate::{
error::Error,
interpolate::Interpolation,
sde::{SDE, StochasticNumericalMethod, solve_sde},
solout::*,
solution::Solution,
traits::{Real, State},
};
#[derive(Debug)]
pub struct SDEProblem<'a, T, Y, F>
where
T: Real,
Y: State<T>,
F: SDE<T, Y>,
{
pub sde: &'a mut F, pub t0: T, pub tf: T, pub y0: Y, }
impl<'a, T, Y, F> SDEProblem<'a, T, Y, F>
where
T: Real,
Y: State<T>,
F: SDE<T, Y>,
{
pub fn new(sde: &'a mut F, t0: T, tf: T, y0: Y) -> Self {
SDEProblem { sde, t0, tf, y0 }
}
pub fn solve<S>(&mut self, solver: &'a mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: StochasticNumericalMethod<T, Y> + Interpolation<T, Y>,
{
let mut default_solout = DefaultSolout::new(); solve_sde(
solver,
self.sde,
self.t0,
self.tf,
&self.y0,
&mut default_solout,
)
}
pub fn solout<O: Solout<T, Y>>(
&'a mut self,
solout: &'a mut O,
) -> SDEProblemMutRefSoloutPair<'a, T, Y, F, O> {
SDEProblemMutRefSoloutPair::new(self, solout)
}
pub fn even(&'a mut self, dt: T) -> SDEProblemSoloutPair<'a, T, Y, F, EvenSolout<T>> {
let even_solout = EvenSolout::new(dt, self.t0, self.tf);
SDEProblemSoloutPair::new(self, even_solout)
}
pub fn dense(&'a mut self, n: usize) -> SDEProblemSoloutPair<'a, T, Y, F, DenseSolout> {
let dense_solout = DenseSolout::new(n);
SDEProblemSoloutPair::new(self, dense_solout)
}
pub fn t_eval(
&'a mut self,
points: impl AsRef<[T]>,
) -> SDEProblemSoloutPair<'a, T, Y, F, TEvalSolout<T>> {
let t_eval_solout = TEvalSolout::new(points, self.t0, self.tf);
SDEProblemSoloutPair::new(self, t_eval_solout)
}
pub fn crossing(
&'a mut self,
component_idx: usize,
threshold: T,
direction: CrossingDirection,
) -> SDEProblemSoloutPair<'a, T, Y, F, CrossingSolout<T>> {
let crossing_solout =
CrossingSolout::new(component_idx, threshold).with_direction(direction);
SDEProblemSoloutPair::new(self, crossing_solout)
}
pub fn hyperplane_crossing<Y1>(
&'a mut self,
point: Y1,
normal: Y1,
extractor: fn(&Y) -> Y1,
direction: CrossingDirection,
) -> SDEProblemSoloutPair<'a, T, Y, F, HyperplaneCrossingSolout<T, Y1, Y>>
where
Y1: State<T>,
{
let solout =
HyperplaneCrossingSolout::new(point, normal, extractor).with_direction(direction);
SDEProblemSoloutPair::new(self, solout)
}
pub fn event<E>(
&'a mut self,
event: &'a E,
) -> SDEProblemSoloutPair<'a, T, Y, F, EventSolout<'a, T, Y, E>>
where
E: Event<T, Y>,
{
let solout = EventSolout::new(event, self.t0, self.tf);
SDEProblemSoloutPair::new(self, solout)
}
}
pub struct SDEProblemMutRefSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: SDE<T, Y>,
O: Solout<T, Y>,
{
pub sde_problem: &'a mut SDEProblem<'a, T, Y, F>,
pub solout: &'a mut O,
}
impl<'a, T, Y, F, O> SDEProblemMutRefSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: SDE<T, Y>,
O: Solout<T, Y>,
{
pub fn new(sde_problem: &'a mut SDEProblem<'a, T, Y, F>, solout: &'a mut O) -> Self {
SDEProblemMutRefSoloutPair {
sde_problem,
solout,
}
}
pub fn solve<S>(&mut self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: StochasticNumericalMethod<T, Y> + Interpolation<T, Y>,
{
solve_sde(
solver,
self.sde_problem.sde,
self.sde_problem.t0,
self.sde_problem.tf,
&self.sde_problem.y0,
self.solout,
)
}
}
#[derive(Debug)]
pub struct SDEProblemSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: SDE<T, Y>,
O: Solout<T, Y>,
{
pub sde_problem: &'a mut SDEProblem<'a, T, Y, F>,
pub solout: O,
}
impl<'a, T, Y, F, O> SDEProblemSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: SDE<T, Y>,
O: Solout<T, Y>,
{
pub fn new(sde_problem: &'a mut SDEProblem<'a, T, Y, F>, solout: O) -> Self {
SDEProblemSoloutPair {
sde_problem,
solout,
}
}
pub fn solve<S>(mut self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: StochasticNumericalMethod<T, Y> + Interpolation<T, Y>,
{
solve_sde(
solver,
self.sde_problem.sde,
self.sde_problem.t0,
self.sde_problem.tf,
&self.sde_problem.y0,
&mut self.solout,
)
}
pub fn event<E>(
self,
event: &'a E,
) -> SDEProblemSoloutPair<'a, T, Y, F, EventWrappedSolout<'a, T, Y, O, E>>
where
E: Event<T, Y>,
{
let wrapped =
EventWrappedSolout::new(self.solout, event, self.sde_problem.t0, self.sde_problem.tf);
SDEProblemSoloutPair::new(self.sde_problem, wrapped)
}
}