Skip to main content

fmi_export/fmi3/instance/
impl_me.rs

1use super::ModelInstance;
2use crate::fmi3::{
3    Model, ModelGetSetStates, ModelState, UserModel,
4    traits::{Context, ModelGetSet, ModelLoggingCategory},
5};
6use fmi::fmi3::{Fmi3Error, Fmi3Res, ModelExchange};
7
8impl<M, C> ModelExchange for ModelInstance<M, C>
9where
10    M: Model + UserModel + ModelGetSet<M> + ModelGetSetStates,
11    C: Context<M>,
12{
13    fn enter_continuous_time_mode(&mut self) -> Result<Fmi3Res, Fmi3Error> {
14        self.context.log(
15            Fmi3Res::OK.into(),
16            M::LoggingCategory::trace_category(),
17            format_args!("enter_continuous_time_mode()"),
18        );
19        self.assert_instance_type(fmi::InterfaceType::ModelExchange)?;
20        match self.state {
21            ModelState::EventMode => {
22                self.state = ModelState::ContinuousTimeMode;
23                Ok(Fmi3Res::OK)
24            }
25            _ => {
26                self.context.log(
27                    Fmi3Error::Error.into(),
28                    M::LoggingCategory::default(),
29                    format_args!(
30                        "enter_continuous_time_mode() called in invalid state {:?}",
31                        self.state
32                    ),
33                );
34                Err(Fmi3Error::Error)
35            }
36        }
37    }
38
39    fn completed_integrator_step(
40        &mut self,
41        _no_set_fmu_state_prior: bool,
42        enter_event_mode: &mut bool,
43        terminate_simulation: &mut bool,
44    ) -> Result<Fmi3Res, Fmi3Error> {
45        self.assert_instance_type(fmi::InterfaceType::ModelExchange)?;
46        // Default implementation - no events, no termination
47        *enter_event_mode = false;
48        *terminate_simulation = false;
49        Ok(Fmi3Res::OK)
50    }
51
52    fn set_time(&mut self, time: f64) -> Result<Fmi3Res, Fmi3Error> {
53        self.context.log(
54            Fmi3Res::OK.into(),
55            M::LoggingCategory::trace_category(),
56            format_args!("set_time({})", time),
57        );
58        self.assert_instance_type(fmi::InterfaceType::ModelExchange)?;
59        self.context.set_time(time);
60        Ok(Fmi3Res::OK)
61    }
62
63    fn set_continuous_states(&mut self, states: &[f64]) -> Result<Fmi3Res, Fmi3Error> {
64        self.context.log(
65            Fmi3Res::OK.into(),
66            M::LoggingCategory::trace_category(),
67            format_args!("set_continuous_states({states:?})"),
68        );
69        self.assert_instance_type(fmi::InterfaceType::ModelExchange)?;
70        self.model.set_continuous_states(states)?;
71        self.is_dirty_values = true;
72        Ok(Fmi3Res::OK)
73    }
74
75    fn get_continuous_states(
76        &mut self,
77        continuous_states: &mut [f64],
78    ) -> Result<Fmi3Res, Fmi3Error> {
79        self.model.get_continuous_states(continuous_states)?;
80        self.context.log(
81            Fmi3Res::OK.into(),
82            M::LoggingCategory::trace_category(),
83            format_args!("get_continuous_states({continuous_states:?})"),
84        );
85        self.assert_instance_type(fmi::InterfaceType::ModelExchange)?;
86        Ok(Fmi3Res::OK)
87    }
88
89    fn get_continuous_state_derivatives(
90        &mut self,
91        derivatives: &mut [f64],
92    ) -> Result<Fmi3Res, Fmi3Error> {
93        // Ensure values are up to date before computing derivatives
94        if self.is_dirty_values {
95            self.model.calculate_values(&self.context)?;
96            self.is_dirty_values = false;
97        }
98        self.model.get_continuous_state_derivatives(derivatives)?;
99        self.context.log(
100            Fmi3Res::OK.into(),
101            M::LoggingCategory::trace_category(),
102            format_args!("get_continuous_state_derivatives({derivatives:?})"),
103        );
104        Ok(Fmi3Res::OK)
105    }
106
107    fn get_event_indicators(&mut self, indicators: &mut [f64]) -> Result<bool, Fmi3Error> {
108        let res = self.model.get_event_indicators(&self.context, indicators)?;
109        self.context.log(
110            Fmi3Res::OK.into(),
111            M::LoggingCategory::trace_category(),
112            format_args!("get_event_indicators({indicators:?})={res}"),
113        );
114        Ok(res)
115    }
116
117    fn get_nominals_of_continuous_states(
118        &mut self,
119        nominals: &mut [f64],
120    ) -> Result<Fmi3Res, Fmi3Error> {
121        // Default implementation: all nominals = 1.0
122        for nominal in nominals.iter_mut() {
123            *nominal = 1.0;
124        }
125        Ok(Fmi3Res::OK)
126    }
127
128    fn get_number_of_event_indicators(&mut self) -> Result<usize, Fmi3Error> {
129        Ok(M::MAX_EVENT_INDICATORS)
130    }
131
132    fn get_number_of_continuous_states(&mut self) -> Result<usize, Fmi3Error> {
133        Ok(M::NUM_STATES)
134    }
135}