linear_sim/
integrator.rs

1//! Numerical integration
2
3use crate::{component, object};
4
5/// Interface trait for integrators of objects with time derivatives
6pub trait Integrator : Clone {
7  // required
8  fn integrate_dt          <O : object::Temporal> (object : &mut O, dt : f64);
9  fn integrate_position_dt <O : object::Temporal> (object : &mut O, dt : f64);
10  fn integrate_velocity_dt <O : object::Temporal> (object : &mut O, dt : f64);
11  // provided
12  fn integrate             <O : object::Temporal> (object : &mut O) {
13    Self::integrate_dt (object, 1.0)
14  }
15  fn integrate_position    <O : object::Temporal> (object : &mut O) {
16    Self::integrate_position_dt (object, 1.0)
17  }
18  fn integrate_velocity    <O : object::Temporal> (object : &mut O) {
19    Self::integrate_velocity_dt (object, 1.0)
20  }
21}
22
23/// Semi-implicit Euler integrator
24#[derive(Clone, Debug, Default, Eq, PartialEq)]
25pub struct SemiImplicitEuler;
26impl Integrator for SemiImplicitEuler {
27  fn integrate_velocity_dt <O : object::Temporal> (object : &mut O, dt : f64) {
28    // second order: accelerate
29    let acceleration = object.derivatives().acceleration;
30    object.derivatives_mut().velocity += dt * acceleration;
31  }
32  fn integrate_position_dt <O : object::Temporal> (object : &mut O, dt : f64) {
33    // first order: translate
34    let velocity = object.derivatives().velocity;
35    let component::Position (position) = object.position_mut();
36    *position += dt * velocity;
37  }
38  /// Integrate with a step size of *dt*
39  fn integrate_dt <O : object::Temporal> (object : &mut O, dt : f64) {
40    Self::integrate_velocity_dt (object, dt);
41    Self::integrate_position_dt (object, dt);
42  }
43}