Skip to main content

fmi_sim/sim/fmi2/
mod.rs

1use arrow::array::RecordBatch;
2
3use fmi::fmi2::import::Fmi2Import;
4
5use crate::{
6    Error,
7    options::{CoSimulationOptions, ModelExchangeOptions},
8    sim::{
9        InputState, RecorderState, SimState, SimStateTrait,
10        traits::{ImportSchemaBuilder, SimInitialize},
11    },
12};
13
14use super::{SimStats, params::SimParams, traits::FmiSim};
15
16#[cfg(feature = "cs")]
17mod cs;
18mod io;
19#[cfg(feature = "me")]
20mod me;
21mod schema;
22
23impl FmiSim for Fmi2Import {
24    #[cfg(feature = "me")]
25    fn simulate_me(
26        &self,
27        options: &ModelExchangeOptions,
28        input_data: Option<RecordBatch>,
29    ) -> Result<(RecordBatch, SimStats), Error> {
30        use crate::sim::{solver, traits::SimMe};
31        use fmi::{fmi2::instance::InstanceME, traits::FmiImport};
32
33        let sim_params =
34            SimParams::new_from_options(&options.common, self.model_description(), true, false);
35
36        let start_values = self.parse_start_values(&options.common.initial_values)?;
37        let input_state = InputState::new(self, input_data)?;
38        let recorder_state: RecorderState<fmi::fmi2::instance::Instance<fmi::ME>> =
39            RecorderState::new(self, &sim_params);
40
41        let nx = self.model_description().num_states();
42        let nz = self.model_description().num_event_indicators();
43
44        let solver: solver::Euler = solver::Solver::<InstanceME>::new(
45            sim_params.start_time,
46            sim_params.tolerance.unwrap_or_default(),
47            nx,
48            nz,
49            (),
50        );
51
52        let mut sim_state =
53            SimState::<InstanceME>::new(self, sim_params, input_state, recorder_state)?;
54        sim_state.initialize(start_values, options.common.initial_fmu_state_file.as_ref())?;
55
56        let stats = sim_state.main_loop(solver)?;
57
58        Ok((sim_state.recorder_state.finish(), stats))
59    }
60
61    #[cfg(feature = "cs")]
62    fn simulate_cs(
63        &self,
64        options: &CoSimulationOptions,
65        input_data: Option<RecordBatch>,
66    ) -> Result<(RecordBatch, SimStats), Error> {
67        use fmi::{fmi2::instance::InstanceCS, traits::FmiImport};
68
69        let sim_params = SimParams::new_from_options(
70            &options.common,
71            self.model_description(),
72            options.event_mode_used,
73            options.early_return_allowed,
74        );
75
76        let start_values = self.parse_start_values(&options.common.initial_values)?;
77        let input_state = InputState::new(self, input_data)?;
78        let recorder_state = RecorderState::new(self, &sim_params);
79
80        let mut sim_state =
81            SimState::<InstanceCS>::new(self, sim_params, input_state, recorder_state)?;
82        sim_state.initialize(start_values, options.common.initial_fmu_state_file.as_ref())?;
83        let stats = sim_state.main_loop().map_err(fmi::Error::from)?;
84
85        Ok((sim_state.recorder_state.finish(), stats))
86    }
87}