forked from DigitalDynamicsLab/fmu_tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FmuToolsCommon.h
277 lines (218 loc) · 9.92 KB
/
FmuToolsCommon.h
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#ifndef FMUTOOLSCOMMON_H
#define FMUTOOLSCOMMON_H
#include "fmi2_headers/fmi2FunctionTypes.h"
#include "fmi2_headers/fmi2Functions.h"
#include <stdexcept>
#include <string>
#include <typeindex>
#include <unordered_map>
#include <cassert>
/////////////////////////////////////////////////////////////////////////////////////////////////
enum class FmuMachineStateType{
anySettableState, // custom element, used to do checks
instantiated,
initializationMode,
stepCompleted, // only CoSimulation
stepInProgress, // only CoSimulation
stepFailed, // only CoSimulation
stepCanceled, // only CoSimulation
terminated,
error,
fatal,
eventMode, // only ModelExchange
continuousTimeMode // only ModelExchange
};
/// Class holding a reference to a single FMU variable
/// Note that this is retrieved from the information from the XML
class FmuVariable {
public:
enum class Type{
Real = 0, // numbering gives the order in which each type is printed in the modelDescription.xml
Integer = 1,
Boolean = 2,
String = 3,
Unknown = 4
};
enum class CausalityType{
parameter,
calculatedParameter,
input,
output,
local,
independent
};
enum class VariabilityType{
constant,
fixed,
tunable,
discrete,
continuous
};
enum class InitialType{
none,
exact,
approx,
calculated
};
FmuVariable() : FmuVariable("", FmuVariable::Type::Real){}
FmuVariable(const FmuVariable& other) {
type = other.type;
name = other.name;
valueReference = other.valueReference;
unitname = other.unitname;
causality = other.causality;
variability = other.variability;
initial = other.initial;
description = other.description;
has_start = other.has_start;
}
FmuVariable(
const std::string& _name,
FmuVariable::Type _type,
CausalityType _causality = CausalityType::local,
VariabilityType _variability = VariabilityType::continuous,
InitialType _initial = InitialType::none):
name(_name),
type(_type),
causality(_causality),
variability(_variability),
initial(_initial)
{
// set default value for "initial" if empty: reference FMIReference 2.0.2 - Section 2.2.7 Definition of Model Variables
// (A)
if((variability == VariabilityType::constant && (causality == CausalityType::output || causality == CausalityType::local)) ||
(variability == VariabilityType::fixed || variability == VariabilityType::tunable) && causality == CausalityType::parameter){
if (initial == InitialType::none)
initial = InitialType::exact;
else
if (initial != InitialType::exact)
throw std::runtime_error("initial not set properly.");
}
// (B)
else if((variability == VariabilityType::fixed || variability == VariabilityType::tunable) && (causality == CausalityType::calculatedParameter || causality == CausalityType::local)){
if (initial == InitialType::none)
initial = InitialType::calculated;
else
if (initial != InitialType::approx && initial != InitialType::calculated)
throw std::runtime_error("initial not set properly.");
}
// (C)
else if((variability == VariabilityType::discrete || variability == VariabilityType::continuous) && (causality == CausalityType::output || causality == CausalityType::local)){
if (initial == InitialType::none)
initial = InitialType::calculated;
}
// From FMI Reference
// (1) If causality = "independent", it is neither allowed to define a value for initial nor a value for start.
// (2) If causality = "input", it is not allowed to define a value for initial and a value for start must be defined.
// (3) [not relevant] If (C) and initial = "exact", then the variable is explicitly defined by its start value in Initialization Mode
if (causality == CausalityType::independent && initial != InitialType::none)
throw std::runtime_error("If causality = 'independent', it is neither allowed to define a value for initial nor a value for start.");
if (causality == CausalityType::input && initial != InitialType::none)
throw std::runtime_error("If causality = 'input', it is not allowed to define a value for initial and a value for start must be defined.");
// Incompatible variability/causality settings
// (a)
if (variability == VariabilityType::constant && (causality == CausalityType::parameter || causality == CausalityType::calculatedParameter || causality == CausalityType::input))
throw std::runtime_error("constants always have their value already set, thus their causality can be only 'output' or 'local'");
// (b)
if ((variability == VariabilityType::discrete || variability == VariabilityType::continuous) && (causality == CausalityType::parameter || causality == CausalityType::calculatedParameter))
throw std::runtime_error("parameters and calculatedParameters cannot be discrete nor continuous, since the latters mean that they could change over time");
// (c)
if (causality == CausalityType::independent && variability != VariabilityType::continuous)
throw std::runtime_error("For an 'independent' variable only variability = 'continuous' makes sense.");
// (d) + (e)
if (causality == CausalityType::input && (variability == VariabilityType::fixed || variability == VariabilityType::tunable))
throw std::runtime_error("A fixed or tunable 'input'|'output' have exactly the same properties as a fixed or tunable parameter. For simplicity, only fixed and tunable parameters|calculatedParameters shall be defined.");
}
// Copy assignment operator
FmuVariable& operator=(const FmuVariable& other) {
if (this == &other) {
return *this; // Self-assignment guard
}
type = other.type;
name = other.name;
valueReference = other.valueReference;
unitname = other.unitname;
causality = other.causality;
variability = other.variability;
initial = other.initial;
description = other.description;
has_start = other.has_start;
return *this;
}
virtual ~FmuVariable() {}
bool operator<(const FmuVariable& other) const {
return this->type != other.type ? this->type < other.type : this->valueReference < other.valueReference;
}
bool operator==(const FmuVariable& other) const {
// according to FMI Reference can exist two different variables with same type and same valueReference;
// they are called "alias" thus they should be allowed but not considered equal
return this->name == other.name;
}
bool HasStartVal() const {
return has_start;
}
bool IsSetAllowed(fmi2Type fmi_type, FmuMachineStateType fmu_machine_state) const {
if (fmi_type == fmi2Type::fmi2CoSimulation){
if (variability != VariabilityType::constant){
if (initial == InitialType::approx)
return fmu_machine_state == FmuMachineStateType::instantiated || fmu_machine_state == FmuMachineStateType::anySettableState;
else if (initial == InitialType::exact)
return fmu_machine_state == FmuMachineStateType::instantiated || fmu_machine_state == FmuMachineStateType::initializationMode || fmu_machine_state == FmuMachineStateType::anySettableState;
}
if (causality == CausalityType::input || (causality == CausalityType::parameter && variability == VariabilityType::tunable))
return fmu_machine_state == FmuMachineStateType::initializationMode || fmu_machine_state == FmuMachineStateType::stepCompleted || fmu_machine_state == FmuMachineStateType::anySettableState;
return false;
}
else
{
// TODO for ModelExchange
}
return false;
}
static std::string Type_toString(Type type){
switch (type)
{
case FmuVariable::Type::Real:
return "Real";
break;
case FmuVariable::Type::Integer:
return "Integer";
break;
case FmuVariable::Type::Boolean:
return "Boolean";
break;
case FmuVariable::Type::Unknown:
return "Unknown";
break;
case FmuVariable::Type::String:
return "String";
break;
default:
throw std::runtime_error("Type_toString: received bad type.");
break;
}
return "";
}
const inline std::string& GetName() const { return name;}
inline CausalityType GetCausality() const { return causality;}
inline VariabilityType GetVariability() const { return variability;}
inline InitialType GetInitial() const { return initial;}
const inline std::string& GetDescription() const { return description;}
void SetDescription(const std::string& _description) { description = _description;}
const inline fmi2ValueReference GetValueReference() const { return valueReference;}
void SetValueReference(fmi2ValueReference valref) { valueReference = valref;}
const inline std::string& GetUnitName() const { return unitname;}
void SetUnitName(const std::string& _unitname) { unitname = _unitname;}
Type GetType() const { return type;}
protected:
Type type = Type::Unknown;
std::string name;
fmi2ValueReference valueReference = 0;
std::string unitname = "1";
CausalityType causality;
VariabilityType variability;
InitialType initial;
std::string description = "";
bool has_start = false;
};
#endif