Skip to main content

A Rust library for solving initial value problems (IVPs) for ordinary differential equations (ODEs).

Project description

ivp

crates.io PyPI docs.rs

Documentation | Examples | GitHub | Crates.io | PyPI


A library of numerical methods for solving initial value problems (IVPs)
for Rust and Python.


This library provides a pure Rust implementation of SciPy's solve_ivp functionality with a typed builder API for first-order, second-order, and Hamiltonian systems. It is also available as a Python package with a SciPy-compatible solve_ivp interface.

Features

Currently implemented solvers:

  • DOP853: An 8th order Dormand-Prince method with step-size control and dense output.
  • DOPRI5: A 5th order Dormand-Prince method with step-size control and dense output.
  • RK4: The classic 4th order Runge-Kutta method with fixed step-size and cubic Hermite interpolation for dense output.
  • RK23: A 3rd order Runge-Kutta method with 2nd order error estimate for step-size control.
  • LSODA: An automatic Adams/BDF switching multistep method for problems that may change stiffness.
  • Radau: A 5th order implicit Runge-Kutta method of Radau IIA type with step-size control and dense output.
  • BDF: A variable-order (1 to 5) Backward Differentiation Formula method for stiff ODEs with adaptive step-size control and dense output.
  • Symplectic methods: Fixed-step structured solvers for separable Hamiltonian and second-order systems, including Symplectic Euler, Velocity Verlet, Ruth 3, and Yoshida 4.

Installation

Rust

cargo add ivp

Python

pip install ivp-rs

Example Usage

from ivp import solve_ivp

def exponential_decay(t, y):
    return -0.5 * y

# Solve the ODE
sol = solve_ivp(exponential_decay, (0, 10), [1.0], method='RK45', rtol=1e-6, atol=1e-9)

print(f"Final time: {sol.t[-1]}")
print(f"Final state: {sol.y[:, -1]}")
use ivp::prelude::*;

struct ExponentialDecay;

impl FirstOrderSystem for ExponentialDecay {
    fn derivative(&self, _t: f64, y: &[f64], dydt: &mut [f64]) {
        dydt[0] = -0.5 * y[0];
    }
}

fn main() {
    let decay = ExponentialDecay;
    let y0 = [1.0];

    let sol = Ivp::first_order(&decay, 0.0, 10.0, &y0)
        .method(Method::DOPRI5)
        .rtol(1e-6)
        .atol(1e-9)
        .solve()
        .unwrap();
    
    println!("Final time: {}", sol.t.last().unwrap());
    println!("Final state: {:?}", sol.y.last().unwrap());
}

More complete examples:

Symplectic Usage

For structured mechanics problems, use the dedicated second-order or Hamiltonian builders instead of the Rust first-order Ivp::first_order(...) path.

use ivp::prelude::*;

struct HarmonicOscillator;

impl SecondOrderSystem for HarmonicOscillator {
    fn acceleration(&self, _t: f64, q: &[f64], a: &mut [f64]) {
        a[0] = -q[0];
    }
}

fn main() {
    let q0 = [1.0];
    let v0 = [0.0];

    let sol = Ivp::second_order(&HarmonicOscillator, 0.0, 20.0, &q0, &v0)
        .method(SymplecticMethod::VelocityVerlet)
        .step_size(0.05)
        .solve()
        .unwrap();

    println!("Final state: {:?}", sol.y.last().unwrap());
}

Python can also route these methods through solve_ivp. Second-order problems can use a plain acceleration callback, and Hamiltonian problems can use a callback pair:

import numpy as np
from ivp import solve_ivp

def acceleration(t, q):
    return -np.asarray(q, dtype=float)

sol = solve_ivp(
    acceleration,
    (0.0, 20.0),
    [1.0, 0.0, -0.5, 0.0, 1.0, 0.25],  # [q..., v...]
    method="VelocityVerlet",
    step_size=0.05,
    dense_output=True,
)

print(sol.sol(0.5))
def position_derivative(t, p):
    return np.array([p[0]])

def momentum_derivative(t, q):
    return np.array([-q[0]])

sol = solve_ivp(
    (position_derivative, momentum_derivative),
    (0.0, 20.0),
    [1.0, 0.0],
    method="Yoshida4",
    step_size=0.05,
)

On the Python side, invalid callback shapes now raise normal Python exceptions with explicit messages. For example, a symplectic callback returning the wrong number of values raises ValueError, and an incomplete Hamiltonian callback pair raises TypeError.

Current limitation: event handling is not yet supported for symplectic methods.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ivp_rs-0.2.0.tar.gz (131.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ivp_rs-0.2.0-cp39-abi3-manylinux_2_34_x86_64.whl (428.3 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.34+ x86-64

File details

Details for the file ivp_rs-0.2.0.tar.gz.

File metadata

  • Download URL: ivp_rs-0.2.0.tar.gz
  • Upload date:
  • Size: 131.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.10.1

File hashes

Hashes for ivp_rs-0.2.0.tar.gz
Algorithm Hash digest
SHA256 00dfa2d72bc909b1190a5f25ef23d3a97ea39d828e7f87b1bae73990fcc56b1d
MD5 d401cf5835e7dd3b47adf8486639b49a
BLAKE2b-256 955ade20e6b47bb56e96e6373e1203d4f2ded0c786017b9306558fa45b7e5508

See more details on using hashes here.

File details

Details for the file ivp_rs-0.2.0-cp39-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for ivp_rs-0.2.0-cp39-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 716b1afb263fc803961d53b8525216695cb8526e93315a0f16a9f42b8491ffb3
MD5 4d55761a4d7ec3755a62c5609160bbff
BLAKE2b-256 847abe67623f02ad0c6e737ef211cfc1be5455048e2cc54ffebd76ea9894a17c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page