use crate::{
dae::{AlgebraicNumericalMethod, DAE, solve_dae},
error::Error,
interpolate::Interpolation,
solout::*,
solution::Solution,
traits::{Real, State},
};
#[derive(Clone, Debug)]
pub struct DAEProblem<T, Y, F>
where
T: Real,
Y: State<T>,
F: DAE<T, Y>,
{
pub dae: F, pub t0: T, pub tf: T, pub y0: Y, }
impl<T, Y, F> DAEProblem<T, Y, F>
where
T: Real,
Y: State<T>,
F: DAE<T, Y>,
{
pub fn new(dae: F, t0: T, tf: T, y0: Y) -> Self {
DAEProblem { dae, t0, tf, y0 }
}
pub fn solve<S>(&self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: AlgebraicNumericalMethod<T, Y> + Interpolation<T, Y>,
{
let mut default_solout = DefaultSolout::new(); solve_dae(
solver,
&self.dae,
self.t0,
self.tf,
&self.y0,
&mut default_solout,
)
}
pub fn solout<'a, O: Solout<T, Y>>(
&'a self,
solout: &'a mut O,
) -> DAEProblemMutRefSoloutPair<'a, T, Y, F, O> {
DAEProblemMutRefSoloutPair::new(self, solout)
}
pub fn even(&self, dt: T) -> DAEProblemSoloutPair<'_, T, Y, F, EvenSolout<T>> {
let even_solout = EvenSolout::new(dt, self.t0, self.tf); DAEProblemSoloutPair::new(self, even_solout)
}
pub fn dense(&self, n: usize) -> DAEProblemSoloutPair<'_, T, Y, F, DenseSolout> {
let dense_solout = DenseSolout::new(n); DAEProblemSoloutPair::new(self, dense_solout)
}
pub fn t_eval(&self, points: Vec<T>) -> DAEProblemSoloutPair<'_, T, Y, F, TEvalSolout<T>> {
let t_eval_solout = TEvalSolout::new(points, self.t0, self.tf); DAEProblemSoloutPair::new(self, t_eval_solout)
}
pub fn crossing(
&self,
component_idx: usize,
threshhold: T,
direction: CrossingDirection,
) -> DAEProblemSoloutPair<'_, T, Y, F, CrossingSolout<T>> {
let crossing_solout =
CrossingSolout::new(component_idx, threshhold).with_direction(direction); DAEProblemSoloutPair::new(self, crossing_solout)
}
pub fn hyperplane_crossing<V1>(
&self,
point: V1,
normal: V1,
extractor: fn(&Y) -> V1,
direction: CrossingDirection,
) -> DAEProblemSoloutPair<'_, T, Y, F, HyperplaneCrossingSolout<T, V1, Y>>
where
V1: State<T>,
{
let solout =
HyperplaneCrossingSolout::new(point, normal, extractor).with_direction(direction);
DAEProblemSoloutPair::new(self, solout)
}
pub fn event<'e, E>(
&'e self,
event: &'e E,
) -> DAEProblemSoloutPair<'e, T, Y, F, EventSolout<'e, T, Y, E>>
where
E: Event<T, Y> + 'e,
{
let solout = EventSolout::new(event, self.t0, self.tf);
DAEProblemSoloutPair::new(self, solout)
}
}
pub struct DAEProblemMutRefSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: DAE<T, Y>,
O: Solout<T, Y>,
{
pub problem: &'a DAEProblem<T, Y, F>, pub solout: &'a mut O, }
impl<'a, T, Y, F, O> DAEProblemMutRefSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: DAE<T, Y>,
O: Solout<T, Y>,
{
pub fn new(problem: &'a DAEProblem<T, Y, F>, solout: &'a mut O) -> Self {
DAEProblemMutRefSoloutPair { problem, solout }
}
pub fn solve<S>(&mut self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: AlgebraicNumericalMethod<T, Y> + Interpolation<T, Y>,
{
solve_dae(
solver,
&self.problem.dae,
self.problem.t0,
self.problem.tf,
&self.problem.y0,
self.solout,
)
}
}
#[derive(Clone, Debug)]
pub struct DAEProblemSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: DAE<T, Y>,
O: Solout<T, Y>,
{
pub problem: &'a DAEProblem<T, Y, F>, pub solout: O, }
impl<'a, T, Y, F, O> DAEProblemSoloutPair<'a, T, Y, F, O>
where
T: Real,
Y: State<T>,
F: DAE<T, Y>,
O: Solout<T, Y>,
{
pub fn new(problem: &'a DAEProblem<T, Y, F>, solout: O) -> Self {
DAEProblemSoloutPair { problem, solout }
}
pub fn solve<S>(mut self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where
S: AlgebraicNumericalMethod<T, Y> + Interpolation<T, Y>,
{
solve_dae(
solver,
&self.problem.dae,
self.problem.t0,
self.problem.tf,
&self.problem.y0,
&mut self.solout,
)
}
pub fn event<E>(
self,
event: &'a E,
) -> DAEProblemSoloutPair<'a, T, Y, F, EventWrappedSolout<'a, T, Y, O, E>>
where
E: Event<T, Y>,
{
let wrapped = EventWrappedSolout::new(self.solout, event, self.problem.t0, self.problem.tf);
DAEProblemSoloutPair {
problem: self.problem,
solout: wrapped,
}
}
}