Trait TimeIntegrable

Source
pub trait TimeIntegrable:
    Debug
    + Clone
    + PartialEq {
    type Derivative: Debug + Clone + PartialEq;

    // Required method
    fn step(self, derivative: Self::Derivative, dt: Time) -> Self;
}
Expand description

A trait for types that support finite time stepping via integration.

Types that implement this trait must have a well-defined time derivative and be able to advance their state over a specified time interval.

This trait is primarily intended for unit-aware physical quantities, such as those provided by the uom crate.

It imposes no operator bounds directly. However, it is automatically implemented for any type T that satisfies the following bounds:

  • T: Div<Time, Output = Derivative>: Defines the derivative as T / Time
  • Derivative: Mul<Time, Output = Delta>: Defines the delta as Derivative * Time
  • T: Add<Delta, Output = T>: Enables applying a delta to produce an updated value
  • T and Derivative implement Debug, Clone, and PartialEq

For such types, which include all uom quantities, integration is performed using a forward Euler step:

next_value = self + derivative * dt

§Example

To implement TimeIntegrable manually for a composite type, define a corresponding derivative type and delegate the integration logic to each field:

use twine_core::{TimeIntegrable, TimeDerivative};
use uom::si::f64::{MassDensity, ThermodynamicTemperature, Time};

#[derive(Debug, Clone, PartialEq)]
struct State<T: TimeIntegrable> {
    temperature: ThermodynamicTemperature,
    density: MassDensity,
    other: T,
}

#[derive(Debug, Clone, PartialEq)]
struct StateTimeDerivative<T: TimeIntegrable> {
    temperature: TimeDerivative<ThermodynamicTemperature>,
    density: TimeDerivative<MassDensity>,
    other: TimeDerivative<T>,
}

impl<T: TimeIntegrable> TimeIntegrable for State<T> {
    type Derivative = StateTimeDerivative<T>;

    fn step(self, derivative: Self::Derivative, dt: Time) -> Self {
        Self {
            temperature: self.temperature.step(derivative.temperature, dt),
            density: self.density.step(derivative.density, dt),
            other: self.other.step(derivative.other, dt),
        }
    }
}

Alternatively, you can derive this implementation automatically using the #[derive(TimeIntegrable)] macro from the [twine_macros] crate:

use twine_macros::TimeIntegrable;
use uom::si::f64::{MassDensity, ThermodynamicTemperature};

#[derive(Debug, Clone, PartialEq, TimeIntegrable)]
struct State {
    temperature: ThermodynamicTemperature,
    density: MassDensity,
}

This generates the same StateTimeDerivative struct and TimeIntegrable implementation as shown above.

Required Associated Types§

Required Methods§

Source

fn step(self, derivative: Self::Derivative, dt: Time) -> Self

Advances the value using its derivative over a time interval.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<T, Derivative, Delta> TimeIntegrable for T
where T: Debug + Clone + PartialEq + Div<Time, Output = Derivative> + Add<Delta, Output = T>, Derivative: Debug + Clone + PartialEq + Mul<Time, Output = Delta>,

Source§

type Derivative = Derivative