Skip to main content

ParametricOdeSystem

Trait ParametricOdeSystem 

Source
pub trait ParametricOdeSystem<S: Scalar> {
    // Required methods
    fn n_states(&self) -> usize;
    fn n_params(&self) -> usize;
    fn params(&self) -> &[S];
    fn rhs_with_params(&self, t: S, y: &[S], p: &[S], dydt: &mut [S]);

    // Provided methods
    fn rhs(&self, t: S, y: &[S], dydt: &mut [S]) { ... }
    fn jacobian_y(&self, t: S, y: &[S], jac: &mut [S]) { ... }
    fn jacobian_p(&self, t: S, y: &[S], jp: &mut [S]) { ... }
    fn initial_sensitivity(&self, _y0: &[S], s0: &mut [S]) { ... }
    fn has_analytical_jacobian_y(&self) -> bool { ... }
    fn has_analytical_jacobian_p(&self) -> bool { ... }
}
Expand description

An ODE system parameterised by a parameter vector p.

Implementors expose dimensions, the nominal parameter vector, the parameterised right-hand side, and optionally analytical Jacobians. Forward finite differences are provided as defaults for jacobian_y and jacobian_p, so a minimal implementation supplies only n_states, n_params, params, and rhs_with_params.

See the module-level documentation for the layout conventions (J_y row-major, J_p and S column-major) and a worked 2-state, 2-parameter example.

Required Methods§

Source

fn n_states(&self) -> usize

Number of state variables N (the dimension of y).

Source

fn n_params(&self) -> usize

Number of parameters N_s (the dimension of p).

Source

fn params(&self) -> &[S]

Nominal parameter vector. Length must equal Self::n_params.

Source

fn rhs_with_params(&self, t: S, y: &[S], p: &[S], dydt: &mut [S])

Evaluate f(t, y, p) -> dy/dt for an arbitrary parameter vector p.

This is the primitive form: it lets the FD-default Jacobians perturb p without mutating self.

Provided Methods§

Source

fn rhs(&self, t: S, y: &[S], dydt: &mut [S])

Convenience: evaluate the RHS at the system’s nominal parameters.

Source

fn jacobian_y(&self, t: S, y: &[S], jac: &mut [S])

Fill the state Jacobian J_y[i,j] = ∂f_i/∂y_j in row-major order (jac[i*N + j], length ).

Default: forward finite differences via Self::rhs_with_params. Override to supply an analytical Jacobian — required for performance on stiff problems with implicit solvers.

Source

fn jacobian_p(&self, t: S, y: &[S], jp: &mut [S])

Fill the parameter Jacobian J_p[i,k] = ∂f_i/∂p_k in column-major order (jp[k*N + i], length N · N_s).

Default: forward finite differences. Override for performance.

Source

fn initial_sensitivity(&self, _y0: &[S], s0: &mut [S])

Initial sensitivity ∂y_0/∂p, column-major (s0[k*N + i], length N · N_s).

Defaults to zero, which is correct when y_0 does not depend on p. Override only if y_0 = y_0(p).

Source

fn has_analytical_jacobian_y(&self) -> bool

Returns true iff Self::jacobian_y has been overridden with an analytical implementation. Default: false.

AugmentedSystem checks this flag inside its hot path. When false (the default), it inlines its own forward-FD using reused scratch buffers — bypassing both the trait default and any override. When true, it calls system.jacobian_y(...) directly so the user’s analytical override is honored.

This is the pattern used by CVODES (set_jacobian_user_supplied): flagging analytical Jacobians lets the augmented-system path skip FD scratch allocation in the common FD case while still respecting analytical overrides in the stiff-problem case where they materially matter. If you override jacobian_y, also override this method to return true — otherwise your override is silently bypassed when running through solve_forward_sensitivity.

§Debug-build safety net

To catch the silent-misconfiguration case (override the method, forget the flag), AugmentedSystem runs a one-time consistency check on the first RHS call: it evaluates Self::jacobian_y (which dispatches to the user’s override or the FD default) and compares against the inline FD result. If they disagree by more than a Frobenius-norm relative threshold of 1e-3, the system panics in debug builds with a message naming the missing flag override. Release builds skip the check entirely (zero overhead). This is a safety net, not a contract — fixing the panic by returning true here is the canonical resolution.

Source

fn has_analytical_jacobian_p(&self) -> bool

Returns true iff Self::jacobian_p has been overridden with an analytical implementation. Default: false. See Self::has_analytical_jacobian_y for the rationale, contract, and debug-build consistency check.

Implementations on Foreign Types§

Source§

impl<S: Scalar, T: ParametricOdeSystem<S>> ParametricOdeSystem<S> for &T

Forwarding impl: a reference to a parametric system is itself a parametric system. Lets solve_forward_sensitivity accept &Sys without taking ownership of the user’s data.

Source§

fn n_states(&self) -> usize

Source§

fn n_params(&self) -> usize

Source§

fn params(&self) -> &[S]

Source§

fn rhs_with_params(&self, t: S, y: &[S], p: &[S], dydt: &mut [S])

Source§

fn rhs(&self, t: S, y: &[S], dydt: &mut [S])

Source§

fn jacobian_y(&self, t: S, y: &[S], jac: &mut [S])

Source§

fn jacobian_p(&self, t: S, y: &[S], jp: &mut [S])

Source§

fn initial_sensitivity(&self, y0: &[S], s0: &mut [S])

Source§

fn has_analytical_jacobian_y(&self) -> bool

Source§

fn has_analytical_jacobian_p(&self) -> bool

Implementors§

Source§

impl<S: Scalar, F> ParametricOdeSystem<S> for ClosureSystem<S, F>
where F: Fn(S, &[S], &[S], &mut [S]),