fmi_sim/sim/
traits.rs

1use std::path::Path;
2
3use arrow::{
4    array::{ArrayRef, RecordBatch},
5    datatypes::{Field, Schema},
6};
7use fmi::traits::{FmiImport, FmiInstance};
8
9use crate::{
10    Error,
11    options::{CoSimulationOptions, ModelExchangeOptions},
12};
13
14use super::{
15    RecorderState, SimStats,
16    interpolation::{Interpolate, PreLookup},
17    io::StartValues,
18    solver::Solver,
19};
20
21/// Interface for building the Arrow schema for the inputs and outputs of an FMU.
22pub trait ImportSchemaBuilder: FmiImport {
23    /// Build the schema for the inputs of the model.
24    fn inputs_schema(&self) -> Schema;
25    /// Build the schema for the outputs of the model.
26    fn outputs_schema(&self) -> Schema;
27    /// Build a list of (Field, ValueReference) for the continuous inputs.
28    fn continuous_inputs(&self) -> impl Iterator<Item = (Field, Self::ValueRef)> + '_;
29    /// Build a list of Schema column (index, ValueReference) for the discrete inputs.
30    fn discrete_inputs(&self) -> impl Iterator<Item = (Field, Self::ValueRef)> + '_;
31    /// Build a list of Schema column (index, ValueReference) for the outputs.
32    fn outputs(&self) -> impl Iterator<Item = (Field, Self::ValueRef)> + '_;
33    /// Parse a list of "var=value" strings.
34    ///
35    /// # Returns
36    /// A tuple of two lists of (ValueReference, Array) tuples. The first list contains any variable with
37    /// `Causality = StructuralParameter` and the second list contains regular parameters.
38    fn parse_start_values(
39        &self,
40        start_values: &[String],
41    ) -> anyhow::Result<StartValues<Self::ValueRef>>;
42}
43
44pub trait InstSetValues: FmiInstance {
45    fn set_array(
46        &mut self,
47        vrs: &[<Self as FmiInstance>::ValueRef],
48        values: &arrow::array::ArrayRef,
49    );
50    fn set_interpolated<I: Interpolate>(
51        &mut self,
52        vr: <Self as FmiInstance>::ValueRef,
53        pl: &PreLookup,
54        array: &ArrayRef,
55    ) -> anyhow::Result<()>;
56}
57
58pub trait InstRecordValues: FmiInstance + Sized {
59    fn record_outputs(
60        &mut self,
61        time: f64,
62        recorder: &mut RecorderState<Self>,
63    ) -> anyhow::Result<()>;
64}
65
66/// Interface for handling events in the simulation.
67/// Implemented by ME in fmi2 and ME+CS in fmi3.
68pub trait SimHandleEvents {
69    fn handle_events(
70        &mut self,
71        time: f64,
72        input_event: bool,
73        terminate_simulation: &mut bool,
74    ) -> Result<bool, Error>;
75}
76
77pub trait SimMe<Inst> {
78    /// Main loop of the model-exchange simulation
79    fn main_loop<S>(&mut self, solver_params: S::Params) -> Result<SimStats, Error>
80    where
81        S: Solver<Inst>;
82}
83
84pub trait SimDefaultInitialize {
85    fn default_initialize(&mut self) -> Result<(), Error>;
86}
87
88pub trait SimApplyStartValues<Inst: FmiInstance> {
89    fn apply_start_values(
90        &mut self,
91        start_values: &StartValues<Inst::ValueRef>,
92    ) -> Result<(), Error>;
93}
94
95pub trait SimInitialize<Inst: FmiInstance>: SimDefaultInitialize {
96    fn initialize<P: AsRef<Path>>(
97        &mut self,
98        start_values: StartValues<Inst::ValueRef>,
99        fmu_state_file: Option<P>,
100    ) -> Result<(), Error>;
101}
102
103pub trait FmiSim: FmiImport + ImportSchemaBuilder {
104    /// Simulate the model using Model Exchange.
105    #[cfg(feature = "me")]
106    fn simulate_me(
107        &self,
108        options: &ModelExchangeOptions,
109        input_data: Option<RecordBatch>,
110    ) -> Result<(RecordBatch, SimStats), Error>;
111
112    /// Simulate the model using Co-Simulation.
113    #[cfg(feature = "cs")]
114    fn simulate_cs(
115        &self,
116        options: &CoSimulationOptions,
117        input_data: Option<RecordBatch>,
118    ) -> Result<(RecordBatch, SimStats), Error>;
119}