Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 67.7% 376 / 0 / 555
Functions: -% 0 / 1 / 1
Branches: 67.3% 179 / 0 / 266

OMCompiler/Compiler/NBackEnd/Classes/NBVariable.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 NBVariable
37 " file: NBVariable.mo
38 description: This ONLY contains the backend variable functions!
39 ===================================================================
40 kabdelhak: The Variable declarations for this file are defined in
41 NFVariable.mo to avoid that the FrontEnd depends on the BackEnd
42 due to the component references containing an InstNode with a
43 pointer to a variable.
44 ===================================================================
45 "
46
47 public
48 //OF Imports
49 import SCodeUtil;
50
51 //NF Imports
52 import Attributes = NFAttributes;
53 import BackendExtension = NFBackendExtension;
54 import NFBackendExtension.{BackendInfo, StateSelect, TearingSelect, VariableAttributes, VariableKind, OptimizerExpression};
55 import NFBinding.Binding;
56 import Ceval = NFCeval;
57 import Class = NFClass;
58 import ComponentRef = NFComponentRef;
59 import Dimension = NFDimension;
60 import Expression = NFExpression;
61 import NFInstNode.InstNode;
62 import Prefixes = NFPrefixes;
63 import Scalarize = NFScalarize;
64 import SimplifyExp = NFSimplifyExp;
65 import Subscript = NFSubscript;
66 import Type = NFType;
67 import Variable = NFVariable;
68
69 // Backend Imports
70 import NBAdjacency.Mapping;
71 import BackendDAE = NBackendDAE;
72 import BackendUtil = NBBackendUtil;
73 import BEquation = NBEquation;
74 import NBEquation.Iterator;
75 import BVariable = NBVariable;
76
77 //Util Imports
78 import Array;
79 import BaseHashTable;
80 import ExpandableArray;
81 import Slice = NBSlice;
82 import StringUtil;
83 import Global;
84 import PointerWeak;
85 import UnorderedMap;
86 import Util;
87
88 public
89 // mainly used for mapping purposes
90 type VariablePointer = Pointer<Variable>;
91 type VarSlice = Slice<Pointer<Variable>>;
92
93 // ==========================================================================
94 // Single Variable constants and functions
95 // ==========================================================================
96 constant Variable DUMMY_VARIABLE = Variable.VARIABLE(ComponentRef.EMPTY(), Type.ANY(),
97 NFBinding.EMPTY_BINDING, NFPrefixes.Visibility.PUBLIC, NFAttributes.DEFAULT_ATTR,
98 {}, {}, SCode.noComment, SCodeUtil.dummyInfo, NFBackendExtension.DUMMY_BACKEND_INFO);
99
100 constant Variable SUBST_VARIABLE = Variable.VARIABLE(NFBuiltin.SUBST_CREF, Type.ANY(),
101 NFBinding.EMPTY_BINDING, NFPrefixes.Visibility.PUBLIC, NFAttributes.DEFAULT_ATTR,
102 {}, {}, SCode.noComment, SCodeUtil.dummyInfo, NFBackendExtension.DUMMY_BACKEND_INFO);
103
104 constant Variable TIME_VARIABLE = Variable.VARIABLE(NFBuiltin.TIME_CREF, Type.REAL(),
105 NFBinding.EMPTY_BINDING, NFPrefixes.Visibility.PUBLIC, NFAttributes.DEFAULT_ATTR,
106 {}, {}, SCode.noComment, SCodeUtil.dummyInfo, BackendInfo.BACKEND_INFO(
107 VariableKind.TIME(), NFBackendExtension.EMPTY_VAR_ATTR_REAL, NFBackendExtension.EMPTY_ANNOTATIONS, NONE(), NONE(), NONE(), NONE(), NONE(), NONE()));
108
109 constant String DERIVATIVE_STR = "$DER";
110 constant String DUMMY_DERIVATIVE_STR = "$dDER";
111 constant String PARTIAL_DERIVATIVE_STR = "$pDER";
112 constant String FUNCTION_DERIVATIVE_STR = "$fDER";
113 constant String FUNCTION_STR = "$FUN";
114 constant String PREVIOUS_STR = "$PRE";
115 constant String AUXILIARY_STR = "$AUX";
116 constant String STATE_ALIAS_STR = "$STA";
117 constant String DUMMY_ALIAS_STR = "$DUM";
118 constant String START_STR = "$START";
119 constant String RESIDUAL_STR = "$RES";
120 constant String TEMPORARY_STR = "$TMP";
121 constant String SEED_STR = "$SEED";
122 constant String TIME_EVENT_STR = "$TEV";
123 constant String STATE_EVENT_STR = "$SEV";
124 constant String WHEN_CONDITION_STR = "$WC";
125 constant String CLOCK_STR = "$CLK";
126
127 function toString
128 input Variable var;
129 input output String str = "";
130 protected
131 String attr;
132 algorithm
133 1068 attr := VariableAttributes.toString(var.backendinfo.attributes);
134
3/4
✓ Branch 9 taken 1053 times.
✓ Branch 10 taken 15 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1053 times.
1068 str := str + VariableKind.toString(var.backendinfo.varKind) + " (" + intString(Variable.size(var, true)) + ") " + Variable.toString(var) + (if attr == "" then "" else " " + attr);
135 end toString;
136
137 function pointerToString
138 input Pointer<Variable> var_ptr;
139 output String str = toString(Pointer.access(var_ptr));
140 end pointerToString;
141
142 function nameString
143 input Pointer<Variable> var_ptr;
144 output String str = ComponentRef.toString(getVarName(var_ptr));
145 end nameString;
146
147 function hash
148 input Pointer<Variable> var_ptr;
149 output Integer i = Variable.hash(Pointer.access(var_ptr));
150 end hash;
151
152 function equalName
153 input Pointer<Variable> var_ptr1;
154 input Pointer<Variable> var_ptr2;
155 output Boolean b = Variable.equalName(Pointer.access(var_ptr1), Pointer.access(var_ptr2));
156 end equalName;
157
158 function size
159 input Pointer<Variable> var_ptr;
160 input Boolean resize = false;
161 output Integer s = Variable.size(Pointer.access(var_ptr), resize);
162 end size;
163
164 function applyToType
165 input Pointer<Variable> var_ptr;
166 input typeFunc func;
167 partial function typeFunc
168 input output Type ty;
169 end typeFunc;
170 protected
171 Variable new, var = Pointer.access(var_ptr);
172 algorithm
173 108 new := Variable.applyToType(var, func);
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if not referenceEq(var, new) then
175 108 Pointer.update(var_ptr, new);
176 end if;
177 end applyToType;
178
179 function fromCref
180 input ComponentRef cref;
181 input Attributes attr = NFAttributes.DEFAULT_ATTR;
182 input Binding binding = NFBinding.EMPTY_BINDING;
183 output Variable variable;
184 protected
185 InstNode node, class_node;
186 array<InstNode> child_nodes;
187 Type ty, elem_ty;
188 Prefixes.Visibility vis;
189 SourceInfo info;
190 list<Variable> children = {};
191 algorithm
192 15254 node := ComponentRef.node(cref);
193 15254 ty := ComponentRef.getSubscriptedType(cref, true);
194 15254 vis := InstNode.visibility(node);
195 15254 info := InstNode.info(node);
196 // get the record children if the variable is a record (and not an external object)
197
2/2
✓ Branch 1 taken 15251 times.
✓ Branch 2 taken 3 times.
15254 if not Type.isExternalObject(ty) then
198 children := match Type.arrayElementType(ty)
199 case elem_ty as Type.COMPLEX() algorithm
200 313 class_node := Type.complexNode(elem_ty);
201 313 child_nodes := Class.getComponents(InstNode.getClass(class_node));
202
4/4
✓ Branch 0 taken 741 times.
✓ Branch 1 taken 313 times.
✓ Branch 3 taken 741 times.
✓ Branch 4 taken 313 times.
2108 children := list(fromCref(ComponentRef.prefixCref(c, InstNode.getType(c), {}, cref)) for c in child_nodes);
203 then children;
204 else {};
205 end match;
206 end if;
207
208 15254 variable := Variable.VARIABLE(cref, ty, binding, vis, attr, {}, children, SCode.noComment, info, NFBackendExtension.DUMMY_BACKEND_INFO);
209 end fromCref;
210
211 function makeVarPtr
212 "Needs a prepared variable and name cref and links a pointer to the variable
213 with its component reference. The cref holds the variable weakly, so the run
214 owns it until it reaches `VariablePointers` -- which is not immediate,
215 NBFunctionAlias reads the cref back first."
216 input Variable var;
217 output Pointer<Variable> var_ptr;
218 input output ComponentRef name;
219 protected
220 list<Pointer<Variable>> created;
221 algorithm
222 27213 var_ptr := Pointer.create(var);
223 27213 created := getGlobalRoot(Global.nbCreatedVars);
224 27213 setGlobalRoot(Global.nbCreatedVars, var_ptr :: created);
225 27213 name := BackendDAE.lowerComponentReferenceInstNode(name, var_ptr);
226 27213 var.name := name;
227 27213 Pointer.update(var_ptr, var);
228 end makeVarPtr;
229
230 function connectPartners
231 "sets the partner for the variable and also sets the variable pointer at the partner variable"
232 input Pointer<Variable> var_ptr;
233 input Pointer<Variable> par_ptr;
234 input BackendInfo.setPartner func;
235 protected
236 Variable var = Pointer.access(var_ptr);
237 Variable par = Pointer.access(par_ptr);
238 algorithm
239
2/2
✓ Branch 0 taken 1189 times.
✓ Branch 1 taken 827 times.
2016 var.backendinfo := func(var.backendinfo, SOME(par_ptr));
240
2/2
✓ Branch 0 taken 1189 times.
✓ Branch 1 taken 827 times.
2016 par.backendinfo := func(par.backendinfo, SOME(var_ptr));
241 2016 Pointer.update(var_ptr, var);
242 2016 Pointer.update(par_ptr, par);
243 end connectPartners;
244
245 function removePartner
246 "removes the partner for the variable"
247 input Pointer<Variable> var_ptr;
248 input BackendInfo.setPartner func;
249 protected
250 Variable var = Pointer.access(var_ptr);
251 algorithm
252 ✗ var.backendinfo := func(var.backendinfo, NONE());
253 ✗ Pointer.update(var_ptr, var);
254 end removePartner;
255
256 function getVar
257 input ComponentRef cref;
258 input SourceInfo info;
259 output Variable var;
260 algorithm
261 10086 var := Pointer.access(getVarPointer(cref, info));
262 end getVar;
263
264 // The following functions provide layers of protection. Whenever accessing names or pointers use these!
265 function getVarPointer
266 input ComponentRef cref;
267 input SourceInfo info;
268 output Pointer<Variable> var;
269 algorithm
270 var := match cref
271 local
272 PointerWeak<Variable> varPointer;
273 case ComponentRef.CREF() guard InstNode.isVar(ComponentRef.node(cref))
274 181733 then PointerWeak.upgrade(InstNode.varPointer(ComponentRef.node(cref)));
275 88 case ComponentRef.CREF() guard InstNode.isName(ComponentRef.node(cref)) then Pointer.create(DUMMY_VARIABLE);
276 ✗ case ComponentRef.WILD() then Pointer.create(DUMMY_VARIABLE);
277 else algorithm
278 ✗ Error.addInternalError(getInstanceName() + " failed for " + ComponentRef.toString(cref) +
279 ", because of wrong InstNode (not VAR_NODE). Show lowering errors with -d=failtrace.", info);
280 ✗ then fail();
281 end match;
282 end getVarPointer;
283
284 function getVarName
285 input Pointer<Variable> var_ptr;
286 output ComponentRef name;
287 protected
288 Variable var = Pointer.access(var_ptr);
289 algorithm
290 344342 name := var.name;
291 end getVarName;
292
293 function setVarName
294 input output Pointer<Variable> var_ptr;
295 input ComponentRef name;
296 protected
297 Variable var = Pointer.access(var_ptr);
298 algorithm
299 116 var.name := name;
300 116 Pointer.update(var_ptr, var);
301 end setVarName;
302
303 function subIdxName
304 "creates new variable pointer to not change the old variable!"
305 input output Pointer<Variable> var_ptr;
306 input Pointer<Integer> index;
307 protected
308 Variable var = Pointer.access(var_ptr);
309 algorithm
310 ✗ var.name := ComponentRef.rename(ComponentRef.firstName(var.name) + "_" + intString(Pointer.access(index)), var.name);
311 ✗ var_ptr := Pointer.create(var);
312 end subIdxName;
313
314 function getVarKind
315 input Pointer<Variable> var_ptr;
316 output VariableKind kind;
317 protected
318 Variable var = Pointer.access(var_ptr);
319 algorithm
320 3855 kind := BackendInfo.getVarKind(var.backendinfo);
321 end getVarKind;
322
323 function toExpression
324 input Pointer<Variable> var_ptr;
325 output Expression exp = Expression.fromCref(getVarName(var_ptr));
326 end toExpression;
327
328 partial function checkVar
329 input Pointer<Variable> var_ptr;
330 output Boolean b;
331 protected
332 Variable var = Pointer.access(var_ptr);
333 end checkVar;
334
335 function isArray extends checkVar;
336 algorithm
337 4886 b := Type.isArray(var.ty);
338 end isArray;
339
340 function getDimensions
341 input Pointer<Variable> var_ptr;
342 output List<Dimension> dims;
343 protected
344 Variable var;
345 algorithm
346 ✗ var := Pointer.access(var_ptr);
347 ✗ dims := Type.arrayDims(var.ty);
348 end getDimensions;
349
350 function isEmpty extends checkVar;
351 algorithm
352 ✗ b := ComponentRef.isEmpty(var.name);
353 end isEmpty;
354
355 function isForcedState extends checkVar;
356 algorithm
357 b := match var.backendinfo.varKind
358 local
359 Boolean natural;
360 86 case VariableKind.STATE(natural = natural) then not natural;
361 else false;
362 end match;
363 end isForcedState;
364
365 function isState extends checkVar;
366 algorithm
367 b := match var.backendinfo.varKind
368 case VariableKind.STATE() then true;
369 else false;
370 end match;
371 end isState;
372
373 function isStateDerivative extends checkVar;
374 algorithm
375 b := match var.backendinfo.varKind
376 case VariableKind.STATE_DER() then true;
377 else false;
378 end match;
379 end isStateDerivative;
380
381 function isAlgebraic extends checkVar;
382 algorithm
383 b := match var.backendinfo.varKind
384 case VariableKind.ALGEBRAIC() then true;
385 else false;
386 end match;
387 end isAlgebraic;
388
389 function isStart extends checkVar;
390 algorithm
391 b := match var.backendinfo.varKind
392 case VariableKind.START() then true;
393 else false;
394 end match;
395 end isStart;
396
397 function isExtObj extends checkVar;
398 algorithm
399 b := match var.backendinfo.varKind
400 case VariableKind.EXTOBJ() then true;
401 else false;
402 end match;
403 end isExtObj;
404
405 function isTime extends checkVar;
406 algorithm
407 b := match var.backendinfo.varKind
408 case VariableKind.TIME() then true;
409 else false;
410 end match;
411 end isTime;
412
413 function isContinuous extends checkVar;
414 input Boolean staticAsContinuous "true if it's an initial system / static variables (e.g. parameters) that are constant over time, are in a variable context";
415 algorithm
416 b := match var.backendinfo.varKind
417 case VariableKind.DISCRETE_STATE() then false; // like parameter?
418 case VariableKind.DISCRETE() then false; // like parameter?
419 case VariableKind.PREVIOUS() then false; // like parameter?
420 case VariableKind.CONSTANT() then false;
421 case VariableKind.ITERATOR() then false;
422 case VariableKind.EXTOBJ() then false;
423
4/4
✓ Branch 0 taken 1111 times.
✓ Branch 1 taken 82 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 1090 times.
1193 case VariableKind.PARAMETER() then staticAsContinuous and Type.isContinuous(var.ty);
424
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 57 times.
153 case VariableKind.RECORD() then List.all(getRecordChildren(var_ptr), function isContinuous(staticAsContinuous = staticAsContinuous));
425 else true;
426 end match;
427 end isContinuous;
428
429 function isDiscontinuous "only for function interface purposes" extends checkVar;
430 input Boolean staticAsContinuous "true if it's an initial system / static variables (e.g. parameters) that are constant over time, are in a variable context";
431 algorithm
432 ✗ b := not isContinuous(var_ptr, staticAsContinuous);
433 end isDiscontinuous;
434
435 function isContinuousRecordAware
436 "acts like isContinous, but returns false if it is part of a record that has a discrete variable"
437 extends checkVar;
438 input Boolean staticAsContinuous "true if it's an initial system / static variables (e.g. parameters) that are constant over time, are in a variable context";
439 algorithm
440 b := match getParent(var_ptr)
441 local
442 Pointer<Variable> parent;
443 ✗ case SOME(parent) then isContinuousRecordAware(parent, staticAsContinuous);
444 ✗ else isContinuous(var_ptr, staticAsContinuous);
445 end match;
446 end isContinuousRecordAware;
447
448 function isDiscreteState extends checkVar;
449 algorithm
450 b := match var.backendinfo.varKind
451 case VariableKind.DISCRETE_STATE() then true;
452 else false;
453 end match;
454 end isDiscreteState;
455
456 function isDiscrete extends checkVar;
457 algorithm
458 b := match var.backendinfo.varKind
459 case VariableKind.DISCRETE() then true;
460 else false;
461 end match;
462 end isDiscrete;
463
464 function isPrevious extends checkVar;
465 algorithm
466 b := match var.backendinfo.varKind
467 case VariableKind.PREVIOUS() then true;
468 else false;
469 end match;
470 end isPrevious;
471
472 function isRecord extends checkVar;
473 algorithm
474 b := match var.backendinfo.varKind
475 case VariableKind.RECORD() then true;
476 else false;
477 end match;
478 end isRecord;
479
480 function isKnownRecord extends checkVar;
481 algorithm
482 b := match var.backendinfo.varKind
483 local
484 Prefixes.Variability variability;
485 case VariableKind.RECORD(max_var = variability) guard(variability < NFPrefixes.Variability.DISCRETE) then true;
486 else false;
487 end match;
488 end isKnownRecord;
489
490 function isUnknownRecord extends checkVar;
491 algorithm
492 b := match var.backendinfo.varKind
493 local
494 Prefixes.Variability variability;
495 case VariableKind.RECORD(min_var = variability) guard(variability > NFPrefixes.Variability.NON_STRUCTURAL_PARAMETER) then true;
496 else false;
497 end match;
498 end isUnknownRecord;
499
500 function isConstRecord extends checkVar;
501 algorithm
502 b := match var.backendinfo.varKind
503 local
504 Prefixes.Variability variability;
505 case VariableKind.RECORD(max_var = variability) guard(variability == NFPrefixes.Variability.CONSTANT) then true;
506 else false;
507 end match;
508 end isConstRecord;
509
510 function isClock extends checkVar;
511 algorithm
512 b := match var.backendinfo.varKind
513 case VariableKind.CLOCK() then true;
514 else false;
515 end match;
516 end isClock;
517
518 function isClocked extends checkVar;
519 algorithm
520 b := match var.backendinfo.varKind
521 case VariableKind.CLOCKED() then true;
522 else false;
523 end match;
524 end isClocked;
525
526 function isClockOrClocked extends checkVar;
527 algorithm
528 b := match var.backendinfo.varKind
529 case VariableKind.CLOCK() then true;
530 case VariableKind.CLOCKED() then true;
531 else false;
532 end match;
533 end isClockOrClocked;
534
535 function isIterator extends checkVar;
536 algorithm
537 b := match var.backendinfo.varKind
538 case VariableKind.ITERATOR() then true;
539 else false;
540 end match;
541 end isIterator;
542
543 function isPDer extends checkVar;
544 algorithm
545 b := match var.backendinfo.varKind
546 case VariableKind.JAC_VAR() then true;
547 case VariableKind.JAC_TMP_VAR() then true;
548 else false;
549 end match;
550 end isPDer;
551
552 function hasTearingSelect
553 "checks if the variable has given tearing select.
554 When provided with different functions can also check other relations.
555 intEq, intNe, intGt, intGe, intLt, intLe"
556 input Pointer<Variable> varPointer;
557 input TearingSelect compareTS;
558 input compare func = intEq;
559 output Boolean b = func(Integer(getTearingSelect(varPointer)), Integer(compareTS));
560 partial function compare
561 input Integer i1, i2;
562 output Boolean b;
563 end compare;
564 end hasTearingSelect;
565
566 partial function getVarPartner
567 input Pointer<Variable> var_ptr;
568 output Option<Pointer<Variable>> partner;
569 output String partnerName "for error messages";
570 protected
571 Variable var = Pointer.access(var_ptr);
572 end getVarPartner;
573
574 function getVarPre
575 "Gets the pre() / previous() var if its a variable / clocked variable or the other way around."
576 extends getVarPartner;
577 algorithm
578 partnerName := "pre variable";
579 536 partner := BackendInfo.strengthen(var.backendinfo.var_pre);
580 end getVarPre;
581
582 function getVarSeed
583 "Gets the SEED var to the variable or the other way around."
584 extends getVarPartner;
585 algorithm
586 partnerName := "seed variable";
587 747 partner := BackendInfo.strengthen(var.backendinfo.var_seed);
588 end getVarSeed;
589
590 function getVarPDer
591 "Gets the partial derivative of a residual or the other way around."
592 extends getVarPartner;
593 input Boolean isTmp;
594 algorithm
595
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 1710 times.
2052 if isTmp then
596 partnerName := "partial derivative (temp)";
597 342 partner := BackendInfo.strengthen(var.backendinfo.var_pder_tmp);
598 else
599 partnerName := "partial derivative (result)";
600 1710 partner := BackendInfo.strengthen(var.backendinfo.var_pder_res);
601 end if;
602 end getVarPDer;
603
604 function getVarDer
605 "Returns the derivative from a state.
606 Only works after the state has been detected by the DetectStates module."
607 extends getVarPartner;
608 algorithm
609 partnerName := "derivative";
610 partner := match var.backendinfo.varKind
611 local Option<PointerWeak<Variable>> partner_weak;
612 case VariableKind.STATE(derivative = partner_weak)
613 628 then BackendInfo.strengthen(partner_weak);
614 else NONE();
615 end match;
616 end getVarDer;
617
618 function getVarState
619 extends getVarPartner;
620 algorithm
621 partnerName := "state";
622 partner := match var.backendinfo.varKind
623 local
624 PointerWeak<Variable> p;
625 120 case VariableKind.STATE_DER(state = p) then SOME(PointerWeak.upgrade(p));
626 else NONE();
627 end match;
628 end getVarState;
629
630 function getVarDummyDer
631 "Returns the dummy derivative from a dummy state.
632 Only works after the dummy state has been created by the IndexReduction module"
633 extends getVarPartner;
634 algorithm
635 partnerName := "dummy derivative";
636 partner := match var.backendinfo.varKind
637 local
638 PointerWeak<Variable> p;
639 40 case VariableKind.DUMMY_STATE(dummy_der = p) then SOME(PointerWeak.upgrade(p));
640 else NONE();
641 end match;
642 end getVarDummyDer;
643
644 function getVarStart
645 extends getVarPartner;
646 algorithm
647 partnerName := "start";
648 10373 partner := BackendInfo.strengthen(var.backendinfo.var_start);
649 end getVarStart;
650
651 function getPartnerCref
652 "Like getVarPartner but for cref. Fails if there is no partner."
653 input ComponentRef cref;
654 input getVarPartner func;
655 input Boolean scalarized = false;
656 output ComponentRef partner_cref;
657 protected
658 Option<Pointer<Variable>> partner;
659 String partnerName;
660 algorithm
661
2/2
✓ Branch 0 taken 862 times.
✓ Branch 1 taken 744 times.
1606 (partner, partnerName) := func(getVarPointer(cref, sourceInfo()));
662
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1606 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1606 times.
1606 if isSome(partner) then
663 1606 partner_cref := getVarName(Util.getOption(partner));
664
1/2
✓ Branch 0 taken 1606 times.
✗ Branch 1 not taken.
1606 if not scalarized then
665 1606 partner_cref := ComponentRef.copySubscripts(cref, partner_cref);
666 end if;
667 else
668 ✗ Error.addMessage(Error.INTERNAL_ERROR,
669 {getInstanceName() + " failed because " + ComponentRef.toString(cref)
670 + " has no corresponding " + partnerName + "."});
671 ✗ fail();
672 end if;
673 end getPartnerCref;
674
675 function hasStartAttr
676 extends checkVar;
677 algorithm
678 ✗ b := isSome(VariableAttributes.getStartAttribute(var.backendinfo.attributes));
679 end hasStartAttr;
680
681 function hasPre
682 "only returns true if the variable itself is not a pre() or previous() and has a pre() pointer set"
683 extends checkVar;
684 algorithm
685
3/6
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18 times.
18 b := not isPrevious(var_ptr) and isSome(getVarPre(var_ptr));
686 end hasPre;
687
688 function isJacobianResultVar
689 "returns true if the variable has a (non-temp or temp) result partial derivative set"
690 extends checkVar;
691 algorithm
692 b := match getVarPDer(var_ptr, false)
693 local
694 Pointer<Variable> der_var;
695 ✗ case SOME(der_var) then isJacobianResultVarPDer(der_var);
696 else match getVarPDer(var_ptr, true)
697 ✗ case SOME(der_var) then isJacobianResultVarPDer(der_var);
698 else false;
699 end match;
700 end match;
701 end isJacobianResultVar;
702
703 function isJacobianResultVarPDer
704 extends checkVar;
705 algorithm
706 b := match var.backendinfo.varKind
707 case VariableKind.JAC_VAR() then true;
708 else false;
709 end match;
710 end isJacobianResultVarPDer;
711
712
713 function isDummyState
714 extends checkVar;
715 algorithm
716 b := match var.backendinfo.varKind
717 case VariableKind.DUMMY_STATE() then true;
718 else false;
719 end match;
720 end isDummyState;
721
722 function isDummyDer
723 extends checkVar;
724 algorithm
725 b := match var.backendinfo.varKind
726 case VariableKind.DUMMY_DER() then true;
727 else false;
728 end match;
729 end isDummyDer;
730
731 function isParamOrConst
732 extends checkVar;
733 algorithm
734 b := match var.backendinfo.varKind
735 case VariableKind.PARAMETER() then true;
736 case VariableKind.CONSTANT() then true;
737 294 case VariableKind.RECORD() then isKnownRecord(var_ptr);
738 else false;
739 end match;
740 end isParamOrConst;
741
742 function isConst
743 extends checkVar;
744 algorithm
745 b := match var.backendinfo.varKind
746 case VariableKind.CONSTANT() then true;
747 356 case VariableKind.RECORD() then isConstRecord(var_ptr);
748 else false;
749 end match;
750 end isConst;
751
752 function isKnown
753 extends checkVar;
754 algorithm
755 b := match var.backendinfo.varKind
756 case VariableKind.PARAMETER() then true;
757 case VariableKind.CONSTANT() then true;
758 case VariableKind.STATE() then true;
759 ✗ case VariableKind.RECORD() then isKnownRecord(var_ptr);
760 else false;
761 end match;
762 end isKnown;
763
764 function isOptimizable
765 "Returns true if the variable is an optimizable parameter or input."
766 extends checkVar;
767 algorithm
768 b := match var.backendinfo
769 case BackendExtension.BACKEND_INFO(varKind = VariableKind.PARAMETER(), annotations = BackendExtension.ANNOTATIONS(optimizable = true)) then true;
770 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizable = true)) guard(isInput(var_ptr)) then true;
771 else false;
772 end match;
773 end isOptimizable;
774
775 function isStateOrOptimizable
776 "Returns true if the variable is a state or an optimizable parameter/input."
777 extends checkVar;
778 algorithm
779 ✗ b := isState(var_ptr) or isOptimizable(var_ptr);
780 end isStateOrOptimizable;
781
782 function isInitialTime
783 "Returns true if the variable represents the initial time t0."
784 extends checkVar;
785 protected
786 OptimizerExpression optExp;
787 algorithm
788 b := match var.backendinfo
789 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
790 ✗ then optExp == OptimizerExpression.INITIAL_TIME;
791 else false;
792 end match;
793 end isInitialTime;
794
795 function isFinalTime
796 "Returns true if the variable represents the final time tf."
797 extends checkVar;
798 protected
799 OptimizerExpression optExp;
800 algorithm
801 b := match var.backendinfo
802 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
803 ✗ then optExp == OptimizerExpression.FINAL_TIME;
804 else false;
805 end match;
806 end isFinalTime;
807
808 function isLagrange
809 "Returns true if the variable is a Lagrange term (L, integral objective)."
810 extends checkVar;
811 protected
812 OptimizerExpression optExp;
813 algorithm
814 b := match var.backendinfo
815 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
816 ✗ then optExp == OptimizerExpression.LAGRANGE;
817 else false;
818 end match;
819 end isLagrange;
820
821 function isMayer
822 "Returns true if the variable is a Mayer term (M, terminal objective)."
823 extends checkVar;
824 protected
825 OptimizerExpression optExp;
826 algorithm
827 b := match var.backendinfo
828 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
829 ✗ then optExp == OptimizerExpression.MAYER;
830 else false;
831 end match;
832 end isMayer;
833
834 function isPathConstraint
835 "Returns true if the variable is a path constraint (g, active over the horizon)."
836 extends checkVar;
837 protected
838 OptimizerExpression optExp;
839 algorithm
840 b := match var.backendinfo
841 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
842 ✗ then optExp == OptimizerExpression.PATH_CONSTRAINT;
843 else false;
844 end match;
845 end isPathConstraint;
846
847 function isFinalConstraint
848 "Returns true if the variable is a final constraint (rf, evaluated at tf)."
849 extends checkVar;
850 protected
851 OptimizerExpression optExp;
852 algorithm
853 b := match var.backendinfo
854 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
855 ✗ then optExp == OptimizerExpression.FINAL_CONSTRAINT;
856 else false;
857 end match;
858 end isFinalConstraint;
859
860 function isInitialConstraint
861 "Returns true if the variable is an initial constraint (r0, evaluated at t0)."
862 extends checkVar;
863 protected
864 OptimizerExpression optExp;
865 algorithm
866 b := match var.backendinfo
867 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
868 ✗ then optExp == OptimizerExpression.INITIAL_CONSTRAINT;
869 else false;
870 end match;
871 end isInitialConstraint;
872
873 function isLfgFunction
874 "Returns true if the variable is a row of the LFG Jacobian: Lagrange (L), state derivative (f), or path constraint (g)."
875 extends checkVar;
876 protected
877 OptimizerExpression optExp;
878 algorithm
879 ✗ if isStateDerivative(var_ptr) then
880 b := true;
881 ✗ return;
882 end if;
883 b := match var.backendinfo
884 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
885 ✗ then optExp == OptimizerExpression.LAGRANGE or optExp == OptimizerExpression.PATH_CONSTRAINT;
886 else false;
887 end match;
888 end isLfgFunction;
889
890 function isMrfFunction
891 "Returns true if the variable is a row of the MRF Jacobian: Mayer term (M) or final constraint (rf)."
892 extends checkVar;
893 protected
894 OptimizerExpression optExp;
895 algorithm
896 b := match var.backendinfo
897 case BackendExtension.BACKEND_INFO(annotations = BackendExtension.ANNOTATIONS(optimizerExpression = SOME(optExp)))
898 ✗ then optExp == OptimizerExpression.MAYER or optExp == OptimizerExpression.FINAL_CONSTRAINT;
899 else false;
900 end match;
901 end isMrfFunction;
902
903 function isLfgVariable
904 "Lfg seed candidates: x (states), u (controls) and p (parameters), excludes t0 and tf."
905 extends checkVar;
906 algorithm
907 ✗ b := not (isFinalTime(var_ptr) or isInitialTime(var_ptr));
908 end isLfgVariable;
909
910 function isMrfVariable
911 "Mrf seed candidates: x (states), u (controls) at final time, p (parameters) and tf (final time), excludes t0."
912 extends checkVar;
913 algorithm
914 ✗ b := not isInitialTime(var_ptr);
915 end isMrfVariable;
916
917 function isR0Variable
918 "R0 seed candidates: x (states), u (controls) at initial time, p (parameters) and t0 (initial time), excludes tf."
919 extends checkVar;
920 algorithm
921 ✗ b := not isFinalTime(var_ptr);
922 end isR0Variable;
923
924 function isResizable
925 extends checkVar;
926 algorithm
927 155 b := List.any(Type.arrayDims(var.ty), Dimension.isResizable);
928 end isResizable;
929
930 function isResizableParameter
931 extends checkVar;
932 algorithm
933 b := match var.backendinfo
934 case BackendExtension.BACKEND_INFO(varKind = VariableKind.PARAMETER(), annotations = BackendExtension.ANNOTATIONS(resizable = true))
935 then true;
936 else false;
937 end match;
938 end isResizableParameter;
939
940 function updateResizableParameter
941 input Pointer<Variable> var_ptr;
942 input UnorderedMap<ComponentRef, Expression> optimal_values;
943 protected
944 Variable var = Pointer.access(var_ptr);
945 Option<Expression> val = UnorderedMap.get(var.name, optimal_values);
946 algorithm
947 () := match (val, var.backendinfo)
948 local
949 Integer i;
950 VariableKind varKind;
951
952 case (SOME(Expression.INTEGER(i)), BackendExtension.BACKEND_INFO(varKind = varKind as VariableKind.PARAMETER(), annotations = BackendExtension.ANNOTATIONS(resizable = true))) algorithm
953 14 varKind.resize_value := SOME(i);
954 14 setVarKind(var_ptr, varKind);
955 then ();
956 else ();
957 end match;
958 end updateResizableParameter;
959
960 function getResizableValue
961 input Pointer<Variable> var_ptr;
962 output Integer val;
963 protected
964 Variable var = Pointer.access(var_ptr);
965 algorithm
966 val := match var.backendinfo
967 case BackendExtension.BACKEND_INFO(varKind = VariableKind.PARAMETER(resize_value = SOME(val))) then val;
968 else algorithm
969 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because following variable is not a resizable parameter: " + toString(var)});
970 ✗ then fail();
971 end match;
972 end getResizableValue;
973
974 function isResidual
975 extends checkVar;
976 algorithm
977 b := match var.backendinfo.varKind
978 case VariableKind.RESIDUAL_VAR() then true;
979 else false;
980 end match;
981 end isResidual;
982
983 function isSeed
984 extends checkVar;
985 algorithm
986 b := match var.backendinfo.varKind
987 case VariableKind.SEED_VAR() then true;
988 else false;
989 end match;
990 end isSeed;
991
992 function isInput
993 extends checkVar;
994 algorithm
995 47 b := var.attributes.direction == NFPrefixes.Direction.INPUT;
996 end isInput;
997
998 function isOutput
999 extends checkVar;
1000 algorithm
1001 ✗ b := var.attributes.direction == NFPrefixes.Direction.OUTPUT;
1002 end isOutput;
1003
1004 function isFixed
1005 extends checkVar;
1006 algorithm
1007 // FIXME use VariableAttributes.isFixed()?
1008 b := match var.backendinfo.attributes
1009 local
1010 Binding fixed;
1011 2515 case VariableAttributes.VAR_ATTR_REAL(fixed = SOME(fixed)) then Expression.isAllTrue(Binding.getTypedExp(fixed));
1012 68 case VariableAttributes.VAR_ATTR_INT(fixed = SOME(fixed)) then Expression.isAllTrue(Binding.getTypedExp(fixed));
1013 21 case VariableAttributes.VAR_ATTR_BOOL(fixed = SOME(fixed)) then Expression.isAllTrue(Binding.getTypedExp(fixed));
1014 11 case VariableAttributes.VAR_ATTR_STRING(fixed = SOME(fixed)) then Expression.isAllTrue(Binding.getTypedExp(fixed));
1015 2 case VariableAttributes.VAR_ATTR_ENUMERATION(fixed = SOME(fixed)) then Expression.isAllTrue(Binding.getTypedExp(fixed));
1016 else false;
1017 end match;
1018 end isFixed;
1019
1020 function isFixable
1021 "states, discretes and parameters are fixable if they are not already fixed.
1022 discrete states are always fixable. previous vars are only fixable if the discrete state for it wasn't fixed."
1023 extends checkVar;
1024 algorithm
1025 b := match var.backendinfo.varKind
1026 139 case VariableKind.STATE() then not isFixed(var_ptr);
1027
3/4
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 44 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
62 case VariableKind.DISCRETE_STATE() then not isFixed(var_ptr) or hasPre(var_ptr);
1028 237 case VariableKind.PARAMETER() then not isFixed(var_ptr);
1029 case VariableKind.PREVIOUS() then true;
1030 else false;
1031 end match;
1032 end isFixable;
1033
1034 function isStateSelect
1035 "checks if a variable has a certain StateSelect attribute"
1036 extends checkVar;
1037 input StateSelect stateSelect;
1038 algorithm
1039 1119 b := VariableAttributes.getStateSelect(var.backendinfo.attributes) == stateSelect;
1040 end isStateSelect;
1041
1042 function setVariableAttributes
1043 input output Variable var;
1044 input VariableAttributes variableAttributes;
1045 protected
1046 BackendInfo backendinfo = var.backendinfo;
1047 algorithm
1048 ✗ backendinfo.attributes := variableAttributes;
1049 ✗ var.backendinfo := backendinfo;
1050 end setVariableAttributes;
1051
1052 function setMin
1053 input output Variable var;
1054 input Option<Expression> min_val;
1055 input Boolean overwrite = false;
1056 algorithm
1057 var := match var
1058 local
1059 BackendExtension.BackendInfo backendinfo;
1060 BackendExtension.VariableAttributes variableAttributes;
1061 case NFVariable.VARIABLE(backendinfo = backendinfo as BackendExtension.BACKEND_INFO(attributes = variableAttributes)) algorithm
1062
1063 88 backendinfo.attributes := BackendExtension.VariableAttributes.setMin(variableAttributes, min_val, overwrite);
1064 88 var.backendinfo := backendinfo;
1065 then var;
1066 end match;
1067 end setMin;
1068
1069 function setMax
1070 input output Variable var;
1071 input Option<Expression> max_val;
1072 input Boolean overwrite = false;
1073 algorithm
1074 var := match var
1075 local
1076 BackendExtension.BackendInfo backendinfo;
1077 BackendExtension.VariableAttributes variableAttributes;
1078 case NFVariable.VARIABLE(backendinfo = backendinfo as BackendExtension.BACKEND_INFO(attributes = variableAttributes)) algorithm
1079
1080 77 backendinfo.attributes := BackendExtension.VariableAttributes.setMax(variableAttributes, max_val, overwrite);
1081 77 var.backendinfo := backendinfo;
1082 then var;
1083 end match;
1084 end setMax;
1085
1086 function setStartAttribute
1087 input output Variable var;
1088 input Expression start_val;
1089 input Boolean overwrite = false;
1090 algorithm
1091 var := match var
1092 local
1093 BackendExtension.BackendInfo backendinfo;
1094 BackendExtension.VariableAttributes variableAttributes;
1095 case NFVariable.VARIABLE(backendinfo = backendinfo as BackendExtension.BACKEND_INFO(attributes = variableAttributes)) algorithm
1096
1097 255 backendinfo.attributes := BackendExtension.VariableAttributes.setStartAttribute(variableAttributes, start_val, overwrite);
1098 255 var.backendinfo := backendinfo;
1099 then var;
1100 end match;
1101 end setStartAttribute;
1102
1103 function setStateSelect
1104 input output Variable var;
1105 input BackendExtension.StateSelect stateSelect_val;
1106 input Boolean overwrite = false;
1107 algorithm
1108 var := match var
1109 local
1110 BackendExtension.BackendInfo backendinfo;
1111 BackendExtension.VariableAttributes variableAttributes;
1112 case NFVariable.VARIABLE(backendinfo = backendinfo as BackendExtension.BACKEND_INFO(attributes = variableAttributes)) algorithm
1113
1114 15 backendinfo.attributes := BackendExtension.VariableAttributes.setStateSelect(variableAttributes, stateSelect_val, overwrite);
1115 15 var.backendinfo := backendinfo;
1116 then var;
1117 end match;
1118 end setStateSelect;
1119
1120 function setTearingSelect
1121 input output Variable var;
1122 input TearingSelect tearingSelect_val;
1123 input Boolean overwrite = false;
1124 algorithm
1125 var := match var
1126 local
1127 BackendExtension.BackendInfo backendinfo;
1128 BackendExtension.VariableAttributes variableAttributes;
1129 case NFVariable.VARIABLE(backendinfo = backendinfo as BackendExtension.BACKEND_INFO(attributes = variableAttributes)) algorithm
1130 ✗ backendinfo.attributes := BackendExtension.VariableAttributes.setTearingSelect(variableAttributes, tearingSelect_val, overwrite);
1131 ✗ var.backendinfo := backendinfo;
1132 then var;
1133 else var;
1134 end match;
1135 end setTearingSelect;
1136
1137 function getTearingSelect
1138 input Pointer<Variable> varPointer;
1139 output BackendExtension.TearingSelect tearingSelect_val;
1140 algorithm
1141 tearingSelect_val := match Pointer.access(varPointer)
1142 local
1143 BackendExtension.VariableAttributes variableAttributes;
1144 case NFVariable.VARIABLE(backendinfo = BackendExtension.BACKEND_INFO(attributes = variableAttributes))
1145 1536 then BackendExtension.VariableAttributes.getTearingSelect(variableAttributes);
1146 else algorithm
1147 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + BVariable.pointerToString(varPointer)});
1148 ✗ then fail();
1149 end match;
1150 end getTearingSelect;
1151
1152 function setVarKind
1153 "use with caution: some variable kinds have extra information that needs to be correct"
1154 input Pointer<Variable> varPointer;
1155 input VariableKind varKind;
1156 protected
1157 Variable var;
1158 algorithm
1159 700 var := Pointer.access(varPointer);
1160 700 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, varKind);
1161 700 Pointer.update(varPointer, var);
1162 end setVarKind;
1163
1164 function setParent
1165 "sets the record parent. only do for record elements!"
1166 input output Pointer<Variable> varPointer;
1167 input Pointer<Variable> parent;
1168 protected
1169 Variable var = Pointer.access(varPointer);
1170 algorithm
1171 804 var.backendinfo := BackendInfo.setParent(var.backendinfo, parent);
1172 804 Pointer.update(varPointer, var);
1173 end setParent;
1174
1175 function getParent
1176 "returns the optional record parent"
1177 input Pointer<Variable> varPointer;
1178 output Option<Pointer<Variable>> parent;
1179 protected
1180 Variable var = Pointer.access(varPointer);
1181 algorithm
1182 20306 parent := BackendInfo.strengthen(var.backendinfo.parent);
1183 end getParent;
1184
1185 function isDummyVariable
1186 "Returns true, if the variable is a dummy variable.
1187 Note: !Only works in the backend, will return true for any variable if used
1188 during frontend!"
1189 extends checkVar;
1190 algorithm
1191 b := match var.backendinfo.varKind
1192 case VariableKind.FRONTEND_DUMMY() then true;
1193 else false;
1194 end match;
1195 end isDummyVariable;
1196
1197 function isArtificial
1198 extends checkVar;
1199 algorithm
1200 100 b := StringUtil.startsWith(ComponentRef.firstName(getVarName(var_ptr)), "$");
1201 end isArtificial;
1202
1203 function isFunctionAlias
1204 extends checkVar;
1205 algorithm
1206 10972 b := StringUtil.startsWith(ComponentRef.firstName(getVarName(var_ptr)), FUNCTION_STR);
1207 end isFunctionAlias;
1208
1209 function isClockAlias
1210 extends checkVar;
1211 algorithm
1212 1706 b := StringUtil.startsWith(ComponentRef.firstName(getVarName(var_ptr)), CLOCK_STR);
1213 end isClockAlias;
1214
1215 function createTimeVar
1216 output Pointer<Variable> var_ptr;
1217 protected
1218 Variable var = TIME_VARIABLE;
1219 algorithm
1220 193 (var_ptr, _) := makeVarPtr(var, var.name);
1221 end createTimeVar;
1222
1223 function setStateDerivativeVar
1224 "Updates a variable pointer to be a state, requires the pointer to its derivative."
1225 input Pointer<Variable> varPointer;
1226 input Pointer<Variable> derivative;
1227 protected
1228 Variable var;
1229 algorithm
1230 245 var := Pointer.access(varPointer);
1231 490 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.STATE(1, BackendInfo.weaken(SOME(derivative)), true));
1232 245 Pointer.update(varPointer, var);
1233 end setStateDerivativeVar;
1234
1235 function setStateDerKind
1236 "Updates a variable pointer to STATE_DER kind, linking it to its state.
1237 Used when an existing frontend derivative variable is promoted to STATE_DER."
1238 input Pointer<Variable> varPointer;
1239 input Pointer<Variable> statePointer;
1240 protected
1241 Variable var;
1242 algorithm
1243 ✗ var := Pointer.access(varPointer);
1244 ✗ var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.STATE_DER(PointerWeak.downgrade(statePointer), NONE()));
1245 ✗ Pointer.update(varPointer, var);
1246 end setStateDerKind;
1247
1248 function makeAlgStateVar
1249 "Updates a variable pointer to be an algebraic state.
1250 Only if it currently is an algebraic variable, required for DAEMode."
1251 input Pointer<Variable> varPointer;
1252 protected
1253 Variable var;
1254 algorithm
1255 ✗ if isAlgebraic(varPointer) then
1256 ✗ var := Pointer.access(varPointer);
1257 ✗ var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.ALG_STATE());
1258 ✗ Pointer.update(varPointer, var);
1259 end if;
1260 end makeAlgStateVar;
1261
1262 function makeDerVar
1263 "Creates a derivative variable pointer from the state cref.
1264 e.g. height -> $DER.height"
1265 input ComponentRef cref "old component reference";
1266 input Boolean scalarized = false;
1267 output ComponentRef der_cref "new component reference";
1268 output Pointer<Variable> var_ptr "pointer to new variable";
1269 protected
1270 ComponentRef state_cref = if scalarized then cref else ComponentRef.stripSubscriptsAll(cref);
1271 algorithm
1272 () := match ComponentRef.node(state_cref)
1273 local
1274 InstNode derNode;
1275 Pointer<Variable> state;
1276 PointerWeak<Variable> dummy_ptr =
1277 PointerWeak.downgrade(Pointer.createImmutable(DUMMY_VARIABLE));
1278 Variable var;
1279 case InstNode.VAR_NODE()
1280 algorithm
1281 248 state := getVarPointer(state_cref, sourceInfo());
1282 // append the $DER to the name
1283 248 derNode := InstNode.VAR_NODE(DERIVATIVE_STR, dummy_ptr);
1284 248 der_cref := ComponentRef.append(state_cref, ComponentRef.fromNode(derNode, ComponentRef.scalarType(state_cref)));
1285 // make the actual derivative variable and make cref and the variable cyclic
1286 248 var := fromCref(ComponentRef.stripSubscriptsAll(der_cref), Variable.attributes(Pointer.access(state)));
1287 496 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.STATE_DER(PointerWeak.downgrade(state), NONE()));
1288 248 (var_ptr, der_cref) := makeVarPtr(var, der_cref);
1289
1/2
✓ Branch 0 taken 248 times.
✗ Branch 1 not taken.
248 if not scalarized then
1290 248 der_cref := ComponentRef.copySubscripts(cref, der_cref);
1291 end if;
1292 then ();
1293
1294 else algorithm
1295 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1296 ✗ then fail();
1297 end match;
1298 end makeDerVar;
1299
1300 function hasDerVar
1301 input Pointer<Variable> state_var;
1302 output Boolean b;
1303 algorithm
1304 b := match Pointer.access(state_var)
1305 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = VariableKind.STATE(derivative = SOME(_)))) then true;
1306 else false;
1307 end match;
1308 end hasDerVar;
1309
1310 function addRecordChild
1311 "adds a child to the records children. use with care, only when creating new records!"
1312 input Pointer<Variable> var_ptr;
1313 input Pointer<Variable> child;
1314 protected
1315 Variable var = Pointer.access(var_ptr);
1316 algorithm
1317 var := match var
1318 local
1319 VariableKind varKind;
1320 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = varKind as VariableKind.RECORD())) algorithm
1321 208 varKind.children := PointerWeak.downgrade(child) :: varKind.children;
1322 104 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, varKind);
1323 then var;
1324 else algorithm
1325 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed adding " + ComponentRef.toString(getVarName(child)) + " as a child to "
1326 + ComponentRef.toString(getVarName(var_ptr)) + " because it is not a record."});
1327 ✗ then fail();
1328 end match;
1329 104 Pointer.update(var_ptr, var);
1330 end addRecordChild;
1331
1332 function setRecordChildren
1333 "sets the records children. use with care, only when creating new records!"
1334 input Pointer<Variable> var_ptr;
1335 input list<Pointer<Variable>> children;
1336 protected
1337 Variable var = Pointer.access(var_ptr);
1338 algorithm
1339 var := match var
1340 local
1341 VariableKind varKind;
1342 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = varKind as VariableKind.RECORD())) algorithm
1343 ✗ varKind.children := list(PointerWeak.downgrade(c) for c in children);
1344 ✗ var.backendinfo := BackendInfo.setVarKind(var.backendinfo, varKind);
1345 then var;
1346 else algorithm
1347 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed adding new children to "
1348 + ComponentRef.toString(getVarName(var_ptr)) + " because it is not a record."});
1349 ✗ then fail();
1350 end match;
1351 ✗ Pointer.update(var_ptr, var);
1352 end setRecordChildren;
1353
1354 function getRecordChildren
1355 "returns all children of the variable if its a record, otherwise returns empty list"
1356 input Pointer<Variable> var;
1357 output list<Pointer<Variable>> children;
1358 algorithm
1359 children := match Pointer.access(var)
1360 local
1361 VariableKind varKind;
1362 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = varKind as VariableKind.RECORD()))
1363
4/4
✓ Branch 0 taken 5105 times.
✓ Branch 1 taken 2049 times.
✓ Branch 2 taken 5105 times.
✓ Branch 3 taken 2049 times.
7154 then list(PointerWeak.upgrade(c) for c in varKind.children);
1364 else {};
1365 end match;
1366 end getRecordChildren;
1367
1368 function getRecordChildrenCells
1369 "The children as stored. For a caller that only iterates; `getRecordChildren`
1370 has to build a list to hand one back."
1371 input Pointer<Variable> var;
1372 output list<PointerWeak<Variable>> children;
1373 algorithm
1374 children := match Pointer.access(var)
1375 local
1376 VariableKind varKind;
1377 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = varKind as VariableKind.RECORD()))
1378 17 then varKind.children;
1379 else {};
1380 end match;
1381 end getRecordChildrenCells;
1382
1383 function getRecordChildrenOrSelf
1384 input Pointer<Variable> var;
1385 output list<Pointer<Variable>> children = getRecordChildren(var);
1386 algorithm
1387
2/2
✓ Branch 0 taken 1985 times.
✓ Branch 1 taken 44 times.
2029 children := if listEmpty(children) then {var} else children;
1388 end getRecordChildrenOrSelf;
1389
1390 function getRecordChildrenCref
1391 input ComponentRef cref;
1392 output list<ComponentRef> children;
1393 protected
1394 list<Subscript> subscripts;
1395 list<Pointer<Variable>> arg_children;
1396 algorithm
1397 2854 subscripts := ComponentRef.subscriptsAllFlat(cref);
1398 2854 arg_children := getRecordChildren(getVarPointer(cref, sourceInfo()));
1399
4/4
✓ Branch 0 taken 1636 times.
✓ Branch 1 taken 2854 times.
✓ Branch 2 taken 1636 times.
✓ Branch 3 taken 2854 times.
4490 children := list(ComponentRef.mergeSubscripts(subscripts, getVarName(child), true, true) for child in arg_children);
1400 end getRecordChildrenCref;
1401
1402 function getRecordChildrenCrefOrSelf
1403 input ComponentRef cref;
1404 output list<ComponentRef> children = getRecordChildrenCref(cref);
1405 algorithm
1406
1/2
✓ Branch 0 taken 205 times.
✗ Branch 1 not taken.
205 children := if listEmpty(children) then {cref} else children;
1407 end getRecordChildrenCrefOrSelf;
1408
1409 function setRecordVariability
1410 input Pointer<Variable> var_ptr;
1411 input Prefixes.Variability variability;
1412 protected
1413 Variable var = Pointer.access(var_ptr);
1414 algorithm
1415 _ := match var.backendinfo.varKind
1416 local
1417 VariableKind varKind;
1418 case varKind as VariableKind.RECORD() algorithm
1419 44 varKind.min_var := variability;
1420 44 varKind.max_var := variability;
1421 44 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, varKind);
1422 44 Pointer.update(var_ptr, var);
1423 then ();
1424 else();
1425 end match;
1426 end setRecordVariability;
1427
1428 function makeDummyState
1429 input Pointer<Variable> varPointer;
1430 output Pointer<Variable> derivative;
1431 protected
1432 Variable var = Pointer.access(varPointer);
1433 algorithm
1434 var.backendinfo := match BackendInfo.getVarKind(var.backendinfo)
1435 local
1436 Variable der_var;
1437 PointerWeak<Variable> derivative_weak;
1438
1439 case VariableKind.STATE(derivative = SOME(derivative_weak)) algorithm
1440 // also update the derivative to be a dummy derivative
1441 107 derivative := PointerWeak.upgrade(derivative_weak);
1442 107 der_var := Pointer.access(derivative);
1443 214 der_var.backendinfo := BackendInfo.setVarKind(der_var.backendinfo, VariableKind.DUMMY_DER(PointerWeak.downgrade(varPointer)));
1444 107 der_var.backendinfo := BackendInfo.setStateSelect(der_var.backendinfo, NFBackendExtension.StateSelect.AVOID);
1445 107 Pointer.update(derivative, der_var);
1446 107 then BackendInfo.setVarKind(var.backendinfo, VariableKind.DUMMY_STATE(PointerWeak.downgrade(derivative)));
1447
1448 // do nothing if its already a dummy state
1449 case VariableKind.DUMMY_STATE(dummy_der = derivative_weak) algorithm
1450 ✗ derivative := PointerWeak.upgrade(derivative_weak);
1451 ✗ then var.backendinfo;
1452
1453 else algorithm
1454 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(getVarName(varPointer)) + "."});
1455 ✗ then fail();
1456 end match;
1457 107 Pointer.update(varPointer, var);
1458 end makeDummyState;
1459
1460 function makeDiscreteStateVar
1461 "Updates a discrete variable pointer to be a discrete state, requires the pointer to its left limit (pre) variable."
1462 input Pointer<Variable> varPointer;
1463 protected
1464 Variable var = Pointer.access(varPointer);
1465 algorithm
1466 68 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.DISCRETE_STATE());
1467 68 Pointer.update(varPointer, var);
1468 end makeDiscreteStateVar;
1469
1470 function makePreVar
1471 "Creates a previous variable pointer from the variable cref.
1472 e.g. isOpen -> $PRE.isOpen"
1473 input ComponentRef cref "old component reference";
1474 output ComponentRef pre_cref "new component reference";
1475 output Pointer<Variable> pre_ptr "pointer to new variable";
1476 algorithm
1477 () := match ComponentRef.node(cref)
1478 local
1479 InstNode qual;
1480 Pointer<Variable> var_ptr;
1481 Variable pre;
1482 case qual as InstNode.VAR_NODE()
1483 algorithm
1484 81 var_ptr := getVarPointer(cref, sourceInfo());
1485 81 qual.name := PREVIOUS_STR;
1486 81 pre_cref := ComponentRef.append(cref, ComponentRef.fromNode(qual, ComponentRef.scalarType(cref)));
1487 81 pre := fromCref(pre_cref, Variable.attributes(Pointer.access(var_ptr)));
1488 81 pre.backendinfo := BackendInfo.setVarKind(pre.backendinfo, VariableKind.PREVIOUS());
1489 81 (pre_ptr, pre_cref) := makeVarPtr(pre, pre_cref);
1490 81 connectPartners(var_ptr, pre_ptr, BackendInfo.setVarPre);
1491 then ();
1492
1493 else algorithm
1494 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1495 ✗ then fail();
1496 end match;
1497 end makePreVar;
1498
1499 function makeSeedVar
1500 "Creates a seed variable pointer from a cref. Used in NBJacobian and NBHessian
1501 to represent generic gradient equations.
1502 e.g: (speed, 'Jac') -> $SEED_Jac.speed"
1503 input output ComponentRef cref "old component reference to new component reference";
1504 input String name "name of the matrix this seed belongs to";
1505 output Pointer<Variable> var_ptr "pointer to new variable";
1506 algorithm
1507 () := match ComponentRef.node(cref)
1508 local
1509 InstNode qual;
1510 Pointer<Variable> old_var_ptr;
1511 Option<Pointer<Variable>> ovar;
1512 Variable var;
1513 VariableKind varKind;
1514 ComponentRef original_cref;
1515
1516 case qual as InstNode.VAR_NODE() algorithm
1517 869 original_cref := cref;
1518 // get the variable pointer from the old cref to later on link back to it
1519 869 old_var_ptr := getVarPointer(cref, sourceInfo());
1520 // Skip base-ptr cache for subscripted element crefs (partial-slice NLS iter vars)
1521 // so that each outer element gets its own scalar seed var instead of all elements
1522 // sharing the first element's seed via the array ptr cache.
1523
2/2
✓ Branch 1 taken 747 times.
✓ Branch 2 taken 122 times.
869 if ComponentRef.hasSubscripts(original_cref) then
1524 ovar := NONE();
1525 else
1526 747 ovar := getVarSeed(old_var_ptr);
1527 // var_seed is a single-slot cache shared across all Jacobians; reject a hit
1528 // cached under a different Jacobian's name (cref root is always $SEED_<name>).
1529
7/8
✗ Branch 1 not taken.
✓ Branch 2 taken 747 times.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 717 times.
✓ Branch 9 taken 14 times.
✓ Branch 10 taken 16 times.
✓ Branch 16 taken 13 times.
✓ Branch 17 taken 1 time.
747 if isSome(ovar) and ComponentRef.firstName(ComponentRef.last(getVarName(Util.getOption(ovar)))) <> SEED_STR + "_" + name then
1530 ovar := NONE();
1531 end if;
1532 end if;
1533
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 869 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 868 times.
869 if isSome(ovar) then
1534 1 var_ptr := Util.getOption(ovar);
1535 1 cref := getVarName(var_ptr);
1536 else
1537 // prepend the seed str and the matrix name and create the new cref
1538 1736 qual.name := SEED_STR + "_" + name;
1539 868 cref := ComponentRef.append(cref, ComponentRef.fromNode(qual, ComponentRef.scalarType(cref)));
1540 868 var := fromCref(cref, NFAttributes.IMPL_DISCRETE_ATTR);
1541
1542 // update the variable to be a seed and pass the pointer to the original variable
1543 // if it is a record, clear the children instead
1544 varKind := match getVarKind(old_var_ptr)
1545 case varKind as VariableKind.RECORD() algorithm
1546 15 varKind.children := {};
1547 then varKind;
1548 else VariableKind.SEED_VAR();
1549 end match;
1550 868 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, varKind);
1551
1552 // create the new variable pointer and safe it to the component reference
1553 868 (var_ptr, cref) := makeVarPtr(var, cref);
1554 // For subscripted element crefs (partial-slice NLS iter vars), skip linking back to
1555 // the base array ptr so the shared cache is not populated, allowing each element to
1556 // create its own independent seed on subsequent calls.
1557
2/2
✓ Branch 1 taken 746 times.
✓ Branch 2 taken 122 times.
868 if not ComponentRef.hasSubscripts(original_cref) then
1558 746 connectPartners(old_var_ptr, var_ptr, BackendInfo.setVarSeed);
1559 end if;
1560 end if;
1561 then ();
1562
1563 else algorithm
1564 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1565 ✗ then fail();
1566 end match;
1567 end makeSeedVar;
1568
1569 function makePDerVar
1570 "Creates a partial derivative variable pointer from a cref. Used in NBJacobian and NBHessian
1571 to represent generic gradient equations.
1572 e.g: (speed, 'Jac') -> $pDer_Jac.speed"
1573 input output ComponentRef cref "old component reference to new component reference";
1574 input String name "name of the matrix this partial derivative belongs to";
1575 input Boolean isTmp "sets variable kind for tmpVar or resultVar accordingly";
1576 output Pointer<Variable> var_ptr "pointer to new variable";
1577 algorithm
1578 () := match ComponentRef.node(cref)
1579 local
1580 InstNode qual;
1581 Pointer<Variable> res_ptr;
1582 Option<Pointer<Variable>> ovar;
1583 VariableKind varKind;
1584 Variable var;
1585
1586 // regular case for jacobians
1587 case qual as InstNode.VAR_NODE() algorithm
1588 1190 res_ptr := getVarPointer(cref, sourceInfo());
1589 1190 ovar := getVarPDer(res_ptr, isTmp);
1590 // var_pder_res/tmp is a single-slot cache shared across all Jacobians; reject a hit
1591 // cached under a different Jacobian's name (cref root is always $pDER_<name>).
1592
7/8
✗ Branch 1 not taken.
✓ Branch 2 taken 1190 times.
✓ Branch 3 taken 209 times.
✓ Branch 4 taken 981 times.
✓ Branch 9 taken 132 times.
✓ Branch 10 taken 77 times.
✓ Branch 16 taken 131 times.
✓ Branch 17 taken 1 time.
1190 if isSome(ovar) and ComponentRef.firstName(ComponentRef.last(getVarName(Util.getOption(ovar)))) <> PARTIAL_DERIVATIVE_STR + "_" + name then
1593 ovar := NONE();
1594 end if;
1595
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1190 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1189 times.
1190 if isSome(ovar) then
1596 1 var_ptr := Util.getOption(ovar);
1597 1 cref := getVarName(var_ptr);
1598 else
1599 // prepend the seed str and the matrix name and create the new cref_DIFF_DIFF
1600 2378 qual.name := PARTIAL_DERIVATIVE_STR + "_" + name;
1601 1189 cref := ComponentRef.append(cref, ComponentRef.fromNode(qual, ComponentRef.scalarType(cref)));
1602 1189 var := fromCref(cref, Variable.attributes(Pointer.access(res_ptr)));
1603
1604 // update the variable to be a partial derivative and pass the pointer to the original variable
1605 // if it is a record, clear the children instead
1606 varKind := match getVarKind(res_ptr)
1607 case varKind as VariableKind.RECORD() algorithm
1608 19 varKind.children := {};
1609 then varKind;
1610
2/2
✓ Branch 0 taken 847 times.
✓ Branch 1 taken 323 times.
1170 else if isTmp then VariableKind.JAC_TMP_VAR() else VariableKind.JAC_VAR();
1611 end match;
1612 1189 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, varKind);
1613
1614 // create the new variable pointer and safe it to the component reference
1615 1189 (var_ptr, cref) := makeVarPtr(var, cref);
1616
2/2
✓ Branch 0 taken 847 times.
✓ Branch 1 taken 342 times.
2036 connectPartners(res_ptr, var_ptr, function BackendInfo.setVarPDer(isTmp = isTmp));
1617 end if;
1618 then ();
1619
1620 else algorithm
1621 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1622 ✗ then fail();
1623 end match;
1624 end makePDerVar;
1625
1626 function makeFDerVar
1627 "Creates a function derivative cref. Used in NBDifferentiation
1628 for differentiating body vars of a function (crefs are not lowered and only known locally).
1629 prepend the funcion derivative name and use the string representation of the cref
1630 for interface reasons they have to be a single cref without restCref (gets converted to InstNode)"
1631 input output ComponentRef cref "old component reference to new component reference";
1632 algorithm
1633 cref := match cref
1634 // add the $FDER to the deepest cref
1635 case ComponentRef.CREF(restCref = ComponentRef.EMPTY()) then match ComponentRef.node(cref)
1636 local
1637 InstNode qual;
1638
1639 // Both arms rename a copy, so both need an identity of their own:
1640 // without one the copy publishes nothing and the cref reads back
1641 // under the old name.
1642
1643 // inside a function body
1644 case qual as InstNode.COMPONENT_NODE() algorithm
1645 291 qual.name := BackendUtil.makeFDerString(ComponentRef.toString(cref));
1646 291 then ComponentRef.fromOwnedNode(InstNode.reidentify(qual), ComponentRef.nodeType(cref));
1647
1648 // partial function application (passing function pointers)
1649 case qual as InstNode.CLASS_NODE() algorithm
1650 ✗ qual.name := BackendUtil.makeFDerString(ComponentRef.toString(cref));
1651 ✗ then ComponentRef.fromOwnedNode(InstNode.reidentify(qual), ComponentRef.nodeType(cref));
1652
1653 else algorithm
1654 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1655 ✗ then fail();
1656 end match;
1657
1658 // recurse deeper
1659 case ComponentRef.CREF() algorithm
1660 57 cref.restCref := makeFDerVar(cref.restCref);
1661 then cref;
1662
1663 else cref;
1664 end match;
1665 end makeFDerVar;
1666
1667 function makeStartVar
1668 "Creates a start variable pointer from a cref. Used in NBInitialization.
1669 e.g: angle -> $START.angle"
1670 input ComponentRef cref "old component reference";
1671 output ComponentRef start_cref "new component reference";
1672 output Pointer<Variable> var_ptr "pointer to new variable";
1673 algorithm
1674 (start_cref, var_ptr) := match ComponentRef.node(cref)
1675 local
1676 InstNode qual;
1677 Pointer<Variable> old_var_ptr;
1678 Variable var, old_var;
1679
1680 case qual as InstNode.VAR_NODE()
1681 algorithm
1682 // get the variable pointer from the old cref to later on link back to it
1683 213 old_var_ptr := getVarPointer(cref, sourceInfo());
1684
1685 // try to see if it already has a start variable
1686 (start_cref, var_ptr) := match getVarStart(old_var_ptr)
1687 // there is already a start variable, take it
1688 10 case SOME(var_ptr) then (getVarName(var_ptr), var_ptr);
1689
1690 // create a new start variable
1691 else algorithm
1692 // prepend the start str
1693 203 qual.name := START_STR;
1694 // remove the subscripts before creating the new cref for the new variable
1695 203 start_cref := ComponentRef.append(ComponentRef.stripSubscriptsAll(cref), ComponentRef.fromNode(qual, ComponentRef.scalarType(cref)));
1696 203 var := fromCref(start_cref, Variable.attributes(getVar(cref, sourceInfo())));
1697 // update the variable to be a start variable and pass the pointer to the original variable
1698
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 197 times.
203 if BVariable.isRecord(old_var_ptr) then
1699 6 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.RECORD({}, NFPrefixes.Variability.PARAMETER, NFPrefixes.Variability.CONTINUOUS));
1700 else
1701 394 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.START(PointerWeak.downgrade(old_var_ptr)));
1702 end if;
1703 203 var.backendinfo := BackendInfo.setVarStart(var.backendinfo, SOME(old_var_ptr));
1704 // create the new variable pointer and safe it to the component reference
1705 203 (var_ptr, start_cref) := makeVarPtr(var, start_cref);
1706 // save the var_ptr to the old var as its start var
1707 203 old_var := Pointer.access(old_var_ptr);
1708 203 old_var.backendinfo := BackendInfo.setVarStart(old_var.backendinfo, SOME(var_ptr));
1709 203 Pointer.update(old_var_ptr, old_var);
1710 203 then (start_cref, var_ptr);
1711 end match;
1712
1713 // copy back all the subscripts
1714 213 start_cref := ComponentRef.copySubscripts(cref, start_cref);
1715 then (start_cref, var_ptr);
1716
1717 else algorithm
1718 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1719 ✗ then fail();
1720 end match;
1721 end makeStartVar;
1722
1723 function makeResidualVar
1724 "Creates a residual variable pointer from a unique index and context name.
1725 e.g. (\"DAE\", 4) --> $RES_DAE_4"
1726 input String name "context name e.g. DAE";
1727 input Integer uniqueIndex "unique identifier index";
1728 input Type ty "equation type containing dims";
1729 output Pointer<Variable> var_ptr "pointer to new variable";
1730 output ComponentRef cref "new component reference";
1731 protected
1732 InstNode node;
1733 Variable var;
1734 algorithm
1735 // create inst node with dummy variable pointer and create cref from it
1736 11069 node := InstNode.VAR_NODE(RESIDUAL_STR + "_" + name + "_" + intString(uniqueIndex), PointerWeak.downgrade(Pointer.createImmutable(DUMMY_VARIABLE)));
1737 // Type for residuals is always REAL() !
1738 11069 cref := ComponentRef.fromNode(node, ty);
1739 // create variable and set its kind to dae_residual (change name?)
1740 11069 var := fromCref(cref);
1741 // update the variable to be a seed and pass the pointer to the original variable
1742 11069 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.RESIDUAL_VAR());
1743 // create the new variable pointer and safe it to the component reference
1744 11069 (var_ptr, cref) := makeVarPtr(var, cref);
1745 end makeResidualVar;
1746
1747 function makeEventVar
1748 "Creates a generic boolean variable pointer from a unique index and context name.
1749 e.g. (\"$SEV\", 4) --> $SEV_4"
1750 input String name "context name e.g. §WHEN";
1751 input Integer uniqueIndex "unique identifier index";
1752 input Type var_ty "variable type";
1753 input Iterator iterator = Iterator.EMPTY() "optional for-loop iterator";
1754 output Pointer<Variable> var_ptr "pointer to new variable";
1755 output ComponentRef cref "new component reference";
1756 protected
1757 InstNode node;
1758 ComponentRef var_cref;
1759 Variable var;
1760 list<Subscript> iter_subs;
1761 Type ty;
1762 algorithm
1763 // get subscripts from optional iterator
1764 142 iter_subs := Iterator.normalizedSubscripts(iterator);
1765
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 136 times.
142 if listEmpty(iter_subs) then
1766 ty := var_ty;
1767 else
1768 6 ty := Type.liftArrayLeftList(var_ty, Iterator.dimensions(iterator));
1769 end if;
1770 // create inst node with dummy variable pointer and create cref from it
1771 142 node := InstNode.VAR_NODE(name + "_" + intString(uniqueIndex),
1772 PointerWeak.downgrade(Pointer.createImmutable(DUMMY_VARIABLE)));
1773 142 cref := ComponentRef.CREF(ComponentRef.storeNode(node), iter_subs, ty, NFComponentRef.Origin.CREF, ComponentRef.EMPTY());
1774 142 var_cref := ComponentRef.CREF(ComponentRef.storeNode(node), {}, ty, NFComponentRef.Origin.CREF, ComponentRef.EMPTY());
1775 // create variable
1776 142 var := fromCref(var_cref, NFAttributes.IMPL_DISCRETE_ATTR);
1777 // update the variable to be discrete and pass the pointer to the original variable
1778 142 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.DISCRETE());
1779 142 var.backendinfo := BackendInfo.setHideResult(var.backendinfo, true);
1780 // create the new variable pointer and safe it to the component reference
1781 142 (var_ptr, cref) := makeVarPtr(var, cref);
1782 end makeEventVar;
1783
1784 function makeAuxVar
1785 "Creates an auxillary variable pointer from a unique index and context name.
1786 e.g. (\"FUN\", 4) --> $FUN_4"
1787 input String name "context name e.g. FUN";
1788 input Integer uniqueIndex "unique identifier index";
1789 input Type ty "variable type containing dims";
1790 input Boolean makeParam "true if it is a parameter";
1791 output Pointer<Variable> var_ptr "pointer to new variable";
1792 output ComponentRef cref "new component reference";
1793 protected
1794 InstNode node;
1795 Variable var;
1796 function updateBackendInfo
1797 input output Variable var;
1798 input Boolean makeParam;
1799 algorithm
1800 // update the variable kind and set hideResult = true
1801 825 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.fromType(Variable.typeOf(var), makeParam));
1802 825 var.backendinfo := BackendInfo.setHideResult(var.backendinfo, true);
1803 end updateBackendInfo;
1804 algorithm
1805 // create inst node with dummy variable pointer and create cref from it
1806 708 node := InstNode.VAR_NODE(name + "_" + intString(uniqueIndex),
1807 PointerWeak.downgrade(Pointer.createImmutable(DUMMY_VARIABLE)));
1808 708 cref := ComponentRef.CREF(ComponentRef.storeNode(node), {}, ty, NFComponentRef.Origin.CREF, ComponentRef.EMPTY());
1809 708 var := fromCref(cref);
1810
1811 708 var := updateBackendInfo(var, makeParam);
1812
4/4
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 708 times.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 708 times.
1533 var.children := list(updateBackendInfo(child, makeParam) for child in var.children);
1813
1814 // create the new variable pointer and safe it to the component reference
1815 708 (var_ptr, cref) := makeVarPtr(var, cref);
1816 end makeAuxVar;
1817
1818 function makeAuxStateVar
1819 "Creates a auxiliary state variable from an expression.
1820 e.g. der(x^2 + y) --> der(aux)"
1821 input Integer uniqueIndex "unique identifier index";
1822 input Option<Expression> binding "optional binding expression";
1823 output Pointer<Variable> var_ptr "pointer to new variable";
1824 output ComponentRef cref "new component reference";
1825 output Pointer<Variable> der_var "pointer to new derivative variable";
1826 output ComponentRef der_cref "new derivative component reference";
1827 protected
1828 InstNode node;
1829 Variable var;
1830 Expression bnd;
1831 algorithm
1832 // create inst node with dummy variable pointer and create cref from it
1833 3 node := InstNode.VAR_NODE(AUXILIARY_STR + "_" + intString(uniqueIndex),
1834 PointerWeak.downgrade(Pointer.createImmutable(DUMMY_VARIABLE)));
1835 3 cref := ComponentRef.CREF(ComponentRef.storeNode(node), {}, Type.REAL(), NFComponentRef.Origin.CREF, ComponentRef.EMPTY());
1836 // create variable and add optional binding
1837
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if isSome(binding) then
1838 3 bnd := Util.getOption(binding);
1839 3 var := fromCref(cref, NFAttributes.DEFAULT_ATTR, Binding.makeFlat(bnd, Expression.variability(bnd), NFBinding.Source.BINDING));
1840 else
1841 ✗ var := fromCref(cref);
1842 end if;
1843 // update the variable to have StateSelect.AVOID as it has no good start values
1844 3 var.backendinfo := BackendInfo.setStateSelect(var.backendinfo, NFBackendExtension.StateSelect.AVOID);
1845
1846 // create the new variable pointer and safe it to the component reference
1847 3 (var_ptr, cref) := makeVarPtr(var, cref);
1848 3 (der_cref, der_var) := makeDerVar(cref);
1849 3 setStateDerivativeVar(var_ptr, der_var);
1850 end makeAuxStateVar;
1851
1852 function makeTmpVar
1853 "Creates a tmp variable pointer from a cref. Used in NBInitialization.
1854 e.g: angle -> $START.angle"
1855 input ComponentRef cref "old component reference";
1856 output ComponentRef tmp_cref "new component reference";
1857 protected
1858 Pointer<Variable> var_ptr "pointer to new variable";
1859 algorithm
1860 () := match ComponentRef.node(cref)
1861 local
1862 InstNode qual;
1863 Pointer<Variable> old_var_ptr;
1864 Variable var;
1865 case qual as InstNode.VAR_NODE()
1866 algorithm
1867 // get the variable pointer from the old cref to later on link back to it
1868 ✗ old_var_ptr := getVarPointer(cref, sourceInfo());
1869 // prepend the tmp str
1870 ✗ qual.name := TEMPORARY_STR;
1871 ✗ tmp_cref := ComponentRef.append(cref, ComponentRef.fromNode(qual, ComponentRef.scalarType(cref)));
1872 ✗ var := fromCref(tmp_cref, Variable.attributes(getVar(cref, sourceInfo())));
1873 // update the variable to be a start variable and pass the pointer to the original variable
1874 ✗ var.backendinfo := BackendInfo.setVarKind(var.backendinfo, getVarKind(old_var_ptr));
1875 // create the new variable pointer and safe it to the component reference
1876 ✗ (var_ptr, tmp_cref) := makeVarPtr(var, tmp_cref);
1877 then ();
1878
1879 else algorithm
1880 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1881 ✗ then fail();
1882 end match;
1883 end makeTmpVar;
1884
1885 function makeClockVar
1886 "Creates a clock variable if an unnamed clock is used in the system"
1887 input Integer uniqueIndex "unique identifier index";
1888 input Type ty "equation type containing dims";
1889 output Pointer<Variable> var_ptr "pointer to new variable";
1890 output ComponentRef cref "new component reference";
1891 protected
1892 InstNode node;
1893 Variable var;
1894 algorithm
1895 // create inst node with dummy variable pointer and create cref from it
1896 2 node := InstNode.VAR_NODE(CLOCK_STR + "_" + intString(uniqueIndex),
1897 PointerWeak.downgrade(Pointer.createImmutable(DUMMY_VARIABLE)));
1898 // Type for residuals is always REAL() !
1899 2 cref := ComponentRef.CREF(ComponentRef.storeNode(node), {}, ty, NFComponentRef.Origin.CREF, ComponentRef.EMPTY());
1900 // create variable and set its kind to dae_residual (change name?)
1901 2 var := fromCref(cref);
1902 // update the variable to be a seed and pass the pointer to the original variable
1903 2 var.backendinfo := BackendInfo.setVarKind(var.backendinfo, VariableKind.CLOCK());
1904 // create the new variable pointer and safe it to the component reference
1905 2 (var_ptr, cref) := makeVarPtr(var, cref);
1906 end makeClockVar;
1907
1908 function getBindingVariability
1909 "returns the variability of the binding, fails if it has the wrong type.
1910 unbound variables return the most restrictive variability because they have
1911 to be solved by the system."
1912 input Pointer<Variable> var_ptr;
1913 output Prefixes.Variability variability;
1914 algorithm
1915 variability := match Pointer.access(var_ptr)
1916 local
1917 Prefixes.Variability tmp;
1918 case Variable.VARIABLE(binding = Binding.TYPED_BINDING(variability = tmp)) then tmp;
1919 case Variable.VARIABLE(binding = Binding.FLAT_BINDING(variability = tmp)) then tmp;
1920 case Variable.VARIABLE(binding = Binding.UNBOUND()) then NFPrefixes.Variability.CONTINUOUS;
1921 else algorithm
1922 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of wrong binding."});
1923 ✗ then fail();
1924 end match;
1925 end getBindingVariability;
1926
1927 function hasEvaluableBinding
1928 extends checkVar;
1929 protected
1930 Expression binding;
1931 function isEvaluable
1932 input Expression exp;
1933 output Boolean b;
1934 protected
1935 Expression new_exp;
1936 algorithm
1937 3186 b := Expression.isLiteralXML(exp);
1938
2/2
✓ Branch 0 taken 2050 times.
✓ Branch 1 taken 1136 times.
3186 if not b then
1939 // try to extract literal from array constructor (use dummy map, there should not be any new iterators)
1940 1136 (_, new_exp) := Iterator.extract(exp);
1941 1136 new_exp := SimplifyExp.simplifyDump(new_exp, true, getInstanceName());
1942 1136 b := Expression.isLiteralXML(Ceval.tryEvalExp(new_exp));
1943 end if;
1944 end isEvaluable;
1945 algorithm
1946 // check binding
1947
2/2
✓ Branch 1 taken 3186 times.
✓ Branch 2 taken 248 times.
3434 if isBound(var_ptr) then
1948 3186 binding := Binding.getExp(var.binding);
1949 3186 b := isEvaluable(binding);
1950 else
1951 b := false;
1952 end if;
1953 end hasEvaluableBinding;
1954
1955 function mapExp
1956 input Pointer<Variable> var_ptr;
1957 input BEquation.MapFuncExp funcExp;
1958 input BEquation.MapFuncExpWrapper mapFunc = Expression.map;
1959 protected
1960 Variable var = Pointer.access(var_ptr);
1961 Option<Expression> opt_start;
1962 Expression binding, new_binding, start, new_start;
1963 Boolean changed = false;
1964 algorithm
1965 // map binding
1966
2/2
✓ Branch 1 taken 2543 times.
✓ Branch 2 taken 185 times.
2728 if isBound(var_ptr) then
1967 2543 binding := Binding.getExp(var.binding);
1968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2543 times.
2543 new_binding := mapFunc(binding, funcExp);
1969
2/2
✓ Branch 0 taken 830 times.
✓ Branch 1 taken 1713 times.
2543 if not referenceEq(binding, new_binding) then
1970 830 var.binding := Binding.setExp(new_binding, var.binding);
1971 changed := true;
1972 end if;
1973 end if;
1974
1975 // map start exp
1976 2728 opt_start := getStartAttribute(var_ptr);
1977
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2728 times.
✓ Branch 2 taken 765 times.
✓ Branch 3 taken 1963 times.
2728 if isSome(opt_start) then
1978 765 SOME(start) := opt_start;
1979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 765 times.
765 new_start := mapFunc(start, funcExp);
1980
1981
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 754 times.
765 if not referenceEq(start, new_start) then
1982 11 var := setStartAttribute(var, new_start, true);
1983 changed := true;
1984 end if;
1985 end if;
1986
1987
2/2
✓ Branch 0 taken 1887 times.
✓ Branch 1 taken 830 times.
2728 if changed then Pointer.update(var_ptr, var); end if;
1988 end mapExp;
1989
1990 function setFixed
1991 input output Pointer<Variable> var_ptr;
1992 input Boolean b = true;
1993 input Boolean overwrite = false;
1994 protected
1995 Variable var;
1996 algorithm
1997 899 var := Pointer.access(var_ptr);
1998 var := match var
1999 local
2000 BackendInfo binfo;
2001
2002 case Variable.VARIABLE(backendinfo = binfo as BackendInfo.BACKEND_INFO()) algorithm
2003 899 binfo.attributes := VariableAttributes.setFixed(binfo.attributes, var.ty, b, overwrite);
2004 899 var.backendinfo := binfo;
2005 then var;
2006
2007 else algorithm
2008 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of wrong binding."});
2009 ✗ then fail();
2010 end match;
2011 899 Pointer.update(var_ptr, var);
2012 end setFixed;
2013
2014 function setBindingAsStart
2015 "use this if a binding is found out to be constant, remove variable to known vars (param/const)"
2016 input Pointer<Variable> var_ptr;
2017 input Boolean overwrite = false;
2018 protected
2019 Variable var;
2020 algorithm
2021 2726 var := Pointer.access(var_ptr);
2022 var := match var
2023 local
2024 BackendInfo binfo;
2025 Expression start;
2026
2027 case Variable.VARIABLE(backendinfo = binfo as BackendInfo.BACKEND_INFO()) algorithm
2028 2726 start := Binding.getExp(var.binding);
2029 2726 binfo.attributes := VariableAttributes.setStartAttribute(binfo.attributes, start, overwrite);
2030 2726 var.backendinfo := binfo;
2031 then var;
2032
2033 else algorithm
2034 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of wrong binding."});
2035 ✗ then fail();
2036 end match;
2037 2726 Pointer.update(var_ptr, var);
2038 end setBindingAsStart;
2039
2040 function setBindingAsStartAndFix
2041 input output Pointer<Variable> var_ptr;
2042 input Boolean b = true;
2043 input Boolean overwrite = false;
2044 algorithm
2045 656 setBindingAsStart(var_ptr, overwrite);
2046 656 var_ptr := setFixed(var_ptr, b);
2047 end setBindingAsStartAndFix;
2048
2049 function getStartAttribute
2050 input Pointer<Variable> var_ptr;
2051 output Option<Expression> start = VariableAttributes.getStartAttribute(Variable.getVariableAttributes(Pointer.access(var_ptr)));
2052 end getStartAttribute;
2053
2054 function hasNonTrivialAliasBinding
2055 "returns true if the binding does not represent a cref, a negated cref or a constant.
2056 used for alias removal since only those can be stored as actual alias variables"
2057 extends checkVar;
2058 protected
2059 Expression binding = Binding.getExp(var.binding);
2060 algorithm
2061
4/4
✓ Branch 1 taken 408 times.
✓ Branch 2 taken 1680 times.
✓ Branch 4 taken 335 times.
✓ Branch 5 taken 73 times.
2088 b := (not Expression.isTrivialCref(binding)) and checkExpMap(binding, isTimeDependent, sourceInfo());
2062 end hasNonTrivialAliasBinding;
2063
2064 function hasConstOrParamAliasBinding
2065 extends checkVar;
2066 algorithm
2067 2015 b := not checkExpMap(Binding.getExp(var.binding), isTimeDependent, sourceInfo());
2068 end hasConstOrParamAliasBinding;
2069
2070 function isTimeDependent
2071 extends checkVar;
2072 algorithm
2073 1767 b := VariableKind.isTimeDependent(var.backendinfo.varKind);
2074 end isTimeDependent;
2075
2076 function isBound
2077 extends checkVar;
2078 algorithm
2079 b := match var.binding
2080 case Binding.TYPED_BINDING() then true;
2081 case Binding.UNTYPED_BINDING() then true;
2082 case Binding.FLAT_BINDING() then true;
2083 else false;
2084 end match;
2085 end isBound;
2086
2087 // ==========================================================================
2088 // Other type wrappers
2089 //
2090 // ==========================================================================
2091
2092 function checkExp
2093 input Expression exp;
2094 input checkVar func;
2095 input SourceInfo info;
2096 output Boolean b;
2097 algorithm
2098 b := match exp
2099 local
2100 ComponentRef cref;
2101 case Expression.CREF(cref = cref)
2102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1767 times.
1767 then func(getVarPointer(cref, info));
2103 else false;
2104 end match;
2105 end checkExp;
2106
2107 function checkExpMap
2108 input Expression exp;
2109 input checkVar func;
2110 input SourceInfo info;
2111 output Boolean b;
2112 function checkExpTraverse
2113 input output Expression exp;
2114 input checkVar func;
2115 input SourceInfo info;
2116 input output Boolean b;
2117 algorithm
2118
2/2
✓ Branch 0 taken 363 times.
✓ Branch 1 taken 2557 times.
2920 if not b then
2119 2557 b := checkExp(exp, func, info);
2120 end if;
2121 end checkExpTraverse;
2122 algorithm
2123 2423 (_, b) := Expression.mapFold(exp, function checkExpTraverse(func=func,info=info), false);
2124 end checkExpMap;
2125
2126 function checkCref
2127 input ComponentRef cref;
2128 input checkVar func;
2129 input SourceInfo info;
2130 output Boolean b = func(getVarPointer(cref, info));
2131 end checkCref;
2132
2133 // ==========================================================================
2134 // Variable Array Stuff
2135 // All variable arrays are pointer arrays to avoid duplicates
2136 // ==========================================================================
2137 uniontype VariablePointers
2138 record VARIABLE_POINTERS
2139 UnorderedMap<ComponentRef, Integer> map "Map for cref->index";
2140 ExpandableArray<Pointer<Variable>> varArr "Array of variable pointers";
2141 Boolean scalarized "true if the variables are scalarized";
2142 end VARIABLE_POINTERS;
2143
2144 function toString
2145 input VariablePointers variables;
2146 input output String str = "";
2147 input Option<array<tuple<Integer,Integer>>> mapping_opt = NONE();
2148 input Boolean printEmpty = true;
2149 protected
2150 Integer numberOfElements = VariablePointers.size(variables);
2151 Integer length, scal_start;
2152 String index;
2153 Boolean useMapping = isSome(mapping_opt);
2154 array<tuple<Integer,Integer>> mapping = listArray({});
2155 algorithm
2156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if useMapping then
2157 length := 15;
2158 ✗ mapping := Util.getOption(mapping_opt);
2159 else
2160 length := 10;
2161 end if;
2162
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if printEmpty or numberOfElements > 0 then
2163 10 str := StringUtil.headline_4(str + " Variables (" + intString(numberOfElements) + "/" + intString(scalarSize(variables, true)) + ")");
2164
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
36 for i in 1:numberOfElements loop
2165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if useMapping then
2166 ✗ (scal_start, _) := mapping[i];
2167 ✗ index := "(" + intString(i) + "|" + intString(scal_start) + ")";
2168 else
2169 26 index := "(" + intString(i) + ")";
2170 end if;
2171 26 index := index + StringUtil.repeat(" ", length - stringLength(index));
2172 26 str := str + BVariable.toString(Pointer.access(ExpandableArray.get(i, variables.varArr)), index) + "\n";
2173 end for;
2174 10 str := str + "\n";
2175 else
2176 str := "";
2177 end if;
2178 end toString;
2179
2180 function map
2181 "Traverses all variables and applies a function to them.
2182 NOTE: Do not changes names with this, it will mess up the Mapping.
2183 Introduce new variables and delete old variables for that!"
2184 input output VariablePointers variables;
2185 input MapFunc func;
2186 partial function MapFunc
2187 input output Variable v;
2188 end MapFunc;
2189 protected
2190 Pointer<Variable> var_ptr;
2191 Variable var, new_var;
2192 algorithm
2193
2/2
✓ Branch 1 taken 92 times.
✓ Branch 2 taken 688 times.
30964 for i in 1:ExpandableArray.getLastUsedIndex(variables.varArr) loop
2194
1/2
✓ Branch 1 taken 30184 times.
✗ Branch 2 not taken.
30184 if ExpandableArray.occupied(i, variables.varArr) then
2195 30184 var_ptr := ExpandableArray.get(i, variables.varArr);
2196 30184 var := Pointer.access(var_ptr);
2197
1/2
✓ Branch 0 taken 30184 times.
✗ Branch 1 not taken.
30184 new_var := func(var);
2198
2/2
✓ Branch 0 taken 18141 times.
✓ Branch 1 taken 12043 times.
30184 if not referenceEq(var, new_var) then
2199 // Do not update the expandable array entry, but the pointer itself
2200 18141 Pointer.update(var_ptr, new_var);
2201 end if;
2202 end if;
2203 end for;
2204 end map;
2205
2206 function mapPtr
2207 "Traverses all variables as pointers and applies a function to them.
2208 NOTE: Do not changes names with this, it will mess up the Mapping.
2209 Introduce new variables and delete old variables for that!
2210 Also does not check for referenceEq, the function has to update the
2211 pointer itself!"
2212 input output VariablePointers variables;
2213 input MapFunc func;
2214 partial function MapFunc
2215 input Pointer<Variable> v;
2216 end MapFunc;
2217 protected
2218 Pointer<Variable> var_ptr;
2219 algorithm
2220
2/2
✓ Branch 1 taken 915 times.
✓ Branch 2 taken 639 times.
8247 for i in 1:ExpandableArray.getLastUsedIndex(variables.varArr) loop
2221
1/2
✓ Branch 1 taken 6693 times.
✗ Branch 2 not taken.
6693 if ExpandableArray.occupied(i, variables.varArr) then
2222 6693 var_ptr := ExpandableArray.get(i, variables.varArr);
2223
1/2
✓ Branch 0 taken 6693 times.
✗ Branch 1 not taken.
6693 func(var_ptr);
2224 end if;
2225 end for;
2226 end mapPtr;
2227
2228 function mapRemovePtr
2229 "Traverses all variable pointers and may invoke to remove the variable pointer
2230 (does not affect other instances of the variable)"
2231 input output VariablePointers variables;
2232 input MapFunc func;
2233 partial function MapFunc
2234 input Pointer<Variable> v;
2235 output Boolean delete;
2236 end MapFunc;
2237 protected
2238 Pointer<Variable> var_ptr;
2239 algorithm
2240
2/2
✓ Branch 1 taken 199 times.
✓ Branch 2 taken 8 times.
3443 for i in 1:ExpandableArray.getLastUsedIndex(variables.varArr) loop
2241
1/2
✓ Branch 1 taken 3236 times.
✗ Branch 2 not taken.
3236 if ExpandableArray.occupied(i, variables.varArr) then
2242 3236 var_ptr := ExpandableArray.get(i, variables.varArr);
2243
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 3212 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 3212 times.
3236 if func(var_ptr) then
2244 24 variables := remove(var_ptr, variables);
2245 end if;
2246 end if;
2247 end for;
2248 207 variables := compress(variables);
2249 end mapRemovePtr;
2250
2251 function empty
2252 "Creates an empty VariablePointers using given size * 1.4."
2253 input Integer size = BaseHashTable.bigBucketSize;
2254 input Boolean scalarized = false;
2255 output VariablePointers variables;
2256 protected
2257 Integer arr_size, bucketSize;
2258 UnorderedMap<ComponentRef, Integer> map;
2259 algorithm
2260 arr_size := max(size, BaseHashTable.lowBucketSize);
2261 15744 bucketSize := Util.nextPrime(arr_size);
2262
2/2
✓ Branch 0 taken 764 times.
✓ Branch 1 taken 14980 times.
15744 if scalarized then
2263 764 map := UnorderedMap.new<Integer>(ComponentRef.hash, ComponentRef.isEqual, bucketSize);
2264 else
2265 14980 map := UnorderedMap.new<Integer>(ComponentRef.hashStrip, ComponentRef.isEqualStrip, bucketSize);
2266 end if;
2267
2/2
✓ Branch 0 taken 14980 times.
✓ Branch 1 taken 764 times.
30724 variables := VARIABLE_POINTERS(map, ExpandableArray.new(arr_size, Pointer.create(DUMMY_VARIABLE)), scalarized);
2268 end empty;
2269
2270 function clone
2271 input VariablePointers variables;
2272 input Boolean shallow = true;
2273 output VariablePointers new;
2274 algorithm
2275
1/2
✓ Branch 0 taken 460 times.
✗ Branch 1 not taken.
460 if shallow then
2276 460 new := fromList(toList(variables));
2277 else
2278 ✗ new := fromList(list(Pointer.create(Pointer.access(eqn)) for eqn in toList(variables)));
2279 end if;
2280 end clone;
2281
2282 function size
2283 "returns the number of elements, not the actual scalarized number of variables!"
2284 input VariablePointers variables;
2285 output Integer sz = ExpandableArray.getNumberOfElements(variables.varArr);
2286 end size;
2287
2288 function lastUsedIndex
2289 "returns the last used index != size!"
2290 input VariablePointers variables;
2291 output Integer sz = ExpandableArray.getLastUsedIndex(variables.varArr);
2292 end lastUsedIndex;
2293
2294 function scalarSize
2295 "returns the scalar size."
2296 input VariablePointers variables;
2297 input Boolean resize = false;
2298 output Integer sz = 0;
2299 algorithm
2300
2/2
✓ Branch 1 taken 7127 times.
✓ Branch 2 taken 489 times.
7616 for var_ptr in toList(variables) loop
2301 7127 sz := sz + BVariable.size(var_ptr, resize);
2302 end for;
2303 end scalarSize;
2304
2305 function toList
2306 "Creates a VariablePointer list from VariablePointers."
2307 input VariablePointers variables;
2308 output list<Pointer<Variable>> var_lst;
2309 algorithm
2310 13271 var_lst := ExpandableArray.toList(variables.varArr);
2311 end toList;
2312
2313 function fromList
2314 "Creates VariablePointers from a VariablePointer list."
2315 input list<Pointer<Variable>> var_lst;
2316 input Boolean scalarized = false;
2317 output VariablePointers variables;
2318 algorithm
2319 15498 variables := empty(listLength(var_lst), scalarized);
2320 15498 variables := addList(var_lst, variables);
2321 end fromList;
2322
2323 function addList
2324 "Adds a list of variables to the Variables structure. If any variable already
2325 exists it's updated instead."
2326 input list<Pointer<Variable>> var_lst;
2327 input output VariablePointers variables;
2328 algorithm
2329 29073 variables := List.fold(var_lst, function add(), variables);
2330 end addList;
2331
2332 function removeList
2333 "Removes a list of variables from the Variables structure."
2334 input list<Pointer<Variable>> var_lst;
2335 input output VariablePointers variables;
2336 algorithm
2337 5589 variables := List.fold(var_lst, function remove(), variables);
2338 5589 variables := compress(variables);
2339 end removeList;
2340
2341 function removeCheck
2342 input output VariablePointers variables;
2343 input checkVar func;
2344 protected
2345 list<Pointer<Variable>> vars;
2346 algorithm
2347
7/8
✗ Branch 1 not taken.
✓ Branch 2 taken 12518 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 12502 times.
✓ Branch 7 taken 12518 times.
✓ Branch 8 taken 760 times.
✓ Branch 9 taken 12502 times.
✓ Branch 10 taken 760 times.
13278 vars := list(var for var guard(not func(var)) in toList(variables));
2348 760 variables := fromList(vars);
2349 end removeCheck;
2350
2351 function add
2352 "Adds a variable pointer to the set, or updates it if it already exists."
2353 input Pointer<Variable> varPointer;
2354 input output VariablePointers variables;
2355 protected
2356 Variable var;
2357 Integer index;
2358 algorithm
2359 147771 var := Pointer.access(varPointer);
2360 () := match UnorderedMap.get(var.name, variables.map)
2361 case SOME(index) guard(index > 0 and (variables.scalarized or ComponentRef.isEqual(var.name, BVariable.getVarName(ExpandableArray.get(index, variables.varArr))))) algorithm
2362 // In non-scalarized (stripped) mode the map key ignores subscripts, so a lookup
2363 // hit here can be a DIFFERENT literal-indexed sibling of the same base array
2364 // (e.g. x[1] found while adding x[2]) rather than a genuine re-add of the same
2365 // variable. Overwriting that slot would silently drop x[1] from the collection
2366 // (VariablePointers.toList/mapPtr only see the array, not the map, so a lost
2367 // slot is a lost variable). Only take the "update in place" path when the
2368 // stored variable's FULL cref actually matches -- otherwise fall through and
2369 // add this as a new, separate entry, same as any other unseen variable.
2370 2022 ExpandableArray.update(index, varPointer, variables.varArr);
2371 then ();
2372 else algorithm
2373 145749 (_, index) := ExpandableArray.add(varPointer, variables.varArr);
2374 145749 UnorderedMap.add(var.name, index, variables.map);
2375 then ();
2376 end match;
2377 end add;
2378
2379 function remove
2380 "Removes a variable pointer identified by its name from the set."
2381 input Pointer<Variable> var_ptr;
2382 input output VariablePointers variables "only an output for mapping";
2383 protected
2384 Variable var;
2385 Integer index;
2386 algorithm
2387 17078 var := Pointer.access(var_ptr);
2388 () := match UnorderedMap.get(var.name, variables.map)
2389 case SOME(index) guard(index > 0) algorithm
2390 8327 ExpandableArray.delete(index, variables.varArr);
2391 // set the index to -1 to avoid removing entries
2392 8327 UnorderedMap.add(var.name, -1, variables.map);
2393 then ();
2394 else ();
2395 end match;
2396 end remove;
2397
2398 function setVarAt
2399 "Sets a Variable pointer at a specific index in the VariablePointers."
2400 input VariablePointers variables;
2401 input Integer idx;
2402 input Pointer<Variable> var_ptr;
2403 protected
2404 Variable var;
2405 algorithm
2406 ✗ ExpandableArray.set(idx, var_ptr, variables.varArr);
2407 ✗ var := Pointer.access(var_ptr);
2408 ✗ UnorderedMap.add(var.name, idx, variables.map);
2409 end setVarAt;
2410
2411 function getVarAt
2412 "Returns the variable pointer at given index. If there is none it fails."
2413 input VariablePointers variables;
2414 input Integer idx;
2415 output Pointer<Variable> var;
2416 algorithm
2417 32164 var := ExpandableArray.get(idx, variables.varArr);
2418 end getVarAt;
2419
2420 function getVarSafe
2421 "Use only for lowering purposes! Otherwise use the InstNode in the
2422 ComponentRef. Fails if the component ref cannot be found."
2423 input VariablePointers variables;
2424 input ComponentRef cref;
2425 input Option<SourceInfo> info = NONE();
2426 output Pointer<Variable> var_ptr;
2427 protected
2428 Integer index;
2429 algorithm
2430 var_ptr := match UnorderedMap.get(cref, variables.map)
2431 124430 case SOME(index) guard(index > 0) then ExpandableArray.get(index, variables.varArr);
2432 else algorithm
2433
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 76 times.
76 if isSome(info) then
2434 ✗ Error.addInternalError(getInstanceName() + " failed for " + ComponentRef.toString(cref), Util.getOption(info));
2435 end if;
2436 76 then fail();
2437 end match;
2438 end getVarSafe;
2439
2440 function getVarIndex
2441 "Returns -1 if cref was deleted or cannot be found."
2442 input VariablePointers variables;
2443 input ComponentRef cref;
2444 output Integer index = UnorderedMap.getOrDefault(cref, variables.map, -1);
2445 end getVarIndex;
2446
2447 function contains
2448 "Returns true if the variable is in the variable pointer array."
2449 input Pointer<Variable> var;
2450 input VariablePointers variables;
2451 output Boolean b = containsCref(getVarName(var), variables);
2452 end contains;
2453
2454 function containsCref
2455 "Returns true if a variable with this name is in the variable pointer array."
2456 input ComponentRef cref;
2457 input VariablePointers variables;
2458 output Boolean b = getVarIndex(variables, cref) > 0;
2459 end containsCref;
2460
2461 function getVarNames
2462 "returns a list of crefs representing the names of all variables"
2463 input VariablePointers variables;
2464 output list<ComponentRef> names;
2465 protected
2466 Pointer<list<ComponentRef>> acc = Pointer.create({});
2467 algorithm
2468 ✗ mapPtr(variables, function getVarNameTraverse(acc = acc));
2469 ✗ names := listReverse(Pointer.access(acc));
2470 end getVarNames;
2471
2472 function getScalarVarNames
2473 "Returns the names of all variables, with arrays and records expanded."
2474 input VariablePointers variables;
2475 input Boolean resize;
2476 output list<ComponentRef> names = {};
2477 protected
2478 Variable var;
2479 algorithm
2480 ✗ for var_ptr in toList(variables) loop
2481 ✗ var := Pointer.access(var_ptr);
2482
2483 ✗ if Type.isArray(var.ty) then
2484 ✗ for cr in ComponentRef.scalarizeAll(ComponentRef.stripSubscriptsAll(var.name), resize) loop
2485 ✗ if Type.isComplex(ComponentRef.nodeType(cr)) then
2486 ✗ names := listAppend(ComponentRef.getRecordChildren(cr), names);
2487 else
2488 names := cr :: names;
2489 end if;
2490 end for;
2491 else
2492 ✗ names := var.name :: names;
2493 end if;
2494 end for;
2495 end getScalarVarNames;
2496
2497 function getMarkedVars
2498 input VariablePointers variables;
2499 input array<Boolean> marks;
2500 output list<Pointer<Variable>> marked_vars;
2501 protected
2502 list<Integer> indices = BackendUtil.findTrueIndices(marks);
2503 algorithm
2504
1/2
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
190 if arrayLength(marks) == VariablePointers.size(variables) then
2505
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 190 times.
190 marked_vars := list(getVarAt(variables, index) for index in indices);
2506 else
2507 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because the number var marks ("
2508 + intString(arrayLength(marks)) + ") is not equal to the number of variables ("
2509 + intString(VariablePointers.size(variables)) + ")."});
2510 ✗ fail();
2511 end if;
2512 end getMarkedVars;
2513
2514 function compress "O(n)
2515 Reorders the elements in order to remove all the gaps.
2516 Be careful: This changes the indices of the elements.
2517 Cannot use ExpandableArray.compress since it needs to
2518 update the UnorderedMap."
2519 input output VariablePointers variables;
2520 protected
2521 list<Pointer<Variable>> vars = {};
2522 algorithm
2523
2/2
✓ Branch 1 taken 2925 times.
✓ Branch 2 taken 3570 times.
76339 for i in ExpandableArray.getLastUsedIndex(variables.varArr):-1:1 loop
2524
2/2
✓ Branch 1 taken 62225 times.
✓ Branch 2 taken 7619 times.
69844 if ExpandableArray.occupied(i, variables.varArr) then
2525 62225 vars := ExpandableArray.get(i, variables.varArr) :: vars;
2526 end if;
2527 end for;
2528 6495 variables := fromList(vars);
2529 end compress;
2530
2531 function sort
2532 "author: kabdelhak
2533 Sorts the variables solely by their attributes and type hash.
2534 Does not use the name! Used for reproduceable heuristic behavior independent of names."
2535 input output VariablePointers variables;
2536 protected
2537 Integer size;
2538 list<tuple<Integer, Pointer<Variable>>> hash_lst;
2539 Pointer<list<tuple<Integer, Pointer<Variable>>>> hash_lst_ptr = Pointer.create({});
2540 Pointer<Variable> var_ptr;
2541 algorithm
2542 // use number of elements
2543 ✗ size := ExpandableArray.getNumberOfElements(variables.varArr);
2544 // hash all variables and create hash - variable tpl list
2545 ✗ mapPtr(variables, function createSortHashTpl(mod = realInt(size * log(size)), hash_lst_ptr = hash_lst_ptr));
2546 ✗ hash_lst := List.sort(Pointer.access(hash_lst_ptr), BackendUtil.indexTplGt);
2547 // create new variables and add them one by one in sorted order
2548 ✗ variables := empty(size, variables.scalarized);
2549 ✗ for tpl in hash_lst loop
2550 ✗ (_, var_ptr) := tpl;
2551 ✗ variables := add(var_ptr, variables);
2552 end for;
2553 end sort;
2554
2555 function scalarize
2556 "author: kabdelhak
2557 Expands all variables to their scalar elements."
2558 input output VariablePointers variables;
2559 protected
2560 list<Pointer<Variable>> vars;
2561 Boolean flattened;
2562 algorithm
2563 2393 (vars, flattened) := scalarizeList(toList(variables));
2564 // only change variables if any of them have been flattened
2565
2/2
✓ Branch 0 taken 2120 times.
✓ Branch 1 taken 273 times.
2393 if flattened then
2566 273 variables := fromList(vars, true);
2567 end if;
2568 end scalarize;
2569
2570 function scalarizeList
2571 input list<Pointer<Variable>> vars;
2572 output list<Pointer<Variable>> new_vars = {};
2573 output Boolean flattened = false;
2574 protected
2575 list<Variable> scalar_vars, element_vars;
2576 Variable var;
2577 algorithm
2578
2/2
✓ Branch 0 taken 10025 times.
✓ Branch 1 taken 2417 times.
12442 for var_ptr in vars loop
2579 10025 var := Pointer.access(var_ptr);
2580 // flatten potential arrays
2581
2/2
✓ Branch 1 taken 1395 times.
✓ Branch 2 taken 8630 times.
10025 if Type.isArray(var.ty) then
2582 flattened := true;
2583 1395 scalar_vars := Scalarize.scalarizeBackendVariable(var);
2584 else
2585 8630 scalar_vars := {Pointer.access(var_ptr)};
2586 end if;
2587
2588 // flatten potential records
2589
2/2
✓ Branch 0 taken 20883 times.
✓ Branch 1 taken 10025 times.
30908 for var in scalar_vars loop
2590
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 20882 times.
20883 if Type.isComplex(var.ty) then
2591 flattened := true;
2592 1 element_vars := Scalarize.scalarizeComplexVariable(var);
2593
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 for elem_var in listReverse(element_vars) loop
2594 1 new_vars := Pointer.create(elem_var) :: new_vars;
2595 end for;
2596 else
2597 20882 new_vars := Pointer.create(var) :: new_vars;
2598 end if;
2599 end for;
2600 end for;
2601 2417 new_vars := listReverse(new_vars);
2602 end scalarizeList;
2603
2604 function varSlice
2605 input VariablePointers vars;
2606 input Integer scal;
2607 input Integer arr;
2608 input Mapping mapping;
2609 input Boolean resize;
2610 output ComponentRef cref;
2611 protected
2612 Pointer<Variable> var;
2613 Integer start;
2614 Type ty;
2615 list<Dimension> dims;
2616 list<Integer> sizes, vals;
2617 list<Subscript> subs;
2618 algorithm
2619 // get array index, start of scalar index and size
2620 6975 (start, _) := mapping.var_AtS[arr];
2621
2622 // get the variable, name and type
2623 6975 var := VariablePointers.getVarAt(vars, arr);
2624
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6975 times.
6975 Variable.VARIABLE(name = cref, ty = ty) := Pointer.access(var);
2625
2626 // get the dimensions, their sizes and the respective index values for the subscripts
2627 6975 dims := Type.arrayDims(ty);
2628
4/4
✓ Branch 0 taken 2826 times.
✓ Branch 1 taken 6975 times.
✓ Branch 2 taken 2826 times.
✓ Branch 3 taken 6975 times.
9801 sizes := list(Dimension.size(dim, resize) for dim in dims);
2629 6975 vals := listReverse(Slice.indexToLocation(scal-start, sizes));
2630
2631 // thread them to the apropriate subscripts and merge them to the cref
2632
7/8
✓ Branch 0 taken 2826 times.
✓ Branch 1 taken 6975 times.
✓ Branch 2 taken 2826 times.
✓ Branch 3 taken 6975 times.
✓ Branch 4 taken 2826 times.
✓ Branch 5 taken 6975 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6975 times.
9801 subs := list(Subscript.nth(dim, val+1) threaded for dim in dims, val in vals);
2633 6975 cref := ComponentRef.mergeSubscripts(subs, cref, true, true);
2634 end varSlice;
2635
2636 protected
2637 function createSortHashTpl
2638 "Helper function for sort(). Creates the hash value without considering the name and
2639 adds it as a tuple to the list in pointer."
2640 input Pointer<Variable> var_ptr;
2641 input Integer mod;
2642 input Pointer<list<tuple<Integer, Pointer<Variable>>>> hash_lst_ptr;
2643 protected
2644 Variable var;
2645 Integer hash;
2646 algorithm
2647 ✗ var := Pointer.access(var_ptr);
2648 // create hash only from backendinfo
2649 ✗ hash := stringHashDjb2Mod(BackendInfo.toString(var.backendinfo), mod);
2650 ✗ Pointer.update(hash_lst_ptr, (hash, var_ptr) :: Pointer.access(hash_lst_ptr));
2651 end createSortHashTpl;
2652 end VariablePointers;
2653
2654 // ==========================================================================
2655 // Variable Data
2656 // All variable arrays are pointer arrays to avoid duplicates
2657 // ==========================================================================
2658 uniontype VarData
2659 "All variable arrays are pointer subsets of an array of variables indicated
2660 by preceding comment. Used to traverse all variables of a special kind."
2661
2662 record VAR_DATA_SIM
2663 "Only to be used for simulation systems."
2664 Pointer<Integer> uniqueIndex "use when trying to create unique variables";
2665 VariablePointers variables "All variables";
2666 /* subset of full variable array */
2667 VariablePointers unknowns "All state derivatives, algebraic variables,
2668 discrete variables";
2669 VariablePointers knowns "Parameters, constants, states";
2670 VariablePointers initials "All initial unknowns (unknowns + states + previous + parameters(non const binding))";
2671 VariablePointers auxiliaries "Variables created by the backend known to be solved
2672 by given binding. E.g. $cse";
2673 VariablePointers aliasVars "Variables removed due to alias removal with 1 or -1 coefficient";
2674 VariablePointers nonTrivialAlias "Variables removed due to alias removal with gain * alias + offset function";
2675
2676 /* subset of unknowns */
2677 VariablePointers derivatives "State derivatives (der(x) -> $DER.x)";
2678 VariablePointers algebraics "Algebraic variables";
2679 VariablePointers discretes "Discrete variables";
2680 VariablePointers discrete_states "Discrete state variables";
2681 VariablePointers clocked_states "Clocked state variables";
2682 VariablePointers previous "Previous variables (pre(d) -> $PRE.d)";
2683 VariablePointers clocks "clock variables";
2684
2685 /* subset of knowns */
2686 VariablePointers states "States";
2687 VariablePointers top_level_inputs "Top level inputs";
2688 VariablePointers resizables "Resizable Parameters";
2689 VariablePointers parameters "Parameters";
2690 VariablePointers constants "Constants";
2691 VariablePointers records "Records";
2692 VariablePointers external_objects "External Objects";
2693 VariablePointers artificials "artificial variables to have pointers on crefs";
2694
2695 /* state order for differentiation and index reduction */
2696 UnorderedMap<ComponentRef, ComponentRef> state_order;
2697 end VAR_DATA_SIM;
2698
2699 record VAR_DATA_JAC
2700 "Only to be used for Jacobians."
2701 VariablePointers variables "All jacobian variables";
2702 /* subset of full variable array */
2703 VariablePointers unknowns "All result and temporary vars"; // FIXME unused?
2704 VariablePointers auxiliaries "Variables created by the backend known to be solved
2705 by given binding. E.g. $cse";
2706 VariablePointers aliasVars "Variables removed due to alias removal";
2707
2708 /* subset of global full variable array */
2709 VariablePointers diffVars "Differentiation variables z where J = dF/dz";
2710 VariablePointers dependencies "All occurring unknowns for linearity analysis";
2711
2712 /* subset of local unknowns */
2713 VariablePointers resultVars "Result variable depending on current seed
2714 ($RES.[jacname].[eq_idx])";
2715 VariablePointers tmpVars "Temporary variables (inner partial derivatives)
2716 dy/dz with y!=z for all y and z
2717 ($TMP.[jacname].y)";
2718
2719 /* subset of auxiliaries */
2720 VariablePointers seedVars "Seed variables representing a generic derivative
2721 dx/dz which is 1 for x==z and 0 otherwise.
2722 ($SEED.[jacname].x)";
2723 end VAR_DATA_JAC;
2724
2725 record VAR_DATA_HES
2726 "Only to be used for Hessians."
2727 VariablePointers variables "All hessian variables";
2728 /* subset of full variable array */
2729 VariablePointers unknowns "All state derivatives, algebraic variables,
2730 discrete variables";
2731 VariablePointers knowns "Parameters, constants";
2732 VariablePointers auxiliaries "Variables created by the backend known to be solved
2733 by given binding. E.g. $cse";
2734 VariablePointers aliasVars "Variables removed due to alias removal";
2735
2736 /* subset of global full variable array */
2737 VariablePointers diffVars "Differentiation variables z where J = dF/dz";
2738 VariablePointers dependencies "All occurring unknowns for linearity analysis";
2739
2740 /* subset of local unknowns */
2741 VariablePointers resultVars "Result variable depending on current seed
2742 ($RES.[jacname].[eq_idx])";
2743 VariablePointers tmpVars "Temporary variables (inner partial derivatives)
2744 dy/dz with y!=z for all y and z
2745 ($TMP.[jacname].y)";
2746
2747 /* subset of auxiliaries */
2748 VariablePointers seedVars "Seed variables representing a generic derivative
2749 dx/dz which is 1 for x==z and 0 otherwise.
2750 ($SEED.[jacname].x)";
2751 /* subset of auxiliaries */
2752 VariablePointers seedVars2 "Second seed variables representing a generic
2753 derivative dx/dz which is 1 for x==z and 0 otherwise.
2754 ($SEED2.[jacname].x)";
2755 Option<VariablePointers> lambdaVars "Lambda variables for optimization";
2756 end VAR_DATA_HES;
2757
2758 record VAR_DATA_EMPTY end VAR_DATA_EMPTY;
2759
2760 function size
2761 input VarData varData;
2762 output Integer s;
2763 algorithm
2764 s := match varData
2765 ✗ case VAR_DATA_SIM() then VariablePointers.size(varData.unknowns);
2766 ✗ case VAR_DATA_JAC() then VariablePointers.size(varData.unknowns);
2767 ✗ case VAR_DATA_HES() then VariablePointers.size(varData.unknowns);
2768 end match;
2769 end size;
2770
2771 function scalarSize
2772 input VarData varData;
2773 input Boolean resize = false;
2774 output Integer s;
2775 algorithm
2776 s := match varData
2777 ✗ case VAR_DATA_SIM() then VariablePointers.scalarSize(varData.unknowns, resize);
2778 ✗ case VAR_DATA_JAC() then VariablePointers.scalarSize(varData.unknowns, resize);
2779 ✗ case VAR_DATA_HES() then VariablePointers.scalarSize(varData.unknowns, resize);
2780 end match;
2781 end scalarSize;
2782
2783 function toString
2784 input VarData varData;
2785 input Integer level = 0;
2786 output String str;
2787 algorithm
2788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 str := if level == 0 then match varData
2789 ✗ case VAR_DATA_SIM() then VariablePointers.toString(varData.variables, "Simulation");
2790 ✗ case VAR_DATA_JAC() then VariablePointers.toString(varData.variables, "Jacobian");
2791 ✗ case VAR_DATA_HES() then VariablePointers.toString(varData.variables, "Hessian");
2792 case VAR_DATA_EMPTY() then "Empty variable Data!\n";
2793 else fail();
2794 end match
2795 elseif level == 1 then toStringVerbose(varData, false)
2796 else toStringVerbose(varData, true);
2797 end toString;
2798
2799 function toStringVerbose
2800 input VarData varData;
2801 input Boolean full = false;
2802 output String str;
2803 algorithm
2804 str := match varData
2805 local
2806 String tmp = "";
2807 VariablePointers lambdaVars;
2808
2809 case VAR_DATA_SIM() algorithm
2810 ✗ tmp := "Variable Data Simulation (scalar unknowns: " + intString(VariablePointers.scalarSize(varData.unknowns, true)) + ")";
2811 ✗ tmp := StringUtil.headline_2(tmp) + "\n";
2812 ✗ if not full then
2813 ✗ tmp := tmp + VariablePointers.toString(varData.unknowns, "Unknown", NONE(), false) +
2814 VariablePointers.toString(varData.states, "Local Known", NONE(), false) +
2815 VariablePointers.toString(varData.knowns, "Global Known", NONE(), false);
2816 else
2817 ✗ tmp := tmp + VariablePointers.toString(varData.states, "State", NONE(), false) +
2818 VariablePointers.toString(varData.derivatives, "Derivative", NONE(), false) +
2819 VariablePointers.toString(varData.algebraics, "Algebraic", NONE(), false) +
2820 VariablePointers.toString(varData.discretes, "Discrete", NONE(), false) +
2821 VariablePointers.toString(varData.discrete_states, "Discrete State", NONE(), false) +
2822 VariablePointers.toString(varData.clocked_states, "Clocked State", NONE(), false) +
2823 VariablePointers.toString(varData.previous, "Previous", NONE(), false) +
2824 VariablePointers.toString(varData.clocks, "Clock", NONE(), false) +
2825 VariablePointers.toString(varData.top_level_inputs, "Top Level Input", NONE(), false) +
2826 VariablePointers.toString(varData.resizables, "Resizable Parameter", NONE(), false) +
2827 VariablePointers.toString(varData.parameters, "Parameter", NONE(), false) +
2828 VariablePointers.toString(varData.constants, "Constant", NONE(), false) +
2829 VariablePointers.toString(varData.records, "Record", NONE(), false) +
2830 VariablePointers.toString(varData.external_objects, "External Object", NONE(), false) +
2831 VariablePointers.toString(varData.artificials, "Artificial", NONE(), false);
2832 end if;
2833 ✗ tmp := tmp + VariablePointers.toString(varData.auxiliaries, "Auxiliary", NONE(), false) +
2834 VariablePointers.toString(varData.aliasVars, "Alias", NONE(), false);
2835 then tmp;
2836
2837 case VAR_DATA_JAC() algorithm
2838 4 tmp := VariablePointers.toString(varData.unknowns, "Partial Derivative", NONE(), false) +
2839 VariablePointers.toString(varData.seedVars, "Seed", NONE(), false);
2840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if full then
2841 ✗ tmp := tmp + VariablePointers.toString(varData.diffVars, "Differentiation", NONE(), false) +
2842 VariablePointers.toString(varData.resultVars, "Residual", NONE(), false) +
2843 VariablePointers.toString(varData.tmpVars, "Inner", NONE(), false) +
2844 VariablePointers.toString(varData.dependencies, "Dependencies", NONE(), false) +
2845 VariablePointers.toString(varData.auxiliaries, "Auxiliary", NONE(), false) +
2846 VariablePointers.toString(varData.aliasVars, "Alias", NONE(), false);
2847 end if;
2848 then tmp;
2849
2850 case VAR_DATA_HES() algorithm
2851 ✗ tmp := StringUtil.headline_2("Variable Data Hessian") + "\n" +
2852 VariablePointers.toString(varData.unknowns, "Unknown", NONE(), false) +
2853 VariablePointers.toString(varData.knowns, "Known", NONE(), false) +
2854 VariablePointers.toString(varData.auxiliaries, "Auxiliary", NONE(), false) +
2855 VariablePointers.toString(varData.aliasVars, "Alias", NONE(), false);
2856 ✗ if full then
2857 ✗ tmp := tmp + VariablePointers.toString(varData.diffVars, "Differentiation", NONE(), false) +
2858 VariablePointers.toString(varData.dependencies, "Dependencies", NONE(), false) +
2859 VariablePointers.toString(varData.resultVars, "Result", NONE(), false) +
2860 VariablePointers.toString(varData.tmpVars, "Temporary", NONE(), false) +
2861 VariablePointers.toString(varData.seedVars, "First Seed", NONE(), false) +
2862 VariablePointers.toString(varData.seedVars2, "Second Seed", NONE(), false);
2863 ✗ if isSome(varData.lambdaVars) then
2864 ✗ SOME(lambdaVars) := varData.lambdaVars;
2865 ✗ tmp := tmp + VariablePointers.toString(lambdaVars, "Lagrangian Lambda", NONE(), false);
2866 end if;
2867 end if;
2868 then tmp;
2869
2870 else fail();
2871 end match;
2872 end toStringVerbose;
2873
2874 function getVariables
2875 input VarData varData;
2876 output VariablePointers variables;
2877 algorithm
2878 variables := match varData
2879 5124 case VAR_DATA_SIM() then varData.variables;
2880 ✗ case VAR_DATA_JAC() then varData.variables;
2881 ✗ case VAR_DATA_HES() then varData.variables;
2882 else fail();
2883 end match;
2884 end getVariables;
2885
2886 function setVariables
2887 input output VarData varData;
2888 input VariablePointers variables;
2889 algorithm
2890 varData := match varData
2891 ✗ case VAR_DATA_SIM() algorithm varData.variables := variables; then varData;
2892 ✗ case VAR_DATA_JAC() algorithm varData.variables := variables; then varData;
2893 ✗ case VAR_DATA_HES() algorithm varData.variables := variables; then varData;
2894 else fail();
2895 end match;
2896 end setVariables;
2897
2898 function getUniqueIndex
2899 input VarData varData;
2900 output Pointer<Integer> uniqueIndex;
2901 algorithm
2902 uniqueIndex := match varData
2903 347 case VAR_DATA_SIM() then varData.uniqueIndex;
2904 else algorithm
2905 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed because of incorrect record type."});
2906 ✗ then fail();
2907 end match;
2908 end getUniqueIndex;
2909
2910 function getStateOrder
2911 input VarData varData;
2912 output UnorderedMap<ComponentRef, ComponentRef> state_order;
2913 algorithm
2914 state_order := match varData
2915 86 case VAR_DATA_SIM() then varData.state_order;
2916 else algorithm
2917 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed because of incorrect record type."});
2918 ✗ then fail();
2919 end match;
2920 end getStateOrder;
2921
2922 // used to add specific types. Fill up with Jacobian/Hessian types
2923 type VarType = enumeration(STATE, STATE_DER, ALGEBRAIC, DISCRETE, DISC_STATE, PREVIOUS, START, PARAMETER, ITERATOR, RECORD, CLOCK);
2924
2925 function addTypedList
2926 "can also be used to add single variables"
2927 input output VarData varData;
2928 input list<Pointer<Variable>> var_lst;
2929 input VarType varType;
2930 algorithm
2931
2/2
✓ Branch 0 taken 2733 times.
✓ Branch 1 taken 579 times.
3312 if listEmpty(var_lst) then return; end if;
2932
2933 varData := match (varData, varType)
2934
2935 case (VAR_DATA_SIM(), VarType.STATE) algorithm
2936 28 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2937 28 varData.knowns := VariablePointers.addList(var_lst, varData.knowns);
2938 28 varData.states := VariablePointers.addList(var_lst, varData.states);
2939 28 varData.initials := VariablePointers.addList(var_lst, varData.initials);
2940 // also remove from algebraics in the case it was moved
2941 28 varData.unknowns := VariablePointers.removeList(var_lst, varData.unknowns);
2942 28 varData.algebraics := VariablePointers.removeList(var_lst, varData.algebraics);
2943 then varData;
2944
2945 case (VAR_DATA_SIM(), VarType.STATE_DER) algorithm
2946 22 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2947 22 varData.unknowns := VariablePointers.addList(var_lst, varData.unknowns);
2948 22 varData.derivatives := VariablePointers.addList(var_lst, varData.derivatives);
2949 22 varData.initials := VariablePointers.addList(var_lst, varData.initials);
2950 then varData;
2951
2952 // algebraic variables, dummy states and dummy derivatives are mathematically equal
2953 case (VAR_DATA_SIM(), VarType.ALGEBRAIC) algorithm
2954 183 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2955 183 varData.unknowns := VariablePointers.addList(var_lst, varData.unknowns);
2956 183 varData.algebraics := VariablePointers.addList(var_lst, varData.algebraics);
2957 183 varData.initials := VariablePointers.addList(var_lst, varData.initials);
2958 // also remove from states/derivatives in the case it was moved
2959 183 varData.states := VariablePointers.removeList(var_lst, varData.states);
2960 183 varData.derivatives := VariablePointers.removeList(var_lst, varData.derivatives);
2961 183 varData.knowns := VariablePointers.removeList(var_lst, varData.knowns);
2962 then varData;
2963
2964 case (VAR_DATA_SIM(), VarType.DISCRETE) algorithm
2965 3 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2966 3 varData.unknowns := VariablePointers.addList(var_lst, varData.unknowns);
2967 3 varData.discretes := VariablePointers.addList(var_lst, varData.discretes);
2968 3 varData.initials := VariablePointers.addList(var_lst, varData.initials);
2969 then varData;
2970
2971 case (VAR_DATA_SIM(), VarType.START) algorithm
2972 27 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2973 27 varData.initials := VariablePointers.addList(var_lst, varData.initials);
2974 then varData;
2975
2976 case (VAR_DATA_SIM(), VarType.PARAMETER) algorithm
2977 11 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2978 11 varData.parameters := VariablePointers.addList(var_lst, varData.parameters);
2979 11 varData.knowns := VariablePointers.addList(var_lst, varData.knowns);
2980 then varData;
2981
2982 case (VAR_DATA_SIM(), VarType.ITERATOR) algorithm
2983 291 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2984 291 varData.knowns := VariablePointers.addList(var_lst, varData.knowns);
2985 291 varData.artificials := VariablePointers.addList(var_lst, varData.artificials);
2986 then varData;
2987
2988 case (VAR_DATA_SIM(), VarType.CLOCK) algorithm
2989 1 varData.clocks := VariablePointers.addList(var_lst, varData.clocks);
2990 then varData;
2991
2992 // IMPORTANT: requires the record elements to be added as children beforehand!
2993 case (VAR_DATA_SIM(), VarType.RECORD) algorithm
2994 13 varData.variables := VariablePointers.addList(var_lst, varData.variables);
2995 13 varData.records := VariablePointers.addList(var_lst, varData.records);
2996 13 varData.knowns := VariablePointers.addList(var_lst, varData.knowns);
2997 26 varData.records := VariablePointers.mapPtr(varData.records, function BackendDAE.lowerUnkownRecordChildren(variables = varData.variables));
2998 then varData;
2999
3000 // ToDo: other cases
3001
3002 else algorithm
3003 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
3004 ✗ then fail();
3005 end match;
3006 end addTypedList;
3007
3008 function removeTypedCheck
3009 "can also be used to add single variables"
3010 input output VarData varData;
3011 input checkVar func;
3012 input VarType varType;
3013 algorithm
3014 varData := match (varData, varType)
3015
3016 case (VAR_DATA_SIM(), VarType.STATE) algorithm
3017 ✗ varData.variables := VariablePointers.removeCheck(varData.variables, func);
3018 ✗ varData.knowns := VariablePointers.removeCheck(varData.knowns, func);
3019 ✗ varData.states := VariablePointers.removeCheck(varData.states, func);
3020 ✗ varData.initials := VariablePointers.removeCheck(varData.initials, func);
3021 then varData;
3022
3023 case (VAR_DATA_SIM(), VarType.STATE_DER) algorithm
3024 ✗ varData.variables := VariablePointers.removeCheck(varData.variables, func);
3025 ✗ varData.unknowns := VariablePointers.removeCheck(varData.unknowns, func);
3026 ✗ varData.derivatives := VariablePointers.removeCheck(varData.derivatives, func);
3027 ✗ varData.initials := VariablePointers.removeCheck(varData.initials, func);
3028 then varData;
3029
3030 case (VAR_DATA_SIM(), VarType.ALGEBRAIC) algorithm
3031 ✗ varData.variables := VariablePointers.removeCheck(varData.variables, func);
3032 ✗ varData.unknowns := VariablePointers.removeCheck(varData.unknowns, func);
3033 ✗ varData.algebraics := VariablePointers.removeCheck(varData.algebraics, func);
3034 ✗ varData.initials := VariablePointers.removeCheck(varData.initials, func);
3035 then varData;
3036
3037 case (VAR_DATA_SIM(), VarType.DISCRETE) algorithm
3038 190 varData.variables := VariablePointers.removeCheck(varData.variables, func);
3039 190 varData.unknowns := VariablePointers.removeCheck(varData.unknowns, func);
3040 190 varData.discretes := VariablePointers.removeCheck(varData.discretes, func);
3041 190 varData.initials := VariablePointers.removeCheck(varData.initials, func);
3042 then varData;
3043
3044 case (VAR_DATA_SIM(), VarType.START) algorithm
3045 ✗ varData.variables := VariablePointers.removeCheck(varData.variables, func);
3046 ✗ varData.initials := VariablePointers.removeCheck(varData.initials, func);
3047 then varData;
3048
3049 case (VAR_DATA_SIM(), VarType.PARAMETER) algorithm
3050 ✗ varData.variables := VariablePointers.removeCheck(varData.variables, func);
3051 ✗ varData.parameters := VariablePointers.removeCheck(varData.parameters, func);
3052 ✗ varData.knowns := VariablePointers.removeCheck(varData.knowns, func);
3053 then varData;
3054
3055 case (VAR_DATA_SIM(), VarType.ITERATOR) algorithm
3056 ✗ varData.variables := VariablePointers.removeCheck(varData.variables, func);
3057 ✗ varData.knowns := VariablePointers.removeCheck(varData.knowns, func);
3058 ✗ varData.artificials := VariablePointers.removeCheck(varData.artificials, func);
3059 then varData;
3060
3061 case (VAR_DATA_SIM(), VarType.CLOCK) algorithm
3062 ✗ varData.clocks := VariablePointers.removeCheck(varData.clocks, func);
3063 then varData;
3064
3065 case (VAR_DATA_SIM(), VarType.RECORD) algorithm
3066 ✗ varData.variables := VariablePointers.removeCheck(varData.variables, func);
3067 ✗ varData.records := VariablePointers.removeCheck(varData.records, func);
3068 ✗ varData.knowns := VariablePointers.removeCheck(varData.knowns, func);
3069 then varData;
3070
3071 // ToDo: other cases
3072
3073 else algorithm
3074 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
3075 ✗ then fail();
3076 end match;
3077 end removeTypedCheck;
3078 end VarData;
3079
3080 // ==========================================================================
3081 // Protected utility functions
3082 // ==========================================================================
3083 protected
3084 function getVarNameTraverse
3085 input Pointer<Variable> var;
3086 input Pointer<list<ComponentRef>> acc;
3087 algorithm
3088 ✗ Pointer.update(acc, getVarName(var) :: Pointer.access(acc));
3089 end getVarNameTraverse;
3090
3091 annotation(__OpenModelica_Interface="nbackend");
3092 end NBVariable;
3093