1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use std::{fmt::Display, str::FromStr};
use crate::utils::AttrList;
/// Dependency of scalar Unknown from Knowns in Continuous-Time and Event Mode (ModelExchange), and
/// at Communication Points (CoSimulation): Unknown=f(Known_1, Known_2, ...).
/// The Knowns are "inputs", "continuous states" and "independent variable" (usually time)".
#[derive(Default, PartialEq, Debug)]
pub struct Fmi2VariableDependency {
/// ScalarVariable index of Unknown
pub index: u32,
/// Defines the dependency of the Unknown (directly or indirectly via auxiliary variables) on
/// the Knowns in Continuous-Time and Event Mode ([`super::ModelExchange`]) and at
/// Communication Points ([`super::CoSimulation`]).
///
/// If not present, it must be assumed that the Unknown depends on all Knowns. If present as
/// empty list, the Unknown depends on none of the Knowns. Otherwise the Unknown depends on
/// the Knowns defined by the given [`super::ScalarVariable`] indices. The indices are
/// ordered according to size, starting with the smallest index.
pub dependencies: Vec<u32>,
/// If not present, it must be assumed that the Unknown depends on the Knowns without a
/// particular structure. Otherwise, the corresponding Known v enters the equation as:
///
/// * [`DependenciesKind::Dependent`]: no particular structure, f(v)
/// * [`DependenciesKind::Constant`]: constant factor, c*v (only for Real variablse)
/// * [`DependenciesKind::Fixed`]: fixed factor, p*v (only for Real variables)
/// * [`DependenciesKind::Tunable`]: tunable factor, p*v (only for Real variables)
/// * [`DependenciesKind::Discrete`]: discrete factor, d*v (only for Real variables)
///
/// If [`Self::dependencies_kind`] is present, [`Self::dependencies`] must be present and must
/// have the same number of list elements.
pub dependencies_kind: Vec<DependenciesKind>,
}
// Custom implementation of XmlRead and XmlWrite for Fmi2VariableDependency to allow multiple tags.
impl<'__input> ::hard_xml::XmlRead<'__input> for Fmi2VariableDependency {
fn from_reader(reader: &mut ::hard_xml::XmlReader<'__input>) -> ::hard_xml::XmlResult<Self> {
use ::hard_xml::XmlError;
use ::hard_xml::xmlparser::{ElementEnd, Token};
let mut __self_index = None;
let mut __self_dependencies = Vec::new();
let mut __self_dependencies_kind = Vec::new();
let tag = reader
.find_element_start(None)?
.expect("Expected start element");
let _ = reader.next().unwrap()?;
while let Some((__key, __value)) = reader.find_attribute()? {
match __key {
"index" => {
__self_index = Some(
<u32 as std::str::FromStr>::from_str(&__value)
.map_err(|e| XmlError::FromStr(e.into()))?,
);
}
"dependencies" => {
let attr_list = <AttrList<u32> as std::str::FromStr>::from_str(&__value)
.map_err(|e| XmlError::FromStr(e.into()))?;
__self_dependencies = attr_list.0;
}
"dependenciesKind" => {
let attr_list =
<AttrList<DependenciesKind> as std::str::FromStr>::from_str(&__value)
.map_err(|e| XmlError::FromStr(e.into()))?;
__self_dependencies_kind = attr_list.0;
}
key => {
return Err(XmlError::UnknownField {
name: "Fmi2VariableDependency".to_owned(),
field: key.to_owned(),
});
}
}
}
if let Token::ElementEnd {
end: ElementEnd::Empty,
..
} = reader.next().unwrap()?
{
return Ok(Fmi2VariableDependency {
index: __self_index.ok_or(XmlError::MissingField {
name: "Fmi2VariableDependency".to_owned(),
field: "index".to_owned(),
})?,
dependencies: __self_dependencies,
dependencies_kind: __self_dependencies_kind,
});
}
if let Some(__tag) = reader.find_element_start(Some(tag))? {
return Err(XmlError::UnknownField {
name: "Fmi2VariableDependency".to_owned(),
field: __tag.to_owned(),
});
}
Ok(Fmi2VariableDependency {
index: __self_index.ok_or(XmlError::MissingField {
name: "Fmi2VariableDependency".to_owned(),
field: "index".to_owned(),
})?,
dependencies: __self_dependencies,
dependencies_kind: __self_dependencies_kind,
})
}
}
impl ::hard_xml::XmlWrite for Fmi2VariableDependency {
fn to_writer<W: std::io::Write>(
&self,
writer: &mut ::hard_xml::XmlWriter<W>,
) -> ::hard_xml::XmlResult<()> {
writer.write_element_start("Unknown")?;
writer.write_attribute("index", &format!("{}", self.index))?;
if !self.dependencies.is_empty() {
writer.write_attribute(
"dependencies",
&format!("{}", AttrList(self.dependencies.clone())),
)?;
}
if !self.dependencies_kind.is_empty() {
writer.write_attribute(
"dependenciesKind",
&format!("{}", AttrList(self.dependencies_kind.clone())),
)?;
}
writer.write_element_end_empty()?;
Ok(())
}
}
#[derive(Clone, Default, PartialEq, Debug)]
pub enum DependenciesKind {
#[default]
Dependent,
Constant,
Fixed,
Tunable,
Discrete,
}
impl FromStr for DependenciesKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"dependent" => Ok(DependenciesKind::Dependent),
"constant" => Ok(DependenciesKind::Constant),
"fixed" => Ok(DependenciesKind::Fixed),
"tunable" => Ok(DependenciesKind::Tunable),
"discrete" => Ok(DependenciesKind::Discrete),
_ => Err(format!("Invalid DependenciesKind: {}", s)),
}
}
}
impl Display for DependenciesKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
DependenciesKind::Dependent => "dependent",
DependenciesKind::Constant => "constant",
DependenciesKind::Fixed => "fixed",
DependenciesKind::Tunable => "tunable",
DependenciesKind::Discrete => "discrete",
};
write!(f, "{}", s)
}
}