use std::rc::Rc;
use crate::{Matrix, Scalar, Vector};
use num_traits::{One, Zero};
use serde::Serialize;
pub mod bdf;
pub mod closure;
pub mod closure_no_jac;
pub mod closure_with_sens;
pub mod constant_closure;
pub mod constant_closure_with_sens;
pub mod filter;
pub mod init;
pub mod linear_closure;
pub mod linear_closure_with_sens;
pub mod linearise;
pub mod matrix;
pub mod sdirk;
pub mod unit;
pub trait Op {
type T: Scalar;
type V: Vector<T = Self::T>;
type M: Matrix<T = Self::T, V = Self::V>;
fn nstates(&self) -> usize;
fn nout(&self) -> usize;
fn nparams(&self) -> usize {
0
}
fn set_params(&mut self, p: Rc<Self::V>) {
assert_eq!(p.len(), self.nparams());
}
fn sparsity(&self) -> Option<&<Self::M as Matrix>::Sparsity> {
None
}
fn sparsity_sens(&self) -> Option<&<Self::M as Matrix>::Sparsity> {
None
}
fn statistics(&self) -> OpStatistics {
OpStatistics::default()
}
}
#[derive(Default, Clone, Serialize)]
pub struct OpStatistics {
pub number_of_calls: usize,
pub number_of_jac_muls: usize,
pub number_of_matrix_evals: usize,
}
impl OpStatistics {
pub fn new() -> Self {
Self {
number_of_jac_muls: 0,
number_of_calls: 0,
number_of_matrix_evals: 0,
}
}
pub fn increment_call(&mut self) {
self.number_of_calls += 1;
}
pub fn increment_jac_mul(&mut self) {
self.number_of_jac_muls += 1;
}
pub fn increment_matrix(&mut self) {
self.number_of_matrix_evals += 1;
}
}
pub trait NonLinearOp: Op {
fn call_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::V);
fn jac_mul_inplace(&self, x: &Self::V, t: Self::T, v: &Self::V, y: &mut Self::V);
fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
if self.nparams() != 0 {
panic!("sens_mul_inplace not implemented for non-zero parameters");
}
y.fill(Self::T::zero());
}
fn has_sens(&self) -> bool {
false
}
fn call(&self, x: &Self::V, t: Self::T) -> Self::V {
let mut y = Self::V::zeros(self.nout());
self.call_inplace(x, t, &mut y);
y
}
fn jac_mul(&self, x: &Self::V, t: Self::T, v: &Self::V) -> Self::V {
let mut y = Self::V::zeros(self.nstates());
self.jac_mul_inplace(x, t, v, &mut y);
y
}
fn sens_mul(&self, x: &Self::V, t: Self::T, v: &Self::V) -> Self::V {
let mut y = Self::V::zeros(self.nstates());
self.sens_mul_inplace(x, t, v, &mut y);
y
}
fn jacobian_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::M) {
self._default_jacobian_inplace(x, t, y);
}
fn _default_jacobian_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::M) {
let mut v = Self::V::zeros(self.nstates());
let mut col = Self::V::zeros(self.nout());
for j in 0..self.nstates() {
v[j] = Self::T::one();
self.jac_mul_inplace(x, t, &v, &mut col);
y.set_column(j, &col);
v[j] = Self::T::zero();
}
}
fn jacobian(&self, x: &Self::V, t: Self::T) -> Self::M {
let n = self.nstates();
let mut y = Self::M::new_from_sparsity(n, n, self.sparsity());
self.jacobian_inplace(x, t, &mut y);
y
}
fn sens_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::M) {
self._default_sens_inplace(x, t, y);
}
fn _default_sens_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::M) {
let mut v = Self::V::zeros(self.nparams());
let mut col = Self::V::zeros(self.nout());
for j in 0..self.nparams() {
v[j] = Self::T::one();
self.sens_mul_inplace(x, t, &v, &mut col);
y.set_column(j, &col);
v[j] = Self::T::zero();
}
}
fn sens(&self, x: &Self::V, t: Self::T) -> Self::M {
let n = self.nstates();
let m = self.nparams();
let mut y = Self::M::new_from_sparsity(n, m, self.sparsity_sens());
self.sens_inplace(x, t, &mut y);
y
}
}
pub trait LinearOp: Op {
fn call_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::V) {
let beta = Self::T::zero();
self.gemv_inplace(x, t, beta, y);
}
fn has_sens(&self) -> bool {
false
}
fn gemv_inplace(&self, x: &Self::V, t: Self::T, beta: Self::T, y: &mut Self::V);
fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
if self.nparams() != 0 {
panic!("sens_mul_inplace not implemented for non-zero parameters");
}
y.fill(Self::T::zero());
}
fn sens_mul(&self, x: &Self::V, t: Self::T, v: &Self::V) -> Self::V {
let mut y = Self::V::zeros(self.nstates());
self.sens_mul_inplace(x, t, v, &mut y);
y
}
fn matrix(&self, t: Self::T) -> Self::M {
let mut y = Self::M::new_from_sparsity(self.nstates(), self.nstates(), self.sparsity());
self.matrix_inplace(t, &mut y);
y
}
fn matrix_inplace(&self, t: Self::T, y: &mut Self::M) {
self._default_matrix_inplace(t, y);
}
fn _default_matrix_inplace(&self, t: Self::T, y: &mut Self::M) {
let mut v = Self::V::zeros(self.nstates());
let mut col = Self::V::zeros(self.nout());
for j in 0..self.nstates() {
v[j] = Self::T::one();
self.call_inplace(&v, t, &mut col);
y.set_column(j, &col);
v[j] = Self::T::zero();
}
}
fn sens_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::M) {
self._default_sens_inplace(x, t, y);
}
fn _default_sens_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::M) {
let mut v = Self::V::zeros(self.nparams());
let mut col = Self::V::zeros(self.nout());
for j in 0..self.nparams() {
v[j] = Self::T::one();
self.sens_mul_inplace(x, t, &v, &mut col);
y.set_column(j, &col);
v[j] = Self::T::zero();
}
}
fn sens(&self, x: &Self::V, t: Self::T) -> Self::M {
let n = self.nstates();
let m = self.nparams();
let mut y = Self::M::new_from_sparsity(n, m, self.sparsity_sens());
self.sens_inplace(x, t, &mut y);
y
}
}
pub trait ConstantOp: Op {
fn call_inplace(&self, t: Self::T, y: &mut Self::V);
fn call(&self, t: Self::T) -> Self::V {
let mut y = Self::V::zeros(self.nout());
self.call_inplace(t, &mut y);
y
}
fn has_sens(&self) -> bool {
false
}
fn sens_mul_inplace(&self, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
if self.nparams() != 0 {
panic!("sens_mul_inplace not implemented for non-zero parameters");
}
y.fill(Self::T::zero());
}
fn sens_inplace(&self, t: Self::T, y: &mut Self::M) {
self._default_sens_inplace(t, y);
}
fn _default_sens_inplace(&self, t: Self::T, y: &mut Self::M) {
let mut v = Self::V::zeros(self.nparams());
let mut col = Self::V::zeros(self.nout());
for j in 0..self.nparams() {
v[j] = Self::T::one();
self.sens_mul_inplace(t, &v, &mut col);
y.set_column(j, &col);
v[j] = Self::T::zero();
}
}
fn sens(&self, t: Self::T) -> Self::M {
let n = self.nstates();
let m = self.nparams();
let mut y = Self::M::new_from_sparsity(n, m, self.sparsity_sens());
self.sens_inplace(t, &mut y);
y
}
}
impl<C: Op> Op for &C {
type T = C::T;
type V = C::V;
type M = C::M;
fn nstates(&self) -> usize {
C::nstates(*self)
}
fn nout(&self) -> usize {
C::nout(*self)
}
fn nparams(&self) -> usize {
C::nparams(*self)
}
}
impl<C: NonLinearOp> NonLinearOp for &C {
fn call_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::V) {
C::call_inplace(*self, x, t, y)
}
fn jac_mul_inplace(&self, x: &Self::V, t: Self::T, v: &Self::V, y: &mut Self::V) {
C::jac_mul_inplace(*self, x, t, v, y)
}
fn jacobian_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::M) {
C::jacobian_inplace(*self, x, t, y)
}
}
impl<C: LinearOp> LinearOp for &C {
fn gemv_inplace(&self, x: &Self::V, t: Self::T, beta: Self::T, y: &mut Self::V) {
C::gemv_inplace(*self, x, t, beta, y)
}
}