use crate::{
linalg::Matrix,
traits::{Real, State},
};
#[allow(unused_variables)]
pub trait ODE<T = f64, Y = f64>
where
T: Real,
Y: State<T>,
{
fn diff(&self, t: T, y: &Y, dydt: &mut Y);
fn jacobian(&self, t: T, y: &Y, j: &mut Matrix<T>) {
let dim = y.len();
let mut y_perturbed = *y;
let mut f_perturbed = Y::zeros();
let mut f_origin = Y::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;
}
}
}
}