mod adaptive;
mod dormandprince;
mod fixed;
use std::{collections::VecDeque, marker::PhantomData};
use crate::{
methods::Delay,
status::Status,
tolerance::Tolerance,
traits::{Real, State},
};
pub struct ExplicitRungeKutta<
E,
F,
T: Real,
Y: State<T>,
const O: usize,
const S: usize,
const I: usize,
> {
t0: T,
pub h0: T,
h: T,
t: T,
y: Y,
dydt: Y,
h_prev: T,
t_prev: T,
y_prev: Y,
dydt_prev: Y,
k: [Y; I],
c: [T; I],
a: [[T; I]; I],
b: [T; S],
bh: Option<[T; S]>, er: Option<[T; S]>,
bi: Option<[[T; I]; I]>, cont: [Y; O],
pub rtol: Tolerance<T>,
pub atol: Tolerance<T>,
pub h_max: T,
pub h_min: T,
pub max_steps: usize,
pub max_rejects: usize,
pub safety_factor: T,
pub min_scale: T,
pub max_scale: T,
pub filter: fn(T) -> T,
stiffness_counter: usize,
non_stiffness_counter: usize,
steps: usize,
status: Status<T, Y>,
order: usize,
stages: usize,
dense_stages: usize,
fsal: bool,
family: PhantomData<F>,
equation: PhantomData<E>,
history: VecDeque<(T, Y, Y)>, max_delay: Option<T>, }
impl<E, F, T: Real, Y: State<T>, const O: usize, const S: usize, const I: usize> Default
for ExplicitRungeKutta<E, F, T, Y, O, S, I>
{
fn default() -> Self {
Self {
t0: T::zero(),
h0: T::zero(),
h: T::zero(),
t: T::zero(),
y: Y::zeros(),
dydt: Y::zeros(),
h_prev: T::zero(),
t_prev: T::zero(),
y_prev: Y::zeros(),
dydt_prev: Y::zeros(),
k: [Y::zeros(); I],
c: [T::zero(); I],
a: [[T::zero(); I]; I],
b: [T::zero(); S],
bh: None,
er: None,
bi: None,
cont: [Y::zeros(); O],
rtol: Tolerance::Scalar(T::from_f64(1.0e-6).unwrap()),
atol: Tolerance::Scalar(T::from_f64(1.0e-6).unwrap()),
h_max: T::infinity(),
h_min: T::zero(),
max_steps: 10_000,
max_rejects: 100,
safety_factor: T::from_f64(0.9).unwrap(),
min_scale: T::from_f64(0.2).unwrap(),
max_scale: T::from_f64(10.0).unwrap(),
filter: |h| h,
stiffness_counter: 0,
non_stiffness_counter: 0,
steps: 0,
status: Status::Uninitialized,
order: O,
stages: S,
dense_stages: I,
fsal: false,
family: PhantomData,
equation: PhantomData,
history: VecDeque::new(),
max_delay: None,
}
}
}
impl<E, F, T: Real, Y: State<T>, const O: usize, const S: usize, const I: usize>
ExplicitRungeKutta<E, F, T, Y, O, S, I>
{
pub fn rtol<V: Into<Tolerance<T>>>(mut self, rtol: V) -> Self {
self.rtol = rtol.into();
self
}
pub fn atol<V: Into<Tolerance<T>>>(mut self, atol: V) -> Self {
self.atol = atol.into();
self
}
pub fn h0(mut self, h0: T) -> Self {
self.h0 = h0;
self
}
pub fn h_min(mut self, h_min: T) -> Self {
self.h_min = h_min;
self
}
pub fn h_max(mut self, h_max: T) -> Self {
self.h_max = h_max;
self
}
pub fn max_steps(mut self, max_steps: usize) -> Self {
self.max_steps = max_steps;
self
}
pub fn max_rejects(mut self, max_rejects: usize) -> Self {
self.max_rejects = max_rejects;
self
}
pub fn safety_factor(mut self, safety_factor: T) -> Self {
self.safety_factor = safety_factor;
self
}
pub fn min_scale(mut self, min_scale: T) -> Self {
self.min_scale = min_scale;
self
}
pub fn max_scale(mut self, max_scale: T) -> Self {
self.max_scale = max_scale;
self
}
pub fn filter(mut self, filter: fn(T) -> T) -> Self {
self.filter = filter;
self
}
pub fn order(&self) -> usize {
self.order
}
pub fn stages(&self) -> usize {
self.stages
}
pub fn dense_stages(&self) -> usize {
self.dense_stages
}
}
impl<F, T: Real, Y: State<T>, const O: usize, const S: usize, const I: usize>
ExplicitRungeKutta<Delay, F, T, Y, O, S, I>
{
pub fn max_delay(mut self, max_delay: T) -> Self {
self.max_delay = Some(max_delay);
self
}
}