Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 60.2% 147 / 0 / 244
Functions: -% 0 / 1 / 1
Branches: 59.6% 90 / 0 / 151

OMCompiler/Compiler/BackEnd/BackendDAETransform.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 BackendDAETransform
37 " file: BackendDAETransform.mo
38 package: BackendDAETransform
39 description: BackendDAETransform contains functions that are needed to perform
40 a transformation to a Block-Lower-Triangular-DAE.
41 - matchingAlgorithm
42 - strongComponents
43 - reduceIndexDummyDer
44
45
46 "
47
48 public
49 import BackendDAE;
50 import DAE;
51
52 protected
53 import BackendDAEUtil;
54 import BackendDump;
55 import BackendEquation;
56 import BackendVariable;
57 import ComponentReference;
58 protected import ComponentReferenceBasics;
59 import DAEUtil;
60 import Debug;
61 import ElementSource;
62 import Error;
63 import Expression;
64 import Flags;
65 import GCExt;
66 import List;
67 import MetaModelica.Dangerous;
68 import Sorting;
69 import SymbolicJacobian;
70 import System;
71 import Types;
72 import Util;
73 import ExpressionBasics;
74
75 // =============================================================================
76 // strongComponents and stuff
77 //
78 // =============================================================================
79
80 public function strongComponentsScalar "author: PA
81 This is the second part of the BLT sorting. It takes the variable
82 assignments and the adjacency matrix as input and identifies strong
83 components, i.e. subsystems of equations."
84 input BackendDAE.EqSystem inSystem;
85 input BackendDAE.Shared inShared;
86 input array<list<Integer>> mapEqnIncRow;
87 input array<Integer> mapIncRowEqn;
88 output BackendDAE.EqSystem outSystem;
89 output BackendDAE.StrongComponents outComps "list of components";
90 algorithm
91 (outSystem, outComps) := matchcontinue inSystem
92 local
93 BackendDAE.EqSystem syst;
94 BackendDAE.AdjacencyMatrixT mt;
95 BackendDAE.StrongComponents comps;
96 array<Integer> ass1, ass2;
97 array<Integer> markarray;
98 list<list<Integer>> comps_m;
99
100 case syst as BackendDAE.EQSYSTEM(mT=SOME(mt), matching=BackendDAE.MATCHING(ass1=ass1, ass2=ass2)) algorithm
101 61669 comps_m := Sorting.TarjanTransposed(mt, ass2);
102
103 61669 markarray := arrayCreate(BackendEquation.getNumberOfEquations(inSystem.orderedEqs), -1);
104 61669 comps := analyseStrongComponentsScalar(comps_m, inSystem, inShared, ass1, ass2, mapEqnIncRow, mapIncRowEqn, 1, markarray);
105 61669 GCExt.free(markarray);
106 61669 ass1 := varAssignmentNonScalar(ass1, mapIncRowEqn);
107
108 // Frenkel TUD: Do not hand over the scalar adjacency Matrix because following modules does not check if scalar or not
109 61669 syst := BackendDAE.EQSYSTEM(syst.orderedVars, syst.orderedEqs, NONE(), NONE(), NONE(), BackendDAE.MATCHING(ass1, ass2, comps), syst.stateSets, syst.partitionKind, syst.removedEqs);
110 then (syst, comps);
111
112 else algorithm
113 ✗ Error.addInternalError("function strongComponentsScalar failed (sorting strong components)", sourceInfo());
114 ✗ then fail();
115 end matchcontinue;
116 end strongComponentsScalar;
117
118 public function eqnAssignmentNonScalar
119 input array<list<Integer>> mapEqnIncRow;
120 input array<Integer> ass2;
121 output array<list<Integer>> outAcc;
122 protected
123 list<Integer> elst, vlst;
124 list<list<Integer>> acc = {};
125 algorithm
126 ✗ for i in 1:arrayLength(mapEqnIncRow) loop
127 ✗ elst := mapEqnIncRow[i];
128 ✗ vlst := list(arrayGet(ass2, e) for e guard(arrayGet(ass2, e) > 0) in elst);
129 acc := vlst::acc;
130 end for;
131
132 ✗ outAcc := List.listArrayReverse(acc);
133 end eqnAssignmentNonScalar;
134
135 public function varAssignmentNonScalar
136 input array<Integer> ass1;
137 input array<Integer> mapIncRowEqn;
138 output array<Integer> outAcc;
139 algorithm
140 61669 outAcc := Dangerous.arrayCreateNoInit(arrayLength(ass1),-1);
141
2/2
✓ Branch 0 taken 1894 times.
✓ Branch 1 taken 59775 times.
539447 for i in 1:arrayLength(ass1) loop
142
1/2
✓ Branch 0 taken 477778 times.
✗ Branch 1 not taken.
477778 Dangerous.arrayUpdateNoBoundsChecking(outAcc, i, if Dangerous.arrayGetNoBoundsChecking(ass1,i) > 0 then mapIncRowEqn[Dangerous.arrayGetNoBoundsChecking(ass1,i)] else -1);
143 end for;
144 end varAssignmentNonScalar;
145
146 protected function analyseStrongComponentsScalar "author: Frenkel TUD 2011-05
147 This analyses the type of the strongly connected components and calculates the jacobian."
148 input list<list<Integer>> inComps;
149 input BackendDAE.EqSystem syst;
150 input BackendDAE.Shared shared;
151 input array<Integer> inAss1;
152 input array<Integer> inAss2;
153 input array<list<Integer>> mapEqnIncRow;
154 input array<Integer> mapIncRowEqn;
155 input Integer imark;
156 input array<Integer> markarray;
157 output BackendDAE.StrongComponents outComps = {};
158 protected
159 list<BackendDAE.StrongComponent> acomp;
160 Integer mark = imark;
161 algorithm
162
2/2
✓ Branch 0 taken 358001 times.
✓ Branch 1 taken 61669 times.
419670 for comp in inComps loop
163 358001 (acomp, mark) := analyseStrongComponentScalar(comp, syst, shared, inAss1, inAss2, mapEqnIncRow, mapIncRowEqn, mark, markarray);
164 358001 outComps := listAppend(acomp,outComps);
165 end for;
166
167 61669 outComps := Dangerous.listReverseInPlace(outComps);
168 end analyseStrongComponentsScalar;
169
170 protected function analyseStrongComponentScalar "author: Frenkel TUD 2011-05"
171 input list<Integer> inComp;
172 input BackendDAE.EqSystem syst;
173 input BackendDAE.Shared shared;
174 input array<Integer> inAss1;
175 input array<Integer> inAss2;
176 input array<list<Integer>> mapEqnIncRow;
177 input array<Integer> mapIncRowEqn;
178 input Integer imark;
179 input array<Integer> markarray;
180 output list<BackendDAE.StrongComponent> outComp;
181 output Integer omark = imark + 1;
182 protected
183 list<Integer> comp, vlst;
184 list<BackendDAE.Var> varlst;
185 BackendDAE.Variables vars;
186 list<BackendDAE.Equation> eqn_lst;
187 BackendDAE.EquationArray eqns;
188 algorithm
189 try
190 358001 BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns) := syst;
191 358001 vlst := List.map1r(inComp, arrayGet, inAss2);
192 358001 vlst := List.select1(vlst, intGt, 0);
193 358001 varlst := List.map1r(vlst, BackendVariable.getVarAt, vars);
194
195 // get from scalar eqns indexes the indexes in the equation array
196 358001 comp := List.map1r(inComp, arrayGet, mapIncRowEqn);
197 358001 comp := List.fold2(comp, uniqueComp, imark, markarray, {});
198 //comp = List.unique(comp);
199 358001 eqn_lst := List.map1r(comp, BackendEquation.get, eqns);
200 358001 outComp := analyseStrongComponentBlock(comp, eqn_lst, varlst, vlst, syst, shared, mapEqnIncRow);
201 else
202 ✗ Error.addInternalError("function analyseStrongComponentScalar failed", sourceInfo());
203 ✗ fail();
204 end try;
205 end analyseStrongComponentScalar;
206
207 protected function uniqueComp
208 input Integer c;
209 input Integer mark;
210 input array<Integer> markarray;
211 input list<Integer> iAcc;
212 output list<Integer> oAcc = iAcc;
213 algorithm
214
2/2
✓ Branch 1 taken 46657 times.
✓ Branch 2 taken 431121 times.
477778 if mark <> markarray[c] then
215 431121 arrayUpdate(markarray,c,mark);
216 oAcc := c::iAcc;
217 end if;
218 end uniqueComp;
219
220 protected function analyseStrongComponentBlock "author: Frenkel TUD 2011-05"
221 input list<Integer> inComp;
222 input list<BackendDAE.Equation> inEqnLst;
223 input list<BackendDAE.Var> inVarLst;
224 input list<Integer> inVarindxLst;
225 input BackendDAE.EqSystem isyst;
226 input BackendDAE.Shared ishared;
227 input array<list<Integer>> mapEqnIncRow;
228 output list<BackendDAE.StrongComponent> outComp;
229 algorithm
230 outComp := matchcontinue (inComp, inEqnLst, inVarLst, inVarindxLst)
231 local
232 Integer compelem, v;
233 list<Integer> comp, varindxs;
234 array<Integer> ass2;
235 BackendDAE.AdjacencyMatrix m;
236 BackendDAE.AdjacencyMatrixT mt;
237 BackendDAE.Variables vars_1;
238 list<BackendDAE.Equation> eqn_lst, eqn_lst1;
239 list<BackendDAE.Var> var_lst, var_lst_1;
240 list<Integer> indxdisc_var;
241 BackendDAE.EquationArray eqns_1;
242 Option<list<tuple<Integer, Integer, BackendDAE.Equation>>> jac;
243 BackendDAE.JacobianType jac_tp;
244 BackendDAE.EqSystem syst;
245 BackendDAE.Shared shared;
246 String msg;
247 list<DAE.ComponentRef> crlst;
248 list<DAE.Exp> expLst;
249 list<String> slst;
250 Boolean jacConstant, mixedSystem, b1;
251 list<BackendDAE.StrongComponent> algorithmComp;
252
253 case (compelem::{}, BackendDAE.ALGORITHM()::{}, _, varindxs)
254 894 then {BackendDAE.SINGLEALGORITHM(compelem, varindxs)};
255
256 case (compelem::{}, BackendDAE.ARRAY_EQUATION()::{}, var_lst, varindxs) algorithm
257 934 crlst := List.map(var_lst,BackendVariable.varCref);
258 // its only an array equation if all the solved variables belong to an array. Otherwise we have to handle it as a non-linear system
259 934 b1 := List.applyAndFold(crlst,boolAnd,ComponentReference.isArrayElement,true);
260
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 792 times.
934 if not b1 then
261 142 expLst := List.map(crlst, Expression.crefExp);
262
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
142 true := List.exist1(inEqnLst,crefsAreArray,expLst);
263 end if;
264 934 then {BackendDAE.SINGLEARRAY(compelem, varindxs)};
265
266 case (compelem::{}, BackendDAE.IF_EQUATION()::{}, _, varindxs)
267 ✗ then {BackendDAE.SINGLEIFEQUATION(compelem, varindxs)};
268
269 case (compelem::{}, BackendDAE.COMPLEX_EQUATION()::{}, _, varindxs)
270 3104 then {BackendDAE.SINGLECOMPLEXEQUATION(compelem, varindxs)};
271
272 case (compelem::{}, BackendDAE.WHEN_EQUATION()::{}, _, varindxs)
273 1295 then {BackendDAE.SINGLEWHENEQUATION(compelem, varindxs)};
274
275 case (compelem::{}, _, _, v::{})
276 346386 then {BackendDAE.SINGLEEQUATION(compelem, v)};
277
278 case (comp, eqn_lst, var_lst, varindxs) algorithm
279 //false = BackendVariable.hasDiscreteVar(var_lst); //lochel: mixed systems and non-linear systems are treated the same
280
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5388 times.
5388 true := BackendVariable.hasContinuousVar(var_lst); //lochel: pure discrete equation systems are not supported
281 5388 eqn_lst1 := BackendEquation.replaceDerOpInEquationList(eqn_lst);
282 // States are solved for der(x) not x.
283 5388 var_lst_1 := List.map(var_lst, transformXToXd);
284 5388 vars_1 := BackendVariable.listVar1(var_lst_1);
285 5388 eqns_1 := BackendEquation.listEquation(eqn_lst1);
286 5388 (mixedSystem, _) := BackendEquation.iterationVarsinRelations(eqn_lst1, vars_1);
287
1/2
✓ Branch 1 taken 5388 times.
✗ Branch 2 not taken.
5388 if not Flags.isSet(Flags.DISABLE_JACSCC) then
288 5388 syst := BackendDAEUtil.createEqSystem(vars_1, eqns_1);
289 5388 (m, mt) := BackendDAEUtil.adjacencyMatrix(syst, BackendDAE.ABSOLUTE(), NONE(), BackendDAEUtil.isInitializationDAE(ishared));
290 // calculate jacobian. If constant, linear system of equations. Otherwise nonlinear
291 5388 (jac, shared) := SymbolicJacobian.calculateJacobian(vars_1, eqns_1, m, true, ishared);
292 // Jacobian of a Linear System is always linear
293 5388 (jac_tp, jacConstant) := SymbolicJacobian.analyzeJacobian(vars_1, eqns_1, jac);
294
295 // if Jacobian is constant, then check if it is singular
296
4/6
✓ Branch 0 taken 262 times.
✓ Branch 1 taken 5126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 262 times.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
5388 if jacConstant and isSome(jac) then
297
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 262 times.
524 true := analyzeConstantJacobian(Util.getOption(jac), arrayLength(mt), var_lst, eqn_lst, shared);
298 end if;
299 else
300 jac := NONE();
301 jac_tp := BackendDAE.JAC_NO_ANALYTIC();
302 end if;
303
2/2
✓ Branch 1 taken 4940 times.
✓ Branch 2 taken 448 times.
10328 then {BackendDAE.EQUATIONSYSTEM(comp, varindxs, BackendDAE.FULL_JACOBIAN(jac), jac_tp, mixedSystem)};
304
305 /*
306 All algorithms - assume each can be solved for its matched variables.
307 Purely discrete algebraic loops are not solvable otherwise.
308 Related to ticket #5659
309 */
310 case (comp, eqn_lst, var_lst, _)
311 guard(BackendEquation.allAlgorithmsLst(eqn_lst))
312 algorithm
313 ✗ true := BackendVariable.hasDiscreteVar(var_lst);
314 ✗ false := BackendVariable.hasContinuousVar(var_lst);
315 ✗ BackendDAE.MATCHING(_, ass2, _) := isyst.matching;
316 algorithmComp := {};
317 ✗ for c in comp loop
318 indxdisc_var := {};
319 // get matched variables for each aglorithm
320 ✗ for j in mapEqnIncRow[c] loop
321 ✗ indxdisc_var := ass2[j] :: indxdisc_var;
322 end for;
323 ✗ algorithmComp := BackendDAE.SINGLEALGORITHM(c, indxdisc_var) :: algorithmComp;
324 end for;
325 then algorithmComp;
326
327 /* Purely discrete algebraic loops are not solvable. */
328 case (_, eqn_lst, var_lst, _) algorithm
329 ✗ true := BackendVariable.hasDiscreteVar(var_lst);
330 ✗ false := BackendVariable.hasContinuousVar(var_lst);
331 msg := getInstanceName() + " failed (Purely discrete algebraic loops cannot be solved by iterative processes. Try to break them open using the delay() operator.)\n";
332 ✗ crlst := List.map(var_lst, BackendVariable.varCref);
333 ✗ slst := List.map(crlst, ComponentReferenceBasics.printComponentRefStr);
334 ✗ msg := msg + stringDelimitList(slst, "\n");
335 ✗ slst := List.map(eqn_lst, BackendDump.equationString);
336 ✗ msg := msg + "\n" + stringDelimitList(slst, "\n");
337 ✗ Error.addInternalError(msg, sourceInfo());
338 ✗ then fail();
339
340 case (_, eqn_lst, var_lst, _) algorithm
341 msg := getInstanceName() + " failed\nvariables:\n ";
342 ✗ crlst := List.map(var_lst, BackendVariable.varCref);
343 ✗ slst := List.map(crlst, ComponentReferenceBasics.printComponentRefStr);
344 ✗ msg := msg + stringDelimitList(slst, "\n ");
345 ✗ slst := List.map(eqn_lst, BackendDump.equationString);
346 ✗ msg := msg + "\nequations:\n " + stringDelimitList(slst, "\n ");
347 ✗ Error.addInternalError(msg, sourceInfo());
348 ✗ then fail();
349
350 else algorithm
351 ✗ Error.addInternalError("function analyseStrongComponentBlock failed", sourceInfo());
352 ✗ then fail();
353 end matchcontinue;
354 end analyseStrongComponentBlock;
355
356 protected function crefsAreArray "author:Waurich TUD 2015-03
357 checks if the crefs build an array on one side of the equation (sometimes used in FMUs)"
358 input BackendDAE.Equation eqIn;
359 input list<DAE.Exp> crefLst;
360 output Boolean isUnsolvable;
361 algorithm
362 isUnsolvable := matchcontinue eqIn
363 local
364 list<DAE.Exp> expLst;
365
366 case BackendDAE.ARRAY_EQUATION(left=DAE.ARRAY(array=expLst)) algorithm
367 142 (_, _, expLst) := List.intersection1OnTrue(expLst, crefLst, ExpressionBasics.expEqual);
368 142 then listEmpty(expLst);
369
370 case BackendDAE.ARRAY_EQUATION(right=DAE.ARRAY(array=expLst)) algorithm
371 ✗ (_, _, expLst) := List.intersection1OnTrue(expLst, crefLst, ExpressionBasics.expEqual);
372 ✗ then listEmpty(expLst);
373
374 else false;
375 end matchcontinue;
376 end crefsAreArray;
377
378 protected function analyzeConstantJacobian
379 input list<tuple<Integer, Integer, BackendDAE.Equation>> inJac;
380 input Integer inSize;
381 input list<BackendDAE.Var> inVars;
382 input list<BackendDAE.Equation> inEqns;
383 input BackendDAE.Shared inShared;
384 output Boolean outValid = true;
385 protected
386 BackendDAE.EquationArray eqns;
387 BackendDAE.Variables vars;
388 AvlTreePathFunction.Tree funcs;
389 Integer info;
390 String infoStr, syst, varnames, varname, rhsStr, jacStr, eqnstr;
391 list<DAE.Exp> beqs;
392 list<Real> rhsVals;
393 list<list<Real>> jacVals;
394 algorithm
395 262 jacVals := SymbolicJacobian.evaluateConstantJacobian(inSize, inJac);
396 262 rhsVals := List.fill(0.0, inSize);
397 262 (_, info) := System.dgesv(jacVals, rhsVals);
398
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
262 if info < 0 then
400 // info < 0: if INFO = -i, the i-th argument had an illegal value
401 // this case should never happen
402 ✗ varnames := stringDelimitList(List.mapMap(inVars, BackendVariable.varCref, ComponentReferenceBasics.printComponentRefStr), " ;\n ");
403 ✗ eqns := BackendEquation.listEquation(inEqns);
404 ✗ vars := BackendVariable.listVar1(inVars);
405 ✗ funcs := BackendDAEUtil.getFunctions(inShared);
406 ✗ (beqs, _) := BackendDAEUtil.getEqnSysRhs(eqns, vars, SOME(funcs));
407 ✗ beqs := listReverse(beqs);
408 ✗ rhsStr := stringDelimitList(List.map(beqs, ExpressionBasics.printExpStr), " ;\n ");
409 ✗ jacStr := stringDelimitList(List.map1(List.mapList(jacVals, realString), stringDelimitList, " , "), " ;\n ");
410 ✗ eqnstr := BackendDump.dumpEqnsStr(inEqns);
411 ✗ syst := eqnstr + "\n[" + jacStr + "] * [" + varnames + "] = [" + rhsStr + "]";
412 ✗ Error.addMessage(Error.LINEAR_SYSTEM_INVALID, {"LAPACK/dgesv", syst});
413 outValid := false;
414 elseif info > 0 then
415 // info > 0: if INFO = i, U(i,i) is exactly zero. The factorization
416 // has been completed, but the factor U is exactly
417 // singular, so the solution could not be computed.
418 ✗ varname := ComponentReferenceBasics.printComponentRefStr(BackendVariable.varCref(listGet(inVars, info)));
419 ✗ infoStr := intString(info);
420 ✗ varnames := stringDelimitList(List.mapMap(inVars, BackendVariable.varCref, ComponentReferenceBasics.printComponentRefStr), " ;\n ");
421 ✗ eqns := BackendEquation.listEquation(inEqns);
422 ✗ vars := BackendVariable.listVar1(inVars);
423 ✗ funcs := BackendDAEUtil.getFunctions(inShared);
424 ✗ (beqs, _) := BackendDAEUtil.getEqnSysRhs(eqns, vars, SOME(funcs));
425 ✗ beqs := listReverse(beqs);
426 ✗ rhsStr := stringDelimitList(List.map(beqs, ExpressionBasics.printExpStr), " ;\n ");
427 ✗ jacStr := stringDelimitList(List.map1(List.mapList(jacVals, realString), stringDelimitList, " , "), " ;\n ");
428 ✗ eqnstr := BackendDump.dumpEqnsStr(inEqns);
429 ✗ syst := "\n" + eqnstr + "\n[\n " + jacStr + "\n]\n *\n[\n " + varnames + "\n]\n =\n[\n " + rhsStr + "\n]";
430 ✗ Error.addMessage(Error.LINEAR_SYSTEM_SINGULAR, {syst, infoStr, varname});
431 //outValid := false;
432 end if;
433 end analyzeConstantJacobian;
434
435 protected function transformXToXd "author: PA
436 this function transforms x variables (in the state vector)
437 to corresponding xd variable (in the derivatives vector)"
438 input BackendDAE.Var inVar;
439 output BackendDAE.Var outVar = inVar;
440 algorithm
441
2/2
✓ Branch 1 taken 83730 times.
✓ Branch 2 taken 3377 times.
87107 if BackendVariable.isStateVar(inVar) then
442 3377 outVar.varName := ComponentReference.crefPrefixDer(inVar.varName);
443 outVar.varKind := BackendDAE.STATE_DER();
444 outVar.unreplaceable := false;
445 end if;
446 end transformXToXd;
447
448 public function getEquationAndSolvedVar "author: PA
449 Retrieves the equation and the variable solved in that equation
450 given an equation number and the variable assignments2"
451 input BackendDAE.StrongComponent inComp;
452 input BackendDAE.EquationArray inEquationArray;
453 input BackendDAE.Variables inVariables;
454 output list<BackendDAE.Equation> outEquation;
455 output list<BackendDAE.Var> outVar;
456 output Integer outIndex;
457 algorithm
458 (outEquation, outVar, outIndex) := match inComp
459 local
460 Integer v, e;
461 list<Integer> elst, vlst, otherEqns, otherVars;
462 list<list<Integer>> otherVarsLst;
463 BackendDAE.Equation eqn;
464 BackendDAE.Var var;
465 list<BackendDAE.Equation> eqnlst, eqnlst1;
466 list<BackendDAE.Var> varlst, varlst1;
467 BackendDAE.InnerEquations innerEquations;
468
469 case BackendDAE.SINGLEEQUATION(eqn=e, var=v) algorithm
470 ✗ eqn := BackendEquation.get(inEquationArray, e);
471 ✗ var := BackendVariable.getVarAt(inVariables, v);
472 then ({eqn}, {var}, e);
473
474 case BackendDAE.EQUATIONSYSTEM(eqns=elst, vars=vlst) algorithm
475 224 eqnlst := BackendEquation.getList(elst, inEquationArray);
476 224 varlst := List.map1r(vlst, BackendVariable.getVarAt, inVariables);
477 224 e := listHead(elst);
478 then (eqnlst, varlst, e);
479
480 case BackendDAE.SINGLEARRAY(eqn=e, vars=vlst) algorithm
481 549 eqn := BackendEquation.get(inEquationArray, e);
482 549 varlst := List.map1r(vlst, BackendVariable.getVarAt, inVariables);
483 then ({eqn}, varlst, e);
484
485 case BackendDAE.SINGLEIFEQUATION(eqn=e, vars=vlst) algorithm
486 ✗ eqn := BackendEquation.get(inEquationArray, e);
487 ✗ varlst := List.map1r(vlst, BackendVariable.getVarAt, inVariables);
488 then ({eqn}, varlst, e);
489
490 case BackendDAE.SINGLEALGORITHM(eqn=e, vars=vlst) algorithm
491 505 eqn := BackendEquation.get(inEquationArray, e);
492 505 varlst := List.map1r(vlst, BackendVariable.getVarAt, inVariables);
493 then ({eqn}, varlst, e);
494
495 case BackendDAE.SINGLECOMPLEXEQUATION(eqn=e, vars=vlst) algorithm
496 1172 eqn := BackendEquation.get(inEquationArray, e);
497 1172 varlst := List.map1r(vlst, BackendVariable.getVarAt, inVariables);
498 then ({eqn}, varlst, e);
499
500 case BackendDAE.SINGLEWHENEQUATION(eqn=e, vars=vlst) algorithm
501 425 eqn := BackendEquation.get(inEquationArray, e);
502 425 varlst := List.map1r(vlst, BackendVariable.getVarAt, inVariables);
503 then ({eqn}, varlst, e);
504
505 case BackendDAE.TORNSYSTEM(BackendDAE.TEARINGSET(tearingvars=vlst, residualequations=elst, innerEquations=innerEquations)) algorithm
506 ✗ eqnlst := BackendEquation.getList(elst, inEquationArray);
507 ✗ varlst := List.map1r(vlst, BackendVariable.getVarAt, inVariables);
508 ✗ (otherEqns,otherVarsLst,_) := List.map_3(innerEquations, BackendDAEUtil.getEqnAndVarsFromInnerEquation);
509 ✗ otherVars := List.flatten(otherVarsLst);
510 ✗ eqnlst1 := BackendEquation.getList(otherEqns, inEquationArray);
511 ✗ varlst1 := List.map1r(otherVars, BackendVariable.getVarAt, inVariables);
512 ✗ e := listHead(elst);
513 ✗ then (listAppend(eqnlst, eqnlst1), listAppend(varlst, varlst1), e);
514
515 else algorithm
516 ✗ true := Flags.isSet(Flags.FAILTRACE);
517 ✗ Debug.traceln("BackendDAETransform.getEquationAndSolvedVar failed!");
518 ✗ then fail();
519 end match;
520 end getEquationAndSolvedVar;
521
522 public function getEquationAndSolvedVarIndxes "author: Frenkel TUD
523 Retrieves the equation and the variable indexes solved in that equation
524 given an equation number and the variable assignments2"
525 input BackendDAE.StrongComponent inComp;
526 output list<Integer> outEquation;
527 output list<Integer> outVar;
528 algorithm
529 (outEquation, outVar) := matchcontinue inComp
530 local
531 Integer v, e;
532 list<Integer> elst, vlst, elst1, vlst1;
533 list<list<Integer>> vLstLst;
534 BackendDAE.InnerEquations innerEquations;
535
536 case BackendDAE.SINGLEEQUATION(eqn=e, var=v)
537 then ({e}, {v});
538
539 case BackendDAE.EQUATIONSYSTEM(eqns=elst, vars=vlst)
540 then (elst, vlst);
541
542 case BackendDAE.SINGLEARRAY(eqn=e, vars=vlst)
543 then ({e}, vlst);
544
545 case BackendDAE.SINGLEIFEQUATION(eqn=e, vars=vlst)
546 then ({e}, vlst);
547
548 case BackendDAE.SINGLEALGORITHM(eqn=e, vars=vlst)
549 then ({e}, vlst);
550
551 case BackendDAE.SINGLECOMPLEXEQUATION(eqn=e, vars=vlst)
552 then ({e}, vlst);
553
554 case BackendDAE.SINGLEWHENEQUATION(eqn=e, vars=vlst)
555 then ({e}, vlst);
556
557 case BackendDAE.TORNSYSTEM(BackendDAE.TEARINGSET(tearingvars=vlst, residualequations=elst, innerEquations=innerEquations)) algorithm
558 1837 (elst1,vLstLst,_) := List.map_3(innerEquations, BackendDAEUtil.getEqnAndVarsFromInnerEquation);
559 1837 vlst1 := List.flatten(vLstLst);
560 1837 elst := listAppend(elst1, elst);
561 1837 vlst := listAppend(vlst1, vlst);
562 then (elst, vlst);
563
564 else algorithm
565 ✗ true := Flags.isSet(Flags.FAILTRACE);
566 ✗ Debug.traceln("BackendDAETransform.getEquationAndSolvedVarIndxes failed!");
567 ✗ then fail();
568 end matchcontinue;
569 end getEquationAndSolvedVarIndxes;
570
571
572 // =============================================================================
573 // traverseBackendDAEExps stuff
574 //
575 // =============================================================================
576
577 public function traverseBackendDAEExpsEqnWithSymbolicOperation
578 "Traverse all expressions of a list of Equations. It is possible to change the equations
579 and the multidim equations and the algorithms.
580 // TODO: remove this together with removeEqualFunctionCall"
581 replaceable type Type_a subtypeof Any;
582 input BackendDAE.Equation inEquation;
583 input FuncExpType func;
584 input Type_a inTypeA;
585 output BackendDAE.Equation outEquation;
586 output Type_a outTypeA;
587 partial function FuncExpType
588 input DAE.Exp inExp;
589 input tuple<list<DAE.SymbolicOperation>, Type_a> inTpl;
590 output DAE.Exp outExp;
591 output tuple<list<DAE.SymbolicOperation>, Type_a> outTpl;
592 end FuncExpType;
593 algorithm
594 (outEquation, outTypeA) := matchcontinue inEquation
595 local
596 DAE.Exp e1_1, e2_1, e1, e2, cond;
597 DAE.Exp iter, start, stop;
598 DAE.ComponentRef cr, cr1;
599 Integer size;
600 Option<Integer> recordSize;
601 list<DAE.Exp> expl;
602 BackendDAE.Equation eqn;
603 BackendDAE.WhenEquation elsepartRes;
604 BackendDAE.WhenEquation elsepart;
605 Option<BackendDAE.WhenEquation> oelsepart;
606 DAE.ElementSource source;
607 list<Integer> dimSize;
608 list<DAE.SymbolicOperation> ops;
609 list<DAE.Statement> statementLst;
610 list<BackendDAE.Equation> eqns;
611 list<list<BackendDAE.Equation>> eqnslst;
612 Type_a ext_arg_1, ext_arg_2, ext_arg_3;
613 DAE.Expand crefExpand;
614 BackendDAE.EquationAttributes eqAttr;
615 list<BackendDAE.WhenOperator> whenStmtLst;
616
617 case BackendDAE.EQUATION(exp = e1, scalar = e2, source = source, attr=eqAttr) algorithm
618
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 252355 times.
252355 (e1_1, (ops, ext_arg_1)) := func(e1, ({}, inTypeA));
619
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 252355 times.
252355 (e2_1, (ops, ext_arg_2)) := func(e2, (ops, ext_arg_1));
620 252355 source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
621 252355 then (BackendDAE.EQUATION(e1_1, e2_1, source, eqAttr), ext_arg_2);
622
623 // Array equation
624 case BackendDAE.ARRAY_EQUATION(dimSize=dimSize, left = e1, right = e2, source = source, attr=eqAttr, recordSize=recordSize) algorithm
625
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2022 times.
2022 (e1_1, (ops, ext_arg_1)) := func(e1, ({}, inTypeA));
626
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2022 times.
2022 (e2_1, (ops, ext_arg_2)) := func(e2, (ops, ext_arg_1));
627 2022 source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
628 2022 then (BackendDAE.ARRAY_EQUATION(dimSize, e1_1, e2_1, source, eqAttr, recordSize), ext_arg_2);
629
630 case BackendDAE.FOR_EQUATION(iter = iter, start = start, stop = stop, body = eqn, source = source, attr = eqAttr) algorithm
631 24 (eqn, outTypeA) := traverseBackendDAEExpsEqnWithSymbolicOperation(eqn, func, inTypeA);
632 24 then (BackendDAE.FOR_EQUATION(iter, start, stop, eqn, source, eqAttr), outTypeA);
633
634 case BackendDAE.SOLVED_EQUATION(componentRef = cr, exp = e2, source=source, attr=eqAttr) algorithm
635 251 e1 := Expression.crefExp(cr);
636
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 251 times.
251 (DAE.CREF(cr1, _), (ops, ext_arg_1)) := func(e1, ({}, inTypeA));
637
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
251 (e2_1, (ops, _)) := func(e2, (ops, ext_arg_1));
638 251 source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
639 251 then (BackendDAE.SOLVED_EQUATION(cr1, e2_1, source, eqAttr), ext_arg_1);
640
641 case BackendDAE.RESIDUAL_EQUATION(exp = e1, source=source, attr=eqAttr) algorithm
642 ✗ (e1_1, (ops, ext_arg_1)) := func(e1, ({}, inTypeA));
643 ✗ source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
644 ✗ then (BackendDAE.RESIDUAL_EQUATION(e1_1, source, eqAttr), ext_arg_1);
645
646 // Algorithms
647 case BackendDAE.ALGORITHM(size = size, alg=DAE.ALGORITHM_STMTS(statementLst = statementLst), source = source, expand = crefExpand, attr=eqAttr) algorithm
648 1716 (statementLst, (ops, ext_arg_1)) := DAEUtil.traverseDAEEquationsStmts(statementLst, func, ({}, inTypeA));
649 1716 source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
650 1716 then (BackendDAE.ALGORITHM(size, DAE.ALGORITHM_STMTS(statementLst), source, crefExpand, eqAttr), ext_arg_1);
651
652 case BackendDAE.WHEN_EQUATION(size=size, whenEquation=BackendDAE.WHEN_STMTS(condition=cond, whenStmtLst=whenStmtLst, elsewhenPart=oelsepart), source = source, attr=eqAttr) algorithm
653 806 (whenStmtLst, ext_arg_1) := traverseBackendDAEExpsWhenOperatorWithSymbolicOperation(whenStmtLst, func, inTypeA);
654
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 806 times.
806 (cond, (ops, ext_arg_2)) := func(cond, ({}, ext_arg_1));
655 806 source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
656
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 806 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 798 times.
806 if isSome(oelsepart) then
657 8 SOME(elsepart) := oelsepart;
658
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 (BackendDAE.WHEN_EQUATION(whenEquation=elsepartRes, source=source), ext_arg_3) := traverseBackendDAEExpsEqnWithSymbolicOperation(BackendDAE.WHEN_EQUATION(size, elsepart, source, eqAttr), func, ext_arg_2);
659 oelsepart := SOME(elsepartRes);
660 else
661 oelsepart := NONE();
662 ext_arg_3 := ext_arg_2;
663 end if;
664 806 eqn := BackendDAE.WHEN_EQUATION(size, BackendDAE.WHEN_STMTS(cond, whenStmtLst, oelsepart), source, eqAttr);
665 then (eqn, ext_arg_3);
666
667 case BackendDAE.COMPLEX_EQUATION(size=size, left = e1, right = e2, source = source, attr=eqAttr) algorithm
668
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2143 times.
2143 (e1_1, (ops, ext_arg_1)) := func(e1, ({}, inTypeA));
669
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2143 times.
2143 (e2_1, (ops, ext_arg_2)) := func(e2, (ops, ext_arg_1));
670 2143 source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
671 2143 then (BackendDAE.COMPLEX_EQUATION(size, e1_1, e2_1, source, eqAttr), ext_arg_2);
672
673 case BackendDAE.IF_EQUATION(conditions=expl, eqnstrue=eqnslst, eqnsfalse=eqns, source=source, attr=eqAttr) algorithm
674 ✗ (expl, (ops, ext_arg_1)) := traverseBackendDAEExpsLstEqnWithSymbolicOperation(expl, func, ({}, inTypeA), {});
675 ✗ source := List.foldr(ops, ElementSource.addSymbolicTransformation, source);
676 ✗ (eqnslst, ext_arg_1) := traverseBackendDAEExpsEqnLstLstWithSymbolicOperation(eqnslst, func, ext_arg_1, {});
677 ✗ (eqns, ext_arg_1) := traverseBackendDAEExpsEqnLstWithSymbolicOperation(eqns, func, ext_arg_1, {});
678 ✗ then (BackendDAE.IF_EQUATION(expl, eqnslst, eqns, source, eqAttr), ext_arg_1);
679
680 else algorithm
681 ✗ Error.addInternalError("function traverseBackendDAEExpsEqnWithSymbolicOperation failed", sourceInfo());
682 ✗ then fail();
683 end matchcontinue;
684 end traverseBackendDAEExpsEqnWithSymbolicOperation;
685
686 protected function traverseBackendDAEExpsLstEqnWithSymbolicOperation
687 replaceable type Type_a subtypeof Any;
688 input list<DAE.Exp> inExps;
689 input FuncExpType func;
690 input Type_a inTypeA;
691 input list<DAE.Exp> iAcc;
692 output list<DAE.Exp> outExps;
693 output Type_a outTypeA;
694 partial function FuncExpType
695 input DAE.Exp inExp;
696 input Type_a inTypeA;
697 output DAE.Exp outExp;
698 output Type_a outA;
699 end FuncExpType;
700 algorithm
701 (outExps, outTypeA) := match inExps
702 local
703 DAE.Exp exp;
704 list<DAE.Exp> rest, exps;
705 Type_a arg;
706
707 case {}
708 ✗ then (listReverse(iAcc), inTypeA);
709
710 case exp::rest algorithm
711 ✗ (exp, arg) := func(exp, inTypeA);
712 ✗ (exps, arg) := traverseBackendDAEExpsLstEqnWithSymbolicOperation(rest, func, arg, exp::iAcc);
713 then (exps, arg);
714 end match;
715 end traverseBackendDAEExpsLstEqnWithSymbolicOperation;
716
717 public function traverseBackendDAEExpsEqnLstWithSymbolicOperation
718 replaceable type Type_a subtypeof Any;
719 input list<BackendDAE.Equation> inEqns;
720 input FuncExpType func;
721 input Type_a inTypeA;
722 input list<BackendDAE.Equation> iAcc = {};
723 output list<BackendDAE.Equation> outEqns;
724 output Type_a outTypeA;
725 partial function FuncExpType
726 input DAE.Exp inExp;
727 input tuple<list<DAE.SymbolicOperation>, Type_a> inTpl;
728 output DAE.Exp outExp;
729 output tuple<list<DAE.SymbolicOperation>, Type_a> outTpl;
730 end FuncExpType;
731 algorithm
732 (outEqns, outTypeA) := match inEqns
733 local
734 BackendDAE.Equation eqn;
735 list<BackendDAE.Equation> rest, eqns;
736 Type_a arg;
737
738 case {}
739 ✗ then (listReverse(iAcc), inTypeA);
740
741 case eqn::rest algorithm
742 ✗ (eqn, arg) := traverseBackendDAEExpsEqnWithSymbolicOperation(eqn, func, inTypeA);
743 ✗ (eqns, arg) := traverseBackendDAEExpsEqnLstWithSymbolicOperation(rest, func, arg, eqn::iAcc);
744 then (eqns, arg);
745 end match;
746 end traverseBackendDAEExpsEqnLstWithSymbolicOperation;
747
748 protected function traverseBackendDAEExpsEqnLstLstWithSymbolicOperation
749 replaceable type Type_a subtypeof Any;
750 input list<list<BackendDAE.Equation>> inEqns;
751 input FuncExpType func;
752 input Type_a inTypeA;
753 input list<list<BackendDAE.Equation>> iAcc;
754 output list<list<BackendDAE.Equation>> outEqns;
755 output Type_a outTypeA;
756 partial function FuncExpType
757 input DAE.Exp inExp;
758 input tuple<list<DAE.SymbolicOperation>, Type_a> inTpl;
759 output DAE.Exp outExp;
760 output tuple<list<DAE.SymbolicOperation>, Type_a> outTpl;
761 end FuncExpType;
762 algorithm
763 (outEqns, outTypeA) := match inEqns
764 local
765 list<BackendDAE.Equation> eqn;
766 list<list<BackendDAE.Equation>> rest, eqnslst;
767 Type_a arg;
768 ✗ case {} then (listReverse(iAcc), inTypeA);
769 case eqn::rest
770 algorithm
771 ✗ (eqn, arg) := traverseBackendDAEExpsEqnLstWithSymbolicOperation(eqn, func, inTypeA, {});
772 ✗ (eqnslst, arg) := traverseBackendDAEExpsEqnLstLstWithSymbolicOperation(rest, func, arg, eqn::iAcc);
773 then
774 (eqnslst, arg);
775 end match;
776 end traverseBackendDAEExpsEqnLstLstWithSymbolicOperation;
777
778 protected function traverseBackendDAEExpsWhenOperatorWithSymbolicOperation<ArgT>
779 " Traverse all expressions of a list of Equations. It is possible to change the equations
780 and the multidim equations and the algorithms."
781 input list<BackendDAE.WhenOperator> inStmtLst;
782 input FuncExpType func;
783 input ArgT inArg;
784 output list<BackendDAE.WhenOperator> outStmtLst = {};
785 output ArgT outArg = inArg;
786 partial function FuncExpType
787 input DAE.Exp inExp;
788 input tuple<list<DAE.SymbolicOperation>, ArgT> inTpl;
789 output DAE.Exp outExp;
790 output tuple<list<DAE.SymbolicOperation>, ArgT> outTpl;
791 end FuncExpType;
792 algorithm
793
7/7
✓ Branch 0 taken 745 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 806 times.
✓ Branch 6 taken 806 times.
1612 for rs in inStmtLst loop
794 rs := match rs
795 local
796 DAE.ComponentRef cr;
797 DAE.Exp lhs,cond, msg, level, exp;
798 DAE.ElementSource src;
799 list<DAE.SymbolicOperation> ops;
800
801 case BackendDAE.ASSIGN(lhs, cond, src) algorithm
802
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 745 times.
745 (cond, (ops, outArg)) := func(cond, ({}, inArg));
803
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 745 times.
745 (lhs, (ops, outArg)) := func(lhs, (ops,outArg));
804 745 src := List.foldr(ops, ElementSource.addSymbolicTransformation, src);
805 745 then BackendDAE.ASSIGN(lhs, cond, src);
806
807 case BackendDAE.REINIT(cr, cond, src) algorithm
808
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 (cond, (ops, outArg)) := func(cond, ({}, inArg));
809
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36 times.
36 (DAE.CREF(componentRef = cr), (ops, outArg)) := func(Expression.crefExp(cr), (ops,outArg));
810 36 src := List.foldr(ops, ElementSource.addSymbolicTransformation, src);
811 36 then BackendDAE.REINIT(cr, cond, src);
812
813 case BackendDAE.ASSERT(cond, msg, level, src) algorithm
814
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 (cond, (ops, outArg)) := func(cond, ({}, inArg));
815 7 src := List.foldr(ops, ElementSource.addSymbolicTransformation, src);
816 7 then BackendDAE.ASSERT(cond, msg, level, src);
817
818 case BackendDAE.NORETCALL(exp, src) algorithm
819 12 (exp, (ops, outArg)) := Expression.traverseExpBottomUp(exp, func, ({}, outArg));
820 12 src := List.foldr(ops, ElementSource.addSymbolicTransformation, src);
821 12 then BackendDAE.NORETCALL(exp, src);
822
823 else rs;
824 end match;
825
826 outStmtLst := rs::outStmtLst;
827 end for;
828
829 806 outStmtLst := listReverse(outStmtLst);
830 end traverseBackendDAEExpsWhenOperatorWithSymbolicOperation;
831
832 public function collapseArrayExpressions
833 input output BackendDAE.BackendDAE dae;
834 algorithm
835
2/2
✓ Branch 0 taken 51482 times.
✓ Branch 1 taken 2181 times.
53663 for syst in dae.eqs loop
836 51482 BackendEquation.traverseEquationArray_WithUpdate(syst.orderedEqs, function traverseBackendDAEExpsEqnWithSymbolicOperation(func=collapseArrayCrefExp), 0);
837 51482 BackendEquation.traverseEquationArray_WithUpdate(syst.removedEqs, function traverseBackendDAEExpsEqnWithSymbolicOperation(func=collapseArrayCrefExp), 0);
838 end for;
839 end collapseArrayExpressions;
840
841 public function collapseArrayCrefExp<T>
842 input DAE.Exp inExp;
843 input tuple<list<DAE.SymbolicOperation>, T> inTpl;
844 output DAE.Exp outExp;
845 output tuple<list<DAE.SymbolicOperation>, T> outTpl;
846 protected
847 list<DAE.SymbolicOperation> ops;
848 T t;
849 algorithm
850 369974 (ops,t) := inTpl;
851 369974 (outExp,t) := Expression.traverseExpTopDown(inExp, collapseArrayCrefExpWork, t);
852
2/2
✓ Branch 1 taken 366 times.
✓ Branch 2 taken 369608 times.
369974 if not ExpressionBasics.expEqual(inExp,outExp) then
853 // print("collapseArrayCrefExp: " + ExpressionBasics.printExpStr(inExp) + " -> " + ExpressionBasics.printExpStr(outExp) + "\n");
854 732 outTpl := (DAE.SIMPLIFY(DAE.PARTIAL_EQUATION(inExp),DAE.PARTIAL_EQUATION(outExp))::ops,t);
855 else
856 outTpl := inTpl;
857 end if;
858 end collapseArrayCrefExp;
859
860 protected function collapseArrayCrefExpWork<T>
861 input output DAE.Exp e;
862 output Boolean cont;
863 input output T t;
864 algorithm
865 (e,cont) := matchcontinue e
866 263 case DAE.MATRIX() then (collapseArrayCrefExpWork2(e),false);
867 8819 case DAE.ARRAY() then (collapseArrayCrefExpWork2(e),false);
868 2103757 else (e,true);
869 end matchcontinue;
870 end collapseArrayCrefExpWork;
871
872 protected function collapseArrayCrefExpWork2
873 input output DAE.Exp e;
874 protected
875 DAE.Type ty;
876 list<DAE.Dimension> dims;
877 list<Integer> ds;
878 Integer len, exp_count;
879 list<DAE.Exp> exps;
880 DAE.Exp exp1;
881 DAE.ComponentRef cr1,cr2;
882 list<DAE.Subscript> subs;
883 Integer ndim;
884 algorithm
885 (dims,ty) := match e
886 case DAE.MATRIX(ty=ty as DAE.T_ARRAY(dims=dims)) then (dims,ty);
887 case DAE.ARRAY(ty=ty as DAE.T_ARRAY(dims=dims)) then (dims,ty);
888 end match;
889 () := match Types.arrayElementType(ty)
890 // TODO: Figure out why the SimCode fails if we collapse arrays of records...
891 4 case DAE.T_COMPLEX() then fail();
892 else ();
893 end match;
894 9040 ds := Expression.dimensionsSizes(dims);
895 9040 ndim := listLength(ds);
896
4/4
✓ Branch 0 taken 9692 times.
✓ Branch 1 taken 9040 times.
✓ Branch 2 taken 9692 times.
✓ Branch 3 taken 9040 times.
18732 len := product(i for i in ds);
897
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 8837 times.
9040 true := len > 0;
898 //(DAE.CREF(componentRef=cr1)::exps) := Expression.flattenArrayExpToList(e); // TODO: Use a better routine? We now get all expressions even if no expression is a cref...
899
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8837 times.
8837 exp1::exps := Expression.flattenArrayExpToList(e);
900
2/2
✓ Branch 0 taken 5301 times.
✓ Branch 1 taken 3536 times.
8837 DAE.CREF(componentRef=cr1) := exp1;
901 // Check that the first element starts at index [1,...,1]
902 3536 subs := ComponentReference.crefLastSubs(cr1);
903
2/2
✓ Branch 1 taken 871 times.
✓ Branch 2 taken 2665 times.
3536 true := ndim==listLength(subs);
904
2/2
✓ Branch 3 taken 625 times.
✓ Branch 4 taken 2040 times.
2665 true := listLength(subs) == listLength(ComponentReferenceBasics.crefSubs(cr1)) "Code generation fails for things like x[7].y when x[7] contains more things than y, and y is an array...";
905
2/2
✓ Branch 0 taken 853 times.
✓ Branch 1 taken 613 times.
1466 for sub in subs loop
906
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 853 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 851 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 841 times.
853 DAE.INDEX(DAE.ICONST(1)) := sub;
907 end for;
908
909 // Same number of expressions as expected...
910 613 exp_count := listLength(exps) + 1;
911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 613 times.
613 true := exp_count == len;
912
913 // Check that the number of expressions matches the size of the array the cref represents.
914 613 dims := TypesDump.getDimensions(ComponentReference.crefLastType(cr1));
915
6/6
✓ Branch 1 taken 841 times.
✓ Branch 2 taken 613 times.
✓ Branch 3 taken 841 times.
✓ Branch 4 taken 613 times.
✓ Branch 5 taken 492 times.
✓ Branch 6 taken 121 times.
1454 true := exp_count == product(i for i in Expression.dimensionsSizes(dims));
916
917
2/2
✓ Branch 0 taken 2883 times.
✓ Branch 1 taken 383 times.
3266 for exp in exps loop
918
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2875 times.
2883 DAE.CREF(componentRef=cr2) := exp;
919
2/2
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2870 times.
2875 true := ndim==listLength(ComponentReference.crefLastSubs(cr2));
920
2/2
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 2774 times.
2870 true := ComponentReferenceBasics.crefEqualWithoutSubs(cr1,cr2);
921
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2774 times.
2774 true := 1==ComponentReferenceBasics.crefCompareIntSubscript(cr2,cr1); // cr2 > cr1
922 cr1 := cr2;
923 end for;
924 // All of the crefs are in ascending order; the first one starts at 1,1; the length is the full array... So it is the complete cref!
925 383 e := Expression.makeCrefExp(ComponentReferenceBasics.crefStripLastSubs(cr1), ty);
926 end collapseArrayCrefExpWork2;
927
928 annotation(__OpenModelica_Interface="backend");
929 end BackendDAETransform;
930