use sim_kernel::{Cx, Result, Symbol, Value};
use sim_lib_numbers_func::Func;
pub trait NumericPlugin: Send + Sync + 'static {
fn name(&self) -> Symbol;
fn kind(&self) -> NumericKind;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum NumericKind {
Differentiator,
QuadratureFixed,
QuadratureAdaptive,
OdeFixed,
OdeAdaptive,
DaeImplicit,
}
#[derive(Clone, Debug)]
pub struct DiffOpts {
pub method: Symbol,
pub h: f64,
}
impl DiffOpts {
pub fn auto() -> Self {
Self {
method: Symbol::new("auto"),
h: 1.0e-6,
}
}
}
#[derive(Clone, Debug)]
pub struct QuadOpts {
pub method: Symbol,
pub n: Option<usize>,
pub tol: Option<f64>,
}
impl QuadOpts {
pub fn fixed_default() -> Self {
Self {
method: Symbol::new("auto"),
n: None,
tol: None,
}
}
pub fn adaptive_default() -> Self {
Self {
method: Symbol::new("auto"),
n: None,
tol: Some(1.0e-10),
}
}
}
#[derive(Clone, Debug)]
pub struct OdeOpts {
pub method: Symbol,
pub h: Option<f64>,
pub tol: Option<f64>,
pub max_steps: Option<usize>,
}
impl OdeOpts {
pub fn default_adaptive() -> Self {
Self {
method: Symbol::new("auto"),
h: None,
tol: Some(1.0e-8),
max_steps: None,
}
}
}
pub struct OdeProblem<'a> {
pub dy: &'a Func,
pub var: &'a Symbol,
pub y_var: &'a Symbol,
pub x0: &'a Value,
pub y0: &'a Value,
pub x_end: &'a Value,
}
pub trait Differentiator: NumericPlugin {
fn diff_at(
&self,
cx: &mut Cx,
f: &Func,
var: &Symbol,
point: &Value,
opt: DiffOpts,
) -> Result<Value>;
}
pub trait Quadrature: NumericPlugin {
fn integrate(
&self,
cx: &mut Cx,
f: &Func,
var: &Symbol,
lo: &Value,
hi: &Value,
opt: QuadOpts,
) -> Result<Value>;
}
pub trait OdeSolver: NumericPlugin {
fn solve(
&self,
cx: &mut Cx,
problem: OdeProblem<'_>,
opt: OdeOpts,
) -> Result<Vec<(Value, Value)>>;
}