Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 2 / 0 / 2
Functions: -% 0 / 1 / 1
Branches: -% 0 / 0 / 0

OMCompiler/Compiler/Util/FMI.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package FMI
37 " file: FMI.mo
38 package: FMI
39 description: This file contains FMI's import specific function, which are implemented in C."
40
41 protected import Flags;
42 protected import List;
43
44 public uniontype Info
45 record INFO
46 String fmiVersion;
47 Integer fmiType;
48 String fmiModelName;
49 String fmiModelIdentifier;
50 String fmiGuid;
51 String fmiDescription;
52 String fmiGenerationTool;
53 String fmiGenerationDateAndTime;
54 String fmiVariableNamingConvention;
55 list<Integer> fmiNumberOfContinuousStates;
56 list<Integer> fmiNumberOfEventIndicators;
57 end INFO;
58 end Info;
59
60 public uniontype TypeDefinitions
61 record ENUMERATIONTYPE
62 String name;
63 String description;
64 String quantity;
65 Integer min;
66 Integer max;
67 list<EnumerationItem> items;
68 end ENUMERATIONTYPE;
69 end TypeDefinitions;
70
71 public uniontype EnumerationItem
72 record ENUMERATIONITEM
73 String name;
74 String description;
75 end ENUMERATIONITEM;
76 end EnumerationItem;
77
78 public uniontype ExperimentAnnotation
79 record EXPERIMENTANNOTATION
80 Real fmiExperimentStartTime;
81 Real fmiExperimentStopTime;
82 Real fmiExperimentTolerance;
83 end EXPERIMENTANNOTATION;
84 end ExperimentAnnotation;
85
86 public uniontype ModelVariables
87 record REALVARIABLE
88 Integer instance;
89 String name;
90 String description;
91 String baseType;
92 String variability;
93 String causality;
94 Boolean hasStartValue;
95 Real startValue;
96 Boolean isFixed;
97 Real valueReference;
98 Integer x1Placement;
99 Integer x2Placement;
100 Integer y1Placement;
101 Integer y2Placement;
102 end REALVARIABLE;
103
104 record INTEGERVARIABLE
105 Integer instance;
106 String name;
107 String description;
108 String baseType;
109 String variability;
110 String causality;
111 Boolean hasStartValue;
112 Integer startValue;
113 Boolean isFixed;
114 Real valueReference;
115 Integer x1Placement;
116 Integer x2Placement;
117 Integer y1Placement;
118 Integer y2Placement;
119 end INTEGERVARIABLE;
120
121 record BOOLEANVARIABLE
122 Integer instance;
123 String name;
124 String description;
125 String baseType;
126 String variability;
127 String causality;
128 Boolean hasStartValue;
129 Boolean startValue;
130 Boolean isFixed;
131 Real valueReference;
132 Integer x1Placement;
133 Integer x2Placement;
134 Integer y1Placement;
135 Integer y2Placement;
136 end BOOLEANVARIABLE;
137
138 record STRINGVARIABLE
139 Integer instance;
140 String name;
141 String description;
142 String baseType;
143 String variability;
144 String causality;
145 Boolean hasStartValue;
146 String startValue;
147 Boolean isFixed;
148 Real valueReference;
149 Integer x1Placement;
150 Integer x2Placement;
151 Integer y1Placement;
152 Integer y2Placement;
153 end STRINGVARIABLE;
154
155 record ENUMERATIONVARIABLE
156 Integer instance;
157 String name;
158 String description;
159 String baseType;
160 String variability;
161 String causality;
162 Boolean hasStartValue;
163 Integer startValue;
164 Boolean isFixed;
165 Real valueReference;
166 Integer x1Placement;
167 Integer x2Placement;
168 Integer y1Placement;
169 Integer y2Placement;
170 end ENUMERATIONVARIABLE;
171
172 /* The records above describe an FMI 1.0 or 2.0 ScalarVariable. FMI 3.0 has a
173 different variable model and gets its own records, so that the import of the
174 older versions keeps working exactly as it did:
175
176 - there is no single Real and no single Integer any more. Float32 and
177 Float64 are separate elements, and so are Int8/16/32/64 and their
178 unsigned counterparts. Grouping them the way Modelica sees them keeps
179 one record per Modelica type; fmiType carries the element the FMU
180 actually used, which the wrapper needs to call the right setter.
181 - any variable can be an array, described by Dimension elements. An empty
182 dimensions list is a scalar.
183 - Binary and Clock have no counterpart in FMI 1.0 or 2.0 at all.
184 - value references are UInt32, so they are Integer here rather than the
185 Real the older records use. */
186
187 record FMI3REALVARIABLE "an FMI 3.0 Float32 or Float64 variable"
188 Integer instance;
189 String name;
190 String description;
191 String baseType;
192 String fmiType "Float32 or Float64";
193 String variability;
194 String causality;
195 Boolean hasStartValue;
196 list<Real> startValue "one element for a scalar, one per element for an array";
197 Boolean isFixed;
198 Integer valueReference;
199 list<Integer> dimensions "empty for a scalar";
200 Integer x1Placement;
201 Integer x2Placement;
202 Integer y1Placement;
203 Integer y2Placement;
204 end FMI3REALVARIABLE;
205
206 record FMI3INTEGERVARIABLE "an FMI 3.0 Int8/16/32/64 or UInt8/16/32/64 variable"
207 Integer instance;
208 String name;
209 String description;
210 String baseType;
211 String fmiType "Int8, UInt8, Int16, ... Int64, UInt64";
212 String variability;
213 String causality;
214 Boolean hasStartValue;
215 list<Integer> startValue;
216 Boolean isFixed;
217 Integer valueReference;
218 list<Integer> dimensions;
219 Integer x1Placement;
220 Integer x2Placement;
221 Integer y1Placement;
222 Integer y2Placement;
223 end FMI3INTEGERVARIABLE;
224
225 record FMI3BOOLEANVARIABLE "an FMI 3.0 Boolean variable"
226 Integer instance;
227 String name;
228 String description;
229 String baseType;
230 String fmiType;
231 String variability;
232 String causality;
233 Boolean hasStartValue;
234 list<Boolean> startValue;
235 Boolean isFixed;
236 Integer valueReference;
237 list<Integer> dimensions;
238 Integer x1Placement;
239 Integer x2Placement;
240 Integer y1Placement;
241 Integer y2Placement;
242 end FMI3BOOLEANVARIABLE;
243
244 record FMI3STRINGVARIABLE "an FMI 3.0 String variable"
245 Integer instance;
246 String name;
247 String description;
248 String baseType;
249 String fmiType;
250 String variability;
251 String causality;
252 Boolean hasStartValue;
253 list<String> startValue;
254 Boolean isFixed;
255 Integer valueReference;
256 list<Integer> dimensions;
257 Integer x1Placement;
258 Integer x2Placement;
259 Integer y1Placement;
260 Integer y2Placement;
261 end FMI3STRINGVARIABLE;
262
263 record FMI3BINARYVARIABLE "an FMI 3.0 Binary variable, which Modelica has no type for"
264 Integer instance;
265 String name;
266 String description;
267 String baseType;
268 String fmiType;
269 String variability;
270 String causality;
271 Boolean hasStartValue;
272 list<String> startValue "the start attribute, which FMI 3.0 writes as hex";
273 Boolean isFixed;
274 Integer valueReference;
275 list<Integer> dimensions;
276 String mimeType;
277 Integer maxSize "0 when the FMU did not say";
278 Integer x1Placement;
279 Integer x2Placement;
280 Integer y1Placement;
281 Integer y2Placement;
282 end FMI3BINARYVARIABLE;
283
284 record FMI3CLOCKVARIABLE "an FMI 3.0 Clock variable"
285 Integer instance;
286 String name;
287 String description;
288 String baseType;
289 String fmiType;
290 String variability;
291 String causality;
292 Boolean hasStartValue;
293 Boolean isFixed;
294 Integer valueReference;
295 list<Integer> dimensions;
296 String intervalVariability;
297 Real intervalDecimal "0.0 when the FMU did not say";
298 Boolean hasIntervalDecimal;
299 Integer x1Placement;
300 Integer x2Placement;
301 Integer y1Placement;
302 Integer y2Placement;
303 end FMI3CLOCKVARIABLE;
304
305 record FMI3ENUMERATIONVARIABLE "an FMI 3.0 Enumeration variable"
306 Integer instance;
307 String name;
308 String description;
309 String baseType;
310 String fmiType;
311 String variability;
312 String causality;
313 Boolean hasStartValue;
314 list<Integer> startValue;
315 Boolean isFixed;
316 Integer valueReference;
317 list<Integer> dimensions;
318 String declaredType;
319 Integer x1Placement;
320 Integer x2Placement;
321 Integer y1Placement;
322 Integer y2Placement;
323 end FMI3ENUMERATIONVARIABLE;
324 end ModelVariables;
325
326 public uniontype FmiImport
327 record FMIIMPORT
328 String platform;
329 String fmuFileName;
330 String fmuWorkingDirectory;
331 Integer fmiLogLevel;
332 Boolean fmiDebugOutput;
333 Option<Integer> fmiContext;
334 Option<Integer> fmiInstance;
335 Info fmiInfo;
336 list<TypeDefinitions> fmiTypeDefinitionsList;
337 ExperimentAnnotation fmiExperimentAnnotation;
338 Option<Integer> fmiModelVariablesInstance;
339 list<ModelVariables> fmiModelVariablesList;
340 Boolean generateInputConnectors;
341 Boolean generateOutputConnectors;
342 end FMIIMPORT;
343 end FmiImport;
344
345 public function getFMIModelIdentifier
346 input Info inFMIInfo;
347 output String fmiModelIdentifier;
348 algorithm
349 fmiModelIdentifier := match inFMIInfo
350 local
351 String modelIdentifier;
352 case INFO(fmiModelIdentifier = modelIdentifier) then modelIdentifier;
353 end match;
354 end getFMIModelIdentifier;
355
356 public function getFMIType
357 input Info inFMIInfo;
358 output String fmiType;
359 algorithm
360 fmiType := match inFMIInfo
361 case INFO(fmiVersion = "1.0", fmiType = 0) then "me";
362 case INFO(fmiVersion = "1.0", fmiType = 1) then "cs_st";
363 case INFO(fmiVersion = "1.0", fmiType = 2) then "cs_tool";
364 case INFO(fmiVersion = "2.0", fmiType = 1) then "me";
365 case INFO(fmiVersion = "2.0", fmiType = 2) then "cs";
366 case INFO(fmiVersion = "2.0", fmiType = 3) then "me_cs";
367 /* FMI 3.0 numbers its interface types as flags, so 2, 4 and 8 rather than the
368 1, 2, 3 of FMI 2.0; see fmi3_fmu_kind_enu_t. FMIImpl.c stores the one the
369 import picked, not the set the FMU offers. */
370 case INFO(fmiVersion = "3.0", fmiType = 2) then "me";
371 case INFO(fmiVersion = "3.0", fmiType = 4) then "cs";
372 case INFO(fmiVersion = "3.0", fmiType = 8) then "se";
373 else "";
374 end match;
375 end getFMIType;
376
377 public function getFMIVersion
378 input Info inFMIInfo;
379 output String fmiVersion;
380 algorithm
381 fmiVersion := match inFMIInfo
382 local
383 String version;
384 case INFO(fmiVersion = version) then version;
385 end match;
386 end getFMIVersion;
387
388 public function checkFMIVersion "Checks if the FMU version is supported."
389 input String inFMIVersion;
390 output Boolean success;
391 algorithm
392 success := match inFMIVersion
393 case "1.0" then true;
394 case "2.0" then true;
395 case "3.0" then true;
396 else false;
397 end match;
398 end checkFMIVersion;
399
400 public function isFMIVersion10 "Checks if the FMI version is 1.0."
401 input String inFMUVersion;
402 output Boolean success;
403 algorithm
404 success := match inFMUVersion
405 case "1.0" then true;
406 else false;
407 end match;
408 end isFMIVersion10;
409
410 public function isFMIVersion20 "Checks if the FMI version is 2.0."
411 input String inFMUVersion = getFMIVersionString();
412 output Boolean success;
413 algorithm
414 success := match inFMUVersion
415 case "2.0" then true;
416 else false;
417 end match;
418 end isFMIVersion20;
419
420 public function isFMIVersion30 "Checks if the FMI version is 3.0."
421 input String inFMUVersion = getFMIVersionString();
422 output Boolean success;
423 algorithm
424 success := match inFMUVersion
425 case "3.0" then true;
426 else false;
427 end match;
428 end isFMIVersion30;
429
430 public function getFMIVersionString "Returns the FMI version string."
431 output String version = Flags.getConfigString(Flags.FMI_VERSION);
432 end getFMIVersionString;
433
434 public function checkFMIType "Checks if the FMU type is supported."
435 input String inFMIType;
436 output Boolean success;
437 algorithm
438 success := match inFMIType
439 case "me" then true;
440 case "cs" then true;
441 case "me_cs" then true;
442 case "se" then true;
443 else false;
444 end match;
445 end checkFMIType;
446
447 public function canExportFMU
448 input String inFMUVersion;
449 input String inFMIType;
450 output Boolean success;
451 algorithm
452 success := match (inFMUVersion, inFMIType)
453 case ("1.0", "me") then true;
454 case ("2.0", "me") then true;
455 case ("2.0", "cs") then true;
456 case ("2.0", "me_cs") then true;
457 case ("3.0", "me") then true;
458 case ("3.0", "cs") then true;
459 case ("3.0", "me_cs") then true;
460 case ("3.0", "se") then true;
461 else false;
462 end match;
463 end canExportFMU;
464
465 public function isFMIMEType "Checks if FMU type is model exchange"
466 input String inFMIType;
467 output Boolean success;
468 algorithm
469 success := match inFMIType
470 case "me" then true;
471 case "me_cs" then true;
472 else false;
473 end match;
474 end isFMIMEType;
475
476 public function isFMICSType "Checks if FMU type is co-simulation"
477 input String inFMIType;
478 output Boolean success;
479 algorithm
480 success := match inFMIType
481 case "cs" then true;
482 case "me_cs" then true;
483 else false;
484 end match;
485 end isFMICSType;
486
487 public function isFMISEType "Checks if FMU type is scheduled execution (FMI 3.0 only)"
488 input String inFMIType;
489 output Boolean success;
490 algorithm
491 success := match inFMIType
492 case "se" then true;
493 else false;
494 end match;
495 end isFMISEType;
496
497 public function getEnumerationTypeFromTypes
498 input list<TypeDefinitions> inTypeDefinitionsList;
499 input String inBaseType;
500 output String outEnumerationType;
501 algorithm
502 outEnumerationType := match (inTypeDefinitionsList, inBaseType)
503 local
504 list<TypeDefinitions> xs;
505 String name_;
506 String baseType;
507 case ((ENUMERATIONTYPE(name = name_) :: _), baseType) guard stringEqual(name_, baseType)
508 then
509 name_;
510 case ((_ :: xs), baseType)
511 algorithm
512 17 name_ := getEnumerationTypeFromTypes(xs, baseType);
513 then
514 name_;
515 case ({}, _) then "";
516 end match;
517 end getEnumerationTypeFromTypes;
518
519 public function filterModelVariables
520 input list<ModelVariables> inModelVariables;
521 input String tipe;
522 input String variableCausality;
523 output list<ModelVariables> outModelVariables;
524 algorithm
525 120 outModelVariables := List.filter2OnTrue(inModelVariables, filterModelVariable, tipe, variableCausality);
526 end filterModelVariables;
527
528 protected function filterModelVariable
529 input ModelVariables modelVar;
530 input String tipe;
531 input String variableCausality;
532 output Boolean result;
533 algorithm
534 result := match modelVar
535 local
536 String causality;
537 case REALVARIABLE(causality=causality)
538 guard tipe == "real" and causality == variableCausality
539 then true;
540 case INTEGERVARIABLE(causality=causality)
541 guard tipe == "integer" and causality == variableCausality
542 then true;
543 case BOOLEANVARIABLE(causality=causality)
544 guard tipe == "boolean" and causality == variableCausality
545 then true;
546 case STRINGVARIABLE(causality=causality)
547 guard tipe == "string" and causality == variableCausality
548 then true;
549 /* The FMI 3.0 records answer to the same type names, so that a caller asking
550 for the real inputs of an FMU does not have to know which FMI version it
551 came from. Binary and Clock have no Modelica type and no name here; they
552 are filtered out until the wrapper knows what to do with them. */
553 case FMI3REALVARIABLE(causality=causality)
554 guard tipe == "real" and causality == variableCausality
555 then true;
556 case FMI3INTEGERVARIABLE(causality=causality)
557 guard tipe == "integer" and causality == variableCausality
558 then true;
559 case FMI3BOOLEANVARIABLE(causality=causality)
560 guard tipe == "boolean" and causality == variableCausality
561 then true;
562 case FMI3STRINGVARIABLE(causality=causality)
563 guard tipe == "string" and causality == variableCausality
564 then true;
565 else then false;
566 end match;
567 end filterModelVariable;
568
569 annotation(__OpenModelica_Interface="util");
570 end FMI;
571