Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 59.8% 134 / 0 / 224
Functions: -% 0 / 1 / 1
Branches: 51.2% 43 / 0 / 84

OMCompiler/Compiler/FrontEnd/CheckModel.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 CheckModel "
37 file: CheckModel.mo
38 package: CheckModel
39 description: Check the Model.
40
41 "
42
43 public import Absyn;
44 public import DAE;
45
46 protected import BaseHashSet;
47 protected import ClassInf;
48 protected import ComponentReference;
49 protected import ComponentReferenceBasics;
50 protected import DAEDump;
51 protected import DAEUtil;
52 protected import Debug;
53 protected import ExecStat;
54 protected import Expression;
55 protected import Flags;
56 protected import HashSet;
57 protected import List;
58 protected import PrefixUtil;
59 protected import Util;
60 protected import Error;
61
62 public function checkModel "This function perform a model check. Count Variables and equations and
63 detect the simple equations."
64 input DAE.DAElist inDAELst;
65 output Integer varSize;
66 output Integer eqnSize;
67 output Integer simpleEqnSize;
68 protected
69 list<DAE.Element> eqns, lst;
70 HashSet.HashSet hs;
71 Boolean debug_dump = Flags.isSet(Flags.DUMP_CHECK_MODEL);
72 CountVarEqnFoldArg arg;
73 algorithm
74 82 ExecStat.execStat("CheckModel - start counting");
75 82 DAE.DAE(lst) := inDAELst;
76 82 hs := HashSet.emptyHashSet();
77 82 (varSize, eqnSize, eqns, hs) := countVarEqnSizeList(lst, (0, 0, {}, hs), debug_dump);
78 82 simpleEqnSize := countSimpleEqnSize(eqns, 0, hs);
79 82 ExecStat.execStat("CheckModel - end counting");
80 end checkModel;
81
82 protected type CountVarEqnFoldArg =
83 tuple<Integer/*varSize*/, Integer/*eqnSize*/, list<DAE.Element>/*eqns*/, HashSet.HashSet/*vars*/>;
84
85 protected function countVarEqnSizeList
86 input list<DAE.Element> elements;
87 input output CountVarEqnFoldArg arg;
88 input Boolean debugDump;
89 algorithm
90
2/2
✓ Branch 0 taken 180208 times.
✓ Branch 1 taken 174 times.
180382 for e in elements loop
91 180208 arg := countVarEqnSize(e, arg, debugDump);
92 end for;
93 end countVarEqnSizeList;
94
95 protected function countVarEqnSize
96 input DAE.Element element;
97 input CountVarEqnFoldArg inArg;
98 input Boolean debugDump;
99 output CountVarEqnFoldArg outArg;
100 algorithm
101 outArg := match element
102 local
103 DAE.Exp e;
104 DAE.ComponentRef cr;
105 DAE.ElementSource source;
106 Integer varSize, eqnSize, size;
107 list<DAE.Element> eqns, daeElts;
108 HashSet.HashSet hs;
109 DAE.Algorithm alg;
110 list<DAE.ComponentRef> crlst;
111 DAE.Type tp;
112 DAE.Element elem;
113
114 // external Objects
115 case DAE.EXTOBJECTCLASS()
116 then inArg;
117
118 // external Variables
119 case DAE.VAR(ty = DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ()))
120 then inArg;
121
122 // parameter variables
123 case DAE.VAR(kind = DAE.PARAM())
124 then inArg;
125
126 // constant variables
127 case DAE.VAR(kind = DAE.CONST())
128 then inArg;
129
130 // continuous/discrete variables
131 case DAE.VAR(componentRef=cr)
132 algorithm
133 98227 (varSize, eqnSize, eqns, hs) := inArg;
134 98227 size := Expression.sizeOf(element.ty);
135 98227 varSize := varSize + size;
136 98227 dumpVar(cr, size, debugDump);
137
138
3/4
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 98226 times.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
98227 if DAEUtil.isInput(element) and DAEUtil.isPublicVar(element) then
139 1 eqnSize := eqnSize + size;
140 1 dumpEqn(element, size, debugDump);
141 else
142
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 98226 times.
✓ Branch 2 taken 7221 times.
✓ Branch 3 taken 91005 times.
98226 if isSome(element.binding) then
143 7221 eqnSize := eqnSize + size;
144 7221 elem := DAE.EQUATION(Expression.crefExp(element.componentRef), Util.getOption(element.binding), element.source);
145 7221 dumpEqn(elem, size, debugDump);
146 eqns := elem :: eqns;
147 end if;
148
149 98226 hs := BaseHashSet.add(cr, hs);
150 end if;
151 98227 then
152 (varSize, eqnSize, eqns, hs);
153
154 // equations
155 case DAE.EQUATION(exp=e)
156 algorithm
157 17542 (varSize, eqnSize, eqns, hs) := inArg;
158 17542 size := Expression.sizeOf(Expression.typeof(e));
159 17542 dumpEqn(element, size, debugDump);
160 17542 then (varSize, eqnSize+size, element::eqns, hs);
161
162 // initial equations
163 case DAE.INITIALEQUATION()
164 then inArg;
165
166 // effort variable equality equations
167 case DAE.EQUEQUATION(cr1 = cr)
168 algorithm
169 22729 (varSize, eqnSize, eqns, hs) := inArg;
170 22729 tp := ComponentReference.crefTypeConsiderSubs(cr);
171 22729 size := Expression.sizeOf(tp);
172 22729 dumpEqn(element, size, debugDump);
173 22729 then (varSize, eqnSize+size, element::eqns, hs);
174
175 // a solved equation
176 case DAE.DEFINE(componentRef = cr)
177 algorithm
178 ✗ (varSize, eqnSize, eqns, hs) := inArg;
179 ✗ tp := ComponentReference.crefTypeConsiderSubs(cr);
180 ✗ size := Expression.sizeOf(tp);
181 ✗ dumpEqn(element, size, debugDump);
182 ✗ then (varSize, eqnSize+size, element::eqns, hs);
183
184 // complex equations
185 case DAE.COMPLEX_EQUATION(lhs = e)
186 algorithm
187 664 (varSize, eqnSize, eqns, hs) := inArg;
188 664 size := Expression.sizeOf(Expression.typeof(e));
189 664 dumpEqn(element, size, debugDump);
190 664 then (varSize, eqnSize+size, element::eqns, hs);
191
192 // complex initial equations
193 case DAE.INITIAL_COMPLEX_EQUATION()
194 then inArg;
195
196 // array equations
197 case DAE.ARRAY_EQUATION()
198 algorithm
199 11424 (varSize, eqnSize, eqns, hs) := inArg;
200 11424 size := Expression.sizeOf(Expression.typeof(element.exp));
201 11424 dumpEqn(element, size, debugDump);
202 11424 then (varSize, eqnSize+size, element::eqns, hs);
203
204 // initial array equations
205 case DAE.INITIAL_ARRAY_EQUATION()
206 then inArg;
207
208 // when equations
209 case DAE.WHEN_EQUATION(equations = daeElts)
210 algorithm
211 3 (varSize, eqnSize, eqns, hs) := inArg;
212 3 (_, size, _, _) := countVarEqnSizeList(daeElts, (0, 0, {}, hs), false);
213 3 dumpEqn(element, size, debugDump);
214 3 then (varSize, eqnSize+size, eqns, hs);
215
216 case DAE.INITIAL_FOR_EQUATION()
217 algorithm
218 ✗ (varSize, eqnSize, eqns, hs) := inArg;
219 ✗ (_, size, _, _) := countVarEqnSizeList(element.equations, (0, 0, {}, hs), false);
220 ✗ size := size * Expression.sizeOf(Expression.typeof(element.range));
221 ✗ dumpEqn(element, size, debugDump);
222 ✗ then
223 (varSize, eqnSize+size, eqns, hs);
224
225 case DAE.FOR_EQUATION()
226 algorithm
227 ✗ (varSize, eqnSize, eqns, hs) := inArg;
228 ✗ (_, size, _, _) := countVarEqnSizeList(element.equations, (0, 0, {}, hs), false);
229 ✗ size := size * Expression.sizeOf(Expression.typeof(element.range));
230 ✗ dumpEqn(element, size, debugDump);
231 ✗ then
232 (varSize, eqnSize+size, eqns, hs);
233
234 // if equation with condition false and no else
235 case DAE.IF_EQUATION(condition1 = {DAE.BCONST(false)}, equations3 = {})
236 then inArg;
237
238 // if equation
239 case DAE.IF_EQUATION(equations2 = daeElts::_)
240 algorithm
241 7 (varSize, eqnSize, eqns, hs) := inArg;
242 7 (_, size, _, _) := countVarEqnSizeList(daeElts, (0, 0, {}, hs), false);
243 7 dumpEqn(element, size, debugDump);
244 7 then (varSize, eqnSize+size, eqns, hs);
245
246 // initial if equation with condition false and no else
247 case DAE.INITIAL_IF_EQUATION(condition1 = {DAE.BCONST(false)}, equations3 = {})
248 then inArg;
249
250 // initial if equation
251 case DAE.INITIAL_IF_EQUATION()
252 then inArg;
253
254 // algorithm
255 case DAE.ALGORITHM(algorithm_ = alg, source = source)
256 algorithm
257 6 (varSize, eqnSize, eqns, hs) := inArg;
258 6 crlst := checkAndGetAlgorithmOutputs(alg, source, DAE.EXPAND());
259 6 size := listLength(crlst);
260 6 dumpEqn(element, size, debugDump);
261 6 then
262 (varSize, eqnSize+size, eqns, hs);
263
264 // initial algorithm
265 case DAE.INITIALALGORITHM()
266 then inArg;
267
268 // flat class / COMP
269 case DAE.COMP(dAElist = daeElts)
270 82 then countVarEqnSizeList(daeElts, inArg, debugDump);
271
272 // reinit
273 case DAE.REINIT()
274 then inArg;
275
276 // assert in equation
277 case DAE.ASSERT()
278 then inArg;
279
280 // assert in equation
281 case DAE.INITIAL_ASSERT()
282 then inArg;
283
284 // terminate in equation section is converted to ALGORITHM
285 case DAE.TERMINATE()
286 then inArg;
287
288 case DAE.INITIAL_TERMINATE()
289 then inArg;
290
291 case DAE.NORETCALL()
292 then inArg;
293
294 case DAE.INITIAL_NORETCALL()
295 then inArg;
296
297 // constraint (Optimica) Just pass the constraints for now. Should anything more be done here?
298 case DAE.CONSTRAINT()
299 then inArg;
300
301 // flat state machine section
302 case DAE.FLAT_SM(dAElist = daeElts)
303 ✗ then countVarEqnSizeList(daeElts, inArg, debugDump);
304
305 // a state/mode component in a state machine
306 case DAE.SM_COMP(dAElist = daeElts)
307 ✗ then countVarEqnSizeList(daeElts, inArg, debugDump);
308
309 else
310 algorithm
311 // show only on failtrace!
312 ✗ true := Flags.isSet(Flags.FAILTRACE);
313 ✗ Debug.traceln("- CheckModel.countVarEqnSize failed on: " + DAEDump.dumpElementsStr({element}));
314 ✗ then
315 fail();
316 end match;
317 end countVarEqnSize;
318
319 protected function dumpVar
320 input DAE.ComponentRef cref;
321 input Integer size;
322 input Boolean dump;
323 algorithm
324
1/2
✓ Branch 0 taken 98227 times.
✗ Branch 1 not taken.
98227 if dump then
325 ✗ print("[var: " + String(size) + "] " + ComponentReferenceBasics.printComponentRefStr(cref) + "\n");
326 end if;
327 end dumpVar;
328
329 protected function dumpEqn
330 input DAE.Element eqn;
331 input Integer size;
332 input Boolean dump;
333 algorithm
334
1/2
✓ Branch 0 taken 59597 times.
✗ Branch 1 not taken.
59597 if dump then
335 ✗ print("[eqn: " + String(size) + "] " + DAEDump.dumpEquationStr(eqn));
336 end if;
337 end dumpEqn;
338
339 public function checkAndGetAlgorithmOutputs
340 "mahge:
341 counts the ouputs of algorithms depending on where the
342 section came from. If the algorithm section came from a scalar
343 component the it is counted acorrding to the inCrefExpansionRule.
344 However in some cases where algorithms come from a member of an array
345 of components expanding arrays and counting them as full in every
346 algorithm secion will cause duplicate countings.
347 See spec 3.3 Modelica spec 3.3 rev 11.1.2 and ticket 2452
348 "
349 input DAE.Algorithm inAlgorithm;
350 input DAE.ElementSource inSource;
351 input DAE.Expand inCrefExpansionRule;
352 output list<DAE.ComponentRef> outCrefLst;
353 algorithm
354 outCrefLst := matchcontinue inSource
355 local
356
357 case DAE.SOURCE(instance = DAE.NOCOMPPRE())
358 1662 then algorithmOutputs(inAlgorithm, inCrefExpansionRule);
359
360 // the algorithm came from a component that is member of an array or not
361 case DAE.SOURCE()
362
2/2
✓ Branch 1 taken 106 times.
✓ Branch 2 taken 512 times.
618 then
363 if PrefixUtil.hasSubs(inSource.instance)
364 then algorithmOutputs(inAlgorithm, DAE.NOT_EXPAND())
365 else algorithmOutputs(inAlgorithm, inCrefExpansionRule);
366
367 else
368 algorithm
369 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"checkAndGetAlgorithmOutputs failed."});
370 ✗ then fail();
371 end matchcontinue;
372 end checkAndGetAlgorithmOutputs;
373
374 public function isCrefListAlgorithmOutput
375 "This function verfies if all crefs in crefList are outputs
376 of the passed algorithm"
377 input list<DAE.ComponentRef> crefList;
378 input DAE.Algorithm inAlgorithm;
379 input DAE.ElementSource inSource;
380 input DAE.Expand inCrefExpansionRule;
381 output Boolean outResult = false;
382 protected
383 HashSet.HashSet ht = HashSet.emptyHashSet();
384 list<DAE.ComponentRef> algOutCrefs;
385 algorithm
386 505 algOutCrefs := CheckModel.checkAndGetAlgorithmOutputs(inAlgorithm, inSource, inCrefExpansionRule);
387 505 ht := List.fold(algOutCrefs, BaseHashSet.add, ht);
388
2/2
✓ Branch 0 taken 2200 times.
✓ Branch 1 taken 502 times.
2702 for cr in crefList loop
389
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2197 times.
2200 if not BaseHashSet.has(cr, ht) then
390 3 return;
391 end if;
392 end for;
393 outResult := true;
394 end isCrefListAlgorithmOutput;
395
396 protected function algorithmOutputs "This function finds the the outputs of an algorithm.
397 An input is all values that are reffered on the right hand side of any
398 statement in the algorithm and an output is a variables belonging to the
399 variables that are assigned a value in the algorithm. If a variable is an
400 input and an output it will be treated as an output."
401 input DAE.Algorithm inAlgorithm;
402 input DAE.Expand inCrefExpansion "expand array to full dimension?";
403 output list<DAE.ComponentRef> outCrefLst;
404 protected
405 list<DAE.Statement> stmts;
406 algorithm
407 2280 DAE.ALGORITHM_STMTS(statementLst=stmts) := inAlgorithm;
408 2280 outCrefLst := algorithmStatementListOutputs(stmts, inCrefExpansion);
409 end algorithmOutputs;
410
411 public function algorithmStatementListOutputs "This function finds the the outputs of an algorithm.
412 An input is all values that are reffered on the right hand side of any
413 statement in the algorithm and an output is a variables belonging to the
414 variables that are assigned a value in the algorithm. If a variable is an
415 input and an output it will be treated as an output."
416 input list<DAE.Statement> inStmts;
417 input DAE.Expand inCrefExpansion "expand array to full dimension?";
418 output list<DAE.ComponentRef> outCrefLst;
419 protected
420 HashSet.HashSet hs;
421 algorithm
422 11300 hs := HashSet.emptyHashSet();
423 11300 hs := List.fold1(inStmts, statementOutputs, inCrefExpansion, hs);
424 11300 outCrefLst := BaseHashSet.hashSetList(hs);
425 end algorithmStatementListOutputs;
426
427 protected function statementOutputs "Helper relation to algorithmOutputs"
428 input DAE.Statement inStatement;
429 input DAE.Expand inCrefExpansion "expand array to full dimension?";
430 input HashSet.HashSet iht;
431 output HashSet.HashSet oht;
432 algorithm
433 oht := matchcontinue inStatement
434 local
435 HashSet.HashSet ht;
436 DAE.ComponentRef cr;
437 list<DAE.ComponentRef> crlst;
438 DAE.Exp e, exp1;
439 DAE.Statement stmt;
440 list<DAE.Statement> stmts;
441 DAE.Else elsebranch;
442 list<DAE.Exp> expl;
443 DAE.Type tp;
444 DAE.Ident iteratorName;
445 String str;
446 list<DAE.Subscript> subs;
447
448 // a := expr;
449 case DAE.STMT_ASSIGN(exp1 = exp1)
450 algorithm
451 38651 (_, (_, ht)) := Expression.traverseExpTopDown(exp1, statementOutputsCrefFinder, (inCrefExpansion, iht));
452 then ht;
453
454 // (a, b, ...) := expr;
455 case DAE.STMT_TUPLE_ASSIGN(expExpLst = expl)
456 algorithm
457 356 (_, (_, ht)) := Expression.traverseExpListTopDown(expl, statementOutputsCrefFinder, (inCrefExpansion, iht));
458 then ht;
459
460 // a := expr; // where a is array
461 case DAE.STMT_ASSIGN_ARR(lhs=exp1)
462 algorithm
463 // (_, (_, ht)) = Expression.traverseExpTopDown(exp1, statementOutputsCrefFinder, (inCrefExpansion, iht));
464 1622 cr := Expression.expCref(exp1);
465 1622 subs := ComponentReference.crefLastSubs(cr);
466
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1602 times.
1622 if not listEmpty(subs) // not an empty subs list
467 then
468 20 subs := List.fill(DAE.WHOLEDIM(), listLength(subs));
469 20 cr := ComponentReference.crefSetLastSubs(cr, subs);
470 end if;
471 1622 crlst := ComponentReference.expandCref(cr, true);
472 1622 ht := List.fold(crlst, BaseHashSet.add, iht);
473 then ht;
474
475 case DAE.STMT_IF(statementLst = stmts, else_ = elsebranch)
476 algorithm
477 6606 ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht);
478 6606 ht := statementElseOutputs(elsebranch, inCrefExpansion, ht);
479 then ht;
480
481 case DAE.STMT_FOR(type_=tp, iter = iteratorName, range = e, statementLst = stmts)
482 algorithm
483 // replace the iterator variable with the range expression
484 3545 cr := ComponentReferenceBasics.makeCrefIdent(iteratorName, tp, {});
485 3545 (stmts, _) := DAEUtil.traverseDAEEquationsStmts(stmts, Expression.traverseSubexpressionsHelper, (Expression.replaceCref, (cr, e)));
486 3545 ht := List.fold1(stmts, statementOutputs, DAE.EXPAND(), iht);
487 then ht;
488
489 case DAE.STMT_PARFOR(type_=tp, iter = iteratorName, range = e, statementLst = stmts)
490 algorithm
491 // replace the iterator variable with the range expression
492 ✗ cr := ComponentReferenceBasics.makeCrefIdent(iteratorName, tp, {});
493 ✗ (stmts, _) := DAEUtil.traverseDAEEquationsStmts(stmts, Expression.traverseSubexpressionsHelper, (Expression.replaceCref, (cr, e)));
494 ✗ ht := List.fold1(stmts, statementOutputs, DAE.EXPAND(), iht);
495 then ht;
496
497 case DAE.STMT_WHILE(statementLst = stmts)
498 algorithm
499 ✗ ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht);
500 then ht;
501
502 case DAE.STMT_WHEN(statementLst = stmts, elseWhen = NONE())
503 algorithm
504 2350 ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht);
505 then ht;
506
507 case DAE.STMT_WHEN(statementLst = stmts, elseWhen = SOME(stmt))
508 algorithm
509 1014 ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht);
510 1014 ht := statementOutputs(stmt, inCrefExpansion, ht);
511 then ht;
512
513 case DAE.STMT_ASSERT() then iht;
514 case DAE.STMT_TERMINATE() then iht;
515
516 // reinit is not a output
517 case DAE.STMT_REINIT() then iht;
518 case DAE.STMT_NORETCALL() then iht;
519 case DAE.STMT_RETURN(_) then iht;
520 case DAE.STMT_BREAK(_) then iht;
521 case DAE.STMT_CONTINUE(_) then iht;
522 case DAE.STMT_ARRAY_INIT() then iht;
523 // MetaModelica extension. KS
524 case DAE.STMT_FAILURE(body = stmts)
525 algorithm
526 ✗ ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht);
527 then ht;
528
529 else
530 algorithm
531 ✗ true := Flags.isSet(Flags.FAILTRACE);
532 ✗ str := DAEDump.ppStatementStr(inStatement);
533 ✗ Debug.traceln("- CheckModel.statementOutputs failed for " + str);
534 ✗ then
535 fail();
536
537 end matchcontinue;
538 end statementOutputs;
539
540 protected function statementElseOutputs "Helper function to statementOutputs"
541 input DAE.Else inElseBranch;
542 input DAE.Expand inCrefExpansion "expand array to full dimension?";
543 input HashSet.HashSet iht;
544 output HashSet.HashSet oht;
545 algorithm
546 oht := match inElseBranch
547 local
548 list<DAE.Statement> stmts;
549 DAE.Else elseBranch;
550 HashSet.HashSet ht;
551
552 case DAE.NOELSE() then iht;
553
554 case DAE.ELSEIF(statementLst=stmts, else_=elseBranch)
555 algorithm
556 2055 ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht);
557 2055 ht := statementElseOutputs(elseBranch, inCrefExpansion, ht);
558 then ht;
559
560 case DAE.ELSE(statementLst=stmts)
561 algorithm
562 1056 ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht);
563 then ht;
564 end match;
565 end statementElseOutputs;
566
567 protected function statementOutputsCrefFinder "author: Frenkel TUD 2012-06"
568 input DAE.Exp inExp;
569 input tuple<DAE.Expand, HashSet.HashSet> inTpl;
570 output DAE.Exp outExp;
571 output Boolean cont;
572 output tuple<DAE.Expand, HashSet.HashSet> outTpl;
573 algorithm
574 (outExp,cont,outTpl) := matchcontinue (inExp,inTpl)
575 local
576 DAE.Exp e, exp, e1, e2;
577 HashSet.HashSet ht;
578 DAE.ComponentRef cr, first_cref;
579 list<DAE.ComponentRef> crlst;
580 DAE.Expand expand;
581
582 // Skip wild
583 case (e as DAE.CREF(componentRef=DAE.WILD()), _)
584 then (e, false, inTpl);
585
586 // Skip time
587 case (e as DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time", subscriptLst={})), _)
588 then (e, false, inTpl);
589
590 // Skip external Objects
591 case (e as DAE.CREF(ty=DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ())), _)
592 then (e, false, inTpl);
593
594 // records are not arays, expand them always
595 case (e as DAE.CREF(componentRef=cr, ty=DAE.T_COMPLEX(complexClassType = ClassInf.RECORD())), (expand,ht))
596 algorithm
597 96 cr := ComponentReference.crefStripSubs(cr);
598 96 crlst := ComponentReference.expandCref(cr, true);
599 96 ht := List.fold(crlst, BaseHashSet.add, ht);
600 96 then (e, false, (expand,ht));
601
602 // NOT_EXPAND strategy (needed for equations translated to algorithms)
603 case (e as DAE.CREF(componentRef=cr), (expand as DAE.NOT_EXPAND(),ht))
604 algorithm
605 1489 ht := List.fold({cr}, BaseHashSet.add, ht);
606 1489 then (e, false, (expand,ht));
607
608 // EXPAND
609 /* mahge:
610 Modelica spec 3.3 rev 11.1.2
611 "If at least one element of an array appears on the left hand side of the assignment operator, then the
612 complete array is initialized in this algorithm section"
613 So we strip the all subs except for model subs and send the whole array to expansion. i.e. we consider the whole array as modified.
614 */
615 case (e as DAE.CREF(componentRef=cr), (expand,ht))
616 algorithm
617 37795 cr := ComponentReference.crefStripSubsExceptModelSubs(cr);
618 // check if first element already is in the set and only expand if not (saves a lot of expand work)
619 // ticket #7832
620 37795 first_cref := ComponentReference.crefArrayGetFirstCref(cr);
621
2/2
✓ Branch 1 taken 19460 times.
✓ Branch 2 taken 18335 times.
37795 if not BaseHashSet.has(first_cref, ht) then
622 19460 crlst := ComponentReference.expandCref(cr, true);
623 19460 ht := List.fold(crlst, BaseHashSet.add, ht);
624 end if;
625 37795 then (e, false, (expand,ht));
626
627 case (e as DAE.ASUB(exp=exp), _)
628 algorithm
629 ✗ (_, outTpl) := Expression.traverseExpTopDown(exp, statementOutputsCrefFinder, inTpl);
630 ✗ then (e, false, outTpl);
631
632 case (e as DAE.TSUB(exp=exp), _)
633 algorithm
634 ✗ (_, outTpl) := Expression.traverseExpTopDown(exp, statementOutputsCrefFinder, inTpl);
635 ✗ then (e, false, outTpl);
636
637 case (e as DAE.RELATION(), _)
638 then (e, false, inTpl);
639
640 case (e as DAE.RANGE(), _)
641 then (e, false, inTpl);
642
643 case (e as DAE.IFEXP(expThen=e1, expElse=e2), _)
644 algorithm
645 ✗ (_, outTpl) := Expression.traverseExpTopDown(e1, statementOutputsCrefFinder, inTpl);
646 ✗ (_, outTpl) := Expression.traverseExpTopDown(e2, statementOutputsCrefFinder, outTpl);
647 ✗ then (e, false, outTpl);
648
649 case (e, _) then (e, true, inTpl);
650
651 end matchcontinue;
652 end statementOutputsCrefFinder;
653
654 protected function countSimpleEqnSize
655 input list<DAE.Element> inEqns;
656 input Integer isimpleEqnSize;
657 input HashSet.HashSet ihs;
658 output Integer osimpleEqnSize;
659 algorithm
660 82 osimpleEqnSize := List.applyAndFold1(inEqns, intAdd, countSimpleEqnSizeWork, ihs, 0);
661 end countSimpleEqnSize;
662
663 protected function countSimpleEqnSizeWork
664 input DAE.Element inEqns;
665 input HashSet.HashSet ihs;
666 output Integer osimpleEqnSize;
667 algorithm
668 osimpleEqnSize := matchcontinue inEqns
669 local
670 DAE.Exp e1, e2;
671 DAE.ComponentRef cr;
672 DAE.Type tp;
673
674 // equations
675 case DAE.EQUATION(exp=e1, scalar=e2)
676 24746 then simpleEquation(e1, e2, ihs);
677
678 // effort variable equality equations
679 case DAE.EQUEQUATION(cr1 = cr)
680 algorithm
681 22727 tp := ComponentReference.crefTypeConsiderSubs(cr);
682 22727 then Expression.sizeOf(tp);
683
684 // a solved equation
685 case DAE.DEFINE(componentRef = cr, exp=e2)
686 algorithm
687 ✗ e1 := Expression.crefExp(cr);
688 ✗ then simpleEquation(e1, e2, ihs);
689
690 // complex equations
691 case DAE.COMPLEX_EQUATION(lhs = e1, rhs = e2)
692 664 then simpleEquation(e1, e2, ihs);
693
694 // array equations
695 case DAE.ARRAY_EQUATION(exp = e1, array = e2)
696 11424 then simpleEquation(e1, e2, ihs);
697
698 else 0;
699 end matchcontinue;
700 end countSimpleEqnSizeWork;
701
702 protected function simpleEquation
703 input DAE.Exp e1;
704 input DAE.Exp e2;
705 input HashSet.HashSet ihs;
706 output Integer osimpleEqnSize;
707 algorithm
708 osimpleEqnSize := matchcontinue(e1, e2)
709 local
710 list<DAE.Exp> ea1, ea2;
711 // a = b;
712 case (DAE.CREF(), DAE.CREF())
713 7628 then
714 Expression.sizeOf(Expression.typeof(e1));
715 // a = -b;
716 case (DAE.CREF(), DAE.UNARY(DAE.UMINUS(_), DAE.CREF()))
717 220 then
718 Expression.sizeOf(Expression.typeof(e1));
719 case (DAE.CREF(), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()))
720 ✗ then
721 Expression.sizeOf(Expression.typeof(e1));
722 // -a = b;
723 case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.CREF())
724 ✗ then
725 Expression.sizeOf(Expression.typeof(e1));
726 case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.CREF())
727 ✗ then
728 Expression.sizeOf(Expression.typeof(e1));
729 // a + b = 0
730 case (DAE.BINARY(DAE.CREF(), DAE.ADD(), DAE.CREF()), _)
731 algorithm
732
2/2
✓ Branch 1 taken 102 times.
✓ Branch 2 taken 2491 times.
2593 true := Expression.isZero(e2);
733 2491 then
734 Expression.sizeOf(Expression.typeof(e1));
735 case (DAE.BINARY(DAE.CREF(), DAE.ADD_ARR(), DAE.CREF()), _)
736 algorithm
737 ✗ true := Expression.isZero(e2);
738 ✗ then
739 Expression.sizeOf(Expression.typeof(e1));
740 // a - b = 0
741 case (DAE.BINARY(DAE.CREF(), DAE.SUB(), DAE.CREF()), _)
742 algorithm
743
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1930 times.
1931 true := Expression.isZero(e2);
744 1930 then
745 Expression.sizeOf(Expression.typeof(e1));
746 case (DAE.BINARY(DAE.CREF(), DAE.SUB_ARR(), DAE.CREF()), _)
747 algorithm
748 ✗ true := Expression.isZero(e2);
749 ✗ then
750 Expression.sizeOf(Expression.typeof(e1));
751 // -a + b = 0
752 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.ADD(), DAE.CREF()), _)
753 algorithm
754
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
99 true := Expression.isZero(e2);
755 99 then
756 Expression.sizeOf(Expression.typeof(e1));
757 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.ADD_ARR(), DAE.CREF()), _)
758 algorithm
759 ✗ true := Expression.isZero(e2);
760 ✗ then
761 Expression.sizeOf(Expression.typeof(e1));
762 // -a - b = 0
763 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.SUB(), DAE.CREF()), _)
764 algorithm
765 ✗ true := Expression.isZero(e2);
766 ✗ then
767 Expression.sizeOf(Expression.typeof(e1));
768 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.SUB_ARR(), DAE.CREF()), _)
769 algorithm
770 ✗ true := Expression.isZero(e2);
771 ✗ then
772 Expression.sizeOf(Expression.typeof(e1));
773 // 0 = a + b
774 case (_, DAE.BINARY(DAE.CREF(), DAE.ADD(), DAE.CREF()))
775 algorithm
776
2/2
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 907 times.
940 true := Expression.isZero(e1);
777 907 then
778 Expression.sizeOf(Expression.typeof(e1));
779 case (_, DAE.BINARY(DAE.CREF(), DAE.ADD_ARR(), DAE.CREF()))
780 algorithm
781 ✗ true := Expression.isZero(e1);
782 ✗ then
783 Expression.sizeOf(Expression.typeof(e1));
784 // 0 = a - b
785 case (_, DAE.BINARY(DAE.CREF(), DAE.SUB(), DAE.CREF()))
786 algorithm
787
1/2
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
360 true := Expression.isZero(e1);
788 ✗ then
789 Expression.sizeOf(Expression.typeof(e1));
790 case (_, DAE.BINARY(DAE.CREF(), DAE.SUB_ARR(), DAE.CREF()))
791 algorithm
792 ✗ true := Expression.isZero(e1);
793 ✗ then
794 Expression.sizeOf(Expression.typeof(e1));
795 // 0 = -a + b
796 case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.ADD(), DAE.CREF()))
797 algorithm
798 ✗ true := Expression.isZero(e1);
799 ✗ then
800 Expression.sizeOf(Expression.typeof(e1));
801 case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.ADD_ARR(), DAE.CREF()))
802 algorithm
803 ✗ true := Expression.isZero(e1);
804 ✗ then
805 Expression.sizeOf(Expression.typeof(e1));
806 // 0 = -a - b
807 case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.SUB(), DAE.CREF()))
808 algorithm
809 ✗ true := Expression.isZero(e1);
810 ✗ then
811 Expression.sizeOf(Expression.typeof(e1));
812 case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.SUB_ARR(), DAE.CREF()))
813 algorithm
814 ✗ true := Expression.isZero(e1);
815 ✗ then
816 Expression.sizeOf(Expression.typeof(e1));
817 // a = der(b);
818 case (DAE.CREF(), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}))
819 2524 then
820 Expression.sizeOf(Expression.typeof(e1));
821 // der(a) = b;
822 case (DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}), DAE.CREF())
823 6 then
824 Expression.sizeOf(Expression.typeof(e2));
825 // a = -der(b);
826 case (DAE.CREF(), DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})))
827 ✗ then
828 Expression.sizeOf(Expression.typeof(e1));
829 case (DAE.CREF(), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})))
830 ✗ then
831 Expression.sizeOf(Expression.typeof(e1));
832 // -der(a) = b;
833 case (DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.CREF())
834 ✗ then
835 Expression.sizeOf(Expression.typeof(e2));
836 case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.CREF())
837 ✗ then
838 Expression.sizeOf(Expression.typeof(e2));
839 // -a = der(b);
840 case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}))
841 ✗ then
842 Expression.sizeOf(Expression.typeof(e1));
843 case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}))
844 ✗ then
845 Expression.sizeOf(Expression.typeof(e1));
846 // der(a) = -b;
847 case (DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}), DAE.UNARY(DAE.UMINUS(_), DAE.CREF()))
848 1 then
849 Expression.sizeOf(Expression.typeof(e2));
850 case (DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()))
851 ✗ then
852 Expression.sizeOf(Expression.typeof(e2));
853 // -a = -der(b);
854 case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})))
855 ✗ then
856 Expression.sizeOf(Expression.typeof(e1));
857 case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})))
858 ✗ then
859 Expression.sizeOf(Expression.typeof(e1));
860 // -der(a) = -b;
861 case (DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.UNARY(DAE.UMINUS(_), DAE.CREF()))
862 ✗ then
863 Expression.sizeOf(Expression.typeof(e2));
864 case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()))
865 ✗ then
866 Expression.sizeOf(Expression.typeof(e2));
867
868 // a = const;
869 case (DAE.CREF(), _)
870 algorithm
871
2/2
✓ Branch 1 taken 6880 times.
✓ Branch 2 taken 11184 times.
18064 true := Expression.isConst(e2);
872 11184 then
873 Expression.sizeOf(Expression.typeof(e1));
874 // const = a;
875 case (_, DAE.CREF())
876 algorithm
877
2/2
✓ Branch 1 taken 136 times.
✓ Branch 2 taken 43 times.
179 true := Expression.isConst(e1);
878 43 then
879 Expression.sizeOf(Expression.typeof(e2));
880
881 // -a = const;
882 case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), _)
883 algorithm
884
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 true := Expression.isConst(e2);
885 ✗ then
886 Expression.sizeOf(Expression.typeof(e1));
887 case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), _)
888 algorithm
889 ✗ true := Expression.isConst(e2);
890 ✗ then
891 Expression.sizeOf(Expression.typeof(e1));
892 // const = -a;
893 case (_, DAE.UNARY(DAE.UMINUS(_), DAE.CREF()))
894 algorithm
895
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Expression.isConst(e1);
896 ✗ then
897 Expression.sizeOf(Expression.typeof(e2));
898 case (_, DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()))
899 algorithm
900 ✗ true := Expression.isConst(e1);
901 ✗ then
902 Expression.sizeOf(Expression.typeof(e2));
903
904 case(_, _)
905 algorithm
906
3/4
✓ Branch 1 taken 9678 times.
✓ Branch 2 taken 123 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9678 times.
9801 true := Expression.isArray(e1) or Expression.isMatrix(e1);
907
2/4
✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 123 times.
✗ Branch 5 not taken.
123 true := Expression.isArray(e2) or Expression.isMatrix(e2);
908 ✗ ea1 := Expression.flattenArrayExpToList(e1);
909 ✗ ea2 := Expression.flattenArrayExpToList(e2);
910 ✗ then
911 simpleEquations(ea1, ea2, 0, ihs);
912
913 case(_, _)
914 algorithm
915
4/4
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 9493 times.
✓ Branch 5 taken 9367 times.
✓ Branch 6 taken 126 times.
9801 (_, (_, _::{})) := Expression.traverseExpBottomUp(Expression.expSub(e1, e2), traversingComponentRefFinder, (ihs, {}));
916 126 then
917 Expression.sizeOf(Expression.typeof(e1));
918
919 else
920 then
921 0;
922 end matchcontinue;
923 end simpleEquation;
924
925 protected function traversingComponentRefFinder
926 input DAE.Exp inExp;
927 input tuple<HashSet.HashSet, list<DAE.ComponentRef>> inTpl;
928 output DAE.Exp outExp;
929 output tuple<HashSet.HashSet, list<DAE.ComponentRef>> outTpl;
930 algorithm
931 (outExp,outTpl) := matchcontinue (inExp,inTpl)
932 local
933 HashSet.HashSet hs;
934 list<DAE.ComponentRef> crefs, crlst;
935 DAE.ComponentRef cr;
936 DAE.Exp e;
937
938 case (DAE.CREF(componentRef = DAE.WILD()), _)
939 then (inExp,inTpl);
940
941 case (e as DAE.CREF(componentRef=cr), (hs, crefs))
942 algorithm
943 49741 crlst := ComponentReference.expandCref(cr, true);
944 49741 crefs := getcr(crlst, hs, crefs);
945 49741 then (e, (hs, crefs));
946
947 else (inExp,inTpl);
948
949 end matchcontinue;
950 end traversingComponentRefFinder;
951
952 protected function getcr
953 input list<DAE.ComponentRef> crefs;
954 input HashSet.HashSet hs;
955 input list<DAE.ComponentRef> iAcc;
956 output list<DAE.ComponentRef> oAcc;
957 algorithm
958 oAcc := match crefs
959 local
960 DAE.ComponentRef cr;
961 list<DAE.ComponentRef> rest, crlst;
962 case {} then iAcc;
963 case cr::rest guard BaseHashSet.has(cr, hs)
964 algorithm
965 75078 crlst := List.unionEltOnTrue(cr, iAcc, ComponentReferenceBasics.crefEqual);
966 75078 then
967 getcr(rest, hs, crlst);
968 case _::rest
969 12041 then
970 getcr(rest, hs, iAcc);
971 end match;
972 end getcr;
973
974 protected function simpleEquations
975 input list<DAE.Exp> e1lst;
976 input list<DAE.Exp> e2lst;
977 input Integer isimpleEqnSize;
978 input HashSet.HashSet ihs;
979 output Integer osimpleEqnSize;
980 algorithm
981 osimpleEqnSize := match(e1lst, e2lst)
982 local
983 DAE.Exp e1, e2;
984 list<DAE.Exp> r1, r2;
985 Integer size;
986 case ({}, {}) then isimpleEqnSize;
987 case (e1::r1, e2::r2)
988 algorithm
989 ✗ size := simpleEquation(e1, e2, ihs);
990 ✗ then
991 simpleEquations(r1, r2, size+isimpleEqnSize, ihs);
992 end match;
993 end simpleEquations;
994
995 annotation(__OpenModelica_Interface="frontend");
996 end CheckModel;
997