use crate::{
error::DiffsolError, Context, DefaultDenseMatrix, DenseMatrix, OdeEquations, OdeSolverProblem,
OdeSolverState, StateRef, StateRefMut, Vector,
};
use super::state::{zeros_mat_with_directions, zeros_with_directions, StateCommon};
use num_traits::Zero;
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) struct RkStepRecord<T> {
pub(crate) h: T,
}
#[derive(Clone)]
pub struct RkState<V, M = <V as DefaultDenseMatrix>::M>
where
V: Vector + DefaultDenseMatrix,
M: DenseMatrix<T = V::T, V = V>,
{
pub(crate) diff: M,
pub(crate) y: V,
pub(crate) dy: V,
pub(crate) g: V,
pub(crate) dg: V,
pub(crate) s: V,
pub(crate) ds: V,
pub(crate) sg: V,
pub(crate) dsg: V,
pub(crate) t: V::T,
pub(crate) h: V::T,
pub(crate) last_step: Option<RkStepRecord<V::T>>,
}
impl<V, M> RkState<V, M>
where
V: Vector + DefaultDenseMatrix,
M: DenseMatrix<T = V::T, V = V, C = V::C>,
{
pub(crate) fn new_empty(ctx: V::C) -> Self {
let default_v = V::zeros(0, ctx.clone());
Self {
diff: M::zeros(0, 0, ctx),
y: default_v.clone(),
dy: default_v.clone(),
g: default_v.clone(),
dg: default_v.clone(),
s: default_v.clone(),
ds: default_v.clone(),
sg: default_v.clone(),
dsg: default_v.clone(),
t: V::T::zero(),
h: V::T::zero(),
last_step: None,
}
}
pub(crate) fn set_nstages(&mut self, nstages: usize) {
let nstates = self.y.len();
if self.diff.nrows() != nstates
|| self.diff.ncols() != nstages
|| self.diff.context().nbatch() != self.y.context().nbatch()
{
self.diff = M::zeros(nstates, nstages, self.y.context().clone());
self.last_step = None;
}
}
}
impl<V, M> OdeSolverState<V> for RkState<V, M>
where
V: Vector + DefaultDenseMatrix,
M: DenseMatrix<T = V::T, V = V, C = V::C>,
{
fn set_problem<Eqn: OdeEquations>(
&mut self,
_ode_problem: &OdeSolverProblem<Eqn>,
) -> Result<(), DiffsolError> {
Ok(())
}
fn set_augmented_problem<Eqn: OdeEquations, AugmentedEqn: crate::AugmentedOdeEquations<Eqn>>(
&mut self,
_ode_problem: &OdeSolverProblem<Eqn>,
_augmented_eqn: &AugmentedEqn,
) -> Result<(), DiffsolError> {
Ok(())
}
fn new_from_common(state: StateCommon<V>) -> Self {
let diff = M::zeros(0, 0, state.y.context().clone());
Self {
diff,
y: state.y,
dy: state.dy,
g: state.g,
dg: state.dg,
s: state.s,
ds: state.ds,
sg: state.sg,
dsg: state.dsg,
t: state.t,
h: state.h,
last_step: None,
}
}
fn into_common(self) -> StateCommon<V> {
StateCommon {
y: self.y,
dy: self.dy,
g: self.g,
dg: self.dg,
s: self.s,
ds: self.ds,
sg: self.sg,
dsg: self.dsg,
t: self.t,
h: self.h,
}
}
fn as_mut(&mut self) -> StateRefMut<'_, V> {
self.last_step = None;
StateRefMut {
y: &mut self.y,
dy: &mut self.dy,
g: &mut self.g,
dg: &mut self.dg,
s: &mut self.s,
ds: &mut self.ds,
sg: &mut self.sg,
dsg: &mut self.dsg,
t: &mut self.t,
h: &mut self.h,
}
}
fn as_ref(&self) -> StateRef<'_, V> {
StateRef {
y: &self.y,
dy: &self.dy,
g: &self.g,
dg: &self.dg,
s: &self.s,
ds: &self.ds,
sg: &self.sg,
dsg: &self.dsg,
t: self.t,
h: self.h,
}
}
fn zeros_like_with_directions(&self, ndirections: usize) -> Result<Self, DiffsolError> {
let v = |v: &V| zeros_with_directions(v, ndirections);
Ok(Self {
diff: zeros_mat_with_directions(&self.diff, ndirections)?,
y: v(&self.y)?,
dy: v(&self.dy)?,
g: v(&self.g)?,
dg: v(&self.dg)?,
s: v(&self.s)?,
ds: v(&self.ds)?,
sg: v(&self.sg)?,
dsg: v(&self.dsg)?,
t: self.t,
h: self.h,
last_step: self.last_step,
})
}
}