fmi_schema/fmi3/
interface_type.rs1use crate::traits::FmiInterfaceType;
2
3use super::Annotations;
4
5#[derive(Default, PartialEq, Debug, hard_xml::XmlRead, hard_xml::XmlWrite)]
6#[xml(tag = "ModelExchange", strict(unknown_attribute, unknown_element))]
7pub struct Fmi3ModelExchange {
8 #[xml(child = "Annotations")]
9 pub annotations: Option<Annotations>,
10 #[xml(attr = "modelIdentifier")]
12 pub model_identifier: String,
13 #[xml(attr = "needsExecutionTool")]
15 pub needs_execution_tool: Option<bool>,
16 #[xml(attr = "canBeInstantiatedOnlyOncePerProcess")]
18 pub can_be_instantiated_only_once_per_process: Option<bool>,
19 #[xml(attr = "canGetAndSetFMUState")]
21 pub can_get_and_set_fmu_state: Option<bool>,
22 #[xml(attr = "canSerializeFMUState")]
24 pub can_serialize_fmu_state: Option<bool>,
25 #[xml(attr = "providesDirectionalDerivatives")]
27 pub provides_directional_derivatives: Option<bool>,
28 #[xml(attr = "providesAdjointDerivatives")]
30 pub provides_adjoint_derivatives: Option<bool>,
31 #[xml(attr = "providesPerElementDependencies")]
32 pub provides_per_element_dependencies: Option<bool>,
33 #[xml(attr = "needsCompletedIntegratorStep")]
34 pub needs_completed_integrator_step: Option<bool>,
35 #[xml(attr = "providesEvaluateDiscreteStates")]
36 pub provides_evaluate_discrete_states: Option<bool>,
37}
38
39#[derive(Default, PartialEq, Debug, hard_xml::XmlRead, hard_xml::XmlWrite)]
40#[xml(tag = "CoSimulation", strict(unknown_attribute, unknown_element))]
41pub struct Fmi3CoSimulation {
42 #[xml(child = "Annotations")]
43 pub annotations: Option<Annotations>,
44 #[xml(attr = "modelIdentifier")]
46 pub model_identifier: String,
47 #[xml(attr = "needsExecutionTool")]
49 pub needs_execution_tool: Option<bool>,
50 #[xml(attr = "canBeInstantiatedOnlyOncePerProcess")]
52 pub can_be_instantiated_only_once_per_process: Option<bool>,
53 #[xml(attr = "canGetAndSetFMUState")]
55 pub can_get_and_set_fmu_state: Option<bool>,
56 #[xml(attr = "canSerializeFMUState")]
58 pub can_serialize_fmu_state: Option<bool>,
59 #[xml(attr = "providesDirectionalDerivatives")]
61 pub provides_directional_derivatives: Option<bool>,
62 #[xml(attr = "providesAdjointDerivatives")]
64 pub provides_adjoint_derivatives: Option<bool>,
65 #[xml(attr = "providesPerElementDependencies")]
66 pub provides_per_element_dependencies: Option<bool>,
67 #[xml(attr = "canHandleVariableCommunicationStepSize")]
68 pub can_handle_variable_communication_step_size: Option<bool>,
69 #[xml(attr = "fixedInternalStepSize")]
70 pub fixed_internal_step_size: Option<f64>,
71 #[xml(attr = "maxOutputDerivativeOrder")]
72 pub max_output_derivative_order: Option<u32>,
73 #[xml(attr = "recommendedIntermediateInputSmoothness")]
74 pub recommended_intermediate_input_smoothness: Option<i32>,
75 #[xml(attr = "providesIntermediateUpdate")]
76 pub provides_intermediate_update: Option<bool>,
77 #[xml(attr = "mightReturnEarlyFromDoStep")]
78 pub might_return_early_from_do_step: Option<bool>,
79 #[xml(attr = "canReturnEarlyAfterIntermediateUpdate")]
80 pub can_return_early_after_intermediate_update: Option<bool>,
81 #[xml(attr = "hasEventMode")]
82 pub has_event_mode: Option<bool>,
83 #[xml(attr = "providesEvaluateDiscreteStates")]
84 pub provides_evaluate_discrete_states: Option<bool>,
85}
86
87#[derive(Default, PartialEq, Debug, hard_xml::XmlRead, hard_xml::XmlWrite)]
88#[xml(tag = "ScheduledExecution", strict(unknown_attribute, unknown_element))]
89pub struct Fmi3ScheduledExecution {
90 #[xml(child = "Annotations")]
91 pub annotations: Option<Annotations>,
92 #[xml(attr = "modelIdentifier")]
94 pub model_identifier: String,
95 #[xml(attr = "needsExecutionTool")]
97 pub needs_execution_tool: Option<bool>,
98 #[xml(attr = "canBeInstantiatedOnlyOncePerProcess")]
100 pub can_be_instantiated_only_once_per_process: Option<bool>,
101 #[xml(attr = "canGetAndSetFMUState")]
103 pub can_get_and_set_fmu_state: Option<bool>,
104 #[xml(attr = "canSerializeFMUState")]
106 pub can_serialize_fmu_state: Option<bool>,
107 #[xml(attr = "providesDirectionalDerivatives")]
109 pub provides_directional_derivatives: Option<bool>,
110 #[xml(attr = "providesAdjointDerivatives")]
112 pub provides_adjoint_derivatives: Option<bool>,
113 #[xml(attr = "providesPerElementDependencies")]
114 pub provides_per_element_dependencies: Option<bool>,
115}
116
117macro_rules! impl_fmi_interface_type {
119 ($name:ident) => {
120 impl FmiInterfaceType for $name {
121 fn model_identifier(&self) -> &str {
122 &self.model_identifier
123 }
124
125 fn needs_execution_tool(&self) -> Option<bool> {
126 self.needs_execution_tool
127 }
128
129 fn can_be_instantiated_only_once_per_process(&self) -> Option<bool> {
130 self.can_be_instantiated_only_once_per_process
131 }
132
133 fn can_get_and_set_fmu_state(&self) -> Option<bool> {
134 self.can_get_and_set_fmu_state
135 }
136
137 fn can_serialize_fmu_state(&self) -> Option<bool> {
138 self.can_serialize_fmu_state
139 }
140
141 fn provides_directional_derivatives(&self) -> Option<bool> {
142 self.provides_directional_derivatives
143 }
144
145 fn provides_adjoint_derivatives(&self) -> Option<bool> {
146 self.provides_adjoint_derivatives
147 }
148
149 fn provides_per_element_dependencies(&self) -> Option<bool> {
150 self.provides_per_element_dependencies
151 }
152 }
153 };
154}
155
156impl_fmi_interface_type!(Fmi3ModelExchange);
157impl_fmi_interface_type!(Fmi3CoSimulation);
158impl_fmi_interface_type!(Fmi3ScheduledExecution);
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use hard_xml::{XmlRead, XmlWrite};
164
165 #[test]
166 fn test_model_exchange_roundtrip() {
167 let xml = r#"<ModelExchange modelIdentifier="test" needsCompletedIntegratorStep="true" providesEvaluateDiscreteStates="false"/>"#;
168
169 let me = Fmi3ModelExchange::from_str(xml).unwrap();
170 assert_eq!(me.model_identifier, "test");
171 assert_eq!(me.needs_completed_integrator_step, Some(true));
172 assert_eq!(me.provides_evaluate_discrete_states, Some(false));
173
174 let xml_out = me.to_string().unwrap();
175 let me2 = Fmi3ModelExchange::from_str(&xml_out).unwrap();
176 assert_eq!(me, me2);
177 }
178
179 #[test]
180 fn test_co_simulation_attributes() {
181 let xml = r#"<CoSimulation modelIdentifier="test" canHandleVariableCommunicationStepSize="true" hasEventMode="false"/>"#;
182
183 let cs = Fmi3CoSimulation::from_str(xml).unwrap();
184 assert_eq!(cs.model_identifier, "test");
185 assert_eq!(cs.can_handle_variable_communication_step_size, Some(true));
186 assert_eq!(cs.has_event_mode, Some(false));
187 }
188
189 #[test]
190 fn test_scheduled_execution_basic() {
191 let xml = r#"<ScheduledExecution modelIdentifier="test"/>"#;
192
193 let se = Fmi3ScheduledExecution::from_str(xml).unwrap();
194 assert_eq!(se.model_identifier, "test");
195 }
196
197 #[test]
198 fn test_fmi_interface_type_trait() {
199 let me = Fmi3ModelExchange {
200 model_identifier: "test".to_string(),
201 needs_execution_tool: Some(true),
202 can_get_and_set_fmu_state: Some(false),
203 ..Default::default()
204 };
205
206 assert_eq!(me.model_identifier(), "test");
207 assert_eq!(me.needs_execution_tool(), Some(true));
208 assert_eq!(me.can_get_and_set_fmu_state(), Some(false));
209 }
210}