1use fmi::traits::{FmiEventHandler, FmiInstance, FmiModelExchange};
4
5use crate::Error;
6
7use super::{
8 SimState, SimStats,
9 interpolation::Linear,
10 solver::Solver,
11 traits::{InstRecordValues, InstSetValues, SimHandleEvents, SimMe},
12};
13
14impl<Inst> SimMe<Inst> for SimState<Inst>
15where
16 Inst: FmiInstance + FmiModelExchange + InstSetValues + InstRecordValues + FmiEventHandler,
17{
18 fn main_loop<S>(&mut self, mut solver: S) -> Result<SimStats, Error>
19 where
20 S: Solver<Inst>,
21 {
22 let mut stats = SimStats::default();
23 self.inst.enter_continuous_time_mode().map_err(Into::into)?;
24
25 let mut time = self.sim_params.start_time;
26
27 loop {
28 self.inst.record_outputs(time, &mut self.recorder_state)?;
29
30 if time >= self.sim_params.stop_time {
31 break;
32 }
33
34 let next_regular_point = self.sim_params.start_time
36 + (stats.num_steps + 1) as f64 * self.sim_params.output_interval;
37 let next_input_event_time = self.input_state.next_input_event(time);
38
39 let input_event = next_regular_point >= next_input_event_time;
40 let time_event = next_regular_point >= self.next_event_time();
41
42 let next_communication_point = if input_event || time_event {
44 next_input_event_time.min(self.next_event_time())
45 } else {
46 next_regular_point
47 };
48
49 let (time_reached, state_event) =
50 solver.step(&mut self.inst, next_communication_point)?;
51 time = time_reached;
52
53 self.inst.set_time(time).map_err(Into::into)?;
54
55 self.input_state
56 .apply_input::<Linear>(time, &mut self.inst, false, true, false)?;
57
58 if time == next_regular_point {
59 stats.num_steps += 1;
60 }
61
62 let mut step_event = false;
63 let mut terminate = false;
64
65 self.inst
66 .completed_integrator_step(true, &mut step_event, &mut terminate)
67 .map_err(Into::into)?;
68
69 if terminate {
70 log::info!("Termination requested by FMU");
71 break;
72 }
73
74 if input_event || time_event || state_event || step_event {
75 log::trace!(
76 "Event encountered at t = {time}. [Input: {input_event}, Time: {time_event}, State: {state_event}, Step: {step_event}]"
77 );
78 stats.num_events += 1;
79 let (reset_solver, terminate) = self.handle_events(time, input_event)?;
80
81 if terminate {
82 break;
83 }
84
85 self.inst.enter_continuous_time_mode().map_err(Into::into)?;
86
87 if reset_solver {
88 solver.reset(&mut self.inst, time)?;
89 }
90 }
91 }
92
93 self.inst.terminate().map_err(Into::into)?;
94
95 Ok(stats)
96 }
97}