Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 85.0% 311 / 0 / 366
Functions: -% 0 / 1 / 1
Branches: 72.5% 316 / 0 / 436

OMCompiler/Compiler/NBackEnd/Modules/1_Main/NBInitialization.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 NBInitialization
37 "file: NBInitialization.mo
38 package: NBInitialization
39 description: This file contains the main data types for the initialization
40 process.
41 "
42
43 protected
44 import AbsynUtil;
45
46 // NF imports
47 import Algorithm = NFAlgorithm;
48 import Binding = NFBinding;
49 import Call = NFCall;
50 import ComponentRef = NFComponentRef;
51 import Dimension = NFDimension;
52 import Expression = NFExpression;
53 import Flatten = NFFlatten;
54 import NFFunction.Function;
55 import NFInstNode.InstNode;
56 import Operator = NFOperator;
57 import Statement = NFStatement;
58 import Subscript = NFSubscript;
59 import Type = NFType;
60 import Variable = NFVariable;
61
62 // Backend imports
63 import BackendDAE = NBackendDAE;
64 import BEquation = NBEquation;
65 import NBEquation.{Equation, EquationPointers, EqData, EquationAttributes, EquationKind, Iterator, WhenEquationBody, WhenStatement, IfEquationBody};
66 import BVariable = NBVariable;
67 import PointerWeak;
68 import NBVariable.{VariablePointer, VariablePointers, VarData};
69 import Causalize = NBCausalize;
70 import Inline = NBInline;
71 import Jacobian = NBJacobian;
72 import Module = NBModule;
73 import Partitioning = NBPartitioning;
74 import Replacements = NBReplacements;
75 import BPartition = NBPartition;
76 import NBPartition.Partition;
77 import StrongComponent = NBStrongComponent;
78 import Tearing = NBTearing;
79
80 // Util imports
81 import ClockIndexes;
82 import Slice = NBSlice;
83 import StringUtil;
84
85 public
86 function main extends Module.wrapper;
87 protected
88 VariablePointers variables, initialVars;
89 EquationPointers equations, initialEqs;
90 list<tuple<Module.wrapper, String>> modules;
91 list<tuple<String, Real>> clocks;
92 list<String> followEquations = Flags.getConfigStringList(Flags.DEBUG_FOLLOW_EQUATIONS);
93 Option<UnorderedSet<String>> eq_filter_opt;
94 algorithm
95 try
96 bdae := match bdae
97 local
98 VarData varData;
99 EqData eqData;
100 EquationPointers clonedEqns;
101 VariablePointers clonedVars;
102 UnorderedSet<ComponentRef> algorithm_outputs = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual);
103 UnorderedSet<VariablePointer> new_iters = UnorderedSet.new(BVariable.hash, BVariable.equalName);
104 UnorderedMap<ComponentRef, Iterator> cref_map = UnorderedMap.new<Iterator>(ComponentRef.hash, ComponentRef.isEqual);
105 list<Pointer<Equation>> parameter_eqs, secondary_eqs, primary_aux_eqs;
106 list<Pointer<Variable>> parameter_vars, secondary_vars;
107 list<StrongComponent> primary_comps;
108
109 case BackendDAE.MAIN( varData = varData as VarData.VAR_DATA_SIM(variables = variables, initials = initialVars),
110 eqData = eqData as EqData.EQ_DATA_SIM(equations = equations, initials = initialEqs))
111 algorithm
112 // clone all simulation equations and add them to the initial equations.
113 188 clonedEqns := EquationPointers.clone(equations, false);
114 188 initialEqs := EquationPointers.addList(EquationPointers.toList(initialEqs), clonedEqns);
115 188 EquationPointers.mapRemovePtr(initialEqs, Equation.isClocked);
116 188 EquationPointers.mapPtr(initialEqs, replaceClockedFunctionsEqn);
117
118 //remove/replace when equations and clocked equations and remove clocked functions
119 188 initialEqs := EquationPointers.map(initialEqs, function removeWhenEquation(iter = Iterator.EMPTY(), cref_map = cref_map));
120 188 (equations, initialEqs) := createWhenReplacementEquations(cref_map, equations, initialEqs, eqData.uniqueIndex);
121
122 // collect algorithm outputs and do not create start equations for them
123 188 EquationPointers.map(initialEqs, function collectAlgorithmOutputs(outputs = algorithm_outputs));
124
125 // create the equations from fixed variables.
126 188 (variables, initialVars, equations, initialEqs) := createStartEquations(varData.states, variables, initialVars, equations, initialEqs, eqData.uniqueIndex, algorithm_outputs, varData.aliasVars, "State");
127 188 (variables, initialVars, equations, initialEqs) := createStartEquations(varData.algebraics, variables, initialVars, equations, initialEqs, eqData.uniqueIndex, algorithm_outputs, varData.aliasVars, "Algebraic");
128 188 (variables, initialVars, equations, initialEqs) := createStartEquations(varData.discretes, variables, initialVars, equations, initialEqs, eqData.uniqueIndex, algorithm_outputs, varData.aliasVars, "Discrete");
129 188 (variables, initialVars, equations, initialEqs) := createStartEquations(varData.discrete_states, variables, initialVars, equations, initialEqs, eqData.uniqueIndex, algorithm_outputs, varData.aliasVars, "Discrete State");
130 188 (variables, initialVars, equations, initialEqs) := createStartEquations(varData.clocked_states, variables, initialVars, equations, initialEqs, eqData.uniqueIndex, algorithm_outputs, varData.aliasVars, "Clocked State");
131 188 (parameter_eqs, parameter_vars) := createParameterEquations(varData.parameters, new_iters, eqData.uniqueIndex, {}, {});
132 188 (parameter_eqs, parameter_vars) := createParameterEquations(varData.resizables, new_iters, eqData.uniqueIndex, parameter_eqs, parameter_vars);
133 188 (parameter_eqs, parameter_vars) := createParameterEquations(varData.records, new_iters, eqData.uniqueIndex, parameter_eqs, parameter_vars);
134 188 (parameter_eqs, parameter_vars) := createParameterEquations(varData.external_objects, new_iters, eqData.uniqueIndex, parameter_eqs, parameter_vars);
135
136 // like the old backend: the primary parameters (not depending on a parameter that is not fixed)
137 // are solved explicitly before the initialization, only the secondary ones are part of it
138 // the function alias variables in the bindings are solved with them if possible
139
6/6
✓ Branch 2 taken 3529 times.
✓ Branch 3 taken 532 times.
✓ Branch 4 taken 4061 times.
✓ Branch 5 taken 188 times.
✓ Branch 6 taken 532 times.
✓ Branch 7 taken 188 times.
4249 (primary_comps, secondary_eqs, secondary_vars, primary_aux_eqs) := selectPrimaryParameters(parameter_eqs, parameter_vars,
140 list(eqn_ptr for eqn_ptr guard(isFunctionAliasBinding(eqn_ptr)) in EquationPointers.toList(initialEqs)), EquationPointers.toList(initialEqs));
141 188 equations := EquationPointers.addList(parameter_eqs, equations);
142 188 initialEqs := EquationPointers.removeList(primary_aux_eqs, initialEqs);
143 188 initialEqs := EquationPointers.addList(secondary_eqs, initialEqs);
144
4/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 188 times.
254 initialVars := VariablePointers.removeList(list(BVariable.getVarPointer(Expression.toCref(Util.getOption(Equation.getLHS(Pointer.access(eqn_ptr)))), sourceInfo()) for eqn_ptr in primary_aux_eqs), initialVars);
145 188 initialVars := VariablePointers.addList(secondary_vars, initialVars);
146
3/4
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 178 times.
188 if Flags.isSet(Flags.INITIALIZATION) or Flags.isSet(Flags.DUMP_BINDINGS) then
147 10 print(List.toStringCustom(secondary_eqs, function Equation.pointerToString(str = "\t"),
148 StringUtil.headline_4("Created Secondary Parameter Binding Equations (" + intString(listLength(secondary_eqs)) + "):"), "", "\n", "", false) + "\n\n");
149 10 print(List.toStringCustom(primary_comps, function StrongComponent.toString(index = -1),
150 StringUtil.headline_4("Created Primary Parameter Binding Equations (" + intString(listLength(primary_comps)) + "):"), "", "\n", "", false) + "\n\n");
151 end if;
152
153 // clone all initial variables and remove clocked variables
154 188 clonedVars := VariablePointers.clone(initialVars);
155 188 VariablePointers.mapRemovePtr(clonedVars, BVariable.isClocked);
156
157 188 varData.variables := variables;
158 188 varData.initials := VariablePointers.compress(clonedVars);
159 188 eqData.equations := equations;
160 188 eqData.initials := EquationPointers.compress(initialEqs);
161
162 // add new iterators
163 188 bdae.eqData := eqData;
164 188 bdae.parameters := primary_comps;
165 188 then BackendDAE.setVarData(bdae, VarData.addTypedList(varData, UnorderedSet.toList(new_iters), NBVariable.VarData.VarType.ITERATOR));
166
167 else algorithm
168 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed to create initial partition!"});
169 ✗ then fail();
170 end match;
171
172 // if we filter dump for equations
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
188 if listEmpty(followEquations) then
174 eq_filter_opt := NONE();
175 else
176 ✗ eq_filter_opt := SOME(UnorderedSet.fromList(followEquations, stringHashDjb2, stringEqual));
177 end if;
178
179 // Modules
180 188 modules := {
181 (function BackendDAE.simplify(init = true), "Simplify"),
182 (function Inline.main(inline_types = {DAE.NORM_INLINE(), DAE.BUILTIN_EARLY_INLINE(), DAE.EARLY_INLINE(), DAE.DEFAULT_INLINE()}, init = true), "Inline"),
183 (function Partitioning.main(kind = NBPartition.Kind.INI), "Partitioning"),
184 (cleanup, "Cleanup"),
185 (function Causalize.main(kind = NBPartition.Kind.INI), "Causalize"),
186 (function Tearing.main(kind = NBPartition.Kind.INI), "Tearing")
187 };
188 188 (bdae, clocks) := BackendDAE.applyModules(bdae, modules, eq_filter_opt, ClockIndexes.RT_CLOCK_NEW_BACKEND_INITIALIZATION);
189
190
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
188 if Flags.isSet(Flags.DUMP_BACKEND_CLOCKS) then
191 ✗ if not listEmpty(clocks) then
192 ✗ print(StringUtil.headline_4("Initialization Backend Clocks:"));
193 ✗ print(stringDelimitList(list(Module.moduleClockString(clck) for clck in clocks), "\n") + "\n");
194 end if;
195 end if;
196 else
197 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed to apply modules!"});
198 ✗ fail();
199 end try;
200 end main;
201
202 function createStartEquations
203 "Creates start equations from (fixed) start values."
204 input VariablePointers states;
205 input output VariablePointers variables;
206 input output VariablePointers initialVars;
207 input output EquationPointers equations;
208 input output EquationPointers initialEqs;
209 input Pointer<Integer> idx;
210 input UnorderedSet<ComponentRef> algorithm_outputs;
211 input VariablePointers aliasVars;
212 input String str "only for debugging dump";
213 protected
214 Pointer<list<Pointer<Variable>>> ptr_start_vars = Pointer.create({});
215 Pointer<list<Pointer<Variable>>> ptr_start_vars_init = Pointer.create({});
216 Pointer<list<Pointer<Equation>>> ptr_start_eqs = Pointer.create({});
217 list<Pointer<Equation>> start_eqs;
218 algorithm
219 940 VariablePointers.mapPtr(states, function createStartEquation(ptr_start_vars = ptr_start_vars, ptr_start_vars_init = ptr_start_vars_init, ptr_start_eqs = ptr_start_eqs, idx = idx, algorithm_outputs = algorithm_outputs, aliasVars = aliasVars));
220 940 start_eqs := Pointer.access(ptr_start_eqs);
221
222 940 variables := BVariable.VariablePointers.addList(Pointer.access(ptr_start_vars), variables);
223 940 initialVars := BVariable.VariablePointers.addList(Pointer.access(ptr_start_vars_init), initialVars);
224 940 equations := EquationPointers.addList(start_eqs, equations);
225 940 initialEqs := EquationPointers.addList(start_eqs, initialEqs);
226
227
1/4
✓ Branch 1 taken 940 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
940 if Flags.isSet(Flags.INITIALIZATION) and not listEmpty(start_eqs) then
228 ✗ print(List.toStringCustom(start_eqs, function Equation.pointerToString(str = "\t"),
229 StringUtil.headline_4("Created " + str + " Start Equations (" + intString(listLength(start_eqs)) + "):"), "", "\n", "", false) + "\n\n");
230 end if;
231 end createStartEquations;
232
233 function createStartEquation
234 "creates a start equation for a fixed variable."
235 input Pointer<Variable> var;
236 input Pointer<list<Pointer<Variable>>> ptr_start_vars "new start vars that are just initialized by the init xml";
237 input Pointer<list<Pointer<Variable>>> ptr_start_vars_init "new start vars that are unknowns in the system";
238 input Pointer<list<Pointer<Equation>>> ptr_start_eqs "new start equations";
239 input Pointer<Integer> idx;
240 input UnorderedSet<ComponentRef> algorithm_outputs;
241 input VariablePointers aliasVars;
242 algorithm
243
2/2
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 2565 times.
2617 if not UnorderedSet.contains(BVariable.getVarName(var), algorithm_outputs) then
244 () := match Pointer.access(var)
245 local
246 ComponentRef name, start_name;
247 Pointer<Variable> start_var;
248 Pointer<Equation> start_eq;
249 EquationKind kind;
250 Expression start_exp;
251 Pointer<Boolean> start_ok;
252
253 // if it is an array create for-equation (fixed or unfixed)
254 case Variable.VARIABLE() guard BVariable.isArray(var) algorithm
255 // the start value of a function output is the call at the start values of its arguments
256
4/4
✓ Branch 1 taken 636 times.
✓ Branch 2 taken 42 times.
✓ Branch 4 taken 56 times.
✓ Branch 5 taken 580 times.
678 if not BVariable.isFixed(var) and isFunctionAliasOrElement(var) then
257 56 start_ok := Pointer.create(true);
258 () := match BVariable.getStartAttribute(var)
259 case SOME(start_exp) guard not Expression.isLiteralXML(start_exp) algorithm
260 15 start_exp := resolveStartCrefs(start_exp, ptr_start_vars, aliasVars, start_ok, 0);
261
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 14 times.
15 if Pointer.access(start_ok) then
262 1 Pointer.update(var, BVariable.setStartAttribute(Pointer.access(var), start_exp, true));
263 end if;
264 then ();
265 else ();
266 end match;
267
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 42 times.
56 if not Pointer.access(start_ok) then
268 14 return;
269 end if;
270 end if;
271
2/2
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 622 times.
664 if BVariable.isFixed(var) then
272 42 createStartEquationSlice(Slice.SLICE(var, {}), ptr_start_vars, ptr_start_eqs, idx, BVariable.isFixed(var));
273 else
274 622 createStartEquationSlice(Slice.SLICE(var, {}), ptr_start_vars_init, ptr_start_eqs, idx, BVariable.isFixed(var));
275 end if;
276 then ();
277
278 // create fixed scalar equation
279 case Variable.VARIABLE() guard BVariable.isFixed(var) algorithm
280 38 name := BVariable.getVarName(var);
281 start_exp := match BVariable.getStartAttribute(var)
282 local
283 Expression e;
284 // use the start attribute itself if it is not a literal
285 case SOME(e) guard not Expression.isLiteralXML(e) then e;
286 else algorithm
287 // create a start variable if it is a literal
288 38 (_, name, start_var, start_name) := createStartVar(var, name, {});
289 38 Pointer.update(ptr_start_vars, start_var :: Pointer.access(ptr_start_vars));
290 38 then Expression.fromCref(start_name);
291 end match;
292
293 // make the new start equation
294
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 30 times.
38 kind := if BVariable.isContinuous(var, true) then EquationKind.CONTINUOUS else EquationKind.DISCRETE;
295 38 start_eq := Equation.makeAssignment(Expression.fromCref(name), start_exp, idx, NBEquation.START_STR, Iterator.EMPTY(), EquationAttributes.default(kind, true));
296 76 Pointer.update(ptr_start_eqs, start_eq :: Pointer.access(ptr_start_eqs));
297 then ();
298
299 // create unfixed scalar start equation
300 case Variable.VARIABLE() algorithm
301 () := match BVariable.getStartAttribute(var)
302 local
303 Expression e;
304 // only create if there is a start attribute that is not literal
305 case SOME(e) guard not Expression.isLiteralXML(e) algorithm
306 // the start value of a function output is the call at the start values of its arguments
307 55 start_ok := Pointer.create(true);
308
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 21 times.
55 if isFunctionAliasOrElement(var) then
309 34 e := resolveStartCrefs(e, ptr_start_vars, aliasVars, start_ok, 0);
310 end if;
311
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 23 times.
55 if Pointer.access(start_ok) then
312 32 (_, _, start_var, start_name) := createStartVar(var, BVariable.getVarName(var), {});
313 // make the new start equation
314
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 kind := if BVariable.isContinuous(var, true) then EquationKind.CONTINUOUS else EquationKind.DISCRETE;
315 32 start_eq := Equation.makeAssignment(Expression.fromCref(start_name), e, idx, NBEquation.START_STR, Iterator.EMPTY(), EquationAttributes.default(kind, true));
316 64 Pointer.update(ptr_start_eqs, start_eq :: Pointer.access(ptr_start_eqs));
317 // add the new variable to initial unknowns
318 32 Pointer.update(ptr_start_vars_init, start_var :: Pointer.access(ptr_start_vars_init));
319 end if;
320 then ();
321
322 else ();
323 end match;
324 then ();
325
326 else ();
327 end match;
328 end if;
329 end createStartEquation;
330
331 function createWhenReplacementEquations
332 "Creates start equations from fixed start values."
333 input UnorderedMap<ComponentRef, Iterator> cref_map;
334 input output EquationPointers equations;
335 input output EquationPointers initialEqs;
336 input Pointer<Integer> idx;
337 protected
338 Pointer<list<Pointer<Equation>>> ptr_start_eqs = Pointer.create({});
339 list<Pointer<Equation>> start_eqs;
340 algorithm
341
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 188 times.
234 for tpl in UnorderedMap.toList(cref_map) loop
342 46 createWhenReplacementEquation(tpl, ptr_start_eqs, idx);
343 end for;
344 188 start_eqs := Pointer.access(ptr_start_eqs);
345
346 188 equations := EquationPointers.addList(start_eqs, equations);
347 188 initialEqs := EquationPointers.addList(start_eqs, initialEqs);
348
349
1/4
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
188 if Flags.isSet(Flags.INITIALIZATION) and not listEmpty(start_eqs) then
350 ✗ print(List.toStringCustom(start_eqs, function Equation.pointerToString(str = "\t"),
351 StringUtil.headline_4("Created When Replacement Equations (" + intString(listLength(start_eqs)) + "):"), "", "\n", "", false) + "\n\n");
352 end if;
353 end createWhenReplacementEquations;
354
355 function createWhenReplacementEquation
356 "creates a start equation for a fixed state or discrete state."
357 input tuple<ComponentRef, Iterator> tpl;
358 input Pointer<list<Pointer<Equation>>> ptr_start_eqs;
359 input Pointer<Integer> idx;
360 protected
361 ComponentRef cref;
362 Iterator iter;
363 Pointer<Variable> var_ptr;
364 Option<Pointer<Variable>> var_pre;
365 ComponentRef pre;
366 EquationKind kind;
367 Pointer<Equation> eq;
368 algorithm
369 46 (cref, iter) := tpl;
370 46 var_ptr := BVariable.getVarPointer(cref, sourceInfo());
371 46 var_pre := BVariable.getVarPre(var_ptr);
372
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
46 if isSome(var_pre) then
373 46 pre := BVariable.getVarName(Util.getOption(var_pre));
374 46 pre := ComponentRef.copySubscripts(cref, pre);
375
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 kind := if BVariable.isContinuous(var_ptr, true) then EquationKind.CONTINUOUS else EquationKind.DISCRETE;
376 46 eq := Equation.makeAssignment(Expression.fromCref(cref, true), Expression.fromCref(pre, true), idx, NBEquation.START_STR, iter, EquationAttributes.default(kind, true));
377 92 Pointer.update(ptr_start_eqs, eq :: Pointer.access(ptr_start_eqs));
378 else
379 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " could not replace when-replacement for "
380 + ComponentRef.toString(cref) + " because it has no pre-variable."});
381 ✗ fail();
382 end if;
383 end createWhenReplacementEquation;
384
385 function createStartVar
386 "creates start variable and cref.
387 for discrete states the variable itself is changed to its
388 pre variable because they have to be initialized instead!.
389 normal: var = $START.var
390 disc state and pre: $PRE.dst = $START.dst"
391 input output Pointer<Variable> var_ptr;
392 input output ComponentRef name;
393 input list<Subscript> subscripts;
394 output Pointer<Variable> start_var;
395 output ComponentRef start_name;
396 protected
397 Option<Pointer<Variable>> var_pre = BVariable.getVarPre(var_ptr);
398 ComponentRef merged_name;
399 algorithm
400
4/6
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 173 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
203 if BVariable.isPrevious(var_ptr) and isSome(var_pre) then
401 // for previous change the rhs to the start value of the discrete state
402 30 merged_name := BVariable.getVarName(Util.getOption(var_pre));
403 30 merged_name := ComponentRef.mergeSubscripts(subscripts, merged_name, true, true, true);
404 elseif isSome(var_pre) then
405 // for vars with previous change the lhs cref to the $PRE cref
406 16 merged_name := ComponentRef.mergeSubscripts(subscripts, name, true, true, true);
407 16 var_ptr := Util.getOption(var_pre);
408 16 name := BVariable.getVarName(var_ptr);
409 16 name := ComponentRef.mergeSubscripts(subscripts, name, true, true, true);
410 else
411 // just apply subscripts and make start var
412 157 name := ComponentRef.mergeSubscripts(subscripts, name, true, true, true);
413 merged_name := name;
414 end if;
415 203 (start_name, start_var) := BVariable.makeStartVar(merged_name);
416
417 // set the record parent if neccessary
418 start_var := match BVariable.getParent(var_ptr)
419 local
420 Pointer<Variable> parent, start_parent;
421 case SOME(parent) algorithm
422 start_parent := match BVariable.getVarStart(parent)
423 case SOME(start_parent) then start_parent;
424 else algorithm
425 6 (_, _, start_parent, _) := createStartVar(parent, BVariable.getVarName(parent), {});
426 6 then start_parent;
427 end match;
428 // create the parent <-> child link
429 12 BVariable.addRecordChild(start_parent, start_var);
430 12 start_var := BVariable.setParent(start_var, start_parent);
431 then start_var;
432 191 else start_var;
433 end match;
434 end createStartVar;
435
436 function createParameterEquations
437 "creates the binding equations of the parameters and their initial unknowns"
438 input VariablePointers parameters;
439 input UnorderedSet<VariablePointer> new_iters;
440 input Pointer<Integer> idx;
441 input output list<Pointer<Equation>> parameter_eqs;
442 input output list<Pointer<Variable>> initial_param_vars;
443 algorithm
444
2/2
✓ Branch 1 taken 3629 times.
✓ Branch 2 taken 752 times.
4381 for var in VariablePointers.toList(parameters) loop
445 3629 (parameter_eqs, initial_param_vars) := createParameterEquation(var, new_iters, idx, parameter_eqs, initial_param_vars);
446 end for;
447 end createParameterEquations;
448
449 function selectPrimaryParameters
450 "Like the old backend (Initialization.selectInitializationVariablesDAE): a parameter is secondary if it is not
451 fixed or depends on a secondary parameter, all others are primary. The bindings of the primary parameters are
452 sorted by their dependencies and solved explicitly before the initialization. Only bindings of the form
453 p = exp are considered, all other ones (for equations, records, external objects) stay in the initialization."
454 input list<Pointer<Equation>> parameter_eqs;
455 input list<Pointer<Variable>> initial_param_vars;
456 input list<Pointer<Equation>> aux_eqs "bindings of function alias variables";
457 input list<Pointer<Equation>> initial_eqs "all equations of the initialization, what they define is not known";
458 output list<StrongComponent> primary_comps = {};
459 output list<Pointer<Equation>> secondary_eqs = {};
460 output list<Pointer<Variable>> secondary_vars = {};
461 output list<Pointer<Equation>> primary_aux_eqs = {};
462 protected
463 UnorderedSet<ComponentRef> primary = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual) "solved parameters";
464 UnorderedSet<ComponentRef> unresolved = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual) "parameters with a binding equation";
465 UnorderedSet<ComponentRef> duplicates = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual) "variables that are defined by several equations";
466 list<Pointer<Equation>> remaining = {}, next, sorted = {};
467 Option<ComponentRef> name_opt;
468 ComponentRef name;
469 Boolean progress = true, ready;
470 algorithm
471
2/2
✓ Branch 1 taken 1668 times.
✓ Branch 2 taken 188 times.
1856 for eqn_ptr in listAppend(parameter_eqs, aux_eqs) loop
472 1668 name_opt := explicitBindingName(eqn_ptr);
473 () := match name_opt
474 case SOME(name) algorithm
475 // a variable that is defined by several equations can not be solved explicitly
476
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1347 times.
1347 if UnorderedSet.contains(name, unresolved) then
477 ✗ UnorderedSet.add(name, duplicates);
478 end if;
479 1347 UnorderedSet.add(name, unresolved);
480 remaining := eqn_ptr :: remaining;
481 then ();
482 // the target of any other equation can not be solved explicitly here
483 else algorithm
484 () := match Equation.getLHS(Pointer.access(eqn_ptr))
485 case SOME(Expression.CREF(cref = name)) algorithm
486 321 UnorderedSet.add(ComponentRef.stripSubscriptsAll(name), unresolved);
487 then ();
488 else ();
489 end match;
490 then ();
491 end match;
492 end for;
493
5/6
✗ Branch 2 not taken.
✓ Branch 3 taken 1347 times.
✓ Branch 4 taken 1347 times.
✓ Branch 5 taken 188 times.
✓ Branch 6 taken 1347 times.
✓ Branch 7 taken 188 times.
1535 remaining := list(eqn_ptr for eqn_ptr guard(not isDuplicateBinding(eqn_ptr, duplicates)) in listReverse(remaining));
494
495 // everything that is defined by an equation of the initialization is unknown until it is solved as a primary parameter
496
2/2
✓ Branch 1 taken 4061 times.
✓ Branch 2 taken 188 times.
4249 for eqn_ptr in initial_eqs loop
497 () := match Equation.getLHS(Pointer.access(eqn_ptr))
498 case SOME(Expression.CREF(cref = name)) algorithm
499 3337 UnorderedSet.add(ComponentRef.stripSubscriptsAll(name), unresolved);
500 then ();
501 else ();
502 end match;
503 end for;
504
505 // repeatedly take all bindings that only depend on primary parameters
506
4/4
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 118 times.
✓ Branch 3 taken 127 times.
306 while progress and not listEmpty(remaining) loop
507 progress := false;
508 next := {};
509
2/2
✓ Branch 0 taken 2627 times.
✓ Branch 1 taken 118 times.
2745 for eqn_ptr in remaining loop
510
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2627 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2627 times.
2627 SOME(name) := explicitBindingName(eqn_ptr);
511 ready := true;
512
2/2
✓ Branch 5 taken 2951 times.
✓ Branch 6 taken 1112 times.
4063 for dep in UnorderedSet.toList(Expression.extractCrefs(Util.getOption(Equation.getRHS(Pointer.access(eqn_ptr))))) loop
513
2/2
✓ Branch 1 taken 1436 times.
✓ Branch 2 taken 1515 times.
2951 if not isPrimaryCref(dep, primary, unresolved) then
514 ready := false;
515 break;
516 end if;
517 end for;
518
2/2
✓ Branch 0 taken 1112 times.
✓ Branch 1 taken 1515 times.
2627 if ready then
519 1112 UnorderedSet.add(name, primary);
520 sorted := eqn_ptr :: sorted;
521 progress := true;
522 else
523 next := eqn_ptr :: next;
524 end if;
525 end for;
526 118 remaining := listReverse(next);
527 end while;
528 188 sorted := listReverse(sorted);
529
530
4/4
✓ Branch 0 taken 1112 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 1112 times.
✓ Branch 3 taken 188 times.
1300 primary_comps := list(StrongComponent.fromSolvedEquationSlice(Slice.SLICE(eqn_ptr, {})) for eqn_ptr in sorted);
531
6/6
✓ Branch 1 taken 1046 times.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 1136 times.
✓ Branch 4 taken 188 times.
✓ Branch 5 taken 90 times.
✓ Branch 6 taken 188 times.
1324 secondary_eqs := list(eqn_ptr for eqn_ptr guard(not isPrimaryBinding(eqn_ptr, primary)) in parameter_eqs);
532
6/6
✓ Branch 3 taken 1119 times.
✓ Branch 4 taken 338 times.
✓ Branch 5 taken 1457 times.
✓ Branch 6 taken 188 times.
✓ Branch 7 taken 338 times.
✓ Branch 8 taken 188 times.
1645 secondary_vars := list(var for var guard(not isSolved(ComponentRef.stripSubscriptsAll(BVariable.getVarName(var)), primary)) in initial_param_vars);
533
7/8
✓ Branch 1 taken 466 times.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 532 times.
✓ Branch 4 taken 188 times.
✓ Branch 5 taken 66 times.
✓ Branch 6 taken 188 times.
✓ Branch 7 taken 188 times.
✗ Branch 8 not taken.
720 primary_aux_eqs := list(eqn_ptr for eqn_ptr guard(isPrimaryBinding(eqn_ptr, primary)) in aux_eqs);
534 end selectPrimaryParameters;
535
536 function isFunctionAliasBinding
537 "a binding aux = exp of a function alias variable"
538 input Pointer<Equation> eqn_ptr;
539 output Boolean b;
540 algorithm
541 b := match Pointer.access(eqn_ptr)
542 local
543 ComponentRef cref;
544 2711 case Equation.SCALAR_EQUATION(lhs = Expression.CREF(cref = cref)) then isFunctionAliasCref(cref);
545 390 case Equation.ARRAY_EQUATION(lhs = Expression.CREF(cref = cref), recordSize = NONE()) then isFunctionAliasCref(cref);
546 else false;
547 end match;
548 end isFunctionAliasBinding;
549
550 function isFunctionAliasCref
551 input ComponentRef cref;
552 output Boolean b;
553 algorithm
554 b := match cref
555 case ComponentRef.CREF() guard InstNode.isVar(ComponentRef.node(cref))
556 3101 then BVariable.isFunctionAlias(BVariable.getVarPointer(cref, sourceInfo()));
557 else false;
558 end match;
559 end isFunctionAliasCref;
560
561 function explicitBindingName
562 "the (unsubscripted) parameter of a binding equation p = exp"
563 input Pointer<Equation> eqn_ptr;
564 output Option<ComponentRef> name;
565 algorithm
566 name := match Pointer.access(eqn_ptr)
567 local
568 ComponentRef cref;
569 Type ty;
570 // only a binding for a whole variable, not for a part of it or of an element of an array of components
571 case Equation.SCALAR_EQUATION(lhs = Expression.CREF(cref = cref)) guard(not hasSubscripts(cref))
572 then SOME(cref);
573 // an array of records is inlined in the initialization, it can not be assigned as a whole
574 case Equation.ARRAY_EQUATION(ty = ty, lhs = Expression.CREF(cref = cref), recordSize = NONE())
575 guard(not hasSubscripts(cref) and not Type.isComplex(Type.arrayElementType(ty)))
576 then SOME(cref);
577 // a record bound as a whole
578 case Equation.RECORD_EQUATION(lhs = Expression.CREF(cref = cref)) guard(not hasSubscripts(cref))
579 then SOME(cref);
580 // a for equation that binds every element of a variable once: x[i, j] = exp
581 case Equation.FOR_EQUATION(body = {Equation.SCALAR_EQUATION(lhs = Expression.CREF(cref = cref))})
582 guard(coversVariable(cref, Pointer.access(eqn_ptr)))
583 182 then SOME(ComponentRef.stripSubscriptsAll(cref));
584 else NONE();
585 end match;
586 end explicitBindingName;
587
588 function coversVariable
589 "the subscripts of the cref are distinct iterators and the equation has as many elements as the variable"
590 input ComponentRef cref;
591 input Equation eqn;
592 output Boolean b;
593 protected
594 list<Subscript> subs = ComponentRef.subscriptsAllFlat(cref);
595 UnorderedSet<ComponentRef> iters = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual);
596 ComponentRef iter;
597 Pointer<Variable> var_ptr;
598 algorithm
599 // a for equation binding a field of a record (e.g. an array of records) is inlined
600 // in the initialization like a whole record, it can not be assigned as a whole
601 182 var_ptr := BVariable.getVarPointer(ComponentRef.stripSubscriptsAll(cref), sourceInfo());
602
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
✓ Branch 5 taken 182 times.
✗ Branch 6 not taken.
182 if isSome(BVariable.getParent(var_ptr)) then
603 b := false;
604 ✗ return;
605 end if;
606 182 b := not listEmpty(subs);
607
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 182 times.
398 for sub in subs loop
608
1/2
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
216 if not Subscript.isIterator(sub) then
609 b := false;
610 break;
611 end if;
612 216 iter := Expression.toCref(Subscript.toExp(sub));
613
1/2
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
216 if UnorderedSet.contains(iter, iters) then
614 b := false;
615 break;
616 end if;
617 216 UnorderedSet.add(iter, iters);
618 end for;
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182 times.
182 if b then
620 182 b := Equation.size(Pointer.create(eqn)) == BVariable.size(BVariable.getVarPointer(ComponentRef.stripSubscriptsAll(cref), sourceInfo()));
621 end if;
622 end coversVariable;
623
624 function hasSubscripts
625 input ComponentRef cref;
626 output Boolean b = not ComponentRef.isEqual(cref, ComponentRef.stripSubscriptsAll(cref));
627 end hasSubscripts;
628
629 function isDuplicateBinding
630 input Pointer<Equation> eqn_ptr;
631 input UnorderedSet<ComponentRef> duplicates;
632 output Boolean b;
633 algorithm
634 b := match explicitBindingName(eqn_ptr)
635 local
636 ComponentRef name;
637 1347 case SOME(name) then UnorderedSet.contains(name, duplicates);
638 else false;
639 end match;
640 end isDuplicateBinding;
641
642 function isPrimaryBinding
643 input Pointer<Equation> eqn_ptr;
644 input UnorderedSet<ComponentRef> primary;
645 output Boolean b;
646 algorithm
647 b := match explicitBindingName(eqn_ptr)
648 local
649 ComponentRef name;
650 1347 case SOME(name) then UnorderedSet.contains(name, primary);
651 else false;
652 end match;
653 end isPrimaryBinding;
654
655 function isSolved
656 "the cref or one of its parents (e.g. a record) is solved as a primary parameter"
657 input ComponentRef cref;
658 input UnorderedSet<ComponentRef> primary;
659 output Boolean b = false;
660 protected
661 ComponentRef parent = cref;
662 algorithm
663
2/2
✓ Branch 1 taken 6904 times.
✓ Branch 2 taken 2608 times.
9512 while not ComponentRef.isEmpty(parent) loop
664
2/2
✓ Branch 1 taken 5185 times.
✓ Branch 2 taken 1719 times.
6904 if UnorderedSet.contains(parent, primary) then
665 b := true;
666 break;
667 end if;
668 5185 parent := ComponentRef.rest(parent);
669 end while;
670 end isSolved;
671
672 function isPrimaryCref
673 "true if the value of the cref is known before the initialization"
674 input ComponentRef cref;
675 input UnorderedSet<ComponentRef> primary;
676 input UnorderedSet<ComponentRef> unresolved;
677 output Boolean b;
678 protected
679 ComponentRef name = ComponentRef.stripSubscriptsAll(cref);
680 ComponentRef parent = name;
681 Pointer<Variable> var_ptr;
682 algorithm
683
4/4
✓ Branch 1 taken 2870 times.
✓ Branch 2 taken 81 times.
✓ Branch 4 taken 2270 times.
✓ Branch 5 taken 600 times.
2951 if ComponentRef.isIterator(cref) or isSolved(name, primary) then
684 b := true;
685 else
686 // a parameter (or one of its parents) that has a binding equation which is not solved explicitly
687 b := true;
688
2/2
✓ Branch 1 taken 3448 times.
✓ Branch 2 taken 1080 times.
4528 while not ComponentRef.isEmpty(parent) loop
689
2/2
✓ Branch 1 taken 2258 times.
✓ Branch 2 taken 1190 times.
3448 if UnorderedSet.contains(parent, unresolved) then
690 b := false;
691 break;
692 end if;
693 2258 parent := ComponentRef.rest(parent);
694 end while;
695
696 // otherwise it has to be a fixed parameter or a constant (e.g. with an evaluable binding)
697
2/2
✓ Branch 0 taken 1080 times.
✓ Branch 1 taken 1190 times.
2270 if b then
698 b := match cref
699 case ComponentRef.CREF() guard InstNode.isVar(ComponentRef.node(cref)) algorithm
700 1080 var_ptr := BVariable.getVarPointer(cref, sourceInfo());
701
5/6
✓ Branch 1 taken 1080 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 758 times.
✓ Branch 5 taken 322 times.
✓ Branch 7 taken 755 times.
✓ Branch 8 taken 3 times.
1080 then BVariable.isConst(var_ptr) or (BVariable.isParamOrConst(var_ptr) and BVariable.isFixed(var_ptr));
702 else false;
703 end match;
704 end if;
705 end if;
706 end isPrimaryCref;
707
708 function createParameterEquation
709 input Pointer<Variable> var;
710 input UnorderedSet<VariablePointer> new_iters;
711 input Pointer<Integer> idx;
712 input output list<Pointer<Equation>> parameter_eqs;
713 input output list<Pointer<Variable>> initial_param_vars;
714 protected
715 Pointer<Variable> parent, c_var;
716 PointerWeak<Variable> c_cell;
717 Boolean skip;
718 algorithm
719
1/2
✓ Branch 1 taken 3630 times.
✗ Branch 2 not taken.
3630 if BVariable.isConst(var) then
720 // skip this variable if it is constant
721 skip := true;
722 else
723 // check if the variable is a record element with bound parent or a record without binding
724 // if the parent is not fully unknown also create individual bindings
725 skip := match BVariable.getParent(var)
726
3/4
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 72 times.
79 case SOME(parent) then BVariable.isBound(parent) and BVariable.isKnownRecord(parent);
727
4/4
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 3354 times.
✓ Branch 4 taken 106 times.
✓ Branch 5 taken 91 times.
3551 else (BVariable.isRecord(var) and not BVariable.isBound(var));
728 end match;
729 end if;
730
731 // do nothing if skipped
732 163 if skip then return; end if;
733
734 // parse known records
735
2/2
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 3393 times.
3467 if BVariable.isKnownRecord(var) then
736 // only consider non-evaluable parameter bindings
737 // if the record is bound or has a start value, create an equation from it, otherwise create from its children
738
3/6
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 57 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
74 if not BVariable.hasEvaluableBinding(var) and (BVariable.isBound(var) or BVariable.hasStartAttr(var)) then
739 57 initial_param_vars := listAppend(BVariable.getRecordChildren(var), initial_param_vars);
740 114 parameter_eqs := Equation.generateBindingEquation(var, idx, true, new_iters) :: parameter_eqs;
741 else
742
2/2
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 17 times.
54 for c_cell in BVariable.getRecordChildrenCells(var) loop
743 37 c_var := PointerWeak.upgrade(c_cell);
744
1/2
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
37 if BVariable.isBound(c_var) then
745 37 BVariable.setBindingAsStart(c_var, true);
746 end if;
747 // Only recurse for record children; scalar children are already handled by the parameters pass
748
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 36 times.
37 if BVariable.isRecord(c_var) then
749 1 (parameter_eqs, initial_param_vars) := createParameterEquation(c_var, new_iters, idx, parameter_eqs, initial_param_vars);
750 end if;
751 end for;
752 end if;
753
754 // all other variables that are not records
755 elseif not BVariable.isRecord(var) then
756 // only consider non-evaluable parameter bindings
757
2/2
✓ Branch 1 taken 1327 times.
✓ Branch 2 taken 2033 times.
3360 if not BVariable.hasEvaluableBinding(var) then
758 // add variable to initial unknowns
759 1327 initial_param_vars := var :: initial_param_vars;
760
2/2
✓ Branch 1 taken 1079 times.
✓ Branch 2 taken 248 times.
1327 if BVariable.isFixed(var) then
761 1079 parameter_eqs := Equation.generateBindingEquation(var, idx, true, new_iters) :: parameter_eqs;
762 end if;
763 elseif BVariable.isBound(var) then
764 2033 BVariable.setBindingAsStart(var, true);
765 end if;
766 end if;
767 end createParameterEquation;
768
769 function isAliasVar
770 input Pointer<Variable> var_ptr;
771 input VariablePointers aliasVars;
772 output Boolean b = VariablePointers.containsCref(BVariable.getVarName(var_ptr), aliasVars);
773 end isAliasVar;
774
775 function isFunctionAliasOrElement
776 "true for function alias variables and the elements of function alias records"
777 input Pointer<Variable> var_ptr;
778 output Boolean b;
779 algorithm
780 b := match BVariable.getParent(var_ptr)
781 local
782 Pointer<Variable> parent;
783 105 case SOME(parent) then isFunctionAliasOrElement(parent);
784 691 else BVariable.isFunctionAlias(var_ptr);
785 end match;
786 end isFunctionAliasOrElement;
787
788 function resolveStartCrefs
789 "Replaces the variables in a start expression by their start values, e.g. the start value of a function output
790 is the function call at the start values of its arguments. Since start values can be changed after the
791 compilation, the start variables ($START.x) are used and not the values.
792 Sets ok to false if the expression can not be resolved."
793 input Expression exp;
794 input Pointer<list<Pointer<Variable>>> ptr_start_vars;
795 input VariablePointers aliasVars;
796 input Pointer<Boolean> ok;
797 input Integer depth;
798 output Expression res;
799 algorithm
800 53 res := Expression.map(exp, function resolveStartCref(ptr_start_vars = ptr_start_vars, aliasVars = aliasVars, ok = ok, depth = depth));
801 end resolveStartCrefs;
802
803 function resolveStartCref
804 input Expression exp;
805 output Expression res = exp;
806 input Pointer<list<Pointer<Variable>>> ptr_start_vars;
807 input VariablePointers aliasVars;
808 input Pointer<Boolean> ok;
809 input Integer depth;
810 protected
811 Pointer<Variable> var_ptr;
812 Variable var;
813 ComponentRef start_name;
814 Pointer<Variable> start_var;
815 Boolean existed;
816 Option<Expression> start_opt;
817 algorithm
818 res := match exp
819 // internal helper functions (e.g. of stream connectors) have no code outside of equations
820 case Expression.CALL() guard(StringUtil.startsWith(AbsynUtil.pathFirstIdent(Call.functionName(exp.call)), "$OMC$")) algorithm
821 ✗ Pointer.update(ok, false);
822 then res;
823
824 case Expression.CREF(cref = ComponentRef.CREF()) guard(not ComponentRef.isTime(exp.cref)) algorithm
825 116 var_ptr := BVariable.getVarPointer(exp.cref, sourceInfo());
826 116 var := Pointer.access(var_ptr);
827
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 116 times.
116 if ComponentRef.isEmpty(var.name) then
828 // not a variable of the system
829 ✗ Pointer.update(ok, false);
830 elseif VariablePointers.containsCref(ComponentRef.stripSubscriptsAll(exp.cref), aliasVars) then
831 // aliases are removed, use their defining expression (e.g. x = time)
832
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
4 if depth < 10 and Binding.isBound(var.binding) then
833 // an element of an array alias is the same element of its defining expression
834 4 res := Binding.getExp(var.binding);
835
3/4
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
4 if ComponentRef.hasSubscripts(exp.cref) and Type.isArray(Expression.typeOf(res)) then
836 3 res := Expression.applySubscripts(ComponentRef.subscriptsAllWithWholeFlat(exp.cref), res, true);
837 end if;
838 4 res := resolveStartCrefs(res, ptr_start_vars, aliasVars, ok, depth + 1);
839 else
840 ✗ Pointer.update(ok, false);
841 end if;
842 elseif List.any(BVariable.getRecordChildren(var_ptr), function isAliasVar(aliasVars = aliasVars)) then
843 // alias records are marked as parameters after alias removal, but their elements are aliases
844 7 Pointer.update(ok, false);
845 elseif BVariable.isParamOrConst(var_ptr) or BVariable.isStart(var_ptr)
846 or BVariable.isIterator(var_ptr) or BVariable.isExtObj(var_ptr) then
847 // already known
848 elseif BVariable.isRecord(var_ptr) or isSome(BVariable.getParent(var_ptr)) then
849 // records (and their elements) can be removed as aliases from the system, referencing
850 // them would bring back their record equations and unbalance the initialization
851 29 Pointer.update(ok, false);
852 elseif Type.isReal(Type.arrayElementType(Variable.typeOf(var))) and not Type.isArray(Expression.typeOf(exp)) and BVariable.isContinuous(var_ptr, true) then
853 14 start_opt := BVariable.getStartAttribute(var_ptr);
854
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 5 times.
14 existed := isSome(BVariable.getVarStart(var_ptr));
855
5/8
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
14 if BVariable.isFixed(var_ptr) and isSome(start_opt) and not Expression.isLiteralXML(Util.getOption(start_opt)) then
856 // fixed variables use their start expression directly, an element uses the same element of it
857 ✗ if depth < 10 then
858 ✗ res := Util.getOption(start_opt);
859 ✗ if ComponentRef.hasSubscripts(exp.cref) and Type.isArray(Expression.typeOf(res)) then
860 ✗ res := Expression.applySubscripts(ComponentRef.subscriptsAllWithWholeFlat(exp.cref), res, true);
861 end if;
862 ✗ res := resolveStartCrefs(res, ptr_start_vars, aliasVars, ok, depth + 1);
863 else
864 ✗ Pointer.update(ok, false);
865 end if;
866 elseif isNone(start_opt) and not existed then
867 // no start value, the call would be evaluated at a meaningless zero
868 4 Pointer.update(ok, false);
869 else
870 10 (start_name, start_var) := BVariable.makeStartVar(exp.cref);
871 10 res := Expression.fromCref(start_name);
872 // literal start values of unfixed variables have to be initialized by the init xml
873
6/12
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 10 not taken.
✓ Branch 13 taken 1 time.
✗ Branch 14 not taken.
10 if not existed and not BVariable.isFixed(var_ptr) and (isNone(start_opt) or Expression.isLiteralXML(Util.getOption(start_opt))) then
874 1 Pointer.update(ptr_start_vars, start_var :: Pointer.access(ptr_start_vars));
875 end if;
876 end if;
877 else
878 19 Pointer.update(ok, false);
879 end if;
880 then res;
881
882 else exp;
883 end match;
884 end resolveStartCref;
885
886 function createStartEquationSlice
887 "creates a start equation for a sliced variable.
888 usually results in a for equation, but might be scalarized if that is not possible."
889 input Slice<VariablePointer> var_slice;
890 input Pointer<list<Pointer<Variable>>> ptr_start_vars "either the new start vars initialized by init xml or intial unkowns depending on fixed=true or false";
891 input Pointer<list<Pointer<Equation>>> ptr_start_eqs "new start equations";
892 input Pointer<Integer> idx;
893 input Boolean fixed;
894 protected
895 Expression start_exp, start_var_exp, e;
896 Pointer<Variable> var_ptr, start_var;
897 ComponentRef name;
898 Option<Pointer<Equation>> start_eq = NONE();
899 EquationKind kind;
900 Iterator iterator;
901 list<Pointer<Equation>> sliced_eqn;
902 algorithm
903 718 var_ptr := Slice.getT(var_slice);
904 718 name := BVariable.getVarName(var_ptr);
905
2/2
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 637 times.
718 kind := if BVariable.isContinuous(var_ptr, true) then EquationKind.CONTINUOUS else EquationKind.DISCRETE;
906
907
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 622 times.
718 if fixed then
908 start_exp := match BVariable.getStartAttribute(var_ptr)
909 // create from start expression if its not a literal
910 case SOME(e) guard not Expression.isLiteralXML(e) algorithm
911 1 (start_exp, var_ptr, name, _, _, iterator) := createStartExpressionSlice(e, var_slice, var_ptr, name);
912 then start_exp;
913
914 // create a start variable if it is a literal
915 else algorithm
916 95 (start_var_exp, var_ptr, name, iterator) := createStartVariableSlice(var_slice, var_ptr, name, ptr_start_vars);
917 then start_var_exp;
918 end match;
919
920 // make the new start equation
921 96 start_eq := SOME(Equation.makeAssignment(Expression.fromCref(name, true), start_exp, idx, NBEquation.START_STR, iterator, EquationAttributes.default(kind, true)));
922 else
923 start_eq := match BVariable.getStartAttribute(var_ptr)
924 // create from start expression only if its not literal
925 case SOME(e) guard not Expression.isLiteralXML(e) algorithm
926 31 (start_exp, var_ptr, _, start_var, name, iterator) := createStartExpressionSlice(e, var_slice, var_ptr, name);
927 31 start_eq := SOME(Equation.makeAssignment(Expression.fromCref(name, true), start_exp, idx, NBEquation.START_STR, iterator, EquationAttributes.default(kind, true)));
928 31 Pointer.update(ptr_start_vars, start_var :: Pointer.access(ptr_start_vars));
929 then start_eq;
930
931 // exit the function, no start equation is created
932 else NONE();
933 end match;
934 end if;
935
936
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 718 times.
✓ Branch 2 taken 127 times.
✓ Branch 3 taken 591 times.
718 if isSome(start_eq) then
937 // empty list indicates full array, slice otherwise
938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
127 if not listEmpty(var_slice.indices) then
939 ✗ (sliced_eqn, _) := Equation.slice(Util.getOption(start_eq), var_slice.indices);
940 ✗ Pointer.update(ptr_start_eqs, listAppend(Pointer.access(ptr_start_eqs), sliced_eqn));
941 else
942 254 Pointer.update(ptr_start_eqs, Util.getOption(start_eq) :: Pointer.access(ptr_start_eqs));
943 end if;
944 end if;
945 end createStartEquationSlice;
946
947 function createStartExpressionSlice
948 input Expression exp;
949 input Slice<VariablePointer> var_slice;
950 output Expression start_exp;
951 input output Pointer<Variable> var_ptr;
952 input output ComponentRef name;
953 output Pointer<Variable> start_var;
954 output ComponentRef start_cref;
955 output Iterator iterator;
956 algorithm
957 (start_exp, iterator) := match exp
958 local
959 Call array_constructor;
960 list<tuple<ComponentRef, Expression, Option<Iterator>>> frames;
961 UnorderedMap<ComponentRef, Expression> replacements;
962 InstNode old_iter;
963 ComponentRef new_iter;
964 list<Subscript> subscripts;
965
966 // convert array constructor to for-equation
967 case Expression.CALL(call = array_constructor as Call.TYPED_ARRAY_CONSTRUCTOR()) algorithm
968 5 (var_ptr, name, start_var, start_cref, _, frames, iterator) := createIteratedStartCref(var_ptr, name, listLength(array_constructor.iters));
969 5 replacements := UnorderedMap.new<Expression>(ComponentRef.hash, ComponentRef.isEqual);
970
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
10 for tpl in List.zip(array_constructor.iters, frames) loop
971 5 ((old_iter, _), (new_iter, _, _)) := tpl;
972 5 UnorderedMap.add(ComponentRef.fromNode(old_iter, InstNode.getType(old_iter)), Expression.fromCref(new_iter), replacements);
973 end for;
974 5 then (Expression.map(array_constructor.exp, function Replacements.applySimpleExp(replacements = replacements)), iterator);
975
976 // use the start attribute itself
977 else algorithm
978
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 if Slice.isFull(var_slice) then
979 27 (var_ptr, name, start_var, start_cref) := createStartVar(var_ptr, name, {});
980 27 iterator := Iterator.EMPTY();
981 start_exp := exp;
982 else
983 ✗ (var_ptr, name, start_var, start_cref, subscripts, _, iterator) := createIteratedStartCref(var_ptr, name, 0);
984 ✗ start_exp := Expression.applySubscripts(subscripts, exp, true);
985 end if;
986 27 then (start_exp, iterator);
987 end match;
988 end createStartExpressionSlice;
989
990 function createStartVariableSlice
991 input Slice<VariablePointer> var_slice;
992 output Expression start_exp;
993 input output Pointer<Variable> var_ptr;
994 input output ComponentRef name;
995 input Pointer<list<Pointer<Variable>>> ptr_start_vars;
996 output Iterator iterator;
997 protected
998 Pointer<Variable> start_var;
999 ComponentRef start_name;
1000 list<Subscript> subscripts;
1001 algorithm
1002
1/2
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
95 if Slice.isFull(var_slice) then
1003 95 (var_ptr, name, start_var, start_name) := createStartVar(var_ptr, name, {});
1004 95 iterator := Iterator.EMPTY();
1005 else
1006 ✗ (var_ptr, name, start_var, start_name, subscripts, _, iterator) := createIteratedStartCref(var_ptr, name, 0);
1007 end if;
1008 95 Pointer.update(ptr_start_vars, start_var :: Pointer.access(ptr_start_vars));
1009 95 start_exp := Expression.fromCref(start_name);
1010 end createStartVariableSlice;
1011
1012 protected function createIteratedStartCref
1013 input output Pointer<Variable> var_ptr;
1014 input output ComponentRef name;
1015 input Integer num_dim;
1016 output Pointer<Variable> start_var;
1017 output ComponentRef start_cref;
1018 output list<Subscript> subscripts;
1019 output list<tuple<ComponentRef, Expression, Option<Iterator>>> frames;
1020 output Iterator iterator;
1021 protected
1022 list<Dimension> dims;
1023 list<InstNode> iterators;
1024 list<Expression> ranges;
1025 list<ComponentRef> iter_crefs;
1026 algorithm
1027 // make unique iterators for the new for-loop
1028 5 dims := Type.arrayDims(ComponentRef.getSubscriptedType(name));
1029
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 dims := if num_dim == 0 then dims else List.firstN(dims, num_dim);
1030 5 (iterators, ranges, subscripts) := Flatten.makeIterators(name, dims);
1031
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
10 iter_crefs := list(ComponentRef.makeIterator(iter, Type.INTEGER()) for iter in iterators);
1032
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
10 iter_crefs := list(BackendDAE.lowerIteratorCref(iter) for iter in iter_crefs);
1033
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
10 subscripts := list(Subscript.mapExp(sub, BackendDAE.lowerIteratorExp) for sub in subscripts);
1034 5 frames := List.zip3(iter_crefs, ranges, List.fill(NONE(), listLength(iter_crefs)));
1035 5 iterator := Iterator.fromFrames(frames);
1036
1037 // create start variable name with subscripts and create start expression
1038 5 (var_ptr, name, start_var, start_cref) := createStartVar(var_ptr, name, subscripts);
1039 end createIteratedStartCref;
1040
1041 public function createPreEquation
1042 "creates d = $PRE.d equations"
1043 input Pointer<Variable> var_ptr;
1044 input Pointer<list<Pointer<Equation>>> ptr_pre_eqs;
1045 input Pointer<Integer> idx;
1046 protected
1047 Option<Pointer<Variable>> pre;
1048 Pointer<Equation> pre_eq;
1049 EquationKind kind;
1050 algorithm
1051 ✗ if not BVariable.isPrevious(var_ptr) then
1052 ✗ pre := BVariable.getVarPre(var_ptr);
1053 ✗ if isSome(pre) then
1054 ✗ kind := if BVariable.isContinuous(var_ptr, true) then EquationKind.CONTINUOUS else EquationKind.DISCRETE;
1055 ✗ pre_eq := Equation.makeAssignment(Expression.fromCref(BVariable.getVarName(var_ptr)), Expression.fromCref(BVariable.getVarName(Util.getOption(pre))), idx, NBEquation.PRE_STR, Iterator.EMPTY(), EquationAttributes.default(kind, true));
1056 ✗ Pointer.update(ptr_pre_eqs, pre_eq :: Pointer.access(ptr_pre_eqs));
1057 end if;
1058 end if;
1059 end createPreEquation;
1060
1061 function createPreEquationSlice
1062 "creates a pre equation for a sliced variable.
1063 usually results in a for equation, but might be scalarized if that is not possible."
1064 input Slice<VariablePointer> var_slice;
1065 input Pointer<list<Pointer<Equation>>> ptr_pre_eqs;
1066 input Pointer<Integer> idx;
1067 protected
1068 Pointer<Variable> var_ptr;
1069 Option<Pointer<Variable>> pre;
1070 ComponentRef name, pre_name;
1071 list<Dimension> dims;
1072 list<InstNode> iterators;
1073 list<Expression> ranges;
1074 list<Subscript> subscripts;
1075 list<tuple<ComponentRef, Expression, Option<Iterator>>> frames;
1076 Pointer<Equation> pre_eq;
1077 EquationKind kind;
1078 list<Pointer<Equation>> sliced_eqn;
1079 algorithm
1080 ✗ var_ptr := Slice.getT(var_slice);
1081 ✗ if not BVariable.isPrevious(var_ptr) then
1082 ✗ pre := BVariable.getVarPre(var_ptr);
1083 ✗ if isSome(pre) then
1084 ✗ name := BVariable.getVarName(var_ptr);
1085 ✗ dims := Type.arrayDims(ComponentRef.getSubscriptedType(name));
1086 ✗ (iterators, ranges, subscripts) := Flatten.makeIterators(name, dims);
1087 ✗ frames := List.zip3(list(ComponentRef.makeIterator(iter, Type.INTEGER()) for iter in iterators), ranges, List.fill(NONE(), listLength(ranges)));
1088
1089 ✗ pre_name := BVariable.getVarName(Util.getOption(pre));
1090 ✗ pre_name := ComponentRef.mergeSubscripts(subscripts, pre_name, true, true);
1091 ✗ name := ComponentRef.mergeSubscripts(subscripts, name, true, true);
1092
1093 ✗ kind := if BVariable.isContinuous(var_ptr, true) then EquationKind.CONTINUOUS else EquationKind.DISCRETE;
1094 ✗ pre_eq := Equation.makeAssignment(Expression.fromCref(name, true), Expression.fromCref(pre_name), idx, NBEquation.PRE_STR, Iterator.fromFrames(frames), EquationAttributes.default(kind, true));
1095
1096 ✗ if not listEmpty(var_slice.indices) then
1097 // empty list indicates full array, slice otherwise
1098 ✗ (sliced_eqn, _) := Equation.slice(pre_eq, var_slice.indices);
1099 ✗ Pointer.update(ptr_pre_eqs, listAppend(Pointer.access(ptr_pre_eqs), sliced_eqn));
1100 else
1101 ✗ Pointer.update(ptr_pre_eqs, pre_eq :: Pointer.access(ptr_pre_eqs));
1102 end if;
1103 end if;
1104 end if;
1105 end createPreEquationSlice;
1106
1107 function cleanup
1108 "removes calls from the initial problem and marks init_0"
1109 extends Module.wrapper;
1110 protected
1111 Pointer<Boolean> hasHom = Pointer.create(false);
1112 list<Partition> init_0;
1113 algorithm
1114 bdae := match bdae
1115 case BackendDAE.MAIN() algorithm
1116 // initial() -> false, initialSimplified() -> false
1117
4/4
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 327 times.
✓ Branch 3 taken 188 times.
703 bdae.ode := list(Partition.mapEqn(par, function cleanupInitialCall(kind = Partition.getKind(par))) for par in bdae.ode);
1118
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
188 bdae.algebraic := list(Partition.mapEqn(par, function cleanupInitialCall(kind = Partition.getKind(par))) for par in bdae.algebraic);
1119
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
188 bdae.ode_event := list(Partition.mapEqn(par, function cleanupInitialCall(kind = Partition.getKind(par))) for par in bdae.ode_event);
1120
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
376 bdae.alg_event := list(Partition.mapEqn(par, function cleanupInitialCall(kind = Partition.getKind(par))) for par in bdae.alg_event);
1121
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
188 if isSome(bdae.dae) then
1122 ✗ bdae.dae := SOME(list(Partition.mapEqn(par, function cleanupInitialCall(kind = Partition.getKind(par))) for par in Util.getOption(bdae.dae)));
1123 end if;
1124 // homotopy(actual, simplified) -> actual
1125
4/4
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 327 times.
✓ Branch 3 taken 188 times.
703 bdae.ode := list(Partition.mapExp(par, function cleanupHomotopy(kind = Partition.getKind(par))) for par in bdae.ode);
1126
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
188 bdae.algebraic := list(Partition.mapExp(par, function cleanupHomotopy(kind = Partition.getKind(par))) for par in bdae.algebraic);
1127
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
188 bdae.ode_event := list(Partition.mapExp(par, function cleanupHomotopy(kind = Partition.getKind(par))) for par in bdae.ode_event);
1128
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
376 bdae.alg_event := list(Partition.mapExp(par, function cleanupHomotopy(kind = Partition.getKind(par))) for par in bdae.alg_event);
1129
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 188 times.
188 if isSome(bdae.dae) then
1130 ✗ bdae.dae := SOME(list(Partition.mapExp(par, function cleanupHomotopy(kind = Partition.getKind(par))) for par in Util.getOption(bdae.dae)));
1131 end if;
1132
1133 // check if we have init lambda0 system
1134
4/4
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 175 times.
✓ Branch 3 taken 188 times.
551 bdae.init := list(Partition.mapExp(par, function containsLambda0(b = hasHom)) for par in bdae.init);
1135
1136 // create init_0 if homotopy call exists.
1137
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 182 times.
188 if Pointer.access(hasHom) then
1138
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
12 init_0 := list(Partition.setKind(Partition.clone(par, false), NBPartition.Kind.INI_0) for par in bdae.init);
1139
1140 // initial() -> true, initialSimplified() -> true
1141
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
12 init_0 := list(Partition.mapEqn(par, function cleanupInitialCall(kind = Partition.getKind(par))) for par in init_0);
1142 // homotopy(actual, simplified) -> simplified
1143
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
12 init_0 := list(Partition.mapExp(par, function cleanupHomotopy(kind = Partition.getKind(par))) for par in init_0);
1144
1145 6 bdae.init_0 := SOME(init_0);
1146 end if;
1147
1148 // initial() -> true, initialSimplified() -> false
1149
4/4
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 175 times.
✓ Branch 3 taken 188 times.
551 bdae.init := list(Partition.mapEqn(par, function cleanupInitialCall(kind = Partition.getKind(par))) for par in bdae.init);
1150
1151 then bdae;
1152
1153 else bdae;
1154 end match;
1155 end cleanup;
1156
1157 function cleanupInitialCall
1158 input output Equation eq;
1159 input BPartition.Kind kind;
1160 protected
1161 Pointer<Boolean> simplify = Pointer.create(false);
1162
1163 function cleanupInitialCallExp
1164 input output Expression exp;
1165 input BPartition.Kind kind;
1166 input Pointer<Boolean> simplify "output, determines if when-equation should be simplified";
1167 algorithm
1168
2/2
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 55390 times.
55411 if Expression.isCallNamed(exp, "initial") then
1169
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 2 times.
40 exp := Expression.BOOLEAN(kind == NBPartition.Kind.INI or kind == NBPartition.Kind.INI_0);
1170 21 Pointer.update(simplify, true);
1171 elseif Flags.isConfigFlagSet(Flags.ALLOW_NON_STANDARD_MODELICA, "initialSimplified") and Expression.isCallNamed(exp, "initialSimplified") then
1172
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
10 exp := Expression.BOOLEAN(kind == NBPartition.Kind.INI_0);
1173 6 Pointer.update(simplify, true);
1174 end if;
1175 end cleanupInitialCallExp;
1176 algorithm
1177 7749 eq := Equation.map(eq, function cleanupInitialCallExp(kind = kind, simplify = simplify));
1178
2/2
✓ Branch 1 taken 7722 times.
✓ Branch 2 taken 27 times.
7749 if Pointer.access(simplify) then
1179 27 eq := Equation.simplify(eq);
1180 end if;
1181 end cleanupInitialCall;
1182
1183 function cleanupHomotopy
1184 input output Expression exp;
1185 input BPartition.Kind kind;
1186 algorithm
1187 exp := match exp
1188 case Expression.CALL() guard Call.isNamed(exp.call, "homotopy")
1189 then match kind
1190 13 case NBPartition.Kind.INI_0 then listGet(Call.arguments(exp.call), 2);
1191 case NBPartition.Kind.INI then exp;
1192 14 else listHead(Call.arguments(exp.call));
1193 end match;
1194 else exp;
1195 end match;
1196 end cleanupHomotopy;
1197
1198 function containsHomotopyCall
1199 input output Expression exp;
1200 input Pointer<Boolean> b;
1201 algorithm
1202
4/4
✓ Branch 1 taken 1514 times.
✓ Branch 2 taken 8327 times.
✓ Branch 4 taken 8320 times.
✓ Branch 5 taken 7 times.
9841 if not Pointer.access(b) and Expression.isCallNamed(exp, "homotopy") then
1203 7 Pointer.update(b, true);
1204 end if;
1205 end containsHomotopyCall;
1206
1207 function containsLambda0
1208 input output Expression exp;
1209 input Pointer<Boolean> b;
1210 algorithm
1211
7/8
✓ Branch 1 taken 2822 times.
✓ Branch 2 taken 25286 times.
✓ Branch 4 taken 25281 times.
✓ Branch 5 taken 5 times.
✓ Branch 7 taken 25280 times.
✓ Branch 8 taken 1 time.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 time.
28108 if not Pointer.access(b) and (
1212 Expression.isCallNamed(exp, "homotopy") or
1213 (
1214 Flags.isConfigFlagSet(Flags.ALLOW_NON_STANDARD_MODELICA, "initialSimplified") and
1215 Expression.isCallNamed(exp, "initialSimplified")
1216 )
1217 )
1218 then
1219 6 Pointer.update(b, true);
1220 end if;
1221 end containsLambda0;
1222
1223 function minimizeHomotopySystem
1224 extends Module.wrapper;
1225 algorithm
1226 bdae := match bdae
1227 case BackendDAE.MAIN() algorithm
1228
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 182 times.
188 if isSome(bdae.init_0) then
1229 // for now all strong components have homotopy if init_0 exists
1230 // TODO reduced analysis on what needs to be computed for homotopy
1231
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
18 bdae.init := list(Partition.mapStrongComponents(par, function StrongComponent.setHomotopy(homotopy = true)) for par in bdae.init);
1232 end if;
1233 then bdae;
1234
1235 else bdae;
1236 end match;
1237 end minimizeHomotopySystem;
1238
1239 function removeWhenEquation
1240 "this function checks if an equation has to be removed before initialization.
1241 true for: when branch without condition initial()"
1242 input output Equation eqn;
1243 input Iterator iter;
1244 input UnorderedMap<ComponentRef, Iterator> cref_map;
1245 algorithm
1246 eqn := match eqn
1247 local
1248 Equation new_eqn;
1249 list<Statement> stmts;
1250 list<ComponentRef> lhs_crefs;
1251 Algorithm alg;
1252
1253 // reduce the body of for equations
1254 case Equation.FOR_EQUATION() algorithm
1255
4/4
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 306 times.
✓ Branch 2 taken 306 times.
✓ Branch 3 taken 306 times.
918 eqn.body := list(removeWhenEquation(b, eqn.iter, cref_map) for b in eqn.body);
1256
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 305 times.
306 then if List.all(eqn.body, Equation.isDummy) then Equation.DUMMY_EQUATION() else eqn;
1257
1258 // reduce the body of when equations
1259 case Equation.WHEN_EQUATION() algorithm
1260 66 stmts := removeWhenEquationBody(SOME(eqn.body));
1261
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 52 times.
66 if not listEmpty(stmts) then
1262 14 new_eqn := Pointer.access(Equation.makeAlgorithm(stmts, true));
1263 14 new_eqn := Equation.setResidualVar(new_eqn, Equation.getResidualVar(Pointer.create(eqn)));
1264 else
1265 // get all the discrete crefs that where in this when equation to create cref = pre.cref
1266 52 lhs_crefs := WhenEquationBody.getAllAssigned(eqn.body);
1267
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 52 times.
98 for cref in lhs_crefs loop UnorderedMap.add(cref, iter, cref_map); end for;
1268 new_eqn := Equation.DUMMY_EQUATION();
1269 end if;
1270 then new_eqn;
1271
1272 // reduce the body of if equations
1273 case Equation.IF_EQUATION() algorithm
1274 5 eqn.body := removeWhenEquationIfBody(eqn.body, iter, cref_map);
1275 5 eqn.size := IfEquationBody.size(eqn.body);
1276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 then if eqn.size > 0 then eqn else Equation.DUMMY_EQUATION();
1277
1278 // reduce the body of algorithms
1279 case Equation.ALGORITHM(alg = alg) algorithm
1280 291 stmts := removeWhenEquationAlgorithmBody(alg.statements);
1281
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 1 time.
291 if not listEmpty(stmts) then
1282 // update alg in-place to preserve original equation kind: re-evaluating via
1283 // makeAlgorithm would set DISCRETE if event auxiliaries (e.g. $SEV_0) are in outputs
1284 290 alg.statements := stmts;
1285 290 eqn.alg := Algorithm.setInputsOutputs(alg);
1286
4/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 290 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 290 times.
628 eqn.size := sum(ComponentRef.size(out, true) for out in eqn.alg.outputs);
1287 new_eqn := eqn;
1288 else
1289 new_eqn := Equation.DUMMY_EQUATION();
1290 end if;
1291 then new_eqn;
1292
1293 else eqn;
1294 end match;
1295 end removeWhenEquation;
1296
1297 function removeWhenEquationBody
1298 input Option<WhenEquationBody> body_opt;
1299 output list<Statement> stmts;
1300 algorithm
1301 stmts := match body_opt
1302 local
1303 WhenEquationBody body;
1304
1305 case SOME(body) algorithm
1306
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 93 times.
107 if isInitialCall(body.condition) then
1307 // this is kept, return the statements
1308
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 14 times.
28 stmts := list(WhenStatement.toStatement(st) for st in body.when_stmts);
1309 else
1310 // dig deeper
1311 93 stmts := removeWhenEquationBody(body.else_when);
1312 end if;
1313 then stmts;
1314
1315 else {};
1316 end match;
1317 end removeWhenEquationBody;
1318
1319 function removeWhenEquationIfBody
1320 input output IfEquationBody body;
1321 input Iterator iter;
1322 input UnorderedMap<ComponentRef, Iterator> cref_map;
1323 algorithm
1324
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
20 body.then_eqns := list(Pointer.apply(e, function removeWhenEquation(iter = iter, cref_map = cref_map)) for e in body.then_eqns);
1325 body.else_if := Util.applyOption(body.else_if, function removeWhenEquationIfBody(iter = iter, cref_map = cref_map));
1326 end removeWhenEquationIfBody;
1327
1328 function removeWhenEquationAlgorithmBody
1329 input list<Statement> in_stmts;
1330 output list<Statement> out_stmts;
1331 protected
1332 UnorderedSet<Expression> condition_set = UnorderedSet.new(Expression.hash, Expression.isEqual);
1333 Pointer<list<Statement>> tail_stmts_ptr = Pointer.create({});
1334 algorithm
1335 // stage 1: remove all when statements (that not have initial() conditions) and collect removed condtitions
1336
4/4
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 291 times.
✓ Branch 2 taken 329 times.
✓ Branch 3 taken 291 times.
620 out_stmts := List.flatten(list(removeWhenEquationStatement(stmt, condition_set) for stmt in in_stmts));
1337 // stage 2: remove all statements computing removed conditions that use a pre() variable on the rhs
1338
4/4
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 291 times.
✓ Branch 2 taken 328 times.
✓ Branch 3 taken 291 times.
619 out_stmts := List.flatten(list(removeConditionEquation(stmt, condition_set, tail_stmts_ptr) for stmt in out_stmts));
1339 // stage 3: add all removed statements to the end of the algorithm and add pre() := post() statements for the pre() of the rhs
1340 291 out_stmts := listAppend(out_stmts, Pointer.access(tail_stmts_ptr)) annotation(__OpenModelica_DisableListAppendWarning=true);
1341 end removeWhenEquationAlgorithmBody;
1342
1343 function removeWhenEquationStatement
1344 input Statement stmt;
1345 input UnorderedSet<Expression> condition_set;
1346 output list<Statement> out_stmts = {};
1347 algorithm
1348 out_stmts := match stmt
1349 local
1350 Expression cond;
1351 list<Statement> stmts;
1352 list<list<Statement>> stmts_acc = {};
1353
1354 case Statement.WHEN() algorithm
1355
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 for tpl in stmt.branches loop
1356 8 (cond, stmts) := tpl;
1357
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
8 if isInitialCall(cond) then
1358 out_stmts := stmts;
1359 end if;
1360 8 collectNonInitial(cond, condition_set);
1361 end for;
1362 then out_stmts;
1363
1364 case Statement.FOR() algorithm
1365
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 11 times.
24 for body_stmt in listReverse(stmt.body) loop
1366 13 stmts_acc := removeWhenEquationStatement(body_stmt, condition_set) :: stmts_acc;
1367 end for;
1368 11 stmts := List.flatten(stmts_acc);
1369
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if not listEmpty(stmts) then
1370 11 stmt.body := stmts;
1371 out_stmts := {stmt};
1372 else
1373 out_stmts := {};
1374 end if;
1375 then out_stmts;
1376
1377 else {stmt};
1378 end match;
1379 end removeWhenEquationStatement;
1380
1381 function removeConditionEquation
1382 input Statement stmt;
1383 input UnorderedSet<Expression> condition_set;
1384 input Pointer<list<Statement>> tail_stmts_ptr;
1385 output list<Statement> out_stmts = {};
1386 algorithm
1387 out_stmts := match stmt
1388 local
1389 UnorderedSet<ComponentRef> pre_set;
1390 ComponentRef post_cref;
1391 list<Statement> tail_stmts;
1392
1393 case Statement.ASSIGNMENT() guard(UnorderedSet.contains(stmt.lhs, condition_set)) algorithm
1394 // this is a cse statement. if it contains a pre variable on the RHS remove and add to tail statements
1395 4 pre_set := UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual);
1396 4 Expression.map(stmt.rhs, function findPreVars(pre_set = pre_set));
1397
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if UnorderedSet.isEmpty(pre_set) then
1398 out_stmts := {stmt};
1399 else
1400 2 tail_stmts := stmt :: Pointer.access(tail_stmts_ptr);
1401
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 for pre_cref in UnorderedSet.toList(pre_set) loop
1402 2 post_cref := BVariable.getPartnerCref(pre_cref, BVariable.getVarPre);
1403 2 tail_stmts := Statement.ASSIGNMENT(Expression.fromCref(pre_cref), Expression.fromCref(post_cref), ComponentRef.getSubscriptedType(pre_cref), DAE.emptyElementSource) :: tail_stmts;
1404 end for;
1405 2 Pointer.update(tail_stmts_ptr, tail_stmts);
1406 end if;
1407 then out_stmts;
1408 else {stmt};
1409 end match;
1410 end removeConditionEquation;
1411
1412 function findPreVars
1413 input output Expression exp;
1414 input UnorderedSet<ComponentRef> pre_set;
1415 algorithm
1416 () := match exp
1417 case Expression.CREF() guard(BVariable.isPrevious(BVariable.getVarPointer(exp.cref, sourceInfo()))) algorithm
1418 2 UnorderedSet.add(exp.cref, pre_set);
1419 then ();
1420 else ();
1421 end match;
1422 end findPreVars;
1423
1424 function replaceClockedFunctionsEqn
1425 input output Pointer<Equation> eqn;
1426 algorithm
1427 3872 Pointer.update(eqn, Equation.map(Pointer.access(eqn), replaceClockedFunctions));
1428 end replaceClockedFunctionsEqn;
1429
1430 function replaceClockedFunctions
1431 input output Expression exp;
1432 algorithm
1433 exp := match exp
1434 local
1435 Call call;
1436 case Expression.CALL(call = call as Call.TYPED_CALL()) guard(AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)) == "$getPart") algorithm
1437 ✗ then Expression.makeZero(Expression.typeOf(exp));
1438 else exp;
1439 end match;
1440 end replaceClockedFunctions;
1441
1442 function isInitialCall
1443 "checks if the expression is an initial call or can be simplified to be one."
1444 input Expression condition;
1445 output Boolean b;
1446 algorithm
1447 b := match condition
1448 // it's an initial call -> true;
1449 17 case Expression.CALL() then Call.isNamed(condition.call, "initial");
1450 // it's an "or" expression, check if either argument is an initial call
1451 case Expression.LBINARY(operator = Operator.OPERATOR(op = NFOperator.Op.OR))
1452 ✗ then isInitialCall(condition.exp1) or isInitialCall(condition.exp2);
1453 // it's an array where any of the elements is an initialCall
1454 10 case Expression.ARRAY() then Array.any(condition.elements, isInitialCall);
1455 // not an initial call. Ignore "and" constructs
1456 else false;
1457 end match;
1458 end isInitialCall;
1459
1460 function collectNonInitial
1461 input Expression condition;
1462 input UnorderedSet<Expression> condition_set;
1463 algorithm
1464 () := match condition
1465 case Expression.CREF() algorithm
1466 7 UnorderedSet.add(condition, condition_set);
1467 then ();
1468 case Expression.ARRAY() algorithm
1469
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 2 times.
8 for elem in condition.elements loop
1470 4 collectNonInitial(elem, condition_set);
1471 end for;
1472 then ();
1473 else ();
1474 end match;
1475 end collectNonInitial;
1476
1477 function collectAlgorithmOutputs
1478 input output Equation eqn;
1479 input UnorderedSet<ComponentRef> outputs;
1480 algorithm
1481 () := match eqn
1482 local
1483 Algorithm alg;
1484 list<ComponentRef> out_crefs;
1485
1486 case Equation.ALGORITHM(alg = alg) algorithm
1487
4/4
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 304 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 304 times.
366 out_crefs := List.flatten(list(BVariable.getRecordChildrenCrefOrSelf(o) for o in alg.outputs));
1488
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 304 times.
366 for cr in out_crefs loop
1489 62 UnorderedSet.add(cr, outputs);
1490 end for;
1491
1492 then ();
1493 else ();
1494 end match;
1495 end collectAlgorithmOutputs;
1496
1497 annotation(__OpenModelica_Interface="nbackend");
1498 end NBInitialization;
1499