Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 71.5% 171 / 0 / 239
Functions: -% 0 / 1 / 1
Branches: 63.1% 159 / 0 / 252

OMCompiler/Compiler/NSimCode/NSimVar.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 NSimVar
37 "file: NSimVar.mo
38 package: NSimVar
39 description: This file contains the data types and functions for variables
40 in simulation code phase.
41 "
42 protected
43 // OF imports
44 import DAE;
45 import SCode;
46
47 // NF imports
48 import NFBackendExtension.{BackendInfo, VariableAttributes, VariableKind};
49 import Binding = NFBinding;
50 import ComponentRef = NFComponentRef;
51 import Dimension = NFDimension;
52 import Expression = NFExpression;
53 import NFInstNode.InstNode;
54 import Operator = NFOperator;
55 import Prefixes = NFPrefixes;
56 import SimplifyExp = NFSimplifyExp;
57 import Type = NFType;
58 import Variable = NFVariable;
59 import MetaModelica.Dangerous.listReverseInPlace;
60 import NBVariable.VariablePointers;
61
62 // Old Backend imports
63 import OldBackendDAE = BackendDAE;
64
65 // Backend imports
66 import BVariable = NBVariable;
67 import NBEquation.Equation;
68 import NBEvents.{EventInfo, Condition, MathEvent};
69 import NBPartition.Partition;
70 import Slice = NBSlice;
71 import StrongComponent = NBStrongComponent;
72
73 // Old Simcode imports
74 import OldSimCode = SimCode;
75 import OldSimCodeVar = SimCodeVar;
76
77 // SimCode imports
78 import SimCode = NSimCode;
79 import NSimCode.SimCodeIndices;
80
81 // Util imports
82 import Config;
83 import Error;
84 import Pointer;
85 import PointerWeak;
86 import StringUtil;
87 import Util;
88
89 public
90 type ConvertEntry = tuple<SimVar, OldSimCodeVar.SimVar>;
91 type ConvertMemo = UnorderedMap<ComponentRef, ConvertEntry> "SimVar -> old SimVar conversions already made";
92
93 uniontype SimVar "Information about a variable in a Modelica model."
94 record SIMVAR
95 ComponentRef name;
96 VariableKind varKind;
97 String comment;
98 String unit;
99 String displayUnit;
100 Integer index;
101 Option<Expression> min;
102 Option<Expression> max;
103 Option<Expression> start;
104 Option<Expression> nominal;
105 Boolean isFixed;
106 Type type_;
107 Boolean isDiscrete;
108 Option<ComponentRef> arrayCref "the name of the array if this variable is the first in that array";
109 Alias aliasvar;
110 SourceInfo info;
111 Option<Causality> causality;
112 Option<Integer> variable_index "valueReference";
113 Option<Integer> fmi_index "index of variable in modelDescription.xml";
114 list<Expression> numArrayElement;
115 Boolean isValueChangeable;
116 Boolean isProtected;
117 Boolean hideResult;
118 Boolean isEncrypted;
119 Option<array<Integer>> inputIndex;
120 Option<String> matrixName "if the varibale is a jacobian var, this is the corresponding matrix";
121 Option<Variability> variability "FMI-2.0 variabilty attribute";
122 Option<Initial> initial_ "FMI-2.0 initial attribute";
123 Option<ComponentRef> exportVar "variables will only be exported to the modelDescription.xml if this attribute is SOME(cref) and this cref is only used in ModelDescription.xml for FMI-2.0 export";
124 Boolean isConnectorFlow "true if the variable is a flow connector member (FMI 3.0 terminal variableKind inflow/outflow)";
125 end SIMVAR;
126
127 function toString
128 input SimVar var;
129 input output String str = "";
130 algorithm
131 250 str := str + "(" + intString(var.index) + ")" + VariableKind.toString(var.varKind)
132 + " (" + intString(SimVar.size(var)) + ") " + Type.toString(var.type_) + " " + ComponentRef.toString(var.name);
133
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 250 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 210 times.
250 if isSome(var.start) then
134 40 str := str + " = " + Expression.toString(Util.getOption(var.start));
135 end if;
136 end toString;
137
138 function listToString
139 input list<SimVar> var_lst;
140 input output String str = "";
141 input Boolean printAlias = false;
142 algorithm
143
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 55 times.
72 if not listEmpty(var_lst) then
144 17 str := StringUtil.headline_4(str + " (" + intString(listLength(var_lst)) + ")");
145
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 17 times.
162 for var in var_lst loop
146 145 str := str + toString(var, " ");
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145 times.
145 str := if printAlias then str + " " + Alias.toString(var.aliasvar) + "\n" else str + "\n";
148 end for;
149 17 str := str + "\n";
150 else
151 str := "";
152 end if;
153 end listToString;
154
155 function create
156 input Variable var;
157 output SimVar simVar;
158 input Integer uniqueIndex;
159 input Integer typeIndex;
160 input Alias alias = Alias.NO_ALIAS();
161 algorithm
162 simVar := match var
163 local
164 VariableKind varKind;
165 String comment, unit, displayUnit;
166 Option<Expression> min;
167 Option<Expression> max;
168 Option<Expression> start;
169 Option<Expression> nominal;
170 Boolean isFixed, isDiscrete, isProtected, isValueChangeable;
171 Causality causality;
172 SimVar result;
173
174 case Variable.VARIABLE() algorithm
175 21434 comment := parseComment(var.comment);
176 21434 (varKind, unit, displayUnit, min, max, start, nominal, isFixed, isDiscrete, isProtected)
177 := parseAttributes(var.backendinfo);
178 // for parameters the binding supersedes the start value if it exists and is constant
179 // ToDo: also for other cases? (constant, struct param ...)
180 21434 (start, isValueChangeable, causality) := parseBinding(start, var);
181
14/16
✓ Branch 1 taken 456 times.
✓ Branch 2 taken 21434 times.
✓ Branch 3 taken 456 times.
✓ Branch 4 taken 21434 times.
✓ Branch 7 taken 20520 times.
✓ Branch 8 taken 914 times.
✓ Branch 11 taken 21434 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 21434 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 19147 times.
✓ Branch 16 taken 2287 times.
✓ Branch 19 taken 13710 times.
✓ Branch 20 taken 7724 times.
✓ Branch 21 taken 14522 times.
✓ Branch 22 taken 6912 times.
134944 result := SIMVAR(
182 name = var.name,
183 varKind = varKind,
184 comment = comment,
185 unit = unit,
186 displayUnit = displayUnit,
187 index = typeIndex,
188 min = min,
189 max = max,
190 start = start,
191 nominal = nominal,
192 isFixed = isFixed,
193 type_ = var.ty,
194 isDiscrete = isDiscrete,
195 arrayCref = ComponentRef.getArrayCrefOpt(var.name),
196 aliasvar = alias,
197 info = var.info,
198 causality = SOME(causality),
199 variable_index = SOME(uniqueIndex),
200 fmi_index = SOME(typeIndex),
201 // dimension sizes (row-major); empty for scalars. Used for FMI array variables.
202 numArrayElement = list(Dimension.sizeExp(dim) for dim in Type.arrayDims(var.ty)),
203 isValueChangeable = isValueChangeable,
204 isProtected = isProtected,
205 hideResult = var.backendinfo.annotations.hideResult,
206 isEncrypted = NFVariable.isEncrypted(var),
207 inputIndex = NONE(),
208 matrixName = NONE(),
209 variability = NONE(),
210 initial_ = NONE(),
211 exportVar = SOME(var.name),
212 isConnectorFlow = Variable.isFlow(var)
213 );
214 then result;
215
216 else algorithm
217 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for variable " + ComponentRef.toString(var.name) + "."});
218 ✗ then fail();
219
220 end match;
221 end create;
222
223 function traverseCreate
224 input output Variable var;
225 input Pointer<list<SimVar>> acc;
226 input Pointer<SimCode.SimCodeIndices> indices_ptr;
227 input VarType varType = VarType.SIMULATION;
228 protected
229 SimCode.SimCodeIndices simCodeIndices = Pointer.access(indices_ptr);
230 algorithm
231 () := match varType
232
233 case VarType.SIMULATION algorithm
234 ✗ Pointer.update(acc, create(var, simCodeIndices.uniqueIndex, simCodeIndices.realVarIndex) :: Pointer.access(acc));
235 ✗ simCodeIndices.uniqueIndex := simCodeIndices.uniqueIndex + 1;
236 ✗ simCodeIndices.realVarIndex := simCodeIndices.realVarIndex + 1;
237 then ();
238
239 case VarType.PARAMETER algorithm
240 ✗ Pointer.update(acc, create(var, simCodeIndices.uniqueIndex, simCodeIndices.realParamIndex) :: Pointer.access(acc));
241 ✗ simCodeIndices.uniqueIndex := simCodeIndices.uniqueIndex + 1;
242 ✗ simCodeIndices.realParamIndex := simCodeIndices.realParamIndex + 1;
243 then ();
244
245 case VarType.ALIAS algorithm
246 ✗ Pointer.update(acc, create(var, simCodeIndices.uniqueIndex, simCodeIndices.realAliasIndex, Alias.fromBinding(var.binding)) :: Pointer.access(acc));
247 ✗ simCodeIndices.uniqueIndex := simCodeIndices.uniqueIndex + 1;
248 ✗ simCodeIndices.realAliasIndex := simCodeIndices.realAliasIndex + 1;
249 then ();
250
251 case VarType.RESIDUAL algorithm
252 2 Pointer.update(acc, create(var, simCodeIndices.uniqueIndex, simCodeIndices.residualIndex) :: Pointer.access(acc));
253 1 simCodeIndices.uniqueIndex := simCodeIndices.uniqueIndex + 1;
254 1 simCodeIndices.residualIndex := simCodeIndices.residualIndex + 1;
255 then ();
256
257 case VarType.EXTERNAL_OBJECT algorithm
258 ✗ Pointer.update(acc, create(var, simCodeIndices.uniqueIndex, simCodeIndices.extObjIndex) :: Pointer.access(acc));
259 ✗ simCodeIndices.uniqueIndex := simCodeIndices.uniqueIndex + 1;
260 ✗ simCodeIndices.extObjIndex := simCodeIndices.extObjIndex + 1;
261 then ();
262
263 else algorithm
264 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for variable " + ComponentRef.toString(var.name) + "."});
265 ✗ then fail();
266
267 end match;
268 1 Pointer.update(indices_ptr, simCodeIndices);
269 end traverseCreate;
270
271 function createList
272 "SimVars for scalar variables in list order, with running indices."
273 input list<Pointer<Variable>> vars;
274 input VarType varType;
275 output list<SimVar> simVars = {};
276 input output SimCode.SimCodeIndices indices;
277 input Boolean elementIndex = false "the index of an array variable is the position of its first element";
278 protected
279 Integer uniq = indices.uniqueIndex;
280 Integer idx = getTypeIndex(indices, varType);
281 Variable var;
282 algorithm
283
2/2
✓ Branch 0 taken 12320 times.
✓ Branch 1 taken 1817 times.
14137 for var_ptr in vars loop
284 12320 var := Pointer.access(var_ptr);
285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12320 times.
12320 simVars := create(var, uniq, idx, if varType == VarType.ALIAS then Alias.fromBinding(var.binding) else Alias.NO_ALIAS()) :: simVars;
286 12320 uniq := uniq + 1;
287
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 12019 times.
12320 idx := idx + (if elementIndex then Variable.size(var) else 1);
288 end for;
289 1817 simVars := listReverseInPlace(simVars);
290 1817 indices.uniqueIndex := uniq;
291 1817 indices := setTypeIndex(indices, varType, idx);
292 end createList;
293
294 function createListsByType
295 "One SimVar list per basic type (real, integer, boolean, string, enumeration),
296 each with its own running index."
297 input list<Pointer<Variable>> vars;
298 input VarType varType;
299 output list<list<SimVar>> simVars;
300 input output SimCode.SimCodeIndices indices;
301 protected
302 Integer uniq = indices.uniqueIndex;
303 Integer real_idx, int_idx, bool_idx, string_idx, enum_idx;
304 list<SimVar> real_lst = {}, int_lst = {}, bool_lst = {}, string_lst = {}, enum_lst = {};
305 Variable var;
306 Alias alias;
307 algorithm
308 1316 (real_idx, int_idx, bool_idx, string_idx, enum_idx) := getTypeIndices(indices, varType);
309
2/2
✓ Branch 0 taken 9114 times.
✓ Branch 1 taken 1316 times.
10430 for var_ptr in vars loop
310 9114 var := Pointer.access(var_ptr);
311
2/2
✓ Branch 0 taken 1488 times.
✓ Branch 1 taken 7626 times.
9114 alias := if varType == VarType.ALIAS then Alias.fromBinding(var.binding) else Alias.NO_ALIAS();
312 () := match Type.arrayElementType(var.ty)
313 case Type.REAL() algorithm
314 7572 real_lst := create(var, uniq, real_idx, alias) :: real_lst;
315 7572 real_idx := real_idx + 1;
316 7572 uniq := uniq + 1;
317 then ();
318
319 case Type.INTEGER() algorithm
320 423 int_lst := create(var, uniq, int_idx, alias) :: int_lst;
321 423 int_idx := int_idx + 1;
322 423 uniq := uniq + 1;
323 then ();
324
325 case Type.BOOLEAN() algorithm
326 1018 bool_lst := create(var, uniq, bool_idx, alias) :: bool_lst;
327 1018 bool_idx := bool_idx + 1;
328 1018 uniq := uniq + 1;
329 then ();
330
331 case Type.STRING() algorithm
332 30 string_lst := create(var, uniq, string_idx, alias) :: string_lst;
333 30 string_idx := string_idx + 1;
334 30 uniq := uniq + 1;
335 then ();
336
337 case Type.ENUMERATION() algorithm
338 70 enum_lst := create(var, uniq, enum_idx, alias) :: enum_lst;
339 70 enum_idx := enum_idx + 1;
340 70 uniq := uniq + 1;
341 then ();
342
343 // clock variables do not exist anymore
344 case Type.CLOCK() then ();
345
346 else algorithm
347 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unhandled Variable " + ComponentRef.toString(var.name) + "."});
348 ✗ then fail();
349 end match;
350 end for;
351 6580 simVars := {listReverseInPlace(real_lst), listReverseInPlace(int_lst), listReverseInPlace(bool_lst),
352 listReverseInPlace(string_lst), listReverseInPlace(enum_lst)};
353 1316 indices.uniqueIndex := uniq;
354 1316 indices := setTypeIndices(indices, varType, real_idx, int_idx, bool_idx, string_idx, enum_idx);
355 end createListsByType;
356
357 function getTypeIndex
358 input SimCode.SimCodeIndices indices;
359 input VarType varType;
360 output Integer idx;
361 algorithm
362 idx := match varType
363 1441 case VarType.SIMULATION then indices.realVarIndex;
364 ✗ case VarType.PARAMETER then indices.realParamIndex;
365 ✗ case VarType.ALIAS then indices.realAliasIndex;
366 188 case VarType.RESIDUAL then indices.residualIndex;
367 188 case VarType.EXTERNAL_OBJECT then indices.extObjIndex;
368 end match;
369 end getTypeIndex;
370
371 function setTypeIndex
372 input output SimCode.SimCodeIndices indices;
373 input VarType varType;
374 input Integer idx;
375 algorithm
376 () := match varType
377 1441 case VarType.SIMULATION algorithm indices.realVarIndex := idx; then ();
378 ✗ case VarType.PARAMETER algorithm indices.realParamIndex := idx; then ();
379 ✗ case VarType.ALIAS algorithm indices.realAliasIndex := idx; then ();
380 188 case VarType.RESIDUAL algorithm indices.residualIndex := idx; then ();
381 188 case VarType.EXTERNAL_OBJECT algorithm indices.extObjIndex := idx; then ();
382 end match;
383 end setTypeIndex;
384
385 function getTypeIndices
386 input SimCode.SimCodeIndices indices;
387 input VarType varType;
388 output Integer real_idx;
389 output Integer int_idx;
390 output Integer bool_idx;
391 output Integer string_idx;
392 output Integer enum_idx;
393 algorithm
394 (real_idx, int_idx, bool_idx, string_idx, enum_idx) := match varType
395 752 case VarType.SIMULATION then (indices.realVarIndex, indices.integerVarIndex, indices.booleanVarIndex, indices.stringVarIndex, indices.enumerationVarIndex);
396 376 case VarType.PARAMETER then (indices.realParamIndex, indices.integerParamIndex, indices.booleanParamIndex, indices.stringParamIndex, indices.enumerationParamIndex);
397 188 case VarType.ALIAS then (indices.realAliasIndex, indices.integerAliasIndex, indices.booleanAliasIndex, indices.stringAliasIndex, indices.enumerationAliasIndex);
398 else algorithm
399 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unhandled VarType."});
400 ✗ then fail();
401 end match;
402 end getTypeIndices;
403
404 function setTypeIndices
405 input output SimCode.SimCodeIndices indices;
406 input VarType varType;
407 input Integer real_idx;
408 input Integer int_idx;
409 input Integer bool_idx;
410 input Integer string_idx;
411 input Integer enum_idx;
412 algorithm
413 () := match varType
414 case VarType.SIMULATION algorithm
415 752 indices.realVarIndex := real_idx;
416 752 indices.integerVarIndex := int_idx;
417 752 indices.booleanVarIndex := bool_idx;
418 752 indices.stringVarIndex := string_idx;
419 752 indices.enumerationVarIndex := enum_idx;
420 then ();
421 case VarType.PARAMETER algorithm
422 376 indices.realParamIndex := real_idx;
423 376 indices.integerParamIndex := int_idx;
424 376 indices.booleanParamIndex := bool_idx;
425 376 indices.stringParamIndex := string_idx;
426 376 indices.enumerationParamIndex := enum_idx;
427 then ();
428 case VarType.ALIAS algorithm
429 188 indices.realAliasIndex := real_idx;
430 188 indices.integerAliasIndex := int_idx;
431 188 indices.booleanAliasIndex := bool_idx;
432 188 indices.stringAliasIndex := string_idx;
433 188 indices.enumerationAliasIndex := enum_idx;
434 then ();
435 end match;
436 end setTypeIndices;
437
438 function createFromResidualComponent
439 input output StrongComponent comp;
440 input Pointer<list<SimVar>> acc;
441 input Pointer<SimCode.SimCodeIndices> indices_ptr;
442 input VarType varType = VarType.SIMULATION;
443 algorithm
444 () := match comp
445 case StrongComponent.SINGLE_COMPONENT() guard(Equation.isResidual(comp.eqn)) algorithm
446 1 traverseCreate(Pointer.access(Equation.getResidualVar(comp.eqn)), acc, indices_ptr, varType);
447 then ();
448 else ();
449 end match;
450 end createFromResidualComponent;
451
452 function size
453 input SimVar var;
454 output Integer s = Type.sizeOf(var.type_);
455 end size;
456
457 function getName
458 input SimVar var;
459 output ComponentRef name = var.name;
460 end getName;
461
462 function getIndex
463 input ComponentRef cref;
464 input UnorderedMap<ComponentRef, SimVar> sim_map;
465 output Integer index;
466 protected
467 SimVar var;
468 algorithm
469 try
470 ✗ var := UnorderedMap.getSafe(cref, sim_map, sourceInfo());
471 ✗ index := var.index;
472 else
473 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed to get index for cref: " + ComponentRef.toString(cref)});
474 ✗ fail();
475 end try;
476 end getIndex;
477
478 function shiftIndex
479 "Shift index by some value. Used to append `enumVars` onto `intVars`."
480 input output SimVar var;
481 input Integer shift;
482 algorithm
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 var.index := var.index + shift;
484
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
70 if isSome(var.fmi_index) then
485 70 var.fmi_index := SOME(Util.getOption(var.fmi_index) + shift);
486 end if;
487 end shiftIndex;
488
489 function convert
490 input SimVar simVar;
491 output OldSimCodeVar.SimVar oldSimVar;
492 protected
493 DAE.ComponentRef name = ComponentRef.toDAE(simVar.name);
494 algorithm
495
4/4
✓ Branch 0 taken 1203 times.
✓ Branch 1 taken 36273 times.
✓ Branch 2 taken 1203 times.
✓ Branch 3 taken 36273 times.
73749 oldSimVar := OldSimCodeVar.SIMVAR(
496 name = name,
497 varKind = convertVarKind(simVar.varKind),
498 comment = simVar.comment,
499 unit = simVar.unit,
500 displayUnit = simVar.displayUnit,
501 index = simVar.index,
502 minValue = convertAttribute(simVar.min),
503 maxValue = convertAttribute(simVar.max),
504 initialValue = convertAttribute(simVar.start),
505 nominalValue = convertAttribute(simVar.nominal),
506 isFixed = simVar.isFixed,
507 type_ = Type.toDAE(simVar.type_),
508 isDiscrete = simVar.isDiscrete,
509 arrayCref = Util.applyOption(simVar.arrayCref, ComponentRef.toDAE),
510 aliasvar = Alias.convert(simVar.aliasvar),
511 source = DAE.emptyElementSource, //ToDo update this!
512 causality = Util.applyOption(simVar.causality, convertCausality),
513 variable_index = simVar.variable_index,
514 fmi_index = simVar.fmi_index,
515 numArrayElement = list(Expression.toString(e) for e in simVar.numArrayElement),
516 isValueChangeable = simVar.isValueChangeable,
517 isProtected = simVar.isProtected,
518 hideResult = SOME(simVar.hideResult),
519 isEncrypted = simVar.isEncrypted,
520 inputIndex = simVar.inputIndex,
521 initNonlinear = false, // TODO: Check what to add here!
522 matrixName = simVar.matrixName,
523 variability = SOME(convertVariability(simVar.varKind)),
524 initial_ = convertInitial(convertVariability(simVar.varKind), Util.applyOption(simVar.causality, convertCausality)),
525 exportVar = convertExportVar(simVar.exportVar, simVar.name, name),
526 relativeQuantity = false,
527 isConnectorFlow = simVar.isConnectorFlow);
528 end convert;
529
530 function convertExportVar
531 "the export variable is the variable itself unless something replaced it,
532 so the converted name is usually the same cref again"
533 input Option<ComponentRef> exportVar;
534 input ComponentRef varName;
535 input DAE.ComponentRef converted "varName converted";
536 output Option<DAE.ComponentRef> dcref;
537 algorithm
538 dcref := match exportVar
539 local ComponentRef cref;
540
2/2
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 36040 times.
36273 case SOME(cref) then SOME(if referenceEq(cref, varName) then converted else ComponentRef.toDAE(cref));
541 else NONE();
542 end match;
543 end convertExportVar;
544
545 function convertAttribute
546 "Util.applyOption would build the partial application once per attribute
547 and variable, which is millions of closures on a scalarized model."
548 input Option<Expression> exp;
549 output Option<DAE.Exp> dexp;
550 algorithm
551 dexp := match exp
552 local Expression e;
553 12307 case SOME(e) then SOME(Expression.toDAE(e, allowEmpty = false));
554 else NONE();
555 end match;
556 end convertAttribute;
557
558 function convertCausality
559 "Convert the new-backend Causality enum to the old SimCodeVar.Causality used
560 by the FMI model-description templates."
561 input Causality c;
562 output OldSimCodeVar.Causality oc;
563 algorithm
564 oc := match c
565 case Causality.NONE then OldSimCodeVar.NONECAUS();
566 case Causality.OUTPUT then OldSimCodeVar.OUTPUT();
567 case Causality.INPUT then OldSimCodeVar.INPUT();
568 case Causality.LOCAL then OldSimCodeVar.LOCAL();
569 case Causality.PARAMETER then OldSimCodeVar.PARAMETER();
570 case Causality.CALCULATED_PARAMETER then OldSimCodeVar.CALCULATED_PARAMETER();
571 end match;
572 end convertCausality;
573
574 function convertVariability
575 "Derive the FMI variability attribute from the variable kind."
576 input VariableKind vk;
577 output OldSimCodeVar.Variability v;
578 algorithm
579 v := match vk
580 case VariableKind.CONSTANT() then OldSimCodeVar.CONSTANT();
581 case VariableKind.PARAMETER() then OldSimCodeVar.FIXED();
582 case VariableKind.DISCRETE() then OldSimCodeVar.DISCRETE();
583 case VariableKind.DISCRETE_STATE() then OldSimCodeVar.DISCRETE();
584 case VariableKind.CLOCKED() then OldSimCodeVar.DISCRETE();
585 case VariableKind.PREVIOUS() then OldSimCodeVar.DISCRETE();
586 else OldSimCodeVar.CONTINUOUS();
587 end match;
588 end convertVariability;
589
590 function convertInitial
591 "Default FMI initial attribute from variability + causality (mirrors
592 SimCodeUtil.getDefaultFmiInitialAttribute). Only the EXACT cases matter
593 for now: they make the start value be emitted to modelDescription.xml."
594 input OldSimCodeVar.Variability v;
595 input Option<OldSimCodeVar.Causality> c;
596 output Option<OldSimCodeVar.Initial> initial_;
597 algorithm
598 initial_ := match (v, c)
599 case (OldSimCodeVar.CONSTANT(), _) then SOME(OldSimCodeVar.EXACT());
600 case (OldSimCodeVar.FIXED(), SOME(OldSimCodeVar.PARAMETER())) then SOME(OldSimCodeVar.EXACT());
601 case (OldSimCodeVar.TUNABLE(), SOME(OldSimCodeVar.PARAMETER())) then SOME(OldSimCodeVar.EXACT());
602 else NONE();
603 end match;
604 end convertInitial;
605
606 function convertList
607 input list<SimVar> simVar_lst;
608 output list<OldSimCodeVar.SimVar> oldSimVar_lst = list(convert(simVar) for simVar in simVar_lst);
609 end convertList;
610
611 function newConvertMemo
612 input Integer size;
613 output ConvertMemo memo = UnorderedMap.new<ConvertEntry>(ComponentRef.hash, ComponentRef.isEqual, Util.nextPrime(size));
614 end newConvertMemo;
615
616 function convertMemo
617 input SimVar simVar;
618 input ConvertMemo memo;
619 output OldSimCodeVar.SimVar oldSimVar = convert(simVar);
620 algorithm
621 27611 UnorderedMap.add(simVar.name, (simVar, oldSimVar), memo);
622 end convertMemo;
623
624 function convertListMemo
625 input list<SimVar> simVar_lst;
626 input ConvertMemo memo;
627 output list<OldSimCodeVar.SimVar> oldSimVar_lst = list(convertMemo(simVar, memo) for simVar in simVar_lst);
628 end convertListMemo;
629
630 function convertMemoized
631 "the remembered conversion of exactly this record, or a fresh one"
632 input SimVar simVar;
633 input ConvertMemo memo;
634 output OldSimCodeVar.SimVar oldSimVar;
635 protected
636 SimVar orig;
637 algorithm
638 oldSimVar := match UnorderedMap.get(simVar.name, memo)
639 case SOME((orig, oldSimVar)) guard referenceEq(orig, simVar) then oldSimVar;
640 7508 else convert(simVar);
641 end match;
642 end convertMemoized;
643
644 function convertTpl
645 input tuple<SimVar, Boolean> tpl;
646 output tuple<OldSimCodeVar.SimVar, Boolean> oldTpl;
647 protected
648 SimVar var;
649 Boolean b;
650 algorithm
651 24 (var, b) := tpl;
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 oldTpl := (convert(var), b);
653 end convertTpl;
654
655 function isOutputSimVar
656 "True if the SimVar is an FMI output (causality OUTPUT), used to collect the
657 output interface variables (the new backend has no top-level-output list)."
658 input SimVar v;
659 output Boolean b;
660 algorithm
661 b := match v.causality
662 case SOME(Causality.OUTPUT) then true;
663 else false;
664 end match;
665 end isOutputSimVar;
666
667 protected
668 function parseAttributes
669 input BackendInfo backendInfo;
670 output VariableKind varKind;
671 output String unit = "";
672 output String displayUnit = "";
673 output Option<Expression> min = NONE();
674 output Option<Expression> max = NONE();
675 output Option<Expression> start = NONE();
676 output Option<Expression> nominal = NONE();
677 output Boolean isFixed = false;
678 output Boolean isDiscrete;
679 output Boolean isProtected;
680 algorithm
681 () := match backendInfo
682 local
683 VariableAttributes varAttr;
684
685 case BackendInfo.BACKEND_INFO(varKind = varKind, attributes = varAttr as VariableAttributes.VAR_ATTR_REAL())
686 algorithm
687 20155 unit := Util.applyOptionOrDefault(Util.applyOption(varAttr.unit, Binding.getTypedExp), Expression.stringValue, "");
688 20155 displayUnit := Util.applyOptionOrDefault(Util.applyOption(varAttr.displayUnit, Binding.getTypedExp), Expression.stringValue, "");
689 20155 min := Util.applyOption(varAttr.min, Binding.getTypedExp);
690 20155 max := Util.applyOption(varAttr.max, Binding.getTypedExp);
691 20155 start := Util.applyOption(varAttr.start, Binding.getTypedExp);
692 20155 nominal := Util.applyOption(varAttr.nominal, Binding.getTypedExp);
693 // FIXME parameters have default fixed = true
694
2/2
✓ Branch 2 taken 13694 times.
✓ Branch 3 taken 6461 times.
20155 isFixed := Util.applyOptionOrDefault(Util.applyOption(varAttr.fixed, Binding.getTypedExp), Expression.isAllTrue, false);
695 isDiscrete := match varKind
696 case VariableKind.DISCRETE() then true;
697 case VariableKind.DISCRETE_STATE() then true;
698 case VariableKind.PREVIOUS() then true;
699 case VariableKind.PARAMETER() then true;
700 case VariableKind.CONSTANT() then true;
701 case VariableKind.START() then true;
702 else false;
703 end match;
704 20155 isProtected := Util.getOptionOrDefault(varAttr.isProtected, false);
705 then ();
706
707 case BackendInfo.BACKEND_INFO(varKind = varKind, attributes = varAttr as VariableAttributes.VAR_ATTR_INT())
708 algorithm
709 409 min := Util.applyOption(varAttr.min, Binding.getTypedExp);
710 409 max := Util.applyOption(varAttr.max, Binding.getTypedExp);
711 409 start := Util.applyOption(varAttr.start, Binding.getTypedExp);
712 409 isFixed := Util.applyOptionOrDefault(Util.applyOption(varAttr.fixed, Binding.getTypedExp), Expression.isAllTrue, false);
713 isDiscrete := true;
714 409 isProtected := Util.getOptionOrDefault(varAttr.isProtected, false);
715 then ();
716
717 case BackendInfo.BACKEND_INFO(varKind = varKind, attributes = varAttr as VariableAttributes.VAR_ATTR_BOOL())
718 algorithm
719 772 start := Util.applyOption(varAttr.start, Binding.getTypedExp);
720 772 isFixed := Util.applyOptionOrDefault(Util.applyOption(varAttr.fixed, Binding.getTypedExp), Expression.isAllTrue, false);
721 isDiscrete := true;
722 772 isProtected := Util.getOptionOrDefault(varAttr.isProtected, false);
723 then ();
724
725 case BackendInfo.BACKEND_INFO(varKind = varKind, attributes = varAttr as VariableAttributes.VAR_ATTR_CLOCK())
726 algorithm
727 isDiscrete := true;
728 ✗ isProtected := Util.getOptionOrDefault(varAttr.isProtected, false);
729 then ();
730
731 case BackendInfo.BACKEND_INFO(varKind = varKind, attributes = varAttr as VariableAttributes.VAR_ATTR_STRING())
732 algorithm
733 30 start := Util.applyOption(varAttr.start, Binding.getTypedExp);
734 30 isFixed := Util.applyOptionOrDefault(Util.applyOption(varAttr.fixed, Binding.getTypedExp), Expression.isAllTrue, false);
735 isDiscrete := true;
736 30 isProtected := Util.getOptionOrDefault(varAttr.isProtected, false);
737 then ();
738
739 case BackendInfo.BACKEND_INFO(varKind = varKind, attributes = varAttr as VariableAttributes.VAR_ATTR_ENUMERATION())
740 algorithm
741 68 min := Util.applyOption(varAttr.min, Binding.getTypedExp);
742 68 max := Util.applyOption(varAttr.max, Binding.getTypedExp);
743 68 start := Util.applyOption(varAttr.start, Binding.getTypedExp);
744 68 isFixed := Util.applyOptionOrDefault(Util.applyOption(varAttr.fixed, Binding.getTypedExp), Expression.isAllTrue, false);
745 isDiscrete := true;
746 68 isProtected := Util.getOptionOrDefault(varAttr.isProtected, false);
747 then ();
748
749 else algorithm
750 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because the BackendInfo could not be parsed:\n"
751 + BackendInfo.toString(backendInfo)});
752 ✗ then fail();
753 end match;
754 end parseAttributes;
755
756 function parseComment
757 input SCode.Comment absynComment;
758 output String commentStr;
759 algorithm
760 commentStr := match absynComment
761 case SCode.COMMENT(comment = SOME(commentStr)) then commentStr;
762 else "";
763 end match;
764 end parseComment;
765
766 function parseBinding
767 "returns the binding expression if the variable is a parameter and the binding is constant
768 returns the original start expression otherwise. Only if the binding is constant and used
769 as initial"
770 input output Option<Expression> start;
771 output Boolean isValueChangeable;
772 output Causality causality;
773 input Variable var;
774 algorithm
775 (start, isValueChangeable, causality) := match var
776 local
777 Expression bindingExp;
778
779 // 1. parameter with constant binding -> start value is updated to the binding value. Value can be changed after sim
780 case Variable.VARIABLE(binding = Binding.TYPED_BINDING(variability = NFPrefixes.Variability.CONSTANT, bindingExp = bindingExp),
781 backendinfo = BackendInfo.BACKEND_INFO(varKind = VariableKind.PARAMETER()))
782 then (SOME(bindingExp), true, Causality.PARAMETER);
783
784 // 2. just like 1. - FLAT_BINDING gets introduced by expanding/scalarizing
785 case Variable.VARIABLE(binding = Binding.FLAT_BINDING(variability = NFPrefixes.Variability.CONSTANT, bindingExp = bindingExp),
786 backendinfo = BackendInfo.BACKEND_INFO(varKind = VariableKind.PARAMETER()))
787 then (SOME(bindingExp), true, Causality.PARAMETER);
788
789 // 3. parameter with non constant binding -> normal start value. Value cannot be changed after simulation
790 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = VariableKind.PARAMETER()))
791 then (start, false, Causality.CALCULATED_PARAMETER);
792
793 // 4. top level input / output variables -> FMI input/output causality (the
794 // flat-model direction; mirrors the old backend so modelDescription.xml
795 // gets causality="input"/"output" and FMI 3.0 terminals get a direction)
796 case _ guard Variable.isInput(var) then (start, true, Causality.INPUT);
797 case _ guard Variable.isOutput(var) then (start, false, Causality.OUTPUT);
798
799 // 0. other variables -> regular start value and it can be changed after simulation
800 else (start, false, Causality.LOCAL);
801
802 // ToDo: more cases!
803
804 // FIXME: variables that are fixed and are not CALCULATED should have isValueChangeable=true
805 end match;
806 end parseBinding;
807
808 function convertVarKind
809 "Usually this function would belong to NFBackendExtension, but we want to
810 avoid Frontend -> Backend dependency."
811 input VariableKind varKind;
812 output OldBackendDAE.VarKind oldVarKind;
813 algorithm
814 oldVarKind := match varKind
815 local
816 Variable var;
817 Option<DAE.ComponentRef> oldCrefOpt;
818
819 case VariableKind.ALGEBRAIC() then OldBackendDAE.VARIABLE();
820 case VariableKind.STATE()
821 algorithm
822
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
✓ Branch 2 taken 605 times.
✗ Branch 3 not taken.
605 if isSome(varKind.derivative) then
823 605 var := Pointer.access(PointerWeak.upgrade(Util.getOption(varKind.derivative)));
824 605 oldCrefOpt := SOME(ComponentRef.toDAE(var.name));
825 else
826 oldCrefOpt := NONE();
827 end if;
828 605 then OldBackendDAE.STATE(varKind.index, oldCrefOpt, varKind.natural);
829 case VariableKind.STATE_DER() then OldBackendDAE.STATE_DER();
830 case VariableKind.DUMMY_DER() then OldBackendDAE.DUMMY_DER();
831 case VariableKind.DUMMY_STATE() then OldBackendDAE.DUMMY_STATE();
832 case VariableKind.DISCRETE() then OldBackendDAE.DISCRETE();
833 case VariableKind.DISCRETE_STATE() then OldBackendDAE.DISCRETE(); // we don't distinguish between clocked, discrete states and discretes in the old backend. is this correct?
834 case VariableKind.CLOCKED() then OldBackendDAE.DISCRETE(); // we don't distinguish between clocked, discrete states and discretes in the old backend. is this correct?
835 case VariableKind.PREVIOUS() then OldBackendDAE.DISCRETE();
836 case VariableKind.PARAMETER() then OldBackendDAE.PARAM();
837 case VariableKind.CONSTANT() then OldBackendDAE.CONST();
838 //ToDo: check this! is this correct? need typechecking?
839 case VariableKind.START() then OldBackendDAE.VARIABLE();
840 6 case VariableKind.EXTOBJ() then OldBackendDAE.EXTOBJ(varKind.fullClassName);
841 case VariableKind.JAC_VAR() then OldBackendDAE.JAC_VAR();
842 case VariableKind.JAC_TMP_VAR() then OldBackendDAE.JAC_TMP_VAR();
843 case VariableKind.SEED_VAR() then OldBackendDAE.SEED_VAR();
844 case VariableKind.OPT_CONSTR() then OldBackendDAE.OPT_CONSTR();
845 case VariableKind.OPT_FCONSTR() then OldBackendDAE.OPT_FCONSTR();
846 case VariableKind.OPT_INPUT_WITH_DER() then OldBackendDAE.OPT_INPUT_WITH_DER();
847 case VariableKind.OPT_INPUT_DER() then OldBackendDAE.OPT_INPUT_DER();
848 case VariableKind.OPT_TGRID() then OldBackendDAE.OPT_TGRID();
849 ✗ case VariableKind.OPT_LOOP_INPUT() then OldBackendDAE.OPT_LOOP_INPUT(ComponentRef.toDAE(varKind.replaceCref));
850 // ToDo maybe deprecated:
851 case VariableKind.ALG_STATE() then OldBackendDAE.ALG_STATE();
852 case VariableKind.ALG_STATE_OLD() then OldBackendDAE.ALG_STATE_OLD();
853 case VariableKind.RESIDUAL_VAR() then OldBackendDAE.DAE_RESIDUAL_VAR();
854 case VariableKind.DAE_AUX_VAR() then OldBackendDAE.DAE_AUX_VAR();
855 case VariableKind.LOOP_ITERATION() then OldBackendDAE.LOOP_ITERATION();
856 case VariableKind.LOOP_SOLVED() then OldBackendDAE.LOOP_SOLVED();
857 case VariableKind.FRONTEND_DUMMY()
858 algorithm
859 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of wrong VariableKind FRONTEND_DUMMY(). This should not exist after frontend."});
860 ✗ then fail();
861 else
862 algorithm
863 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unhandled VariableKind " + VariableKind.toString(varKind) + "."});
864 ✗ then fail();
865 end match;
866 end convertVarKind;
867 end SimVar;
868
869 uniontype Alias
870 record NO_ALIAS end NO_ALIAS;
871
872 record ALIAS
873 "General alias expression with a coefficent.
874 var := gain * alias + offset"
875 ComponentRef alias "The name of the alias variable.";
876 Real gain " = 1 for regular alias.";
877 Real offset " = 0 for regular alias.";
878 end ALIAS;
879
880 function fromBinding
881 input Binding binding;
882 output Alias alias;
883 algorithm
884 alias := match binding
885 1171 case Binding.TYPED_BINDING() then getAlias(binding.bindingExp);
886 317 case Binding.FLAT_BINDING() then getAlias(binding.bindingExp);
887 else NO_ALIAS();
888 end match;
889 end fromBinding;
890
891 function toString
892 input Alias alias;
893 output String str;
894 algorithm
895 str := match alias
896 local
897 String gainStr, offsetStr;
898 case NO_ALIAS() then "(no alias)";
899 case ALIAS() algorithm
900 ✗ gainStr := if alias.gain == 1.0 then "" else realString(alias.gain) + "*";
901 ✗ offsetStr := if alias.offset == 0.0 then "" else "+" + realString(alias.offset);
902 ✗ then "(bound alias: " + gainStr + ComponentRef.toString(alias.alias) + offsetStr + ")";
903 end match;
904 end toString;
905
906 function convert
907 input Alias alias;
908 output OldSimCodeVar.AliasVariable oldAlias;
909 algorithm
910 oldAlias := match alias
911 case NO_ALIAS() then OldSimCodeVar.NOALIAS();
912
913 case ALIAS() guard(realEq(alias.gain, 1.0) and realEq(alias.offset, 0.0))
914 1244 then OldSimCodeVar.ALIAS(ComponentRef.toDAE(alias.alias));
915
916 case ALIAS() guard(realEq(alias.gain, -1.0) and realEq(alias.offset, 0.0))
917 243 then OldSimCodeVar.NEGATEDALIAS(ComponentRef.toDAE(alias.alias));
918
919 /* unfortunately not possible in old sim code
920 case ALIAS()
921 then OldSimCodeVar.ALIAS_FUNC(ComponentRef.toDAE(alias.alias), alias.gain, alias.offset);
922 */
923 else
924 algorithm
925 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unknown Alias type."});
926 ✗ then fail();
927 end match;
928 end convert;
929
930 protected
931 function getAlias
932 input Expression exp;
933 output Alias alias;
934 algorithm
935
936 alias := match SimplifyExp.simplify(exp)
937 local
938 Expression e;
939 ComponentRef cref;
940
941 // equality alias
942 1245 case e as Expression.CREF() then ALIAS(e.cref, 1.0, 0.0);
943
944 // negated alias
945 228 case Expression.UNARY(exp = e as Expression.CREF()) then ALIAS(e.cref, -1.0, 0.0);
946
947 // negated logical alias
948 15 case Expression.LUNARY(exp = e as Expression.CREF()) then ALIAS(e.cref, -1.0, 0.0);
949 /*
950 // gain alias
951 case e as Expression.MULTARY(arguments = {e1, e2}, inv_arguments = {})
952 guard(Operator.getMathClassification(e.operator) == NFOperator.MathClassification.MULTIPLICATION)
953 algorithm
954 (cref, gain) := getGainAlias(e1, e2);
955 then ALIAS(cref, gain, 0.0);
956
957 // offset alias (possibly also gain alias)
958 // constant should always be simplified to the arguments list even if it is negative
959 case e as Expression.MULTARY(arguments = {e1, e2}, inv_arguments = {})
960 guard(Operator.getMathClassification(e.operator) == NFOperator.MathClassification.ADDITION)
961 algorithm
962 (cref, gain, offset) := getOffsetAlias(e1, e2);
963 then ALIAS(cref, gain, offset);
964 */
965 else NO_ALIAS();
966 end match;
967 end getAlias;
968
969 function getGainAlias
970 input Expression e1;
971 input Expression e2;
972 output ComponentRef cref;
973 output Real gain;
974 algorithm
975 (cref, gain) := match(e1, e2)
976 // first argument is the cref and second is const
977 ✗ case (Expression.CREF(), _) guard(Expression.isConstNumber(e2)) then (e1.cref, Expression.realValue(e2));
978 // secoond argument is the cref and first is const
979 ✗ case (_, Expression.CREF()) guard(Expression.isConstNumber(e1)) then (e2.cref, Expression.realValue(e1));
980 else algorithm
981 ✗ Error.addInternalError(getInstanceName() + " cannot generate gain alias from Expressions: {"
982 + Expression.toString(e1) + ", " + Expression.toString(e2) + "}", sourceInfo());
983 ✗ then fail();
984 end match;
985 end getGainAlias;
986
987 function getOffsetAlias
988 input Expression e1;
989 input Expression e2;
990 output ComponentRef cref;
991 output Real gain;
992 output Real offset;
993 algorithm
994 (cref, gain, offset) := match (e1, e2)
995 local
996 Expression arg1, arg2;
997
998 // first argument is the cref and second is const
999 ✗ case (Expression.CREF(), _) guard(Expression.isConstNumber(e2)) then (e1.cref, 0.0, Expression.realValue(e2));
1000
1001 // second is the cref and first is const
1002 ✗ case (_, Expression.CREF()) guard(Expression.isConstNumber(e1)) then (e2.cref, 0.0, Expression.realValue(e1));
1003
1004 // first argument is a multiplication with two arguments, second is constant
1005 // check if multiplication represents simple gain
1006 case (Expression.MULTARY(arguments = {arg1, arg2}, inv_arguments = {}), _)
1007 guard((Operator.getMathClassification(e1.operator) == NFOperator.MathClassification.MULTIPLICATION)
1008 and Expression.isConstNumber(e2))
1009 algorithm
1010 ✗ (cref, gain) := getGainAlias(arg1, arg2);
1011 ✗ then (cref, gain, Expression.realValue(e2));
1012
1013 // second argument is a multiplication with two arguments, first is constant
1014 // check if multiplication represents simple gain
1015 case (_, Expression.MULTARY(arguments = {arg1, arg2}, inv_arguments = {}))
1016 guard((Operator.getMathClassification(e2.operator) == NFOperator.MathClassification.MULTIPLICATION)
1017 and Expression.isConstNumber(e1))
1018 algorithm
1019 ✗ (cref, gain) := getGainAlias(arg1, arg2);
1020 ✗ then (cref, gain, Expression.realValue(e1));
1021
1022 else algorithm
1023 ✗ Error.addInternalError(getInstanceName() + " cannot generate offset alias from Expressions: {"
1024 + Expression.toString(e1) + ", " + Expression.toString(e2) + "}", sourceInfo());
1025 ✗ then fail();
1026 end match;
1027 end getOffsetAlias;
1028 end Alias;
1029
1030 // kabdelhak: i don't like "CALCULATED_PARAMETER", is there a better way to describe it?
1031 type Causality = enumeration(NONE, OUTPUT, INPUT, LOCAL, PARAMETER, CALCULATED_PARAMETER);
1032 // kabdelhak: where is the difference between approx and calculated?
1033 type Initial = enumeration(NONE, EXACT, APPROX, CALCULATED);
1034 // kabdelhak: i don't like "TUNABLE" -> just "VARIABLE"?
1035 type Variability = enumeration(CONSTANT, FIXED, TUNABLE, DISCRETE, CONTINUOUS);
1036
1037 uniontype SimVars "Container for metadata about variables in a Modelica model."
1038 record SIMVARS
1039 list<SimVar> stateVars;
1040 list<SimVar> derivativeVars;
1041 list<SimVar> algVars;
1042 list<SimVar> discreteAlgVars;
1043 list<SimVar> intAlgVars;
1044 list<SimVar> boolAlgVars;
1045 list<SimVar> stringAlgVars;
1046 list<SimVar> enumAlgVars;
1047 list<SimVar> inputVars;
1048 list<SimVar> outputVars;
1049 list<SimVar> aliasVars;
1050 list<SimVar> intAliasVars;
1051 list<SimVar> boolAliasVars;
1052 list<SimVar> stringAliasVars;
1053 list<SimVar> enumAliasVars;
1054 list<SimVar> paramVars;
1055 list<SimVar> intParamVars;
1056 list<SimVar> boolParamVars;
1057 list<SimVar> stringParamVars;
1058 list<SimVar> enumParamVars;
1059 list<SimVar> extObjVars;
1060 list<SimVar> constVars;
1061 list<SimVar> intConstVars;
1062 list<SimVar> boolConstVars;
1063 list<SimVar> stringConstVars;
1064 list<SimVar> enumConstVars;
1065 list<SimVar> residualVars;
1066 list<SimVar> jacobianVars;
1067 list<SimVar> seedVars;
1068 list<SimVar> realOptimizeConstraintsVars;
1069 list<SimVar> realOptimizeFinalConstraintsVars;
1070 list<SimVar> sensitivityVars "variable used to calculate sensitivities for parameters nSensitivitityParameters + nRealParam*nStates";
1071 list<SimVar> dataReconSetcVars;
1072 list<SimVar> dataReconinputVars;
1073 list<SimVar> dataReconSetBVars;
1074 end SIMVARS;
1075
1076 function toString
1077 input SimVars vars;
1078 input output String str = "";
1079 algorithm
1080 6 str := StringUtil.headline_2("SimVars " + str);
1081 6 str := str + SimVar.listToString(vars.stateVars, "States");
1082 6 str := str + SimVar.listToString(vars.derivativeVars, "Derivatives");
1083 6 str := str + SimVar.listToString(vars.algVars, "Algebraic Variables");
1084 6 str := str + SimVar.listToString(vars.discreteAlgVars, "Discrete Algebraic Variables");
1085 6 str := str + SimVar.listToString(vars.intAlgVars, "Integer Algebraic Variables");
1086 6 str := str + SimVar.listToString(vars.boolAlgVars, "Boolean Algebraic Variables");
1087 6 str := str + SimVar.listToString(vars.paramVars, "Real Parameters");
1088 6 str := str + SimVar.listToString(vars.intParamVars, "Integer Parameters");
1089 6 str := str + SimVar.listToString(vars.boolParamVars, "Boolean Parameters");
1090 6 str := str + SimVar.listToString(vars.residualVars, "Residual Variables");
1091 6 str := str + SimVar.listToString(vars.aliasVars, "Real Alias", true);
1092 // ToDo: all the other stuff
1093 end toString;
1094
1095 function create
1096 input BVariable.VarData varData;
1097 input VariablePointers residual_vars;
1098 output SimVars simVars;
1099 input output SimCode.SimCodeIndices simCodeIndices;
1100 protected
1101 list<SimVar> stateVars = {}, derivativeVars = {}, algVars = {}, nonTrivialAlias = {};
1102 list<SimVar> discreteAlgVars = {}, intAlgVars = {}, boolAlgVars = {}, stringAlgVars = {}, enumAlgVars = {};
1103 list<SimVar> discreteAlgVars2 = {}, intAlgVars2 = {}, boolAlgVars2 = {}, stringAlgVars2 = {}, enumAlgVars2 = {};
1104 list<SimVar> discreteAlgVars3 = {}, intAlgVars3 = {}, boolAlgVars3 = {}, stringAlgVars3 = {}, enumAlgVars3 = {};
1105 list<SimVar> inputVars = {};
1106 list<SimVar> outputVars = {};
1107 list<SimVar> aliasVars = {}, intAliasVars = {}, boolAliasVars = {}, stringAliasVars = {}, enumAliasVars = {};
1108 list<SimVar> paramVars = {}, intParamVars = {}, boolParamVars = {}, stringParamVars = {}, enumParamVars = {};
1109 list<SimVar> paramVarsR = {}, intParamVarsR = {}, boolParamVarsR = {}, stringParamVarsR = {}, enumParamVarsR = {};
1110 list<SimVar> constVars = {}, intConstVars = {}, boolConstVars = {}, stringConstVars = {}, enumConstVars = {};
1111 list<SimVar> extObjVars = {};
1112 list<SimVar> residualVars = {};
1113 list<SimVar> jacobianVars = {};
1114 list<SimVar> seedVars = {};
1115 list<SimVar> realOptimizeConstraintsVars = {};
1116 list<SimVar> realOptimizeFinalConstraintsVars = {};
1117 Integer enum_shift = 0;
1118 list<SimVar> sensitivityVars = {};
1119 list<SimVar> dataReconSetcVars = {};
1120 list<SimVar> dataReconinputVars = {};
1121 list<SimVar> dataReconSetBVars = {};
1122 algorithm
1123 () := match varData
1124 case BVariable.VAR_DATA_SIM() algorithm
1125
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
188 ({stateVars}, simCodeIndices) := createSimVarLists(varData.states, simCodeIndices, SplitType.NONE, VarType.SIMULATION);
1126
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
188 ({derivativeVars}, simCodeIndices) := createSimVarLists(varData.derivatives, simCodeIndices, SplitType.NONE, VarType.SIMULATION);
1127
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
188 ({algVars}, simCodeIndices) := createSimVarLists(varData.algebraics, simCodeIndices, SplitType.NONE, VarType.SIMULATION);
1128
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
188 ({inputVars}, simCodeIndices) := createSimVarLists(varData.top_level_inputs, simCodeIndices, SplitType.NONE, VarType.SIMULATION);
1129
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
188 ({nonTrivialAlias}, simCodeIndices) := createSimVarLists(varData.nonTrivialAlias, simCodeIndices, SplitType.NONE, VarType.SIMULATION);
1130
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
188 ({discreteAlgVars, intAlgVars, boolAlgVars, stringAlgVars, enumAlgVars}, simCodeIndices) := createSimVarLists(varData.discretes, simCodeIndices, SplitType.TYPE, VarType.SIMULATION);
1131
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
188 ({discreteAlgVars2, intAlgVars2, boolAlgVars2, stringAlgVars2, enumAlgVars2}, simCodeIndices) := createSimVarLists(varData.discrete_states, simCodeIndices, SplitType.TYPE, VarType.SIMULATION);
1132
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
188 ({discreteAlgVars3, intAlgVars3, boolAlgVars3, stringAlgVars3, enumAlgVars3}, simCodeIndices) := createSimVarLists(varData.clocked_states, simCodeIndices, SplitType.TYPE, VarType.SIMULATION);
1133
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
188 ({aliasVars, intAliasVars, boolAliasVars, stringAliasVars, enumAliasVars}, simCodeIndices) := createSimVarLists(varData.aliasVars, simCodeIndices, SplitType.TYPE, VarType.ALIAS);
1134 // enums are appended to the integer variables, constants do not take part in the shift
1135 188 enum_shift := simCodeIndices.integerVarIndex;
1136
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
188 ({paramVars, intParamVars, boolParamVars, stringParamVars, enumParamVars}, simCodeIndices) := createSimVarLists(varData.parameters, simCodeIndices, SplitType.TYPE, VarType.PARAMETER);
1137
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
188 ({paramVarsR, intParamVarsR, boolParamVarsR, stringParamVarsR, enumParamVarsR}, simCodeIndices) := createSimVarLists(varData.resizables, simCodeIndices, SplitType.TYPE, VarType.PARAMETER);
1138
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
188 ({constVars, intConstVars, boolConstVars, stringConstVars, enumConstVars}, simCodeIndices) := createSimVarLists(varData.constants, simCodeIndices, SplitType.TYPE, VarType.SIMULATION);
1139
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
188 ({residualVars}, simCodeIndices) := createSimVarLists(residual_vars, simCodeIndices, SplitType.NONE, VarType.RESIDUAL);
1140 // The new backend has no separate top-level-output partition; outputs are
1141 // algebraic/state/discrete variables flagged OUTPUT by parseBinding. Collect
1142 // them across ALL base types (real, integer, boolean, string, enum) for the
1143 // FMI inputVars/outputVars interface (used e.g. by the FMI 3.0 terminal
1144 // export and ModelStructure). The variables stay in their original lists too.
1145 188 outputVars := List.filterOnTrue(
1146 List.flatten({stateVars, algVars,
1147 discreteAlgVars, discreteAlgVars2, discreteAlgVars3,
1148 intAlgVars, intAlgVars2, intAlgVars3,
1149 boolAlgVars, boolAlgVars2, boolAlgVars3,
1150 stringAlgVars, stringAlgVars2, stringAlgVars3,
1151 enumAlgVars, enumAlgVars2, enumAlgVars3}),
1152 SimVar.isOutputSimVar);
1153 then ();
1154 case BVariable.VAR_DATA_JAC() then ();
1155 case BVariable.VAR_DATA_HES() then ();
1156
1157 else algorithm
1158 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
1159 ✗ then fail();
1160 end match;
1161
1162 188 simVars := SIMVARS(
1163 stateVars = stateVars,
1164 derivativeVars = derivativeVars,
1165 algVars = List.flatten({algVars, inputVars, nonTrivialAlias}),
1166 discreteAlgVars = List.flatten({discreteAlgVars, discreteAlgVars2, discreteAlgVars3}),
1167 intAlgVars = List.flatten({intAlgVars, intAlgVars2, intAlgVars3}),
1168 boolAlgVars = List.flatten({boolAlgVars, boolAlgVars2, boolAlgVars3}),
1169 stringAlgVars = List.flatten({stringAlgVars, stringAlgVars2, stringAlgVars3}),
1170 enumAlgVars = List.flatten({enumAlgVars, enumAlgVars2, enumAlgVars3}),
1171 inputVars = inputVars,
1172 outputVars = outputVars,
1173 aliasVars = aliasVars,
1174 intAliasVars = intAliasVars,
1175 boolAliasVars = boolAliasVars,
1176 stringAliasVars = stringAliasVars,
1177 enumAliasVars = enumAliasVars,
1178 paramVars = List.flatten({paramVars, paramVarsR}),
1179 intParamVars = List.flatten({intParamVars, intParamVarsR}),
1180 boolParamVars = List.flatten({boolParamVars, boolParamVarsR}),
1181 stringParamVars = List.flatten({stringParamVars, stringParamVarsR}),
1182 enumParamVars = List.flatten({enumParamVars, enumParamVarsR}),
1183 extObjVars = extObjVars,
1184 constVars = constVars,
1185 intConstVars = intConstVars,
1186 boolConstVars = boolConstVars,
1187 stringConstVars = stringConstVars,
1188 enumConstVars = enumConstVars,
1189 residualVars = residualVars,
1190 jacobianVars = jacobianVars,
1191 seedVars = seedVars,
1192 realOptimizeConstraintsVars = realOptimizeConstraintsVars,
1193 realOptimizeFinalConstraintsVars = realOptimizeFinalConstraintsVars,
1194 sensitivityVars = sensitivityVars,
1195 dataReconSetcVars = dataReconSetcVars,
1196 dataReconinputVars = dataReconinputVars,
1197 dataReconSetBVars = dataReconSetBVars
1198 );
1199
1200 // FIXME we currently handle enumerations as integers.
1201 // We append enums to ints so we have to shift the index accordingly.
1202
12/16
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 188 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 188 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 188 times.
✓ Branch 12 taken 69 times.
✓ Branch 13 taken 188 times.
✓ Branch 14 taken 69 times.
✓ Branch 15 taken 188 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 188 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 188 times.
258 simVars.intAlgVars := listAppend(simVars.intAlgVars, list(SimVar.shiftIndex(v, enum_shift) for v in simVars.enumAlgVars));
1203 simVars.intAliasVars := listAppend(simVars.intAliasVars, list(SimVar.shiftIndex(v, simCodeIndices.integerAliasIndex) for v in simVars.enumAliasVars));
1204 simVars.intParamVars := listAppend(simVars.intParamVars, list(SimVar.shiftIndex(v, simCodeIndices.integerParamIndex) for v in simVars.enumParamVars));
1205 simVars.intConstVars := listAppend(simVars.intConstVars, list(SimVar.shiftIndex(v, simCodeIndices.integerVarIndex) for v in simVars.enumConstVars));
1206 end create;
1207
1208 function addSeedAndJacobianVars
1209 input output SimVars vars;
1210 input list<tuple<ComponentRef, SimVar>> hash_tpl;
1211 protected
1212 ComponentRef cref;
1213 SimVar var;
1214 list<SimVar> seed_vars = {};
1215 list<SimVar> jacobian_vars = {};
1216 algorithm
1217
2/2
✓ Branch 0 taken 5380 times.
✓ Branch 1 taken 167 times.
5547 for tpl in hash_tpl loop
1218 5380 (cref, var) := tpl;
1219
2/2
✓ Branch 1 taken 1524 times.
✓ Branch 2 taken 3856 times.
5380 if BVariable.checkCref(cref, BVariable.isSeed, sourceInfo()) then
1220 seed_vars := var :: seed_vars;
1221 else
1222 jacobian_vars := var :: jacobian_vars;
1223 end if;
1224 end for;
1225 167 vars.seedVars := listAppend(seed_vars, vars.seedVars);
1226 vars.jacobianVars := listAppend(jacobian_vars, vars.jacobianVars);
1227 end addSeedAndJacobianVars;
1228
1229 function size
1230 input SimVars simVars;
1231 output Integer size = listLength(simVars.stateVars)
1232 + listLength(simVars.derivativeVars)
1233 + listLength(simVars.algVars)
1234 + listLength(simVars.discreteAlgVars)
1235 + listLength(simVars.intAlgVars)
1236 + listLength(simVars.boolAlgVars)
1237 + listLength(simVars.inputVars)
1238 + listLength(simVars.outputVars)
1239 + listLength(simVars.aliasVars)
1240 + listLength(simVars.intAliasVars)
1241 + listLength(simVars.boolAliasVars)
1242 + listLength(simVars.paramVars)
1243 + listLength(simVars.intParamVars)
1244 + listLength(simVars.boolParamVars)
1245 + listLength(simVars.stringAlgVars)
1246 + listLength(simVars.stringParamVars)
1247 + listLength(simVars.stringAliasVars)
1248 + listLength(simVars.extObjVars)
1249 + listLength(simVars.constVars)
1250 + listLength(simVars.intConstVars)
1251 + listLength(simVars.boolConstVars)
1252 + listLength(simVars.stringConstVars)
1253 + listLength(simVars.stringAlgVars)
1254 + listLength(simVars.jacobianVars)
1255 + listLength(simVars.seedVars)
1256 + listLength(simVars.realOptimizeConstraintsVars)
1257 + listLength(simVars.realOptimizeFinalConstraintsVars)
1258 + listLength(simVars.sensitivityVars)
1259 + listLength(simVars.dataReconSetcVars)
1260 + listLength(simVars.dataReconinputVars)
1261 + listLength(simVars.dataReconSetBVars);
1262 end size;
1263
1264 function convert
1265 input SimVars simVars;
1266 input ConvertMemo memo;
1267 output OldSimCodeVar.SimVars oldSimVars;
1268 algorithm
1269 188 oldSimVars := OldSimCodeVar.SIMVARS(
1270 stateVars = SimVar.convertListMemo(simVars.stateVars, memo),
1271 derivativeVars = SimVar.convertListMemo(simVars.derivativeVars, memo),
1272 algVars = SimVar.convertListMemo(simVars.algVars, memo),
1273 discreteAlgVars = SimVar.convertListMemo(simVars.discreteAlgVars, memo),
1274 intAlgVars = SimVar.convertListMemo(simVars.intAlgVars, memo),
1275 boolAlgVars = SimVar.convertListMemo(simVars.boolAlgVars, memo),
1276 inputVars = SimVar.convertListMemo(simVars.inputVars, memo),
1277 outputVars = SimVar.convertListMemo(simVars.outputVars, memo),
1278 aliasVars = SimVar.convertListMemo(simVars.aliasVars, memo),
1279 intAliasVars = SimVar.convertListMemo(simVars.intAliasVars, memo),
1280 boolAliasVars = SimVar.convertListMemo(simVars.boolAliasVars, memo),
1281 paramVars = SimVar.convertListMemo(simVars.paramVars, memo),
1282 intParamVars = SimVar.convertListMemo(simVars.intParamVars, memo),
1283 boolParamVars = SimVar.convertListMemo(simVars.boolParamVars, memo),
1284 stringAlgVars = SimVar.convertListMemo(simVars.stringAlgVars, memo),
1285 stringParamVars = SimVar.convertListMemo(simVars.stringParamVars, memo),
1286 stringAliasVars = SimVar.convertListMemo(simVars.stringAliasVars, memo),
1287 extObjVars = SimVar.convertListMemo(simVars.extObjVars, memo),
1288 constVars = SimVar.convertListMemo(simVars.constVars, memo),
1289 intConstVars = SimVar.convertListMemo(simVars.intConstVars, memo),
1290 boolConstVars = SimVar.convertListMemo(simVars.boolConstVars, memo),
1291 stringConstVars = SimVar.convertListMemo(simVars.stringConstVars, memo),
1292 jacobianVars = SimVar.convertListMemo(simVars.jacobianVars, memo),
1293 seedVars = SimVar.convertListMemo(simVars.seedVars, memo),
1294 realOptimizeConstraintsVars = SimVar.convertListMemo(simVars.realOptimizeConstraintsVars, memo),
1295 realOptimizeFinalConstraintsVars = SimVar.convertListMemo(simVars.realOptimizeFinalConstraintsVars, memo),
1296 sensitivityVars = SimVar.convertListMemo(simVars.sensitivityVars, memo),
1297 dataReconSetcVars = SimVar.convertListMemo(simVars.dataReconSetcVars, memo),
1298 dataReconinputVars = SimVar.convertListMemo(simVars.dataReconinputVars, memo),
1299 dataReconSetBVars = SimVar.convertListMemo(simVars.dataReconSetBVars, memo));
1300 end convert;
1301
1302 function createSimVarLists
1303 "creates a list of simvar lists. SplitType.NONE always returns a list with only
1304 one list as its element and SplitType.TYPE returns a list with four lists."
1305 input VariablePointers vars;
1306 output list<list<SimVar>> simVars = {};
1307 input output SimCode.SimCodeIndices simCodeIndices;
1308 input SplitType splitType;
1309 input VarType varType;
1310 protected
1311 // scalarize goes through fromList, whose cref dedupe a record and its elements rely on
1312 list<Pointer<Variable>> sim_vars = VariablePointers.toList(if Flags.getConfigBool(Flags.SIM_CODE_SCALARIZE) then VariablePointers.scalarize(vars) else vars);
1313 list<SimVar> lst;
1314 algorithm
1315
1316
2/2
✓ Branch 0 taken 1128 times.
✓ Branch 1 taken 1316 times.
2444 if splitType == SplitType.NONE then
1317 1128 (lst, simCodeIndices) := SimVar.createList(sim_vars, varType, simCodeIndices);
1318 simVars := {lst};
1319 elseif splitType == SplitType.TYPE then
1320 1316 (simVars, simCodeIndices) := SimVar.createListsByType(sim_vars, varType, simCodeIndices);
1321 else
1322 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of invalid splitType."});
1323 end if;
1324 end createSimVarLists;
1325
1326 function getPartitionVars
1327 input Partition partition;
1328 input UnorderedMap<ComponentRef, SimVar> simcode_map;
1329 output list<SimVar> part_vars;
1330 algorithm
1331 part_vars := match partition.strongComponents
1332 local
1333 array<StrongComponent> comps;
1334 list<list<SimVar>> result = {};
1335
1336 case SOME(comps) algorithm
1337
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
42 for i in 1:arrayLength(comps) loop
1338 24 result := getStrongComponentVars(comps[i], simcode_map) :: result;
1339 end for;
1340 18 then List.flatten(result);
1341
1342 else algorithm
1343 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for\n" + Partition.Partition.toString(partition)});
1344 ✗ then fail();
1345 end match;
1346 end getPartitionVars;
1347
1348 function getStrongComponentVars
1349 input StrongComponent comp;
1350 input UnorderedMap<ComponentRef, SimVar> simcode_map;
1351 output list<SimVar> part_vars = {};
1352 algorithm
1353 part_vars := match comp
1354 24 case StrongComponent.SINGLE_COMPONENT() then getVars(comp.var, simcode_map);
1355 ✗ case StrongComponent.MULTI_COMPONENT() then List.flatten(list(getVars(Slice.getT(v), simcode_map) for v in comp.vars));
1356 ✗ case StrongComponent.SLICED_COMPONENT() then getVars(Slice.getT(comp.var), simcode_map);
1357 ✗ case StrongComponent.RESIZABLE_COMPONENT() then getVars(Slice.getT(comp.var), simcode_map);
1358 ✗ case StrongComponent.GENERIC_COMPONENT() then getVars(BVariable.getVarPointer(comp.var_cref, sourceInfo()), simcode_map);
1359 ✗ case StrongComponent.ENTWINED_COMPONENT() then List.flatten(list(getStrongComponentVars(c, simcode_map) for c in comp.entwined_slices));
1360 ✗ case StrongComponent.ALGEBRAIC_LOOP() then List.flatten(list(getVars(Slice.getT(v), simcode_map) for v in comp.strict.iteration_vars));
1361 ✗ case StrongComponent.ALIAS() then getStrongComponentVars(comp.original, simcode_map);
1362 else algorithm
1363 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed with unknown reason for\n" + StrongComponent.toString(comp)});
1364 ✗ then fail();
1365 end match;
1366 end getStrongComponentVars;
1367
1368 public
1369 function numScalarElems
1370 "Total scalar element count across a list of SimVars, independent of the
1371 codegen target. Unlike listScalarSize, always returns the product of
1372 dimension sizes (not listLength). Used by NBackEnd Jacobian generation
1373 to compute the correct number of columns/rows when --simCodeScalarize=false
1374 yields array SimVars (e.g. x[100] is one SimVar with numArrayElement=[100])."
1375 input list<SimVar> vars;
1376 output Integer n;
1377 algorithm
1378
8/8
✓ Branch 0 taken 2910 times.
✓ Branch 1 taken 334 times.
✓ Branch 2 taken 2910 times.
✓ Branch 3 taken 334 times.
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 2910 times.
✓ Branch 6 taken 68 times.
✓ Branch 7 taken 2910 times.
3312 n := sum(product(Expression.integerValueOrDefault(e, 1) for e in v.numArrayElement) for v in vars);
1379 end numScalarElems;
1380
1381 protected
1382 function getVars
1383 input Pointer<Variable> var;
1384 input UnorderedMap<ComponentRef, SimVar> simcode_map;
1385 output list<SimVar> vars = {};
1386 algorithm
1387
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 if Flags.getConfigBool(Flags.SIM_CODE_SCALARIZE) then
1388
4/4
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 24 times.
48 vars := list(UnorderedMap.getSafe(BVariable.getVarName(v), simcode_map, sourceInfo()) for v in VariablePointers.scalarizeList({var}));
1389 else
1390 ✗ vars := {UnorderedMap.getSafe(BVariable.getVarName(var), simcode_map, sourceInfo())};
1391 end if;
1392 end getVars;
1393
1394 end SimVars;
1395
1396 constant SimVars emptySimVars = SIMVARS(
1397 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
1398 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});
1399
1400 type SplitType = enumeration(NONE, TYPE);
1401 type VarType = enumeration(SIMULATION, PARAMETER, ALIAS, RESIDUAL, EXTERNAL_OBJECT); // ToDo: PRE, OLD, RELATIONS...
1402
1403 uniontype VarInfo
1404 record VAR_INFO
1405 Integer numZeroCrossings;
1406 Integer numTimeEvents;
1407 Integer numRelations;
1408 Integer numMathEventFunctions;
1409 Integer numStateVars;
1410 Integer numAlgVars;
1411 Integer numDiscreteReal;
1412 Integer numIntAlgVars;
1413 Integer numBoolAlgVars;
1414 Integer numAlgAliasVars;
1415 Integer numIntAliasVars;
1416 Integer numBoolAliasVars;
1417 Integer numParams;
1418 Integer numIntParams;
1419 Integer numBoolParams;
1420 Integer numOutVars;
1421 Integer numInVars;
1422 Integer numExternalObjects;
1423 Integer numStringAlgVars;
1424 Integer numStringParamVars;
1425 Integer numStringAliasVars;
1426 Integer numEquations;
1427 Integer numLinearSystems;
1428 Integer numNonLinearSystems;
1429 Integer numMixedSystems;
1430 Integer numStateSets;
1431 Integer numJacobians;
1432 Integer numOptimizeConstraints;
1433 Integer numOptimizeFinalConstraints;
1434 Integer numSensitivityParameters;
1435 Integer numSetcVars;
1436 Integer numDataReconVars;
1437 Integer numRealIntputVars;
1438 Integer numSetbVars;
1439 Integer numRelatedBoundaryConditions;
1440 end VAR_INFO;
1441
1442 function listScalarSize
1443 "Var-vector size for a simvar list. The C++ target keeps arrays un-expanded
1444 but sizes its var vectors and value references per scalar element, so the
1445 array sizes are summed. Every other target (notably the C runtime, which
1446 also supports simCodeScalarize=false) keeps one slot per simvar."
1447 input list<SimVar> vars;
1448 output Integer sz;
1449 algorithm
1450
3/4
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 2618 times.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
2632 if stringEqual(Config.simCodeTarget(), "Cpp") then
1451
8/8
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 4 times.
21 sz := sum(product(Expression.integerValueOrDefault(e, 1) for e in v.numArrayElement) for v in vars);
1452 else
1453 2618 sz := listLength(vars);
1454 end if;
1455 end listScalarSize;
1456
1457 function create
1458 input SimVars vars;
1459 input EventInfo eventInfo;
1460 input SimCodeIndices simCodeIndices;
1461 output VarInfo varInfo;
1462 algorithm
1463
17/22
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 188 times.
✓ Branch 3 taken 82 times.
✓ Branch 4 taken 188 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 188 times.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 188 times.
✓ Branch 12 taken 82 times.
✓ Branch 13 taken 188 times.
✓ Branch 14 taken 82 times.
✓ Branch 15 taken 188 times.
✓ Branch 17 taken 11 times.
✓ Branch 18 taken 188 times.
✓ Branch 19 taken 11 times.
✓ Branch 20 taken 188 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 11 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
368 varInfo := VAR_INFO(
1464 numZeroCrossings = sum(Condition.size(cond) for cond in UnorderedMap.keyList(eventInfo.state_map)) + sum(MathEvent.numZeroCrossings(mev) for mev in eventInfo.math_lst),
1465 numTimeEvents = UnorderedSet.size(eventInfo.time_set),
1466 numRelations = sum(Condition.numRelations(cond) for cond in UnorderedMap.keyList(eventInfo.state_map)),
1467 numMathEventFunctions = eventInfo.numberMathEvents,
1468 numStateVars = listScalarSize(vars.stateVars),
1469 numAlgVars = listScalarSize(vars.algVars),
1470 numDiscreteReal = listScalarSize(vars.discreteAlgVars),
1471 numIntAlgVars = listScalarSize(vars.intAlgVars),
1472 numBoolAlgVars = listScalarSize(vars.boolAlgVars),
1473 numAlgAliasVars = listScalarSize(vars.aliasVars),
1474 numIntAliasVars = listScalarSize(vars.intAliasVars),
1475 numBoolAliasVars = listScalarSize(vars.boolAliasVars),
1476 numParams = listScalarSize(vars.paramVars),
1477 numIntParams = listScalarSize(vars.intParamVars),
1478 numBoolParams = listScalarSize(vars.boolParamVars),
1479 numOutVars = listLength(vars.outputVars),
1480 // one value per scalar input in simulationInfo->inputVars, also for the C target
1481 numInVars = sum(if Type.isArray(v.type_) then product(Expression.integerValueOrDefault(e, 1) for e in v.numArrayElement) else 1 for v in vars.inputVars),
1482 numExternalObjects = listLength(vars.extObjVars),
1483 numStringAlgVars = listScalarSize(vars.stringAlgVars),
1484 numStringParamVars = listScalarSize(vars.stringParamVars),
1485 numStringAliasVars = listScalarSize(vars.stringAliasVars),
1486 numEquations = simCodeIndices.equationIndex,
1487 numLinearSystems = simCodeIndices.linearSystemIndex,
1488 numNonLinearSystems = simCodeIndices.nonlinearSystemIndex,
1489 numMixedSystems = 0,
1490 numStateSets = 0,
1491 numJacobians = simCodeIndices.nonlinearSystemIndex + simCodeIndices.linearSystemIndex + 5, // #nonlinSystems + #linSystems (torn linear systems with a symbolic Jacobian consume a jacobianIndex slot from the same analyticJacobians array too) + 5 simulation jacs (add state sets later!)
1492 numOptimizeConstraints = 0,
1493 numOptimizeFinalConstraints = 0,
1494 numSensitivityParameters = 0,
1495 numSetcVars = 0,
1496 numDataReconVars = 0,
1497 numRealIntputVars = 0,
1498 numSetbVars = 0,
1499 numRelatedBoundaryConditions = 0);
1500 end create;
1501
1502 function convert
1503 input VarInfo varInfo;
1504 output OldSimCode.VarInfo oldVarInfo;
1505 algorithm
1506 376 oldVarInfo := OldSimCode.VARINFO(
1507 numZeroCrossings = varInfo.numZeroCrossings,
1508 numTimeEvents = varInfo.numTimeEvents,
1509 numRelations = varInfo.numRelations,
1510 numMathEventFunctions = varInfo.numMathEventFunctions,
1511 numStateVars = varInfo.numStateVars,
1512 numAlgVars = varInfo.numAlgVars,
1513 numDiscreteReal = varInfo.numDiscreteReal,
1514 numIntAlgVars = varInfo.numIntAlgVars,
1515 numBoolAlgVars = varInfo.numBoolAlgVars,
1516 numAlgAliasVars = varInfo.numAlgAliasVars,
1517 numIntAliasVars = varInfo.numIntAliasVars,
1518 numBoolAliasVars = varInfo.numBoolAliasVars,
1519 numParams = varInfo.numParams,
1520 numIntParams = varInfo.numIntParams,
1521 numBoolParams = varInfo.numBoolParams,
1522 numOutVars = varInfo.numOutVars,
1523 numInVars = varInfo.numInVars,
1524 numExternalObjects = varInfo.numExternalObjects,
1525 numStringAlgVars = varInfo.numStringAlgVars,
1526 numStringParamVars = varInfo.numStringParamVars,
1527 numStringAliasVars = varInfo.numStringAliasVars,
1528 numEquations = varInfo.numEquations,
1529 numLinearSystems = varInfo.numLinearSystems,
1530 numNonLinearSystems = varInfo.numNonLinearSystems,
1531 numMixedSystems = varInfo.numMixedSystems,
1532 numStateSets = varInfo.numStateSets,
1533 numJacobians = varInfo.numJacobians,
1534 numOptimizeConstraints = varInfo.numOptimizeConstraints,
1535 numOptimizeFinalConstraints = varInfo.numOptimizeFinalConstraints,
1536 numSensitivityParameters = varInfo.numSensitivityParameters,
1537 numSetcVars = varInfo.numSetcVars,
1538 numDataReconVars = varInfo.numDataReconVars,
1539 numRealInputVars = varInfo.numRealIntputVars,
1540 numSetbVars = varInfo.numSetbVars,
1541 numRelatedBoundaryConditions = varInfo.numRelatedBoundaryConditions);
1542 end convert;
1543 end VarInfo;
1544
1545 uniontype ExtObjInfo
1546 record EXT_OBJ_INFO
1547 list<SimVar> objects;
1548 list<tuple<ComponentRef, ComponentRef>> aliases;
1549 end EXT_OBJ_INFO;
1550
1551
1552 function toString
1553 input ExtObjInfo info;
1554 output String str = SimVar.listToString(info.objects, "External Objects");
1555 end toString;
1556
1557 function create
1558 input VariablePointers external_objects;
1559 output ExtObjInfo info;
1560 input output SimVars vars;
1561 input output SimCodeIndices simCodeIndices;
1562 protected
1563 list<SimVar> var_lst;
1564 algorithm
1565 188 (var_lst, simCodeIndices) := SimVar.createList(VariablePointers.toList(external_objects), VarType.EXTERNAL_OBJECT, simCodeIndices);
1566 188 vars.extObjVars := var_lst;
1567 // todo: alias
1568 188 info := EXT_OBJ_INFO(var_lst, {});
1569 end create;
1570
1571 function convert
1572 input ExtObjInfo info;
1573 output OldSimCode.ExtObjInfo oldInfo;
1574 algorithm
1575 188 oldInfo := OldSimCode.EXTOBJINFO(SimVar.convertList(info.objects), {});
1576 end convert;
1577 end ExtObjInfo;
1578
1579 annotation(__OpenModelica_Interface="nbackend");
1580 end NSimVar;
1581