FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Haghrah/DDEINT-Rust: Rust solver for delay differential equations, with per-variable delay support. Inspired by Zulko's Python ddeint. · GitHub

Latest commit

 

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Delay differential equations solver for Rust

ddeint is a small toolkit for numerically solving delay differential equations (DDEs), i.e. ODEs whose right-hand side depends on the state at past times t - delay. It wraps integrators from the ode_solvers crate, plus a piecewise-linear history interpolator (DdeVar/DdeVars) that is updated after every accepted integration step so that delayed lookups always reflect the actual solved trajectory rather than only the initial history.

Three integrators are available, all with the same shape (new/step/ integrate, a results: Vec<(f64, DVector<f64>)> field) so switching between them is close to a drop-in change:

Type Underlying method Extra constructor args
DdeRK4 fixed-step RK4 --
DdeDopri5 adaptive Dormand-Prince 5(4) rtol, atol
DdeDop853 adaptive Dormand-Prince 8(5,3) rtol, atol

For all three, step_size controls how often the delayed history is updated and a result is recorded. For DdeRK4 that's also the literal integration step; for the two adaptive solvers, the actual number of internal steps between two recorded points is chosen by their own error control, and the state at exactly t + step_size is obtained from their dense-output interpolant rather than by counting steps. See examples/integrator_comparison.rs for all three solving the same DDE side by side (and a note on why the higher-order integrator isn't automatically the more accurate one here).

Examples

Interpolating a table of values

use ddeint::Interpolator;

let x = vec![0.0, 1.0, 2.0];
let y = vec![0.0, 1.0, 4.0];
let interpolator = Interpolator::new(x, y, /* fill_value = */ 0.0);

assert_eq!(interpolator.interpolate(0.5), Some(0.5));

Solving a delayed predator-prey system

A System that needs delayed state has to implement DdeSystem in addition to ode_solvers's System trait; DdeSystem::record is called by DdeRK4 after every step and is where the system should push the newly solved state into its own history storage (typically an Rc<RefCell<DdeVars>> shared with the closure/struct that reads it back in system()):

use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;
use nalgebra::DVector;
use ddeint::{DdeRK4, DdeSystem, DdeVars};

#[derive(Clone)]
struct DelayedPredatorPrey {
    delay: f64,
    history: Rc<RefCell<DdeVars>>,
}

impl ode_solvers::System<f64, DVector<f64>> for DelayedPredatorPrey {
    fn system(&self, t: f64, y: &DVector<f64>, dy: &mut DVector<f64>) {
        let history = self.history.borrow();
        let prey_delayed = history[0].instance_value(t - self.delay);
        let predator_delayed = history[1].instance_value(t - self.delay);

        dy[0] = 0.5 * y[0] * (1.0 - predator_delayed);
        dy[1] = -0.5 * y[1] * (1.0 - prey_delayed);
    }
}

impl DdeSystem for DelayedPredatorPrey {
    fn record(&self, t: f64, y: &DVector<f64>) {
        let mut history = self.history.borrow_mut();
        history[0].update(t, y[0]);
        history[1].update(t, y[1]);
    }
}

See src/lotka_delay.rs for the full, runnable version of this example (ddeint::solve_lotka_volterra), also wired into main.rs.

More examples

Runnable examples live under examples/. Each one writes its result to a CSV file (in the directory cargo is run from) in addition to printing a short summary:

cargo run --release --example three_var_dde          # 3-variable, 2-delay system (Willé & Baker's classic example)
cargo run --release --example sine_delay              # single delay, checked against its exact closed-form solution
cargo run --release --example variable_delay          # a delay that is itself a function of time, not a constant
cargo run --release --example integrator_comparison   # DdeRK4 vs DdeDopri5 vs DdeDop853 on the same DDE

The exact-solution and convergence checks these examples use for verification are also captured as cargo test-run regression tests in tests/analytic_verification.rs.

Acknowledgments

This project was inspired by Zulko's Python ddeint, a lightweight DDE solver built on top of scipy.integrate.ode. Many thanks to Zulko for the original design and the history-interpolation (ddeVar) idea this crate is built around.

One thing this crate does differently: in the original ddeint, the whole state is a single vector-valued history function, so every state variable is looked up with the same delay. This port's DdeVars instead keeps a separate history per state variable, so different variables can use different delay values within the same system -- see examples/three_var_dde.rs, where y1 is delayed by 1.0 and y2 by 0.2 in the same system.

About

Rust solver for delay differential equations, with per-variable delay support. Inspired by Zulko's Python ddeint.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages


Back | FazBrowse Home | New Git URL