fmi_sim/sim/solver/
euler.rs1use super::{Model, Solver, SolverError};
2
3pub struct Euler {
4 time: f64,
6 x: Vec<f64>,
8 dx: Vec<f64>,
10 z: Vec<f64>,
12 prez: Vec<f64>,
14}
15
16impl<M: Model> Solver<M> for Euler {
17 type Params = ();
18
19 fn new(start_time: f64, _tol: f64, nx: usize, nz: usize, _solver_params: Self::Params) -> Self {
20 Self {
21 time: start_time,
22 x: vec![0.0; nx],
23 dx: vec![0.0; nx],
24 z: vec![0.0; nz],
25 prez: vec![0.0; nz],
26 }
27 }
28
29 fn step(&mut self, model: &mut M, next_time: f64) -> Result<(f64, bool), SolverError> {
30 let dt = next_time - self.time;
31
32 if !self.x.is_empty() {
33 model.get_continuous_states(&mut self.x);
34 model.get_continuous_state_derivatives(&mut self.dx);
35
36 for i in 0..self.x.len() {
37 self.x[i] += self.dx[i] * dt;
38 }
39
40 model.set_continuous_states(&self.x);
41 }
42
43 let mut state_event = false;
44
45 if !self.z.is_empty() {
46 model.get_event_indicators(&mut self.z);
47
48 self.z
49 .iter()
50 .zip(self.prez.iter_mut())
51 .for_each(|(z, prez)| {
52 let cross_pos = *prez <= 0.0 && *z > 0.0;
54 let cross_neg = *prez > 0.0 && *z <= 0.0;
56 state_event = cross_pos || cross_neg || state_event;
57 *prez = *z;
58 });
59 }
60 self.time = next_time;
61
62 Ok((self.time, state_event))
63 }
64
65 fn reset(&mut self, model: &mut M, _time: f64) -> Result<(), SolverError> {
66 if !self.z.is_empty() {
67 model.get_event_indicators(&mut self.z);
68 }
69 Ok(())
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 struct SimpleModel;
78
79 impl Model for SimpleModel {
80 fn get_continuous_states(&mut self, x: &mut [f64]) {
81 x[0] = 0.0;
82 }
83
84 fn set_continuous_states(&mut self, states: &[f64]) {
85 assert_eq!(states[0], 1.0);
86 }
87
88 fn get_continuous_state_derivatives(&mut self, dx: &mut [f64]) {
89 dx[0] = 1.0;
90 }
91
92 fn get_event_indicators(&mut self, z: &mut [f64]) {
93 z[0] = 0.0;
94 }
95 }
96
97 #[test]
98 fn test_euler() {
99 let mut euler = <Euler as Solver<SimpleModel>>::new(0.0, 1e-6, 1, 1, ());
100 let (time, state_event) = euler.step(&mut SimpleModel, 1.0).unwrap();
101 assert_eq!(time, 1.0);
102 assert!(!state_event);
103 }
104}