ODEProblem

Struct ODEProblem 

Source
pub struct ODEProblem<'a, T, Y, F>
where T: Real, Y: State<T>, F: ODE<T, Y>,
{ pub ode: &'a F, pub t0: T, pub tf: T, pub y0: Y, }
Expand description

Initial Value Problem for Ordinary Differential Equations (ODEs)

The Initial Value Problem takes the form: y’ = f(t, y), a <= t <= b, y(a) = alpha

§Overview

The ODEProblem struct provides a simple interface for solving differential equations:

§Example

use differential_equations::prelude::*;

struct LinearEquation {
   pub a: f32,
   pub b: f32,
}

impl ODE<f32, f32> for LinearEquation {
   fn diff(&self, _t: f32, y: &f32, dydt: &mut f32) {
       *dydt = self.a + self.b * y;
  }
}

// Create the ode and initial conditions
let ode = LinearEquation { a: 1.0, b: 2.0 };
let t0 = 0.0;
let tf = 1.0;
let y0 = 1.0;
let mut solver = ExplicitRungeKutta::dop853().rtol(1e-8).atol(1e-6);

// Basic usage:
let problem = ODEProblem::new(ode, t0, tf, y0);
let solution = problem.solve(&mut solver).unwrap();

// Advanced output control:
let solution = problem.even(0.1).solve(&mut solver).unwrap();

§Fields

  • ode - ODE implementing the differential equation
  • t0 - Initial time
  • tf - Final time
  • y0 - Initial state vector

§Basic Usage

  • new(ode, t0, tf, y0) - Create a new ODEProblem
  • solve(&mut solver) - Solve using default output (solver step points)

§Output Control Methods

These methods configure how solution points are generated and returned:

  • even(dt) - Generate evenly spaced output points with interval dt
  • dense(n) - Include n interpolated points between each solver step
  • t_eval(points) - Evaluate solution at specific time points
  • solout(custom_solout) - Use a custom output handler

Each returns a solver configuration that can be executed with .solve(&mut solver).

§Example 2

use differential_equations::prelude::*;
use nalgebra::{SVector, vector};

struct HarmonicOscillator { k: f64 }

impl ODE<f64, SVector<f64, 2>> for HarmonicOscillator {
    fn diff(&self, _t: f64, y: &SVector<f64, 2>, dydt: &mut SVector<f64, 2>) {
        dydt[0] = y[1];
        dydt[1] = -self.k * y[0];
    }
}

let ode = HarmonicOscillator { k: 1.0 };
let mut method = ExplicitRungeKutta::dop853().rtol(1e-12).atol(1e-12);

// Basic usage with default output points
let problem = ODEProblem::new(ode, 0.0, 10.0, vector![1.0, 0.0]);
let results = problem.solve(&mut method).unwrap();

// Advanced: evenly spaced output with 0.1 time intervals
let results = problem.dense(4).solve(&mut method).unwrap();

Fields§

§ode: &'a F

ODE object implementing ODE trait

§t0: T

Initial Time

§tf: T

Final Time

§y0: Y

Initial State Vector

Implementations§

Source§

impl<'a, T, Y, F> ODEProblem<'a, T, Y, F>
where T: Real, Y: State<T>, F: ODE<T, Y>,

Source

pub fn new(ode: &'a F, t0: T, tf: T, y0: Y) -> Self

Create a new Initial Value Problem

§Arguments
  • ode - ODE containing the Differential Equation and Optional Terminate Function.
  • t0 - Initial Time.
  • tf - Final Time.
  • y0 - Initial State Vector.
§Returns
  • ODEProblem Problem ready to be solved.
Source

pub fn solve<S>(&self, solver: &mut S) -> Result<Solution<T, Y>, Error<T, Y>>
where S: OrdinaryNumericalMethod<T, Y> + Interpolation<T, Y>,

Solve the ODEProblem using a default solout, e.g. outputting solutions at calculated steps.

§Returns
  • Result<Solution<T, Y>, Status<T, Y>> - Ok(Solution) if successful or interrupted by events, Err(Status) if an errors or issues such as stiffness are encountered.
Source

pub fn solout<O: Solout<T, Y>>( &'a self, solout: &'a mut O, ) -> ODEProblemMutRefSoloutPair<'a, T, Y, F, O>

Returns an ODEProblem OrdinaryNumericalMethod with the provided solout function for outputting points.

§Returns
  • ODEProblem OrdinaryNumericalMethod with the provided solout function ready for .solve() method.
Source

pub fn even(&self, dt: T) -> ODEProblemSoloutPair<'_, T, Y, F, EvenSolout<T>>

Uses the an Even Solout implementation to output evenly spaced points between the initial and final time. Note that this does not include the solution of the calculated steps.

§Arguments
  • dt - Interval between each output point.
§Returns
  • ODEProblem OrdinaryNumericalMethod with Even Solout function ready for .solve() method.
Source

pub fn dense(&self, n: usize) -> ODEProblemSoloutPair<'_, T, Y, F, DenseSolout>

Uses the Dense Output method to output n number of interpolation points between each step. Note this includes the solution of the calculated steps.

§Arguments
  • n - Number of interpolation points between each step.
§Returns
  • ODEProblem OrdinaryNumericalMethod with Dense Output function ready for .solve() method.
Source

pub fn t_eval( &self, points: impl AsRef<[T]>, ) -> ODEProblemSoloutPair<'_, T, Y, F, TEvalSolout<T>>

Uses the provided time points for evaluation instead of the default method. Note this does not include the solution of the calculated steps.

§Arguments
  • points - Custom output points.
§Returns
  • ODEProblem OrdinaryNumericalMethod with Custom Time Evaluation function ready for .solve() method.
Source

pub fn crossing( &self, component_idx: usize, threshhold: T, direction: CrossingDirection, ) -> ODEProblemSoloutPair<'_, T, Y, F, CrossingSolout<T>>

Uses the CrossingSolout method to output points when a specific component crosses a threshold. Note this does not include the solution of the calculated steps.

§Arguments
  • component_idx - Index of the component to monitor for crossing.
  • threshhold - Value to cross.
  • direction - Direction of crossing (positive or negative).
§Returns
  • ODEProblem OrdinaryNumericalMethod with CrossingSolout function ready for .solve() method.
Source

pub fn hyperplane_crossing<Y1>( &self, point: Y1, normal: Y1, extractor: fn(&Y) -> Y1, direction: CrossingDirection, ) -> ODEProblemSoloutPair<'_, T, Y, F, HyperplaneCrossingSolout<T, Y1, Y>>
where Y1: State<T>,

Uses the HyperplaneCrossingSolout method to output points when a specific hyperplane is crossed. Note this does not include the solution of the calculated steps.

§Arguments
  • point - Point on the hyperplane.
  • normal - Normal vector of the hyperplane.
  • extractor - Function to extract the component from the state vector.
  • direction - Direction of crossing (positive or negative).
§Returns
  • ODEProblem OrdinaryNumericalMethod with HyperplaneCrossingSolout function ready for .solve() method.
Source

pub fn event<E>( &'a self, event: &'a E, ) -> ODEProblemSoloutPair<'a, T, Y, F, EventSolout<'a, T, Y, E>>
where E: Event<T, Y>,

Uses an EventSolout to detect zero crossings of a user-defined event function (SciPy style). The provided event implements the Event trait returning a scalar function g(t,y) whose roots are sought. Each detected event point (t*, y*) is appended to the solution. Optional termination after N events can be configured in the Event implementation via config().

§Arguments
  • event - Object implementing Event<T, Y> whose zero crossings are desired.
§Returns
  • ODEProblemSoloutPair with EventSolout ready for .solve(&mut solver).
§Example
use differential_equations::prelude::*;
use nalgebra::{Vector2, vector};

struct SHO; // Simple harmonic oscillator
impl ODE<f64, Vector2<f64>> for SHO {
    fn diff(&self, _t: f64, y: &Vector2<f64>, dydt: &mut Vector2<f64>) {
        dydt[0]=y[1];
        dydt[1]=-y[0];
    }
}

// Event: detect when position crosses zero going positive (like SciPy event)
struct ZeroUp;
impl Event<f64, Vector2<f64>> for ZeroUp {
    fn config(&self) -> EventConfig {
        // Force only positive crossings
        EventConfig::default().direction(CrossingDirection::Positive)
    }
 
    fn event(&self, _t: f64, y: &Vector2<f64>) -> f64 {
        y[0]
    }
}

let osc = SHO; 
let t0 = 0.0; 
let tf = 10.0; 
let y0 = vector![1.0, 0.0];
let problem = ODEProblem::new(&osc, t0, tf, y0);
let mut solver = ExplicitRungeKutta::dop853();
let solution = problem.event(&ZeroUp).solve(&mut solver).unwrap();
// solution.t now contains zero-up crossing times

Trait Implementations§

Source§

impl<'a, T, Y, F> Clone for ODEProblem<'a, T, Y, F>
where T: Real + Clone, Y: State<T> + Clone, F: ODE<T, Y> + Clone,

Source§

fn clone(&self) -> ODEProblem<'a, T, Y, F>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a, T, Y, F> Debug for ODEProblem<'a, T, Y, F>
where T: Real + Debug, Y: State<T> + Debug, F: ODE<T, Y> + Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a, T, Y, F> Freeze for ODEProblem<'a, T, Y, F>
where T: Freeze, Y: Freeze,

§

impl<'a, T, Y, F> RefUnwindSafe for ODEProblem<'a, T, Y, F>

§

impl<'a, T, Y, F> Send for ODEProblem<'a, T, Y, F>
where Y: Send, F: Sync,

§

impl<'a, T, Y, F> Sync for ODEProblem<'a, T, Y, F>
where Y: Sync, F: Sync,

§

impl<'a, T, Y, F> Unpin for ODEProblem<'a, T, Y, F>
where T: Unpin, Y: Unpin,

§

impl<'a, T, Y, F> UnwindSafe for ODEProblem<'a, T, Y, F>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.