1mod attribute_groups;
6mod interface_type;
7mod model_description;
8mod scalar_variable;
9mod r#type;
10mod unit;
11mod variable_dependency;
12
13use std::str::FromStr;
14
15pub use attribute_groups::*;
16pub use interface_type::*;
17pub use model_description::*;
18pub use scalar_variable::*;
19pub use r#type::*;
20pub use unit::*;
21pub use variable_dependency::*;
22
23use crate::{
24 Error,
25 variable_counts::{Counts, VariableCounts},
26};
27
28pub type ScalarVariableMap<'a> = std::collections::HashMap<String, &'a ScalarVariable>;
29pub type UnknownsTuple<'a> = (&'a ScalarVariable, Vec<&'a ScalarVariable>);
30
31impl FromStr for Fmi2ModelDescription {
32 type Err = Error;
33
34 fn from_str(s: &str) -> Result<Self, Self::Err> {
35 yaserde::de::from_str(s).map_err(Error::XmlParse)
36 }
37}
38
39impl crate::traits::DefaultExperiment for Fmi2ModelDescription {
40 fn start_time(&self) -> Option<f64> {
41 self.default_experiment.as_ref().map(|de| de.start_time)
42 }
43
44 fn stop_time(&self) -> Option<f64> {
45 self.default_experiment.as_ref().map(|de| de.stop_time)
46 }
47
48 fn tolerance(&self) -> Option<f64> {
49 self.default_experiment.as_ref().map(|de| de.tolerance)
50 }
51
52 fn step_size(&self) -> Option<f64> {
53 None
54 }
55}
56
57impl VariableCounts for ModelVariables {
58 fn model_counts(&self) -> Counts {
59 self.variables
60 .iter()
61 .fold(Counts::default(), |mut cts, sv| {
62 match sv.variability {
63 Variability::Constant => {
64 cts.num_constants += 1;
65 }
66 Variability::Continuous => {
67 cts.num_continuous += 1;
68 }
69 Variability::Discrete => {
70 cts.num_discrete += 1;
71 }
72 _ => {}
73 }
74 match sv.causality {
75 Causality::CalculatedParameter => {
76 cts.num_calculated_parameters += 1;
77 }
78 Causality::Parameter => {
79 cts.num_parameters += 1;
80 }
81 Causality::Input => {
82 cts.num_inputs += 1;
83 }
84 Causality::Output => {
85 cts.num_outputs += 1;
86 }
87 Causality::Local => {
88 cts.num_local += 1;
89 }
90 Causality::Independent => {
91 cts.num_independent += 1;
92 }
93 }
94 match sv.elem {
95 ScalarVariableElement::Real { .. } => {
96 cts.num_real_vars += 1;
97 }
98 ScalarVariableElement::Integer { .. } => {
99 cts.num_integer_vars += 1;
100 }
101 ScalarVariableElement::Enumeration => {
102 cts.num_enum_vars += 1;
103 }
104 ScalarVariableElement::Boolean { .. } => {
105 cts.num_bool_vars += 1;
106 }
107 ScalarVariableElement::String => {
108 cts.num_string_vars += 1;
109 }
110 }
111 cts
112 })
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_default_experiment() {
122 let s = r##"<DefaultExperiment stopTime="3.0" tolerance="0.0001"/>"##;
123 let x: DefaultExperiment = yaserde::de::from_str(s).unwrap();
124 assert_eq!(x.start_time, 0.0);
125 assert_eq!(x.stop_time, 3.0);
126 assert_eq!(x.tolerance, 0.0001);
127
128 let s = r#"<DefaultExperiment startTime = "0.20000000000000000e+00" stopTime = "1.50000000000000000e+00" tolerance = "0.0001"/>"#;
129 let x: DefaultExperiment = yaserde::de::from_str(s).unwrap();
130 assert_eq!(x.start_time, 0.2);
131 assert_eq!(x.stop_time, 1.5);
132 assert_eq!(x.tolerance, 0.0001);
133 }
134
135 #[test]
136 fn test_model_variables() {
137 let s = r##"
138 <ModelVariables>
139 <ScalarVariable name="x[1]" valueReference="0" initial="exact"> <Real/> </ScalarVariable> <!-- idex="5" -->
140 <ScalarVariable name="x[2]" valueReference="1" initial="exact"> <Real/> </ScalarVariable> <!-- index="6" -->
141 <ScalarVariable name="der(x[1])" valueReference="2"> <Real derivative="5"/> </ScalarVariable> <!-- index="7" -->
142 <ScalarVariable name="der(x[2])" valueReference="3"> <Real derivative="6"/> </ScalarVariable> <!-- index="8" -->
143 </ModelVariables>
144 "##;
145 let x: ModelVariables = yaserde::de::from_str(s).unwrap();
146 assert_eq!(x.variables.len(), 4);
147 assert!(
148 x.variables
149 .iter()
150 .map(|v| &v.name)
151 .zip(["x[1]", "x[2]", "der(x[1])", "der(x[2])"].iter())
152 .all(|(a, b)| a == b)
153 );
154 }
155
156 #[test]
157 fn test_model_structure() {
158 let s = r##"
159 <ModelStructure>
160 <Outputs>
161 <Unknown index="3" />
162 <Unknown index="4" />
163 </Outputs>
164 <Derivatives>
165 <Unknown index="7" />
166 <Unknown index="8" />
167 </Derivatives>
168 <InitialUnknowns>
169 <Unknown index="3" />
170 <Unknown index="4" />
171 <Unknown index="7" dependencies="5 2" />
172 <Unknown index="8" dependencies="5 6" />
173 </InitialUnknowns>
174 </ModelStructure>
175 "##;
176 let ms: ModelStructure = yaserde::de::from_str(s).unwrap();
177 assert_eq!(ms.outputs.unknowns.len(), 2);
178 assert_eq!(ms.outputs.unknowns[0].index, 3);
179 assert_eq!(ms.outputs.unknowns[1].index, 4);
180 assert_eq!(ms.derivatives.unknowns.len(), 2);
181 assert_eq!(ms.derivatives.unknowns[0].index, 7);
182 assert_eq!(ms.derivatives.unknowns[1].index, 8);
183 assert_eq!(ms.initial_unknowns.unknowns.len(), 4);
184 assert_eq!(ms.initial_unknowns.unknowns[0].index, 3);
185 assert_eq!(ms.initial_unknowns.unknowns[1].index, 4);
186 assert_eq!(ms.initial_unknowns.unknowns[2].index, 7);
187 assert_eq!(ms.initial_unknowns.unknowns[2].dependencies, vec! {5, 2});
188 assert_eq!(ms.initial_unknowns.unknowns[3].dependencies, vec! {5, 6});
189 }
190}