use crate::{
control::ControlFlag,
linalg::Matrix,
traits::{Real, State},
};
#[allow(unused_variables)]
pub trait DAE<T = f64, V = f64>
where
T: Real,
V: State<T>,
{
fn diff(&self, t: T, y: &V, f: &mut V);
fn mass(&self, m: &mut Matrix<T>);
fn event(&self, t: T, y: &V) -> ControlFlag<T, V> {
ControlFlag::Continue
}
fn jacobian(&self, t: T, y: &V, j: &mut Matrix<T>) {
let dim = y.len();
let mut y_perturbed = *y;
let mut f_perturbed = V::zeros();
let mut f_origin = V::zeros();
self.diff(t, y, &mut f_origin);
let eps = T::default_epsilon().sqrt();
for j_col in 0..dim {
let y_original_j = y.get(j_col);
let perturbation = eps * y_original_j.abs().max(T::one());
y_perturbed.set(j_col, y_original_j + perturbation);
self.diff(t, &y_perturbed, &mut f_perturbed);
y_perturbed.set(j_col, y_original_j);
for i_row in 0..dim {
j[(i_row, j_col)] = (f_perturbed.get(i_row) - f_origin.get(i_row)) / perturbation;
}
}
}
}