Skip to main content

sciforge_hub/engine/simulation/
model.rs

1/// Trait for systems of ordinary differential equations.
2pub trait DynamicalSystem {
3    /// Number of state variables.
4    fn dimension(&self) -> usize;
5    /// Computes derivatives at time `t` and `state`, writing into `out`.
6    fn derivatives(&self, t: f64, state: &[f64], out: &mut [f64]);
7    /// Returns the initial state vector.
8    fn initial_state(&self) -> Vec<f64>;
9    /// Returns the integration time span (t0, tf).
10    fn time_span(&self) -> (f64, f64);
11}
12
13/// Boxed derivative function signature.
14pub type SystemFn = Box<dyn Fn(f64, &[f64], &mut [f64])>;
15
16/// Generic model built from a closure.
17pub struct SimpleModel {
18    y0: Vec<f64>,
19    t_span: (f64, f64),
20    f: SystemFn,
21}
22
23impl SimpleModel {
24    /// Creates a model from initial state, time span, and derivative function.
25    pub fn new(y0: Vec<f64>, t_span: (f64, f64), f: SystemFn) -> Self {
26        Self { y0, t_span, f }
27    }
28}
29
30impl DynamicalSystem for SimpleModel {
31    fn dimension(&self) -> usize {
32        self.y0.len()
33    }
34    fn derivatives(&self, t: f64, state: &[f64], out: &mut [f64]) {
35        (self.f)(t, state, out);
36    }
37    fn initial_state(&self) -> Vec<f64> {
38        self.y0.clone()
39    }
40    fn time_span(&self) -> (f64, f64) {
41        self.t_span
42    }
43}
44
45/// Simple harmonic oscillator model.
46pub struct HarmonicOscillator {
47    /// Angular frequency.
48    pub omega: f64,
49    /// Initial displacement.
50    pub x0: f64,
51    /// Initial velocity.
52    pub v0: f64,
53    /// Integration time span.
54    pub t_span: (f64, f64),
55}
56
57impl DynamicalSystem for HarmonicOscillator {
58    fn dimension(&self) -> usize {
59        2
60    }
61    fn derivatives(&self, _t: f64, state: &[f64], out: &mut [f64]) {
62        out[0] = state[1];
63        out[1] = -self.omega * self.omega * state[0];
64    }
65    fn initial_state(&self) -> Vec<f64> {
66        vec![self.x0, self.v0]
67    }
68    fn time_span(&self) -> (f64, f64) {
69        self.t_span
70    }
71}
72
73/// Lotka-Volterra predator-prey model.
74pub struct LotkaVolterra {
75    /// Prey growth rate.
76    pub alpha: f64,
77    /// Predation rate.
78    pub beta: f64,
79    /// Predator reproduction rate per prey consumed.
80    pub delta: f64,
81    /// Predator mortality rate.
82    pub gamma: f64,
83    /// Initial prey population.
84    pub prey0: f64,
85    /// Initial predator population.
86    pub pred0: f64,
87    /// Integration time span.
88    pub t_span: (f64, f64),
89}
90
91impl DynamicalSystem for LotkaVolterra {
92    fn dimension(&self) -> usize {
93        2
94    }
95    fn derivatives(&self, _t: f64, state: &[f64], out: &mut [f64]) {
96        let x = state[0];
97        let y = state[1];
98        out[0] = self.alpha * x - self.beta * x * y;
99        out[1] = self.delta * x * y - self.gamma * y;
100    }
101    fn initial_state(&self) -> Vec<f64> {
102        vec![self.prey0, self.pred0]
103    }
104    fn time_span(&self) -> (f64, f64) {
105        self.t_span
106    }
107}