Skip to main content

Module integrator

Module integrator 

Source
Expand description

Enum-dispatched ODE integration — solver choice and system ownership.

§What this adds over the bare steppers

Euler, Rkf45 and Rosenbrock23 each integrate a system you hand them by reference on every call. That is fine inside one function, but a constitutive law or a solver loop usually wants to store “the integrator for this material point” — solver plus system together — and step it later. Storing a borrow would require a lifetime parameter on the storing struct, which the workspace design rules forbid outright.

This module removes the need for one. Two enums, no lifetimes anywhere:

  • OdeSolver — which stepper. A closed set (Euler, Rkf45, Rosenbrock23), so the scheme can be chosen at run time without a trait object and without heap allocation. Adding a stepper forces every match site to be updated.
  • OdeIntegrator — how the system is supplied. Two variants, and they are the whole point of this module:
    • OdeIntegrator::TypedState owns a concrete, statically-known system by value. Derivative calls are statically dispatched and inlinable. This is the preferred variant.
    • OdeIntegrator::DynSystem holds the system behind SharedOdeSystem (Arc<dyn OdeSystem + Send + Sync>). It exists by maintainer decision, for flexibility, so a caller that genuinely does not know the system type at the call site — a registry, a case-file reader, a test harness sweeping several systems — has a path that does not require inventing an enum of its own.

§Why there is no lifetime parameter

Both variants own their system: S by value, or shared ownership through Arc. Nothing here borrows the system, so nothing here needs to name the region the borrow is valid for. An OdeIntegrator can therefore be stored in a struct, moved between threads, or held in a Vec for one integrator per material point, with no lifetime plumbing at any call site.

§On the dyn in OdeIntegrator::DynSystem

The workspace rule is “no trait objects for dispatch — use enums”, and the dispatch here is the enum: OdeIntegrator chooses between two owning strategies by match, exhaustively. The Arc<dyn OdeSystem + Send + Sync> inside one of its variants is a boundary coercion for callers who ask for it, kept deliberately, not an accident to be cleaned up later. Prefer OdeIntegrator::TypedState; reach for OdeIntegrator::DynSystem when the type genuinely is not known statically.

§Example — the preferred typed path

use outram_foam_basic_lib::ode::{OdeIntegrator, OdeSolver, OdeSystem};

struct Decay;
impl OdeSystem for Decay {
    fn n_eqns(&self) -> usize { 1 }
    fn derivatives(&self, _x: f64, y: &[f64], dydx: &mut Vec<f64>) {
        dydx[0] = -y[0];
    }
}

// Owned by value — no borrow, no lifetime, storable in any struct.
let mut integrator = OdeIntegrator::typed(Decay, OdeSolver::rkf45(1, 1e-10, 1e-8));
let mut y = vec![1.0_f64];
let mut dx = 0.1;
integrator.integrate(0.0, 1.0, &mut y, &mut dx).unwrap();
assert!((y[0] - (-1.0_f64).exp()).abs() < 1e-8);

§Example — the shared dyn path

use std::sync::Arc;
use outram_foam_basic_lib::ode::{OdeIntegrator, OdeSolver, OdeSystem, SharedOdeSystem};

struct Decay;
impl OdeSystem for Decay {
    fn n_eqns(&self) -> usize { 1 }
    fn derivatives(&self, _x: f64, y: &[f64], dydx: &mut Vec<f64>) {
        dydx[0] = -y[0];
    }
}

let shared: SharedOdeSystem = Arc::new(Decay);
let mut integrator = OdeIntegrator::shared(shared, OdeSolver::rkf45(1, 1e-10, 1e-8));
let mut y = vec![1.0_f64];
let mut dx = 0.1;
integrator.integrate(0.0, 1.0, &mut y, &mut dx).unwrap();
assert!((y[0] - (-1.0_f64).exp()).abs() < 1e-8);

Structs§

DynSystemIntegrator
Solver plus a shared, runtime-typed system.
NoTypedSystem
The zero-equation system, and the default type argument of OdeIntegrator.
TypedStateIntegrator
Solver plus a statically-typed, owned system — the preferred variant of OdeIntegrator.

Enums§

OdeIntegrator
Enum-dispatch wrapper over the two ways of owning an ODE system.
OdeSolver
Which stepper integrates the system — enum dispatch over the closed set of solvers this crate ports.

Type Aliases§

SharedOdeSystem
A shared, runtime-typed ODE system.