Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 64.9% 2472 / 0 / 3808
Functions: -% 0 / 1 / 1
Branches: 57.9% 1118 / 0 / 1930

OMCompiler/Compiler/SimCode/SimCodeUtil.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 SimCodeUtil
37 " file: SimCodeUtil.mo
38 package: SimCodeUtil
39 description: Code generation using Susan templates
40
41 The entry points to this module are the functions createSimCode and
42 createFunctions."
43
44
45 // public imports
46 public
47 import Absyn;
48 import AvlTreePathFunction;
49 import ExpressionBasics;
50 import FCore;
51 import FGraph;
52 import ProgramUtil;
53 import BackendDAE;
54 import Ceval;
55 import DAE;
56 import DoubleEnded;
57 import File;
58 import HashTable;
59 import HashTableCrIListArray;
60 import HashTableCrILst;
61 import SCode;
62 import SCodeUtil;
63 import SimCode;
64 import SimCodeFunction;
65 import SimCodeVar;
66 import Tpl;
67 import Types;
68 import Unit = NFUnit;
69 import Values;
70 import HashSetString;
71
72 // protected imports
73 protected
74 import AbsynUtil;
75 import Array;
76 import Autoconf;
77 import AvlSetInt;
78 import AvlSetString;
79 import AvlTreeCRToInt;
80 import BackendDAEOptimize;
81 import BackendDAETransform;
82 import BackendDAEUtil;
83 import BackendDump;
84 import BackendEquation;
85 import BackendVariable;
86 import BackendVarTransform;
87 import BaseHashSet;
88 import BaseHashTable;
89 import Builtin;
90 import CheckModel;
91 import ClassInf;
92 import ClockIndexes;
93 import CommonSubExpression.isCSECref;
94 import ComponentReference;
95 import ComponentReferenceBasics;
96 import Config;
97 import DAEDump;
98 import DAEUtil;
99 import Debug;
100 import Differentiate;
101 import ElementSource;
102 import Error;
103 import ExecStat.execStat;
104 import Expression;
105 import ExpressionDump;
106 import ExpressionSimplify;
107 import ExpressionSolve;
108 import Flags;
109 import FlagsUtil;
110 import FMI;
111 import GCExt;
112 import Global;
113 import Graph;
114 import HashSet;
115 import HashSetExp;
116 import HashTableCrefSimVar;
117 import HashTableSimCodeEqCache;
118 import HpcOmSimCode;
119 import Inline;
120 import List;
121 import Matching;
122 import MetaModelica.Dangerous;
123 import Mutable;
124 import PriorityQueue;
125 import SemanticVersion;
126 import SimCodeDump;
127 import SimCodeFunctionUtil;
128 import SimCodeUtilShared;
129 import Static;
130 import StringUtil;
131 import SymbolicJacobian;
132 import SymbolTable;
133 import System;
134 import TypesDump;
135 import Util;
136 import ValuesUtil;
137 import VisualXML;
138 import FindZeroCrossings;
139 import ZeroCrossings;
140 import ReduceDAE;
141 import Settings;
142 import UnorderedMap;
143 import UnorderedSet;
144 import SimCodeCodegenUtil;
145
146 protected constant String UNDERLINE = "========================================";
147
148 public function hashEqSystem
149 input SimCode.SimEqSystem eq;
150 output Integer hash;
151 algorithm
152 hash := match eq
153 local
154 DAE.Statement stmt;
155 28 case SimCode.SES_RESIDUAL() then ExpressionBasics.hashExp(eq.exp);
156 ✗ case SimCode.SES_FOR_RESIDUAL() then ExpressionBasics.hashExp(eq.exp); // also hash the indices?
157 ✗ case SimCode.SES_GENERIC_RESIDUAL() then ExpressionBasics.hashExp(eq.exp); // also hash the indices?
158 665032 case SimCode.SES_SIMPLE_ASSIGN() then ComponentReferenceBasics.hashComponentRef(eq.cref)+7*ExpressionBasics.hashExp(eq.exp);
159 ✗ case SimCode.SES_SIMPLE_ASSIGN_CONSTRAINTS() then ComponentReferenceBasics.hashComponentRef(eq.cref)+7*ExpressionBasics.hashExp(eq.exp);
160 1693 case SimCode.SES_ARRAY_CALL_ASSIGN() then ExpressionBasics.hashExp(eq.lhs)+7*ExpressionBasics.hashExp(eq.exp);
161 35250 case SimCode.SES_ALGORITHM(statements={stmt as DAE.STMT_ASSERT()}) then ExpressionBasics.hashExp(stmt.cond)+7*ExpressionBasics.hashExp(stmt.msg)+49*ExpressionBasics.hashExp(stmt.level);
162 // Whatever; we're not caching these values anyway
163 5979 else valueConstructor(eq);
164 end match;
165 end hashEqSystem;
166
167 public function compareEqSystemsEquality "Is true if the equations are the same except the index. If false they might still be the same."
168 input SimCode.SimEqSystem eq1;
169 input SimCode.SimEqSystem eq2;
170 output Boolean b;
171 algorithm
172 b := match (eq1,eq2)
173 local
174 DAE.Statement stmt1,stmt2;
175 case (SimCode.SES_SIMPLE_ASSIGN(),SimCode.SES_SIMPLE_ASSIGN())
176
2/2
✓ Branch 1 taken 275140 times.
✓ Branch 2 taken 136295 times.
411435 then if 0==ComponentReferenceBasics.crefCompareGeneric(eq1.cref, eq2.cref) then ExpressionBasics.expEqual(eq1.exp, eq2.exp) else false;
177 case (SimCode.SES_ARRAY_CALL_ASSIGN(),SimCode.SES_ARRAY_CALL_ASSIGN())
178
2/2
✓ Branch 1 taken 829 times.
✓ Branch 2 taken 30 times.
859 then if ExpressionBasics.expEqual(eq1.lhs, eq2.lhs) then ExpressionBasics.expEqual(eq1.exp, eq2.exp) else false;
179 case (SimCode.SES_ALGORITHM(statements={stmt1 as DAE.STMT_ASSERT()}),SimCode.SES_ALGORITHM(statements={stmt2 as DAE.STMT_ASSERT()}))
180 ✗ then if ExpressionBasics.expEqual(stmt1.cond, stmt2.cond) then (if ExpressionBasics.expEqual(stmt1.msg, stmt2.msg) then ExpressionBasics.expEqual(stmt1.level, stmt2.level) else false) else false;
181 else false;
182 end match;
183 end compareEqSystemsEquality;
184
185 // =============================================================================
186 // section to create SimCode from BackendDAE
187 //
188 // =============================================================================
189
190 protected function setTimeIndependentVars
191 "Records the known variables that are not parameters: the backend only
192 computes them at initialization."
193 input BackendDAE.Variables knownVars;
194 protected
195 UnorderedSet<DAE.ComponentRef> vars = UnorderedSet.new(ComponentReferenceBasics.hashComponentRef, ComponentReferenceBasics.crefEqual);
196 algorithm
197
2/2
✓ Branch 1 taken 181394 times.
✓ Branch 2 taken 1060 times.
182454 for v in BackendVariable.varList(knownVars) loop
198
4/4
✓ Branch 1 taken 42371 times.
✓ Branch 2 taken 139023 times.
✓ Branch 4 taken 42086 times.
✓ Branch 5 taken 285 times.
181394 if BackendVariable.isVarAlg(v) and not BackendVariable.isInput(v) then
199 42086 UnorderedSet.add(v.varName, vars);
200 end if;
201 end for;
202 1060 setGlobalRoot(Global.timeIndependentVars, SOME(vars));
203 end setTimeIndependentVars;
204
205 public function createSimCode "entry point to create SimCode from BackendDAE."
206 input BackendDAE.BackendDAE inBackendDAE;
207 input BackendDAE.BackendDAE inInitDAE;
208 input Option<BackendDAE.BackendDAE> inInitDAE_lambda0;
209 input Option<BackendDAE.InlineData> inInlineData;
210 input list<BackendDAE.Equation> inRemovedInitialEquationLst;
211 input Absyn.Path inClassName;
212 input String filenamePrefix;
213 input String inFileDir;
214 input list<SimCodeFunction.Function> functions;
215 input list<String> externalFunctionIncludes;
216 input list<String> includeDirs;
217 input list<String> libs;
218 input list<String> libPaths;
219 input Absyn.Program program;
220 input Option<SimCode.SimulationSettings> simSettingsOpt;
221 input list<SimCodeFunction.RecordDeclaration> recordDecls;
222 input tuple<Integer, UnorderedMap<DAE.Exp, Integer>, list<DAE.Exp>> literals;
223 input Absyn.FunctionArgs args;
224 input Boolean isFMU=false;
225 input String FMUVersion="";
226 input String fmuTargetName="";
227 input BackendDAE.SymbolicJacobians inFMIDer = {};
228 output SimCode.SimCode simCode;
229 output tuple<Integer, list<tuple<Integer, Integer>>> outMapping "the highest simEqIndex in the mapping and the mapping simEq-Index -> scc-Index itself";
230 protected
231 BackendDAE.BackendDAE dlow, initDAE_lambda0;
232 BackendDAE.EquationArray removedEqs;
233 BackendDAE.EventInfo eventInfo;
234 BackendDAE.Shared shared;
235 BackendDAE.SymbolicJacobians symJacs;
236 BackendDAE.Variables globalKnownVars;
237 Boolean ifcpp;
238 HashTableCrIListArray.HashTable varToArrayIndexMapping "maps each array-variable to a array of positions";
239 HashTableCrILst.HashTable varToIndexMapping "maps each variable to an array position";
240 Integer maxDelayedExpIndex, uniqueEqIndex, numStateSets, sccOffset;
241 Integer numberofFixedParameters, reasonableSize;
242 Option<SimCode.FmiModelStructure> modelStructure = NONE();
243 Option<SimCode.FmiSimulationFlags> fmiSimulationFlags = NONE();
244 SimCode.BackendMapping backendMapping;
245 SimCode.ExtObjInfo extObjInfo;
246 SimCode.HashTableCrefToSimVar crefToSimVarHT;
247 SimCodeFunction.MakefileParams makefileParams;
248 SimCode.ModelInfo modelInfo;
249 tuple<Integer, UnorderedMap<DAE.Exp, Integer>, list<DAE.Exp>> literalsAcc = literals;
250 list<SimCodeFunction.RecordDeclaration> recordDeclsAcc = recordDecls;
251 AvlTreePathFunction.Tree fmiDerInitFuncTree;
252 HashTable.HashTable crefToClockIndexHT;
253 array<Integer> systemIndexMap;
254 list<BackendDAE.EqSystem> clockedSysts, contSysts;
255 //list<BackendDAE.Equation> paramAsserts, remEqLst;
256 list<BackendDAE.TimeEvent> timeEvents;
257 BackendDAE.ZeroCrossingSet zeroCrossingsSet, sampleZCSet;
258 BackendDAE.ZeroCrossingSet de_relations;
259 list<BackendDAE.ZeroCrossing> zeroCrossings, sampleZC, relations;
260 list<DAE.ClassAttributes> classAttributes;
261 list<DAE.ComponentRef> discreteModelVars, iterationVarsLst1, iterationVarsLst2;
262 list<DAE.Constraint> constraints;
263 list<DAE.Exp> lits;
264 list<SimCode.ClockedPartition> clockedPartitions;
265 list<SimCode.JacobianMatrix> LinearMatrices, SymbolicJacs, SymbolicJacsTemp, SymbolicJacsStateSelect, SymbolicJacsStateSelectInternal, SymbolicJacsNLS, SymbolicJacsFMI={}, SymbolicJacsdatarecon={};
266 list<SimCode.SimEqSystem> algorithmAndEquationAsserts;
267 list<SimCode.SimEqSystem> localKnownVars;
268 list<SimCode.SimEqSystem> allEquations;
269 list<SimCode.SimEqSystem> equationsForZeroCrossings;
270 list<SimCode.SimEqSystem> initialEquations; // --> initial_equations
271 list<SimCode.SimEqSystem> initialEquations_lambda0; // --> initial_equations_lambda0
272 list<SimCode.SimEqSystem> jacobianEquations = {};
273 list<SimCode.SimEqSystem> maxValueEquations = {}; // --> updateBoundMaxValues
274 list<SimCode.SimEqSystem> minValueEquations = {}; // --> updateBoundMinValues
275 list<SimCode.SimEqSystem> nominalValueEquations = {}; // --> updateBoundNominalValues
276 //list<SimCode.SimEqSystem> paramAssertSimEqs;
277 list<SimCode.SimEqSystem> parameterEquations = {}; // --> updateBoundParameters
278 list<SimCode.SimEqSystem> removedEquations;
279 list<SimCode.SimEqSystem> removedInitialEquations; // -->
280 list<SimCode.SimEqSystem> startValueEquations = {}; // --> updateBoundStartValues
281 list<SimCode.StateSet> stateSets;
282 list<SimCodeVar.SimVar> tempvars, jacobianSimvars, seedVars;
283 list<list<SimCode.SimEqSystem>> algebraicEquations; // --> functionAlgebraics
284 list<list<SimCode.SimEqSystem>> odeEquations; // --> functionODE
285 list<list<SimCode.SimEqSystem>> inlineEquationsTemp; // --> symbolicInlineSystemTemp
286 list<SimCode.SimEqSystem> inlineEquations; // --> symbolicInlineSystem
287 SimCodeVar.SimVars tmpSimVars;
288 SimCode.VarInfo varInfo;
289 list<SimCodeVar.SimVar> sensitivityVars;
290 Integer countSenParams;
291 list<tuple<Integer, Integer>> equationSccMapping, eqBackendSimCodeMapping;
292 list<tuple<Integer, tuple<DAE.Exp, DAE.Exp, DAE.Exp>>> delayedExps;
293 SimCode.SpatialDistributionInfo spatialInfo;
294 BackendDAE.InlineData inlineData;
295 list<SimCodeVar.SimVar> inlineSimKnVars;
296 BackendDAE.Variables emptyVars;
297 Integer SymEuler_help = 0;
298 SimCodeVar.SimVar dtSimVar;
299 BackendDAE.Var dtVar;
300 HashTableSimCodeEqCache.HashTable eqCache;
301 BackendDAE.Jacobian dataReconJac;
302 Option<BackendDAE.Jacobian> dataReconJacH;
303 BackendDAE.Variables setcVars, datareconinputvars;
304 Option<BackendDAE.Variables> setBVars;
305 list<SimCodeVar.SimVar> tmpsetcVars, tmpdatareconinputvars, tmpsetBVars;
306 SimCode.JacobianMatrix dataReconSimJac, dataReconSimJacH;
307 Integer numRelatedBoundaryConditions;
308 String fullPathPrefix, fileNamePrefixHash, iterationVarsStr;
309
310 SimCode.SimulationSettings theSettings;
311
312 constant Boolean debug = false;
313 algorithm
314 try
315 1060 execStat("Backend phase and start with SimCode phase");
316 1060 dlow := BackendDAEUtil.markNonlinearIterationVariables(inBackendDAE);
317 // transfer timeInterval from siulation settings to shared
318
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
✓ Branch 2 taken 1060 times.
✗ Branch 3 not taken.
1060 if isSome(simSettingsOpt) then
319 ✗ SOME(theSettings) := simSettingsOpt;
320 1060 shared := dlow.shared;
321 2120 shared.timeInterval := SOME(DAE.RCONST(theSettings.stepSize));
322 1060 dlow.shared := shared;
323 end if;
324 1060 System.tmpTickReset(0);
325 1060 uniqueEqIndex := 1;
326
4/4
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1010 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 46 times.
1060 ifcpp := (stringEqual(Config.simCodeTarget(), "Cpp"));
327
328 1060 backendMapping := setUpBackendMapping(inBackendDAE);
329
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1057 times.
1060 if Flags.isSet(Flags.VISUAL_XML) then
330 3 dlow := VisualXML.visualizationInfoXML(dlow, filenamePrefix, program);
331 end if;
332
333
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1058 times.
1060 if Flags.isSet(Flags.ITERATION_VARS) then
334 2 BackendDAEOptimize.listAllIterationVariables(dlow);
335 end if;
336 // initialization stuff
337 // ********************
338
339 // generate equations for initDAE
340 1060 (initialEquations, uniqueEqIndex, tempvars) := createInitialEquations(inInitDAE, uniqueEqIndex, {});
341
342 // generate equations for initDAE_lambda0
343
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 1027 times.
1060 if isSome(inInitDAE_lambda0) then
344 33 SOME(initDAE_lambda0) := inInitDAE_lambda0;
345 33 (initialEquations_lambda0, uniqueEqIndex, tempvars) := createInitialEquations_lambda0(initDAE_lambda0, uniqueEqIndex, tempvars);
346 else
347 initialEquations_lambda0 := {};
348 end if;
349
350 // generate equations for removed initial equations
351 1060 (removedInitialEquations, (uniqueEqIndex, _), tempvars) := createNonlinearResidualEquations(inRemovedInitialEquationLst, (uniqueEqIndex, 0), tempvars, dlow.shared.functionTree);
352 1060 removedInitialEquations := fixNonlinearResidualIndices(removedInitialEquations);
353 1060 execStat("simCode: created initialization part");
354
355 1060 shared as BackendDAE.SHARED(globalKnownVars=globalKnownVars,
356 constraints=constraints,
357 classAttrs=classAttributes,
358 symjacs=symJacs,
359 eventInfo=eventInfo) := dlow.shared;
360 1060 setTimeIndependentVars(globalKnownVars);
361
362 1060 removedEqs := BackendDAEUtil.collapseRemovedEqs(dlow);
363
364 // created event suff e.g. zeroCrossings, samples, ...
365 1060 timeEvents := eventInfo.timeEvents;
366 (zeroCrossings,relations,sampleZC) := match eventInfo
367 case BackendDAE.EVENT_INFO(zeroCrossings=zeroCrossingsSet, relations=de_relations, samples=sampleZCSet)
368 1060 then (ZeroCrossings.toList(zeroCrossingsSet), ZeroCrossings.toList(de_relations), ZeroCrossings.toList(sampleZCSet));
369 end match;
370
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1014 times.
1060 if ifcpp then
371 46 zeroCrossings := listAppend(relations, sampleZC);
372 end if;
373
374 1060 (clockedSysts, contSysts) := List.splitOnTrue(dlow.eqs, BackendDAEUtil.isClockedSyst);
375 1060 execStat("simCode: created event and clocks part");
376
377 // ToDo: fix this ugly flag switchting
378
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1048 times.
1060 if (Flags.getConfigEnum(Flags.SYM_SOLVER) > 0) then
379 12 SymEuler_help := Flags.getConfigEnum(Flags.SYM_SOLVER);
380 12 FlagsUtil.setConfigEnum(Flags.SYM_SOLVER, 0);
381 end if;
382
383
384 1060 (uniqueEqIndex, odeEquations, algebraicEquations, localKnownVars, allEquations, equationsForZeroCrossings, tempvars,
385 equationSccMapping, eqBackendSimCodeMapping, backendMapping, sccOffset) :=
386 createEquationsForSystems(contSysts, shared, uniqueEqIndex, zeroCrossings, tempvars, 1, backendMapping, true);
387 if debug then execStat("simCode: createEquationsForSystems"); end if;
388
389
390
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1048 times.
1060 if (SymEuler_help > 0) then
391 12 FlagsUtil.setConfigEnum(Flags.SYM_SOLVER, SymEuler_help);
392 end if;
393
394 //List.map1_0(inlineEquations, dumpSimEqSystemLst,"\n");
395 if debug then execStat("simCode: createEquationsForSystems for inline module"); end if;
396
397 1060 outMapping := (uniqueEqIndex /* highestSimEqIndex */, equationSccMapping);
398 1060 execStat("simCode: created simulation system equations");
399
400 //(remEqLst, paramAsserts) := List.fold1(BackendEquation.equationList(removedEqs), getParamAsserts, globalKnownVars,({},{}));
401 //((uniqueEqIndex, removedEquations)) := BackendEquation.traverseEquationArray(BackendEquation.listEquation(remEqLst), traversedlowEqToSimEqSystem, (uniqueEqIndex, {}));
402 1060 (uniqueEqIndex, removedEquations) := BackendEquation.traverseEquationArray(removedEqs, traversedlowEqToSimEqSystem, (uniqueEqIndex, {}));
403 if debug then execStat("simCode: traversedlowEqToSimEqSystem"); end if;
404
405 1060 (clockedPartitions, uniqueEqIndex, backendMapping, equationSccMapping, eqBackendSimCodeMapping, tempvars) :=
406 translateClockedEquations(clockedSysts, dlow.shared, sccOffset, uniqueEqIndex,
407 backendMapping, equationSccMapping, eqBackendSimCodeMapping, tempvars);
408 if debug then execStat("simCode: translateClockedEquations"); end if;
409
410 // create parameter equations
411 1060 (uniqueEqIndex, startValueEquations, _) := BackendDAEUtil.foldEqSystem(dlow, createStartValueEquations, (uniqueEqIndex, {}, globalKnownVars));
412 if debug then execStat("simCode: createStartValueEquations"); end if;
413
414 1060 (uniqueEqIndex, nominalValueEquations) := createValueEquationsShared(dlow.shared, createInitialAssignmentsFromNominal, (uniqueEqIndex, nominalValueEquations));
415 if debug then execStat("simCode: createNominalValueEquationsShared"); end if;
416 1060 (uniqueEqIndex, nominalValueEquations) := BackendDAEUtil.foldEqSystem(dlow, createNominalValueEquations, (uniqueEqIndex, nominalValueEquations));
417 if debug then execStat("simCode: createNominalValueEquations"); end if;
418
419 1060 (uniqueEqIndex, minValueEquations) := createValueEquationsShared(dlow.shared, createInitialAssignmentsFromMin, (uniqueEqIndex, minValueEquations));
420 if debug then execStat("simCode: createMinValueEquationsShared"); end if;
421 1060 (uniqueEqIndex, minValueEquations) := BackendDAEUtil.foldEqSystem(dlow, createMinValueEquations, (uniqueEqIndex, minValueEquations));
422 if debug then execStat("simCode: createMinValueEquations"); end if;
423
424 1060 (uniqueEqIndex, maxValueEquations) := createValueEquationsShared(dlow.shared, createInitialAssignmentsFromMax, (uniqueEqIndex, maxValueEquations));
425 if debug then execStat("simCode: createMaxValueEquationsShared"); end if;
426 1060 (uniqueEqIndex, maxValueEquations) := BackendDAEUtil.foldEqSystem(dlow, createMaxValueEquations, (uniqueEqIndex, maxValueEquations));
427 if debug then execStat("simCode: createMaxValueEquations"); end if;
428
429 1060 (uniqueEqIndex, parameterEquations, numberofFixedParameters) := createParameterEquations(uniqueEqIndex, parameterEquations, globalKnownVars,
430 List.unionOnTrue(listReverse(shared.parameterAsserts), listReverse(inInitDAE.shared.parameterAsserts), ExpressionSolve.assertCondEqual));
431 if debug then execStat("simCode: createParameterEquations"); end if;
432 //((uniqueEqIndex, paramAssertSimEqs)) := BackendEquation.traverseEquationArray(BackendEquation.listEquation(paramAsserts), traversedlowEqToSimEqSystem, (uniqueEqIndex, {}));
433 //parameterEquations := listAppend(parameterEquations, paramAssertSimEqs);
434
435 1060 (uniqueEqIndex, algorithmAndEquationAsserts) := BackendDAEUtil.foldEqSystem(dlow, createAlgorithmAndEquationAsserts, (uniqueEqIndex, {}));
436 if debug then execStat("simCode: createAlgorithmAndEquationAsserts"); end if;
437 1060 discreteModelVars := BackendDAEUtil.foldEqSystem(dlow, extractDiscreteModelVars, {});
438 if debug then execStat("simCode: extractDiscreteModelVars"); end if;
439 1060 makefileParams := SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths, false, isFMU);
440 1060 (delayedExps, maxDelayedExpIndex) := extractDelayedExpressions(dlow);
441 1060 spatialInfo := extractSpatialDistributionInfo(dlow);
442 1060 execStat("simCode: created of all other equations (e.g. parameter, nominal, assert, etc)");
443
444 // append removed equation to all equations, since these are actually
445 // just the algorithms without outputs
446 // TODO: Should removedEquations really be solved in EVERY iteration?
447 // TODO: They include some things that look like aliases and equations depending only on parameters...
448 // TODO: That might actually be a problem for the CSE module though...
449 1060 algebraicEquations := List.appendElt(listReverse(removedEquations), listReverse(algebraicEquations));
450 1060 allEquations := List.append_reverse(allEquations, removedEquations);
451
452 // create inline equations if present
453
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1048 times.
1060 if isSome(inInlineData) then
454 12 SOME(inlineData) := inInlineData;
455 12 (uniqueEqIndex, inlineEquationsTemp, _, _, _, _, tempvars, _, _, _, _) :=
456 createEquationsForSystems(inlineData.inlineSystems,
457 shared, uniqueEqIndex, {}, tempvars, uniqueEqIndex,
458 SimCode.NO_MAPPING(), false);
459 12 inlineEquations := List.flatten(inlineEquationsTemp);
460 else
461 inlineEquations := {};
462 end if;
463
464 // state set stuff
465 1060 (dlow, stateSets, uniqueEqIndex, tempvars, numStateSets) := createStateSets(dlow, {}, uniqueEqIndex, tempvars);
466 if debug then execStat("simCode: createStateSets"); end if;
467
468 // create model info
469 1060 modelInfo := createModelInfo(inClassName, program, dlow, inInitDAE, functions, {}, numStateSets, spatialInfo.maxIndex, inFileDir, listLength(clockedSysts), tempvars, inInitDAE_lambda0);
470 if debug then execStat("simCode: createModelInfo and variables"); end if;
471
472 //build labels
473
3/4
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1014 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
1060 if(boolAnd(ifcpp,Flags.getConfigBool(Flags.LABELED_REDUCTION))) then
474 ✗ FlagsUtil.setConfigBool(Flags.GENERATE_LABELED_SIMCODE,true);
475 end if;
476
477
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1014 times.
1060 if(ifcpp) then
478
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if Flags.getConfigBool(Flags.GENERATE_LABELED_SIMCODE) then
479 ✗ (allEquations,modelInfo) := ReduceDAE.buildLabels(allEquations,modelInfo,{},args);
480 //FlagsUtil.set(Flags.REDUCE_DAE,true);
481 if debug then execStat("ReduceDAE: buildLabels"); end if;
482 end if;
483 end if;
484
485 tmpSimVars := modelInfo.vars;
486
487 //reduce terms
488
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1014 times.
1060 if(ifcpp) then
489
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if Flags.getConfigBool(Flags.REDUCE_TERMS) then
490 ✗ (allEquations,modelInfo) := ReduceDAE.reduceTerms(allEquations,modelInfo,args);
491 ✗ FlagsUtil.setConfigBool(Flags.REDUCE_TERMS, false);
492 ✗ FlagsUtil.disableDebug(Flags.REDUCE_DAE);
493 if debug then execStat("ReduceDAE: reduceTerms"); end if;
494 end if;
495 end if;
496 // external objects
497 1060 extObjInfo := createExtObjInfo(shared);
498
499 // update index of zero-Crossings after equations are created
500 1060 zeroCrossings := updateZeroCrossEqnIndex(zeroCrossings, eqBackendSimCodeMapping, BackendDAEUtil.equationArraySizeBDAE(dlow));
501 if debug then execStat("simCode: update zero crossing index"); end if;
502
503 // collect all LinearSystem and NonlinearSystem algebraic system in modelInfo and update
504 // the corresponding index (indexNonLinear, indexLinear) in SES_NONLINEAR and SES_LINEAR
505 // Also collect all jacobians
506 1060 SymbolicJacsNLS := {};
507 1060 (initialEquations, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfo(initialEquations, modelInfo);
508 1060 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
509 1060 (initialEquations_lambda0, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfo(initialEquations_lambda0, modelInfo);
510 1060 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
511 1060 (parameterEquations, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfo(parameterEquations, modelInfo);
512 1060 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
513 1060 (allEquations, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfo(allEquations, modelInfo);
514 1060 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
515 1060 (clockedPartitions, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsClockPartitions(clockedPartitions, modelInfo);
516 1060 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
517 1060 (inlineEquations, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfo(inlineEquations, modelInfo);
518 1060 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
519
520 // Generate jacobian code for DataReconciliation
521
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 1035 times.
1060 if isSome(shared.dataReconciliationData) then
522 25 BackendDAE.DATA_RECON(dataReconJac, setcVars, datareconinputvars, setBVars, dataReconJacH, numRelatedBoundaryConditions) := Util.getOption(shared.dataReconciliationData);
523
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
25 (SOME(dataReconSimJac), uniqueEqIndex, tempvars) := createSymbolicSimulationJacobian(dataReconJac, uniqueEqIndex, tempvars);
524 // check for jacobian H for state estimation, if exist generate Matrix H
525
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 24 times.
25 if (isSome(dataReconJacH)) then
526
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
1 (SOME(dataReconSimJacH), uniqueEqIndex, tempvars) := createSymbolicSimulationJacobian(Util.getOption(dataReconJacH), uniqueEqIndex, tempvars);
527 1 (SymbolicJacsdatarecon, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfoSymJacs({dataReconSimJac, dataReconSimJacH}, modelInfo);
528 else
529 24 (SymbolicJacsdatarecon, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfoSymJacs({dataReconSimJac}, modelInfo);
530 end if;
531 25 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
532 //SymbolicJacsNLS := dataReconSimJac::SymbolicJacsNLS;
533 // write iteration variables to file for data reconciliation report
534 25 (_, iterationVarsLst1) := BackendDAEOptimize.listAllIterationVariables0(inInitDAE.eqs);
535 25 (_, iterationVarsLst2) := BackendDAEOptimize.listAllIterationVariables0(inBackendDAE.eqs);
536 25 iterationVarsLst1 := List.unique(listAppend(iterationVarsLst1, iterationVarsLst2));
537
538 25 iterationVarsStr := "List of iteration variables(" + intString(listLength(iterationVarsLst1)) + "):" + "\n=============================\n";
539
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6 times.
25 if listEmpty(iterationVarsLst1) then
540 19 iterationVarsStr := iterationVarsStr + "No iteration variables found.\n";
541 else
542
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 6 times.
49 for var in iterationVarsLst1 loop
543 43 iterationVarsStr := iterationVarsStr + ComponentReference.crefStr(var) + "\n";
544 end for;
545 end if;
546 25 System.writeFile(shared.info.fileNamePrefix + "_iterationVars.txt", iterationVarsStr);
547 end if;
548
549 // collect symbolic jacobians from state selection
550 1060 (stateSets, modelInfo, SymbolicJacsStateSelect, SymbolicJacsStateSelectInternal) := addAlgebraicLoopsModelInfoStateSets(stateSets, modelInfo);
551 if debug then execStat("simCode: collect and index LS/NLS in modelInfo"); end if;
552
553 // collect fmi partial derivative (FMI 2.0 and 3.0 both expose a ModelStructure)
554
4/4
✓ Branch 1 taken 990 times.
✓ Branch 2 taken 70 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 977 times.
1060 if FMI.isFMIVersion20(FMUVersion) or FMI.isFMIVersion30(FMUVersion) then
555 83 System.realtimeTick(ClockIndexes.RT_CLOCK_FMU_SIMCODE);
556 83 (SymbolicJacsFMI, modelStructure, modelInfo, SymbolicJacsTemp, uniqueEqIndex, fmiDerInitFuncTree) := createFMIModelStructure(inFMIDer, modelInfo, uniqueEqIndex, inInitDAE, inBackendDAE);
557 83 SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS);
558 // the FMIDERINIT jacobian is created here, i.e. after the functions have been
559 // elaborated, so the functions it calls on its own have to be added now
560 83 (modelInfo, literalsAcc, recordDeclsAcc) := addFmiDerInitFunctions(program, fmiDerInitFuncTree,
561 BackendDAEUtil.getFunctions(inBackendDAE.shared), modelInfo, literalsAcc, recordDeclsAcc);
562 83 System.realtimeAccumulate(ClockIndexes.RT_CLOCK_FMU_SIMCODE);
563 if debug then execStat("simCode: create FMI model structure"); end if;
564 end if;
565
566 // Collect FMI sim flags
567
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 974 times.
1060 if isFMU then
568 86 System.realtimeTick(ClockIndexes.RT_CLOCK_FMU_SIMCODE);
569 86 fmiSimulationFlags := createFMISimulationFlags();
570 86 System.realtimeAccumulate(ClockIndexes.RT_CLOCK_FMU_SIMCODE);
571 end if;
572
573 // collect symbolic jacobians in linear loops of the overall jacobians
574 1060 (LinearMatrices, uniqueEqIndex) := createJacobianLinearCode(symJacs, modelInfo, uniqueEqIndex, shared);
575 1060 (SymbolicJacs, modelInfo, SymbolicJacsTemp) := addAlgebraicLoopsModelInfoSymJacs(LinearMatrices, modelInfo);
576 // append datareconciliation jacobians equation to SymbolicJacs for correct generation of equations in model_info.json
577 2120 SymbolicJacs := List.flatten({SymbolicJacsFMI, SymbolicJacs, SymbolicJacsStateSelect, SymbolicJacsdatarecon});
578 1060 (delayedExps, maxDelayedExpIndex, SymbolicJacsNLS) := extractJacobianDelayedExpressions(delayedExps, maxDelayedExpIndex, SymbolicJacsNLS);
579 1060 (delayedExps, maxDelayedExpIndex, SymbolicJacs) := extractJacobianDelayedExpressions(delayedExps, maxDelayedExpIndex, SymbolicJacs);
580 1060 (delayedExps, maxDelayedExpIndex, SymbolicJacsTemp) := extractJacobianDelayedExpressions(delayedExps, maxDelayedExpIndex, SymbolicJacsTemp);
581 1060 (delayedExps, maxDelayedExpIndex, SymbolicJacsStateSelectInternal) := extractJacobianDelayedExpressions(delayedExps, maxDelayedExpIndex, SymbolicJacsStateSelectInternal);
582
583 // collect jacobian equation only for equantion info file
584 1060 jacobianEquations := collectAllJacobianEquations(SymbolicJacs);
585 if debug then execStat("simCode: create Jacobian linear code"); end if;
586
587 2120 SymbolicJacs := List.flatten({listReverse(SymbolicJacsNLS), SymbolicJacs, SymbolicJacsTemp, SymbolicJacsStateSelectInternal});
588
589 1060 jacobianSimvars := collectAllJacobianVars(SymbolicJacs);
590 1060 modelInfo := setJacobianVars(jacobianSimvars, modelInfo);
591 1060 seedVars := collectAllSeedVars(SymbolicJacs);
592 1060 modelInfo := setSeedVars(seedVars, modelInfo);
593 1060 execStat("simCode: created linear, non-linear and system jacobian parts");
594
595 // map index also odeEquations and algebraicEquations
596 1060 systemIndexMap := List.fold(allEquations, getSystemIndexMap, arrayCreate(uniqueEqIndex, -1));
597 1060 odeEquations := List.map1List(odeEquations, setSystemIndexMap, systemIndexMap);
598 1060 algebraicEquations := List.map1List(algebraicEquations, setSystemIndexMap, systemIndexMap);
599 1060 modelInfo := addNumEqns(modelInfo, uniqueEqIndex /* This is a *much* better estimate than the guessed number of equations */ );
600
601 1060 odeEquations := makeEqualLengthLists(odeEquations, Config.noProc());
602 1060 algebraicEquations := makeEqualLengthLists(algebraicEquations, Config.noProc());
603
604 // Filter out empty systems to improve code generation
605 1060 odeEquations := List.filterOnFalse(odeEquations, listEmpty);
606 1060 algebraicEquations := List.filterOnFalse(algebraicEquations, listEmpty);
607
608
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1060 times.
1060 if Flags.isSet(Flags.EXEC_HASH) then
609 ✗ print("*** SimCode -> generate cref2simVar hashtable: " + realString(clock()) + "\n");
610 end if;
611 // generate cref2simVar hash table
612 1060 crefToSimVarHT := SimCodeCodegenUtil.createCrefToSimVarHT(modelInfo);
613
614
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1060 times.
1060 if Flags.isSet(Flags.EXEC_HASH) then
615 ✗ print("*** SimCode -> generate cref2simVar hashtable done!: " + realString(clock()) + "\n");
616 end if;
617 // add known inline vars to simVarHT
618
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1048 times.
1060 if (Flags.getConfigEnum(Flags.SYM_SOLVER) > 0) then
619
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 SOME(inlineData) := inInlineData;
620 12 emptyVars := BackendVariable.emptyVars();
621 12 inlineSimKnVars := adjustStatesForInlineSolver(modelInfo.vars.stateVars);
622 // omc dt
623
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
12 ({dtVar},_) := BackendVariable.getVar(ComponentReferenceBasics.makeCrefIdent(BackendDAE.symSolverDT, DAE.T_REAL_DEFAULT, {}), inlineData.knownVariables);
624 12 dtSimVar := dlowvarToSimvar(dtVar, NONE(), emptyVars);
625 12 dtSimVar.index := listLength(inlineSimKnVars);
626 inlineSimKnVars := dtSimVar::inlineSimKnVars;
627 12 crefToSimVarHT := List.fold(inlineSimKnVars,HashTableCrefSimVar.addSimVarToHashTable,crefToSimVarHT);
628 end if;
629
630
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1059 times.
1060 if Flags.getConfigBool(Flags.CALCULATE_SENSITIVITIES) then
631 1 tmpSimVars := modelInfo.vars;
632 1 (sensitivityVars, countSenParams) := createSimVarsForSensitivities(tmpSimVars.stateVars, tmpSimVars.paramVars, numberofFixedParameters);
633 1 sensitivityVars := rewriteIndex(sensitivityVars, 0);
634 1 tmpSimVars.sensitivityVars := sensitivityVars;
635 1 modelInfo.vars := tmpSimVars;
636 // set varInfo nSensitivities
637 1 varInfo := modelInfo.varInfo;
638 1 varInfo.numSensitivityParameters := countSenParams;
639 1 modelInfo.varInfo := varInfo;
640 end if;
641 // Generates c code for setC-results which calculates c(x,y) for dataReconciliation
642
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 1035 times.
1060 if isSome(shared.dataReconciliationData) then
643 25 tmpSimVars := modelInfo.vars;
644 25 BackendDAE.DATA_RECON(setcVars=setcVars, datareconinputs=datareconinputvars, setBVars=setBVars, relatedBoundaryConditions=numRelatedBoundaryConditions) := Util.getOption(shared.dataReconciliationData);
645 25 emptyVars := BackendVariable.emptyVars();
646 25 (tmpsetcVars, _) := BackendVariable.traverseBackendDAEVars(setcVars, traversingdlowvarToSimvar, ({}, emptyVars));
647 25 tmpsetcVars := rewriteIndex(tmpsetcVars, 0);
648 25 tmpSimVars.dataReconSetcVars := tmpsetcVars;
649 25 modelInfo.vars := tmpSimVars;
650
651 //add the input vars for dataReconciliation
652 25 (tmpdatareconinputvars, _) := BackendVariable.traverseBackendDAEVars(datareconinputvars, traversingdlowvarToSimvar, ({}, emptyVars));
653 25 tmpdatareconinputvars := rewriteIndex(listReverse(tmpdatareconinputvars), 0);
654 25 tmpSimVars.dataReconinputVars := tmpdatareconinputvars;
655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 modelInfo.vars := tmpSimVars;
656
657 // set setBVars
658
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 if isSome(setBVars) then
659 25 (tmpsetBVars, _) := BackendVariable.traverseBackendDAEVars(Util.getOption(setBVars), traversingdlowvarToSimvar, ({}, emptyVars));
660 25 tmpsetBVars := rewriteIndex(tmpsetBVars, 0);
661 25 tmpSimVars.dataReconSetBVars := tmpsetBVars;
662 25 modelInfo.vars := tmpSimVars;
663 // set varInfo nsetbvars
664 25 varInfo := modelInfo.varInfo;
665 25 varInfo.numSetbVars := listLength(tmpsetBVars);
666 25 modelInfo.varInfo := varInfo;
667 end if;
668
669 // set varInfo nsetcvars
670 25 varInfo := modelInfo.varInfo;
671 25 varInfo.numSetcVars := listLength(tmpsetcVars);
672 25 varInfo.numDataReconVars := listLength(tmpdatareconinputvars);
673 25 varInfo.numRelatedBoundaryConditions := numRelatedBoundaryConditions;
674 25 modelInfo.varInfo := varInfo;
675 //print("\n simcode gen setc:*****"+anyString(tmpsetcVars) + "\n lenght of vars :" +anyString(listLength(tmpsetcVars)));
676 end if;
677 //print("\n created model_info:"+ anyString(modelInfo.varInfo.numSetcVars)+ "\n setcvars" + anyString(modelInfo.vars.dataReconSetcVars));
678 1060 backendMapping := setBackendVarMapping(inBackendDAE, crefToSimVarHT, modelInfo, backendMapping);
679 //dumpBackendMapping(backendMapping);
680
681 1060 (varToArrayIndexMapping, varToIndexMapping) := SimCodeUtilShared.createVarToArrayIndexMapping(modelInfo);
682 //print("HASHTABLE MAPPING\n\n");
683 //BaseHashTable.dumpHashTable(varToArrayIndexMapping);
684 //print("END MAPPING\n\n");
685
686 1060 (crefToClockIndexHT, _) := List.fold(listReverse(inBackendDAE.eqs), collectClockedVars, (HashTable.emptyHashTable(), 1));
687
688 1060 execStat("simCode: some other stuff during SimCode phase");
689
690
691
692
4/4
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1010 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 46 times.
1060 if ((Config.simCodeTarget() <> "Cpp"))then
693 1014 reasonableSize := Util.nextPrime(10+integer(1.4*(BackendDAEUtil.equationArraySizeBDAE(inBackendDAE)+BackendDAEUtil.equationArraySizeBDAE(inInitDAE)+listLength(parameterEquations))));
694 1014 eqCache := HashTableSimCodeEqCache.emptyHashTableSized(reasonableSize);
695
696
697 // Alias equations to other equations.
698 // The C++ codegen does things differently and will not handle this
699 1014 (allEquations, eqCache) := aliasSimEqs(allEquations, eqCache);
700 1014 (odeEquations, eqCache) := aliasSimEqSystems(odeEquations, eqCache);
701 1014 (algebraicEquations, eqCache) := aliasSimEqSystems(algebraicEquations, eqCache);
702 1014 (initialEquations, eqCache) := aliasSimEqs(initialEquations, eqCache);
703 1014 (initialEquations_lambda0, eqCache) := aliasSimEqs(initialEquations_lambda0, eqCache);
704 1014 (removedEquations, eqCache) := aliasSimEqs(removedEquations, eqCache);
705 1014 (removedInitialEquations, eqCache) := aliasSimEqs(removedInitialEquations, eqCache);
706 1014 (algorithmAndEquationAsserts, eqCache) := aliasSimEqs(algorithmAndEquationAsserts, eqCache);
707 1014 (jacobianEquations, eqCache) := aliasSimEqs(jacobianEquations, eqCache);
708 1014 (parameterEquations, eqCache) := aliasSimEqs(parameterEquations, eqCache);
709 1014 execStat("simCode: alias equations");
710 end if;
711
712 // fix issue https://github.com/OpenModelica/OpenModelica/issues/12916
713 1060 fileNamePrefixHash := Util.hashFileNamePrefix(filenamePrefix);
714
715 // Set fullPathPrefix for FMUs
716
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 974 times.
1060 if isFMU then
717 86 fullPathPrefix := fileNamePrefixHash+".fmutmp/sources/";
718 else
719 fullPathPrefix := "";
720 end if;
721
722
2/2
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 974 times.
1060 simCode := SimCode.SIMCODE(
723 modelInfo = modelInfo,
724 literals = {}, // Set by the traversal below...
725 recordDecls = recordDeclsAcc,
726 externalFunctionIncludes = externalFunctionIncludes,
727 generic_loop_calls = {}, // only used in new backend
728 localKnownVars = localKnownVars,
729 allEquations = allEquations,
730 odeEquations = odeEquations,
731 algebraicEquations = algebraicEquations,
732 clockedPartitions = clockedPartitions,
733 initialEquations = initialEquations,
734 initialEquations_lambda0 = initialEquations_lambda0,
735 removedInitialEquations = removedInitialEquations,
736 startValueEquations = startValueEquations,
737 nominalValueEquations = nominalValueEquations,
738 minValueEquations = minValueEquations,
739 maxValueEquations = maxValueEquations,
740 parameterEquations = parameterEquations,
741 removedEquations = removedEquations,
742 algorithmAndEquationAsserts = algorithmAndEquationAsserts,
743 equationsForZeroCrossings = equationsForZeroCrossings,
744 jacobianEquations = jacobianEquations,
745 stateSets = stateSets,
746 constraints = constraints,
747 classAttributes = classAttributes,
748 zeroCrossings = FindZeroCrossings.setOperatorZeroCrossingIndices(ZeroCrossings.updateIndices(zeroCrossings)),
749 relations = ZeroCrossings.updateIndices(relations),
750 timeEvents = timeEvents,
751 discreteModelVars = discreteModelVars,
752 extObjInfo = extObjInfo,
753 makefileParams = makefileParams,
754 delayedExps = SimCode.DELAYED_EXPRESSIONS(delayedExps, maxDelayedExpIndex),
755 spatialInfo = spatialInfo,
756 jacobianMatrices = SymbolicJacs,
757 simulationSettingsOpt = simSettingsOpt,
758 fileNamePrefix = filenamePrefix,
759 fullPathPrefix = fullPathPrefix,
760 fmuTargetName = fmuTargetName,
761 hpcomData = HpcOmSimCode.emptyHpcomData,
762 valueReferences = if isFMU then getValueReferenceMapping(modelInfo) else AvlTreeCRToInt.EMPTY(),
763 varToArrayIndexMapping = varToArrayIndexMapping,
764 varToIndexMapping = varToIndexMapping,
765 crefToSimVarHT = crefToSimVarHT,
766 crefToClockIndexHT = crefToClockIndexHT,
767 backendMapping = SOME(backendMapping),
768 modelStructure = modelStructure,
769 fmiSimulationFlags = fmiSimulationFlags,
770 partitionData = SimCode.emptyPartitionData,
771 daeModeData = NONE(),
772 inlineEquations = inlineEquations,
773 scalarized = true,
774 fmiFigures = {}
775 );
776
777 1060 (simCode, lits) := findSimCodeLiterals(simCode, literalsAcc);
778 1060 simCode := setSimCodeLiterals(simCode, lits);
779
780 // dumpCrefToSimVarHashTable(crefToSimVarHT);
781 // print("*** SimCode -> collect all files started: " + realString(clock()) + "\n");
782 // adrpo: collect all the files from SourceInfo and DAE.ElementSource
783 // simCode := collectAllFiles(simCode);
784 // print("*** SimCode -> collect all files done!: " + realString(clock()) + "\n");
785 1060 execStat("simCode: all other stuff during SimCode phase");
786
787
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1059 times.
1060 if Flags.isSet(Flags.DUMP_SIMCODE) then
788 1 dumpSimCodeDebug(simCode);
789 end if;
790 else
791 ✗ Error.addInternalError("function createSimCode failed [Transformation from optimised DAE to simulation code structure failed]", sourceInfo());
792 ✗ fail();
793 end try;
794 end createSimCode;
795
796 protected function getParamAsserts"splits the equationArray in variable-dependent and parameter-dependent equations.
797 author: Waurich TUD-2015-04"
798 input BackendDAE.Equation eqIn;
799 input BackendDAE.Variables vars;
800 input tuple<list<BackendDAE.Equation>, list<BackendDAE.Equation>> tplIn; //<var-dependent, param-dependent>
801 output tuple<list<BackendDAE.Equation>, list<BackendDAE.Equation>> tplOut;
802 algorithm
803 tplOut := matchcontinue(eqIn, tplIn)
804 local
805 list<DAE.Statement> stmts;
806 list<DAE.ComponentRef> crefs;
807 list<BackendDAE.Var> varLst;
808 list<list<BackendDAE.Var>> varLstLst;
809 list<BackendDAE.Equation> varDep,paramDep;
810 case(BackendDAE.ALGORITHM(alg=DAE.ALGORITHM_STMTS(statementLst=stmts)), (varDep,paramDep))
811 algorithm
812 ✗ crefs := List.fold(stmts,DAEUtil.getAssertConditionCrefs,{});
813 ✗ (varLstLst,_) := List.map1_2(crefs,BackendVariable.getVar,vars);
814 ✗ varLst := List.flatten(varLstLst);
815 ✗ true := List.any(varLst,BackendVariable.isParam);
816 ✗ then ((varDep,eqIn::paramDep));
817 else
818 algorithm
819 ✗ (varDep,paramDep) := tplIn;
820 ✗ then ((eqIn::varDep,paramDep));
821 end matchcontinue;
822 end getParamAsserts;
823
824 protected function translateClockedEquations
825 input BackendDAE.EqSystems inSysts;
826 input BackendDAE.Shared inShared;
827 input Integer iSccOffset;
828 input Integer iuniqueEqIndex;
829 input SimCode.BackendMapping iBackendMapping;
830 input list<tuple<Integer,Integer>> ieqSccMapping;
831 input list<tuple<Integer,Integer>> ieqBackendSimCodeMapping;
832 input list<SimCodeVar.SimVar> itempvars;
833 output list<SimCode.ClockedPartition> outPartitions = {};
834 output Integer ouniqueEqIndex = iuniqueEqIndex;
835 output SimCode.BackendMapping oBackendMapping = iBackendMapping;
836 output list<tuple<Integer,Integer>> oeqSccMapping = ieqSccMapping;
837 output list<tuple<Integer,Integer>> oeqBackendSimCodeMapping = ieqBackendSimCodeMapping;
838 output list<SimCodeVar.SimVar> otempvars = itempvars;
839 protected
840 Integer subPartIdx;
841 list<SimCode.SimEqSystem> removedEquations, equations;
842 SimCode.SubPartition simSubPartition;
843 Boolean holdEvents;
844 array<Integer> ass1, stateeqnsmark, zceqnsmarks;
845 AvlTreePathFunction.Tree funcs;
846 BackendDAE.StrongComponents comps;
847 Integer sccOffset = iSccOffset;
848 list<Integer> varIxs;
849 BackendDAE.Var var;
850 SimCodeVar.SimVar simVar;
851 DAE.ComponentRef cr;
852 list<SimCodeVar.SimVar> clockedVars;
853 list<tuple<SimCodeVar.SimVar, Boolean>> prevClockedVars;
854 array<Option<SimCode.SubPartition>> simSubPartitions;
855 BackendDAE.SubPartition subPartition;
856 array<Boolean> isPrevVar;
857 SimCode.SimEqSystem simEq;
858 algorithm
859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
2120 simSubPartitions := arrayCreate(arrayLength(inShared.partitionsInfo.subPartitions), NONE());
860 1060 funcs := BackendDAEUtil.getFunctions(inShared);
861
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1060 times.
1121 for syst in inSysts loop
862 //syst := preCalculateStartValues(syst, inShared.globalKnownVars, funcs);
863
864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 BackendDAE.CLOCKED_PARTITION(subPartIdx) := syst.partitionKind;
865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 BackendDAE.MATCHING(ass1=ass1, comps=comps) := syst.matching;
866 61 subPartition := inShared.partitionsInfo.subPartitions[subPartIdx];
867
868 122 (syst, _, _) := BackendDAEUtil.getAdjacencyMatrixfromOption(syst, BackendDAE.ABSOLUTE(), SOME(funcs), BackendDAEUtil.isInitializationDAE(inShared));
869 61 stateeqnsmark := arrayCreate(BackendDAEUtil.equationArraySizeDAE(syst), 0);
870 61 stateeqnsmark := BackendDAEUtil.markStateEquations(syst, stateeqnsmark, ass1);
871 61 zceqnsmarks := arrayCreate(BackendDAEUtil.equationArraySizeDAE(syst), 0);
872
873 //FIXME: Add continuous clocked systems support
874 61 (_, _, equations, _, ouniqueEqIndex, clockedVars, oeqSccMapping, oeqBackendSimCodeMapping, oBackendMapping) :=
875 createEquationsForSystem(stateeqnsmark, zceqnsmarks, syst, inShared, comps, ouniqueEqIndex, {},
876 sccOffset, oeqSccMapping, oeqBackendSimCodeMapping, oBackendMapping, true);
877 61 sccOffset := listLength(comps) + sccOffset;
878 //otempvars := listAppend(clockedVars, otempvars);
879 61 GCExt.free(stateeqnsmark);
880 61 GCExt.free(zceqnsmarks);
881
882 61 (ouniqueEqIndex, removedEquations) := BackendEquation.traverseEquationArray(syst.removedEqs, traversedlowEqToSimEqSystem, (ouniqueEqIndex, {}));
883
884 prevClockedVars := {};
885 61 isPrevVar := arrayCreate(BackendVariable.varsSize(syst.orderedVars), false);
886
887
2/2
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 61 times.
258 for cr in subPartition.prevVars loop
888 197 (_, varIxs) := BackendVariable.getVar(cr, syst.orderedVars);
889
2/2
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 197 times.
394 for i in varIxs loop
890 197 arrayUpdate(isPrevVar, i, true);
891 end for;
892 end for;
893
1/2
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
590 for i in 1:BackendVariable.varsSize(syst.orderedVars) loop
894 529 var := BackendVariable.getVarAt(syst.orderedVars, i);
895 529 simVar := dlowvarToSimvar(var, SOME(inShared.aliasVars), inShared.globalKnownVars);
896 529 prevClockedVars := (simVar, isPrevVar[i])::prevClockedVars;
897 529 clockedVars := simVar::clockedVars;
898
2/2
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 332 times.
529 if isPrevVar[i] then
899 197 cr := simVar.name;
900 197 simVar.name := ComponentReference.crefPrefixPrevious(cr);
901 197 clockedVars := simVar::clockedVars;
902 197 simEq := SimCode.SES_SIMPLE_ASSIGN(ouniqueEqIndex, simVar.name, DAE.CREF(cr, simVar.type_), DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
903 197 equations := simEq::equations;
904 197 ouniqueEqIndex := ouniqueEqIndex + 1;
905 end if;
906 end for;
907 61 GCExt.free(isPrevVar);
908
909 //otempvars := listAppend(clockedVars, otempvars);
910 61 simSubPartition := SimCode.SUBPARTITION(prevClockedVars, equations, removedEquations, subPartition.clock, subPartition.holdEvents);
911
912
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 61 times.
61 assert(isNone(simSubPartitions[subPartIdx]), "SimCodeUtil.translateClockedEquations failed");
913 61 arrayUpdate(simSubPartitions, subPartIdx, SOME(simSubPartition));
914
915 end for;
916 1060 outPartitions := createClockedSimPartitions(inShared.partitionsInfo.basePartitions, simSubPartitions);
917 1060 GCExt.free(simSubPartitions);
918 end translateClockedEquations;
919
920 protected function createClockedSimPartitions
921 input array<BackendDAE.BasePartition> basePartitions;
922 input array<Option<SimCode.SubPartition>> subPartitions;
923 output list<SimCode.ClockedPartition> clockedPartitions = {};
924 protected
925 Integer off = 1;
926 BackendDAE.BasePartition basePartition;
927 list<SimCode.SubPartition> simSubPartitions;
928 algorithm
929
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1021 times.
1106 for i in 1:arrayLength(basePartitions) loop
930 46 basePartition := basePartitions[i];
931
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 time.
46 if basePartition.nSubClocks > 0 then
932 45 simSubPartitions := List.map(Array.getRange(off, off + basePartition.nSubClocks - 1, subPartitions), Util.getOption);
933 45 simSubPartitions := listReverse(simSubPartitions);
934 else
935 // we should skip it and remove the base clock but that is quite complicated
936 simSubPartitions := {};
937 end if;
938 46 off := off + basePartition.nSubClocks;
939 46 clockedPartitions := SimCode.CLOCKED_PARTITION(basePartition.clock, simSubPartitions)::clockedPartitions;
940 end for;
941 1060 clockedPartitions := listReverse(clockedPartitions); // in order to keep the correct indexes for the correct clkfire-calls
942 end createClockedSimPartitions;
943
944 public function collectClockedVars "author: rfranke
945 This function collects clocked variables along with their clockIndex"
946 input BackendDAE.EqSystem inEqSystem;
947 input tuple<HashTable.HashTable, Integer> inTpl;
948 output tuple<HashTable.HashTable, Integer> outTpl;
949 protected
950 HashTable.HashTable inHT, outHT;
951 Integer clockIndex;
952 algorithm
953 3920 (inHT, clockIndex) := inTpl;
954 outTpl := match inEqSystem
955 case BackendDAE.EQSYSTEM(partitionKind = BackendDAE.CLOCKED_PARTITION(_)) algorithm
956 61 (outHT, _) := BackendVariable.traverseBackendDAEVars(inEqSystem.orderedVars, collectClockedVars1, (inHT, clockIndex));
957 61 then (outHT, clockIndex + 1);
958 else inTpl;
959 end match;
960 end collectClockedVars;
961
962 protected function collectClockedVars1 "author: rfranke
963 Helper to collectClockedVars"
964 input BackendDAE.Var inVar;
965 input tuple<HashTable.HashTable, Integer> inTpl;
966 output BackendDAE.Var outVar;
967 output tuple<HashTable.HashTable, Integer> outTpl;
968 protected
969 HashTable.HashTable clkHT;
970 Integer clockIndex;
971 DAE.ComponentRef cref;
972 algorithm
973 529 (clkHT, clockIndex) := inTpl;
974 (outVar, outTpl) := match inVar
975 case BackendDAE.VAR(varName=cref) algorithm
976 529 clkHT := BaseHashTable.add((cref, clockIndex), clkHT);
977 529 clkHT := BaseHashTable.add((ComponentReference.crefPrefixPrevious(cref), clockIndex), clkHT);
978 529 then (inVar, (clkHT, clockIndex));
979 else (inVar, inTpl);
980 end match;
981 end collectClockedVars1;
982
983 protected function addTempVars
984 input array<list<SimCodeVar.SimVar>> simVars;
985 input list<SimCodeVar.SimVar> tempVars;
986 protected
987 Integer ix;
988 algorithm
989
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3395 times.
✓ Branch 2 taken 3395 times.
✓ Branch 3 taken 1069 times.
4464 for e in tempVars loop
990 ix := match e.type_
991 case DAE.T_INTEGER() then Integer(SimVarsIndex.intAlg);
992 case DAE.T_ENUMERATION() then Integer(SimVarsIndex.intAlg);
993 case DAE.T_BOOL() then Integer(SimVarsIndex.boolAlg);
994 case DAE.T_STRING() then Integer(SimVarsIndex.stringAlg);
995 else Integer(SimVarsIndex.alg);
996 end match;
997 6790 arrayUpdate(simVars, ix, e::simVars[ix]);
998 end for;
999 end addTempVars;
1000
1001 public function setJacobianVars "author: unknown
1002 Set the given jacobian vars in the given model info. The old jacobian variables will be replaced."
1003 input list<SimCodeVar.SimVar> iJacobianVars;
1004 input SimCode.ModelInfo iModelInfo;
1005 output SimCode.ModelInfo oModelInfo = iModelInfo;
1006 protected
1007 SimCodeVar.SimVars vars;
1008 algorithm
1009
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 362 times.
1069 if not listEmpty(iJacobianVars) then
1010 362 vars := oModelInfo.vars;
1011 362 vars.jacobianVars := iJacobianVars;
1012 362 oModelInfo.vars := vars;
1013 end if;
1014 end setJacobianVars;
1015
1016 public function setSeedVars
1017 "Set the given seed vars in the given model info, replacing old seed vars.
1018 author: rfranke"
1019 input list<SimCodeVar.SimVar> seedVars;
1020 input output SimCode.ModelInfo modelInfo;
1021 protected
1022 SimCodeVar.SimVars vars;
1023 algorithm
1024 1069 vars := modelInfo.vars;
1025 1069 vars.seedVars := seedVars;
1026 1069 modelInfo.vars := vars;
1027 end setSeedVars;
1028
1029 public function addNumEqns
1030 input SimCode.ModelInfo modelInfo;
1031 input Integer numEqns;
1032 output SimCode.ModelInfo omodelInfo = modelInfo;
1033 protected
1034 SimCode.VarInfo varInfo;
1035 algorithm
1036 1069 varInfo := omodelInfo.varInfo;
1037 1069 varInfo.numEquations := numEqns;
1038 1069 omodelInfo.varInfo := varInfo;
1039 end addNumEqns;
1040
1041 protected function getSystemIndexMap
1042 input SimCode.SimEqSystem inEqn;
1043 input array<Integer> inSysIndexMap;
1044 output array<Integer> outSysIndexMap;
1045 algorithm
1046 outSysIndexMap := match inEqn
1047 local
1048 Integer index, systemIndex, index2, systemIndex2;
1049 array<Integer> sysIndexMap;
1050 SimCode.SimEqSystem cont;
1051 list<SimCode.SimEqSystem> eqs, eqs2;
1052
1053 // no dynamic tearing
1054 case SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(index=index, indexLinearSystem=systemIndex), NONE()) algorithm
1055 580 sysIndexMap := arrayUpdate(inSysIndexMap, index, systemIndex);
1056 then sysIndexMap;
1057
1058 case SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(index=index, eqs=eqs, indexNonLinearSystem=systemIndex), NONE()) algorithm
1059 567 sysIndexMap := List.fold(eqs, getSystemIndexMap, inSysIndexMap);
1060 567 sysIndexMap := arrayUpdate(sysIndexMap, index, systemIndex);
1061 then sysIndexMap;
1062
1063 // dynamic tearing
1064 case SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(index=index, indexLinearSystem=systemIndex), SOME(SimCode.LINEARSYSTEM(index=index2, indexLinearSystem=systemIndex2))) algorithm
1065 ✗ arrayUpdate(inSysIndexMap, index, systemIndex);
1066 ✗ sysIndexMap := arrayUpdate(inSysIndexMap, index2, systemIndex2);
1067 then sysIndexMap;
1068
1069 case SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(index=index, eqs=eqs, indexNonLinearSystem=systemIndex) , SOME(SimCode.NONLINEARSYSTEM(index=index2, eqs=eqs2, indexNonLinearSystem=systemIndex2))) algorithm
1070 3 sysIndexMap := List.fold(eqs, getSystemIndexMap, inSysIndexMap);
1071 3 sysIndexMap := arrayUpdate(sysIndexMap, index, systemIndex);
1072 3 sysIndexMap := List.fold(eqs2, getSystemIndexMap, inSysIndexMap);
1073 3 sysIndexMap := arrayUpdate(sysIndexMap, index2, systemIndex2);
1074 then sysIndexMap;
1075
1076 case SimCode.SES_MIXED(cont=cont, index=index, indexMixedSystem=systemIndex) algorithm
1077 ✗ getSystemIndexMap(cont, inSysIndexMap);
1078 ✗ sysIndexMap := arrayUpdate(inSysIndexMap, index, systemIndex);
1079 then sysIndexMap;
1080
1081 else inSysIndexMap;
1082 end match;
1083 end getSystemIndexMap;
1084
1085 protected function setSystemIndexMap "
1086 updates index of strong components systems"
1087 input SimCode.SimEqSystem inEqn;
1088 input array<Integer> inSysIndexMap;
1089 output SimCode.SimEqSystem outEqn;
1090 algorithm
1091 outEqn := match inEqn
1092 local
1093 Integer index, sysIndex;
1094 SimCode.LinearSystem lSystem;
1095 SimCode.NonlinearSystem nlSystem;
1096 Option<SimCode.LinearSystem> alternativeTearingL;
1097 Option<SimCode.NonlinearSystem> alternativeTearingNL;
1098 SimCode.SimEqSystem simEq;
1099 SimCode.SimEqSystem cont;
1100
1101 case simEq as SimCode.SES_LINEAR(lSystem=lSystem, alternativeTearing=alternativeTearingL) algorithm
1102 580 sysIndex := inSysIndexMap[lSystem.index];
1103 580 lSystem.indexLinearSystem := sysIndex;
1104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 580 times.
580 simEq.lSystem := lSystem;
1105 // dynamic tearing
1106
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 580 times.
580 if isSome(alternativeTearingL) then
1107 ✗ lSystem := Util.getOption(alternativeTearingL);
1108 ✗ sysIndex := inSysIndexMap[lSystem.index];
1109 ✗ lSystem.indexLinearSystem := sysIndex;
1110 alternativeTearingL := SOME(lSystem);
1111 ✗ simEq.alternativeTearing := alternativeTearingL;
1112 end if;
1113 then simEq;
1114
1115 case simEq as SimCode.SES_NONLINEAR(nlSystem=nlSystem, alternativeTearing=alternativeTearingNL) algorithm
1116 570 sysIndex := inSysIndexMap[nlSystem.index];
1117 570 nlSystem.indexNonLinearSystem := sysIndex;
1118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 570 times.
570 simEq.nlSystem := nlSystem;
1119 // dynamic tearing
1120
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 570 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 567 times.
570 if isSome(alternativeTearingNL) then
1121 3 nlSystem := Util.getOption(alternativeTearingNL);
1122 3 sysIndex := inSysIndexMap[nlSystem.index];
1123 3 nlSystem.indexNonLinearSystem := sysIndex;
1124 alternativeTearingNL := SOME(nlSystem);
1125 3 simEq.alternativeTearing := alternativeTearingNL;
1126 end if;
1127 then simEq;
1128
1129 case simEq as SimCode.SES_MIXED(cont=cont) algorithm
1130 ✗ sysIndex := inSysIndexMap[simEq.index];
1131 ✗ cont := setSystemIndexMap(cont, inSysIndexMap);
1132 ✗ simEq.cont := cont;
1133 ✗ simEq.indexMixedSystem := sysIndex;
1134 then simEq;
1135
1136 else
1137 then inEqn;
1138 end match;
1139 end setSystemIndexMap;
1140
1141 public function addAlgebraicLoopsModelInfo "
1142 Adds algebraic loops from list of SimEqSystem into ModelInfo
1143 and SimEqSystem equation algebraic system index."
1144 input output list<SimCode.SimEqSystem> eqns;
1145 input output SimCode.ModelInfo modelInfo;
1146 input Boolean addNLSToModelInfo = true "If false, nonlinear systems found here are indexed but not added to
1147 modelInfo.nonLinearSystems. Used when recursing into the inner equations of a nonlinear system, because the
1148 code generation templates already emit those nested nonlinear systems from within their parent (see
1149 generateNonLinearResidualFunction / generateNonLinearSystemData in CodegenC.tpl). Adding them here as well
1150 leads to duplicate residualFunc/initializeStaticDataNLS/... definitions and a C compiler error (#15433).";
1151 output list<SimCode.JacobianMatrix> symJacs = {};
1152 protected
1153 list<SimCode.SimEqSystem> resEqns = {};
1154 algorithm
1155
2/2
✓ Branch 0 taken 364457 times.
✓ Branch 1 taken 9683 times.
374140 for eqn in eqns loop
1156 eqn := match eqn
1157 local
1158 SimCode.NonlinearSystem nlSyst, altNlSyst;
1159 Option<SimCode.NonlinearSystem> optNlSyst;
1160 SimCode.LinearSystem linearSyst, altLinearSyst;
1161 Option<SimCode.LinearSystem> optLinearSyst;
1162 SimCode.SimEqSystem system;
1163 BackendDAE.EquationAttributes eqAttr;
1164
1165 // nonlinear case
1166 case SimCode.SES_NONLINEAR(nlSystem=nlSyst as SimCode.NONLINEARSYSTEM(), alternativeTearing=optNlSyst, eqAttr=eqAttr) algorithm
1167
1168 1084 (nlSyst, modelInfo, symJacs) := updateNonLinearSyst(nlSyst, modelInfo, symJacs);
1169
1170 // process the alternative system
1171
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1084 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1081 times.
1084 if isSome(optNlSyst) then
1172 3 altNlSyst := Util.getOption(optNlSyst);
1173 3 (altNlSyst, modelInfo, symJacs) := updateNonLinearSyst(altNlSyst, modelInfo, symJacs);
1174 optNlSyst := SOME(altNlSyst);
1175 end if;
1176 1084 system := SimCode.SES_NONLINEAR(nlSyst, optNlSyst, eqAttr);
1177 // Only add top-level nonlinear systems to modelInfo. Nested ones (inner equations of another
1178 // nonlinear system) are emitted by the templates from within their parent, so adding them here
1179 // too would generate duplicate C functions (ticket #15433).
1180
1/2
✓ Branch 0 taken 1084 times.
✗ Branch 1 not taken.
1084 if addNLSToModelInfo then
1181 2168 modelInfo.nonLinearSystems := system::modelInfo.nonLinearSystems;
1182 end if;
1183 then system;
1184
1185 // linear case
1186 case SimCode.SES_LINEAR(lSystem=linearSyst as SimCode.LINEARSYSTEM(), alternativeTearing=optLinearSyst, eqAttr=eqAttr) algorithm
1187
1188 1109 (linearSyst, modelInfo, symJacs) := updateLinearSyst(linearSyst, modelInfo, symJacs);
1189
1190 // process the alternative system
1191
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1109 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1109 times.
1109 if isSome(optLinearSyst) then
1192 ✗ altLinearSyst := Util.getOption(optLinearSyst);
1193 ✗ (altLinearSyst, modelInfo, symJacs) := updateLinearSyst(altLinearSyst, modelInfo, symJacs);
1194 optLinearSyst := SOME(altLinearSyst);
1195 end if;
1196 1109 system := SimCode.SES_LINEAR(linearSyst, optLinearSyst, eqAttr);
1197 2218 modelInfo.linearSystems := system::modelInfo.linearSystems;
1198 then system;
1199
1200 else eqn;
1201 end match;
1202 resEqns := eqn::resEqns;
1203 end for;
1204 9683 eqns := listReverse(resEqns);
1205 end addAlgebraicLoopsModelInfo;
1206
1207 protected function updateNonLinearSyst
1208 "Helper function of addAlgebraicLoopsModelInfo
1209 Updates nonlinear system indexes"
1210 input output SimCode.NonlinearSystem inSyst = inSyst;
1211 input output SimCode.ModelInfo modelInfo = modelInfo;
1212 input output list<SimCode.JacobianMatrix> allSymJacs = allSymJacs;
1213 protected
1214 SimCode.VarInfo varInfo = modelInfo.varInfo;
1215 list<SimCode.SimEqSystem> eqs;
1216 SimCode.JacobianMatrix tmpSymJac;
1217 list<SimCode.JacobianMatrix> tmpSymJacs;
1218 constant Boolean debug = false;
1219 algorithm
1220
1221 // set system index and count
1222 1087 inSyst.indexNonLinearSystem := varInfo.numNonLinearSystems;
1223 1087 varInfo.numNonLinearSystems := varInfo.numNonLinearSystems+1;
1224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1087 times.
1087 modelInfo.varInfo := varInfo;
1225
1226 // collect the jacobian
1227
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1087 times.
✓ Branch 2 taken 888 times.
✓ Branch 3 taken 199 times.
1087 if isSome(inSyst.jacobianMatrix) then
1228 888 tmpSymJac := Util.getOption(inSyst.jacobianMatrix);
1229 // add only if the directional derivativ is available and
1230 // not just the sparsty pattern
1231
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 565 times.
888 if not listEmpty(tmpSymJac.columns) then
1232
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 323 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 323 times.
323 ({tmpSymJac}, modelInfo, tmpSymJacs) := addAlgebraicLoopsModelInfoSymJacs({tmpSymJac}, modelInfo);
1233 323 inSyst.jacobianMatrix := SOME(tmpSymJac);
1234 323 allSymJacs := listAppend(tmpSymJacs, allSymJacs);
1235 allSymJacs := tmpSymJac::allSymJacs;
1236 end if;
1237 end if;
1238
1239 // proceed inSyst.eqs
1240 // Index the inner (nested) systems, but do NOT add nested nonlinear systems to modelInfo.nonLinearSystems:
1241 // the templates emit them from within this parent nonlinear system (ticket #15433). Nested linear systems
1242 // are still added because the linear templates do not recurse into inner equations.
1243 1087 (eqs, modelInfo, tmpSymJacs) := addAlgebraicLoopsModelInfo(inSyst.eqs, modelInfo, addNLSToModelInfo = false);
1244 1087 inSyst.eqs := eqs;
1245 1087 allSymJacs := listAppend(tmpSymJacs, allSymJacs);
1246
1247 if debug then
1248 print("Update nonlinear system " + intString(inSyst.indexNonLinearSystem) +
1249 " collected Jacobians: " + intString(listLength(allSymJacs)) + "\n");
1250 end if;
1251 end updateNonLinearSyst;
1252
1253 protected function updateLinearSyst
1254 "Helper function of addAlgebraicLoopsModelInfo
1255 Updates linear system indexes"
1256 input output SimCode.LinearSystem inSyst = inSyst;
1257 input output SimCode.ModelInfo modelInfo = modelInfo;
1258 input output list<SimCode.JacobianMatrix> allSymJacs = allSymJacs;
1259 protected
1260 SimCode.VarInfo varInfo = modelInfo.varInfo;
1261 list<SimCode.SimEqSystem> eqs;
1262 SimCode.JacobianMatrix tmpSymJac;
1263 list<SimCode.JacobianMatrix> tmpSymJacs;
1264 constant Boolean debug = false;
1265 algorithm
1266
1267 // set system index and count
1268 1109 inSyst.indexLinearSystem := varInfo.numLinearSystems;
1269 1109 varInfo.numLinearSystems := varInfo.numLinearSystems+1;
1270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1109 times.
1109 modelInfo.varInfo := varInfo;
1271
1272 // collect the jacobian
1273
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1109 times.
✓ Branch 2 taken 965 times.
✓ Branch 3 taken 144 times.
1109 if isSome(inSyst.jacobianMatrix) then
1274 965 tmpSymJac := Util.getOption(inSyst.jacobianMatrix);
1275 // add only if the directional derivativ is available and
1276 // not just the sparsty pattern
1277
1/2
✓ Branch 0 taken 965 times.
✗ Branch 1 not taken.
965 if not listEmpty(tmpSymJac.columns) then
1278
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 965 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 965 times.
965 ({tmpSymJac}, modelInfo, tmpSymJacs) := addAlgebraicLoopsModelInfoSymJacs({tmpSymJac}, modelInfo);
1279 965 inSyst.jacobianMatrix := SOME(tmpSymJac);
1280 965 allSymJacs := listAppend(tmpSymJacs, allSymJacs);
1281 allSymJacs := tmpSymJac::allSymJacs;
1282 end if;
1283 end if;
1284
1285 // proceed inSyst.eqs
1286 // Keep addNLSToModelInfo = true (default) here: the linear templates do not recurse into inner equations,
1287 // so any nonlinear system nested inside this linear system must stay in modelInfo.nonLinearSystems.
1288 1109 (eqs, modelInfo, tmpSymJacs) := addAlgebraicLoopsModelInfo(inSyst.residual, modelInfo);
1289 1109 inSyst.residual := eqs;
1290 1109 allSymJacs := listAppend(tmpSymJacs, allSymJacs);
1291
1292 if debug then
1293 print("Update linear system " + intString(inSyst.indexLinearSystem) +
1294 " collected Jacobians: " + intString(listLength(allSymJacs)) + "\n");
1295 end if;
1296 end updateLinearSyst;
1297
1298 public function addAlgebraicLoopsModelInfoSymJacs "
1299 Adds algebraic loops from list of SimEqSystem into ModelInfo
1300 and SimEqSystem equation algebraic system index."
1301 input output list<SimCode.JacobianMatrix> symjacs;
1302 input output SimCode.ModelInfo modelInfo;
1303 output list<SimCode.JacobianMatrix> outSymJacsInSymJacs = {};
1304 protected
1305 SimCode.JacobianColumn column;
1306 list<SimCode.SimEqSystem> eqs;
1307 SimCode.VarInfo varInfo;
1308 list<SimCode.JacobianMatrix> tmpSymJacs;
1309 list<SimCode.JacobianMatrix> outSymJacs = {};
1310 constant Boolean debug = false;
1311 algorithm
1312
2/2
✓ Branch 0 taken 8817 times.
✓ Branch 1 taken 2428 times.
11245 for symjac in symjacs loop
1313 8817 varInfo := modelInfo.varInfo;
1314 8817 symjac.jacobianIndex := varInfo.numJacobians;
1315 8817 varInfo.numJacobians := varInfo.numJacobians + 1;
1316 8817 modelInfo.varInfo := varInfo;
1317 if debug then
1318 print("Collect Jacobian " + symjac.matrixName + " and set index to: " + intString(symjac.jacobianIndex) + "\n");
1319 end if;
1320 try
1321
3/4
✓ Branch 0 taken 6718 times.
✓ Branch 1 taken 2099 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2099 times.
8817 column::{} := symjac.columns;
1322 2099 (eqs, modelInfo, tmpSymJacs) := addAlgebraicLoopsModelInfo(column.columnEqns, modelInfo);
1323 // set partition index to number of clocks (max index) for now.
1324 // TODO: use actual clock index to support multirate systems
1325
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2099 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 2099 times.
2112 tmpSymJacs := list(rewriteJacPartIdx(a, modelInfo.nSubClocks) for a in tmpSymJacs);
1326 2099 outSymJacsInSymJacs := listAppend(tmpSymJacs, outSymJacsInSymJacs);
1327 2099 column.columnEqns := eqs;
1328 2099 symjac.columns := {column};
1329 outSymJacs := symjac::outSymJacs;
1330 else
1331 outSymJacs := symjac::outSymJacs;
1332 end try;
1333 end for;
1334 2428 symjacs := listReverse(outSymJacs);
1335 2428 outSymJacsInSymJacs := listReverse(outSymJacsInSymJacs);
1336 end addAlgebraicLoopsModelInfoSymJacs;
1337
1338 public function addAlgebraicLoopsModelInfoStateSets
1339 " function to collect jacobians for statesets"
1340 input list<SimCode.StateSet> inSets;
1341 input SimCode.ModelInfo inModelInfo;
1342 output list<SimCode.StateSet> outSets = {};
1343 output SimCode.ModelInfo modelInfo = inModelInfo;
1344 output list<SimCode.JacobianMatrix> outSymJacs = {};
1345 output list<SimCode.JacobianMatrix> outSymJacsInternal = {};
1346 protected
1347 SimCode.JacobianMatrix symJac;
1348 list<SimCode.JacobianMatrix> tmpSymJacs;
1349 algorithm
1350
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1060 times.
1081 for set in inSets loop
1351
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21 times.
21 ({symJac}, modelInfo, tmpSymJacs) := addAlgebraicLoopsModelInfoSymJacs({set.jacobianMatrix}, modelInfo);
1352 21 outSymJacsInternal := listAppend(tmpSymJacs, outSymJacsInternal);
1353 21 set.jacobianMatrix := symJac;
1354 outSymJacs := symJac::outSymJacs;
1355 outSets := set::outSets;
1356 end for;
1357 1060 outSets := listReverse(outSets);
1358 1060 outSymJacs := listReverse(outSymJacs);
1359 1060 outSymJacsInternal := listReverse(outSymJacsInternal);
1360 end addAlgebraicLoopsModelInfoStateSets;
1361
1362 protected function addAlgebraicLoopsClockPartitions "
1363 function to process clockPartitions for symbolic jacobians"
1364 input list<SimCode.ClockedPartition> inColockPartition;
1365 input SimCode.ModelInfo inModelInfo;
1366 output list<SimCode.ClockedPartition> outColockPartition = {};
1367 output SimCode.ModelInfo modelInfo = inModelInfo;
1368 output list<SimCode.JacobianMatrix> outSymJacs = {};
1369 protected
1370 SimCode.SubPartition subPartitionTmp;
1371 SimCode.ClockedPartition clockPartitionTmp;
1372 list<SimCode.SubPartition> subPartitionsTmp;
1373 list<SimCode.SimEqSystem> equations;
1374 list<SimCode.JacobianMatrix> tmpJacs;
1375 Integer clockIndex = 0;
1376 algorithm
1377
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1060 times.
1106 for clockPartion in inColockPartition loop
1378 subPartitionsTmp := {};
1379
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 46 times.
107 for subPartion in clockPartion.subPartitions loop
1380 61 clockIndex := clockIndex + 1;
1381 61 (equations, modelInfo, tmpJacs) := addAlgebraicLoopsModelInfo(subPartion.equations, modelInfo);
1382
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 61 times.
61 tmpJacs := list(rewriteJacPartIdx(a,clockIndex) for a in tmpJacs);
1383 61 outSymJacs := listAppend(tmpJacs, outSymJacs);
1384 61 subPartitionTmp := SimCode.SUBPARTITION(
1385 subPartion.vars,
1386 equations,
1387 subPartion.removedEquations,
1388 subPartion.subClock,
1389 subPartion.holdEvents);
1390 subPartitionsTmp := subPartitionTmp::subPartitionsTmp;
1391 end for;
1392 46 clockPartitionTmp := SimCode.CLOCKED_PARTITION(clockPartion.baseClock, listReverse(subPartitionsTmp));
1393 outColockPartition := clockPartitionTmp::outColockPartition;
1394 end for;
1395 1060 outColockPartition := listReverse(outColockPartition);
1396 end addAlgebraicLoopsClockPartitions;
1397
1398 protected function rewriteJacPartIdx
1399 input SimCode.JacobianMatrix inJac;
1400 input Integer index;
1401 output SimCode.JacobianMatrix outJac = inJac;
1402 algorithm
1403 38 outJac.partitionIndex := index;
1404 end rewriteJacPartIdx;
1405
1406 // =============================================================================
1407 // section to create SimCode.Equations from BackendDAE.Equation
1408 //
1409 // =============================================================================
1410
1411
1412 protected type CreateEquationsForSystemsFold =
1413 tuple<Integer /*uniqueEqIndex*/,
1414 list<list<SimCode.SimEqSystem>> /*odeEquations*/,
1415 list<list<SimCode.SimEqSystem>> /*algebraicEquations*/,
1416 list<SimCode.SimEqSystem> /*allEquations*/,
1417 list<SimCode.SimEqSystem> /*equationsForZeroCrossings*/,
1418 list<SimCodeVar.SimVar> /*tempvars*/,
1419 list<tuple<Integer,Integer>> /*eqSccMapping*/,
1420 list<tuple<Integer,Integer>> /*eqBackendSimCodeMapping*/,
1421 SimCode.BackendMapping /*backendSimCodeMapping*/,
1422 Integer /*sccOffset*/>;
1423 protected type CreateEquationsForSystemsArg = tuple<BackendDAE.Shared, Boolean>;
1424
1425 protected function createEquationsForSystems "Some kind of comments would be very helpful!"
1426 input BackendDAE.EqSystems inSysts;
1427 input BackendDAE.Shared shared;
1428 input Integer iuniqueEqIndex;
1429 input list<BackendDAE.ZeroCrossing> inAllZeroCrossings;
1430 input list<SimCodeVar.SimVar> itempvars;
1431 input Integer iSccOffset; //to map the generated equations to the old strongcomponents, they are numbered from (1+offset) to (n+offset)
1432 input SimCode.BackendMapping iBackendMapping;
1433 input Boolean createAlgebraicEquations;
1434 output Integer ouniqueEqIndex;
1435 output list<list<SimCode.SimEqSystem>> oodeEquations;
1436 output list<list<SimCode.SimEqSystem>> oalgebraicEquations;
1437 output list<SimCode.SimEqSystem> olocalKnownVars;
1438 output list<SimCode.SimEqSystem> oallEquations;
1439 output list<SimCode.SimEqSystem> oequationsForZeroCrossings;
1440 output list<SimCodeVar.SimVar> otempvars;
1441 output list<tuple<Integer,Integer>> oeqSccMapping;
1442 output list<tuple<Integer,Integer>> oeqBackendSimCodeMapping;
1443 output SimCode.BackendMapping obackendMapping;
1444 output Integer oSccOffset;
1445 protected
1446 CreateEquationsForSystemsFold foldArg;
1447 CreateEquationsForSystemsArg arg;
1448 array<AvlSetInt.Tree> zcVars;
1449 Integer sysIdx = 0;
1450 algorithm
1451 try
1452
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2164 times.
2188 arg := (shared, createAlgebraicEquations);
1453 2176 zcVars := BackendDAEUtil.zeroCrossingVarIndices(inSysts, inAllZeroCrossings);
1454 2176 foldArg := (iuniqueEqIndex, {}, {}, {}, {}, itempvars, {}, {}, iBackendMapping, iSccOffset);
1455
2/2
✓ Branch 0 taken 51273 times.
✓ Branch 1 taken 2176 times.
53449 for syst in inSysts loop
1456 51273 sysIdx := sysIdx + 1;
1457 51273 foldArg := createEquationsForSystems1(syst, arrayGet(zcVars, sysIdx), arg, foldArg);
1458 end for;
1459 2176 (ouniqueEqIndex, oodeEquations, oalgebraicEquations, oallEquations, oequationsForZeroCrossings, otempvars,
1460 oeqSccMapping, oeqBackendSimCodeMapping, obackendMapping, oSccOffset) := foldArg;
1461 2176 oequationsForZeroCrossings := Dangerous.listReverseInPlace(oequationsForZeroCrossings);
1462
2/2
✓ Branch 2 taken 1072 times.
✓ Branch 3 taken 1104 times.
2176 (ouniqueEqIndex, olocalKnownVars) := BackendVariable.traverseBackendDAEVars(shared.localKnownVars, traverseKnVarsToSimEqSystem, (ouniqueEqIndex, {}));
1463 else
1464 ✗ Error.addInternalError(getInstanceName() + " failed", sourceInfo());
1465 ✗ fail();
1466 end try;
1467 end createEquationsForSystems;
1468
1469 protected function createEquationsForSystems1
1470 input BackendDAE.EqSystem inSyst;
1471 input AvlSetInt.Tree zcVars "this system's variables occurring in a zero crossing";
1472 input CreateEquationsForSystemsArg inArg;
1473 input CreateEquationsForSystemsFold inFold;
1474 output CreateEquationsForSystemsFold outFold;
1475 algorithm
1476 outFold := match inSyst.matching
1477 local
1478 list<SimCode.SimEqSystem> odeEquations1, algebraicEquations1, allEquations1;
1479 BackendDAE.StrongComponents comps;
1480 BackendDAE.EqSystem syst;
1481 list<list<SimCode.SimEqSystem>> odeEquations, algebraicEquations;
1482 list<SimCode.SimEqSystem> allEquations;
1483 list<SimCode.SimEqSystem> equationsForZeroCrossings, equationsForZeroCrossings1;
1484 Integer uniqueEqIndex, sccOffset;
1485 array<Integer> ass1, stateeqnsmark, zceqnsmarks;
1486 list<SimCodeVar.SimVar> tempvars;
1487 AvlTreePathFunction.Tree funcs;
1488 list<tuple<Integer,Integer>> eqSccMapping, eqBackendSimCodeMapping;
1489 SimCode.BackendMapping backendMapping;
1490 BackendDAE.Shared shared;
1491 Boolean createAlgebraicEquations;
1492 case BackendDAE.MATCHING(ass1=ass1, comps=comps)
1493 algorithm
1494
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51273 times.
51273 if Flags.isSet(Flags.BLT_MATRIX_DUMP) then
1495 ✗ BackendDump.dumpEqSystemBLTmatrixHTML(inSyst);
1496 end if;
1497
1498 51273 (shared, createAlgebraicEquations) := inArg;
1499 51273 (uniqueEqIndex, odeEquations, algebraicEquations, allEquations, equationsForZeroCrossings, tempvars,
1500 eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccOffset) := inFold;
1501
1502 51273 funcs := BackendDAEUtil.getFunctions(shared);
1503 102546 (syst, _, _) := BackendDAEUtil.getAdjacencyMatrixfromOption(inSyst, BackendDAE.ABSOLUTE(), SOME(funcs), BackendDAEUtil.isInitializationDAE(shared));
1504
1505 51273 stateeqnsmark := arrayCreate(BackendDAEUtil.equationArraySizeDAE(syst), 0);
1506 51273 zceqnsmarks := arrayCreate(BackendDAEUtil.equationArraySizeDAE(syst), 0);
1507 51273 stateeqnsmark := BackendDAEUtil.markStateEquations(syst, stateeqnsmark, ass1);
1508 51273 zceqnsmarks := BackendDAEUtil.markZeroCrossingEquations(syst, zcVars, zceqnsmarks, ass1);
1509
1510 51273 (odeEquations1, algebraicEquations1, allEquations1, equationsForZeroCrossings1, uniqueEqIndex,
1511 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping) :=
1512 createEquationsForSystem(
1513 stateeqnsmark, zceqnsmarks, syst, shared, comps, uniqueEqIndex, tempvars,
1514 sccOffset, eqSccMapping, eqBackendSimCodeMapping, backendMapping, createAlgebraicEquations);
1515 51273 GCExt.free(stateeqnsmark);
1516 51273 GCExt.free(zceqnsmarks);
1517
1518 51273 odeEquations := List.consOnTrue(not listEmpty(odeEquations1), odeEquations1, odeEquations);
1519 51273 algebraicEquations := List.consOnTrue(not listEmpty(algebraicEquations1), algebraicEquations1, algebraicEquations);
1520 51273 allEquations := List.append_reverse(allEquations1, allEquations);
1521 51273 equationsForZeroCrossings := List.append_reverse(equationsForZeroCrossings1, equationsForZeroCrossings);
1522
1523 51273 then ( uniqueEqIndex, odeEquations, algebraicEquations, allEquations, equationsForZeroCrossings, tempvars,
1524 eqSccMapping, eqBackendSimCodeMapping, backendMapping, listLength(comps) + sccOffset );
1525
1526 else inFold;
1527 end match;
1528 end createEquationsForSystems1;
1529
1530 protected type CreateEquationsForSystemFold =
1531 tuple<Integer /*uniqueEqIndex*/,
1532 list<list<SimCode.SimEqSystem>> /*odeEquations*/,
1533 list<list<SimCode.SimEqSystem>> /*algebraicEquations*/,
1534 list<list<SimCode.SimEqSystem>> /*allEquations*/,
1535 list<list<SimCode.SimEqSystem>> /*equationsForZeroCrossings*/,
1536 list<SimCodeVar.SimVar> /*tempvars*/,
1537 list<tuple<Integer,Integer>> /*eqSccMapping*/,
1538 list<tuple<Integer,Integer>> /*eqBackendSimCodeMapping*/,
1539 SimCode.BackendMapping /*backendSimCodeMapping*/,
1540 Integer /*sccOffset*/>;
1541 protected type CreateEquationsForSystemArg =
1542 tuple<array<Integer> /*stateeqnsmark*/, array<Integer> /*zceqnsmark*/,
1543 BackendDAE.EqSystem /*syst*/, BackendDAE.Shared /*shared*/, Boolean>;
1544
1545 protected function createEquationsForSystem
1546 input array<Integer> stateeqnsmark;
1547 input array<Integer> zceqnsmark;
1548 input BackendDAE.EqSystem syst;
1549 input BackendDAE.Shared shared;
1550 input BackendDAE.StrongComponents comps;
1551 input Integer iuniqueEqIndex;
1552 input list<SimCodeVar.SimVar> itempvars;
1553 input Integer iSccIndex;
1554 input list<tuple<Integer,Integer>> ieqSccMapping;
1555 input list<tuple<Integer,Integer>> ieqBackendSimCodeMapping;
1556 input SimCode.BackendMapping iBackendMapping;
1557 input Boolean createAlgebraicEquations;
1558 output list<SimCode.SimEqSystem> outOdeEquations;
1559 output list<SimCode.SimEqSystem> outAlgebraicEquations;
1560 output list<SimCode.SimEqSystem> outAllEquations;
1561 output list<SimCode.SimEqSystem> outEquationsforZeroCrossings;
1562 output Integer ouniqueEqIndex;
1563 output list<SimCodeVar.SimVar> otempvars;
1564 output list<tuple<Integer,Integer>> oeqSccMapping;
1565 output list<tuple<Integer,Integer>> oeqBackendSimCodeMapping;
1566 output SimCode.BackendMapping oBackendMapping;
1567 protected
1568 CreateEquationsForSystemFold foldArg;
1569 CreateEquationsForSystemArg arg;
1570 list<list<SimCode.SimEqSystem>> odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings;
1571 algorithm
1572
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 51316 times.
51352 arg := (stateeqnsmark, zceqnsmark, syst, shared, createAlgebraicEquations);
1573 51334 foldArg := (iuniqueEqIndex, {}, {}, {}, {}, itempvars, ieqSccMapping, ieqBackendSimCodeMapping, iBackendMapping, iSccIndex);
1574 51334 foldArg := List.fold2(comps, createEquationsForSystem1, arg, partitionKindToClockIndex(syst.partitionKind), foldArg);
1575 51334 (ouniqueEqIndex, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1576 otempvars, oeqSccMapping, oeqBackendSimCodeMapping, oBackendMapping, _) := foldArg;
1577 51334 outOdeEquations := List.flattenReverse(odeEquations);
1578 51334 outAlgebraicEquations := List.flattenReverse(algebraicEquations);
1579 51334 outAllEquations := List.flattenReverse(allEquations);
1580 51334 outEquationsforZeroCrossings := List.flattenReverse(equationsforZeroCrossings);
1581 end createEquationsForSystem;
1582
1583 protected function addEquationsToLists
1584 input list<SimCode.SimEqSystem> inEq;
1585 input array<Integer> stateeqnsmark;
1586 input array<Integer> zceqnsmark;
1587 input list<Integer> eqsIdx;
1588 input list<list<SimCode.SimEqSystem>> inOdeEquations;
1589 input list<list<SimCode.SimEqSystem>> inAlgebraicEquations;
1590 input list<list<SimCode.SimEqSystem>> inAllEquations;
1591 input list<list<SimCode.SimEqSystem>> inEquationsforZeroCrossings;
1592 output list<list<SimCode.SimEqSystem>> outOdeEquations;
1593 output list<list<SimCode.SimEqSystem>> outAlgebraicEquations;
1594 output list<list<SimCode.SimEqSystem>> outAllEquations;
1595 output list<list<SimCode.SimEqSystem>> outEquationsforZeroCrossings;
1596 protected
1597 Boolean bdynamic "block is dynamic, belongs to dynamic section";
1598 Boolean bzceqns "block needs to evaluate zeroCrossings";
1599 algorithm
1600 143576 bdynamic := BackendDAEUtil.blockIsDynamic(eqsIdx, stateeqnsmark);
1601 143576 bzceqns := BackendDAEUtil.blockIsDynamic(eqsIdx, zceqnsmark);
1602
2/2
✓ Branch 0 taken 19489 times.
✓ Branch 1 taken 124087 times.
143576 outOdeEquations := if bdynamic then inEq::inOdeEquations else inOdeEquations;
1603
2/2
✓ Branch 0 taken 124087 times.
✓ Branch 1 taken 19489 times.
143576 outAlgebraicEquations := if not bdynamic then inEq::inAlgebraicEquations else inAlgebraicEquations;
1604 outAllEquations := inEq::inAllEquations;
1605
2/2
✓ Branch 0 taken 4349 times.
✓ Branch 1 taken 139227 times.
143576 outEquationsforZeroCrossings := if bzceqns then inEq::inEquationsforZeroCrossings else inEquationsforZeroCrossings;
1606 end addEquationsToLists;
1607
1608 protected function createEquationsForSystem1
1609 input BackendDAE.StrongComponent comp;
1610 input CreateEquationsForSystemArg inArg;
1611 input Option<Integer> clockIndex;
1612 input CreateEquationsForSystemFold inFold;
1613 output CreateEquationsForSystemFold outFold;
1614 protected
1615 array<Integer> stateeqnsmark;
1616 array<Integer> zceqnsmark;
1617 BackendDAE.EqSystem syst;
1618 BackendDAE.Shared shared;
1619 Integer uniqueEqIndex, sccIndex;
1620 list<SimCodeVar.SimVar> tempvars;
1621 list<tuple<Integer,Integer>> eqSccMapping, eqBackendSimCodeMapping;
1622 SimCode.BackendMapping backendMapping;
1623 list<list<SimCode.SimEqSystem>> odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings;
1624 list<Integer> eqsIdx,varIdx;
1625 list<BackendDAE.Var> varlst;
1626 list<BackendDAE.Equation> eqnlst;
1627 Boolean createAlgebraicEquations, bdynamic, skip;
1628 Boolean debug = false;
1629 algorithm
1630 144000 (stateeqnsmark, zceqnsmark, syst, shared, createAlgebraicEquations) := inArg;
1631 144000 (uniqueEqIndex, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1632 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex) := inFold;
1633 144000 (varlst,varIdx,eqnlst,eqsIdx) := BackendDAEUtil.getStrongComponentVarsAndEquations(comp, syst.orderedVars, syst.orderedEqs);
1634 144000 bdynamic := BackendDAEUtil.blockIsDynamic(eqsIdx, stateeqnsmark);
1635
1636 skip := false;
1637
1638 if debug then
1639 print("Proceed component: " + BackendDump.strongComponentString(comp) + "\n");
1640 BackendDump.dumpEquationList(eqnlst,"Equations:");
1641 BackendDump.dumpVarList(varlst,"Variables:");
1642 end if;
1643 // skip is when equations
1644 144000 skip := List.all(eqnlst, BackendEquation.isWhenEquation);
1645 // skip is discrete
1646
4/4
✓ Branch 0 taken 143576 times.
✓ Branch 1 taken 424 times.
✓ Branch 3 taken 10440 times.
✓ Branch 4 taken 133136 times.
144000 skip := skip or List.all(varlst, BackendVariable.isVarDiscrete);
1647
1648 outFold := match comp
1649 local
1650 Integer e, index, vindex, firstEqIndex, uniqueEqIndex1;
1651 BackendDAE.Equation eqn;
1652 SimCode.SimEqSystem firstSES;
1653
1654 list<Integer> eqnslst;
1655 list<SimCode.SimEqSystem> equations1, noDiscEquations1;
1656 String message;
1657
1658 case _ guard not (createAlgebraicEquations or bdynamic) or skip and not createAlgebraicEquations
1659 2 then (uniqueEqIndex, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1660 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex);
1661
1662 case BackendDAE.SINGLEEQUATION(eqn=index, var=vindex)
1663 algorithm
1664 139473 (equations1, uniqueEqIndex1, tempvars) := createEquation(index, vindex, syst, shared, false, uniqueEqIndex, tempvars, {});
1665
1/2
✓ Branch 0 taken 139473 times.
✗ Branch 1 not taken.
139473 if not listEmpty(equations1) then
1666 139473 firstSES := listHead(equations1); // check if the all equations occur with this index in the c file
1667
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 139473 times.
139473 firstEqIndex := if isSimEqSys(firstSES) then uniqueEqIndex1-1 else uniqueEqIndex;
1668 139473 eqSccMapping := appendSccIdxRange(firstEqIndex, uniqueEqIndex1 - 1, sccIndex, eqSccMapping);
1669 139473 eqBackendSimCodeMapping := appendSccIdxRange(firstEqIndex, uniqueEqIndex1 - 1, index, eqBackendSimCodeMapping);
1670 139473 backendMapping := setEqMapping(List.intRange2(firstEqIndex, uniqueEqIndex1 - 1), {index}, backendMapping);
1671 end if;
1672
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 139473 times.
139473 if BackendEquation.isWhenEquation(BackendEquation.get(syst.orderedEqs, index)) then
1673 ✗ allEquations := equations1::allEquations;
1674 else
1675 139473 (odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings) :=
1676 addEquationsToLists(equations1, stateeqnsmark, zceqnsmark, {index}, odeEquations,
1677 algebraicEquations, allEquations, equationsforZeroCrossings);
1678 end if;
1679 139473 then (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1680 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex + 1);
1681
1682 // A single array equation
1683 case BackendDAE.SINGLEARRAY(eqn=e)
1684 algorithm
1685 529 (eqnlst, varlst,_) := BackendDAETransform.getEquationAndSolvedVar(comp, syst.orderedEqs, syst.orderedVars);
1686 // States are solved for der(x) not x.
1687 529 varlst := List.map(varlst, BackendVariable.transformXToXd);
1688 529 (equations1,_, uniqueEqIndex1, tempvars) := createSingleArrayEqnCode(true, eqnlst, varlst, uniqueEqIndex, tempvars, shared);
1689
1690 529 eqSccMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, sccIndex, eqSccMapping);
1691 529 eqBackendSimCodeMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, e, eqBackendSimCodeMapping);
1692
1693 529 (odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings) :=
1694 addEquationsToLists(equations1, stateeqnsmark, zceqnsmark, {e}, odeEquations,
1695 algebraicEquations, allEquations, equationsforZeroCrossings);
1696 529 then
1697 (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1698 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex + 1);
1699
1700 // A single algorithm section for several variables.
1701 case BackendDAE.SINGLEALGORITHM(eqn=e)
1702 algorithm
1703 462 (eqnlst, varlst, _) := BackendDAETransform.getEquationAndSolvedVar(comp, syst.orderedEqs, syst.orderedVars);
1704 462 varlst := List.map(varlst, BackendVariable.transformXToXd);
1705 462 (equations1, uniqueEqIndex1) := createSingleAlgorithmCode(eqnlst, varlst, false, uniqueEqIndex, clockIndex);
1706
1707 462 eqSccMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, sccIndex, eqSccMapping);
1708 462 eqBackendSimCodeMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, e, eqBackendSimCodeMapping);
1709
1710 462 (odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings) :=
1711 addEquationsToLists(equations1, stateeqnsmark, zceqnsmark, {e}, odeEquations,
1712 algebraicEquations, allEquations, equationsforZeroCrossings);
1713 462 then
1714 (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1715 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex + 1);
1716
1717 // A single complex equation
1718 case BackendDAE.SINGLECOMPLEXEQUATION(eqn=e)
1719 algorithm
1720 775 (eqnlst, varlst,_) := BackendDAETransform.getEquationAndSolvedVar(comp, syst.orderedEqs, syst.orderedVars);
1721 // States are solved for der(x) not x.
1722 775 varlst := List.map(varlst, BackendVariable.transformXToXd);
1723 775 (equations1, uniqueEqIndex1, tempvars) := createSingleComplexEqnCode(listHead(eqnlst), varlst, uniqueEqIndex, tempvars, shared.info, true, shared.functionTree, clockIndex);
1724
1725 775 eqSccMapping := appendSccIdx(uniqueEqIndex1-1, sccIndex, eqSccMapping);
1726 775 eqBackendSimCodeMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, e, eqBackendSimCodeMapping);
1727
1728 775 (odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings) :=
1729 addEquationsToLists(equations1, stateeqnsmark, zceqnsmark, {e}, odeEquations,
1730 algebraicEquations, allEquations, equationsforZeroCrossings);
1731 775 then
1732 (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1733 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex + 1);
1734
1735 // A single when equation
1736 case BackendDAE.SINGLEWHENEQUATION()
1737 algorithm
1738 422 (eqnlst, varlst, index) := BackendDAETransform.getEquationAndSolvedVar(comp, syst.orderedEqs, syst.orderedVars);
1739 // States are solved for der(x) not x.
1740 422 varlst := List.map(varlst, BackendVariable.transformXToXd);
1741 422 (equations1, uniqueEqIndex1, tempvars) := createSingleWhenEqnCode(listHead(eqnlst), varlst, shared, uniqueEqIndex, tempvars);
1742
1743 422 eqSccMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, sccIndex, eqSccMapping);
1744 422 eqBackendSimCodeMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, index, eqBackendSimCodeMapping);
1745
1746 422 allEquations := equations1::allEquations;
1747 422 then
1748 (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1749 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex + 1);
1750
1751 // A single if equation
1752 case BackendDAE.SINGLEIFEQUATION(eqn=e)
1753 algorithm
1754
1755 ✗ (eqnlst, varlst, index) := BackendDAETransform.getEquationAndSolvedVar(comp, syst.orderedEqs, syst.orderedVars);
1756 // States are solved for der(x) not x.
1757 ✗ varlst := List.map(varlst, BackendVariable.transformXToXd);
1758 ✗ (equations1, uniqueEqIndex1, tempvars) := createSingleIfEqnCode(listHead(eqnlst), varlst, shared, true, uniqueEqIndex, tempvars);
1759
1760 ✗ eqSccMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, sccIndex, eqSccMapping);
1761 ✗ eqBackendSimCodeMapping := appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, index, eqBackendSimCodeMapping);
1762
1763 ✗ (odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings) :=
1764 addEquationsToLists(equations1, stateeqnsmark, zceqnsmark, {e}, odeEquations,
1765 algebraicEquations, allEquations, equationsforZeroCrossings);
1766 ✗ then
1767 (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings,
1768 tempvars, eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex + 1);
1769
1770 // EQUATIONSYSTEM size 1 -> single equation
1771 case BackendDAE.EQUATIONSYSTEM(eqns={index}, vars={vindex})
1772 algorithm
1773 356 (equations1, uniqueEqIndex1, tempvars) := createEquation(index, vindex, syst, shared, false, uniqueEqIndex, tempvars, {});
1774
1/2
✓ Branch 0 taken 356 times.
✗ Branch 1 not taken.
356 if not listEmpty(equations1) then
1775 356 firstSES := listHead(equations1); // check if the all equations occur with this index in the c file
1776
2/2
✓ Branch 1 taken 162 times.
✓ Branch 2 taken 194 times.
356 firstEqIndex := if isSimEqSys(firstSES) then uniqueEqIndex1-1 else uniqueEqIndex;
1777 356 eqSccMapping := appendSccIdxRange(firstEqIndex, uniqueEqIndex1 - 1, sccIndex, eqSccMapping);
1778 356 eqBackendSimCodeMapping := appendSccIdxRange(firstEqIndex, uniqueEqIndex1 - 1, index, eqBackendSimCodeMapping);
1779 356 backendMapping := setEqMapping(List.intRange2(firstEqIndex, uniqueEqIndex1 - 1),{index}, backendMapping);
1780 end if;
1781
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 356 times.
356 if BackendEquation.isWhenEquation(BackendEquation.get(syst.orderedEqs, index)) then
1782 ✗ allEquations := equations1::allEquations;
1783 else
1784 356 (odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings) :=
1785 addEquationsToLists(equations1, stateeqnsmark, zceqnsmark, {index}, odeEquations,
1786 algebraicEquations, allEquations, equationsforZeroCrossings);
1787 end if;
1788 356 then
1789 (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings, tempvars,
1790 eqSccMapping, eqBackendSimCodeMapping,backendMapping, sccIndex + 1);
1791
1792 // a system of equations
1793 case _
1794 algorithm
1795 // block is dynamic, belong in dynamic section
1796 1981 (eqnslst, _) := BackendDAETransform.getEquationAndSolvedVarIndxes(comp);
1797
1798 1981 (_, noDiscEquations1, uniqueEqIndex1, tempvars, eqSccMapping, backendMapping) :=
1799 createOdeSystem(true and createAlgebraicEquations, false, syst, shared, comp, uniqueEqIndex, tempvars, sccIndex, eqSccMapping, backendMapping);
1800 //eqSccMapping = appendSccIdxRange(uniqueEqIndex, uniqueEqIndex1 - 1, sccIndex, eqSccMapping);
1801
1802 1981 (odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings) :=
1803 addEquationsToLists(noDiscEquations1, stateeqnsmark, zceqnsmark, eqnslst, odeEquations,
1804 algebraicEquations, allEquations, equationsforZeroCrossings);
1805 1981 then
1806 (uniqueEqIndex1, odeEquations, algebraicEquations, allEquations, equationsforZeroCrossings, tempvars,
1807 eqSccMapping, eqBackendSimCodeMapping, backendMapping, sccIndex + 1);
1808
1809 // detailed error message
1810 else
1811 algorithm
1812 ✗ message := "function createEquationsForSystem1 failed for component " + BackendDump.strongComponentString(comp);
1813 ✗ Error.addInternalError(message, sourceInfo());
1814 ✗ then fail();
1815 end match;
1816 end createEquationsForSystem1;
1817
1818 protected function appendSccIdx
1819 input Integer iCurrentIdx;
1820 input Integer iSccIdx;
1821 input list<tuple<Integer,Integer>> iSccIdc;
1822 output list<tuple<Integer,Integer>> oSccIdc;
1823 algorithm
1824 2579 oSccIdc := ((iCurrentIdx,iSccIdx))::iSccIdc;
1825 end appendSccIdx;
1826
1827 protected function appendSccIdxRange
1828 input Integer iCurrentIdxStart;
1829 input Integer iCurrentIdxStop;
1830 input Integer iSccIdx;
1831 input list<tuple<Integer,Integer>> iSccIdc;
1832 output list<tuple<Integer,Integer>> oSccIdc = iSccIdc;
1833 algorithm
1834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 283462 times.
571304 for i in iCurrentIdxStop:-1:iCurrentIdxStart loop
1835 287842 oSccIdc := ((i,iSccIdx))::iSccIdc;
1836 end for;
1837 end appendSccIdxRange;
1838
1839 protected function createEquations
1840 input Boolean includeWhen;
1841 input Boolean skipDiscInZc;
1842 input Boolean genDiscrete;
1843 input Boolean skipDiscInAlgorithm;
1844 input BackendDAE.EqSystem syst;
1845 input BackendDAE.Shared shared;
1846 input BackendDAE.StrongComponents comps;
1847 input Integer iuniqueEqIndex;
1848 input list<SimCodeVar.SimVar> itempvars;
1849 output list<SimCode.SimEqSystem> equations;
1850 output list<SimCode.SimEqSystem> noDiscEquations;
1851 output Integer ouniqueEqIndex = iuniqueEqIndex;
1852 output list<SimCodeVar.SimVar> otempvars = itempvars;
1853 protected
1854 list<list<SimCode.SimEqSystem>> accEquations = {};
1855 list<list<SimCode.SimEqSystem>> accNoDiscEquations = {};
1856 algorithm
1857
2/2
✓ Branch 0 taken 20824 times.
✓ Branch 1 taken 1583 times.
22407 for comp in comps loop
1858 20824 (equations, noDiscEquations, ouniqueEqIndex, otempvars) := createEquationsWork(includeWhen, skipDiscInZc, genDiscrete, skipDiscInAlgorithm, syst, shared, comp, ouniqueEqIndex, otempvars, {});
1859 accEquations := equations::accEquations;
1860 20824 accNoDiscEquations := noDiscEquations::accNoDiscEquations;
1861 end for;
1862 1583 equations := List.flattenReverse(accEquations);
1863 1583 noDiscEquations := List.flattenReverse(accNoDiscEquations);
1864 end createEquations;
1865
1866 protected function createEquationsWork
1867 input Boolean includeWhen;
1868 input Boolean skipDiscInZc;
1869 input Boolean genDiscrete;
1870 input Boolean skipDiscInAlgorithm;
1871 input BackendDAE.EqSystem syst;
1872 input BackendDAE.Shared shared;
1873 input BackendDAE.StrongComponent comp;
1874 input Integer iuniqueEqIndex;
1875 input list<SimCodeVar.SimVar> itempvars;
1876 input BackendDAE.Constraints cons;
1877 output list<SimCode.SimEqSystem> equations;
1878 output list<SimCode.SimEqSystem> noDiscEquations;
1879 output Integer ouniqueEqIndex;
1880 output list<SimCodeVar.SimVar> otempvars;
1881 algorithm
1882 (equations, noDiscEquations, ouniqueEqIndex, otempvars) := match(includeWhen, skipDiscInZc, genDiscrete, syst, shared, comp)
1883 local
1884 Integer index, vindex, uniqueEqIndex;
1885 BackendDAE.Variables vars;
1886 BackendDAE.EquationArray eqns;
1887 list<BackendDAE.Equation> eqnlst;
1888 list<BackendDAE.Var> varlst;
1889 list<SimCode.SimEqSystem> equations1, noDiscEquations1;
1890 list<SimCodeVar.SimVar> tempvars;
1891 BackendDAE.ExtraInfo ei;
1892
1893 // ignore when equations if we should not generate them
1894 case (false, _, _, BackendDAE.EQSYSTEM(orderedEqs=eqns), _, BackendDAE.SINGLEEQUATION(eqn=index))
1895 guard(BackendEquation.isWhenEquation(BackendEquation.get(eqns, index)))
1896 ✗ then ({}, {}, iuniqueEqIndex, itempvars);
1897
1898 case (false, _, _, BackendDAE.EQSYSTEM(), _, BackendDAE.SINGLEWHENEQUATION())
1899 16 then ({}, {}, iuniqueEqIndex, itempvars);
1900
1901 // ignore discrete if we should not generate them
1902 case (_, _, false, BackendDAE.EQSYSTEM(orderedVars=vars), _, BackendDAE.SINGLEEQUATION(var=index))
1903 guard(BackendVariable.isVarDiscrete(BackendVariable.getVarAt(vars, index)))
1904 8 then ({}, {}, iuniqueEqIndex, itempvars);
1905
1906 case (_, _, false, BackendDAE.EQSYSTEM(), _, BackendDAE.SINGLEWHENEQUATION())
1907 ✗ then ({}, {}, iuniqueEqIndex, itempvars);
1908
1909 // ignore discrete in zero crossing if we should not generate them
1910 case (_, true, _, BackendDAE.EQSYSTEM(orderedVars=vars), _, BackendDAE.SINGLEEQUATION(eqn=index, var=vindex))
1911 guard(BackendVariable.isVarDiscrete(BackendVariable.getVarAt(vars, vindex)) and listMember(index, zeroCrossingsEquations(syst, shared)))
1912 ✗ then ({}, {}, iuniqueEqIndex, itempvars);
1913
1914 // single equation
1915 case (_, _, _, _, _, BackendDAE.SINGLEEQUATION(eqn=index, var=vindex))
1916 algorithm
1917
5/6
✓ Branch 1 taken 46966 times.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 46966 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
46970 if (Flags.isSet(Flags.TEARING_DUMP) or Flags.isSet(Flags.TEARING_DUMPVERBOSE)) and not listEmpty(cons) then
1918 2 print("Single Equation with constraint:\n" + BackendDump.equationString(BackendEquation.get(syst.orderedEqs, index)) + "\n");
1919 2 print("Constraints:" + ExpressionDump.constraintDTlistToString(cons,"\n") + "\n\n");
1920 end if;
1921 46970 (equations1, uniqueEqIndex, tempvars) := createEquation(index, vindex, syst, shared, skipDiscInAlgorithm, iuniqueEqIndex, itempvars, cons);
1922 46970 then (equations1, equations1, uniqueEqIndex, tempvars);
1923
1924 // A single array equation
1925 case (_, _, _, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), _, BackendDAE.SINGLEARRAY())
1926 algorithm
1927 20 (eqnlst, varlst,_) := BackendDAETransform.getEquationAndSolvedVar(comp, eqns, vars);
1928 // States are solved for der(x) not x.
1929 20 varlst := List.map(varlst, BackendVariable.transformXToXd);
1930 20 (equations1, noDiscEquations1, uniqueEqIndex, tempvars) := createSingleArrayEqnCode(genDiscrete, eqnlst, varlst, iuniqueEqIndex, itempvars, shared);
1931 then (equations1, noDiscEquations1, uniqueEqIndex, tempvars);
1932
1933 // A single algorithm section for several variables.
1934 case (_, _, _, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), _, BackendDAE.SINGLEALGORITHM())
1935 algorithm
1936 43 (eqnlst, varlst, _) := BackendDAETransform.getEquationAndSolvedVar(comp, eqns, vars);
1937 43 varlst := List.map(varlst, BackendVariable.transformXToXd);
1938 43 (equations1, uniqueEqIndex) := createSingleAlgorithmCode(eqnlst, varlst, skipDiscInAlgorithm, iuniqueEqIndex, partitionKindToClockIndex(syst.partitionKind));
1939 43 then (equations1, equations1, uniqueEqIndex, itempvars);
1940
1941 // A single complex equation
1942 case (_, _, _, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), BackendDAE.SHARED(info = ei), BackendDAE.SINGLECOMPLEXEQUATION())
1943 algorithm
1944 397 (eqnlst, varlst,_) := BackendDAETransform.getEquationAndSolvedVar(comp, eqns, vars);
1945 // States are solved for der(x) not x.
1946 397 varlst := List.map(varlst, BackendVariable.transformXToXd);
1947 397 (equations1, uniqueEqIndex, tempvars) := createSingleComplexEqnCode(listHead(eqnlst), varlst, iuniqueEqIndex, itempvars, ei, genDiscrete, shared.functionTree, partitionKindToClockIndex(syst.partitionKind));
1948 397 then (equations1, equations1, uniqueEqIndex, tempvars);
1949
1950 // A single when equation
1951 case (_, _, _, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), _, BackendDAE.SINGLEWHENEQUATION())
1952 algorithm
1953 3 (eqnlst, varlst,_) := BackendDAETransform.getEquationAndSolvedVar(comp, eqns, vars);
1954 // States are solved for der(x) not x.
1955 3 varlst := List.map(varlst, BackendVariable.transformXToXd);
1956 3 (equations1, uniqueEqIndex, tempvars) := createSingleWhenEqnCode(listHead(eqnlst), varlst, shared, iuniqueEqIndex, itempvars);
1957 3 then (equations1, equations1, uniqueEqIndex, tempvars);
1958
1959 // A single if equation
1960 case (_, _, _, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), _, BackendDAE.SINGLEIFEQUATION())
1961 algorithm
1962 ✗ (eqnlst, varlst,_) := BackendDAETransform.getEquationAndSolvedVar(comp, eqns, vars);
1963 // States are solved for der(x) not x.
1964 ✗ varlst := List.map(varlst, BackendVariable.transformXToXd);
1965 ✗ (equations1, uniqueEqIndex, tempvars) := createSingleIfEqnCode(listHead(eqnlst), varlst, shared, genDiscrete, iuniqueEqIndex, itempvars);
1966 ✗ then (equations1, equations1, uniqueEqIndex, tempvars);
1967
1968 // a system of equations
1969 case (_, _, _, _, _, _)
1970 algorithm
1971 26 (equations1, noDiscEquations1, uniqueEqIndex, tempvars, _, _) := createOdeSystem(genDiscrete, skipDiscInAlgorithm, syst, shared, comp, iuniqueEqIndex, itempvars, 1, {}, SimCode.NO_MAPPING());
1972 26 then (equations1, noDiscEquations1, uniqueEqIndex, tempvars);
1973
1974 // failure
1975 else
1976 algorithm
1977 ✗ Error.addInternalError("createEquation failed", sourceInfo());
1978 ✗ then fail();
1979 end match;
1980 end createEquationsWork;
1981
1982 public function getSimCodeDAEModeDataEqns
1983 input Option<SimCode.DaeModeData> inOptDaeMode;
1984 output list<list<SimCode.SimEqSystem>> daeEquations;
1985 protected
1986 SimCode.DaeModeData daeModeData;
1987 algorithm
1988
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1204 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1196 times.
1204 if isSome(inOptDaeMode) then
1989 8 daeModeData := Util.getOption(inOptDaeMode);
1990 8 daeEquations := daeModeData.daeEquations;
1991 else
1992 daeEquations := {};
1993 end if;
1994 end getSimCodeDAEModeDataEqns;
1995
1996 public function sortSimVarsAndWriteIndex
1997 input list<SimCodeVar.SimVar> inSimVar;
1998 input SimCode.HashTableCrefToSimVar crefToSimVarHT;
1999 output list<SimCodeVar.SimVar> outSimVar;
2000 protected
2001 list<DAE.ComponentRef> crefs;
2002 list<SimCodeVar.SimVar> sorted;
2003 algorithm
2004 9 crefs := List.map(inSimVar, SimCodeCodegenUtil.getSimVarCompRef);
2005 9 sorted := getSimVars2Crefs(crefs, crefToSimVarHT);
2006 9 sorted := List.sort(sorted, compareVarIndexGt);
2007 9 outSimVar := rewriteIndex(sorted, 0);
2008 end sortSimVarsAndWriteIndex;
2009
2010 // =============================================================================
2011 // section for zeroCrossingsEquations
2012 //
2013 // =============================================================================
2014
2015 protected function zeroCrossingsEquations "
2016 Returns a list of all equations (by their index) that contain a zero crossing
2017 Used e.g. to find out which discrete equations are not part of a zero crossing"
2018 input BackendDAE.EqSystem syst;
2019 input BackendDAE.Shared shared;
2020 output list<Integer> eqns;
2021 protected
2022 BackendDAE.ZeroCrossingSet zeroCrossingLst;
2023 list<list<Integer>> zcEqns;
2024 list<Integer> wcEqns;
2025 BackendDAE.EquationArray orderedEqs;
2026 algorithm
2027 ✗ BackendDAE.EQSYSTEM(orderedEqs=orderedEqs) := syst;
2028 ✗ BackendDAE.SHARED(eventInfo=BackendDAE.EVENT_INFO(zeroCrossings=zeroCrossingLst)) := shared;
2029 ✗ zcEqns := List.map(ZeroCrossings.toList(zeroCrossingLst), zeroCrossingEquations);
2030 ✗ wcEqns := whenEquationsIndices(orderedEqs);
2031 ✗ eqns := List.unionList(listAppend(zcEqns, {wcEqns}));
2032 end zeroCrossingsEquations;
2033
2034 protected function zeroCrossingEquations "
2035 Returns the list of equations (indices) from a ZeroCrossing"
2036 input BackendDAE.ZeroCrossing inZC;
2037 output list<Integer> outLst;
2038 algorithm
2039 ✗ BackendDAE.ZERO_CROSSING(_, _, outLst, _) := inZC;
2040 end zeroCrossingEquations;
2041
2042 protected function whenEquationsIndices "
2043 Returns all equation-indices that contain a when clause"
2044 input BackendDAE.EquationArray eqns;
2045 output list<Integer> res;
2046 protected
2047 Boolean b;
2048 Integer i = 1;
2049 Integer size;
2050 algorithm
2051 ✗ size := BackendEquation.getNumberOfEquations(eqns);
2052 res := {};
2053 ✗ while i <= size loop
2054 b:= match BackendEquation.get(eqns, i)
2055 case BackendDAE.WHEN_EQUATION() then true;
2056 else false;
2057 end match;
2058 res := if b then i::res else res;
2059 ✗ i := i+1;
2060 end while;
2061 end whenEquationsIndices;
2062
2063 protected function updateZeroCrossEqnIndex
2064 input list<BackendDAE.ZeroCrossing> izeroCrossings;
2065 input list<tuple<Integer, Integer>> eqBackendSimCodeMapping;
2066 input Integer numEqnsinArray;
2067 output list<BackendDAE.ZeroCrossing> ozeroCrossings = {};
2068 protected
2069 array<Integer> mappingArray;
2070 DAE.Exp exp;
2071 list<Integer> occurEquLst;
2072 Option<list<BackendDAE.SimIterator>> iter;
2073 algorithm
2074 1060 mappingArray := convertListMappingToArray(eqBackendSimCodeMapping, numEqnsinArray);
2075
2/2
✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 1060 times.
2734 for zc in izeroCrossings loop
2076 1674 BackendDAE.ZERO_CROSSING(relation_=exp, occurEquLst=occurEquLst, iter=iter) := zc;
2077 1674 ozeroCrossings := BackendDAE.ZERO_CROSSING(0, exp, convertListIndx(occurEquLst, mappingArray), iter)::ozeroCrossings;
2078 end for;
2079 1060 ozeroCrossings := Dangerous.listReverseInPlace(ozeroCrossings);
2080 end updateZeroCrossEqnIndex;
2081
2082 protected function convertListMappingToArray
2083 input list<tuple<Integer,Integer>> iMapping; //<simEqIdx,BackendEqnIndx>
2084 input Integer numOfBackendEqs;
2085 output array<Integer> outMapping;
2086 algorithm
2087 1060 outMapping := arrayCreate(numOfBackendEqs, -1);
2088 1060 outMapping := List.fold(iMapping, convertListMappingToArray1, outMapping);
2089 end convertListMappingToArray;
2090
2091 protected function convertListMappingToArray1
2092 input tuple<Integer,Integer> iMapping; //<simEqIdx,BackendEqnIndx>
2093 input array<Integer> iMappingArray;
2094 output array<Integer> outMappingArray;
2095 protected
2096 Integer simEqIdx,BackendEqnIdx;
2097 algorithm
2098 40566 (simEqIdx,BackendEqnIdx) := iMapping;
2099 40566 outMappingArray := arrayUpdate(iMappingArray,BackendEqnIdx,simEqIdx);
2100 end convertListMappingToArray1;
2101
2102 protected function convertListIndx
2103 input list<Integer> iIntList;
2104 input array<Integer> iMappingArray;
2105 output list<Integer> oIntList;
2106 algorithm
2107 1674 oIntList := List.map1r(iIntList, arrayGet, iMappingArray);
2108 end convertListIndx;
2109
2110 protected function addAssertEqn
2111 input list<DAE.Statement> asserts;
2112 input list<SimCode.SimEqSystem> iequations;
2113 input Integer iuniqueEqIndex;
2114 output list<SimCode.SimEqSystem> oequations;
2115 output Integer ouniqueEqIndex;
2116 algorithm
2117 (oequations, ouniqueEqIndex) := match asserts
2118 case {}
2119 then (iequations, iuniqueEqIndex);
2120
2121 else
2122 ✗ then (SimCode.SES_ALGORITHM(iuniqueEqIndex, asserts, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)::iequations, iuniqueEqIndex+1);
2123 end match;
2124 end addAssertEqn;
2125
2126 protected function partitionKindToClockIndex
2127 input BackendDAE.BaseClockPartitionKind kind;
2128 output Option<Integer> clockIndex;
2129 algorithm
2130 clockIndex := match kind
2131 local
2132 Integer index;
2133 case BackendDAE.CLOCKED_PARTITION(subPartIdx=index) then SOME(index);
2134 else NONE();
2135 end match;
2136 end partitionKindToClockIndex;
2137
2138 protected function createEquation
2139 input Integer eqNum;
2140 input Integer varNum;
2141 input BackendDAE.EqSystem syst;
2142 input BackendDAE.Shared shared;
2143 input Boolean skipDiscInAlgorithm;
2144 input Integer iuniqueEqIndex;
2145 input list<SimCodeVar.SimVar> itempvars;
2146 input BackendDAE.Constraints cons;
2147 output list<SimCode.SimEqSystem> equation_;
2148 output Integer ouniqueEqIndex;
2149 output list<SimCodeVar.SimVar> otempvars;
2150 protected
2151 BackendDAE.Variables vars;
2152 BackendDAE.EquationArray eqns;
2153 BackendDAE.Equation eqn;
2154 BackendDAE.Var v;
2155 BackendDAE.BaseClockPartitionKind partitionKind;
2156 algorithm
2157 186799 BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, partitionKind=partitionKind) := syst;
2158 186799 eqn := BackendEquation.get(eqns, eqNum);
2159 v := match eqn
2160 ✗ case BackendDAE.WHEN_EQUATION() then
2161 BackendVariable.makeVar(DAE.emptyCref); // dummy, not used
2162 186799 else
2163 BackendVariable.getVarAt(vars, varNum);
2164 end match;
2165 186799 (equation_, ouniqueEqIndex, otempvars) := createEquationImpl(eqn, v, vars, partitionKind, shared, skipDiscInAlgorithm, iuniqueEqIndex, itempvars, cons);
2166 end createEquation;
2167
2168 protected function createEquationImpl
2169 input BackendDAE.Equation eqn;
2170 input BackendDAE.Var v;
2171 input BackendDAE.Variables vars;
2172 input BackendDAE.BaseClockPartitionKind partitionKind;
2173 input BackendDAE.Shared shared;
2174 input Boolean skipDiscInAlgorithm;
2175 input Integer iuniqueEqIndex;
2176 input list<SimCodeVar.SimVar> itempvars;
2177 input BackendDAE.Constraints cons;
2178 output list<SimCode.SimEqSystem> equation_;
2179 output Integer ouniqueEqIndex;
2180 output list<SimCodeVar.SimVar> otempvars;
2181 algorithm
2182 (equation_, ouniqueEqIndex, otempvars) := match eqn
2183 local
2184 DAE.ComponentRef cr;
2185 BackendDAE.Var var;
2186 Integer uniqueEqIndex1, uniqueEqIndex;
2187 list<DAE.Statement> algStatements;
2188 list<DAE.ComponentRef> conditions, solveCr;
2189 list<SimCode.SimEqSystem> resEqs;
2190 DAE.ComponentRef left, varOutput;
2191 DAE.Exp e1, e2, varexp, exp_, start, cond;
2192 DAE.Ident iter;
2193 BackendDAE.WhenEquation whenEquation, elseWhen;
2194 Option<BackendDAE.WhenEquation> oelseWhen;
2195 String algStr, message;
2196 DAE.ElementSource source;
2197 list<DAE.Statement> asserts;
2198 SimCode.SimEqSystem elseWhenEquation, simEqSys;
2199 DAE.Algorithm alg;
2200 list<SimCodeVar.SimVar> tempvars;
2201 Boolean initialCall;
2202 DAE.Expand crefExpand;
2203 Boolean homotopySupport;
2204 AvlTreePathFunction.Tree funcs;
2205 list<BackendDAE.Equation> solveEqns;
2206 list<SimCode.SimEqSystem> eqSystlst, eqs;
2207 list<BackendDAE.WhenOperator> whenStmtLst;
2208 Option<SimCode.SimEqSystem> oelseWhenSimEq;
2209 BackendDAE.EquationAttributes eqAttr;
2210 Boolean b;
2211
2212 // array equation that may result from -d=-nfScalarize and is assumed solved
2213 case BackendDAE.ARRAY_EQUATION(left = DAE.CREF(componentRef = cr), right = e2, source = source, attr = eqAttr) algorithm
2214 10 varexp := Expression.crefExp(cr);
2215 10 simEqSys := SimCode.SES_ARRAY_CALL_ASSIGN(iuniqueEqIndex, varexp, e2, source, eqAttr);
2216 10 then
2217 ({simEqSys}, iuniqueEqIndex + 1, itempvars);
2218
2219 // for equation that may result from -d=-nfScalarize
2220 case BackendDAE.FOR_EQUATION(iter = varexp, start = start, stop = cond, source = source, attr = eqAttr)
2221 algorithm
2222 (b, e1, e2) := match eqn.body
2223 case BackendDAE.EQUATION(exp = e1, scalar = e2) then
2224 (true, e1, e2);
2225 case BackendDAE.ARRAY_EQUATION(left = e1, right = e2) then
2226 (true, e1, e2);
2227 else
2228 (false, DAE.BCONST(false), DAE.BCONST(false));
2229 end match;
2230
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
19 DAE.CREF(componentRef = DAE.CREF_IDENT(ident = iter)) := varexp;
2231 var := v;
2232 38 var.varName := ComponentReference.crefApplySubs(v.varName, {DAE.INDEX(DAE.CREF(DAE.CREF_IDENT(iter, DAE.T_INTEGER_DEFAULT, {}), DAE.T_INTEGER_DEFAULT))});
2233
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 2 times.
19 if b then
2234 cr := var.varName;
2235 17 BackendDAE.SHARED(functionTree = funcs) := shared;
2236 try
2237 34 (exp_, asserts, solveEqns, solveCr) := ExpressionSolve.solve2(e1, e2, Expression.crefExp(cr), SOME(funcs), SOME(iuniqueEqIndex), true, BackendDAEUtil.isSimulationDAE(shared));
2238 else
2239 ✗ Error.addInternalError("solving FOR_EQUATION body: " + BackendDump.equationString(eqn.body) + "\nfor variable: " + ComponentReferenceBasics.printComponentRefStr(cr) + ".", sourceInfo());
2240 ✗ fail();
2241 end try;
2242 17 simEqSys := SimCode.SES_FOR_LOOP(iuniqueEqIndex, varexp, start, cond, cr, exp_, source, eqAttr);
2243 17 otempvars := itempvars;
2244 else
2245 2 (resEqs, _, otempvars) := createEquationImpl(eqn.body, var, vars, partitionKind, shared, skipDiscInAlgorithm, iuniqueEqIndex, itempvars, cons);
2246 2 simEqSys := SimCode.SES_FOR_EQUATION(iuniqueEqIndex, varexp, start, cond, resEqs, source, eqAttr);
2247 end if;
2248 19 then
2249 ({simEqSys}, iuniqueEqIndex + 1, otempvars);
2250
2251 // solved equation
2252 case BackendDAE.SOLVED_EQUATION(exp=e2, source=source, attr=eqAttr)
2253 algorithm
2254 5360 cr := v.varName;
2255 5360 varexp := Expression.crefExp(cr);
2256
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5360 times.
5360 varexp := if BackendVariable.isStateVar(v) then Expression.expDer(varexp) else varexp;
2257 10720 then
2258 ({SimCode.SES_SIMPLE_ASSIGN(iuniqueEqIndex, cr, e2, source, eqAttr)}, iuniqueEqIndex+1, itempvars);
2259
2260 // when eq
2261 case BackendDAE.WHEN_EQUATION(whenEquation=whenEquation, source=source, attr=eqAttr)
2262 algorithm
2263 ✗ BackendDAE.WHEN_STMTS(cond, whenStmtLst, oelseWhen) := whenEquation;
2264 ✗ if isSome(oelseWhen) then
2265 ✗ SOME(elseWhen) := oelseWhen;
2266 ✗ (elseWhenEquation,uniqueEqIndex) := createElseWhenEquation(elseWhen, {}, iuniqueEqIndex+1, source, eqAttr);
2267 oelseWhenSimEq := SOME(elseWhenEquation);
2268 else
2269 ✗ uniqueEqIndex := iuniqueEqIndex+1;
2270 oelseWhenSimEq := NONE();
2271 end if;
2272 ✗ (conditions, initialCall) := BackendDAEUtil.getConditionList(cond);
2273 ✗ then
2274 ({SimCode.SES_WHEN(iuniqueEqIndex, conditions, initialCall, whenStmtLst, oelseWhenSimEq, source, eqAttr)}, uniqueEqIndex+1, itempvars);
2275
2276 // single equation
2277 case BackendDAE.EQUATION(exp=e1, scalar=e2, source=source, attr=eqAttr)
2278 algorithm
2279 181412 cr := v.varName;
2280 181412 varexp := Expression.crefExp(cr);
2281
2/2
✓ Branch 1 taken 3710 times.
✓ Branch 2 taken 177702 times.
181412 varexp := if BackendVariable.isStateVar(v) then Expression.expDer(varexp) else varexp;
2282 181412 BackendDAE.SHARED(functionTree = funcs) := shared;
2283 try
2284 362824 (exp_, asserts, solveEqns, solveCr) := ExpressionSolve.solve2(e1, e2, varexp, SOME(funcs), SOME(iuniqueEqIndex), true, BackendDAEUtil.isSimulationDAE(shared));
2285 181250 solveEqns := listReverse(solveEqns);
2286 181250 solveCr := listReverse(solveCr);
2287
2/2
✓ Branch 1 taken 3709 times.
✓ Branch 2 taken 177541 times.
181250 cr := if BackendVariable.isStateVar(v) then ComponentReference.crefPrefixDer(cr) else cr;
2288 181250 source := ElementSource.addSymbolicTransformationSolve(true, source, cr, e1, e2, exp_, asserts);
2289 181250 (eqs, uniqueEqIndex1) := List.mapFold(solveEqns, makeSolved, iuniqueEqIndex);
2290
2/2
✓ Branch 0 taken 181246 times.
✓ Branch 1 taken 4 times.
181250 if listEmpty(cons) then
2291 362492 (resEqs, uniqueEqIndex) := addAssertEqn(asserts, {SimCode.SES_SIMPLE_ASSIGN(uniqueEqIndex1, cr, exp_, source, eqAttr)}, uniqueEqIndex1+1);
2292 else
2293 8 (resEqs, uniqueEqIndex) := addAssertEqn(asserts, {SimCode.SES_SIMPLE_ASSIGN_CONSTRAINTS(uniqueEqIndex1, cr, exp_, source, cons, eqAttr)}, uniqueEqIndex1+1);
2294 end if;
2295 181250 eqSystlst := listAppend(eqs,resEqs);
2296 181250 tempvars := createTempVarsforCrefs(List.map(solveCr, Expression.crefExp),itempvars);
2297 else
2298 // non-linear
2299 162 (resEqs, (uniqueEqIndex, _), tempvars) := createNonlinearResidualEquations({eqn}, (iuniqueEqIndex, 0), itempvars, shared.functionTree);
2300 162 resEqs := fixNonlinearResidualIndices(resEqs);
2301
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 161 times.
162 cr := if BackendVariable.isStateVar(v) then ComponentReference.crefPrefixDer(cr) else cr;
2302 162 (_, homotopySupport) := BackendEquation.traverseExpsOfEquation(eqn, BackendDAEUtil.containsHomotopyCall, false);
2303
2/2
✓ Branch 1 taken 156 times.
✓ Branch 2 taken 6 times.
318 eqSystlst := {SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(uniqueEqIndex, resEqs, {cr}, 0, 1, NONE(), homotopySupport, false, false, partitionKindToClockIndex(partitionKind)), NONE(), eqAttr)};
2304 162 uniqueEqIndex := uniqueEqIndex+1;
2305 end try;
2306 181412 then (eqSystlst, uniqueEqIndex,tempvars);
2307
2308 // Algorithm for single variable.
2309 case BackendDAE.ALGORITHM(alg=alg, source=source, expand=crefExpand, attr=eqAttr)
2310 algorithm
2311 ✗ varOutput::{} := CheckModel.checkAndGetAlgorithmOutputs(alg, source, crefExpand);
2312 // The output variable of the algorithm must be the variable solved
2313 // for, otherwise we need to solve an inverse problem of an algorithm
2314 // section.
2315 ✗ DAE.ALGORITHM_STMTS(algStatements) := BackendDAEUtil.collateAlgorithm(alg, NONE());
2316 ✗ if ComponentReferenceBasics.crefEqualNoStringCompare(BackendVariable.varCref(v), varOutput) then
2317 ✗ if skipDiscInAlgorithm then
2318 ✗ algStatements := BackendDAEUtil.removeDiscreteAssignments(algStatements, vars);
2319 end if;
2320 else
2321 try
2322 ✗ algStatements := solveAlgorithmInverse(algStatements, {v});
2323 else
2324 ✗ algStr := DAEDump.dumpAlgorithmsStr({DAE.ALGORITHM(alg, source)});
2325 ✗ message := ComponentReferenceBasics.printComponentRefStr(BackendVariable.varCref(v));
2326 ✗ message := stringAppendList({"Inverse Algorithm needs to be solved for ", message, " in\n", algStr, "This has not been implemented yet.\n"});
2327 ✗ Error.addInternalError(message, sourceInfo());
2328 ✗ fail();
2329 end try;
2330 end if;
2331 ✗ then
2332 ({SimCode.SES_ALGORITHM(iuniqueEqIndex, algStatements, eqAttr)}, iuniqueEqIndex+1, itempvars);
2333
2334 end match;
2335 end createEquationImpl;
2336
2337 protected function replaceIFBrancheswithoutVar
2338 input DAE.Exp inExp;
2339 input tuple<DAE.Exp, DAE.Exp> inTpl;
2340 output DAE.Exp outExp;
2341 output tuple<DAE.Exp, DAE.Exp> outTpl;
2342 algorithm
2343 (outExp,outTpl) := match (inExp,inTpl)
2344 local
2345 DAE.Exp exp, crexp, cond, e1, e2;
2346 Boolean b1, b2;
2347 case (DAE.IFEXP(cond, e1, e2), (crexp, exp))
2348 algorithm
2349 ✗ b1 := Expression.expContains(e1, crexp);
2350 ✗ e1 := if b1 then e1 else exp;
2351 ✗ b2 := Expression.expContains(e2, crexp);
2352 ✗ e2 := if b2 then e2 else exp;
2353 ✗ then (if b1 and b2 then inExp else DAE.IFEXP(cond, e1, e2), inTpl);
2354 else (inExp,inTpl);
2355 end match;
2356 end replaceIFBrancheswithoutVar;
2357
2358 protected function solveAlgorithmInverse "author: jfrenkel
2359 This function solves symbolically a algorithm inverse for a few special cases."
2360 input list<DAE.Statement> inStmts;
2361 input list<BackendDAE.Var> inSolveFor;
2362 output list<DAE.Statement> outStmts;
2363 algorithm
2364 outStmts := match (inStmts, inSolveFor)
2365 local
2366 DAE.ComponentRef cr1;
2367 DAE.Exp e11, e12, varexp1, solvedExp1;
2368 DAE.ElementSource source1;
2369 DAE.Type tp1;
2370 BackendDAE.Var v1;
2371
2372 DAE.ComponentRef cr2;
2373 DAE.Exp e21, e22, varexp2, solvedExp2;
2374 DAE.ElementSource source2;
2375 DAE.Type tp2;
2376 BackendDAE.Var v2;
2377
2378 list<DAE.Statement> asserts;
2379
2380 // Algorithm for single variable
2381 // a := exp1(b); => b := exp1_(a);
2382 case (DAE.STMT_ASSIGN(exp1=e11, exp=e12, source=source1)::{}, (v1 as BackendDAE.VAR(varName=cr1))::{}) algorithm
2383 ✗ varexp1 := Expression.crefExp(cr1);
2384 ✗ varexp1 := if BackendVariable.isStateVar(v1) then Expression.expDer(varexp1) else varexp1;
2385 ✗ (solvedExp1, asserts) := ExpressionSolve.solve(e11, e12, varexp1);
2386 ✗ cr1 := if BackendVariable.isStateVar(v1) then ComponentReference.crefPrefixDer(cr1) else cr1;
2387 ✗ source1 := ElementSource.addSymbolicTransformationSolve(true, source1, cr1, e11, e12, solvedExp1, asserts);
2388 ✗ tp1 := Expression.typeof(varexp1);
2389 ✗ then {DAE.STMT_ASSIGN(tp1, varexp1, solvedExp1, source1)};
2390
2391 // a := exp1(b); c := exp2(d); => b := exp1_(a); d := exp2_(c);
2392 case (DAE.STMT_ASSIGN(exp1=e11, exp=e12, source=source1)::DAE.STMT_ASSIGN(exp1=e21, exp=e22, source=source2)::{}, (v1 as BackendDAE.VAR(varName=cr1))::(v2 as BackendDAE.VAR(varName=cr2))::{}) algorithm
2393 // check for cross-over dependencies
2394 ✗ false := Expression.expHasCref(e12, cr2);
2395 ✗ false := Expression.expHasCref(e22, cr1);
2396
2397 ✗ varexp1 := Expression.crefExp(cr1);
2398 ✗ varexp1 := if BackendVariable.isStateVar(v1) then Expression.expDer(varexp1) else varexp1;
2399 ✗ (solvedExp1, asserts) := ExpressionSolve.solve(e11, e12, varexp1);
2400 ✗ cr1 := if BackendVariable.isStateVar(v1) then ComponentReference.crefPrefixDer(cr1) else cr1;
2401 ✗ source1 := ElementSource.addSymbolicTransformationSolve(true, source1, cr1, e11, e12, solvedExp1, asserts);
2402 ✗ tp1 := Expression.typeof(varexp1);
2403
2404 ✗ varexp2 := Expression.crefExp(cr2);
2405 ✗ varexp2 := if BackendVariable.isStateVar(v2) then Expression.expDer(varexp2) else varexp2;
2406 ✗ (solvedExp2, asserts) := ExpressionSolve.solve(e21, e22, varexp2);
2407 ✗ cr2 := if BackendVariable.isStateVar(v2) then ComponentReference.crefPrefixDer(cr2) else cr2;
2408 ✗ source2 := ElementSource.addSymbolicTransformationSolve(true, source2, cr2, e21, e22, solvedExp2, asserts);
2409 ✗ tp2 := Expression.typeof(varexp2);
2410 ✗ then {DAE.STMT_ASSIGN(tp1, varexp1, solvedExp1, source1), DAE.STMT_ASSIGN(tp2, varexp2, solvedExp2, source2)};
2411 end match;
2412 end solveAlgorithmInverse;
2413
2414 // =============================================================================
2415 // Section for handling complex equations
2416 //
2417 // =============================================================================
2418
2419 protected function createNonlinearResidualEquationsComplex
2420 input DAE.Exp inExp;
2421 input DAE.Exp inExp1;
2422 input DAE.ElementSource source;
2423 input BackendDAE.EquationAttributes eqAttr;
2424 output list<SimCode.SimEqSystem> equations_;
2425 input output tuple<Integer, Integer> idx_tpl;
2426 input output list<SimCodeVar.SimVar> tempvars;
2427 protected
2428 Integer eq_idx, res_idx;
2429 algorithm
2430 23 (eq_idx, res_idx) := idx_tpl;
2431 (equations_, idx_tpl, tempvars) := matchcontinue (inExp, inExp1)
2432 local
2433 DAE.ComponentRef cr, crtmp;
2434 list<DAE.ComponentRef> crlst;
2435 list<list<DAE.ComponentRef>> crlstlst;
2436 DAE.Exp e1, e2, e1_1, e2_1, etmp;
2437 DAE.Statement stms;
2438 DAE.Type tp;
2439 list<DAE.Exp> expl, crexplst;
2440 list<DAE.Var> varLst;
2441 list<DAE.Exp> e1lst, e2lst;
2442 SimCode.SimEqSystem simeqn_complex;
2443 list<SimCode.SimEqSystem> eqSystlst;
2444 list<tuple<DAE.Exp, DAE.Exp>> exptl;
2445 Absyn.Path path, rpath;
2446 String ident, s, s1, s2;
2447
2448 /* casts */
2449 case (DAE.CAST(_, e1), _) algorithm
2450 ✗ (equations_, idx_tpl, tempvars) := createNonlinearResidualEquationsComplex(e1, inExp1, source, eqAttr, idx_tpl, tempvars);
2451 then (equations_, idx_tpl, tempvars);
2452
2453 /* casts */
2454 case (_, DAE.CAST(_, e2)) algorithm
2455 ✗ (equations_, idx_tpl, tempvars) := createNonlinearResidualEquationsComplex(inExp, e2, source, eqAttr, idx_tpl, tempvars);
2456 then (equations_, idx_tpl, tempvars);
2457
2458 /* a = f() */
2459 case (DAE.CREF(componentRef=cr), _) algorithm
2460 // ((e1_1, _)) = Expression.extendArrExp((inExp, false));
2461 12 (e2_1, _) := Expression.extendArrExp(inExp1, false);
2462 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
2463
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 tp as DAE.T_COMPLEX(varLst=varLst, complexClassType=ClassInf.RECORD(path)) := Expression.typeof(inExp);
2464 // tmp
2465 12 ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2466 12 crtmp := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(eq_idx), tp, {});
2467 12 tempvars := createTempVars(varLst, crtmp, tempvars);
2468 // 0 = a - tmp
2469 12 e1lst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr);
2470 12 e2lst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, crtmp);
2471 12 exptl := List.zip(e1lst, e2lst);
2472 12 (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
2473 // tmp = f(x, y)
2474 12 etmp := Expression.crefExp(crtmp);
2475 12 stms := DAE.STMT_ASSIGN(tp, etmp, e2_1, source);
2476 12 eqSystlst := SimCode.SES_ALGORITHM(eq_idx, {stms}, eqAttr)::eqSystlst;
2477 12 then (eqSystlst, (eq_idx + 1, res_idx), tempvars);
2478
2479 /* f() = a */
2480 case (_, DAE.CREF(componentRef=cr)) algorithm
2481 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
2482 ✗ (e1_1, _) := Expression.extendArrExp(inExp, false);
2483 // ((e2_1, _)) = Expression.extendArrExp((inExp1, false));
2484 ✗ tp as DAE.T_COMPLEX(varLst=varLst, complexClassType=ClassInf.RECORD(path)) := Expression.typeof(inExp1);
2485 // tmp
2486 ✗ ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2487 ✗ crtmp := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(eq_idx), tp, {});
2488 ✗ tempvars := createTempVars(varLst, crtmp, tempvars);
2489 // 0 = a - tmp
2490 ✗ e1lst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr);
2491 ✗ e2lst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, crtmp);
2492 ✗ exptl := List.zip(e1lst, e2lst);
2493 ✗ (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
2494 // tmp = f(x, y)
2495 ✗ etmp := Expression.crefExp(crtmp);
2496 ✗ stms := DAE.STMT_ASSIGN(tp, etmp, e1_1, source);
2497 ✗ eqSystlst := SimCode.SES_ALGORITHM(eq_idx, {stms}, eqAttr)::eqSystlst;
2498 ✗ then (eqSystlst, (eq_idx + 1, res_idx), tempvars);
2499
2500 /* Record() = f() */
2501 case (DAE.CALL(path=path, expLst=e2lst, attr=DAE.CALL_ATTR(ty= tp as DAE.T_COMPLEX(varLst=varLst, complexClassType=ClassInf.RECORD(rpath)))), _) algorithm
2502 ✗ true := AbsynUtil.pathEqual(path, rpath);
2503 ✗ (e2_1, _) := Expression.extendArrExp(inExp1, false);
2504 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
2505 // tmp = f()
2506 ✗ ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2507 ✗ cr := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(eq_idx), tp, {});
2508 ✗ e1_1 := Expression.crefToExp(cr);
2509 ✗ stms := DAE.STMT_ASSIGN(tp, e1_1, e2_1, source);
2510 ✗ simeqn_complex := SimCode.SES_ALGORITHM(eq_idx, {stms}, eqAttr);
2511 ✗ eq_idx := eq_idx + 1;
2512
2513 // Record()-tmp = 0
2514 /* Expand the tmp record and any arrays */
2515 ✗ e1lst := Expression.expandExpression(e1_1, expandRecord = true);
2516 /* Expand the varLst. Each var might be an array or record. */
2517 ✗ e2lst := List.mapFlat(e2lst, function Expression.expandExpression(expandRecord = true));
2518 /* pair each of the expanded expressions to coressponding one*/
2519 ✗ exptl := List.zip(e1lst, e2lst);
2520 /* Create residual equations for each pair*/
2521 ✗ (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
2522 eqSystlst := simeqn_complex::eqSystlst;
2523
2524 ✗ tempvars := createTempVars(varLst, cr, tempvars);
2525 ✗ then (eqSystlst, (eq_idx, res_idx), tempvars);
2526
2527 /* Record() = f() */
2528 case (DAE.RECORD(path=path, exps=e2lst, ty= tp as DAE.T_COMPLEX(varLst=varLst)), _) algorithm
2529 11 (e2_1, _) := Expression.extendArrExp(inExp1, false);
2530 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
2531 // tmp = f()
2532 11 ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2533 11 cr := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(eq_idx), tp, {});
2534 11 e1_1 := Expression.crefToExp(cr);
2535 11 stms := DAE.STMT_ASSIGN(tp, e1_1, e2_1, source);
2536 11 simeqn_complex := SimCode.SES_ALGORITHM(eq_idx, {stms}, eqAttr);
2537 11 eq_idx := eq_idx + 1;
2538
2539 // Record()-tmp = 0
2540 /* Expand the tmp record and any arrays */
2541 11 e1lst := Expression.expandExpression(e1_1, expandRecord = true);
2542 /* Expand the varLst. Each var might be an array or record. */
2543 11 e2lst := List.mapFlat(e2lst, function Expression.expandExpression(expandRecord = true));
2544 /* pair each of the expanded expressions to coressponding one*/
2545 11 exptl := List.zip(e1lst, e2lst);
2546 /* Create residual equations for each pair*/
2547 11 (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
2548 eqSystlst := simeqn_complex::eqSystlst;
2549
2550 11 tempvars := createTempVars(varLst, cr, tempvars);
2551
2552 11 then (eqSystlst, (eq_idx, res_idx), tempvars);
2553
2554 /* f() = Record() */
2555 case (_, DAE.CALL(path=path, expLst=e2lst, attr=DAE.CALL_ATTR(ty=tp as DAE.T_COMPLEX(varLst=varLst, complexClassType=ClassInf.RECORD(rpath))))) algorithm
2556 ✗ true := AbsynUtil.pathEqual(path, rpath);
2557 ✗ (e1_1, _) := Expression.extendArrExp(inExp1, false);
2558 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
2559 // tmp = f()
2560 ✗ ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2561 ✗ cr := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(eq_idx), tp, {});
2562 ✗ e2_1 := Expression.crefExp(cr);
2563 ✗ stms := DAE.STMT_ASSIGN(tp, e2_1, e1_1, source);
2564 ✗ simeqn_complex := SimCode.SES_ALGORITHM(eq_idx, {stms}, eqAttr);
2565 ✗ eq_idx := eq_idx + 1;
2566 // Record()-tmp = 0
2567 ✗ e1lst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr);
2568 ✗ exptl := List.zip(e1lst, e2lst);
2569 ✗ (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
2570 eqSystlst := simeqn_complex::eqSystlst;
2571 ✗ tempvars := createTempVars(varLst, cr, tempvars);
2572 ✗ then (eqSystlst, (eq_idx, res_idx), tempvars);
2573
2574 /* f() = Record() */
2575 case (_, DAE.RECORD(path=path, exps=e2lst, ty=tp as DAE.T_COMPLEX(varLst=varLst))) algorithm
2576 ✗ (e1_1, _) := Expression.extendArrExp(inExp1, false);
2577 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
2578 // tmp = f()
2579 ✗ ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2580 ✗ cr := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(eq_idx), tp, {});
2581 ✗ e2_1 := Expression.crefExp(cr);
2582 ✗ stms := DAE.STMT_ASSIGN(tp, e2_1, e1_1, source);
2583 ✗ simeqn_complex := SimCode.SES_ALGORITHM(eq_idx, {stms}, eqAttr);
2584 ✗ eq_idx := eq_idx + 1;
2585 // Record()-tmp = 0
2586 ✗ e1lst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr);
2587 ✗ exptl := List.zip(e1lst, e2lst);
2588 ✗ (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
2589 eqSystlst := simeqn_complex::eqSystlst;
2590 ✗ tempvars := createTempVars(varLst, cr, tempvars);
2591 ✗ then (eqSystlst, (eq_idx, res_idx), tempvars);
2592
2593 /* Tuple() = f() */
2594 case (DAE.TUPLE(PR=expl), DAE.CALL(path=path)) algorithm
2595 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
2596 // tmp = f()
2597 ✗ tp := Expression.typeof(inExp);
2598 ✗ ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2599 ✗ cr := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(eq_idx), tp, {});
2600 ✗ crexplst := List.map1(expl, Expression.generateCrefsExpFromExp, cr);
2601 ✗ stms := DAE.STMT_TUPLE_ASSIGN(tp, crexplst, inExp1, source);
2602 ✗ simeqn_complex := SimCode.SES_ALGORITHM(eq_idx, {stms}, eqAttr);
2603 ✗ eq_idx := eq_idx + 1;
2604
2605 // for creating makeSES_RESIDUAL1 all crefs needs to expanded
2606 // and all WILD() crefs are filtered
2607 ✗ expl := List.filterOnTrue(expl, Expression.isNotWild);
2608 ✗ expl := List.flatten(List.map1(expl, Expression.generateCrefsExpLstFromExp, NONE()));
2609 ✗ crexplst := List.flatten(List.map1(expl, Expression.generateCrefsExpLstFromExp, SOME(cr)));
2610 ✗ crlst := List.map(crexplst, Expression.expCref);
2611 ✗ crlstlst := List.map1(crlst, ComponentReference.expandCref, true);
2612 ✗ crlst := List.flatten(crlstlst);
2613 ✗ crexplst := List.map(crlst, Expression.crefExp);
2614
2615 ✗ crlst := List.map(expl, Expression.expCref);
2616 ✗ crlstlst := List.map1(crlst, ComponentReference.expandCref, true);
2617 ✗ crlst := List.flatten(crlstlst);
2618 ✗ expl := List.map(crlst, Expression.crefExp);
2619
2620 // Tuple() - tmp = 0
2621 ✗ exptl := List.zip(expl, crexplst);
2622 ✗ (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
2623 eqSystlst := simeqn_complex::eqSystlst;
2624
2625 ✗ tempvars := createTempVarsforCrefs(listReverse(crexplst), tempvars);
2626 ✗ then (eqSystlst, (eq_idx, res_idx), tempvars);
2627
2628 // failure
2629 else algorithm
2630 ✗ s1 := ExpressionBasics.printExpStr(inExp);
2631 ✗ s2 := ExpressionBasics.printExpStr(inExp1);
2632 ✗ s := stringAppendList({"function createNonlinearResidualEquationsComplex failed for: ", s1, " = " , s2 });
2633 ✗ Error.addInternalError(s, sourceInfo());
2634 ✗ then fail();
2635 end matchcontinue;
2636 end createNonlinearResidualEquationsComplex;
2637
2638 protected function createNonlinearResidualEquationsSingleComplex
2639 input DAE.Exp inExp;
2640 input DAE.Exp inExp1;
2641 input DAE.ElementSource source;
2642 input BackendDAE.EquationAttributes eqAttr;
2643 input Integer iuniqueEqIndex;
2644 input list<SimCodeVar.SimVar> itempvars;
2645 output list<SimCode.SimEqSystem> equations_;
2646 output Integer ouniqueEqIndex;
2647 output list<SimCodeVar.SimVar> otempvars;
2648 input output list<DAE.ComponentRef> eqCrefs = {};
2649 algorithm
2650 (equations_, ouniqueEqIndex, otempvars) := match (inExp, inExp1)
2651 local
2652 DAE.ComponentRef cr;
2653 list<DAE.ComponentRef> callCrefs;
2654 DAE.Statement stms;
2655 DAE.Type tp;
2656 list<DAE.Exp> expl, callExps, crexplst, lhsExpLstRes, rhsExpLstRes, lhsExpLstAss, rhsExpLstAss;
2657 SimCode.SimEqSystem simeqn_complex;
2658 list<SimCode.SimEqSystem> eqSystlst, eqSystlst_simpAss;
2659 list<tuple<DAE.Exp, DAE.Exp>> exptl;
2660 Integer uniqueEqIndex;
2661 Absyn.Path path;
2662 String ident;
2663 list<SimCodeVar.SimVar> tempvars;
2664
2665 /* Tuple() = f() */
2666 case (DAE.TUPLE(PR=expl), DAE.CALL(path=path, expLst=callExps)) algorithm
2667 // Get all crefs in the call arguments
2668 2 (_, callCrefs) := Expression.traverseExpList(callExps, Expression.traversingComponentRefFinder, {});
2669
2670 // Prepare cref prefix for temporary variables
2671 2 tp := Expression.typeof(inExp);
2672 2 ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
2673 2 cr := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(iuniqueEqIndex), tp, {});
2674
2675 // Create temporary variables and residual equations for variables not solved in this equation
2676 2 (eqCrefs, crexplst, lhsExpLstRes, rhsExpLstRes, lhsExpLstAss, rhsExpLstAss) := createTmpCrefExpsForComplexEqnSys(expl, cr, eqCrefs, callCrefs);
2677
2678 // Create algorithm equation from complex equation with temporary variables
2679 2 stms := DAE.STMT_TUPLE_ASSIGN(tp, crexplst, inExp1, source);
2680 2 simeqn_complex := SimCode.SES_ALGORITHM(iuniqueEqIndex, {stms}, eqAttr);
2681 2 uniqueEqIndex := iuniqueEqIndex + 1;
2682
2683 // Make simple assignments
2684 // var := tmp_var
2685 2 exptl := List.zip(lhsExpLstAss, rhsExpLstAss);
2686 2 (eqSystlst_simpAss, uniqueEqIndex) := List.map2Fold(exptl, makeSES_SIMPLE_ASSIGN, source, eqAttr, uniqueEqIndex);
2687
2688 // Make residual equations
2689 // tmp_var - var = 0
2690 2 exptl := List.zip(rhsExpLstRes, lhsExpLstRes);
2691 2 (eqSystlst, (uniqueEqIndex, _)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (uniqueEqIndex, 0));
2692
2693 // Add simEqns to eqSystlst and temporary variables to tempvars
2694 2 eqSystlst := simeqn_complex :: listAppend(eqSystlst_simpAss, eqSystlst);
2695 2 tempvars := createTempVarsforCrefs(listReverse(rhsExpLstAss), itempvars);
2696 2 tempvars := createTempVarsforCrefs(listReverse(lhsExpLstRes), tempvars);
2697 then (eqSystlst, uniqueEqIndex, tempvars);
2698
2699 /* To-Do: Add other cases
2700 - a = f()
2701 - f() = a
2702 - Record() = f()
2703 - f() = Record()
2704 */
2705 end match;
2706 end createNonlinearResidualEquationsSingleComplex;
2707
2708 protected function createTmpCrefExpsForComplexEqnSys
2709 "This function creates tmp cref expressions for crefs that are not solved in the current complex equation or occur on rhs and lhs.
2710 It also returns lists of expressions to create inner equations and residual equations from.
2711 author: ptaeuber 06-2017"
2712 input list<DAE.Exp> inExpLst;
2713 input DAE.ComponentRef crPrefix;
2714 input output list<DAE.ComponentRef> eqCrefs;
2715 input list<DAE.ComponentRef> callCrefs;
2716 output list<DAE.Exp> outExpList = {};
2717 input output list<DAE.Exp> lhsExpLstRes = {};
2718 input output list<DAE.Exp> rhsExpLstRes = {};
2719 input output list<DAE.Exp> lhsExpLstAss = {};
2720 input output list<DAE.Exp> rhsExpLstAss = {};
2721 protected
2722 DAE.Exp newExp;
2723 algorithm
2724
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for e in inExpLst loop
2725 8 (eqCrefs, newExp, lhsExpLstRes, rhsExpLstRes, lhsExpLstAss, rhsExpLstAss) := createTmpCrefExpsForComplexEqnSys_work(e, crPrefix, eqCrefs, callCrefs, lhsExpLstRes, rhsExpLstRes, lhsExpLstAss, rhsExpLstAss);
2726 8 outExpList := newExp::outExpList;
2727 end for;
2728 2 outExpList := Dangerous.listReverseInPlace(outExpList);
2729 end createTmpCrefExpsForComplexEqnSys;
2730
2731 protected function createTmpCrefExpsForComplexEqnSys_work
2732 "This function gets a crefExp and decides if a tmp_crefExp is needed. If yes, tmp_crefExp is created and returned.
2733 It also returns lists of expressions to create inner equations and residual equations from.
2734 author: ptaeuber 06-2017"
2735 input DAE.Exp inExp;
2736 input DAE.ComponentRef inCrefPrefix;
2737 input output list<DAE.ComponentRef> eqCrefs;
2738 input list<DAE.ComponentRef> callCrefs;
2739 output DAE.Exp outCrefExp;
2740 input output list<DAE.Exp> lhsExpLstRes;
2741 input output list<DAE.Exp> rhsExpLstRes;
2742 input output list<DAE.Exp> lhsExpLstAss;
2743 input output list<DAE.Exp> rhsExpLstAss;
2744 algorithm
2745 outCrefExp := match inExp
2746 local
2747 String name;
2748 DAE.Type ty;
2749 DAE.ComponentRef cr, c1;
2750 list<DAE.ComponentRef> crlist;
2751 DAE.Exp e, exp, tmp_exp;
2752 list<DAE.Exp> tmp_lhsExpLstRes = {}, tmp_rhsExpLstRes = {}, tmp_lhsExpLstAss = {}, tmp_rhsExpLstAss = {};
2753 Boolean isEqCref, createTmpVar = false;
2754
2755 // Wild cref
2756 case DAE.CREF(componentRef=DAE.WILD()) then inExp;
2757
2758 // Array cref
2759 case DAE.CREF(componentRef=cr) guard Expression.isArrayType(ComponentReference.crefTypeFull(cr))
2760 algorithm
2761 2 crlist := ComponentReference.expandCref(cr, true);
2762
2763 // Loop array crefs to find out if at least one cref is not in cref list
2764 // (means not a variable solved in the current equation)
2765
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 for c in crlist loop
2766 // Prepare temporary crefExp
2767 10 name := ComponentReference.crefModelicaStr(c);
2768 10 ty := ComponentReference.crefTypeFull(c);
2769 10 c1 := ComponentReference.crefPrependIdent(inCrefPrefix,name,ComponentReferenceBasics.crefSubs(c),ty);
2770 10 tmp_exp := Expression.makeCrefExp(c1, ty);
2771 10 exp := Expression.makeCrefExp(c, ty);
2772
2773 10 isEqCref := List.isMemberOnTrue(c, eqCrefs, ComponentReferenceBasics.crefEqual);
2774
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if isEqCref then
2775 // Add cref to temporary assignment lists
2776 tmp_lhsExpLstAss := exp :: tmp_lhsExpLstAss;
2777 tmp_rhsExpLstAss := tmp_exp :: tmp_rhsExpLstAss;
2778
2779 // Delete that cref because it is not an iteration variable!
2780 10 eqCrefs := List.deleteMemberOnTrue(c, eqCrefs, ComponentReferenceBasics.crefEqual);
2781 else
2782 // Add cref to temporary residual lists
2783 tmp_lhsExpLstRes := tmp_exp :: tmp_lhsExpLstRes;
2784 tmp_rhsExpLstRes := exp :: tmp_rhsExpLstRes;
2785 end if;
2786
2787 10 createTmpVar := createTmpVar or not isEqCref;
2788 end for;
2789
2790 // If at least one cref is not in cref list create new tmp crefExp (variable) to add to the system
2791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if createTmpVar then
2792 // Prepare temporary crefExp
2793 ✗ name := ComponentReference.crefModelicaStr(cr);
2794 ✗ ty := ComponentReference.crefTypeFull(cr);
2795 ✗ cr := ComponentReference.crefPrependIdent(inCrefPrefix,name,ComponentReferenceBasics.crefSubs(cr),ty);
2796 ✗ e := Expression.makeCrefExp(cr, ty);
2797
2798 // Add temporary residual and assignment list to global lists
2799 ✗ lhsExpLstAss := listAppend(tmp_lhsExpLstAss, lhsExpLstAss);
2800 ✗ rhsExpLstAss := listAppend(tmp_rhsExpLstAss, rhsExpLstAss);
2801 ✗ lhsExpLstRes := listAppend(tmp_lhsExpLstRes, lhsExpLstRes);
2802 ✗ rhsExpLstRes := listAppend(tmp_rhsExpLstRes, rhsExpLstRes);
2803 else
2804 // All the crefs are to be solved in the current equation, so no tmp var is needed
2805 e := inExp;
2806 end if;
2807 then e;
2808
2809 // Normal cref
2810 case DAE.CREF(componentRef=cr)
2811 algorithm
2812 // If cref is not in cref list (means not a variable solved in the current equation)
2813 // create new tmp crefExp (variable) to add to the system
2814 // Also do this if cref occurs in lhs and rhs
2815
3/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
6 if not List.isMemberOnTrue(cr, eqCrefs, ComponentReferenceBasics.crefEqual) or List.isMemberOnTrue(cr, callCrefs, ComponentReferenceBasics.crefEqual) then
2816 // Prepare temporary crefExp
2817 2 name := ComponentReference.crefModelicaStr(cr);
2818 2 ty := ComponentReference.crefTypeFull(cr);
2819 2 cr := ComponentReference.crefPrependIdent(inCrefPrefix,name,ComponentReferenceBasics.crefSubs(cr),ty);
2820 2 e := Expression.makeCrefExp(cr, ty);
2821
2822 // Add expressions to residual lists
2823 lhsExpLstRes := e :: lhsExpLstRes;
2824 2 rhsExpLstRes := inExp :: rhsExpLstRes;
2825 else
2826 // Cref is to be solved in the current equation on the lhs, so no tmp var is needed
2827 e := inExp;
2828 // Delete that cref because it is not an iteration variable!
2829 4 eqCrefs := List.deleteMemberOnTrue(cr, eqCrefs, ComponentReferenceBasics.crefEqual);
2830 end if;
2831 then e;
2832
2833 else
2834 algorithm
2835 ✗ print("SimCodeUtil.createTmpCrefExpsForComplexEqnSys_work: fail for" + ExpressionBasics.printExpStr(inExp) + "\n");
2836 ✗ then fail();
2837 end match;
2838 end createTmpCrefExpsForComplexEqnSys_work;
2839
2840 protected function createArrayTempVar
2841 input DAE.ComponentRef name;
2842 input list<Integer> dims;
2843 input list<DAE.Exp> inTmpCrefsLst;
2844 input list<SimCodeVar.SimVar> itempvars;
2845 output list<SimCodeVar.SimVar> otempvars;
2846 algorithm
2847 otempvars := match inTmpCrefsLst
2848 local
2849 list<DAE.Exp> rest;
2850 list<SimCodeVar.SimVar> tempvars;
2851 DAE.Type ty;
2852 DAE.ComponentRef cr;
2853 SimCodeVar.SimVar var;
2854 list<String> slst;
2855
2856 case {} then itempvars;
2857
2858 case DAE.CREF(cr, ty)::rest algorithm
2859 129 slst := List.map(dims, intString);
2860
2/4
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 129 times.
129 if (FMI.isFMIVersion20() or FMI.isFMIVersion30()) then
2861 ✗ var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, SOME(name), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.LOCAL()), NONE(), NONE(), slst, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2862 else
2863 129 var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, SOME(name), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.NONECAUS()), NONE(), NONE(), slst, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2864 end if;
2865 129 tempvars := createTempVarsforCrefs(rest, {var});
2866 129 then List.append_reverse(tempvars, itempvars);
2867 end match;
2868 end createArrayTempVar;
2869
2870 protected function createTempVarsforCrefs
2871 input list<DAE.Exp> inTmpCrefsLst;
2872 input list<SimCodeVar.SimVar> itempvars;
2873 output list<SimCodeVar.SimVar> otempvars;
2874 algorithm
2875 otempvars := match inTmpCrefsLst
2876 local
2877 list<DAE.Exp> rest, expl;
2878 DAE.Type ty;
2879 DAE.ComponentRef cr;
2880 SimCodeVar.SimVar var;
2881 Option<DAE.ComponentRef> arrayCref;
2882 list<SimCodeVar.SimVar> tempvars;
2883 list<String> numArrayElement;
2884 list<DAE.Dimension> inst_dims;
2885
2886 case {} then itempvars;
2887
2888 case DAE.ARRAY(array=expl)::rest algorithm
2889 ✗ tempvars := createTempVarsforCrefs(expl, itempvars);
2890 ✗ then createTempVarsforCrefs(rest, tempvars);
2891
2892 case DAE.TUPLE(PR=expl)::rest algorithm
2893 ✗ tempvars := createTempVarsforCrefs(expl, itempvars);
2894 ✗ then createTempVarsforCrefs(rest, tempvars);
2895
2896 case DAE.CREF(cr, ty)::rest algorithm
2897 1778 arrayCref := ComponentReference.getArrayCref(cr);
2898 1778 inst_dims := ComponentReferenceBasics.crefDims(cr);
2899 1778 numArrayElement := List.map(inst_dims, ExpressionBasics.dimensionString);
2900
3/4
✓ Branch 2 taken 1775 times.
✓ Branch 3 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1775 times.
1778 if (FMI.isFMIVersion20() or FMI.isFMIVersion30()) then
2901 3 var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, arrayCref, SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.LOCAL()), NONE(), NONE(), numArrayElement, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2902 else
2903 1775 var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, arrayCref, SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.NONECAUS()), NONE(), NONE(), numArrayElement, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2904 end if;
2905 1778 then createTempVarsforCrefs(rest, var::itempvars);
2906 end match;
2907 end createTempVarsforCrefs;
2908
2909 protected function createTempVars
2910 input list<DAE.Var> varLst;
2911 input DAE.ComponentRef inCrefPrefix;
2912 input list<SimCodeVar.SimVar> itempvars;
2913 output list<SimCodeVar.SimVar> otempvars;
2914 algorithm
2915 otempvars := match varLst
2916 local
2917 list<DAE.Var> rest;
2918 list<SimCodeVar.SimVar> ttmpvars;
2919 DAE.Ident name;
2920 DAE.Type ty;
2921 DAE.ComponentRef cr, arraycref;
2922 list<String> numArrayElement;
2923 list<DAE.ComponentRef> crlst;
2924 SimCodeVar.SimVar var;
2925
2926 case {}
2927 then itempvars;
2928
2929 case DAE.TYPES_VAR(name=name, ty=ty as DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_)))::rest algorithm
2930 ✗ cr := ComponentReference.crefPrependIdent(inCrefPrefix, name, {}, ty);
2931 ✗ ttmpvars := createTempVars(ty.varLst, cr, itempvars);
2932 ✗ then createTempVars(rest, inCrefPrefix, ttmpvars);
2933
2934 case DAE.TYPES_VAR(name=name, ty=ty)::rest
2935 algorithm
2936 /* Prepend the tmp ident.*/
2937 1396 cr := ComponentReference.crefPrependIdent(inCrefPrefix, name, {}, ty);
2938 /* Expand the resulting cref.*/
2939
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1396 times.
1396 cr::crlst := ComponentReference.expandCref(cr, true /*the way it is now we won't get records here. but if we do somehow expand them*/);
2940
2941 /* Create SimVars from the list of expanded crefs.*/
2942
2943 /* Mark the first element as an arrayCref i.e. we have 'SOME(arraycref)' since this is how the C template
2944 detects first elements of arrays to generate VARNAME_indexed(..) macros for accessing the array
2945 with variable indexes.*/
2946 1396 arraycref := ComponentReference.crefStripSubs(cr);
2947 1396 numArrayElement := List.map(ComponentReferenceBasics.crefDims(cr), ExpressionBasics.dimensionString);
2948 1396 ty := ComponentReference.crefTypeFull(cr);
2949
3/4
✓ Branch 2 taken 1391 times.
✓ Branch 3 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1391 times.
1396 if (FMI.isFMIVersion20() or FMI.isFMIVersion30()) then
2950 5 var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, SOME(arraycref), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.LOCAL()), NONE(), NONE(), numArrayElement, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2951 else
2952 1391 var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, SOME(arraycref), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.NONECAUS()), NONE(), NONE(), numArrayElement, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2953 end if;
2954
2955 /* The rest don't need to be marked i.e. we have 'NONE()'. Just create simvars. */
2956 ttmpvars := {var};
2957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1396 times.
1396 for cr in crlst loop
2958 ✗ ty := ComponentReference.crefTypeFull(cr);
2959 ✗ if (FMI.isFMIVersion20() or FMI.isFMIVersion30()) then
2960 ✗ var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, NONE(), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.LOCAL()), NONE(), NONE(), numArrayElement, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2961 else
2962 ✗ var := SimCodeVar.SIMVAR(cr, BackendDAE.VARIABLE(), "", "", "", 0, NONE(), NONE(), NONE(), NONE(), false, ty, false, NONE(), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SOME(SimCodeVar.NONECAUS()), NONE(), NONE(), numArrayElement, false, true, SOME(true), false, NONE(), false, NONE(), NONE(), NONE(), SOME(cr), false, false);
2963 end if;
2964 ttmpvars := var::ttmpvars;
2965 end for;
2966 1396 ttmpvars := Dangerous.listReverseInPlace(ttmpvars);
2967 1396 ttmpvars := listAppend(itempvars,ttmpvars);
2968 1396 then createTempVars(rest, inCrefPrefix, ttmpvars);
2969
2970 end match;
2971 end createTempVars;
2972
2973 public function createNonlinearResidualEquations
2974 input list<BackendDAE.Equation> eqs;
2975 output list<SimCode.SimEqSystem> eqSystems = {};
2976 input output tuple<Integer, Integer> idx_tpl;
2977 input output list<SimCodeVar.SimVar> tempvars;
2978 input AvlTreePathFunction.Tree funcTree;
2979 protected
2980 Integer eq_idx, res_idx;
2981 algorithm
2982 try
2983
2/2
✓ Branch 1 taken 7162 times.
✓ Branch 2 taken 3116 times.
13394 for eq in listReverse(eqs) loop
2984 7162 (eq_idx, res_idx) := idx_tpl;
2985 eqSystems := match eq
2986 local
2987 DAE.Exp res_exp, e1, e2, e, lhse;
2988 list<DAE.Exp> explst, explst1;
2989 list<SimCode.SimEqSystem> eqSystlst;
2990 list<Integer> ds;
2991 DAE.ComponentRef left;
2992 list<DAE.Statement> algStatements;
2993 DAE.ElementSource source;
2994 list<tuple<DAE.Exp, DAE.Exp>> exptl;
2995 list<DAE.ComponentRef> crefs, crefstmp;
2996 BackendVarTransform.VariableReplacements repl;
2997 DAE.Type ty;
2998 DAE.Expand crefExpand;
2999 BackendDAE.EquationAttributes eqAttr;
3000 BackendDAE.Equation ifEq;
3001 list<BackendDAE.Equation> resEqs;
3002
3003 case BackendDAE.EQUATION(exp=e1, scalar=e2, source=source, attr=eqAttr) algorithm
3004 7124 res_exp := Expression.createResidualExp(e1, e2);
3005 7124 res_exp := Expression.replaceDerOpInExp(res_exp);
3006 7124 idx_tpl := (eq_idx + 1, res_idx + 1);
3007 7124 then SimCode.SES_RESIDUAL(eq_idx, res_idx, res_exp, source, eqAttr)::eqSystems;
3008
3009 case BackendDAE.RESIDUAL_EQUATION(exp=e, source=source, attr=eqAttr) algorithm
3010 ✗ (res_exp, _) := ExpressionSimplify.simplify(e);
3011 ✗ res_exp := Expression.replaceDerOpInExp(res_exp);
3012 ✗ idx_tpl := (eq_idx + 1, res_idx + 1);
3013 ✗ then SimCode.SES_RESIDUAL(eq_idx, res_idx, res_exp, source, eqAttr) :: eqSystems;
3014
3015 // if equations (kabdelhak: why eq_idx-1?)
3016 case ifEq as BackendDAE.IF_EQUATION() algorithm
3017 ✗ resEqs := BackendEquation.equationToScalarResidualForm(ifEq, funcTree);
3018 ✗ (eqSystlst, idx_tpl, tempvars) := createNonlinearResidualEquations(resEqs, (eq_idx-1, res_idx), tempvars, funcTree);
3019 then eqSystlst;
3020
3021 // An array equation
3022 case BackendDAE.ARRAY_EQUATION(dimSize=ds, left=e1, right=e2, source=source, attr=eqAttr) algorithm
3023 3 ty := Expression.typeof(e1);
3024 3 left := ComponentReferenceBasics.makeCrefIdent("$TMP_" + intString(eq_idx), ty, {});
3025 3 lhse := DAE.CREF(left,ty);
3026
3027 3 res_exp := Expression.createResidualExp(e1, e2);
3028 3 res_exp := Expression.replaceDerOpInExp(res_exp);
3029 3 crefstmp := ComponentReference.expandCref(left, false);
3030 3 explst1 := List.map(crefstmp, Expression.crefExp);
3031 3 (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(explst1, makeSES_RESIDUAL, source, eqAttr, (eq_idx, res_idx));
3032 3 eqSystlst := SimCode.SES_ARRAY_CALL_ASSIGN(eq_idx, lhse, res_exp, source, eqAttr)::eqSystlst;
3033 3 tempvars := createArrayTempVar(left, ds, explst1, tempvars);
3034 3 idx_tpl := (eq_idx + 1, res_idx);
3035 3 then listAppend(eqSystlst, eqSystems);
3036
3037 // A complex equation
3038 case BackendDAE.COMPLEX_EQUATION(left=e1, right=e2, source=source, attr=eqAttr) algorithm
3039 23 (e1, _) := ExpressionSimplify.simplify(e1);
3040 23 e1 := Expression.replaceDerOpInExp(e1);
3041 23 (e2, _) := ExpressionSimplify.simplify(e2);
3042 23 e2 := Expression.replaceDerOpInExp(e2);
3043 23 (eqSystlst, idx_tpl, tempvars) := createNonlinearResidualEquationsComplex(e1, e2, source, eqAttr, idx_tpl, tempvars);
3044 23 then listAppend(eqSystlst, eqSystems);
3045
3046 case BackendDAE.WHEN_EQUATION(whenEquation=BackendDAE.WHEN_STMTS()) algorithm
3047 // This following does not work. It does not take index or elseWhen into account.
3048 // The generated code for the when-equation also does not solve a linear system; it uses the variables directly.
3049 /*
3050 tp = Expression.typeof(e2);
3051 e1 = Expression.makeCrefExp(left, tp);
3052 res_exp = DAE.BINARY(e1, DAE.SUB(tp), e2);
3053 res_exp = ExpressionSimplify.simplify(res_exp);
3054 res_exp = Expression.replaceDerOpInExp(res_exp);
3055 (eqSystemsRest) = createNonlinearResidualEquations(rest, repl, uniqueEqIndex );
3056 then
3057 (SimCode.SES_RESIDUAL(0, res_exp) :: eqSystemsRest, entrylst1);
3058 */
3059 ✗ Error.addSourceMessage(Error.UNSUPPORTED_LANGUAGE_FEATURE, {"non-linear equations within when-equations", "Perform non-linear operations outside the when-equation (this is slower, but works)"}, BackendEquation.equationInfo(eq));
3060 ✗ then fail();
3061
3062 case BackendDAE.ALGORITHM(alg=DAE.ALGORITHM_STMTS(algStatements), source=source, expand=crefExpand, attr=eqAttr) algorithm
3063 12 crefs := CheckModel.checkAndGetAlgorithmOutputs(DAE.ALGORITHM_STMTS(algStatements), source, crefExpand);
3064 // BackendDump.debugStrCrefLstStr(("Crefs : ", crefs, ", ", "\n"));
3065 12 (crefstmp, repl) := createTmpCrefs(crefs, eq_idx, {}, BackendVarTransform.emptyReplacements());
3066 // BackendDump.debugStrCrefLstStr(("Crefs : ", crefstmp, ", ", "\n"));
3067 12 explst := List.map(crefs, Expression.crefExp);
3068 12 explst := List.map(explst, Expression.replaceDerOpInExp);
3069
3070 // BackendDump.dumpAlgorithms({DAE.ALGORITHM_STMTS(algStatements)}, 0);
3071 12 (algStatements, _) := BackendVarTransform.replaceStatementLst(algStatements, repl, SOME(BackendVarTransform.skipPreOperator), {}, false);
3072 // BackendDump.dumpAlgorithms({DAE.ALGORITHM_STMTS(algStatements)}, 0);
3073
3074 12 explst1 := List.map(crefstmp, Expression.crefExp);
3075 12 explst1 := List.map(explst1, Expression.replaceDerOpInExp);
3076 12 tempvars := createTempVarsforCrefs(explst1, tempvars);
3077
3078 // 0 = a - tmp
3079 12 exptl := List.zip(explst, explst1);
3080 12 (eqSystlst, (eq_idx, res_idx)) := List.map2Fold(exptl, makeSES_RESIDUAL1, source, eqAttr, (eq_idx, res_idx));
3081
3082 12 eqSystlst := SimCode.SES_ALGORITHM(eq_idx, algStatements, eqAttr)::eqSystlst;
3083 // Tpl.tplPrint(SimCodeDump.dumpEqs, eqSystlst);
3084
3085 12 idx_tpl := (eq_idx + 1, res_idx);
3086 12 then listAppend(eqSystlst, eqSystems);
3087 end match;
3088 end for;
3089 else
3090 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"function createNonlinearResidualEquations failed"});
3091 ✗ fail();
3092 end try;
3093 end createNonlinearResidualEquations;
3094
3095 public function fixNonlinearResidualIndices
3096 input list<SimCode.SimEqSystem> inSysts;
3097 output list<SimCode.SimEqSystem> outSysts = {};
3098 protected
3099 Integer index = 0;
3100 algorithm
3101
2/2
✓ Branch 0 taken 7423 times.
✓ Branch 1 taken 3109 times.
10532 for syst in inSysts loop
3102 syst := match syst
3103 case SimCode.SES_RESIDUAL() algorithm
3104 7383 syst.res_index := index;
3105 7383 index := index + 1;
3106 then syst;
3107 else syst;
3108 end match;
3109 outSysts := syst :: outSysts;
3110 end for;
3111 3109 outSysts := listReverse(outSysts);
3112 end fixNonlinearResidualIndices;
3113
3114 protected function createTmpCrefs
3115 input list<DAE.ComponentRef> inCrefs;
3116 input Integer iuniqueEqIndex;
3117 input list<DAE.ComponentRef> inCrefsAcc;
3118 input BackendVarTransform.VariableReplacements iRepl;
3119 output list<DAE.ComponentRef> outCrefs;
3120 output BackendVarTransform.VariableReplacements oRepl;
3121 algorithm
3122 (outCrefs, oRepl) := match inCrefs
3123 local
3124 DAE.ComponentRef cref, crtmp;
3125 list<DAE.ComponentRef> rest, result;
3126 DAE.Type tp;
3127 String ident;
3128 BackendVarTransform.VariableReplacements repl;
3129
3130 case {}
3131 12 then (listReverse(inCrefsAcc), iRepl);
3132
3133 case cref::rest algorithm
3134 20 ident := ComponentReferenceBasics.printComponentRefStr(cref);
3135 20 tp := Types.arrayElementType(ComponentReference.crefLastType(cref));
3136 20 crtmp := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + "_" + intString(iuniqueEqIndex), tp, {});
3137 40 repl := BackendVarTransform.addReplacement(iRepl, cref, DAE.CREF(crtmp, tp), SOME(BackendVarTransform.skipPreOperator));
3138 20 (result, repl) := createTmpCrefs(rest, iuniqueEqIndex, crtmp::inCrefsAcc, repl);
3139 then (result, repl);
3140 end match;
3141 end createTmpCrefs;
3142
3143 protected function makeSES_RESIDUAL
3144 input DAE.Exp inExp;
3145 input DAE.ElementSource source;
3146 input BackendDAE.EquationAttributes eqAttr;
3147 output SimCode.SimEqSystem outSimEqn;
3148 input output tuple<Integer, Integer> idx_tpl;
3149 annotation(__OpenModelica_EarlyInline = true);
3150 protected
3151 Integer eq_idx, res_idx;
3152 algorithm
3153 7 (eq_idx, res_idx) := idx_tpl;
3154 7 outSimEqn := SimCode.SES_RESIDUAL(eq_idx, res_idx, inExp, source, eqAttr);
3155 7 idx_tpl := (eq_idx + 1, res_idx + 1);
3156 end makeSES_RESIDUAL;
3157
3158 protected function makeSES_RESIDUAL1
3159 input tuple<DAE.Exp, DAE.Exp> inTpl;
3160 input DAE.ElementSource source;
3161 input BackendDAE.EquationAttributes eqAttr;
3162 output SimCode.SimEqSystem outSimEqn;
3163 input output tuple<Integer, Integer> idx_tpl;
3164 protected
3165 DAE.Exp e1, e2, e;
3166 Integer eq_idx, res_idx;
3167 algorithm
3168 252 (e1, e2) := inTpl;
3169 252 (eq_idx, res_idx) := idx_tpl;
3170 252 e := Expression.createResidualExp(e1, e2);
3171 252 outSimEqn := SimCode.SES_RESIDUAL(eq_idx, res_idx, e, source, eqAttr);
3172 252 idx_tpl := (eq_idx + 1, res_idx + 1);
3173 end makeSES_RESIDUAL1;
3174
3175 protected function makeSES_SIMPLE_ASSIGN
3176 input tuple<DAE.Exp, DAE.Exp> inTpl;
3177 input DAE.ElementSource source;
3178 input BackendDAE.EquationAttributes eqAttr;
3179 input Integer iuniqueEqIndex;
3180 output SimCode.SimEqSystem outSimEqn;
3181 output Integer ouniqueEqIndex;
3182 protected
3183 DAE.Exp e;
3184 DAE.ComponentRef cr;
3185 String msg;
3186 algorithm
3187 (cr, e) := match inTpl
3188 case (DAE.CREF(cr, _), e)
3189 then (cr,e);
3190 case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF(cr, _)), e)
3191 ✗ then (cr,Expression.negate(e)); // PHI: does this ever happen?
3192 else
3193 algorithm
3194 ✗ msg := "SimCodeUtil.makeSES_SIMPLE_ASSIGN failed for: " + ExpressionBasics.printExpStr(Util.tuple21(inTpl))+" = "+ExpressionBasics.printExpStr(Util.tuple22(inTpl))+"\n";
3195 ✗ Error.addCompilerWarning(msg);
3196 ✗ then fail();
3197 end match;
3198 2256 outSimEqn := SimCode.SES_SIMPLE_ASSIGN(iuniqueEqIndex, cr, e, source, eqAttr);
3199
1/2
✓ Branch 0 taken 2256 times.
✗ Branch 1 not taken.
2256 ouniqueEqIndex := iuniqueEqIndex+1;
3200 end makeSES_SIMPLE_ASSIGN;
3201
3202 protected function makeSES_SIMPLE_ASSIGNwithArray
3203 "extra case to correctly parse arrays that end up in simple assignments,
3204 mainly used for record attributes that are arrays.
3205 ticket #10519"
3206 input tuple<DAE.Exp, DAE.Exp> inTpl;
3207 input DAE.ElementSource source;
3208 input BackendDAE.EquationAttributes eqAttr;
3209 input Integer iuniqueEqIndex;
3210 output list<SimCode.SimEqSystem> outSimEqn = {};
3211 output Integer ouniqueEqIndex = iuniqueEqIndex;
3212 protected
3213 SimCode.SimEqSystem eqn;
3214 algorithm
3215 (outSimEqn, ouniqueEqIndex) := match inTpl
3216 local
3217 DAE.Exp left, right;
3218 list<DAE.Exp> elems;
3219 list<DAE.Var> varLst;
3220
3221 // parse arrays
3222 case(left as DAE.ARRAY(), right as DAE.CREF()) algorithm
3223 try
3224 // vectorize rhs and take the elements as a list
3225 ✗ DAE.ARRAY(array = elems) := Static.crefVectorize(true, right, right.ty, NONE(), Types.arrayElementType(right.ty));
3226 // create an assignment from each lhs and rhs element individually
3227 ✗ for tpl in List.zip(left.array, elems) loop
3228 ✗ (eqn, ouniqueEqIndex) := makeSES_SIMPLE_ASSIGN(tpl, source, eqAttr, ouniqueEqIndex);
3229 outSimEqn := eqn :: outSimEqn;
3230 end for;
3231 ✗ outSimEqn := listReverse(outSimEqn);
3232 else
3233 ✗ Error.terminate(getInstanceName() + " failed because expression "
3234 + ExpressionBasics.printExpStr(right) + " could not be scalarized.", sourceInfo());
3235 end try;
3236 ✗ then (outSimEqn, ouniqueEqIndex);
3237
3238 // parse records: a record inside a record is a record expression on the
3239 // left while the right hand side is still a cref
3240 case(DAE.RECORD(exps = elems, ty = DAE.T_COMPLEX(varLst = varLst)), right as DAE.CREF())
3241 ✗ then assignRecordElements(elems, varLst, right.componentRef, source, eqAttr, ouniqueEqIndex);
3242
3243 case(DAE.CALL(expLst = elems, attr = DAE.CALL_ATTR(ty = DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_), varLst = varLst))), right as DAE.CREF())
3244 ✗ then assignRecordElements(elems, varLst, right.componentRef, source, eqAttr, ouniqueEqIndex);
3245
3246 // kabdelhak: is this case needed? probably handled fine by simple assign
3247 // case(_, DAE.ARRAY()) algorithm
3248
3249 else algorithm
3250 1166 (eqn, ouniqueEqIndex) := makeSES_SIMPLE_ASSIGN(inTpl, source, eqAttr, ouniqueEqIndex);
3251 1166 then ({eqn}, ouniqueEqIndex);
3252 end match;
3253 end makeSES_SIMPLE_ASSIGNwithArray;
3254
3255 protected function assignRecordElements
3256 "Assigns each element of a record expression from the matching element of the
3257 record the given cref names. Neither side is a cref that could be assigned as
3258 a whole, since the left hand side is an expression over scalarized variables."
3259 input list<DAE.Exp> elems;
3260 input list<DAE.Var> varLst;
3261 input DAE.ComponentRef cref;
3262 input DAE.ElementSource source;
3263 input BackendDAE.EquationAttributes eqAttr;
3264 input Integer iuniqueEqIndex;
3265 output list<SimCode.SimEqSystem> outSimEqn = {};
3266 output Integer ouniqueEqIndex = iuniqueEqIndex;
3267 protected
3268 list<SimCode.SimEqSystem> eqns;
3269 SimCode.SimEqSystem eqn;
3270 algorithm
3271 ✗ for tpl in List.zip(elems, list(Expression.generateCrefsExpFromExpVar(v, cref) for v in varLst)) loop
3272 ✗ (eqns, ouniqueEqIndex) := makeSES_SIMPLE_ASSIGNwithArray(tpl, source, eqAttr, ouniqueEqIndex);
3273 ✗ for eqn in eqns loop
3274 outSimEqn := eqn :: outSimEqn;
3275 end for;
3276 end for;
3277 ✗ outSimEqn := listReverse(outSimEqn);
3278 end assignRecordElements;
3279
3280 protected function makeSolved
3281 input BackendDAE.Equation eq;
3282 output SimCode.SimEqSystem outSimEqn;
3283 input output Integer uniqueEqIndex;
3284 algorithm
3285 outSimEqn := match eq
3286 local
3287 list<tuple<DAE.Exp, list<SimCode.SimEqSystem>>> ifbranches;
3288 list<SimCode.SimEqSystem> elsebranch;
3289 list<DAE.Statement> stmts;
3290
3291 case BackendDAE.SOLVED_EQUATION()
3292 788 then SimCode.SES_SIMPLE_ASSIGN(uniqueEqIndex, eq.componentRef, eq.exp, eq.source, eq.attr);
3293
3294 case BackendDAE.IF_EQUATION() algorithm
3295 8 (ifbranches, uniqueEqIndex) := List.threadMapFold(eq.conditions, eq.eqnstrue, makeSolvedIfBranch, uniqueEqIndex);
3296 8 (elsebranch, uniqueEqIndex) := List.mapFold(eq.eqnsfalse, makeSolved, uniqueEqIndex);
3297 8 then SimCode.SES_IFEQUATION(uniqueEqIndex, ifbranches, elsebranch, eq.source, eq.attr);
3298
3299 case BackendDAE.ALGORITHM(alg = DAE.ALGORITHM_STMTS(stmts)) algorithm
3300 93 then SimCode.SES_ALGORITHM(uniqueEqIndex, stmts, eq.attr);
3301
3302 else algorithm
3303 ✗ Error.addInternalError(getInstanceName() + " failed!", sourceInfo());
3304 ✗ then fail();
3305 end match;
3306
1/2
✓ Branch 0 taken 889 times.
✗ Branch 1 not taken.
889 uniqueEqIndex := uniqueEqIndex + 1;
3307 end makeSolved;
3308
3309 protected function makeSolvedIfBranch
3310 input DAE.Exp cond;
3311 input list<BackendDAE.Equation> ifbranch;
3312 output tuple<DAE.Exp, list<SimCode.SimEqSystem>> result;
3313 input output Integer uniqueEqIndex;
3314 protected
3315 list<SimCode.SimEqSystem> lst;
3316 algorithm
3317 8 (lst, uniqueEqIndex) := List.mapFold(ifbranch, makeSolved, uniqueEqIndex);
3318 8 result := (cond, lst);
3319 end makeSolvedIfBranch;
3320
3321 protected function createOdeSystem
3322 input Boolean genDiscrete "if true generate discrete equations";
3323 input Boolean skipDiscInAlgorithm "if true skip discrete algorithm vars";
3324 input BackendDAE.EqSystem isyst;
3325 input BackendDAE.Shared ishared;
3326 input BackendDAE.StrongComponent inComp;
3327 input Integer iuniqueEqIndex;
3328 input list<SimCodeVar.SimVar> itempvars;
3329 input Integer isccIndex; //just to create the simEq to scc mapping. If you don't need this, set the parameter to 1
3330 input list<tuple<Integer,Integer>> ieqSccMapping;
3331 input SimCode.BackendMapping iBackendMapping;
3332 output list<SimCode.SimEqSystem> equations_;
3333 output list<SimCode.SimEqSystem> noDiscequations_;
3334 output Integer ouniqueEqIndex;
3335 output list<SimCodeVar.SimVar> otempvars;
3336 output list<tuple<Integer,Integer>> oeqSccMapping;
3337 output SimCode.BackendMapping oBackendMapping;
3338 algorithm
3339 (equations_, noDiscequations_, ouniqueEqIndex, otempvars, oeqSccMapping, oBackendMapping) := matchcontinue (isyst, ishared, inComp)
3340 local
3341 list<BackendDAE.Equation> eqn_lst;
3342 list<BackendDAE.Var> var_lst, var_lst_1;
3343 BackendDAE.Variables vars_1, vars, globalKnownVars;
3344 BackendDAE.EquationArray eqns_1, eqns;
3345 Option<list<tuple<Integer, Integer, BackendDAE.Equation>>> jac;
3346 BackendDAE.JacobianType jac_tp;
3347 AvlTreePathFunction.Tree funcs;
3348 list<Integer> eqIdcs;
3349 BackendDAE.StrongComponent comp;
3350 Integer uniqueEqIndex, uniqueEqIndexMapping;
3351 String msg;
3352 list<SimCodeVar.SimVar> tempvars;
3353 Boolean b;
3354 list<tuple<Integer,Integer>> tmpEqSccMapping;
3355 BackendDAE.ExtraInfo ei;
3356 BackendDAE.Jacobian jacobian;
3357 SimCode.BackendMapping tmpBackendMapping;
3358 Boolean mixedSystem;
3359 BackendDAE.TearingSet strictTearingSet;
3360 Option<BackendDAE.TearingSet> casualTearingSet;
3361 Boolean partOfJac;
3362 BackendDAE.InnerEquations innerEquations;
3363
3364 // EQUATIONSYSTEM: continuous system of equations
3365 case (BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns),
3366 BackendDAE.SHARED(globalKnownVars=globalKnownVars, functionTree=funcs, info = ei),
3367 comp as BackendDAE.EQUATIONSYSTEM(eqns=eqIdcs,jac=jacobian,jacType=jac_tp, mixedSystem=mixedSystem))
3368 algorithm
3369
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 202 times.
202 if Flags.isSet(Flags.FAILTRACE) then
3370 ✗ Debug.trace("function createOdeSystem create continuous system.\n");
3371 end if;
3372
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 202 times.
202 if Flags.isSet(Flags.GRAPHML) then
3373 ✗ BackendDump.dumpBipartiteGraphStrongComponent1(inComp,BackendEquation.equationList(eqns),BackendVariable.varList(vars), SOME(BackendDAEUtil.getFunctions(ishared)),"BIPARITEGRPAH_LS_"+intString(iuniqueEqIndex));
3374 end if;
3375
3376 // print("\ncreateOdeSystem -> Cont sys: ...\n");
3377 // extract the variables and equations of the block.
3378 202 (eqn_lst, var_lst,_) := BackendDAETransform.getEquationAndSolvedVar(comp, eqns, vars);
3379 // BackendDump.printEquationList(eqn_lst);
3380 // BackendDump.dumpVarList(var_lst, "var_lst");
3381 202 eqn_lst := BackendEquation.replaceDerOpInEquationList(eqn_lst);
3382 // States are solved for der(x) not x.
3383 202 var_lst_1 := List.map(var_lst, BackendVariable.transformXToXd);
3384 202 vars_1 := BackendVariable.listVar1(var_lst_1);
3385 202 eqns_1 := BackendEquation.listEquation(eqn_lst);
3386 202 partOfJac := BackendDAEUtil.isJacobianDAE(ishared);
3387 202 (equations_, uniqueEqIndex, tempvars) := createOdeSystem2(false, vars_1, globalKnownVars, eqns_1, jacobian, jac_tp, funcs, vars, iuniqueEqIndex, ei, mixedSystem, partOfJac, itempvars, partitionKindToClockIndex(isyst.partitionKind));
3388 202 uniqueEqIndexMapping := uniqueEqIndex-1; //a system with this index is created that contains all the equations with the indeces from iuniqueEqIndex to uniqueEqIndex-2
3389 //tmpEqSccMapping = appendSccIdxRange(iuniqueEqIndex, uniqueEqIndex - 1, isccIndex, ieqSccMapping);
3390 202 tmpEqSccMapping := appendSccIdxRange(uniqueEqIndexMapping, uniqueEqIndex - 1, isccIndex, ieqSccMapping);
3391 202 tmpBackendMapping := setEqMapping(List.intRange2(uniqueEqIndexMapping, uniqueEqIndex - 1),eqIdcs,iBackendMapping);
3392 202 then (equations_, equations_, uniqueEqIndex, tempvars, tmpEqSccMapping, tmpBackendMapping);
3393
3394 // TORNSYSTEM without residual equations: its inner equations solve it
3395 case (_, _, BackendDAE.TORNSYSTEM(strictTearingSet=BackendDAE.TEARINGSET(residualequations={}, innerEquations=innerEquations)))
3396 algorithm
3397 1 (equations_, uniqueEqIndex, tempvars) := createTornSystemInnerEqns(innerEquations, skipDiscInAlgorithm, genDiscrete, isyst, ishared, iuniqueEqIndex, itempvars, {});
3398 1 tmpEqSccMapping := appendSccIdxRange(iuniqueEqIndex, uniqueEqIndex - 1, isccIndex, ieqSccMapping);
3399 1 then (equations_, equations_, uniqueEqIndex, tempvars, tmpEqSccMapping, iBackendMapping);
3400
3401 // TORNSYSTEM
3402 case (BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), _, BackendDAE.TORNSYSTEM(strictTearingSet=strictTearingSet, casualTearingSet=casualTearingSet, linear=b, mixedSystem=mixedSystem))
3403 algorithm
3404
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1804 times.
1804 if Flags.isSet(Flags.GRAPHML) then
3405 ✗ BackendDump.dumpBipartiteGraphStrongComponent1(inComp,BackendEquation.equationList(eqns),BackendVariable.varList(vars), SOME(BackendDAEUtil.getFunctions(ishared)),"BIPARITEGRPAH_TS_"+intString(iuniqueEqIndex));
3406 end if;
3407
3408 1804 (equations_, uniqueEqIndex, tempvars) := createTornSystem(b, skipDiscInAlgorithm, genDiscrete, strictTearingSet, casualTearingSet, isyst, ishared, iuniqueEqIndex, mixedSystem, itempvars);
3409 1804 tmpEqSccMapping := appendSccIdx(uniqueEqIndex-1, isccIndex, ieqSccMapping);
3410 tmpBackendMapping := iBackendMapping;
3411 1804 then (equations_, equations_, uniqueEqIndex, tempvars, tmpEqSccMapping, tmpBackendMapping);
3412
3413 else
3414 algorithm
3415 ✗ msg := "function createOdeSystem failed for component " + BackendDump.strongComponentString(inComp);
3416 ✗ Error.addInternalError(msg, sourceInfo());
3417 ✗ then fail();
3418 end matchcontinue;
3419 end createOdeSystem;
3420
3421 protected function createOdeSystem2
3422 input Boolean mixedEvent "true if generating the mixed system event code";
3423 input BackendDAE.Variables inVars;
3424 input BackendDAE.Variables inKnVars;
3425 input BackendDAE.EquationArray inEquationArray;
3426 input BackendDAE.Jacobian inJacobian;
3427 input BackendDAE.JacobianType inJacobianType;
3428 input AvlTreePathFunction.Tree inFuncs;
3429 input BackendDAE.Variables inAllVars;
3430 input Integer iuniqueEqIndex;
3431 input BackendDAE.ExtraInfo iei;
3432 input Boolean mixedSystem;
3433 input Boolean partOfJac;
3434 input list<SimCodeVar.SimVar> itempvars;
3435 input Option<Integer> clockIndex;
3436 output list<SimCode.SimEqSystem> equations_;
3437 output Integer ouniqueEqIndex;
3438 output list<SimCodeVar.SimVar> otempvars;
3439 algorithm
3440 (equations_, ouniqueEqIndex, otempvars) := matchcontinue (inJacobian, inJacobianType)
3441 local
3442 Integer uniqueEqIndex;
3443 list<BackendDAE.Equation> eqn_lst;
3444 list<DAE.ComponentRef> crefs;
3445 list<SimCode.SimEqSystem> resEqs;
3446 list<SimCodeVar.SimVar> simVars;
3447 list<DAE.Exp> beqs;
3448 list<tuple<Integer, Integer, BackendDAE.Equation>> jac;
3449 list<tuple<Integer, Integer, SimCode.SimEqSystem>> simJac;
3450 Integer linInfo;
3451 list<list<Real>> jacVals;
3452 list<Real> rhsVals, solvedVals;
3453 list<DAE.ElementSource> sources;
3454 list<DAE.ComponentRef> names;
3455 list<SimCodeVar.SimVar> tempvars;
3456 String str;
3457 Option<SimCode.JacobianMatrix> jacobianMatrix;
3458 Boolean homotopySupport;
3459
3460 // constant jacobians. Linear system of equations (A x = b) where
3461 // A and b are constants. TODO: implement symbolic gaussian elimination
3462 // here. Currently uses dgesv as for next case
3463 case (BackendDAE.FULL_JACOBIAN(SOME(jac)), BackendDAE.JAC_CONSTANT()) algorithm
3464 ✗ if Flags.isSet(Flags.FAILTRACE) then
3465 ✗ Debug.trace("function createOdeSystem2 create linear system(const jacobian).\n");
3466 end if;
3467 ✗ (simVars, _) := BackendVariable.traverseBackendDAEVars(inVars, traversingdlowvarToSimvar, ({}, inKnVars));
3468 ✗ simVars := listReverse(simVars);
3469 ✗ (beqs, sources) := BackendDAEUtil.getEqnSysRhs(inEquationArray, inVars, SOME(inFuncs));
3470 ✗ beqs := listReverse(beqs);
3471 ✗ rhsVals := ValuesUtil.valueReals(List.map(beqs, Ceval.cevalSimple));
3472 ✗ jacVals := SymbolicJacobian.evaluateConstantJacobian(listLength(simVars), jac);
3473 ✗ (solvedVals, linInfo) := System.dgesv(jacVals, rhsVals);
3474 ✗ names := list(v.name for v in simVars);
3475 ✗ checkLinearSystem(linInfo, names, jacVals, rhsVals);
3476 // TODO: Move these to known vars :/ This is done in the wrong phase of the compiler... Also, if done as an optimization module, we can optimize more!
3477 ✗ sources := List.map1(sources, ElementSource.addSymbolicTransformation, DAE.LINEAR_SOLVED(names, jacVals, rhsVals, solvedVals));
3478 ✗ (equations_, uniqueEqIndex) := List.thread3MapFold(simVars, solvedVals, sources, generateSolvedEquation, iuniqueEqIndex);
3479 then (equations_, uniqueEqIndex, itempvars);
3480
3481 // Time varying linear jacobian. Linear system of equations that needs to be solved during runtime.
3482 case (BackendDAE.FULL_JACOBIAN(SOME(jac)), BackendDAE.JAC_LINEAR()) algorithm
3483
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
144 if Flags.isSet(Flags.FAILTRACE) then
3484 ✗ Debug.trace("function createOdeSystem2 create linear system with jacobian.\n");
3485 end if;
3486 144 (simVars, _) := BackendVariable.traverseBackendDAEVars(inVars, traversingdlowvarToSimvar, ({}, inKnVars));
3487 144 simVars := listReverse(simVars);
3488 144 (beqs, sources) := BackendDAEUtil.getEqnSysRhs(inEquationArray, inVars, SOME(inFuncs));
3489 144 beqs := listReverse(beqs);
3490 144 simJac := List.map1(jac, jacToSimjac, inVars);
3491
3/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 140 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
144 if (Config.simCodeTarget() == "Cpp" ) then
3492 4 simJac := List.sort(simJac,simJacCSRToCSC);
3493 end if;
3494
3495
3/4
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
563 then ({SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(iuniqueEqIndex, mixedEvent, false, simVars, beqs, simJac, {}, NONE(), sources, 0, inVars.numberOfVars, partOfJac), NONE(), BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)}, iuniqueEqIndex+1, itempvars);
3496
3497 // Time varying nonlinear jacobian. Non-linear system of equations.
3498 case (_, BackendDAE.JAC_GENERIC()) algorithm
3499
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if Flags.isSet(Flags.FAILTRACE) then
3500 ✗ Debug.trace("function createOdeSystem2 create non-linear system with jacobian.");
3501 end if;
3502 57 eqn_lst := BackendEquation.equationList(inEquationArray);
3503 57 crefs := BackendVariable.getAllCrefFromVariables(inVars);
3504
3505 57 (resEqs, (uniqueEqIndex, _), tempvars) := createNonlinearResidualEquations(eqn_lst, (iuniqueEqIndex, 0), itempvars, inFuncs);
3506 57 resEqs := fixNonlinearResidualIndices(resEqs);
3507 // create symbolic jacobian for simulation
3508 57 (jacobianMatrix, uniqueEqIndex, tempvars) := createSymbolicSimulationJacobian(inJacobian, uniqueEqIndex, tempvars, true);
3509 57 (_, homotopySupport) := BackendEquation.traverseExpsOfEquationList(eqn_lst, BackendDAEUtil.containsHomotopyCall, false);
3510
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
228 then ({SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(uniqueEqIndex, resEqs, crefs, 0, inVars.numberOfVars+listLength(tempvars)-listLength(itempvars), jacobianMatrix, homotopySupport, mixedSystem, false, clockIndex), NONE(), BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)}, uniqueEqIndex+1, tempvars);
3511
3512 // No analytic jacobian available. Generate non-linear system.
3513 case (_, _) algorithm
3514
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if Flags.isSet(Flags.FAILTRACE) then
3515 ✗ Debug.trace("function createOdeSystem2 create non-linear system without jacobian.");
3516 end if;
3517 1 eqn_lst := BackendEquation.equationList(inEquationArray);
3518 1 crefs := BackendVariable.getAllCrefFromVariables(inVars);
3519 1 (resEqs, (uniqueEqIndex, _), tempvars) := createNonlinearResidualEquations(eqn_lst, (iuniqueEqIndex, 0), itempvars, inFuncs);
3520 1 resEqs := fixNonlinearResidualIndices(resEqs);
3521 1 (_, homotopySupport) := BackendEquation.traverseExpsOfEquationList(eqn_lst, BackendDAEUtil.containsHomotopyCall, false);
3522
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
4 then ({SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(uniqueEqIndex, resEqs, crefs, 0, inVars.numberOfVars+listLength(tempvars)-listLength(itempvars), NONE(), homotopySupport, mixedSystem, false, clockIndex), NONE(), BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)}, uniqueEqIndex+1, tempvars);
3523
3524 // failure
3525 else algorithm
3526 ✗ str := BackendDump.jacobianTypeStr(inJacobianType);
3527 ✗ str := stringAppendList({"createOdeSystem2 failed for ", str});
3528 ✗ Error.addInternalError(str, sourceInfo());
3529 ✗ then fail();
3530 end matchcontinue;
3531 end createOdeSystem2;
3532
3533 protected function checkLinearSystem
3534 input Integer info;
3535 input list<DAE.ComponentRef> vars;
3536 input list<list<Real>> jac;
3537 input list<Real> rhs;
3538 algorithm
3539 () := matchcontinue info
3540 local
3541 String infoStr, syst, varnames, varname, rhsStr, jacStr;
3542 case 0 then ();
3543 case _
3544 algorithm
3545 ✗ true := info > 0;
3546 ✗ varname := ComponentReferenceBasics.printComponentRefStr(listGet(vars, info));
3547 ✗ infoStr := intString(info);
3548 ✗ varnames := stringDelimitList(List.map(vars, ComponentReferenceBasics.printComponentRefStr), " ;\n ");
3549 ✗ rhsStr := stringDelimitList(List.map(rhs, realString), " ;\n ");
3550 ✗ jacStr := stringDelimitList(List.map1(List.mapList(jac, realString), stringDelimitList, " , "), " ;\n ");
3551 ✗ syst := stringAppendList({"\n[\n ", jacStr, "\n]\n *\n[\n ", varnames, "\n]\n =\n[\n ", rhsStr, "\n]"});
3552 ✗ Error.addMessage(Error.LINEAR_SYSTEM_SINGULAR, {syst, infoStr, varname});
3553 ✗ then fail();
3554 case _
3555 algorithm
3556 ✗ true := info < 0;
3557 ✗ varnames := stringDelimitList(List.map(vars, ComponentReferenceBasics.printComponentRefStr), " ;\n ");
3558 ✗ rhsStr := stringDelimitList(List.map(rhs, realString), " ; ");
3559 ✗ jacStr := stringDelimitList(List.map1(List.mapList(jac, realString), stringDelimitList, " , "), " ; ");
3560 ✗ syst := stringAppendList({"[", jacStr, "] * [", varnames, "] = [", rhsStr, "]"});
3561 ✗ Error.addMessage(Error.LINEAR_SYSTEM_INVALID, {"LAPACK/dgesv", syst});
3562 ✗ then fail();
3563 end matchcontinue;
3564 end checkLinearSystem;
3565
3566 protected function generateSolvedEquation
3567 input SimCodeVar.SimVar var;
3568 input Real val;
3569 input DAE.ElementSource source;
3570 input Integer iuniqueEqIndex;
3571 output SimCode.SimEqSystem eq;
3572 output Integer ouniqueEqIndex;
3573 protected
3574 DAE.ComponentRef name;
3575 algorithm
3576 ✗ SimCodeVar.SIMVAR(name=name) := var;
3577 ✗ eq := SimCode.SES_SIMPLE_ASSIGN(iuniqueEqIndex, name, DAE.RCONST(val), source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
3578 ✗ ouniqueEqIndex := iuniqueEqIndex+1;
3579 end generateSolvedEquation;
3580
3581 protected function createTornSystem
3582 input Boolean linear;
3583 input Boolean skipDiscInAlgorithm "if true skip discrete algorithm vars";
3584 input Boolean genDiscrete;
3585 input BackendDAE.TearingSet strictTearingSet;
3586 input Option<BackendDAE.TearingSet> casualTearingSet;
3587 input BackendDAE.EqSystem isyst;
3588 input BackendDAE.Shared ishared;
3589 input Integer iuniqueEqIndex;
3590 input Boolean mixedSystem;
3591 input list<SimCodeVar.SimVar> itempvars;
3592 output list<SimCode.SimEqSystem> equations_;
3593 output Integer ouniqueEqIndex;
3594 output list<SimCodeVar.SimVar> otempvars;
3595 algorithm
3596 (equations_, ouniqueEqIndex, otempvars) := match(linear, isyst, ishared)
3597 local
3598 list<BackendDAE.Var> tvars;
3599 list<BackendDAE.Equation> reqns;
3600 BackendDAE.Variables vars, globalKnownVars;
3601 BackendDAE.EquationArray eqns;
3602 list<SimCodeVar.SimVar> tempvars, tempvars2, simVars;
3603 list<SimCode.SimEqSystem> simequations, resEqs, eqs;
3604 Integer uniqueEqIndex, nInnerVars;
3605 list<DAE.ComponentRef> tcrs;
3606 Option<SimCode.JacobianMatrix> jacobianMatrix;
3607 list<Integer> tearingVars, residualEqns;
3608 Boolean homotopySupport;
3609 BackendDAE.InnerEquations innerEquations;
3610 BackendDAE.Jacobian inJacobian;
3611 SimCode.LinearSystem lSystem;
3612 SimCode.NonlinearSystem nlSystem;
3613 Option<SimCode.LinearSystem> alternativeTearingL;
3614 Option<SimCode.NonlinearSystem> alternativeTearingNl;
3615 Boolean partOfJac;
3616 Option<Integer> clockIndex;
3617
3618 // CASE: linear
3619 case(true, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), BackendDAE.SHARED(globalKnownVars=globalKnownVars)) algorithm
3620 965 BackendDAE.TEARINGSET(tearingvars=tearingVars, residualequations=residualEqns, innerEquations=innerEquations, jac=inJacobian) := strictTearingSet;
3621
3622
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 965 times.
965 if not SymbolicJacobian.isJacobianGeneric(inJacobian) then
3623 ✗ Error.addMessage(Error.NO_JACONIAN_TORNLINEAR_SYSTEM, {});
3624 ✗ fail();
3625 end if;
3626
3627 // get tearing vars
3628 965 tvars := List.map1r(tearingVars, BackendVariable.getVarAt, vars);
3629 965 tvars := List.map(tvars, BackendVariable.transformXToXd);
3630 965 (simVars, _) := List.fold(tvars, traversingdlowvarToSimvarFold, ({}, globalKnownVars));
3631 965 simVars := listReverse(simVars);
3632
3633 // get residual eqns
3634 965 reqns := BackendEquation.getList(residualEqns, eqns);
3635 965 reqns := BackendEquation.replaceDerOpInEquationList(reqns);
3636 // generate other equations
3637 965 (simequations, uniqueEqIndex, tempvars, nInnerVars, _) := createTornSystemInnerEqns(innerEquations, skipDiscInAlgorithm, genDiscrete, isyst, ishared, iuniqueEqIndex, itempvars, {});
3638 965 (resEqs, (uniqueEqIndex, _), tempvars) := createNonlinearResidualEquations(reqns, (uniqueEqIndex, 0), tempvars, ishared.functionTree);
3639 965 resEqs := fixNonlinearResidualIndices(resEqs);
3640 965 eqs := listAppend(simequations, resEqs);
3641
3642 965 (jacobianMatrix, uniqueEqIndex, tempvars) := createSymbolicSimulationJacobian(inJacobian, uniqueEqIndex, tempvars);
3643 965 partOfJac := BackendDAEUtil.isJacobianDAE(ishared);
3644
2/2
✓ Branch 0 taken 952 times.
✓ Branch 1 taken 13 times.
1917 lSystem := SimCode.LINEARSYSTEM(uniqueEqIndex, false, true, simVars, {}, {}, eqs, jacobianMatrix, {}, 0, listLength(tvars)+nInnerVars+listLength(tempvars)-listLength(itempvars), partOfJac);
3645 965 tempvars2 := tempvars;
3646
3647 // Do if dynamic tearing is activated
3648
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 965 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 965 times.
965 if isSome(casualTearingSet) then
3649 ✗ SOME(BackendDAE.TEARINGSET(tearingvars=tearingVars, residualequations=residualEqns, innerEquations=innerEquations, jac=inJacobian)) := casualTearingSet;
3650 // get tearing vars
3651 ✗ tvars := List.map1r(tearingVars, BackendVariable.getVarAt, vars);
3652 ✗ tvars := List.map(tvars, BackendVariable.transformXToXd);
3653 ✗ (simVars, _) := List.fold(tvars, traversingdlowvarToSimvarFold, ({}, globalKnownVars));
3654 ✗ simVars := listReverse(simVars);
3655
3656 // get residual eqns
3657 ✗ reqns := BackendEquation.getList(residualEqns, eqns);
3658 ✗ reqns := BackendEquation.replaceDerOpInEquationList(reqns);
3659 // generate other equations
3660 ✗ (simequations, uniqueEqIndex, tempvars2, nInnerVars, _) := createTornSystemInnerEqns(innerEquations, skipDiscInAlgorithm, genDiscrete, isyst, ishared, uniqueEqIndex+1, tempvars, {});
3661 ✗ (resEqs, (uniqueEqIndex, _), tempvars2) := createNonlinearResidualEquations(reqns, (uniqueEqIndex, 0), tempvars2, ishared.functionTree);
3662 ✗ resEqs := fixNonlinearResidualIndices(resEqs);
3663 ✗ eqs := listAppend(simequations, resEqs);
3664
3665 ✗ (jacobianMatrix, uniqueEqIndex, tempvars2) := createSymbolicSimulationJacobian(inJacobian, uniqueEqIndex, tempvars2);
3666 ✗ alternativeTearingL := SOME(SimCode.LINEARSYSTEM(uniqueEqIndex, false, true, simVars, {}, {}, eqs, jacobianMatrix, {}, 0, listLength(tvars)+nInnerVars+listLength(tempvars2)-listLength(tempvars), partOfJac));
3667
3668 else
3669 alternativeTearingL := NONE();
3670 end if;
3671 1930 then ({SimCode.SES_LINEAR(lSystem, alternativeTearingL, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)}, uniqueEqIndex+1, tempvars2);
3672
3673 // CASE: nonlinear
3674 case(false, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), _) algorithm
3675 839 BackendDAE.TEARINGSET(tearingvars=tearingVars, residualequations=residualEqns, innerEquations=innerEquations, jac=inJacobian) := strictTearingSet;
3676 // get tearing vars
3677 839 tvars := List.map1r(tearingVars, BackendVariable.getVarAt, vars);
3678 839 tvars := List.map(tvars, BackendVariable.transformXToXd);
3679
3680 // get residual eqns
3681 839 reqns := BackendEquation.getList(residualEqns, eqns);
3682 839 reqns := BackendEquation.replaceDerOpInEquationList(reqns);
3683 // generate residual replacements
3684 839 tcrs := List.map(tvars, BackendVariable.varCref);
3685 // generate other equations
3686 839 (simequations, uniqueEqIndex, tempvars, nInnerVars, homotopySupport) := createTornSystemInnerEqns(innerEquations, skipDiscInAlgorithm, genDiscrete, isyst, ishared, iuniqueEqIndex, itempvars, {});
3687 839 (resEqs, (uniqueEqIndex, _), tempvars) := createNonlinearResidualEquations(reqns, (uniqueEqIndex, 0), tempvars, ishared.functionTree);
3688 839 resEqs := fixNonlinearResidualIndices(resEqs);
3689 839 eqs := listAppend(simequations, resEqs);
3690
3691 839 (jacobianMatrix, uniqueEqIndex, tempvars) := createSymbolicSimulationJacobian(inJacobian, uniqueEqIndex, tempvars, true);
3692
2/2
✓ Branch 0 taken 811 times.
✓ Branch 1 taken 28 times.
839 if not homotopySupport then
3693 811 (_, homotopySupport) := BackendEquation.traverseExpsOfEquationList(reqns, BackendDAEUtil.containsHomotopyCall, false);
3694 end if;
3695
3696 839 clockIndex := partitionKindToClockIndex(isyst.partitionKind);
3697
3698
4/4
✓ Branch 0 taken 634 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 803 times.
✓ Branch 3 taken 36 times.
2276 nlSystem := SimCode.NONLINEARSYSTEM(uniqueEqIndex, eqs, tcrs, 0, listLength(tvars)+nInnerVars+listLength(tempvars)-listLength(itempvars), jacobianMatrix, homotopySupport, mixedSystem, true, clockIndex);
3699 839 tempvars2 := tempvars;
3700
3701 // Do if dynamic tearing is activated
3702
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 839 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 836 times.
839 if isSome(casualTearingSet) then
3703 3 SOME(BackendDAE.TEARINGSET(tearingvars=tearingVars, residualequations=residualEqns, innerEquations=innerEquations, jac=inJacobian)) := casualTearingSet;
3704 // get tearing vars
3705 3 tvars := List.map1r(tearingVars, BackendVariable.getVarAt, vars);
3706 3 tvars := List.map(tvars, BackendVariable.transformXToXd);
3707
3708 // get residual eqns
3709 3 reqns := BackendEquation.getList(residualEqns, eqns);
3710 3 reqns := BackendEquation.replaceDerOpInEquationList(reqns);
3711 // generate residual replacements
3712 3 tcrs := List.map(tvars, BackendVariable.varCref);
3713 // generate other equations
3714 3 (simequations, uniqueEqIndex, tempvars2, nInnerVars, homotopySupport) := createTornSystemInnerEqns(innerEquations, skipDiscInAlgorithm, genDiscrete, isyst, ishared, uniqueEqIndex+1, tempvars, {});
3715 3 (resEqs, (uniqueEqIndex, _), tempvars2) := createNonlinearResidualEquations(reqns, (uniqueEqIndex, 0), tempvars2, ishared.functionTree);
3716 3 resEqs := fixNonlinearResidualIndices(resEqs);
3717 3 eqs := listAppend(simequations, resEqs);
3718
3719 3 (jacobianMatrix, uniqueEqIndex, tempvars2) := createSymbolicSimulationJacobian(inJacobian, uniqueEqIndex, tempvars2);
3720
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if not homotopySupport then
3721 3 (_, homotopySupport) := BackendEquation.traverseExpsOfEquationList(reqns, BackendDAEUtil.containsHomotopyCall, false);
3722 end if;
3723
3724
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 alternativeTearingNl := SOME(SimCode.NONLINEARSYSTEM(uniqueEqIndex, eqs, tcrs, 0, listLength(tvars)+nInnerVars+listLength(tempvars2)-listLength(tempvars), jacobianMatrix, homotopySupport, mixedSystem, true, clockIndex));
3725 else
3726 alternativeTearingNl := NONE();
3727 end if;
3728 1678 then ({SimCode.SES_NONLINEAR(nlSystem, alternativeTearingNl, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)}, uniqueEqIndex+1, tempvars2);
3729 end match;
3730 end createTornSystem;
3731
3732 protected function solveInnerEquations "author: Frenkel TUD 2011-05
3733 try to solve the equations"
3734 input BackendDAE.InnerEquations innerEquations;
3735 input BackendDAE.EquationArray inEqns;
3736 input BackendDAE.Variables inVars;
3737 input BackendDAE.Shared ishared;
3738 input BackendVarTransform.VariableReplacements inRepl;
3739 output BackendVarTransform.VariableReplacements outRepl;
3740 algorithm
3741 outRepl := match innerEquations
3742 local
3743 BackendDAE.InnerEquations rest;
3744 Integer v, e;
3745 DAE.Exp e1, e2, varexp, expr;
3746 DAE.ComponentRef cr, dcr;
3747 BackendVarTransform.VariableReplacements repl;
3748 BackendDAE.Var var;
3749 list<BackendDAE.Var> varlst;
3750 list<Integer> ds, vlst;
3751 list<DAE.Exp> explst1, explst2;
3752 BackendDAE.Equation eqn;
3753 list<list<DAE.Subscript>> subslst;
3754 AvlTreePathFunction.Tree funcs;
3755
3756 case {} then inRepl;
3757 case BackendDAE.INNEREQUATION(eqn=e, vars={v})::rest
3758 algorithm
3759 ✗ BackendDAE.EQUATION(exp=e1, scalar=e2) := BackendEquation.get(inEqns, e);
3760 ✗ var as BackendDAE.VAR(varName=cr) := BackendVariable.getVarAt(inVars, v);
3761 ✗ varexp := Expression.crefExp(cr);
3762 ✗ varexp := if BackendVariable.isStateVar(var) then Expression.expDer(varexp) else varexp;
3763 ✗ BackendDAE.SHARED(functionTree = funcs) := ishared;
3764 ✗ (expr, {}, {}, {}) := ExpressionSolve.solve2(e1, e2, varexp, SOME(funcs), NONE(), true, BackendDAEUtil.isSimulationDAE(ishared));
3765 ✗ dcr := if BackendVariable.isStateVar(var) then ComponentReference.crefPrefixDer(cr) else cr;
3766 ✗ repl := BackendVarTransform.addReplacement(inRepl, dcr, expr, SOME(BackendVarTransform.skipPreOperator));
3767 ✗ repl := if BackendVariable.isStateVar(var) then BackendVarTransform.addDerConstRepl(cr, expr, repl) else repl;
3768 // BackendDump.debugStrCrefStrExpStr(("", cr, " := ", expr, "\n"));
3769 ✗ then
3770 solveInnerEquations(rest, inEqns, inVars, ishared, repl);
3771 case BackendDAE.INNEREQUATION(eqn=e, vars=vlst)::rest
3772 algorithm
3773 ✗ BackendDAE.ARRAY_EQUATION(dimSize=ds, left=e1, right=e2) := BackendEquation.get(inEqns, e);
3774 ✗ varlst := List.map1r(vlst, BackendVariable.getVarAt, inVars);
3775 ✗ subslst := Expression.dimensionSizesSubscripts(ds);
3776 ✗ subslst := Expression.rangesToSubscripts(subslst);
3777 ✗ explst1 := List.map1r(subslst, Expression.applyExpSubscripts, e1);
3778 ✗ explst1 := ExpressionSimplify.simplifyList(explst1);
3779 ✗ explst2 := List.map1r(subslst, Expression.applyExpSubscripts, e2);
3780 ✗ explst2 := ExpressionSimplify.simplifyList(explst2);
3781 ✗ repl := solveInnerEquations1(explst1, explst2, varlst, inVars, ishared, inRepl);
3782 ✗ then
3783 solveInnerEquations(rest, inEqns, inVars, ishared, repl);
3784 case BackendDAE.INNEREQUATIONCONSTRAINTS(eqn=e, vars={v})::rest
3785 algorithm
3786 ✗ BackendDAE.EQUATION(exp=e1, scalar=e2) := BackendEquation.get(inEqns, e);
3787 ✗ var as BackendDAE.VAR(varName=cr) := BackendVariable.getVarAt(inVars, v);
3788 ✗ varexp := Expression.crefExp(cr);
3789 ✗ varexp := if BackendVariable.isStateVar(var) then Expression.expDer(varexp) else varexp;
3790 ✗ BackendDAE.SHARED(functionTree = funcs) := ishared;
3791 ✗ (expr, {}, {}, {}) := ExpressionSolve.solve2(e1, e2, varexp, SOME(funcs), NONE(), true, BackendDAEUtil.isSimulationDAE(ishared));
3792 ✗ dcr := if BackendVariable.isStateVar(var) then ComponentReference.crefPrefixDer(cr) else cr;
3793 ✗ repl := BackendVarTransform.addReplacement(inRepl, dcr, expr, SOME(BackendVarTransform.skipPreOperator));
3794 ✗ repl := if BackendVariable.isStateVar(var) then BackendVarTransform.addDerConstRepl(cr, expr, repl) else repl;
3795 // BackendDump.debugStrCrefStrExpStr(("", cr, " := ", expr, "\n"));
3796 ✗ then
3797 solveInnerEquations(rest, inEqns, inVars, ishared, repl);
3798 case BackendDAE.INNEREQUATIONCONSTRAINTS(eqn=e, vars=vlst)::rest
3799 algorithm
3800 ✗ BackendDAE.ARRAY_EQUATION(dimSize=ds, left=e1, right=e2) := BackendEquation.get(inEqns, e);
3801 ✗ varlst := List.map1r(vlst, BackendVariable.getVarAt, inVars);
3802 ✗ subslst := Expression.dimensionSizesSubscripts(ds);
3803 ✗ subslst := Expression.rangesToSubscripts(subslst);
3804 ✗ explst1 := List.map1r(subslst, Expression.applyExpSubscripts, e1);
3805 ✗ explst1 := ExpressionSimplify.simplifyList(explst1);
3806 ✗ explst2 := List.map1r(subslst, Expression.applyExpSubscripts, e2);
3807 ✗ explst2 := ExpressionSimplify.simplifyList(explst2);
3808 ✗ repl := solveInnerEquations1(explst1, explst2, varlst, inVars, ishared, inRepl);
3809 ✗ then
3810 solveInnerEquations(rest, inEqns, inVars, ishared, repl);
3811 end match;
3812 end solveInnerEquations;
3813
3814 protected function solveInnerEquations1 "author: Frenkel TUD 2011-05
3815 try to solve the equations"
3816 input list<DAE.Exp> iExps1;
3817 input list<DAE.Exp> iExps2;
3818 input list<BackendDAE.Var> iVars;
3819 input BackendDAE.Variables inVars;
3820 input BackendDAE.Shared ishared;
3821 input BackendVarTransform.VariableReplacements inRepl;
3822 output BackendVarTransform.VariableReplacements outRepl;
3823 algorithm
3824 outRepl :=
3825 match (iExps1, iExps2, iVars)
3826 local
3827 DAE.Exp e1, e2, varexp, expr;
3828 DAE.ComponentRef cr, dcr;
3829 BackendVarTransform.VariableReplacements repl;
3830 BackendDAE.Var var;
3831 list<BackendDAE.Var> rest;
3832 list<DAE.Exp> explst1, explst2;
3833 AvlTreePathFunction.Tree funcs;
3834 case ({}, _, _) then inRepl;
3835 case (e1::explst1, e2::explst2, (var as BackendDAE.VAR(varName=cr))::rest)
3836 algorithm
3837 ✗ varexp := Expression.crefExp(cr);
3838 ✗ varexp := if BackendVariable.isStateVar(var) then Expression.expDer(varexp) else varexp;
3839 ✗ BackendDAE.SHARED(functionTree = funcs) := ishared;
3840 ✗ (expr, {}, {}, {}) := ExpressionSolve.solve2(e1, e2, varexp, SOME(funcs), NONE(), true, BackendDAEUtil.isSimulationDAE(ishared));
3841 ✗ dcr := if BackendVariable.isStateVar(var) then ComponentReference.crefPrefixDer(cr) else cr;
3842 ✗ repl := BackendVarTransform.addReplacement(inRepl, dcr, expr, SOME(BackendVarTransform.skipPreOperator));
3843 ✗ repl := if BackendVariable.isStateVar(var) then BackendVarTransform.addDerConstRepl(cr, expr, repl) else repl;
3844 // BackendDump.debugStrCrefStrExpStr(("", cr, " := ", expr, "\n"));
3845 ✗ then
3846 solveInnerEquations1(explst1, explst2, rest, inVars, ishared, repl);
3847 end match;
3848 end solveInnerEquations1;
3849
3850 protected function createTornSystemInnerEqns
3851 input BackendDAE.InnerEquations innerEquations;
3852 input Boolean skipDiscInAlgorithm "if true skip discrete algorithm vars";
3853 input Boolean genDiscrete;
3854 input BackendDAE.EqSystem isyst;
3855 input BackendDAE.Shared ishared;
3856 input Integer iuniqueEqIndex;
3857 input list<SimCodeVar.SimVar> itempvars;
3858 input list<SimCode.SimEqSystem> isimequations;
3859 output list<SimCode.SimEqSystem> equations_;
3860 output Integer ouniqueEqIndex = iuniqueEqIndex;
3861 output list<SimCodeVar.SimVar> otempvars = itempvars;
3862 output Integer nVars = 0;
3863 output Boolean homotopySupport = false;
3864 protected
3865 BackendDAE.EquationArray eqns;
3866 Integer eqnindx;
3867 list<Integer> vars;
3868 BackendDAE.Equation eqn;
3869 BackendDAE.StrongComponent comp;
3870 list<SimCode.SimEqSystem> simequations;
3871 DoubleEnded.MutableList<SimCode.SimEqSystem> equations;
3872 BackendDAE.Constraints cons;
3873 algorithm
3874
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 1775 times.
1808 if listEmpty(innerEquations) then
3875 equations_ := isimequations;
3876 33 return;
3877 end if;
3878
3879 1775 BackendDAE.EQSYSTEM(orderedEqs = eqns) := isyst;
3880 1775 equations := DoubleEnded.fromList(isimequations);
3881
3882
2/2
✓ Branch 0 taken 26659 times.
✓ Branch 1 taken 1775 times.
28434 for eq in innerEquations loop
3883 // get Eqn
3884 26659 (eqnindx, vars, cons) := BackendDAEUtil.getEqnAndVarsFromInnerEquation(eq);
3885 26659 nVars := nVars + listLength(vars);
3886 26659 eqn := BackendEquation.get(eqns, eqnindx);
3887
2/2
✓ Branch 0 taken 24448 times.
✓ Branch 1 taken 2211 times.
26659 if not homotopySupport then
3888 24448 (_, homotopySupport) := BackendEquation.traverseExpsOfEquation(eqn, BackendDAEUtil.containsHomotopyCall, false);
3889 end if;
3890 // generate comp
3891 26659 comp := createTornSystemInnerEqns1(eqn, eqnindx, vars);
3892 26659 (simequations, _, ouniqueEqIndex, otempvars) := createEquationsWork(genDiscrete, false, genDiscrete, skipDiscInAlgorithm, isyst, ishared, comp, ouniqueEqIndex, otempvars, cons);
3893 26659 DoubleEnded.push_list_back(equations, simequations);
3894 end for;
3895
3896 1775 equations_ := DoubleEnded.toListAndClear(equations);
3897 end createTornSystemInnerEqns;
3898
3899 protected function createTornSystemInnerEqns1
3900 input BackendDAE.Equation eqn;
3901 input Integer eqnindx;
3902 input list<Integer> varindx;
3903 output BackendDAE.StrongComponent ocomp;
3904 algorithm
3905 ocomp := match(eqn, varindx)
3906 local
3907 Integer v;
3908 case (BackendDAE.EQUATION(), v::{})
3909 26267 then
3910 BackendDAE.SINGLEEQUATION(eqnindx, v);
3911
3912 case (BackendDAE.RESIDUAL_EQUATION(), v::{})
3913 ✗ then
3914 BackendDAE.SINGLEEQUATION(eqnindx, v);
3915
3916 case (BackendDAE.SOLVED_EQUATION(), v::{})
3917 ✗ then
3918 BackendDAE.SINGLEEQUATION(eqnindx, v);
3919
3920 case (BackendDAE.ARRAY_EQUATION(), _)
3921 20 then
3922 BackendDAE.SINGLEARRAY(eqnindx, varindx);
3923
3924 case (BackendDAE.IF_EQUATION(), _)
3925 ✗ then
3926 BackendDAE.SINGLEIFEQUATION(eqnindx, varindx);
3927
3928 case (BackendDAE.ALGORITHM(), _)
3929 30 then
3930 BackendDAE.SINGLEALGORITHM(eqnindx, varindx);
3931
3932 case (BackendDAE.COMPLEX_EQUATION(), _)
3933 335 then
3934 BackendDAE.SINGLECOMPLEXEQUATION(eqnindx, varindx);
3935
3936 case (BackendDAE.WHEN_EQUATION(), _)
3937 7 then
3938 BackendDAE.SINGLEWHENEQUATION(eqnindx, varindx);
3939
3940 else
3941 algorithm
3942 ✗ print("SimCodeUtil.createTornSystemInnerEqns1 failed for\n");
3943 ✗ BackendDump.printEquationList({eqn});
3944 ✗ print("Eqn: " + intString(eqnindx) + " Vars: " + stringDelimitList(List.map(varindx, intString), ", ") + "\n");
3945 ✗ then
3946 fail();
3947 end match;
3948 end createTornSystemInnerEqns1;
3949
3950 // =============================================================================
3951 // section to create state set equations
3952 //
3953 // =============================================================================
3954
3955 public function createStateSets "author: Frenkel TUD 2012
3956 This function handle states sets for code generation."
3957 input BackendDAE.BackendDAE inDAE;
3958 input list<SimCode.StateSet> iEquations;
3959 input Integer iuniqueEqIndex;
3960 input list<SimCodeVar.SimVar> itempvars;
3961 output BackendDAE.BackendDAE outDAE;
3962 output list<SimCode.StateSet> oEquations;
3963 output Integer ouniqueEqIndex;
3964 output list<SimCodeVar.SimVar> otempvars;
3965 output Integer numStateSets;
3966 algorithm
3967
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1060 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1060 if Flags.getConfigString(Flags.INDEX_REDUCTION_METHOD) == "dummyDerivatives" then
3968 outDAE := inDAE;
3969 oEquations := iEquations;
3970 ouniqueEqIndex := iuniqueEqIndex;
3971 otempvars := itempvars;
3972 numStateSets := 0;
3973 else
3974 1060 (outDAE, (oEquations, ouniqueEqIndex, otempvars, numStateSets)) :=
3975 BackendDAEUtil.mapEqSystemAndFold(inDAE, createStateSetsSystem, (iEquations, iuniqueEqIndex, itempvars, 0));
3976 end if;
3977 // BackendDump.printBackendDAE(outDAE);
3978 end createStateSets;
3979
3980 protected function createStateSetsSystem "author: Frenkel TUD 2012-12
3981 traverse an Equationsystem to handle states sets"
3982 input BackendDAE.EqSystem isyst;
3983 input BackendDAE.Shared inShared;
3984 input tuple<list<SimCode.StateSet>, Integer, list<SimCodeVar.SimVar>, Integer> inTpl;
3985 output BackendDAE.EqSystem osyst;
3986 output BackendDAE.Shared outShared = inShared;
3987 output tuple<list<SimCode.StateSet>, Integer, list<SimCodeVar.SimVar>, Integer> outTpl;
3988 algorithm
3989 (osyst, outTpl):= match (isyst, inTpl)
3990 local
3991 BackendDAE.Variables vars;
3992 BackendDAE.EquationArray eqns;
3993 BackendDAE.StateSets stateSets;
3994 BackendDAE.EqSystem syst;
3995 list<SimCode.StateSet> equations;
3996 Integer uniqueEqIndex, numStateSets;
3997 list<SimCodeVar.SimVar> tempvars;
3998 BackendDAE.StrongComponents comps;
3999 // no stateSet
4000 case (BackendDAE.EQSYSTEM(stateSets={}), _) then (isyst, inTpl);
4001 // sets
4002 case (syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, matching=BackendDAE.MATCHING(comps=comps), stateSets=stateSets),
4003 (equations, uniqueEqIndex, tempvars, numStateSets))
4004 algorithm
4005 13 (equations, uniqueEqIndex, tempvars, numStateSets) :=
4006 createStateSetsSets(stateSets, vars, eqns, comps, equations, uniqueEqIndex, tempvars, numStateSets);
4007 13 then
4008 (syst,(equations, uniqueEqIndex, tempvars, numStateSets));
4009 end match;
4010 end createStateSetsSystem;
4011
4012 protected function createStateSetsSets
4013 input BackendDAE.StateSets iStateSets;
4014 input BackendDAE.Variables iVars;
4015 input BackendDAE.EquationArray iEqns;
4016 input BackendDAE.StrongComponents comps;
4017 input list<SimCode.StateSet> iEquations;
4018 input Integer iuniqueEqIndex;
4019 input list<SimCodeVar.SimVar> itempvars;
4020 input Integer iNumStateSets;
4021 output list<SimCode.StateSet> oEquations;
4022 output Integer ouniqueEqIndex;
4023 output list<SimCodeVar.SimVar> otempvars;
4024 output Integer oNumStateSets;
4025 algorithm
4026 (oEquations, ouniqueEqIndex, otempvars, oNumStateSets) :=
4027 matchcontinue iStateSets
4028 local
4029 BackendDAE.StateSets sets;
4030 Integer rang, numStateSets, nCandidates;
4031 list<DAE.ComponentRef> crset;
4032 DAE.ComponentRef crA;
4033 list<BackendDAE.Var> aVars, statevars;
4034 list<DAE.ComponentRef> crstates;
4035 SimCode.JacobianMatrix jacobianMatrix;
4036 list<SimCode.StateSet> simequations;
4037 list<SimCodeVar.SimVar> tempvars, simCodeAVars;
4038 Integer uniqueEqIndex;
4039 BackendDAE.Jacobian jacobian;
4040 String errorMessage;
4041
4042 13 case {} then (iEquations, iuniqueEqIndex, itempvars, iNumStateSets);
4043
4044 case BackendDAE.STATESET(rang=rang, state=crset, crA=crA, varA=aVars, statescandidates=statevars, jacobian=jacobian)::sets
4045 algorithm
4046 // get state names
4047 21 crstates := List.map(statevars, BackendVariable.varCref);
4048
4049 // create vars for A
4050 21 simCodeAVars := List.map3(aVars, dlowvarToSimvar, NONE(), iVars, NONE());
4051
4052 // get first a element for varinfo
4053 21 crA := ComponentReference.subscriptCrefWithInt(crA, 1);
4054
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 16 times.
21 crA := if intGt(listLength(crset), 1) then ComponentReference.subscriptCrefWithInt(crA, 1) else crA;
4055
4056 // number of states
4057 21 nCandidates := listLength(statevars);
4058
4059 // create symbolic jacobian for simulation
4060
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
21 (SOME(jacobianMatrix), uniqueEqIndex, tempvars) := createSymbolicSimulationJacobian(jacobian, iuniqueEqIndex, listAppend(itempvars,simCodeAVars));
4061
4062 // next set
4063 42 (simequations, uniqueEqIndex, tempvars, numStateSets) := createStateSetsSets(sets, iVars, iEqns, comps, SimCode.SES_STATESET(iuniqueEqIndex, nCandidates, rang, crset, crstates, crA, jacobianMatrix)::iEquations, uniqueEqIndex, tempvars, iNumStateSets+1);
4064 then
4065 (simequations, uniqueEqIndex, tempvars, numStateSets);
4066 else
4067 algorithm
4068 errorMessage := "function createStateSetsSets failed.";
4069 ✗ Error.addInternalError(errorMessage, sourceInfo());
4070 ✗ then
4071 fail();
4072 end matchcontinue;
4073 end createStateSetsSets;
4074
4075 // =============================================================================
4076 // section to create SimCode symbolic jacobian from BackendDAE.Equations
4077 //
4078 // =============================================================================
4079
4080 public function createSymbolicSimulationJacobian "function createSymbolicSimulationJacobian
4081 author: wbraun
4082 function creates a symbolic jacobian column for
4083 non-linear systems and tearing systems."
4084 input BackendDAE.Jacobian inJacobian;
4085 input Integer iuniqueEqIndex;
4086 input list<SimCodeVar.SimVar> itempvars;
4087 input Boolean detectNonlinearPattern = false;
4088 output Option<SimCode.JacobianMatrix> res;
4089 output Integer ouniqueEqIndex;
4090 output list<SimCodeVar.SimVar> otempvars;
4091 algorithm
4092 (res, ouniqueEqIndex, otempvars) := matchcontinue(inJacobian, iuniqueEqIndex, itempvars)
4093 local
4094
4095 BackendDAE.Variables emptyVars, independentVars, residualVars, systvars;
4096 list<BackendDAE.Var> independentVarsLst, dependentVarsLst, residualVarsLst, allVars;
4097 list<DAE.ComponentRef> independentComRefs, dependentVarsComRefs;
4098
4099 DAE.ComponentRef x;
4100 BackendDAE.SparsePattern pattern;
4101 BackendDAE.SparseColoring sparseColoring;
4102 list<list<Integer>> coloring;
4103 BackendDAE.SparsePatternCrefs sparsepatternComRefs, sparsepatternComRefsT;
4104 BackendDAE.NonlinearPatternCrefs nonlinearpatternComRefs, nonlinearpatternComRefsT;
4105 SimCode.SparsityPattern sparseInts, sparseIntsT;
4106 SimCode.NonlinearPattern nonlinearPat, nonlinearPatT;
4107
4108 list<BackendDAE.EqSystem> systs;
4109 BackendDAE.Shared shared;
4110
4111 list<SimCodeVar.SimVar> tempvars;
4112 String name, dummyVar;
4113 Integer maxColor, uniqueEqIndex, nRows;
4114
4115 list<SimCode.SimEqSystem> allEquations = {}, constantEqns = {};
4116 list<SimCodeVar.SimVar> columnVars;
4117 list<SimCodeVar.SimVar> varsSeedIndex, seedVars, indexVars;
4118
4119 String errorMessage;
4120
4121
4122 HashTableCrefSimVar.HashTable crefToSimVarHTJacobian;
4123
4124 case (BackendDAE.EMPTY_JACOBIAN(), _, _) then (NONE(), iuniqueEqIndex, itempvars);
4125
4126 case (BackendDAE.FULL_JACOBIAN(_), _, _) then (NONE(), iuniqueEqIndex, itempvars);
4127
4128 case (BackendDAE.GENERIC_JACOBIAN(NONE(),pattern as (sparsepatternComRefs, sparsepatternComRefsT,
4129 (independentComRefs, dependentVarsComRefs), _),
4130 sparseColoring, (nonlinearpatternComRefs, nonlinearpatternComRefsT, _, _)), _, _)
4131 algorithm
4132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 565 times.
565 if Flags.isSet(Flags.JAC_DUMP2) then
4133 ✗ print("create sparse pattern for algebraic loop time: " + realString(clock()) + "\n");
4134 ✗ BackendDump.dumpSparsityPattern(pattern, "---+++ SparsePattern +++---");
4135 end if;
4136
4/4
✓ Branch 0 taken 2084 times.
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 2084 times.
✓ Branch 3 taken 565 times.
2649 seedVars := list(makeTmpRealSimCodeVar(cr, BackendDAE.SEED_VAR()) for cr in independentComRefs);
4137
4/4
✓ Branch 0 taken 2083 times.
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 2083 times.
✓ Branch 3 taken 565 times.
2648 indexVars := list(makeTmpRealSimCodeVar(cr, BackendDAE.VARIABLE()) for cr in dependentVarsComRefs);
4138
4139 565 seedVars := rewriteIndex(seedVars, 0);
4140 565 indexVars := rewriteIndex(indexVars, 0);
4141
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 565 times.
565 if Flags.isSet(Flags.JAC_DUMP2) then
4142 ✗ print("\n---+++ seedVars variables +++---\n");
4143 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, seedVars));
4144 ✗ print("\n---+++ indexVars variables +++---\n");
4145 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, indexVars));
4146 end if;
4147 //sort sparse pattern
4148 565 varsSeedIndex := listAppend(seedVars, indexVars);
4149 //sort sparse pattern
4150 565 sparseInts := sortSparsePattern(varsSeedIndex, sparsepatternComRefs, false);
4151 565 sparseIntsT := sortSparsePattern(varsSeedIndex, sparsepatternComRefsT, false);
4152
4153 565 nonlinearPat := sortSparsePattern(varsSeedIndex, nonlinearpatternComRefs, false);
4154 565 nonlinearPatT := sortSparsePattern(varsSeedIndex, nonlinearpatternComRefsT, false);
4155
4156 // set sparse pattern
4157 565 coloring := sortColoring(seedVars, sparseColoring);
4158 565 maxColor := listLength(sparseColoring);
4159
4160
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 565 times.
565 if Flags.isSet(Flags.JAC_DUMP2) then
4161 ✗ print("created sparse pattern for algebraic loop time: " + realString(clock()) + "\n");
4162 end if;
4163
4164 565 then (SOME(SimCode.JAC_MATRIX({}, {}, "", SimCode.Sparsity.EMPTY(), sparseInts, sparseIntsT, nonlinearPat, nonlinearPatT, coloring, {}, maxColor, -1, 0, {}, NONE(), false, false, -1, "")), iuniqueEqIndex, itempvars);
4165
4166 case (BackendDAE.GENERIC_JACOBIAN(SOME((BackendDAE.DAE(eqs=systs, shared=shared), name, independentVarsLst, residualVarsLst, dependentVarsLst, _)),
4167 (sparsepatternComRefs, sparsepatternComRefsT, _, _),
4168 sparseColoring, (nonlinearpatternComRefs, nonlinearpatternComRefsT, _, _)), uniqueEqIndex, tempvars)
4169 algorithm
4170 // create SimCodeVar.SimVars from jacobian vars
4171 1335 dummyVar := ("dummyVar" + name);
4172 1335 x := DAE.CREF_IDENT(dummyVar, DAE.T_REAL_DEFAULT, {});
4173 1335 emptyVars := BackendVariable.emptyVars();
4174
4175 1335 residualVars := BackendVariable.listVar1(residualVarsLst);
4176 1335 independentVars := BackendVariable.listVar1(independentVarsLst);
4177
4178 // get cse and other aux vars > columnVars
4179 1335 (allVars, _) := BackendVariable.traverseBackendDAEVars(BackendVariable.listVar1(BackendVariable.equationSystemsVarsLst(systs)), getFurtherVars , ({}, x));
4180 1335 systvars := BackendVariable.listVar1(allVars);
4181 1335 (columnVars, _) := BackendVariable.traverseBackendDAEVars(systvars, traversingdlowvarToSimvar, ({}, emptyVars));
4182 1335 columnVars := List.map1(columnVars, setSimVarKind, BackendDAE.JAC_TMP_VAR());
4183 1335 columnVars := List.map1(columnVars, setSimVarMatrixName, SOME(name));
4184 1335 columnVars := rewriteIndex(columnVars, 0);
4185
4186 1335 columnVars := createAllDiffedSimVars(dependentVarsLst, x, residualVars, 0, listLength(columnVars), name, columnVars);
4187 1335 columnVars := listReverse(columnVars);
4188
4189
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1335 times.
1335 if Flags.isSet(Flags.JAC_DUMP2) then
4190 ✗ print("\n---+++ all column variables +++---\n");
4191 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, columnVars));
4192 ✗ print("analytical Jacobians -> create all SimCode vars for Matrix " + name + " time: " + realString(clock()) + "\n");
4193 end if;
4194
4195 1335 (seedVars, _) := BackendVariable.traverseBackendDAEVars(independentVars, traversingdlowvarToSimvar, ({}, emptyVars));
4196 1335 (indexVars, _) := BackendVariable.traverseBackendDAEVars(residualVars, traversingdlowvarToSimvar, ({}, emptyVars));
4197 1335 seedVars := rewriteIndex(listReverse(seedVars), 0);
4198 1335 indexVars := rewriteIndex(listReverse(indexVars), 0);
4199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1335 times.
1335 if Flags.isSet(Flags.JAC_DUMP2) then
4200 ✗ print("\n---+++ seedVars variables +++---\n");
4201 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, seedVars));
4202 ✗ print("\n---+++ indexVars variables +++---\n");
4203 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, indexVars));
4204 end if;
4205 //sort sparse pattern
4206 1335 varsSeedIndex := listAppend(seedVars, indexVars);
4207
4208 1335 sparseInts := sortSparsePattern(varsSeedIndex, sparsepatternComRefs, false);
4209 1335 sparseIntsT := sortSparsePattern(varsSeedIndex, sparsepatternComRefsT, false);
4210
4211
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 1014 times.
1335 if detectNonlinearPattern then
4212 321 nonlinearPat := sortSparsePattern(varsSeedIndex, nonlinearpatternComRefs, false);
4213 321 nonlinearPatT := sortSparsePattern(varsSeedIndex, nonlinearpatternComRefsT, false);
4214 else
4215 nonlinearPat := {};
4216 nonlinearPatT := {};
4217 end if;
4218
4219 // set sparse pattern
4220 1335 coloring := sortColoring(varsSeedIndex, sparseColoring);
4221 1335 maxColor := listLength(sparseColoring);
4222 1335 nRows := listLength(residualVarsLst);
4223
4224 // create seed vars
4225 1335 seedVars := replaceSeedVarsName(seedVars, name);
4226 1335 seedVars := List.map1(seedVars, setSimVarKind, BackendDAE.SEED_VAR());
4227 1335 seedVars := List.map1(seedVars, setSimVarMatrixName, SOME(name));
4228
4229
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1335 times.
1335 if Flags.isSet(Flags.JAC_DUMP2) then
4230 ✗ print("analytical Jacobians -> transformed to SimCode for Matrix " + name + " time: " + realString(clock()) + "\n");
4231 end if;
4232
4233 1335 crefToSimVarHTJacobian := HashTableCrefSimVar.emptyHashTableSized(listLength(seedVars)+ listLength(columnVars));
4234 1335 crefToSimVarHTJacobian := List.fold(seedVars, HashTableCrefSimVar.addSimVarToHashTable, crefToSimVarHTJacobian);
4235 1335 crefToSimVarHTJacobian := List.fold(columnVars, HashTableCrefSimVar.addSimVarToHashTable, crefToSimVarHTJacobian);
4236
4237 1335 (allEquations, constantEqns, uniqueEqIndex, tempvars) := getSimEqSystemForJacobians(systs, shared, uniqueEqIndex, tempvars);
4238
4239 4005 then (SOME(SimCode.JAC_MATRIX({SimCode.JAC_COLUMN(allEquations, columnVars, nRows, constantEqns)}, seedVars, name, SimCode.Sparsity.EMPTY(), sparseInts, sparseIntsT, nonlinearPat, nonlinearPatT, coloring, {}, maxColor, -1, 0, {}, SOME(crefToSimVarHTJacobian), false, false, -1, "")), uniqueEqIndex, tempvars);
4240
4241 else
4242 algorithm
4243 ✗ if Flags.isSet(Flags.JAC_DUMP) then
4244 errorMessage := "function createSymbolicSimulationJacobian failed.";
4245 ✗ Error.addInternalError(errorMessage, sourceInfo());
4246 end if;
4247 then (NONE(), iuniqueEqIndex, itempvars);
4248
4249 end matchcontinue;
4250 end createSymbolicSimulationJacobian;
4251
4252 public function syncDAEandSimJac
4253 input SimCode.JacobianMatrix symJac;
4254 input output SimCode.JacobianMatrix daeJac;
4255 algorithm
4256 ✗ if symJac.matrixName == "A" then
4257 ✗ daeJac.columns := list(updateSimVarIndex(col, daeJac.crefsHT) for col in symJac.columns);
4258 daeJac.jacobianIndex := symJac.jacobianIndex;
4259 else
4260 daeJac := symJac;
4261 end if;
4262 end syncDAEandSimJac;
4263
4264 public function updateSimVarIndex
4265 input output SimCode.JacobianColumn column;
4266 input Option<HashTableCrefSimVar.HashTable> crefsHT;
4267 algorithm
4268 column := match crefsHT
4269 local
4270 HashTableCrefSimVar.HashTable table;
4271 case SOME(table) algorithm
4272 ✗ column.columnVars := list(BaseHashTable.getOrDefault(var.name, table, var) for var in column.columnVars);
4273 then column;
4274 else column;
4275 end match;
4276 end updateSimVarIndex;
4277
4278 protected function getFurtherVars
4279 input BackendDAE.Var v;
4280 input tuple<list<BackendDAE.Var>, DAE.ComponentRef> inTpl;
4281 output BackendDAE.Var outVar = v;
4282 output tuple<list<BackendDAE.Var>, DAE.ComponentRef> outTpl = inTpl;
4283 protected
4284 DAE.ComponentRef diffCref;
4285 list<BackendDAE.Var> vars;
4286 Boolean b;
4287 algorithm
4288 16215 (vars, diffCref) := inTpl;
4289 16215 b := ComponentReferenceBasics.crefLastIdentEqual(BackendVariable.varCref(v), diffCref);
4290
2/2
✓ Branch 0 taken 15359 times.
✓ Branch 1 taken 856 times.
16215 if not b then
4291 vars := v::vars;
4292 856 outTpl := (vars, diffCref);
4293 end if;
4294 end getFurtherVars;
4295
4296 protected function getSimEqSystemForJacobians
4297 "Creates simcode equations for jacobians.
4298 If inSysts has more than one system the rest are seperated constant equations."
4299 input BackendDAE.EqSystems inSysts;
4300 input BackendDAE.Shared inShared;
4301 input Integer iuniqueEqIndex;
4302 input list<SimCodeVar.SimVar> itempvars;
4303 output list<SimCode.SimEqSystem> allEquations = {};
4304 output list<SimCode.SimEqSystem> constantEqns = {};
4305 output Integer uniqueEqIndex = iuniqueEqIndex;
4306 output list<SimCodeVar.SimVar> tempvars = itempvars;
4307 protected
4308 BackendDAE.StrongComponents comps;
4309 BackendDAE.EqSystems rest;
4310 BackendDAE.EqSystem syst;
4311 list<list<SimCode.SimEqSystem>> accEqns = {};
4312 algorithm
4313 // First system contains the main direction derivative equations,
4314 // while the other systems contain equations which are considered to be constant.
4315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1570 times.
1570 syst::rest := inSysts;
4316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1570 times.
1570 BackendDAE.EQSYSTEM(matching=BackendDAE.MATCHING(comps=comps)) := syst;
4317 1570 (allEquations, _, uniqueEqIndex, tempvars) := createEquations(false, false, true, false, syst, inShared, comps, uniqueEqIndex, tempvars);
4318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1570 times.
1570 for eq in rest loop
4319 ✗ BackendDAE.EQSYSTEM(matching=BackendDAE.MATCHING(comps=comps)) := eq;
4320 // Generate discrete equations, they might be introduced by wrapfunctioncalls
4321 ✗ (constantEqns, _, uniqueEqIndex, tempvars) := createEquations(false, false, true, false, eq, inShared, comps, uniqueEqIndex, tempvars);
4322 accEqns := constantEqns::accEqns;
4323 end for;
4324 1570 constantEqns := List.flattenReverse(accEqns);
4325 end getSimEqSystemForJacobians;
4326
4327 public function createJacobianLinearCode
4328 input BackendDAE.SymbolicJacobians inSymjacs;
4329 input SimCode.ModelInfo inModelInfo;
4330 input Integer iuniqueEqIndex;
4331 input BackendDAE.Shared shared;
4332 output list<SimCode.JacobianMatrix> res = {};
4333 output Integer ouniqueEqIndex;
4334 algorithm
4335 (res,ouniqueEqIndex) := match iuniqueEqIndex
4336 local
4337 SimCode.HashTableCrefToSimVar crefSimVarHT;
4338 list<String> matrixnames;
4339 Option<BackendDAE.Jacobian> jacH;
4340 case _
4341 algorithm
4342 // b := FlagsUtil.disableDebug(Flags.EXEC_STAT);
4343 1060 crefSimVarHT := SimCodeCodegenUtil.createCrefToSimVarHT(inModelInfo);
4344 // The jacobian code requires single systems;
4345 // I did not rewrite it to take advantage of any parallelism in the code
4346
4347 // This is used to set the matrixnames for Linearization and DataReconciliation procedure
4348 // For dataReconciliation F is set in earlier order which cause index problem for linearization matrix and hence identify if
4349 // dataReconciliation is involved and pass the matrix names
4350 // for stateEstimation problem two jacobinas are needed F and H
4351
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 1035 times.
1060 if isSome(shared.dataReconciliationData) then
4352 25 BackendDAE.DATA_RECON(_, _, _, _, jacH) := Util.getOption(shared.dataReconciliationData);
4353
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 1 time.
25 if isSome(jacH) then // check for matrix H is present which means state estimation algorithm is choosed and jacobian F and H are generated earlier
4354 matrixnames := {"A", "B", "C", "D", "ADJ"};
4355 else
4356 matrixnames := {"A", "B", "C", "D", "H", "ADJ"};
4357 end if;
4358 else
4359 matrixnames := {"A", "B", "C", "D", "F", "H", "ADJ"};
4360 end if;
4361 1060 (res, ouniqueEqIndex) := createSymbolicJacobianssSimCode(inSymjacs, crefSimVarHT, iuniqueEqIndex, matrixnames, {});
4362 // _ := FlagsUtil.set(Flags.EXEC_STAT, b);
4363 then (res,ouniqueEqIndex);
4364 end match;
4365 end createJacobianLinearCode;
4366
4367 protected function checkForEmptyBDAE
4368 input Option<BackendDAE.SymbolicJacobian> inBDAE;
4369 output Boolean result;
4370 algorithm
4371 result := match inBDAE
4372 case NONE()
4373 then true;
4374 case SOME((_,_,{},{},{},_))
4375 then true;
4376 else
4377 false;
4378 end match;
4379 end checkForEmptyBDAE;
4380
4381 public function createSymbolicJacobianssSimCode
4382 "function creates the linear model matrices column-wise
4383 author: wbraun"
4384 input BackendDAE.SymbolicJacobians inSymJacobians;
4385 input SimCode.HashTableCrefToSimVar inSimVarHT;
4386 input Integer iuniqueEqIndex;
4387 input list<String> inNames;
4388 input list<SimCode.JacobianMatrix> inJacobianMatrices;
4389 output list<SimCode.JacobianMatrix> outJacobianMatrices;
4390 output Integer ouniqueEqIndex;
4391 algorithm
4392 (outJacobianMatrices, ouniqueEqIndex) :=
4393 matchcontinue (inSymJacobians, iuniqueEqIndex, inNames)
4394 local
4395 BackendDAE.EqSystems systs;
4396 BackendDAE.Shared shared;
4397 BackendDAE.Variables vars, empty, systvars, emptyVars;
4398
4399 DAE.ComponentRef x;
4400 list<BackendDAE.Var> diffedVars, alldiffedVars, allVars;
4401 list<DAE.ComponentRef> diffCompRefs, diffedCompRefs, allCrefs;
4402
4403 Integer uniqueEqIndex, nRows;
4404
4405 list<String> restnames;
4406 String name, dummyVar;
4407
4408 list<SimCode.SimEqSystem> allEquations = {}, constantEqns = {};
4409 list<SimCodeVar.SimVar> columnVars, otherColumnVars;
4410 list<SimCodeVar.SimVar> seedVars, indexVars, seedIndexVars;
4411
4412 BackendDAE.SparsePatternCrefs sparsepattern, sparsepatternT;
4413 BackendDAE.NonlinearPatternCrefs nonlinearpattern, nonlinearpatternT;
4414 list<list<DAE.ComponentRef>> colsColors;
4415 Integer maxColor;
4416
4417 BackendDAE.SymbolicJacobians rest;
4418 list<SimCode.JacobianMatrix> linearModelMatrices;
4419 SimCode.SparsityPattern sparseInts, sparseIntsT;
4420 SimCode.NonlinearPattern nonlinearPat, nonlinearPatT;
4421 list<list<Integer>> coloring;
4422 Option<BackendDAE.SymbolicJacobian> optionBDAE;
4423
4424 SimCode.JacobianMatrix tmpJac;
4425 HashTableCrefSimVar.HashTable crefToSimVarHTJacobian;
4426
4427 1103 case (_, _, {}) then (inJacobianMatrices, iuniqueEqIndex);
4428
4429 // if nothing is generated
4430 case ({}, _, name::restnames)
4431 algorithm
4432 tmpJac := SimCode.emptyJacobian;
4433 3217 tmpJac.matrixName := name;
4434 linearModelMatrices := tmpJac::inJacobianMatrices;
4435 3217 (linearModelMatrices, uniqueEqIndex) := createSymbolicJacobianssSimCode({}, inSimVarHT, iuniqueEqIndex, restnames, linearModelMatrices);
4436 then
4437 (linearModelMatrices, uniqueEqIndex);
4438
4439 // if nothing is generated
4440 case (((NONE(), ({}, {}, ({}, {}), _), {}, _))::rest, _, name::restnames)
4441 algorithm
4442 tmpJac := SimCode.emptyJacobian;
4443 3501 tmpJac.matrixName := name;
4444 linearModelMatrices := tmpJac::inJacobianMatrices;
4445 3501 (linearModelMatrices, uniqueEqIndex) := createSymbolicJacobianssSimCode(rest, inSimVarHT, iuniqueEqIndex, restnames, linearModelMatrices);
4446 then
4447 (linearModelMatrices, uniqueEqIndex);
4448
4449 // if only sparsity pattern is generated
4450 case (((optionBDAE, (sparsepattern, sparsepatternT, (diffCompRefs, diffedCompRefs), _), colsColors, _))::rest, _, name::restnames)
4451 guard checkForEmptyBDAE(optionBDAE)
4452 algorithm
4453
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 538 times.
538 if Flags.isSet(Flags.JAC_DUMP2) then
4454 ✗ print("Start sparse pattern without analytical Jacobians\n");
4455 end if;
4456
4457 538 seedVars := getSimVars2Crefs(diffCompRefs, inSimVarHT);
4458 538 seedVars := List.sort(seedVars, compareVarIndexGt);
4459
4460
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 538 times.
538 if Flags.isSet(Flags.JAC_DUMP2) then
4461 ✗ print("diffCrefs: " + ComponentReferenceBasics.printComponentRefListStr(diffCompRefs) + "\n");
4462 ✗ print("\n---+++ seedVars +++---\n");
4463 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, seedVars));
4464 end if;
4465
4466 538 indexVars := getSimVars2Crefs(diffedCompRefs, inSimVarHT);
4467 538 indexVars := List.sort(indexVars, compareVarIndexGt);
4468
4469
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 538 times.
538 if Flags.isSet(Flags.JAC_DUMP2) then
4470 ✗ print("diffedCrefs: " + ComponentReferenceBasics.printComponentRefListStr(diffedCompRefs) + "\n");
4471 ✗ print("\n---+++ indexVars +++---\n");
4472 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, indexVars));
4473 ✗ print("\n---+++ sparse pattern vars +++---\n");
4474 ✗ dumpSparsePattern(sparsepattern);
4475 ✗ print("\n---+++ sparse pattern transpose +++---\n");
4476 ✗ dumpSparsePattern(sparsepatternT);
4477 end if;
4478 538 seedVars := rewriteIndex(seedVars, 0);
4479 538 indexVars := rewriteIndex(indexVars, 0);
4480 538 seedIndexVars := listAppend(seedVars, indexVars);
4481
4482 538 sparseInts := sortSparsePattern(seedIndexVars, sparsepattern, false);
4483 538 sparseIntsT := sortSparsePattern(seedIndexVars, sparsepatternT, false);
4484
4485 nonlinearPat := {};
4486 nonlinearPatT := {};
4487
4488 538 maxColor := listLength(colsColors);
4489 538 nRows := listLength(diffedCompRefs);
4490 538 coloring := sortColoring(seedVars, colsColors);
4491
4492
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 538 times.
538 if Flags.isSet(Flags.JAC_DUMP2) then
4493 ✗ print("analytical Jacobians -> transformed to SimCode for Matrix " + name + " time: " + realString(clock()) + "\n");
4494 ✗ print("\n---+++ sparse pattern vars +++---\n");
4495 ✗ dumpSparsePatternInt(sparseInts);
4496 ✗ print("\n---+++ sparse pattern transpose +++---\n");
4497 ✗ dumpSparsePatternInt(sparseIntsT);
4498 end if;
4499
4500 // create seed vars
4501 538 seedVars := replaceSeedVarsName(seedVars, name);
4502 538 seedVars := List.map1(seedVars, setSimVarKind, BackendDAE.SEED_VAR());
4503 538 seedVars := List.map1(seedVars, setSimVarMatrixName, SOME(name));
4504
4505 1076 tmpJac := SimCode.JAC_MATRIX({SimCode.JAC_COLUMN({},{},nRows, {})}, seedVars, name, SimCode.Sparsity.EMPTY(), sparseInts, sparseIntsT, nonlinearPat, nonlinearPatT, coloring, {}, maxColor, -1, 0, {}, NONE(), false, false, -1, "");
4506 linearModelMatrices := tmpJac::inJacobianMatrices;
4507 538 (linearModelMatrices, uniqueEqIndex) := createSymbolicJacobianssSimCode(rest, inSimVarHT, iuniqueEqIndex, restnames, linearModelMatrices);
4508
4509 then
4510 (linearModelMatrices, uniqueEqIndex);
4511
4512 case (((SOME((BackendDAE.DAE(eqs=systs, shared=shared), name, _, diffedVars, alldiffedVars, _)),
4513 (sparsepattern, sparsepatternT, (diffCompRefs, diffedCompRefs), _), colsColors,
4514 (nonlinearpattern, nonlinearpatternT, _, _)))::rest, uniqueEqIndex, _::restnames)
4515 algorithm
4516 // create SimCodeVar.SimVars from jacobian vars
4517 235 dummyVar := ("dummyVar" + name);
4518 235 x := DAE.CREF_IDENT(dummyVar, DAE.T_REAL_DEFAULT, {});
4519
4520 // get cse and other aux vars > columnVars
4521 235 emptyVars := BackendVariable.emptyVars();
4522 235 (allVars, _) := BackendVariable.traverseBackendDAEVars(BackendVariable.listVar1(BackendVariable.equationSystemsVarsLst(systs)), getFurtherVars , ({}, x));
4523 235 systvars := BackendVariable.listVar1(allVars);
4524 235 (otherColumnVars, _) := BackendVariable.traverseBackendDAEVars(systvars, traversingdlowvarToSimvar, ({}, emptyVars));
4525 235 otherColumnVars := List.map1(otherColumnVars, setSimVarKind, BackendDAE.JAC_TMP_VAR());
4526 235 otherColumnVars := List.map1(otherColumnVars, setSimVarMatrixName, SOME(name));
4527 235 otherColumnVars := rewriteIndex(otherColumnVars, 0);
4528
4529 //sort variable for index
4530 235 empty := BackendVariable.listVar1(alldiffedVars);
4531 235 allCrefs := List.map(alldiffedVars, BackendVariable.varCref);
4532 235 columnVars := getSimVars2Crefs(allCrefs, inSimVarHT);
4533 235 columnVars := List.sort(columnVars, compareVarIndexGt);
4534
4/4
✓ Branch 0 taken 2380 times.
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 2380 times.
✓ Branch 3 taken 235 times.
2615 alldiffedVars := list(sortBackVarWithSimVarsOrder(v, empty) for v in columnVars);
4535 235 vars := BackendVariable.listVar1(diffedVars);
4536
4537 235 columnVars := createAllDiffedSimVars(alldiffedVars, x, vars, 0, listLength(otherColumnVars), name, otherColumnVars);
4538
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
235 if Flags.isSet(Flags.JAC_DUMP2) then
4539 ✗ print("\n---+++ second columnVars +++---\n");
4540 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, columnVars));
4541 ✗ print("analytical Jacobians -> create column variables for matrix " + name + " time: " + realString(clock()) + "\n");
4542 end if;
4543
4544
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
235 if Flags.isSet(Flags.JAC_DUMP2) then
4545 ✗ print("analytical Jacobians -> create all SimCode vars for Matrix " + name + " time: " + realString(clock()) + "\n");
4546 ✗ print("\n---+++ columnVars +++---\n");
4547 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, columnVars));
4548 end if;
4549
4550 235 seedVars := getSimVars2Crefs(diffCompRefs, inSimVarHT);
4551 235 seedVars := List.sort(seedVars, compareVarIndexGt);
4552
4553
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
235 if Flags.isSet(Flags.JAC_DUMP2) then
4554 ✗ print("diffCrefs: " + ComponentReferenceBasics.printComponentRefListStr(diffCompRefs) + "\n");
4555 ✗ print("\n---+++ seedVars +++---\n");
4556 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, seedVars));
4557 end if;
4558
4559 235 indexVars := getSimVars2Crefs(diffedCompRefs, inSimVarHT);
4560 235 indexVars := List.sort(indexVars, compareVarIndexGt);
4561
4562
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
235 if Flags.isSet(Flags.JAC_DUMP2) then
4563 ✗ print("diffedCrefs: " + ComponentReferenceBasics.printComponentRefListStr(diffedCompRefs) + "\n");
4564 ✗ print("\n---+++ indexVars +++---\n");
4565 ✗ print(Tpl.tplString(SimCodeDump.dumpVarsShort, indexVars));
4566
4567 ✗ print("\n---+++ sparse pattern vars +++---\n");
4568 ✗ dumpSparsePattern(sparsepattern);
4569 ✗ print("\n---+++ sparse pattern transpose +++---\n");
4570 ✗ dumpSparsePattern(sparsepatternT);
4571 end if;
4572 235 seedVars := rewriteIndex(seedVars, 0);
4573 235 indexVars := rewriteIndex(indexVars, 0);
4574 235 seedIndexVars := listAppend(seedVars, indexVars);
4575 235 sparseIntsT := sortSparsePattern(seedIndexVars, sparsepatternT, false);
4576 235 sparseInts := sortSparsePattern(seedIndexVars, sparsepattern, false);
4577
4578 235 nonlinearPat := sortSparsePattern(seedIndexVars, nonlinearpattern, false);
4579 235 nonlinearPatT := sortSparsePattern(seedIndexVars, nonlinearpatternT, false);
4580
4581 235 maxColor := listLength(colsColors);
4582 235 nRows := listLength(diffedVars);
4583 235 coloring := sortColoring(seedVars, colsColors);
4584
4585
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
235 if Flags.isSet(Flags.JAC_DUMP2) then
4586 ✗ print("analytical Jacobians -> transformed to SimCode for Matrix " + name + " time: " + realString(clock()) + "\n");
4587 ✗ print("\n---+++ sparse pattern vars +++---\n");
4588 ✗ dumpSparsePatternInt(sparseInts);
4589 ✗ print("\n---+++ sparse pattern transpose +++---\n");
4590 ✗ dumpSparsePatternInt(sparseIntsT);
4591 end if;
4592
4593 // create seed vars
4594 235 seedVars := replaceSeedVarsName(seedVars, name);
4595 235 seedVars := List.map1(seedVars, setSimVarKind, BackendDAE.SEED_VAR());
4596 235 seedVars := List.map1(seedVars, setSimVarMatrixName, SOME(name));
4597
4598 // create hash table for this jacobians
4599 235 crefToSimVarHTJacobian := HashTableCrefSimVar.emptyHashTableSized(listLength(seedVars)+ listLength(columnVars));
4600 235 crefToSimVarHTJacobian := List.fold(seedVars, HashTableCrefSimVar.addSimVarToHashTable, crefToSimVarHTJacobian);
4601 235 crefToSimVarHTJacobian := List.fold(columnVars, HashTableCrefSimVar.addSimVarToHashTable, crefToSimVarHTJacobian);
4602
4603
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
235 if Flags.isSet(Flags.JAC_DUMP2) then
4604 ✗ print("analytical Jacobians -> creating SimCode equations for Matrix " + name + " time: " + realString(clock()) + "\n");
4605 end if;
4606 235 (allEquations, constantEqns, uniqueEqIndex, _) := getSimEqSystemForJacobians(systs, shared, uniqueEqIndex, {});
4607
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
235 if Flags.isSet(Flags.JAC_DUMP2) then
4608 ✗ print("analytical Jacobians -> created all SimCode equations for Matrix " + name + " time: " + realString(clock()) + "\n");
4609 end if;
4610
4611 470 tmpJac := SimCode.JAC_MATRIX({SimCode.JAC_COLUMN(allEquations, columnVars, nRows, constantEqns)}, seedVars, name, SimCode.Sparsity.EMPTY(), sparseInts, sparseIntsT, nonlinearPat, nonlinearPatT, coloring, {}, maxColor, -1, 0, {}, SOME(crefToSimVarHTJacobian), false, false, -1, "");
4612 linearModelMatrices := tmpJac::inJacobianMatrices;
4613 235 (linearModelMatrices, uniqueEqIndex) := createSymbolicJacobianssSimCode(rest, inSimVarHT, uniqueEqIndex, restnames, linearModelMatrices);
4614 then
4615 (linearModelMatrices, uniqueEqIndex);
4616 else
4617 algorithm
4618 ✗ Error.addInternalError("Generation of symbolic matrix SimCode (SimCodeUtil.createSymbolicJacobianssSimCode) failed", sourceInfo());
4619 ✗ then
4620 fail();
4621 end matchcontinue;
4622 end createSymbolicJacobianssSimCode;
4623
4624 public function getSimVars2Crefs
4625 input list<DAE.ComponentRef> inCrefs;
4626 input SimCode.HashTableCrefToSimVar inSimVarHT;
4627 output list<SimCodeVar.SimVar> outSimVars = {};
4628 algorithm
4629
2/2
✓ Branch 0 taken 28855 times.
✓ Branch 1 taken 2316 times.
31171 for cref in inCrefs loop
4630 try
4631 28855 outSimVars := BaseHashTable.get(cref, inSimVarHT)::outSimVars;
4632 else
4633 end try;
4634 end for;
4635 end getSimVars2Crefs;
4636
4637 protected function replaceSeedVarsName
4638 input list<SimCodeVar.SimVar> inVars;
4639 input String inMatrixName;
4640 output list<SimCodeVar.SimVar> outSimVars = list(replaceSimVarName(Differentiate.createSeedCrefName(v.name, inMatrixName), v) for v in inVars);
4641 end replaceSeedVarsName;
4642
4643 protected function sortBackVarWithSimVarsOrder
4644 input SimCodeVar.SimVar var;
4645 input BackendDAE.Variables vars;
4646 output BackendDAE.Var outVar = BackendVariable.getVarSingle(var.name, vars);
4647 end sortBackVarWithSimVarsOrder;
4648
4649 protected function createJacSimVarsColumn "author: wbraun"
4650 input list<BackendDAE.Var> inVars;
4651 input DAE.ComponentRef inCref;
4652 input BackendDAE.Variables inAllVars;
4653 input Integer inResIndex;
4654 input Integer inTmpIndex;
4655 input String inMatrixName;
4656 input output list<SimCodeVar.SimVar> tmpVars;
4657 input output list<SimCodeVar.SimVar> resVars;
4658 algorithm
4659 (tmpVars, resVars) := match inVars
4660 local
4661 BackendDAE.Var v, v1;
4662 SimCodeVar.SimVar simVar;
4663 DAE.ComponentRef currVar, derivedCref;
4664 list<BackendDAE.Var> restVar;
4665 Integer resIndex=inResIndex, tmpIndex=inTmpIndex;
4666 BackendDAE.VarKind varkind;
4667
4668 1570 case {} then (listReverse(tmpVars), listReverse(resVars));
4669
4670 case (v as BackendDAE.VAR(varName=currVar, varKind=varkind))::restVar algorithm
4671 try
4672 18861 BackendVariable.getVarSingle(currVar, inAllVars);
4673 currVar := match varkind
4674 360 case BackendDAE.STATE() then ComponentReference.crefPrefixDer(currVar);
4675 5183 else currVar;
4676 end match;
4677 5543 derivedCref := ComponentReference.createDifferentiatedCrefName(currVar, inCref, inMatrixName);
4678 5543 v1 := BackendVariable.copyVarNewName(derivedCref, v);
4679 5543 v1 := BackendVariable.setVarKind(v1, BackendDAE.JAC_VAR());
4680 5543 simVar := dlowvarToSimvar(v1, NONE(), inAllVars);
4681 5543 simVar.index := inResIndex;
4682 5543 resIndex := inResIndex + 1;
4683 5543 simVar.matrixName := SOME(inMatrixName);
4684 resVars := simVar::resVars;
4685 else
4686 currVar := match varkind
4687 144 case BackendDAE.STATE() then ComponentReference.crefPrefixDer(currVar);
4688 13174 else currVar;
4689 end match;
4690 13318 derivedCref := ComponentReference.createDifferentiatedCrefName(currVar, inCref, inMatrixName);
4691 13318 v1 := BackendVariable.copyVarNewName(derivedCref, v);
4692 13318 v1 := BackendVariable.setVarKind(v1, BackendDAE.JAC_TMP_VAR());
4693 13318 simVar := dlowvarToSimvar(v1, NONE(), inAllVars);
4694 13318 simVar.index := inTmpIndex;
4695 13318 simVar.matrixName := SOME(inMatrixName);
4696 13318 tmpIndex := inTmpIndex + 1;
4697 tmpVars := simVar::tmpVars;
4698 end try;
4699 18861 then
4700 createJacSimVarsColumn(restVar, inCref, inAllVars, resIndex, tmpIndex, inMatrixName, tmpVars, resVars);
4701
4702 else
4703 algorithm
4704 ✗ Error.addInternalError("function createAllDiffedSimVars failed", sourceInfo());
4705 ✗ then fail();
4706 end match;
4707 end createJacSimVarsColumn;
4708
4709 protected function createAllDiffedSimVars "author: wbraun"
4710 input list<BackendDAE.Var> inVars;
4711 input DAE.ComponentRef inCref;
4712 input BackendDAE.Variables inAllVars;
4713 input Integer inResIndex;
4714 input Integer inTmpIndex;
4715 input String inMatrixName;
4716 input list<SimCodeVar.SimVar> iVars;
4717 output list<SimCodeVar.SimVar> outVars;
4718 protected
4719 list<SimCodeVar.SimVar> lst1;
4720 algorithm
4721 1570 (outVars, lst1) := createJacSimVarsColumn(inVars, inCref, inAllVars, inResIndex, inTmpIndex, inMatrixName, iVars, {});
4722 1570 outVars := listAppend(lst1, outVars);
4723 end createAllDiffedSimVars;
4724
4725 public function collectAllJacobianEquations
4726 input list<SimCode.JacobianMatrix> inJacobianMatrix;
4727 output list<SimCode.SimEqSystem> outEqn = {};
4728 protected
4729 list<SimCode.JacobianColumn> column;
4730 list<SimCode.SimEqSystem> tmp,constantEqns;
4731 algorithm
4732
2/2
✓ Branch 0 taken 7529 times.
✓ Branch 1 taken 1069 times.
8598 for m in inJacobianMatrix loop
4733 7529 SimCode.JAC_MATRIX(columns=column) := m;
4734
2/2
✓ Branch 0 taken 811 times.
✓ Branch 1 taken 7529 times.
8340 for c in column loop
4735 811 SimCode.JAC_COLUMN(columnEqns=tmp,constantEqns=constantEqns) := c;
4736 811 outEqn := listAppend(tmp, outEqn);
4737 811 outEqn := listAppend(constantEqns, outEqn);
4738 end for;
4739 end for;
4740 end collectAllJacobianEquations;
4741
4742 public function collectAllJacobianVars
4743 input list<SimCode.JacobianMatrix> inJacobianMatrix;
4744 output list<SimCodeVar.SimVar> outVars = {};
4745 protected
4746 list<SimCode.JacobianColumn> column;
4747 list<SimCodeVar.SimVar> tmp;
4748 algorithm
4749
2/2
✓ Branch 0 taken 8817 times.
✓ Branch 1 taken 1069 times.
9886 for m in inJacobianMatrix loop
4750 8817 SimCode.JAC_MATRIX(columns=column) := m;
4751
2/2
✓ Branch 0 taken 2099 times.
✓ Branch 1 taken 8817 times.
10916 for c in column loop
4752 2099 SimCode.JAC_COLUMN(columnVars=tmp) := c;
4753 2099 outVars := listAppend(tmp, outVars);
4754 end for;
4755 end for;
4756 end collectAllJacobianVars;
4757
4758 public function collectAllSeedVars
4759 "Collect seed vars of Jacobian matrices. author: rfranke"
4760 input list<SimCode.JacobianMatrix> inJacobianMatrices;
4761 output list<SimCodeVar.SimVar> outVars = {};
4762 protected
4763 list<SimCodeVar.SimVar> seedVars;
4764 algorithm
4765
2/2
✓ Branch 0 taken 8817 times.
✓ Branch 1 taken 1069 times.
9886 for m in inJacobianMatrices loop
4766 8817 SimCode.JAC_MATRIX(seedVars=seedVars) := m;
4767 8817 outVars := listAppend(seedVars, outVars);
4768 end for;
4769 1069 outVars := List.map1(outVars, setSimVarKind, BackendDAE.SEED_VAR());
4770 end collectAllSeedVars;
4771
4772 protected function setSimVarKind
4773 input output SimCodeVar.SimVar simVar;
4774 input BackendDAE.VarKind varKind;
4775 algorithm
4776 24058 simVar.varKind := varKind;
4777 end setSimVarKind;
4778
4779 protected function setSimVarMatrixName
4780 input output SimCodeVar.SimVar simVar;
4781 input Option<String> optName;
4782 algorithm
4783 14357 simVar.matrixName := optName;
4784 end setSimVarMatrixName;
4785
4786 protected function makeTmpRealSimCodeVar
4787 input DAE.ComponentRef inName;
4788 input BackendDAE.VarKind inVarKind;
4789 output SimCodeVar.SimVar outSimVar;
4790 algorithm
4791
3/4
✓ Branch 2 taken 4155 times.
✓ Branch 3 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4155 times.
4167 if (FMI.isFMIVersion20() or FMI.isFMIVersion30()) then
4792 12 outSimVar := SimCodeVar.SIMVAR(inName, inVarKind, "", "", "", -1 /* use -1 to get an error in simulation if something failed */,
4793 NONE(), NONE(), NONE(), NONE(), false, DAE.T_REAL_DEFAULT,
4794 false, NONE(), SimCodeVar.NOALIAS(), DAE.emptyElementSource,
4795 SOME(SimCodeVar.LOCAL()), NONE(), NONE(), {}, false, false, NONE(), false, NONE(), false, NONE(), NONE(), NONE(), SOME(inName), false, false);
4796 else
4797 4155 outSimVar := SimCodeVar.SIMVAR(inName, inVarKind, "", "", "", -1 /* use -1 to get an error in simulation if something failed */,
4798 NONE(), NONE(), NONE(), NONE(), false, DAE.T_REAL_DEFAULT,
4799 false, NONE(), SimCodeVar.NOALIAS(), DAE.emptyElementSource,
4800 SOME(SimCodeVar.NONECAUS()), NONE(), NONE(), {}, false, false, NONE(), false, NONE(), false, NONE(), NONE(), NONE(), SOME(inName), false, false);
4801 end if;
4802 end makeTmpRealSimCodeVar;
4803
4804 protected function sortInitialUnknowsSimVars
4805 "Sorts the crefs, according to FMI-INDEX"
4806 input list<SimCodeVar.SimVar> inSimVars;
4807 output list<tuple<Integer, DAE.ComponentRef>> sortedCrefs = {};
4808 protected
4809 DAE.ComponentRef cref;
4810 list<tuple<Integer, DAE.ComponentRef>> unsortedCrefs={};
4811 Integer index;
4812 algorithm
4813 // get the FMIINDEX of the vars
4814
2/2
✓ Branch 0 taken 2534 times.
✓ Branch 1 taken 138 times.
2672 for var in inSimVars loop
4815
2/2
✓ Branch 1 taken 2098 times.
✓ Branch 2 taken 436 times.
2534 if isRealInput(var) then
4816 2098 unsortedCrefs := (SimCodeCodegenUtil.getVariableFMIIndex(var), var.name) :: unsortedCrefs;
4817 end if;
4818 end for;
4819
4820 // sort the crefs and set the index which will be used by fmi2GetDirectionalDerivative() to get the partial derivatives
4821 index := 0;
4822
2/2
✓ Branch 1 taken 2098 times.
✓ Branch 2 taken 138 times.
2236 for i in List.sort(unsortedCrefs, Util.compareTupleIntGt) loop
4823 2098 (_, cref) := i;
4824 2098 sortedCrefs := (index, cref) :: sortedCrefs;
4825 2098 index := index + 1;
4826 end for;
4827 138 sortedCrefs := listReverse(sortedCrefs);
4828 //dumpSortedInitialUnknownCrefs(sortedCrefs);
4829 end sortInitialUnknowsSimVars;
4830
4831 protected function dumpSortedInitialUnknownCrefs
4832 input list<tuple<Integer, DAE.ComponentRef>> sortedCrefs;
4833 protected
4834 DAE.ComponentRef cref;
4835 Integer index;
4836 algorithm
4837 ✗ for i in sortedCrefs loop
4838 ✗ (index, cref) := i;
4839 ✗ print("\nindex :" + intString(index) + "=>" + ComponentReferenceBasics.printComponentRefStr(cref));
4840 end for;
4841 ✗ print("\n*********");
4842 end dumpSortedInitialUnknownCrefs;
4843
4844 protected function sortSparsePattern
4845 "Sorts the indices and dependencies for the modelStructure section in modeldescription.xml."
4846 input list<SimCodeVar.SimVar> inSimVars;
4847 input BackendDAE.SparsePatternCrefs inSparsePattern;
4848 input Boolean useFMIIndex;
4849 output SimCode.SparsityPattern outSparse = {};
4850 protected
4851 HashTable.HashTable ht;
4852 DAE.ComponentRef cref;
4853 Integer size, i, j;
4854 list<Integer> intLst;
4855 list<DAE.ComponentRef> crefs;
4856 algorithm
4857 //create HT
4858 7742 size := listLength(inSimVars);
4859
2/2
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 7516 times.
7742 if size > 0 then
4860 7516 ht := HashTable.emptyHashTableSized(size);
4861
2/2
✓ Branch 0 taken 83086 times.
✓ Branch 1 taken 7516 times.
90602 for var in inSimVars loop
4862
2/2
✓ Branch 0 taken 76684 times.
✓ Branch 1 taken 6402 times.
83086 if not useFMIIndex then
4863 76684 SimCodeVar.SIMVAR(name=cref, index=i) := var;
4864 else
4865 6402 SimCodeVar.SIMVAR(name=cref) := var;
4866 6402 i := SimCodeCodegenUtil.getVariableFMIIndex(var);
4867 end if;
4868 //print("Setup HashTable with cref: " + ComponentReferenceBasics.printComponentRefStr(cref) + " index: "+ intString(i) + "\n");
4869 83086 ht := BaseHashTable.add((cref, i), ht);
4870 end for;
4871
4872 //translate
4873
2/2
✓ Branch 0 taken 35564 times.
✓ Branch 1 taken 7516 times.
43080 for tpl in inSparsePattern loop
4874 35564 (cref, crefs) := tpl;
4875 35564 i := BaseHashTable.get(cref, ht);
4876
2/2
✓ Branch 0 taken 34718 times.
✓ Branch 1 taken 846 times.
35564 if not useFMIIndex or i > 0 then // 0 means fmi_index = NONE() and represents internal variables that should be eliminated
4877 intLst := {};
4878
2/2
✓ Branch 0 taken 156287 times.
✓ Branch 1 taken 34718 times.
191005 for cr in crefs loop
4879 156287 j := BaseHashTable.get(cr, ht);
4880
2/2
✓ Branch 0 taken 156285 times.
✓ Branch 1 taken 2 times.
156287 if not useFMIIndex or j > 0 then // 0 means fmi_index = NONE() and represents internal variables that should be eliminated
4881 intLst := j :: intLst;
4882 end if;
4883 end for;
4884 34718 intLst := List.heapSortIntList(intLst);
4885 34718 outSparse := (i, intLst) :: outSparse;
4886 end if;
4887 end for;
4888 7516 outSparse := List.sort(outSparse, Util.compareTupleIntGt);
4889 end if;
4890 end sortSparsePattern;
4891
4892 protected function sortColoring
4893 input list<SimCodeVar.SimVar> inSimVars;
4894 input list<list<DAE.ComponentRef>> inColoring;
4895 output list<list<Integer>> outColoring = {};
4896 protected
4897 HashTable.HashTable ht;
4898 Integer size, i, j;
4899 list<Integer> intLst;
4900 DAE.ComponentRef cref;
4901 algorithm
4902 //create HT
4903 2673 size := listLength(inSimVars);
4904
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 2600 times.
2673 if size>0 then
4905 2600 ht := HashTable.emptyHashTableSized(size);
4906
2/2
✓ Branch 0 taken 20525 times.
✓ Branch 1 taken 2600 times.
23125 for var in inSimVars loop
4907 20525 SimCodeVar.SIMVAR(name = cref, index=i) := var;
4908 //print("Setup HashTable with cref: " + ComponentReferenceBasics.printComponentRefStr(cref) + " index: "+ intString(i) + "\n");
4909 20525 ht := BaseHashTable.add((cref, i), ht);
4910 end for;
4911
4912 //translate
4913
2/2
✓ Branch 0 taken 6392 times.
✓ Branch 1 taken 2600 times.
8992 for crefs in inColoring loop
4914 intLst := {};
4915
2/2
✓ Branch 0 taken 15585 times.
✓ Branch 1 taken 6392 times.
21977 for cr in crefs loop
4916 15585 j := BaseHashTable.get(cr, ht);
4917 intLst := j :: intLst;
4918 end for;
4919 outColoring := intLst :: outColoring;
4920 end for;
4921 end if;
4922 end sortColoring;
4923
4924 protected function dumpSparsePatternInt
4925 input SimCode.SparsityPattern sparsePattern;
4926 protected
4927 Integer i;
4928 list<Integer> lst;
4929 algorithm
4930 ✗ for tpl in sparsePattern loop
4931 ✗ (i, lst) := tpl;
4932 ✗ print("Row " + intString(i) + "\n");
4933 ✗ print("Cols: " + stringDelimitList(List.map(lst, intString)," ") + "\n");
4934 end for;
4935 end dumpSparsePatternInt;
4936
4937 protected function dumpSparsePattern
4938 input BackendDAE.SparsePatternCrefs sparsePattern;
4939 protected
4940 DAE.ComponentRef cr;
4941 list<DAE.ComponentRef> crefs;
4942 algorithm
4943 ✗ for tpl in sparsePattern loop
4944 ✗ (cr, crefs) := tpl;
4945 ✗ print("Row " + ComponentReferenceBasics.printComponentRefStr(cr) + "\n");
4946 ✗ print("Cols: " + stringDelimitList(List.map(crefs, ComponentReferenceBasics.printComponentRefStr)," ") + "\n");
4947 end for;
4948 end dumpSparsePattern;
4949
4950
4951
4952 // =============================================================================
4953 // section with unsorted function
4954 //
4955 // TODO: clean up this section ;)
4956 // =============================================================================
4957
4958 protected function isSimEqSys "checks if the given SES needs an additional equationsystem for the simulation and therefore skips an simEqIdx in the c-file.
4959 this is used to get the right simCode-eq-mapping for hpcm.
4960 add more cases here if you know for which cases this happens.
4961 author: Waurich TUD 2013-11 "
4962 input SimCode.SimEqSystem simEqSysIn;
4963 output Boolean isEqSys;
4964 algorithm
4965 isEqSys := match simEqSysIn
4966 case SimCode.SES_NONLINEAR()
4967 then true;
4968 else
4969 then false;
4970 end match;
4971 end isSimEqSys;
4972
4973 protected function collectDelayExpressions
4974 "Put expression into a list if it is a call to delay().
4975 Useable as a function parameter for Expression.traverseExpression."
4976 input DAE.Exp e;
4977 input list<DAE.Exp> acc;
4978 output DAE.Exp outExp;
4979 output list<DAE.Exp> outAcc;
4980 algorithm
4981 (outExp,outAcc) := match e
4982 case DAE.CALL(path = Absyn.IDENT("delay"))
4983 then (e, e :: acc);
4984 else (e,acc);
4985 end match;
4986 end collectDelayExpressions;
4987
4988 protected function updateDelayExpressions
4989 "Put expression into a list and update the index if it is a call to delay().
4990 Useable as a function parameter for Expression.traverseExpression."
4991 input output DAE.Exp e;
4992 input output tuple<list<DAE.Exp>, Integer> acc;
4993 algorithm
4994 (e, acc) := match (e, acc)
4995 local
4996 DAE.Exp res;
4997 Integer i, index;
4998 list<DAE.Exp> lst, rest;
4999 case (DAE.CALL(path = Absyn.IDENT("delay"), expLst = DAE.ICONST(i)::rest), (lst, index)) guard(i < 0) algorithm
5000 ✗ res := DAE.CALL(Absyn.IDENT("delay"), DAE.ICONST(index)::rest, e.attr);
5001 ✗ then (res, (res :: lst, index + 1));
5002 else (e, acc);
5003 end match;
5004 end updateDelayExpressions;
5005
5006 public function extractDelayedExpressions
5007 input BackendDAE.BackendDAE dlow;
5008 output list<tuple<Integer, tuple<DAE.Exp, DAE.Exp, DAE.Exp>>> delayedExps;
5009 output Integer maxDelayedExpIndex;
5010 algorithm
5011 (delayedExps, maxDelayedExpIndex) := matchcontinue dlow
5012 local
5013 list<DAE.Exp> exps;
5014 case _
5015 algorithm
5016 1069 (_,exps) := BackendDAEUtil.traverseBackendDAEExps(dlow, Expression.traverseSubexpressionsHelper, (collectDelayExpressions, {}));
5017 1069 delayedExps := List.map(exps, extractIdAndExpFromDelayExp);
5018 1069 maxDelayedExpIndex := List.applyAndFold(delayedExps, intMax, Util.tuple21, -1);
5019
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 then
5020 (delayedExps, maxDelayedExpIndex+1);
5021 else
5022 algorithm
5023 ✗ Error.addInternalError("function extractDelayedExpressions failed", sourceInfo());
5024 ✗ then
5025 fail();
5026 end matchcontinue;
5027 end extractDelayedExpressions;
5028
5029 public function extractJacobianDelayedExpressions
5030 input output list<tuple<Integer, tuple<DAE.Exp, DAE.Exp, DAE.Exp>>> delayedExps;
5031 input output Integer maxDelayedExpIndex;
5032 input output list<SimCode.JacobianMatrix> SymJacs;
5033 protected
5034 list<SimCode.JacobianMatrix> tmpJacs = {};
5035 list<SimCode.JacobianColumn> tmpCols;
5036 list<SimCode.SimEqSystem> tmpSysts;
5037 list<DAE.Exp> new_delayedExps;
5038 algorithm
5039
2/2
✓ Branch 1 taken 8685 times.
✓ Branch 2 taken 4240 times.
12925 for jac in listReverse(SymJacs) loop
5040 tmpCols := {};
5041
2/2
✓ Branch 2 taken 2030 times.
✓ Branch 3 taken 8685 times.
10715 for col in listReverse(jac.columns) loop
5042 2030 (tmpSysts, (_, (new_delayedExps, maxDelayedExpIndex))) := traverseExpsEqSystems(col.columnEqns, Expression.traverseSubexpressionsHelper, (updateDelayExpressions, ({}, maxDelayedExpIndex)), {});
5043 2030 delayedExps := listAppend(List.map(new_delayedExps, extractIdAndExpFromDelayExp), delayedExps);
5044 2030 col.columnEqns := tmpSysts;
5045 tmpCols := col :: tmpCols;
5046 end for;
5047 8685 jac.columns := tmpCols;
5048 tmpJacs := jac :: tmpJacs;
5049 end for;
5050 SymJacs := tmpJacs;
5051 end extractJacobianDelayedExpressions;
5052
5053 function extractIdAndExpFromDelayExp
5054 input DAE.Exp delayCallExp;
5055 output tuple<Integer, tuple<DAE.Exp, DAE.Exp, DAE.Exp>> delayedExp;
5056 algorithm
5057 delayedExp :=
5058 match delayCallExp
5059 local
5060 DAE.Exp e, delay, delayMax;
5061 Integer i;
5062 case DAE.CALL(path=Absyn.IDENT("delay"), expLst={DAE.ICONST(i), e, delay, delayMax})
5063 27 then ((i, (e, delay, delayMax)));
5064 end match;
5065 end extractIdAndExpFromDelayExp;
5066
5067 function extractSpatialDistributionInfo
5068 "Create spatialDistribution simCode from backend DAE."
5069 input BackendDAE.BackendDAE dlow;
5070 output SimCode.SpatialDistributionInfo spatialInfo;
5071 protected
5072 list<SimCode.SpatialDistribution> spatial_lst;
5073 Mutable<Integer> maxIndex_ptr = Mutable.create(-1);
5074 algorithm
5075 // Traverse top-down so we can keep track of the guard condition of the
5076 // enclosing if-branch a spatialDistribution() operator sits in. The
5077 // storeSpatialDistribution() callback must be guarded by the same condition
5078 1069 (_, (_, spatial_lst)) := BackendDAEUtil.traverseBackendDAEExps(dlow, Expression.traverseSubexpressionsTopDownHelper, (function extractSpatialDistributionInfoExp(maxIndex_ptr = maxIndex_ptr), (NONE(), {})));
5079 1069 spatialInfo := SimCode.SPATIAL_DISTRIBUTION_INFO(spatial_lst, Mutable.access(maxIndex_ptr));
5080 end extractSpatialDistributionInfo;
5081
5082 function extractSpatialDistributionInfoExp
5083 "Top-down expression traversal that collects every spatialDistribution() call
5084 together with the guard condition of the enclosing if-branch it sits in.
5085 The condition is carried in the traversal argument and conjoined per branch
5086 (then = cond, else = not cond) so the generated storeSpatialDistribution
5087 callback can be guarded by the same event as the operator's evaluation."
5088 input output DAE.Exp callExp;
5089 output Boolean cont "Continue descending flag for Expression.traverseExpTopDown";
5090 input output tuple<Option<DAE.Exp>, list<SimCode.SpatialDistribution>> tpl "current guard condition and collected operators";
5091 input Mutable<Integer> maxIndex_ptr;
5092 algorithm
5093 (cont, tpl) := match callExp
5094 local
5095 Integer i, initSize;
5096 DAE.Exp in0, in1, pos, dir, initPnts, initVals, cond, tb, fb;
5097 Option<DAE.Exp> curCond;
5098 list<SimCode.SpatialDistribution> spatialInfo;
5099 case DAE.CALL(path = Absyn.IDENT("spatialDistribution"), expLst={DAE.ICONST(i), in0, in1, pos, dir, initPnts, initVals})
5100 algorithm
5101 8 (curCond, spatialInfo) := tpl;
5102
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if i > Mutable.access(maxIndex_ptr) then
5103 8 Mutable.update(maxIndex_ptr, i);
5104 end if;
5105
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 if not Expression.sizeOf(Expression.typeof(initPnts)) == Expression.sizeOf(Expression.typeof(initVals)) then
5106 ✗ Error.addInternalError("function extractDelayedExpressions failed: initialPoints and initialValues of spatialDistribution are not of the same size.", sourceInfo());
5107 end if;
5108 8 initSize := Expression.sizeOf(Expression.typeof(initPnts));
5109 8 spatialInfo := SimCode.SPATIAL_DISTRIBUTION(i, in0, in1, pos, dir, initPnts, initVals, initSize, curCond) :: spatialInfo;
5110 8 then (true, (curCond, spatialInfo));
5111
5112 // Descend into the branches ourselves so the accumulated guard condition
5113 // can differ between the then- and else-branch. Return cont=false to keep
5114 // the generic traversal from visiting the children a second time.
5115 case DAE.IFEXP(cond, tb, fb)
5116 algorithm
5117 6038 (curCond, spatialInfo) := tpl;
5118 6038 (_, (_, spatialInfo)) := Expression.traverseExpTopDown(cond, function extractSpatialDistributionInfoExp(maxIndex_ptr = maxIndex_ptr), (curCond, spatialInfo));
5119 12076 (_, (_, spatialInfo)) := Expression.traverseExpTopDown(tb, function extractSpatialDistributionInfoExp(maxIndex_ptr = maxIndex_ptr), (SOME(combineGuardCondition(curCond, cond)), spatialInfo));
5120 12076 (_, (_, spatialInfo)) := Expression.traverseExpTopDown(fb, function extractSpatialDistributionInfoExp(maxIndex_ptr = maxIndex_ptr), (SOME(combineGuardCondition(curCond, Expression.negate(cond))), spatialInfo));
5121 6038 then (false, (curCond, spatialInfo));
5122
5123 else (true, tpl);
5124 end match;
5125 end extractSpatialDistributionInfoExp;
5126
5127 function combineGuardCondition
5128 "Conjoins an outer guard condition (if any) with a branch condition."
5129 input Option<DAE.Exp> outerCond;
5130 input DAE.Exp branchCond;
5131 output DAE.Exp cond;
5132 algorithm
5133 cond := match outerCond
5134 4154 case SOME(cond) then DAE.LBINARY(cond, DAE.AND(DAE.T_BOOL_DEFAULT), branchCond);
5135 else branchCond;
5136 end match;
5137 end combineGuardCondition;
5138
5139 public function createExtObjInfo
5140 input BackendDAE.Shared shared;
5141 output SimCode.ExtObjInfo extObjInfo;
5142 protected
5143 BackendDAE.Variables evars;
5144 list<BackendDAE.Var> evarLst;
5145 list<SimCode.ExtAlias> aliases;
5146 list<SimCodeVar.SimVar> simvars;
5147 algorithm
5148 1069 BackendDAE.SHARED(externalObjects=evars) := shared;
5149 1069 evarLst := BackendVariable.varList(evars);
5150 1069 evarLst := orderExtVars(evarLst, BackendDAEUtil.isInitializationDAE(shared));
5151 //evarLst := listReverse(evarLst);
5152 1069 (simvars, aliases) := extractExtObjInfo2(evarLst, evars);
5153 1069 extObjInfo := SimCode.EXTOBJINFO(simvars, aliases);
5154 end createExtObjInfo;
5155
5156 protected function orderExtVars"External Variables have to be ordered.
5157 It might occure that their binding expressions are dependent on other external variables and therefore, these vars and their binding exps have to be causalized.
5158 author: waurich TUD 08.2015"
5159 input list<BackendDAE.Var> varLstIn;
5160 input Boolean isInitial;
5161 output list<BackendDAE.Var> varLstOut;
5162 protected
5163 list<Integer> order;
5164 array<Integer> ass1,ass2;
5165 list<list<Integer>> comps;
5166 list<BackendDAE.Var> varsWithBind, varsWithoutBind;
5167 algorithm
5168 try
5169 1069 (varsWithBind,varsWithoutBind) := List.separateOnTrue(varLstIn,BackendVariable.varHasBindExp);
5170 1069 (comps,ass1,ass2) := BackendDAEUtil.causalizeVarBindSystem(varsWithBind, isInitial);
5171 1069 order := List.map1(List.flatten(comps),Array.getIndexFirst,ass1);
5172 1069 varsWithBind := List.map1(order,List.getIndexFirst,varsWithBind);
5173 1069 varLstOut := listAppend(varsWithoutBind,varsWithBind);
5174 else
5175 varLstOut := varLstIn;
5176 end try;
5177 end orderExtVars;
5178
5179 protected function extractExtObjInfo2
5180 input list<BackendDAE.Var> varLst;
5181 input BackendDAE.Variables evars;
5182 output list<SimCodeVar.SimVar> vars = {};
5183 output list<SimCode.ExtAlias> aliases = {};
5184 algorithm
5185
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 1069 times.
1131 for bv in varLst loop
5186 () := match bv
5187 local
5188 DAE.ComponentRef cr, name;
5189 SimCodeVar.SimVar sv;
5190 case BackendDAE.VAR(varName=name, bindExp=SOME(DAE.CREF(cr, _)), varKind=BackendDAE.EXTOBJ(_))
5191 algorithm
5192 ✗ aliases := (name, cr)::aliases;
5193 then ();
5194 else
5195 algorithm
5196 62 sv := dlowvarToSimvar(bv, NONE(), evars);
5197 vars := sv::vars;
5198 then ();
5199 end match;
5200 end for;
5201 1069 vars := Dangerous.listReverseInPlace(vars);
5202 1069 aliases := Dangerous.listReverseInPlace(aliases);
5203 end extractExtObjInfo2;
5204
5205 protected function createAlgorithmAndEquationAsserts
5206 input BackendDAE.EqSystem syst;
5207 input BackendDAE.Shared shared;
5208 input tuple<Integer, list<SimCode.SimEqSystem>> acc;
5209 output tuple<Integer, list<SimCode.SimEqSystem>> algorithmAndEquationAsserts;
5210 algorithm
5211 algorithmAndEquationAsserts := matchcontinue (syst, shared, acc)
5212 local
5213 list<SimCode.SimEqSystem> simeqns;
5214 list<DAE.Algorithm> res;
5215 BackendDAE.Variables vars;
5216 list<SimCode.SimEqSystem> result;
5217 Integer uniqueEqIndex;
5218
5219 case (BackendDAE.EQSYSTEM(orderedVars = vars), BackendDAE.SHARED(), (uniqueEqIndex, simeqns))
5220 algorithm
5221 // get minmax asserts
5222 3918 res := BackendVariable.traverseBackendDAEVars(vars, BackendVariable.getMinMaxAsserts, {});
5223 3918 (result, uniqueEqIndex) := List.mapFold(res, dlowAlgToSimEqSystem, uniqueEqIndex);
5224 3918 then ((uniqueEqIndex, listAppend(result, simeqns)));
5225 else
5226 algorithm
5227 ✗ Error.addInternalError("function createAlgorithmAndEquationAsserts failed", sourceInfo());
5228 ✗ then fail();
5229 end matchcontinue;
5230 end createAlgorithmAndEquationAsserts;
5231
5232 public function traversedlowEqToSimEqSystem
5233 input BackendDAE.Equation inEq;
5234 input tuple<Integer, list<SimCode.SimEqSystem>> inTpl;
5235 output BackendDAE.Equation outEq;
5236 output tuple<Integer, list<SimCode.SimEqSystem>> outTpl;
5237 algorithm
5238 (outEq,outTpl) := matchcontinue (inEq,inTpl)
5239 local
5240 BackendDAE.Equation e;
5241 SimCode.SimEqSystem se;
5242 list<SimCode.SimEqSystem> seqnlst;
5243 Integer uniqueEqIndex;
5244 case (e, (uniqueEqIndex, seqnlst))
5245 algorithm
5246 2633 (se, uniqueEqIndex) := dlowEqToSimEqSystem(e, uniqueEqIndex);
5247 2633 then (e, (uniqueEqIndex, se::seqnlst));
5248 else (inEq,inTpl);
5249 end matchcontinue;
5250 end traversedlowEqToSimEqSystem;
5251
5252 public function extractDiscreteModelVars
5253 input BackendDAE.EqSystem syst;
5254 input BackendDAE.Shared shared;
5255 input list<DAE.ComponentRef> acc;
5256 output list<DAE.ComponentRef> discreteModelVars;
5257 algorithm
5258 discreteModelVars := matchcontinue syst
5259 local
5260 BackendDAE.Variables v;
5261 list<DAE.ComponentRef> vLst2;
5262
5263 case BackendDAE.EQSYSTEM(orderedVars=v)
5264 algorithm
5265 // select all discrete vars.
5266 // remove those vars that are solved in when equations
5267 // replace var with cref
5268 3931 vLst2 := BackendVariable.traverseBackendDAEVars(v, traversingisVarDiscreteCrefFinder, acc);
5269 // vLst2 = List.unionOnTrue(vLst2, vLst1, ComponentReferenceBasics.crefEqual);
5270 then vLst2;
5271 else
5272 algorithm
5273 ✗ Error.addInternalError("function extractDiscreteModelVars failed", sourceInfo());
5274 ✗ then fail();
5275 end matchcontinue;
5276 end extractDiscreteModelVars;
5277
5278 protected function traversingisVarDiscreteCrefFinder
5279 input BackendDAE.Var inVar;
5280 input list<DAE.ComponentRef> inTpl;
5281 output BackendDAE.Var outVar;
5282 output list<DAE.ComponentRef> outTpl;
5283 algorithm
5284 outVar := inVar;
5285
2/2
✓ Branch 1 taken 4054 times.
✓ Branch 2 taken 63401 times.
67455 outTpl := if BackendVariable.isVarDiscrete(inVar) then BackendVariable.varCref(inVar) :: inTpl else inTpl;
5286 end traversingisVarDiscreteCrefFinder;
5287
5288 protected function jacToSimjac
5289 input tuple<Integer, Integer, BackendDAE.Equation> jac;
5290 input BackendDAE.Variables v;
5291 output tuple<Integer, Integer, SimCode.SimEqSystem> simJac;
5292 algorithm
5293 simJac := match jac
5294 local
5295 Integer row;
5296 Integer col;
5297 DAE.Exp e;
5298 DAE.ElementSource source;
5299 BackendDAE.EquationAttributes eqAttr;
5300
5301 case (row, col, BackendDAE.RESIDUAL_EQUATION(exp=e, source=source, attr=eqAttr))
5302 algorithm
5303 // rhs_exp = BackendDAEUtil.getEqnsysRhsExp(e, v, NONE());
5304 // rhs_exp_1 = ExpressionSimplify.simplify(rhs_exp);
5305 // then ((row - 1, col - 1, SimCode.SES_RESIDUAL(rhs_exp_1)));
5306 11090 then
5307 ((row - 1, col - 1, SimCode.SES_RESIDUAL(0, 0, e, source, eqAttr)));
5308 end match;
5309 end jacToSimjac;
5310
5311 protected function simJacCSRToCSC"outputs true if a simjac entry of type <row,col> is before another in the sense of a compressed sparse column format"
5312 input tuple<Integer,Integer,SimCode.SimEqSystem> e1; //<row,col>
5313 input tuple<Integer,Integer,SimCode.SimEqSystem> e2;
5314 output Boolean isGt;
5315 protected
5316 Integer r1,r2,c1,c2;
5317 algorithm
5318 98 (r1,c1,_) := e1;
5319 98 (r2,c2,_) := e2;
5320
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 36 times.
98 if intNe(c1,c2) then
5321 62 isGt := intGt(c1,c2);
5322 else
5323 36 isGt := intGt(r1,r2);
5324 end if;
5325 end simJacCSRToCSC;
5326
5327 protected function createSingleWhenEqnCode
5328 input BackendDAE.Equation inEquation;
5329 input list<BackendDAE.Var> inVars;
5330 input BackendDAE.Shared shared;
5331 input Integer iuniqueEqIndex;
5332 input list<SimCodeVar.SimVar> itempvars;
5333 output list<SimCode.SimEqSystem> equations_;
5334 output Integer ouniqueEqIndex;
5335 output list<SimCodeVar.SimVar> otempvars;
5336 algorithm
5337 (equations_, ouniqueEqIndex, otempvars) := matchcontinue inEquation
5338 local
5339 DAE.Exp cond;
5340 DAE.ComponentRef left;
5341 DAE.ElementSource source;
5342 list<DAE.ComponentRef> crefs;
5343 BackendDAE.WhenEquation elseWhen;
5344 list<DAE.ComponentRef> conditions;
5345 Boolean initialCall;
5346 list<BackendDAE.WhenOperator> whenStmtLst;
5347 Integer uniqueEqIndex;
5348 Option<BackendDAE.WhenEquation> oelseWhen;
5349 SimCode.SimEqSystem simElseWhenEq;
5350 Option<SimCode.SimEqSystem> osimElseWhenEq;
5351 BackendDAE.EquationAttributes eqAttr;
5352
5353
5354 // when eq without else
5355 case BackendDAE.WHEN_EQUATION(whenEquation=BackendDAE.WHEN_STMTS(condition=cond, whenStmtLst=whenStmtLst, elsewhenPart = oelseWhen), source=source, attr=eqAttr)
5356 algorithm
5357
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 425 times.
850 for stmt in whenStmtLst loop
5358 () := match stmt
5359 case BackendDAE.ASSIGN(left = DAE.CREF(componentRef = left)) algorithm
5360 419 crefs := List.map(inVars, BackendVariable.varCref);
5361
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 419 times.
419 true := List.all(crefs, function ComponentReferenceBasics.crefPrefixOf(prefixCref = left));
5362 then ();
5363 else ();
5364 end match;
5365 end for;
5366
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 418 times.
✓ Branch 3 taken 7 times.
425 if isSome(oelseWhen) then
5367 7 SOME(elseWhen) := oelseWhen;
5368 7 (simElseWhenEq, uniqueEqIndex) := createElseWhenEquation(elseWhen, inVars, iuniqueEqIndex+1, source, eqAttr);
5369 osimElseWhenEq := SOME(simElseWhenEq);
5370 else
5371 418 uniqueEqIndex := iuniqueEqIndex+1;
5372 osimElseWhenEq := NONE();
5373 end if;
5374 425 (conditions, initialCall) := BackendDAEUtil.getConditionList(cond);
5375
2/4
✓ Branch 0 taken 425 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 425 times.
✗ Branch 4 not taken.
1275 then ({SimCode.SES_WHEN(iuniqueEqIndex, conditions, initialCall, whenStmtLst, osimElseWhenEq, source, eqAttr)}, uniqueEqIndex, itempvars);
5376
5377 // failure
5378 else
5379 algorithm
5380 ✗ Error.addInternalError("function createSingleWhenEqnCode failed. When equations currently only supported on form v = ...", sourceInfo());
5381 ✗ then fail();
5382 end matchcontinue;
5383 end createSingleWhenEqnCode;
5384
5385 protected function createElseWhenEquation
5386 input BackendDAE.WhenEquation inElseWhenEquation;
5387 input list<BackendDAE.Var> inVars;
5388 input Integer iuniqueEqIndex;
5389 input DAE.ElementSource inElementSource;
5390 input BackendDAE.EquationAttributes inEqAttr;
5391 output SimCode.SimEqSystem outSimEqSystem;
5392 output Integer ouniqueEqIndex;
5393 algorithm
5394 (outSimEqSystem, ouniqueEqIndex) := match inElseWhenEquation
5395 local
5396 DAE.ComponentRef left;
5397 DAE.Exp cond;
5398 BackendDAE.WhenEquation elseWhenEquation;
5399 Option<BackendDAE.WhenEquation> oelseWhenEquation;
5400 SimCode.SimEqSystem simElseWhenEq;
5401 Option<SimCode.SimEqSystem> osimElseWhenEq;
5402 list<DAE.ComponentRef> conditions;
5403 Boolean initialCall;
5404 list<BackendDAE.WhenOperator> whenStmtLst;
5405 Integer uniqueEqIndex;
5406 list<DAE.ComponentRef> crefs;
5407
5408 // when eq with else
5409 case BackendDAE.WHEN_STMTS(condition=cond, whenStmtLst=whenStmtLst, elsewhenPart = oelseWhenEquation) algorithm
5410
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 for stmt in whenStmtLst loop
5411 () := match stmt
5412 case BackendDAE.ASSIGN(left = DAE.CREF(componentRef = left)) algorithm
5413 7 crefs := List.map(inVars, BackendVariable.varCref);
5414
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
7 true := List.all(crefs, function ComponentReferenceBasics.crefPrefixOf(prefixCref = left));
5415 then ();
5416 else ();
5417 end match;
5418 end for;
5419
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if isSome(oelseWhenEquation) then
5420 ✗ SOME(elseWhenEquation) := oelseWhenEquation;
5421 ✗ (simElseWhenEq, uniqueEqIndex) := createElseWhenEquation(elseWhenEquation, inVars, iuniqueEqIndex+1, inElementSource, inEqAttr);
5422 osimElseWhenEq := SOME(simElseWhenEq);
5423 else
5424 8 uniqueEqIndex := iuniqueEqIndex+1;
5425 osimElseWhenEq := NONE();
5426 end if;
5427 8 (conditions, initialCall) := BackendDAEUtil.getConditionList(cond);
5428
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
16 then (SimCode.SES_WHEN(iuniqueEqIndex, conditions, initialCall, whenStmtLst, osimElseWhenEq, inElementSource, inEqAttr), uniqueEqIndex);
5429 end match;
5430 end createElseWhenEquation;
5431
5432 protected function createSingleIfEqnCode
5433 input BackendDAE.Equation inEquation;
5434 input list<BackendDAE.Var> inVars;
5435 input BackendDAE.Shared shared;
5436 input Boolean genDiscrete;
5437 input Integer iuniqueEqIndex;
5438 input list<SimCodeVar.SimVar> itempvars;
5439 output list<SimCode.SimEqSystem> equations_;
5440 output Integer ouniqueEqIndex;
5441 output list<SimCodeVar.SimVar> otempvars;
5442 algorithm
5443 (equations_, ouniqueEqIndex, otempvars) := matchcontinue(inEquation, shared)
5444 local
5445 list<DAE.Exp> conditions;
5446 Integer uniqueEqIndex;
5447
5448 list<SimCodeVar.SimVar> tempvars;
5449 list<list<BackendDAE.Equation>> eqnsLst;
5450 list<BackendDAE.Equation> elseqns;
5451 list<tuple<DAE.Exp, list<SimCode.SimEqSystem>>> ifbranches;
5452 DAE.ElementSource source_;
5453 BackendDAE.ExtraInfo ei;
5454 BackendDAE.EquationAttributes eqAttr;
5455
5456 case (BackendDAE.IF_EQUATION(conditions=conditions, eqnstrue=eqnsLst, eqnsfalse=elseqns, source=source_, attr=eqAttr), BackendDAE.SHARED(info = ei)) algorithm
5457 ✗ (ifbranches, uniqueEqIndex, tempvars) := createEquationsIfBranch(conditions, eqnsLst, inVars, shared, genDiscrete, iuniqueEqIndex, itempvars);
5458 ✗ (equations_, uniqueEqIndex, tempvars) := createEquationsfromList(elseqns, inVars, uniqueEqIndex, tempvars, ei, genDiscrete);
5459 ✗ then ({SimCode.SES_IFEQUATION(uniqueEqIndex, ifbranches, equations_, source_, eqAttr)}, uniqueEqIndex+1, tempvars);
5460
5461 else algorithm
5462 ✗ Error.addInternalError("SimCodeUtil.createSingleIfEqnCode failed.", sourceInfo());
5463 ✗ then fail();
5464 end matchcontinue;
5465 end createSingleIfEqnCode;
5466
5467 protected function createEquationsIfBranch
5468 input list<DAE.Exp> inConditions;
5469 input list<list<BackendDAE.Equation>> inEquationsLst;
5470 input list<BackendDAE.Var> inVars;
5471 input BackendDAE.Shared shared;
5472 input Boolean genDiscrete;
5473 input Integer iuniqueEqIndex;
5474 input list<SimCodeVar.SimVar> itempvars;
5475 output list<tuple<DAE.Exp, list<SimCode.SimEqSystem>>> outEquations;
5476 output Integer ouniqueEqIndex;
5477 output list<SimCodeVar.SimVar> otempvars;
5478 algorithm
5479 (outEquations, ouniqueEqIndex, otempvars) := matchcontinue(inConditions, inEquationsLst, shared)
5480 local
5481 list<BackendDAE.Equation> eqns;
5482 list<list<BackendDAE.Equation>> eqnsLst;
5483 DAE.Exp condition;
5484 list<DAE.Exp> conditionList;
5485 list<SimCodeVar.SimVar> tempvars;
5486 Integer uniqueEqIndex;
5487 list<SimCode.SimEqSystem> equations_;
5488 tuple<DAE.Exp, list<SimCode.SimEqSystem>> ifbranch;
5489 list<tuple<DAE.Exp, list<SimCode.SimEqSystem>>> ifbranches;
5490 BackendDAE.ExtraInfo ei;
5491
5492 case ({}, {}, _)
5493 then ({}, iuniqueEqIndex, itempvars);
5494
5495 case (condition::conditionList, eqns::eqnsLst, BackendDAE.SHARED(info = ei)) algorithm
5496 ✗ (equations_, uniqueEqIndex, tempvars) := createEquationsfromList(eqns, inVars, iuniqueEqIndex, itempvars, ei, genDiscrete);
5497 ✗ ifbranch := ((condition, equations_));
5498 ✗ (ifbranches, uniqueEqIndex, tempvars) := createEquationsIfBranch(conditionList, eqnsLst, inVars, shared, genDiscrete, uniqueEqIndex, tempvars);
5499 ifbranches := ifbranch::ifbranches;
5500 ✗ then (ifbranches, uniqueEqIndex, tempvars);
5501
5502 else algorithm
5503 ✗ Error.addInternalError("SimCodeUtil.createEquationfromList failed.", sourceInfo());
5504 ✗ then fail();
5505 end matchcontinue;
5506 end createEquationsIfBranch;
5507
5508 public function createEquationsfromBackendDAE
5509 input BackendDAE.BackendDAE inBDAE;
5510 input Integer iuniqueEqIndex;
5511 input list<SimCodeVar.SimVar> itempvars;
5512 input Boolean genDiscrete = false;
5513 input Boolean includeWhen = false;
5514 input Boolean skipDiscInZc = false;
5515 input Boolean skipDiscInAlgorithm = false;
5516 output list<list<SimCode.SimEqSystem>> outEquations = {};
5517 output Integer uniqueEqIndex = iuniqueEqIndex;
5518 output list<SimCodeVar.SimVar> tempvars = itempvars;
5519 protected
5520 BackendDAE.StrongComponents comps;
5521 list<SimCode.SimEqSystem> simEqs, zeroVarEquations;
5522 algorithm
5523
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9 times.
22 for syst in inBDAE.eqs loop
5524 // get components
5525 13 comps := BackendDAEUtil.getCompsOfMatching(syst.matching);
5526
5527 // create SimCode equatinos
5528 13 (simEqs, _, uniqueEqIndex, tempvars) := createEquations(includeWhen, skipDiscInZc, genDiscrete, skipDiscInAlgorithm, syst, inBDAE.shared, comps, uniqueEqIndex, tempvars);
5529
5530 // process also the zeroVariable equations
5531 13 (uniqueEqIndex, zeroVarEquations) := BackendEquation.traverseEquationArray(syst.removedEqs, SimCodeUtil.traversedlowEqToSimEqSystem, (uniqueEqIndex, {}));
5532
5533 // add equations
5534 13 outEquations := listAppend(simEqs, zeroVarEquations) :: outEquations;
5535 end for;
5536
5537 9 outEquations := Dangerous.listReverseInPlace(outEquations);
5538 end createEquationsfromBackendDAE;
5539
5540 public function createEquationsfromList
5541 input list<BackendDAE.Equation> inEquations;
5542 input list<BackendDAE.Var> inVars;
5543 input Integer iuniqueEqIndex;
5544 input list<SimCodeVar.SimVar> itempvars;
5545 input BackendDAE.ExtraInfo iextra;
5546 input Boolean genDiscrete = false;
5547 input Boolean includeWhen = false;
5548 input Boolean skipDiscInZc = false;
5549 input Boolean skipDiscInAlgorithm = false;
5550 output list<SimCode.SimEqSystem> equations_;
5551 output Integer ouniqueEqIndex;
5552 output list<SimCodeVar.SimVar> otempvars;
5553 algorithm
5554 (equations_, ouniqueEqIndex, otempvars) := matchcontinue inEquations
5555 local
5556 BackendDAE.Variables vars1;
5557 BackendDAE.EquationArray eqns_1;
5558 BackendDAE.BackendDAE subsystem_dae;
5559 BackendDAE.StrongComponents comps;
5560 BackendDAE.EqSystem syst;
5561 BackendDAE.Shared shared;
5562 Integer uniqueEqIndex;
5563 list<SimCodeVar.SimVar> tempvars;
5564
5565 case {}
5566 then ({}, iuniqueEqIndex, itempvars);
5567
5568 case _ algorithm
5569 ✗ eqns_1 := BackendEquation.listEquation(inEquations);
5570 ✗ vars1 := BackendVariable.listVar1(inVars);
5571 ✗ syst := BackendDAEUtil.createEqSystem(vars1, eqns_1);
5572 ✗ shared := BackendDAEUtil.createEmptyShared(BackendDAE.ARRAYSYSTEM(), iextra, FCore.emptyCache(), FGraph.empty());
5573 ✗ subsystem_dae := BackendDAE.DAE({syst}, shared);
5574 ✗ BackendDAE.DAE({syst as BackendDAE.EQSYSTEM(matching=BackendDAE.MATCHING(comps=comps))}, shared) :=
5575 BackendDAEUtil.transformBackendDAE( subsystem_dae, SOME((BackendDAE.NO_INDEX_REDUCTION(),
5576 BackendDAE.ALLOW_UNDERCONSTRAINED())), NONE(), NONE() );
5577 ✗ (equations_, _, uniqueEqIndex, tempvars) := createEquations(includeWhen, skipDiscInZc, genDiscrete, skipDiscInAlgorithm, syst, shared, comps, iuniqueEqIndex, itempvars);
5578 ✗ then (equations_, uniqueEqIndex, tempvars);
5579
5580 else algorithm
5581 ✗ Error.addInternalError("SimCodeUtil.createEquationfromList failed.", sourceInfo());
5582 ✗ then fail();
5583
5584 end matchcontinue;
5585 end createEquationsfromList;
5586
5587 protected function createSingleComplexEqnCode
5588 input BackendDAE.Equation inEquation;
5589 input list<BackendDAE.Var> inVars;
5590 input Integer iuniqueEqIndex;
5591 input list<SimCodeVar.SimVar> itempvars;
5592 input BackendDAE.ExtraInfo iextra;
5593 input Boolean genDiscrete;
5594 input AvlTreePathFunction.Tree funcTree;
5595 input Option<Integer> clockIndex;
5596 output list<SimCode.SimEqSystem> equations_;
5597 output Integer ouniqueEqIndex;
5598 output list<SimCodeVar.SimVar> otempvars;
5599 algorithm
5600 (equations_, ouniqueEqIndex, otempvars) := matchcontinue inEquation
5601 local
5602 Integer uniqueEqIndex;
5603 DAE.Exp e1, e2;
5604 DAE.ElementSource source;
5605 list<DAE.ComponentRef> crefs;
5606 list<SimCode.SimEqSystem> resEqs;
5607 list<SimCodeVar.SimVar> tempvars;
5608 String s, s1, s2, s3;
5609 Boolean homotopySupport;
5610 BackendDAE.EquationAttributes eqAttr;
5611
5612 case BackendDAE.COMPLEX_EQUATION(left=e1, right=e2, source=source, attr=eqAttr) algorithm
5613 1172 crefs := List.map(inVars, BackendVariable.varCref);
5614 1172 e1 := Expression.replaceDerOpInExp(e1);
5615 1172 e2 := Expression.replaceDerOpInExp(e2);
5616 1172 (equations_, uniqueEqIndex, tempvars) := createSingleComplexEqnCode2(crefs, e1, e2, iuniqueEqIndex, itempvars, source, eqAttr, iextra, genDiscrete, inVars);
5617 then (equations_, uniqueEqIndex, tempvars);
5618
5619 case BackendDAE.COMPLEX_EQUATION(left=e1, right=e2, source=source, attr=eqAttr) algorithm
5620 22 crefs := List.map(inVars, BackendVariable.varCref);
5621
5622 // Check that all crefs are of Type Real
5623 // otherwise we can't solve that with one Non-linear equation
5624
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 true := List.mapMapBoolAnd(crefs, ComponentReference.crefLastType, Types.isRealOrSubTypeReal);
5625
5626 // Simplify
5627 22 (e1, _) := ExpressionSimplify.simplify(e1);
5628 22 e1 := Expression.replaceDerOpInExp(e1);
5629 22 (e2, _) := ExpressionSimplify.simplify(e2);
5630 22 e2 := Expression.replaceDerOpInExp(e2);
5631
5632 // Create nonlinear equation system from complex function
5633 22 (resEqs, uniqueEqIndex, tempvars, crefs) := createNonlinearResidualEquationsSingleComplex(e1, e2, source, eqAttr, iuniqueEqIndex, itempvars, crefs);
5634 2 resEqs := fixNonlinearResidualIndices(resEqs);
5635 2 (_, homotopySupport) := BackendEquation.traverseExpsOfEquation(inEquation, BackendDAEUtil.containsHomotopyCall, false);
5636
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
6 then ({SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(uniqueEqIndex, resEqs, crefs, 0, listLength(inVars)+listLength(tempvars)-listLength(itempvars), NONE(), homotopySupport, false, false, clockIndex), NONE(), eqAttr)}, uniqueEqIndex+1, tempvars);
5637
5638 case BackendDAE.COMPLEX_EQUATION(attr=eqAttr) algorithm
5639 20 crefs := List.map(inVars, BackendVariable.varCref);
5640
5641 // check that all crefs are of Type Real
5642 // otherwise we can't solve that with one Non-linear equation
5643
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 true := List.mapMapBoolAnd(crefs, ComponentReference.crefLastType, Types.isRealOrSubTypeReal);
5644
5645 // wbraun:
5646 // TODO: Fix createNonlinearResidualEquations support cases where
5647 // solved variables are on rhs and also lhs. This is not
5648 // considered yet there.
5649 20 (resEqs, (uniqueEqIndex, _), tempvars) := createNonlinearResidualEquations({inEquation}, (iuniqueEqIndex, 0), itempvars, funcTree);
5650 20 resEqs := fixNonlinearResidualIndices(resEqs);
5651 20 (_, homotopySupport) := BackendEquation.traverseExpsOfEquation(inEquation, BackendDAEUtil.containsHomotopyCall, false);
5652
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
60 then ({SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(uniqueEqIndex, resEqs, crefs, 0, listLength(inVars)+listLength(tempvars)-listLength(itempvars), NONE(), homotopySupport, false, false, clockIndex), NONE(), eqAttr)}, uniqueEqIndex+1, tempvars);
5653
5654 // failure
5655 case BackendDAE.COMPLEX_EQUATION(left=e1, right=e2) algorithm
5656 ✗ crefs := List.map(inVars, BackendVariable.varCref);
5657
5658 // check that all crefs are of Type Real
5659 // otherwise we can't solve that with one Non-linear equation
5660 ✗ false := List.mapMapBoolAnd(crefs, ComponentReference.crefLastType, Types.isRealOrSubTypeReal);
5661
5662 ✗ s1 := ExpressionBasics.printExpStr(e1);
5663 ✗ s2 := ExpressionBasics.printExpStr(e2);
5664 ✗ s3 := ComponentReferenceBasics.printComponentRefListStr(crefs);
5665 ✗ s := stringAppendList({"No support of solving not real variables with a non-linear solver. Equation:\n", s1, " = " , s2, " solve for ", s3 });
5666 ✗ Error.addInternalError(s, sourceInfo());
5667 ✗ then fail();
5668
5669 // failure
5670 case BackendDAE.COMPLEX_EQUATION(left=e1, right=e2) algorithm
5671 ✗ crefs := List.map(inVars, BackendVariable.varCref);
5672
5673 // check that all crefs are of Type Real
5674 // otherwise we can't solve that with one Non-linear equation
5675 ✗ true := List.mapMapBoolAnd(crefs, ComponentReference.crefLastType, Types.isRealOrSubTypeReal);
5676
5677 ✗ s1 := ExpressionBasics.printExpStr(e1);
5678 ✗ s2 := ExpressionBasics.printExpStr(e2);
5679 ✗ s3 := ComponentReferenceBasics.printComponentRefListStr(crefs);
5680 ✗ s := stringAppendList({"complex equations currently only supported on form v = functioncall(...). Equation: ", s1, " = " , s2, " solve for ", s3 });
5681 ✗ Error.addInternalError(s, sourceInfo());
5682 ✗ then fail();
5683 end matchcontinue;
5684 end createSingleComplexEqnCode;
5685
5686 // TODO: are the cases really correct?
5687 // mahge: These should be revised or removed!!
5688 protected function createSingleComplexEqnCode2
5689 input list<DAE.ComponentRef> crefs;
5690 input DAE.Exp inExp3;
5691 input DAE.Exp inExp4;
5692 input Integer iuniqueEqIndex;
5693 input list<SimCodeVar.SimVar> itempvars;
5694 input DAE.ElementSource source;
5695 input BackendDAE.EquationAttributes eqKind;
5696 input BackendDAE.ExtraInfo iextra;
5697 input Boolean genDiscrete;
5698 input list<BackendDAE.Var> inVars;
5699 output list<SimCode.SimEqSystem> equations_;
5700 output Integer ouniqueEqIndex;
5701 output list<SimCodeVar.SimVar> otempvars;
5702 algorithm
5703 (equations_, ouniqueEqIndex, otempvars) := matchcontinue (inExp3, inExp4)
5704 local
5705 DAE.ComponentRef cr1, cr2;
5706 DAE.Exp e1, e2, e1_1, e2_1;
5707 list<DAE.Exp> expl, expl1;
5708 DAE.Statement stms;
5709 DAE.Type tp;
5710 DAE.CallAttributes attr;
5711 Absyn.Path path, rpath;
5712 list<DAE.Exp> expLst, crexplst ;
5713 DAE.Ident ident;
5714 list<tuple<DAE.Exp, DAE.Exp>> exptl;
5715 SimCode.SimEqSystem simeqn_complex;
5716 list<SimCode.SimEqSystem> eqSystlst;
5717 list<list<SimCode.SimEqSystem>> eqSystlst_nonflat;
5718 list<SimCodeVar.SimVar> tempvars;
5719 Integer uniqueEqIndex;
5720 list<DAE.Var> varLst;
5721 HashSet.HashSet ht;
5722 String s, s1, s2, s3;
5723 list<BackendDAE.Equation> eqnLst;
5724
5725 case (DAE.CAST(exp = e1), _)
5726 algorithm
5727 ✗ (equations_, ouniqueEqIndex, otempvars) :=
5728 createSingleComplexEqnCode2(crefs, e1, inExp4, iuniqueEqIndex, itempvars, source, eqKind, iextra, genDiscrete, inVars);
5729 then
5730 (equations_, ouniqueEqIndex, otempvars);
5731
5732 case (_, DAE.CAST(exp = e1))
5733 algorithm
5734 ✗ (equations_, ouniqueEqIndex, otempvars) :=
5735 createSingleComplexEqnCode2(crefs, inExp3, e1, iuniqueEqIndex, itempvars, source, eqKind, iextra, genDiscrete, inVars);
5736 then
5737 (equations_, ouniqueEqIndex, otempvars);
5738
5739 case (e1 as DAE.CREF(componentRef = cr2), e2)
5740 algorithm
5741
2/2
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 532 times.
542 true := List.all(crefs, function ComponentReferenceBasics.crefPrefixOf(prefixCref = cr2));
5742 // ((e1_1, _)) = Expression.extendArrExp((e1, false));
5743 532 (e2_1, _) := Expression.extendArrExp(e2, false);
5744 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
5745 532 tp := Expression.typeof(e1);
5746 532 stms := DAE.STMT_ASSIGN(tp, e1, e2_1, source);
5747 1064 then
5748 ({SimCode.SES_ALGORITHM(iuniqueEqIndex, {stms}, eqKind)}, iuniqueEqIndex+1, itempvars);
5749
5750 case (e1, e2 as DAE.CREF(componentRef = cr2))
5751 algorithm
5752 ✗ true := List.all(crefs, function ComponentReferenceBasics.crefPrefixOf(prefixCref = cr2));
5753 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
5754 ✗ (e1_1, _) := Expression.extendArrExp(e1, false);
5755 // ((e2_1, _)) = Expression.extendArrExp((e2, false));
5756 ✗ tp := Expression.typeof(e2);
5757 ✗ stms := DAE.STMT_ASSIGN(tp, e2, e1_1, source);
5758 ✗ then
5759 ({SimCode.SES_ALGORITHM(iuniqueEqIndex, {stms}, eqKind)}, iuniqueEqIndex+1, itempvars);
5760
5761 /* Record() = f() */
5762 case (DAE.CALL(path=path, expLst=expLst, attr=DAE.CALL_ATTR(ty= tp as DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(path=rpath), varLst=varLst))), e2)
5763 algorithm
5764
5765 ✗ true := AbsynUtil.pathEqual(path, rpath);
5766 // check all crefs are on the lhs
5767 ✗ ht := HashSet.emptyHashSet();
5768 ✗ ht := List.fold(crefs, BaseHashSet.add, ht);
5769 ✗ expLst := Expression.traverseExpList(expLst, function Expression.expandCrefs(expandRecord=true), 0) "The routines generate bad code for arrays inside the record unless we expand them";
5770 ✗ List.foldAllValue(expLst, createSingleComplexEqnCode3, true, ht);
5771 ✗ (e2_1, _) := Expression.extendArrExp(e2, false);
5772
5773 // tmp = somexp
5774 ✗ ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
5775 ✗ cr1 := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(iuniqueEqIndex), tp, {});
5776 ✗ e1_1 := Expression.crefToExp(cr1);
5777 ✗ stms := DAE.STMT_ASSIGN(tp, e1_1, e2_1, source);
5778 ✗ simeqn_complex := SimCode.SES_ALGORITHM(iuniqueEqIndex, {stms}, eqKind);
5779 ✗ uniqueEqIndex := iuniqueEqIndex + 1;
5780
5781 /* Expand the varLst. Each var might be an array or record. */
5782 ✗ crexplst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr1);
5783 /* pair each of the expanded expressions to coressponding one*/
5784 ✗ exptl := List.zip(expLst, crexplst);
5785 /* Create residual equations for each pair*/
5786 ✗ (eqSystlst_nonflat, uniqueEqIndex) := List.map2Fold(exptl, makeSES_SIMPLE_ASSIGNwithArray, source, eqKind, uniqueEqIndex);
5787 ✗ eqSystlst := simeqn_complex::List.flatten(eqSystlst_nonflat);
5788
5789 ✗ tempvars := createTempVars(varLst, cr1, itempvars);
5790 ✗ then
5791 (eqSystlst, uniqueEqIndex, tempvars);
5792
5793 /* Record() = f() */
5794 case (DAE.RECORD(path=path, exps=expLst, ty= tp as DAE.T_COMPLEX(varLst=varLst)), e2)
5795 algorithm
5796 // check all crefs are on the lhs
5797 142 ht := HashSet.emptyHashSet();
5798 142 ht := List.fold(crefs, BaseHashSet.add, ht);
5799 142 expLst := Expression.traverseExpList(expLst, function Expression.expandCrefs(expandRecord=true), 0) "The routines generate bad code for arrays inside the record unless we expand them";
5800 142 List.foldAllValue(expLst, createSingleComplexEqnCode3, true, ht);
5801 131 (e2_1, _) := Expression.extendArrExp(e2, false);
5802
5803 // tmp = somexp
5804 131 ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
5805 131 cr1 := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(iuniqueEqIndex), tp, {});
5806 131 e1_1 := Expression.crefToExp(cr1);
5807 131 stms := DAE.STMT_ASSIGN(tp, e1_1, e2_1, source);
5808 131 simeqn_complex := SimCode.SES_ALGORITHM(iuniqueEqIndex, {stms}, eqKind);
5809 131 uniqueEqIndex := iuniqueEqIndex + 1;
5810
5811 /* Expand the varLst. Each var might be an array or record. */
5812 131 crexplst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr1);
5813 /* pair each of the expanded expressions to coressponding one*/
5814 131 exptl := List.zip(expLst, crexplst);
5815 /* Create residual equations for each pair*/
5816 131 (eqSystlst_nonflat, uniqueEqIndex) := List.map2Fold(exptl, makeSES_SIMPLE_ASSIGNwithArray, source, eqKind, uniqueEqIndex);
5817 131 eqSystlst := simeqn_complex::List.flatten(eqSystlst_nonflat);
5818
5819 131 tempvars := createTempVars(varLst, cr1, itempvars);
5820 131 then
5821 (eqSystlst, uniqueEqIndex, tempvars);
5822
5823 /* f() = Record() */
5824 case (e1, DAE.CALL(path=path, expLst=expLst, attr=DAE.CALL_ATTR(ty= tp as DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(path=rpath), varLst=varLst))))
5825 algorithm
5826
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 true := AbsynUtil.pathEqual(path, rpath);
5827 // check all crefs are on the rhs => turn
5828 ✗ ht := HashSet.emptyHashSet();
5829 ✗ ht := List.fold(crefs, BaseHashSet.add, ht);
5830 ✗ expLst := Expression.traverseExpList(expLst, function Expression.expandCrefs(expandRecord=true), 0) "The routines generate bad code for arrays inside the record unless we expand them";
5831 ✗ List.foldAllValue(expLst, createSingleComplexEqnCode3, true, ht);
5832 ✗ (e1_1, _) := Expression.extendArrExp(e1, false);
5833 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
5834 // tmp = f()
5835 ✗ ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
5836 ✗ cr1 := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(iuniqueEqIndex), tp, {});
5837 ✗ e2_1 := Expression.crefExp(cr1);
5838 ✗ stms := DAE.STMT_ASSIGN(tp, e2_1, e1_1, source);
5839 ✗ simeqn_complex := SimCode.SES_ALGORITHM(iuniqueEqIndex, {stms}, eqKind);
5840 ✗ uniqueEqIndex := iuniqueEqIndex + 1;
5841 // Record()=tmp
5842 ✗ crexplst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr1);
5843 ✗ exptl := List.zip(expLst, crexplst);
5844 ✗ (eqSystlst_nonflat, uniqueEqIndex) := List.map2Fold(exptl, makeSES_SIMPLE_ASSIGNwithArray, source, eqKind, uniqueEqIndex);
5845 ✗ eqSystlst := simeqn_complex::List.flatten(eqSystlst_nonflat);
5846 ✗ tempvars := createTempVars(varLst, cr1, itempvars);
5847 ✗ then
5848 (eqSystlst, uniqueEqIndex, tempvars);
5849
5850 /* f() = Record() */
5851 case (e1, DAE.RECORD(path=path, exps=expLst, ty= tp as DAE.T_COMPLEX(varLst=varLst)))
5852 algorithm
5853 // check all crefs are on the rhs => turn
5854 1 ht := HashSet.emptyHashSet();
5855 1 ht := List.fold(crefs, BaseHashSet.add, ht);
5856 1 expLst := Expression.traverseExpList(expLst, function Expression.expandCrefs(expandRecord=true), 0) "The routines generate bad code for arrays inside the record unless we expand them";
5857 1 List.foldAllValue(expLst, createSingleComplexEqnCode3, true, ht);
5858 1 (e1_1, _) := Expression.extendArrExp(e1, false);
5859 // true = ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr2);
5860 // tmp = f()
5861 1 ident := AbsynUtil.pathStringUnquoteReplaceDot(path, "_");
5862 1 cr1 := ComponentReferenceBasics.makeCrefIdent("$TMP_" + ident + intString(iuniqueEqIndex), tp, {});
5863 1 e2_1 := Expression.crefExp(cr1);
5864 1 stms := DAE.STMT_ASSIGN(tp, e2_1, e1_1, source);
5865 1 simeqn_complex := SimCode.SES_ALGORITHM(iuniqueEqIndex, {stms}, eqKind);
5866 1 uniqueEqIndex := iuniqueEqIndex + 1;
5867 // Record()=tmp
5868 1 crexplst := List.map1(varLst, Expression.generateCrefsExpFromExpVar, cr1);
5869 1 exptl := List.zip(expLst, crexplst);
5870 1 (eqSystlst_nonflat, uniqueEqIndex) := List.map2Fold(exptl, makeSES_SIMPLE_ASSIGNwithArray, source, eqKind, uniqueEqIndex);
5871 1 eqSystlst := simeqn_complex::List.flatten(eqSystlst_nonflat);
5872 1 tempvars := createTempVars(varLst, cr1, itempvars);
5873 1 then
5874 (eqSystlst, uniqueEqIndex, tempvars);
5875
5876 /* Tuple() = f() */
5877 case (e1 as DAE.TUPLE(expl), e2 as DAE.CALL())
5878 algorithm
5879 // debug
5880 // print("Tuple crefs Strings: "+ ComponentReferenceBasics.printComponentRefListStr(crefs) + "\n");
5881 // print(" = ExpList : " + ExpressionDump.printExpListStr(expl) + "\n");
5882 488 tp := Expression.typeof(e1);
5883
5884 //check that solved vars are on lhs
5885 488 ht := HashSet.emptyHashSet();
5886 488 ht := List.fold(crefs, BaseHashSet.add, ht);
5887 // check lhs depend on rhs
5888
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 486 times.
488 false := Expression.expHasCrefsNoPreOrStart(e2,crefs);
5889 486 List.foldAllValue(expl, createSingleComplexEqnCode3, true, ht);
5890
5891 972 eqSystlst := {SimCode.SES_ALGORITHM(iuniqueEqIndex, {DAE.STMT_TUPLE_ASSIGN(tp, expl, e2, source)}, eqKind)};
5892 486 uniqueEqIndex := iuniqueEqIndex + 1;
5893 486 then
5894 (eqSystlst, uniqueEqIndex, itempvars);
5895
5896 // Tuple(crefs) = Tuple(expl)
5897 case (DAE.TUPLE(expl), DAE.TUPLE(expl1))
5898 algorithm
5899 // debug
5900 // print("Tuple crefs Strings: "+ ComponentReferenceBasics.printComponentRefListStr(crefs) + "\n");
5901 // print(" = ExpList : " + ExpressionDump.printExpListStr(expl1) + "\n");
5902
5903 //check that all crefs are on lhs
5904 ✗ ht := HashSet.emptyHashSet();
5905 ✗ ht := List.fold(crefs, BaseHashSet.add, ht);
5906 ✗ List.foldAllValue(expl, createSingleComplexEqnCode3, true, ht);
5907
5908 // create all equations
5909 ✗ eqnLst := List.threadMap2(expl, expl1, BackendEquation.generateEquation, source, eqKind);
5910
5911 // generate SimCode equations therefore
5912 ✗ (eqSystlst, uniqueEqIndex, tempvars) := createEquationsfromList(eqnLst, inVars, iuniqueEqIndex, itempvars, iextra, genDiscrete);
5913 then
5914 (eqSystlst, uniqueEqIndex, tempvars);
5915
5916 // Tuple(expl) = Tuple(crefs)
5917 case (DAE.TUPLE(expl1), DAE.TUPLE(expl))
5918 algorithm
5919 // debug
5920 // print("Tuple crefs Strings: "+ ComponentReferenceBasics.printComponentRefListStr(crefs) + "\n");
5921 // print(" = ExpList : " + ExpressionDump.printExpListStr(expl1) + "\n");
5922
5923 //check that all crefs are on rhs
5924 ✗ ht := HashSet.emptyHashSet();
5925 ✗ ht := List.fold(crefs, BaseHashSet.add, ht);
5926 ✗ List.foldAllValue(expl, createSingleComplexEqnCode3, true, ht);
5927
5928 // create all equations
5929 ✗ eqnLst := List.threadMap2(expl, expl1, BackendEquation.generateEquation, source, eqKind);
5930
5931 // generate SimCode equations therefore
5932 ✗ (eqSystlst, uniqueEqIndex,_) := createEquationsfromList(eqnLst, inVars, iuniqueEqIndex, itempvars, iextra, genDiscrete);
5933 ✗ then
5934 (eqSystlst, uniqueEqIndex, itempvars);
5935
5936
5937 // failure
5938 case (e1, e2)
5939 algorithm
5940
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 true := Flags.isSet(Flags.FAILTRACE);
5941 ✗ s1 := ExpressionBasics.printExpStr(e1);
5942 ✗ s2 := ExpressionBasics.printExpStr(e2);
5943 ✗ s3 := ComponentReferenceBasics.printComponentRefListStr(crefs);
5944 ✗ s := stringAppendList({"function createSingleComplexEqnCode2 failed for: ", s1, " = " , s2, " solve for ", s3 });
5945 ✗ Debug.traceln(s);
5946 ✗ then
5947 fail();
5948 end matchcontinue;
5949 end createSingleComplexEqnCode2;
5950
5951 protected function createSingleComplexEqnCode3
5952 input DAE.Exp inExp;
5953 input HashSet.HashSet iht;
5954 output Boolean outB;
5955 output HashSet.HashSet oht;
5956 algorithm
5957 (outB, oht) := matchcontinue inExp
5958 local
5959 DAE.ComponentRef cr;
5960 HashSet.HashSet ht;
5961 list<DAE.ComponentRef> crefs;
5962 list<DAE.Exp> expLst;
5963
5964 case DAE.CREF(componentRef=cr) guard BaseHashSet.has(cr, iht)
5965 algorithm
5966 4338 ht := BaseHashSet.delete(cr, iht);
5967 then
5968 (true, ht);
5969 /* consider also array and record crefs */
5970 case DAE.CREF(componentRef=cr)
5971 algorithm
5972 142 crefs := ComponentReference.expandCref(cr, true);
5973
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 94 times.
142 false := valueEq({cr},crefs); // Not an expanded element
5974 94 expLst := List.map(crefs, Expression.crefExp);
5975 94 List.foldAllValue(expLst, createSingleComplexEqnCode3, true, iht);
5976 then (true, iht);
5977 case DAE.RCONST(_) then (true, iht);
5978 case DAE.ICONST(_) then (true, iht);
5979 case DAE.BCONST(_) then (true, iht);
5980 case DAE.CREF(componentRef=DAE.WILD()) then (true, iht);
5981 /* Consider also record constructor */
5982 case DAE.CALL(expLst=expLst) algorithm
5983 ✗ List.foldAllValue(expLst, createSingleComplexEqnCode3, true, iht);
5984 then (true, iht);
5985 case DAE.RECORD(exps=expLst) algorithm
5986 8 List.foldAllValue(expLst, createSingleComplexEqnCode3, true, iht);
5987 then (true, iht);
5988 /* consider also array type */
5989 case DAE.ARRAY(array=expLst) algorithm
5990 ✗ List.foldAllValue(expLst, createSingleComplexEqnCode3, true, iht);
5991 then (true, iht);
5992 else
5993 (false, iht);
5994 end matchcontinue;
5995 end createSingleComplexEqnCode3;
5996
5997 protected function createSingleArrayEqnCode
5998 input Boolean genDiscrete;
5999 input list<BackendDAE.Equation> inEquations;
6000 input list<BackendDAE.Var> inVars;
6001 input Integer iuniqueEqIndex;
6002 input list<SimCodeVar.SimVar> itempvars;
6003 input BackendDAE.Shared shared;
6004 output list<SimCode.SimEqSystem> equations_;
6005 output list<SimCode.SimEqSystem> noDiscequations;
6006 output Integer ouniqueEqIndex;
6007 output list<SimCodeVar.SimVar> otempvars;
6008 protected
6009 BackendDAE.Equation inEquation;
6010 algorithm
6011 // first replace der() to match them as cref $DER. below
6012 inEquation := match listHead(inEquations)
6013 case inEquation as BackendDAE.ARRAY_EQUATION(_)
6014 algorithm
6015 549 inEquation.left := Expression.replaceDerOpInExp(inEquation.left);
6016 549 inEquation.right := Expression.replaceDerOpInExp(inEquation.right);
6017 then inEquation;
6018 end match;
6019 (equations_, noDiscequations, ouniqueEqIndex, otempvars) := matchcontinue(inEquation, inVars)
6020 local
6021 list<Integer> ds;
6022 DAE.Exp e1, e2, lhse, rhse;
6023 list<DAE.Exp> expLst, expLstTmp;
6024 DAE.ComponentRef cr, cr_1, left;
6025 AvlTreePathFunction.Tree funcs;
6026 DAE.ElementSource source;
6027 SimCode.SimEqSystem equation_;
6028 list<SimCode.SimEqSystem> eqSystlst;
6029 Integer uniqueEqIndex;
6030 String str;
6031 list<DAE.Dimension> dims;
6032 list<SimCodeVar.SimVar> tempvars;
6033 BackendDAE.EquationAttributes eqAttr;
6034 list<DAE.ComponentRef> crefstmp;
6035 DAE.Type ty,basety;
6036 list<tuple<DAE.Exp, DAE.Exp>> exptl;
6037
6038 // A special case for built-in function stateSelectionSet
6039 case ((BackendDAE.ARRAY_EQUATION(right=rhse as DAE.CALL(path=Absyn.IDENT(name="$stateSelectionSet")), source=source, attr=eqAttr)), _)
6040 algorithm
6041 ✗ equation_ := SimCode.SES_ALGORITHM(iuniqueEqIndex, {DAE.STMT_NORETCALL(rhse, source)}, eqAttr);
6042 ✗ uniqueEqIndex := iuniqueEqIndex + 1;
6043 then ({equation_}, {equation_}, uniqueEqIndex, itempvars);
6044
6045 // A special case for built-in function initialStateSelect
6046 case ((BackendDAE.ARRAY_EQUATION(right=rhse as DAE.CALL(path=Absyn.IDENT(name="$initialStateSelect")), source=source, attr=eqAttr)), _)
6047 algorithm
6048 ✗ equation_ := SimCode.SES_ALGORITHM(iuniqueEqIndex, {DAE.STMT_NORETCALL(rhse, source)}, eqAttr);
6049 ✗ uniqueEqIndex := iuniqueEqIndex + 1;
6050 then ({equation_}, {equation_}, uniqueEqIndex, itempvars);
6051
6052 // An array equation
6053 // {z1,z2,..} = rhsexp -> solved for {z1,z2,..}
6054 // => tmp = rhsexp;
6055 // z1 = tmp[1]; z2 = tmp[2] ....
6056 case ((BackendDAE.ARRAY_EQUATION(dimSize=ds, left=e1, right=e2, source=source, attr=eqAttr)), _)
6057 guard Expression.isMatrix(e1) or Expression.isArray(e1)
6058 algorithm
6059 // Flattne multi-dimensional ARRAY{ARRAY} expressions
6060 126 expLst := Expression.flattenArrayExpToList(e1);
6061 // create the lhs tmp var
6062 126 ty := Expression.typeof(e1);
6063 126 (basety,dims) := TypesDump.flattenArrayType(ty);
6064 126 ty := DAE.T_ARRAY(basety, dims);
6065 126 left := ComponentReferenceBasics.makeCrefIdent("$TMP_" + intString(iuniqueEqIndex), ty, {});
6066
6067 126 lhse := DAE.CREF(left,ty);
6068 // Expand the tmp cref and create the list of rhs vars
6069 // to update the original lhs vars
6070 126 crefstmp := ComponentReference.expandCref(left, false);
6071 126 expLstTmp := List.map(crefstmp, Expression.crefExp);
6072 126 tempvars := createArrayTempVar(left, ds, expLstTmp, itempvars);
6073 // Create the simple assignments for the lhs vars from the tmp rhs's
6074 126 exptl := List.zip(expLst, expLstTmp);
6075 126 (eqSystlst, uniqueEqIndex) := List.map2Fold(exptl, makeSES_SIMPLE_ASSIGN, source, eqAttr, iuniqueEqIndex);
6076 // Create the array equation with the tmp var as lhs
6077 126 eqSystlst := SimCode.SES_ARRAY_CALL_ASSIGN(uniqueEqIndex, lhse, e2, source, eqAttr)::eqSystlst;
6078 126 then (eqSystlst, eqSystlst, uniqueEqIndex+1, tempvars);
6079
6080 // An array equation
6081 // cref = rhsexp
6082 case ((BackendDAE.ARRAY_EQUATION(left=e1 as DAE.CREF(cr_1, _), right=e2, source=source, attr=eqAttr)), BackendDAE.VAR(varName=cr)::_)
6083 guard ComponentReferenceBasics.crefEqual(cr_1, ComponentReferenceBasics.crefStripLastSubs(cr))
6084 algorithm
6085 418 (e1, _) := BackendDAEUtil.collateArrExp(e1, NONE());
6086 418 (e2, _) := BackendDAEUtil.collateArrExp(e2, NONE());
6087 418 equation_ := SimCode.SES_ARRAY_CALL_ASSIGN(iuniqueEqIndex, e1, e2, source, eqAttr);
6088 418 uniqueEqIndex := iuniqueEqIndex + 1;
6089 then ({equation_}, {equation_}, uniqueEqIndex, itempvars);
6090
6091 // An array equation
6092 // lhsexp = cref
6093 case ((BackendDAE.ARRAY_EQUATION(left=e1, right=e2 as DAE.CREF(cr_1, _), source=source, attr=eqAttr)), BackendDAE.VAR(varName=cr)::_)
6094 guard ComponentReferenceBasics.crefEqual(cr_1, ComponentReferenceBasics.crefStripLastSubs(cr))
6095 algorithm
6096 5 (e1, _) := BackendDAEUtil.collateArrExp(e1, NONE());
6097 5 (e2, _) := BackendDAEUtil.collateArrExp(e2, NONE());
6098 5 equation_ := SimCode.SES_ARRAY_CALL_ASSIGN(iuniqueEqIndex, e2, e1, source, eqAttr);
6099 5 uniqueEqIndex := iuniqueEqIndex + 1;
6100 then ({equation_}, {equation_}, uniqueEqIndex, itempvars);
6101
6102 // An array equation
6103 // lhsexp = rhsexp
6104 case ((BackendDAE.ARRAY_EQUATION(left=lhse, right=rhse, source=source, attr=eqAttr)), BackendDAE.VAR(varName=cr)::_)
6105 algorithm
6106 ✗ (lhse, _) := BackendDAEUtil.collateArrExp(lhse, NONE());
6107 ✗ (rhse, _) := BackendDAEUtil.collateArrExp(rhse, NONE());
6108 ✗ BackendDAE.SHARED(functionTree = funcs) := shared;
6109 ✗ e1 := Expression.crefExp(cr);
6110 ✗ e2 := ExpressionSolve.solve2(lhse, rhse, e1, SOME(funcs), SOME(iuniqueEqIndex), true, BackendDAEUtil.isSimulationDAE(shared));
6111 ✗ equation_ := SimCode.SES_ARRAY_CALL_ASSIGN(iuniqueEqIndex, e1, e2, source, eqAttr);
6112 ✗ uniqueEqIndex := iuniqueEqIndex + 1;
6113 then ({equation_}, {equation_}, uniqueEqIndex, itempvars);
6114
6115 // failure
6116 else algorithm
6117 ✗ BackendDAE.VAR(varName = cr)::_ := inVars;
6118 ✗ str := BackendDump.dumpEqnsStr(inEquations);
6119 ✗ str := "solving array equation: " + str + "\nfor variable: " + ComponentReferenceBasics.printComponentRefStr(cr) + ".";
6120 ✗ Error.addInternalError(str, sourceInfo());
6121 ✗ then fail();
6122 end matchcontinue;
6123 end createSingleArrayEqnCode;
6124
6125 protected function createSingleAlgorithmCode
6126 input list<BackendDAE.Equation> eqns;
6127 input list<BackendDAE.Var> vars;
6128 input Boolean skipDiscinAlgorithm;
6129 input Integer iuniqueEqIndex;
6130 input Option<Integer> clockIndex;
6131 output list<SimCode.SimEqSystem> equations_;
6132 output Integer ouniqueEqIndex;
6133 algorithm
6134 (equations_, ouniqueEqIndex) := matchcontinue (eqns, skipDiscinAlgorithm)
6135 local
6136 DAE.Algorithm alg;
6137 list<DAE.ComponentRef> solvedVars, algOutVars, knownOutputCrefs;
6138 String crefsStr, algStr;
6139 list<DAE.Statement> algStatements;
6140 DAE.ElementSource source;
6141 DAE.Expand crefExpand;
6142 BackendDAE.EquationAttributes eqAttr;
6143 list<SimCode.SimEqSystem> result;
6144 list<DAE.Exp> discreteVarsExp;
6145 constant Boolean debug = false;
6146
6147 // normal call
6148 case (BackendDAE.ALGORITHM(alg=alg, source = source, expand=crefExpand, attr=eqAttr)::_, false) algorithm
6149 505 solvedVars := List.map(vars, BackendVariable.varCref);
6150
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 502 times.
505 true := CheckModel.isCrefListAlgorithmOutput(solvedVars, alg, source, crefExpand);
6151 502 DAE.ALGORITHM_STMTS(algStatements) := BackendDAEUtil.collateAlgorithm(alg, NONE());
6152 1004 then ({SimCode.SES_ALGORITHM(iuniqueEqIndex, algStatements, eqAttr)}, iuniqueEqIndex+1);
6153
6154 // remove discrete Vars
6155 case (BackendDAE.ALGORITHM(alg=alg, source=source, expand=crefExpand, attr=eqAttr)::_, true) algorithm
6156 ✗ solvedVars := List.map(vars, BackendVariable.varCref);
6157 ✗ true := CheckModel.isCrefListAlgorithmOutput(solvedVars, alg, source, crefExpand);
6158 ✗ DAE.ALGORITHM_STMTS(algStatements) := BackendDAEUtil.collateAlgorithm(alg, NONE());
6159 ✗ algStatements := BackendDAEUtil.removeDiscreteAssignments(algStatements, BackendVariable.listVar1(vars));
6160 ✗ then ({SimCode.SES_ALGORITHM(iuniqueEqIndex, algStatements, eqAttr)}, iuniqueEqIndex+1);
6161
6162 // inverse Algorithm for single variable.
6163 case (BackendDAE.ALGORITHM(alg=alg, attr=eqAttr)::_, false) algorithm
6164 // We need to solve an inverse problem of an algorithm section.
6165 3 DAE.ALGORITHM_STMTS(algStatements) := BackendDAEUtil.collateAlgorithm(alg, NONE());
6166 3 algStatements := solveAlgorithmInverse(algStatements, vars);
6167 ✗ then ({SimCode.SES_ALGORITHM(iuniqueEqIndex, algStatements, eqAttr)}, iuniqueEqIndex+1);
6168
6169 // inverse algorithms
6170 case (BackendDAE.ALGORITHM(alg=alg as DAE.ALGORITHM_STMTS(algStatements), source=source, expand=crefExpand, attr=eqAttr)::_, _) algorithm
6171 if debug then
6172 print("createSingleAlgorithmCode ->\n");
6173 BackendDump.dumpAlgorithms({DAE.ALGORITHM_STMTS(algStatements)}, 0);
6174 end if;
6175
6176 // get and expand the searched variables
6177 3 solvedVars := List.map(vars, BackendVariable.varCref);
6178 3 solvedVars := List.unionList(List.map1(solvedVars, ComponentReference.expandCref, true));
6179 if debug then BackendDump.debugStrCrefLstStr("solvedVars : ", solvedVars, ", ", "\n"); end if;
6180
6181 // get and expand all other variables
6182 3 algOutVars := CheckModel.checkAndGetAlgorithmOutputs(alg, source, crefExpand);
6183 3 algOutVars := List.unionList(List.map1(algOutVars, ComponentReference.expandCref, true));
6184
6185 // the remaining quantity of all out vars to the solved vars
6186 3 knownOutputCrefs := List.setDifference(algOutVars, solvedVars);
6187
6188 // filter since are not solvable with non-linear solver
6189 3 solvedVars := List.map(List.filterOnTrue(vars, BackendVariable.isVarNonDiscrete), BackendVariable.varCref);
6190
6191 // discrete vars are added with there start value and by
6192 // event iteration we ensure that all variable are consistent
6193
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 discreteVarsExp := list(Expression.crefToExp(BackendVariable.varCref(v)) for v in List.filterOnTrue(vars, BackendVariable.isVarDiscrete));
6194 3 algStatements := BackendDAEOptimize.expandAlgorithmStmts(algStatements, discreteVarsExp, BackendVariable.listVar(vars), true);
6195
6196 if debug then
6197 BackendDump.debugStrCrefLstStr("algOutVars : ", algOutVars, ", ", "\n");
6198 BackendDump.debugStrCrefLstStr("filtered solvedVars: ", solvedVars, ", ", "\n");
6199 BackendDump.debugStrCrefLstStr("knownOutputCrefs : ", knownOutputCrefs, ", ", "\n");
6200 end if;
6201
6202 //Why should we have the same amount of solved vars and know vars?
6203 //true = intEq(listLength(solvedVars), listLength(knownOutputCrefs));
6204
6205 3 alg := DAE.ALGORITHM_STMTS(algStatements);
6206 3 DAE.ALGORITHM_STMTS(algStatements) := BackendDAEUtil.collateAlgorithm(alg, NONE());
6207
6208
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if not listEmpty(solvedVars) then
6209 6 result := {SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(iuniqueEqIndex+1,
6210 {SimCode.SES_INVERSE_ALGORITHM(iuniqueEqIndex, algStatements, knownOutputCrefs, true, eqAttr)},
6211 solvedVars, 0, listLength(vars), NONE(), false, false, false, clockIndex), NONE(), eqAttr)};
6212 3 ouniqueEqIndex := iuniqueEqIndex+2;
6213 else
6214 ✗ result := {SimCode.SES_INVERSE_ALGORITHM(iuniqueEqIndex, algStatements, knownOutputCrefs, false, eqAttr)};
6215 ✗ ouniqueEqIndex := iuniqueEqIndex+1;
6216 end if;
6217
6218 then (result, ouniqueEqIndex);
6219
6220 // Error message, inverse algorithms cannot be solved for discrete variables
6221 case (BackendDAE.ALGORITHM(alg=alg, source=source, expand=crefExpand)::_, _) algorithm
6222 ✗ solvedVars := List.map(vars, BackendVariable.varCref);
6223 ✗ false := CheckModel.isCrefListAlgorithmOutput(solvedVars, alg, source, crefExpand);
6224
6225 ✗ crefsStr := ComponentReferenceBasics.printComponentRefListStr(solvedVars);
6226 ✗ algStr := DAEDump.dumpAlgorithmsStr({DAE.ALGORITHM(alg, source)});
6227 ✗ Error.addInternalError("Inverse Algorithm needs to be solved for " + crefsStr + " in\n" + algStr + "Discrete variables are not supported yet.", sourceInfo());
6228 ✗ then fail();
6229
6230 // failure
6231 else algorithm
6232 ✗ Error.addInternalError("function createSingleAlgorithmCode failed", sourceInfo());
6233 ✗ then fail();
6234 end matchcontinue;
6235 end createSingleAlgorithmCode;
6236
6237 public function createInitialEquations "author: lochel"
6238 input BackendDAE.BackendDAE inInitDAE;
6239 input Integer iuniqueEqIndex;
6240 input list<SimCodeVar.SimVar> itempvars;
6241 output list<SimCode.SimEqSystem> outInitialEqns = {};
6242 output Integer ouniqueEqIndex = iuniqueEqIndex;
6243 output list<SimCodeVar.SimVar> otempvars = itempvars;
6244 protected
6245 BackendDAE.EquationArray removedEqs;
6246 list<SimCodeVar.SimVar> tempvars;
6247 Integer uniqueEqIndex;
6248 list<SimCode.SimEqSystem> allEquations, knownVarEquations, solvedEquations, removedEquations, aliasEquations;
6249 BackendDAE.EqSystems systs;
6250 BackendDAE.Shared shared;
6251 BackendDAE.Variables globalKnownVars, aliasVars;
6252 algorithm
6253 1069 BackendDAE.DAE(systs, shared as BackendDAE.SHARED(globalKnownVars=globalKnownVars, aliasVars=aliasVars)) := inInitDAE;
6254 1069 removedEqs := BackendDAEUtil.collapseRemovedEqs(inInitDAE);
6255 // generate equations from the known unfixed variables
6256 1069 (uniqueEqIndex, knownVarEquations) := BackendVariable.traverseBackendDAEVars(globalKnownVars, traverseKnVarsToSimEqSystem, (iuniqueEqIndex, {}));
6257 // generate equations from the solved systems
6258 1069 (uniqueEqIndex, _, _, _, solvedEquations, _, tempvars, _, _, _, _) :=
6259 createEquationsForSystems(systs, shared, uniqueEqIndex, {}, itempvars, 0, SimCode.NO_MAPPING(), true);
6260 // generate equations from the removed equations
6261 1069 (uniqueEqIndex, removedEquations) := BackendEquation.traverseEquationArray(removedEqs, traversedlowEqToSimEqSystem, (uniqueEqIndex, {}));
6262 // generate equations from the alias variables
6263 1069 (uniqueEqIndex, aliasEquations) := BackendVariable.traverseBackendDAEVars(aliasVars, traverseAliasVarsToSimEqSystem, (uniqueEqIndex, {}));
6264
6265 1069 allEquations := Dangerous.listReverseInPlace(aliasEquations);
6266 1069 allEquations := listAppend(removedEquations, allEquations);
6267 1069 allEquations := List.append_reverse(solvedEquations, allEquations);
6268 1069 allEquations := listAppend(knownVarEquations, allEquations);
6269
6270 // output
6271 outInitialEqns := allEquations;
6272 ouniqueEqIndex := uniqueEqIndex;
6273
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 otempvars := tempvars;
6274 end createInitialEquations;
6275
6276 public function createInitialEquations_lambda0 "author: lochel"
6277 input BackendDAE.BackendDAE inInitDAE;
6278 input Integer iuniqueEqIndex;
6279 input list<SimCodeVar.SimVar> itempvars;
6280 output list<SimCode.SimEqSystem> outInitialEqns = {};
6281 output Integer ouniqueEqIndex = iuniqueEqIndex;
6282 output list<SimCodeVar.SimVar> otempvars = itempvars;
6283 protected
6284 list<SimCodeVar.SimVar> tempvars;
6285 Integer uniqueEqIndex;
6286 list<SimCode.SimEqSystem> allEquations, knownEquations, solvedEquations, aliasEquations;
6287 BackendDAE.EqSystems systs;
6288 BackendDAE.Shared shared;
6289 BackendDAE.Variables globalKnownVars, aliasVars;
6290 algorithm
6291 35 BackendDAE.DAE(systs, shared as BackendDAE.SHARED(globalKnownVars=globalKnownVars, aliasVars=aliasVars)) := inInitDAE;
6292
6293 // generate equations from the known unfixed variables
6294 35 (uniqueEqIndex, knownEquations) := BackendVariable.traverseBackendDAEVars(globalKnownVars, traverseKnVarsToSimEqSystem, (iuniqueEqIndex, {}));
6295 // generate equations from the solved systems
6296 35 (uniqueEqIndex, _, _, _, solvedEquations, _, tempvars, _, _, _, _) :=
6297 createEquationsForSystems(systs, shared, uniqueEqIndex, {}, itempvars, 0, SimCode.NO_MAPPING(), true);
6298 // generate equations from the alias variables
6299 35 (uniqueEqIndex, aliasEquations) := BackendVariable.traverseBackendDAEVars(aliasVars, traverseAliasVarsToSimEqSystem, (uniqueEqIndex, {}));
6300 35 allEquations := List.append_reverse(solvedEquations, aliasEquations);
6301 35 allEquations := listAppend(knownEquations, allEquations);
6302
6303 // output
6304 outInitialEqns := allEquations;
6305 ouniqueEqIndex := uniqueEqIndex;
6306
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 otempvars := tempvars;
6307 end createInitialEquations_lambda0;
6308
6309 protected function traverseKnVarsToSimEqSystem
6310 "author: Frenkel TUD 2012-10"
6311 input BackendDAE.Var inVar;
6312 input tuple<Integer, list<SimCode.SimEqSystem>> inTpl;
6313 output BackendDAE.Var outVar;
6314 output tuple<Integer, list<SimCode.SimEqSystem>> outTpl;
6315 algorithm
6316 (outVar,outTpl) := matchcontinue (inVar,inTpl)
6317 local
6318 BackendDAE.Var v;
6319 Integer uniqueEqIndex;
6320 list<SimCode.SimEqSystem> eqns;
6321 DAE.ComponentRef cr;
6322 DAE.Exp exp;
6323 DAE.ElementSource source;
6324 case (v as BackendDAE.VAR(varName = cr, bindExp=SOME(exp), source=source), (uniqueEqIndex, eqns))
6325 algorithm
6326 //false = BackendVariable.varFixed(v);
6327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 false := BackendVariable.isVarOnTopLevelAndInput(v);
6328 4 then
6329 (v, (uniqueEqIndex+1, SimCode.SES_SIMPLE_ASSIGN(uniqueEqIndex, cr, exp, source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)::eqns));
6330 else (inVar,inTpl);
6331 end matchcontinue;
6332 end traverseKnVarsToSimEqSystem;
6333
6334 protected function traverseAliasVarsToSimEqSystem
6335 "author: Frenkel TUD 2012-10"
6336 input BackendDAE.Var inVar;
6337 input tuple<Integer, list<SimCode.SimEqSystem>> inTpl;
6338 output BackendDAE.Var outVar;
6339 output tuple<Integer, list<SimCode.SimEqSystem>> outTpl;
6340 algorithm
6341 (outVar,outTpl) := match (inVar,inTpl)
6342 local
6343 BackendDAE.Var v;
6344 Integer uniqueEqIndex;
6345 list<SimCode.SimEqSystem> eqns;
6346 DAE.ComponentRef cr;
6347 DAE.Exp exp;
6348 DAE.ElementSource source;
6349 case (v as BackendDAE.VAR(varName = cr, bindExp=SOME(exp), source=source), (uniqueEqIndex, eqns))
6350 ✗ then
6351 (v, (uniqueEqIndex+1, SimCode.SES_SIMPLE_ASSIGN(uniqueEqIndex, cr, exp, source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN)::eqns));
6352 end match;
6353 end traverseAliasVarsToSimEqSystem;
6354
6355 protected function dlowEqToSimEqSystem
6356 input BackendDAE.Equation inEquation;
6357 input Integer iuniqueEqIndex;
6358 output SimCode.SimEqSystem outEquation;
6359 output Integer ouniqueEqIndex;
6360 algorithm
6361 (outEquation, ouniqueEqIndex) := match inEquation
6362 local
6363 DAE.ComponentRef cr;
6364 DAE.Exp exp_, cond;
6365 DAE.Algorithm alg;
6366 list<DAE.Statement> algStatements;
6367 DAE.ElementSource source;
6368 BackendDAE.WhenEquation whenEquation, elseWhen;
6369 list<BackendDAE.WhenOperator> whenStmtLst;
6370 Option<BackendDAE.WhenEquation> oelseWhen;
6371 list<DAE.ComponentRef> conditions;
6372 Boolean initialCall;
6373 SimCode.SimEqSystem elseWhenEquation;
6374 Option<SimCode.SimEqSystem> oelseWhenSimEq;
6375 Integer uniqueEqIndex;
6376 BackendDAE.EquationAttributes eqAttr;
6377
6378 case BackendDAE.SOLVED_EQUATION(componentRef=cr, exp=exp_, source=source, attr=eqAttr)
6379 5162 then (SimCode.SES_SIMPLE_ASSIGN(iuniqueEqIndex, cr, exp_, source, eqAttr), iuniqueEqIndex+1);
6380
6381 // kabdelhak: how can this happen? maybe residual index has to be adapted here and not be 0
6382 case BackendDAE.RESIDUAL_EQUATION(exp=exp_, source=source, attr=eqAttr)
6383 ✗ then (SimCode.SES_RESIDUAL(iuniqueEqIndex, 0, exp_, source, eqAttr), iuniqueEqIndex+1);
6384
6385 case BackendDAE.ALGORITHM(alg=alg, attr=eqAttr) algorithm
6386 2556 DAE.ALGORITHM_STMTS(algStatements) := BackendDAEUtil.collateAlgorithm(alg, NONE());
6387 2556 then (SimCode.SES_ALGORITHM(iuniqueEqIndex, algStatements, eqAttr), iuniqueEqIndex+1);
6388
6389 // when eq
6390 case BackendDAE.WHEN_EQUATION(whenEquation=whenEquation, source=source, attr=eqAttr) algorithm
6391 77 BackendDAE.WHEN_STMTS(cond, whenStmtLst, oelseWhen) := whenEquation;
6392
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 1 time.
77 if isSome(oelseWhen) then
6393 1 SOME(elseWhen) := oelseWhen;
6394 1 (elseWhenEquation,uniqueEqIndex) := createElseWhenEquation(elseWhen, {}, iuniqueEqIndex+1, source, eqAttr);
6395 oelseWhenSimEq := SOME(elseWhenEquation);
6396 else
6397 76 uniqueEqIndex := iuniqueEqIndex+1;
6398 oelseWhenSimEq := NONE();
6399 end if;
6400 77 (conditions, initialCall) := BackendDAEUtil.getConditionList(cond);
6401
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
154 then
6402 (SimCode.SES_WHEN(iuniqueEqIndex, conditions, initialCall, whenStmtLst, oelseWhenSimEq, source, eqAttr), uniqueEqIndex);
6403
6404 else algorithm
6405 ✗ if Flags.isSet(Flags.FAILTRACE) then
6406 ✗ Error.addInternalError("function dlowEqToSimEqSystem failed.", sourceInfo());
6407 end if;
6408 ✗ then fail();
6409 end match;
6410 end dlowEqToSimEqSystem;
6411
6412 protected function dlowAlgToSimEqSystem
6413 input DAE.Algorithm inAlg;
6414 input Integer iuniqueEqIndex;
6415 output SimCode.SimEqSystem outEquation;
6416 output Integer ouniqueEqIndex;
6417 protected
6418 list<DAE.Statement> algStatements;
6419 algorithm
6420 31402 DAE.ALGORITHM_STMTS(algStatements) := BackendDAEUtil.collateAlgorithm(inAlg, NONE());
6421 31402 outEquation := SimCode.SES_ALGORITHM(iuniqueEqIndex, algStatements, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6422
1/2
✓ Branch 0 taken 31402 times.
✗ Branch 1 not taken.
31402 ouniqueEqIndex := iuniqueEqIndex+1;
6423 end dlowAlgToSimEqSystem;
6424
6425 public function createStartValueEquations
6426 input BackendDAE.EqSystem syst;
6427 input BackendDAE.Shared shared;
6428 input tuple<Integer, list<SimCode.SimEqSystem>, BackendDAE.Variables > acc;
6429 output tuple<Integer, list<SimCode.SimEqSystem>, BackendDAE.Variables> startValueEquations;
6430 algorithm
6431 startValueEquations := matchcontinue (syst, shared, acc)
6432 local
6433 BackendDAE.Variables vars, av;
6434 list<BackendDAE.Equation> startValueEquationsTmp2;
6435 list<SimCode.SimEqSystem> simeqns, simeqns1;
6436 Integer uniqueEqIndex;
6437 BackendDAE.Variables globalKnownVars;
6438
6439 case (BackendDAE.EQSYSTEM(orderedVars=vars), BackendDAE.SHARED(aliasVars=av), (uniqueEqIndex, simeqns, globalKnownVars)) algorithm
6440 // vars
6441 4484 (startValueEquationsTmp2, _, _) := BackendVariable.traverseBackendDAEVars(vars, createInitialAssignmentsFromStart, ({}, av, globalKnownVars));
6442 4484 startValueEquationsTmp2 := listReverse(startValueEquationsTmp2);
6443 // kvars
6444 // ((startValueEquationsTmp, _)) = BackendVariable.traverseBackendDAEVars(globalKnownVars, createInitialAssignmentsFromStart, ({}, av));
6445 // startValueEquationsTmp = listReverse(startValueEquationsTmp);
6446 // startValueEquationsTmp2 = listAppend(startValueEquationsTmp2, startValueEquationsTmp);
6447
6448 4484 (simeqns1, uniqueEqIndex) := List.mapFold(startValueEquationsTmp2, dlowEqToSimEqSystem, uniqueEqIndex);
6449 4484 then ((uniqueEqIndex, listAppend(simeqns1, simeqns), globalKnownVars));
6450
6451 else algorithm
6452 ✗ Error.addInternalError("function createStartValueEquations failed", sourceInfo());
6453 ✗ then fail();
6454 end matchcontinue;
6455 end createStartValueEquations;
6456
6457 public function createValueEquationsShared
6458 input BackendDAE.Shared shared;
6459 input Function valueFunction;
6460 input tuple<Integer, list<SimCode.SimEqSystem>> acc;
6461 output tuple<Integer, list<SimCode.SimEqSystem>> maxValueEquations;
6462
6463 partial function Function
6464 input BackendDAE.Var inVar;
6465 input tuple<list<BackendDAE.Equation>, BackendDAE.Variables> inTpl;
6466 output BackendDAE.Var outVar;
6467 output tuple<list<BackendDAE.Equation>, BackendDAE.Variables> outTpl;
6468 end Function;
6469 algorithm
6470 maxValueEquations := match(shared, acc)
6471 local
6472 list<BackendDAE.Equation> maxValueEquationsTmp;
6473 list<SimCode.SimEqSystem> simeqns, simeqns1;
6474 Integer uniqueEqIndex;
6475
6476 case (BackendDAE.SHARED(), (uniqueEqIndex, simeqns)) algorithm
6477 // vars
6478 3207 (maxValueEquationsTmp, _) := BackendVariable.traverseBackendDAEVars(shared.globalKnownVars, valueFunction, ({}, shared.aliasVars));
6479 3207 maxValueEquationsTmp := listReverse(maxValueEquationsTmp);
6480
6481 3207 (simeqns1, uniqueEqIndex) := List.mapFold(maxValueEquationsTmp, dlowEqToSimEqSystem, uniqueEqIndex);
6482 3207 then ((uniqueEqIndex, listAppend(simeqns1, simeqns)));
6483
6484 else algorithm
6485 ✗ Error.addInternalError("function createValueEquationsShared failed", sourceInfo());
6486 ✗ then fail();
6487 end match;
6488 end createValueEquationsShared;
6489
6490 public function createNominalValueEquations
6491 input BackendDAE.EqSystem syst;
6492 input BackendDAE.Shared shared;
6493 input tuple<Integer, list<SimCode.SimEqSystem>> acc;
6494 output tuple<Integer, list<SimCode.SimEqSystem>> nominalValueEquations;
6495 algorithm
6496 nominalValueEquations := match (syst, shared, acc)
6497 local
6498 list<BackendDAE.Equation> nominalValueEquationsTmp;
6499 list<SimCode.SimEqSystem> simeqns, simeqns1;
6500 Integer uniqueEqIndex;
6501
6502 case (BackendDAE.EQSYSTEM(), BackendDAE.SHARED(), (uniqueEqIndex, simeqns)) algorithm
6503 // vars
6504 3931 (nominalValueEquationsTmp, _) := BackendVariable.traverseBackendDAEVars(syst.orderedVars, createInitialAssignmentsFromNominal, ({}, shared.aliasVars));
6505 3931 nominalValueEquationsTmp := listReverse(nominalValueEquationsTmp);
6506
6507 3931 (simeqns1, uniqueEqIndex) := List.mapFold(nominalValueEquationsTmp, dlowEqToSimEqSystem, uniqueEqIndex);
6508 3931 then ((uniqueEqIndex, listAppend(simeqns1, simeqns)));
6509
6510 else algorithm
6511 ✗ Error.addInternalError("function createNominalValueEquations failed", sourceInfo());
6512 ✗ then fail();
6513 end match;
6514 end createNominalValueEquations;
6515
6516 public function createMinValueEquations
6517 input BackendDAE.EqSystem syst;
6518 input BackendDAE.Shared shared;
6519 input tuple<Integer, list<SimCode.SimEqSystem>> acc;
6520 output tuple<Integer, list<SimCode.SimEqSystem>> minValueEquations;
6521 algorithm
6522 minValueEquations := match (syst, shared, acc)
6523 local
6524 list<BackendDAE.Equation> minValueEquationsTmp;
6525 list<SimCode.SimEqSystem> simeqns, simeqns1;
6526 Integer uniqueEqIndex;
6527
6528 case (BackendDAE.EQSYSTEM(), BackendDAE.SHARED(), (uniqueEqIndex, simeqns)) algorithm
6529 // vars
6530 3931 (minValueEquationsTmp, _) := BackendVariable.traverseBackendDAEVars(syst.orderedVars, createInitialAssignmentsFromMin, ({}, shared.aliasVars));
6531 3931 minValueEquationsTmp := listReverse(minValueEquationsTmp);
6532
6533 3931 (simeqns1, uniqueEqIndex) := List.mapFold(minValueEquationsTmp, dlowEqToSimEqSystem, uniqueEqIndex);
6534 3931 then ((uniqueEqIndex, listAppend(simeqns1, simeqns)));
6535
6536 else algorithm
6537 ✗ Error.addInternalError("function createMinValueEquations failed", sourceInfo());
6538 ✗ then fail();
6539 end match;
6540 end createMinValueEquations;
6541
6542 public function createMaxValueEquations
6543 input BackendDAE.EqSystem syst;
6544 input BackendDAE.Shared shared;
6545 input tuple<Integer, list<SimCode.SimEqSystem>> acc;
6546 output tuple<Integer, list<SimCode.SimEqSystem>> maxValueEquations;
6547 algorithm
6548 maxValueEquations := match (syst, shared, acc)
6549 local
6550 list<BackendDAE.Equation> maxValueEquationsTmp;
6551 list<SimCode.SimEqSystem> simeqns, simeqns1;
6552 Integer uniqueEqIndex;
6553
6554 case (BackendDAE.EQSYSTEM(), BackendDAE.SHARED(), (uniqueEqIndex, simeqns)) algorithm
6555 // vars
6556 3931 (maxValueEquationsTmp, _) := BackendVariable.traverseBackendDAEVars(syst.orderedVars, createInitialAssignmentsFromMax, ({}, shared.aliasVars));
6557 3931 maxValueEquationsTmp := listReverse(maxValueEquationsTmp);
6558
6559 3931 (simeqns1, uniqueEqIndex) := List.mapFold(maxValueEquationsTmp, dlowEqToSimEqSystem, uniqueEqIndex);
6560 3931 then ((uniqueEqIndex, listAppend(simeqns1, simeqns)));
6561
6562 else algorithm
6563 ✗ Error.addInternalError("function createMaxValueEquations failed", sourceInfo());
6564 ✗ then fail();
6565 end match;
6566 end createMaxValueEquations;
6567
6568 protected function makeSolved_fromStartValue
6569 input BackendDAE.Var inVar;
6570 input Integer inUniqueEqIndex;
6571 output SimCode.SimEqSystem outSimEqn;
6572 output Integer outUniqueEqIndex;
6573 protected
6574 DAE.Exp e, varExp;
6575 DAE.ComponentRef cr;
6576 DAE.ElementSource source;
6577 algorithm
6578 141774 e := BackendVariable.varBindExpStartValueNoFail(inVar);
6579 141774 source := BackendVariable.getVarSource(inVar);
6580
2/2
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 141678 times.
141774 if Types.isArray(inVar.varType) then
6581 96 varExp := BackendVariable.varExp(inVar);
6582 96 outSimEqn := SimCode.SES_ARRAY_CALL_ASSIGN(inUniqueEqIndex, varExp, e, source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6583 else
6584 141678 cr := BackendVariable.varCref(inVar);
6585 141678 outSimEqn := SimCode.SES_SIMPLE_ASSIGN(inUniqueEqIndex, cr, e, source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6586 end if;
6587
1/2
✓ Branch 0 taken 141774 times.
✗ Branch 1 not taken.
141774 outUniqueEqIndex := inUniqueEqIndex+1;
6588 end makeSolved_fromStartValue;
6589
6590 public function createParameterEquations
6591 "Traverses the globalKnownVars and creates simEqns for the variable if necessary."
6592 input Integer inUniqueEqIndex;
6593 input list<SimCode.SimEqSystem> acc;
6594 input BackendDAE.Variables globalKnownVars;
6595 input list<DAE.Statement> parameterAsserts = {};
6596 output Integer outUniqueEqIndex = inUniqueEqIndex;
6597 output list<SimCode.SimEqSystem> outParameterEquations = {};
6598 output Integer nFixedParameters;
6599 protected
6600 list<SimCode.SimEqSystem> simvarasserts;
6601 list<DAE.Algorithm> varasserts;
6602 algorithm
6603 1069 (outUniqueEqIndex, outParameterEquations, varasserts, nFixedParameters, _) := BackendVariable.traverseBackendDAEVars(globalKnownVars, createSimEqsForGlobalKnownVars, (outUniqueEqIndex, outParameterEquations, {}, 0, HashSetExp.emptyHashSetSized(Util.nextPrime(globalKnownVars.numberOfVars))));
6604
6605
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1067 times.
1069 if Flags.isSet(Flags.PARAM_DLOW_DUMP) then
6606 2 print("\nparameters in order (" + intString(listLength(outParameterEquations)) + ")\n" + UNDERLINE + "\n");
6607 2 dumpSimEqSystemLst(listReverse(outParameterEquations), "\n");
6608 2 print("\n");
6609 end if;
6610
6611
4/4
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 1069 times.
✓ Branch 2 taken 575 times.
✓ Branch 3 taken 1069 times.
2219 varasserts := List.append_reverse(list(DAE.ALGORITHM_STMTS({a}) for a in parameterAsserts), varasserts);
6612 1069 varasserts := MetaModelica.Dangerous.listReverseInPlace(varasserts);
6613 1069 (simvarasserts, outUniqueEqIndex) := List.mapFold(varasserts, dlowAlgToSimEqSystem, outUniqueEqIndex);
6614
6615 1069 outParameterEquations := List.append_reverse(simvarasserts, outParameterEquations);
6616 1069 outParameterEquations := List.append_reverse(acc, outParameterEquations);
6617 1069 outParameterEquations := listReverse(outParameterEquations);
6618 end createParameterEquations;
6619
6620
6621 protected function createSimEqsForGlobalKnownVars
6622 "Decides if a simEq is generated from the globalKnownVar and creates it.
6623 author: ptaeuber"
6624 input output BackendDAE.Var globalKnownVar;
6625 input tuple<Integer, list<SimCode.SimEqSystem>, list<DAE.Algorithm>, Integer, HashSetExp.HashSet> inTuple;
6626 output tuple<Integer, list<SimCode.SimEqSystem>, list<DAE.Algorithm>, Integer, HashSetExp.HashSet> outTuple;
6627 protected
6628 Integer uniqueEqIndex, nFixedParameters;
6629 SimCode.SimEqSystem simEq;
6630 list<SimCode.SimEqSystem> parameterEquations;
6631 list<DAE.Algorithm> varasserts, varasserts2;
6632 HashSetExp.HashSet tplExpHT;
6633 algorithm
6634 185582 (uniqueEqIndex, parameterEquations, varasserts, nFixedParameters, tplExpHT) := inTuple;
6635
6636 // Get min/max and nominal asserts for fixed parameters
6637
4/4
✓ Branch 1 taken 134677 times.
✓ Branch 2 taken 50905 times.
✓ Branch 4 taken 132992 times.
✓ Branch 5 taken 1685 times.
185582 if BackendVariable.isParam(globalKnownVar) and BackendVariable.varFixed(globalKnownVar) then
6638 132992 varasserts2 := createVarAsserts(globalKnownVar);
6639 132992 varasserts := List.append_reverse(varasserts2, varasserts);
6640 132992 nFixedParameters := nFixedParameters + 1;
6641 end if;
6642
6643 // Create SimCode Equation for special globalKnownVars
6644
22/24
✓ Branch 1 taken 134677 times.
✓ Branch 2 taken 50905 times.
✓ Branch 4 taken 132992 times.
✓ Branch 5 taken 1685 times.
✓ Branch 7 taken 42068 times.
✓ Branch 8 taken 90924 times.
✓ Branch 10 taken 32826 times.
✓ Branch 11 taken 9242 times.
✓ Branch 13 taken 2914 times.
✓ Branch 14 taken 31597 times.
✓ Branch 16 taken 2898 times.
✓ Branch 17 taken 16 times.
✓ Branch 19 taken 43057 times.
✓ Branch 20 taken 42343 times.
✓ Branch 22 taken 42772 times.
✓ Branch 23 taken 285 times.
✓ Branch 25 taken 38 times.
✓ Branch 26 taken 42734 times.
✓ Branch 28 taken 61 times.
✓ Branch 29 taken 42605 times.
✓ Branch 31 taken 61 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 61 times.
✗ Branch 35 not taken.
185582 if (BackendVariable.isParam(globalKnownVar) and
6645 ((BackendVariable.varFixed(globalKnownVar) and (BackendVariable.isFinalOrProtectedVar(globalKnownVar) or BackendVariable.varHasNonConstantBindExpOrStartValue(globalKnownVar)))
6646 or (BackendVariable.varHasStartValue(globalKnownVar) and not BackendVariable.varHasConstantStartExp(globalKnownVar))))
6647 or (BackendVariable.isVarAlg(globalKnownVar) and not BackendVariable.isInput(globalKnownVar)) and BackendVariable.varFixed(globalKnownVar)
6648 or (BackendVariable.isExtObj(globalKnownVar) and BackendVariable.varHasBindExp(globalKnownVar) and BackendVariable.varFixed(globalKnownVar))
6649 then
6650
6651 () := match globalKnownVar
6652 local
6653 DAE.Exp call, tplExp, rec;
6654 DAE.ElementSource source;
6655 list<DAE.Exp> expl;
6656 DAE.Type tp;
6657
6658 // tuple_cse = call
6659 case BackendDAE.VAR(tplExp = SOME(tplExp as DAE.TUPLE(expl)))
6660 algorithm
6661
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 4 times.
32 if BaseHashSet.has(tplExp, tplExpHT) then
6662 28 outTuple := (uniqueEqIndex, parameterEquations, varasserts, nFixedParameters, tplExpHT);
6663 28 return;
6664 else
6665 4 tp := Expression.typeof(tplExp);
6666
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 SOME(call) := globalKnownVar.bindExp;
6667 4 source := BackendVariable.getVarSource(globalKnownVar);
6668 8 simEq := SimCode.SES_ALGORITHM(uniqueEqIndex, {DAE.STMT_TUPLE_ASSIGN(tp, expl, call, source)}, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6669 4 uniqueEqIndex := uniqueEqIndex+1;
6670 4 tplExpHT := BaseHashSet.add(tplExp, tplExpHT);
6671 end if;
6672 then ();
6673
6674 // record_cse = call
6675 case BackendDAE.VAR(tplExp = SOME(rec))
6676 algorithm
6677
2/2
✓ Branch 1 taken 1080 times.
✓ Branch 2 taken 91 times.
1171 if BaseHashSet.has(rec, tplExpHT) then
6678 1080 outTuple := (uniqueEqIndex, parameterEquations, varasserts, nFixedParameters, tplExpHT);
6679 1080 return;
6680 else
6681 91 tp := Expression.typeof(rec);
6682
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 91 times.
91 SOME(call) := globalKnownVar.bindExp;
6683 91 source := BackendVariable.getVarSource(globalKnownVar);
6684 182 simEq := SimCode.SES_ALGORITHM(uniqueEqIndex, {DAE.STMT_ASSIGN(tp, rec, call, source)}, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6685 91 uniqueEqIndex := uniqueEqIndex+1;
6686 91 tplExpHT := BaseHashSet.add(rec, tplExpHT);
6687 end if;
6688 then ();
6689
6690 // 'normal' globalKnownVars
6691 else
6692 algorithm
6693 141774 (simEq, uniqueEqIndex) := makeSolved_fromStartValue(globalKnownVar, uniqueEqIndex);
6694 then ();
6695 end match;
6696
6697 parameterEquations := simEq::parameterEquations;
6698 end if;
6699
6700 184474 outTuple := (uniqueEqIndex, parameterEquations, varasserts, nFixedParameters, tplExpHT);
6701 end createSimEqsForGlobalKnownVars;
6702
6703
6704 protected function createInitialAssignmentsFromStart
6705 input BackendDAE.Var inVar;
6706 input tuple<list<BackendDAE.Equation>, BackendDAE.Variables, BackendDAE.Variables> inTpl;
6707 output BackendDAE.Var outVar;
6708 output tuple<list<BackendDAE.Equation>, BackendDAE.Variables, BackendDAE.Variables> outTpl;
6709 algorithm
6710 (outVar,outTpl) := matchcontinue (inVar,inTpl)
6711 local
6712 BackendDAE.Var var;
6713 BackendDAE.Equation initialEquation;
6714 list<BackendDAE.Equation> eqns;
6715 DAE.ComponentRef cref;
6716 DAE.Exp startExp;
6717 DAE.ElementSource source;
6718 BackendDAE.Variables av;
6719 BackendDAE.Variables globalKnownVars;
6720 list<DAE.ComponentRef> parameters;
6721
6722 // also add an assignment for variables that have non-constant
6723 // expressions, e.g. parameter values, as start. NOTE: such start
6724 // attributes can then not be changed in the text file, since the initial
6725 // calc. will override those entries!
6726 case (var as BackendDAE.VAR(varName=cref, source=source), (eqns, av, globalKnownVars))
6727 algorithm
6728 71517 startExp := BackendVariable.varStartValueFail(var);
6729 23341 parameters := Expression.getAllCrefs(startExp);
6730
2/2
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 23241 times.
23341 true := BackendVariable.areAllCrefsPrimaryParameters(parameters, globalKnownVars) "add equations if the start value depends only on primary parameters";
6731
2/2
✓ Branch 1 taken 18747 times.
✓ Branch 2 taken 4494 times.
23241 false := Expression.isConst(startExp) "don't add equations for constant start values";
6732
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4494 times.
4494 SimCodeVar.NOALIAS() := getAliasVar(var, SOME(av));
6733 4494 initialEquation := BackendDAE.SOLVED_EQUATION(ComponentReference.crefPrefixStart(cref), startExp, source, BackendDAE.EQ_ATTR_DEFAULT_INITIAL);
6734 4494 then (var, (initialEquation :: eqns, av, globalKnownVars));
6735
6736 else (inVar,inTpl);
6737 end matchcontinue;
6738 end createInitialAssignmentsFromStart;
6739
6740 public function createInitialAssignmentsFromNominal "see also createInitialAssignmentsFromStart"
6741 input BackendDAE.Var inVar;
6742 input tuple<list<BackendDAE.Equation>, BackendDAE.Variables> inTpl;
6743 output BackendDAE.Var outVar;
6744 output tuple<list<BackendDAE.Equation>, BackendDAE.Variables> outTpl;
6745 algorithm
6746 (outVar,outTpl) := matchcontinue (inVar,inTpl)
6747 local
6748 BackendDAE.Var var;
6749 BackendDAE.Equation initialEquation;
6750 list<BackendDAE.Equation> eqns;
6751 DAE.ComponentRef name;
6752 DAE.Exp nominalv;
6753 DAE.ElementSource source;
6754 BackendDAE.Variables av;
6755
6756 case (var as BackendDAE.VAR(varName=name, source=source), (eqns, av)) algorithm
6757 253037 nominalv := BackendVariable.varNominalValueFail(var);
6758
2/2
✓ Branch 1 taken 13980 times.
✓ Branch 2 taken 621 times.
14601 false := Expression.isConst(nominalv);
6759
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 621 times.
621 SimCodeVar.NOALIAS() := getAliasVar(var, SOME(av));
6760 621 initialEquation := BackendDAE.SOLVED_EQUATION(name, nominalv, source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6761 621 then (var, (initialEquation :: eqns, av));
6762
6763 else (inVar,inTpl);
6764 end matchcontinue;
6765 end createInitialAssignmentsFromNominal;
6766
6767 public function createInitialAssignmentsFromMin "see also createInitialAssignmentsFromStart"
6768 input BackendDAE.Var inVar;
6769 input tuple<list<BackendDAE.Equation>, BackendDAE.Variables> inTpl;
6770 output BackendDAE.Var outVar;
6771 output tuple<list<BackendDAE.Equation>, BackendDAE.Variables> outTpl;
6772 algorithm
6773 (outVar,outTpl) := matchcontinue (inVar,inTpl)
6774 local
6775 BackendDAE.Var var;
6776 BackendDAE.Equation initialEquation;
6777 list<BackendDAE.Equation> eqns;
6778 DAE.ComponentRef name;
6779 DAE.Exp minv;
6780 DAE.ElementSource source;
6781 BackendDAE.Variables av;
6782
6783 case (var as BackendDAE.VAR(varName=name, source=source), (eqns, av)) algorithm
6784 253037 minv := BackendVariable.varMinValueFail(var);
6785
2/2
✓ Branch 1 taken 28308 times.
✓ Branch 2 taken 29 times.
28337 false := Expression.isConst(minv);
6786
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 SimCodeVar.NOALIAS() := getAliasVar(var, SOME(av));
6787 29 initialEquation := BackendDAE.SOLVED_EQUATION(name, minv, source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6788 29 then (var, (initialEquation :: eqns, av));
6789
6790 else (inVar,inTpl);
6791 end matchcontinue;
6792 end createInitialAssignmentsFromMin;
6793
6794 public function createInitialAssignmentsFromMax "see also createInitialAssignmentsFromStart"
6795 input BackendDAE.Var inVar;
6796 input tuple<list<BackendDAE.Equation>, BackendDAE.Variables> inTpl;
6797 output BackendDAE.Var outVar;
6798 output tuple<list<BackendDAE.Equation>, BackendDAE.Variables> outTpl;
6799 algorithm
6800 (outVar,outTpl) := matchcontinue (inVar,inTpl)
6801 local
6802 BackendDAE.Var var;
6803 BackendDAE.Equation initialEquation;
6804 list<BackendDAE.Equation> eqns;
6805 DAE.ComponentRef name;
6806 DAE.Exp maxv;
6807 DAE.ElementSource source;
6808 BackendDAE.Variables av;
6809
6810 case (var as BackendDAE.VAR(varName=name, source=source), (eqns, av)) algorithm
6811 253037 maxv := BackendVariable.varMaxValueFail(var);
6812
2/2
✓ Branch 1 taken 9607 times.
✓ Branch 2 taken 18 times.
9625 false := Expression.isConst(maxv);
6813
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 SimCodeVar.NOALIAS() := getAliasVar(var, SOME(av));
6814 18 initialEquation := BackendDAE.SOLVED_EQUATION(name, maxv, source, BackendDAE.EQ_ATTR_DEFAULT_UNKNOWN);
6815 18 then (var, (initialEquation :: eqns, av));
6816
6817 else (inVar,inTpl);
6818 end matchcontinue;
6819 end createInitialAssignmentsFromMax;
6820
6821 protected function createVarAsserts
6822 input BackendDAE.Var inVar;
6823 output list<DAE.Algorithm> outAlgs;
6824 algorithm
6825 132992 (_, outAlgs) := BackendVariable.getMinMaxAsserts(inVar);
6826 end createVarAsserts;
6827
6828 public function createModelInfo
6829 input Absyn.Path class_;
6830 input Absyn.Program program;
6831 input BackendDAE.BackendDAE dlow "simulation";
6832 input BackendDAE.BackendDAE inInitDAE "initialization";
6833 input list<SimCodeFunction.Function> functions;
6834 input list<String> labels;
6835 input Integer numStateSets;
6836 input Integer numSpatialDistributions;
6837 input String fileDir;
6838 input Integer nSubClock;
6839 input list<SimCodeVar.SimVar> tempVars;
6840 input Option<BackendDAE.BackendDAE> inInitDAE_lambda0 = NONE() "homotopy initialization at lambda = 0";
6841 output SimCode.ModelInfo modelInfo;
6842 protected
6843 String description, directory, version, author, license, copyright, fileName;
6844 SimCode.VarInfo varInfo;
6845 SimCodeVar.SimVars vars;
6846 Integer nx, ny, ndy, np, na, next, numOutVars, numInVars, ny_int, np_int, na_int, ny_bool, np_bool, numOptimizeConstraints, numOptimizeFinalConstraints, numRealInputVars;
6847 Integer na_bool, ny_string, np_string, na_string;
6848 Boolean hasLargeEqSystems;
6849 list<SimCode.UnitDefinition> unitDefinitions;
6850 constant Boolean debug = false;
6851 algorithm
6852 try
6853 // name = AbsynUtil.pathStringNoQual(class_);
6854 1069 directory := System.trim(fileDir, "\"");
6855 1069 version := System.trim(ProgramUtil.getNamedAnnotationExp(class_, program, Absyn.IDENT("version"), SOME(""), ProgramUtil.getDefaultComponentPrefixesModStr), "\"");
6856
6857 // fix issue https://github.com/OpenModelica/OpenModelica/issues/13169
6858 1069 author := System.trim(ProgramUtil.getNamedAnnotationExp(class_, program, Absyn.IDENT("__OpenModelica_author"), SOME(""), ProgramUtil.getDefaultComponentPrefixesModStr), "\"");
6859 1069 license := System.trim(ProgramUtil.getNamedAnnotationExp(class_, program, Absyn.IDENT("__OpenModelica_license"), SOME(""), ProgramUtil.getDefaultComponentPrefixesModStr), "\"");
6860 1069 copyright := System.trim(ProgramUtil.getNamedAnnotationExp(class_, program, Absyn.IDENT("__OpenModelica_copyright"), SOME(""), ProgramUtil.getDefaultComponentPrefixesModStr), "\"");
6861
6862 // get fileName as the filename and model name can be different which will be used in dataReconciliation Report
6863 1069 fileName := System.basename(AbsynUtil.classFilename(ProgramUtil.getPathedClassInProgram(class_, program)));
6864 1069 (vars, unitDefinitions) := createVars(dlow, inInitDAE, tempVars, inInitDAE_lambda0);
6865
6866 if debug then execStat("simCode: createVars"); end if;
6867 BackendDAE.DAE(shared=BackendDAE.SHARED(info=BackendDAE.EXTRA_INFO(description=description))) := dlow;
6868 1069 nx := SimCodeCodegenUtil.getNumScalars(vars.stateVars);
6869 1069 ny := SimCodeCodegenUtil.getNumScalars(vars.algVars);
6870 1069 ndy := SimCodeCodegenUtil.getNumScalars(vars.discreteAlgVars);
6871 1069 ny_int := SimCodeCodegenUtil.getNumScalars(vars.intAlgVars);
6872 1069 ny_bool := SimCodeCodegenUtil.getNumScalars(vars.boolAlgVars);
6873 1069 numOutVars := SimCodeCodegenUtil.getNumScalars(vars.outputVars);
6874 1069 numInVars := SimCodeCodegenUtil.getNumScalars(vars.inputVars);
6875 1069 na := SimCodeCodegenUtil.getNumScalars(vars.aliasVars);
6876 1069 na_int := SimCodeCodegenUtil.getNumScalars(vars.intAliasVars);
6877 1069 na_bool := SimCodeCodegenUtil.getNumScalars(vars.boolAliasVars);
6878 1069 np := SimCodeCodegenUtil.getNumScalars(vars.paramVars);
6879 1069 np_int := SimCodeCodegenUtil.getNumScalars(vars.intParamVars);
6880 1069 np_bool := SimCodeCodegenUtil.getNumScalars(vars.boolParamVars);
6881 1069 ny_string := SimCodeCodegenUtil.getNumScalars(vars.stringAlgVars);
6882 1069 np_string := SimCodeCodegenUtil.getNumScalars(vars.stringParamVars);
6883 1069 na_string := SimCodeCodegenUtil.getNumScalars(vars.stringAliasVars);
6884 1069 next := SimCodeCodegenUtil.getNumScalars(vars.extObjVars);
6885 1069 numOptimizeConstraints := SimCodeCodegenUtil.getNumScalars(vars.realOptimizeConstraintsVars);
6886 1069 numOptimizeFinalConstraints := SimCodeCodegenUtil.getNumScalars(vars.realOptimizeFinalConstraintsVars);
6887 1069 numRealInputVars := getNumberOfRealInputs(vars.inputVars);
6888 if debug then execStat("simCode: get lengths"); end if;
6889 1069 varInfo := createVarInfo(dlow, nx, ny, ndy, np, na, next, numOutVars, numInVars,
6890 ny_int, np_int, na_int, ny_bool, np_bool, na_bool, ny_string, np_string, na_string,
6891 numStateSets, numOptimizeConstraints, numOptimizeFinalConstraints, numRealInputVars);
6892 if debug then execStat("simCode: createVarInfo"); end if;
6893 1069 hasLargeEqSystems := hasLargeEquationSystems(dlow, inInitDAE);
6894 if debug then execStat("simCode: hasLargeEquationSystems"); end if;
6895
6/8
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 983 times.
✓ Branch 4 taken 1041 times.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1069 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1069 times.
4248 modelInfo := SimCode.MODELINFO(class_, dlow.shared.info.description, version, author, license, copyright, directory, fileName, varInfo, vars, functions,
6896 labels,
6897 if Flags.getConfigBool(Flags.BUILDING_FMU) then getResources(program.classes, dlow, inInitDAE) else {},
6898 List.sort(program.classes, AbsynUtil.classNameGreater),
6899 arrayLength(dlow.shared.partitionsInfo.basePartitions),
6900 arrayLength(dlow.shared.partitionsInfo.subPartitions),
6901 numSpatialDistributions + 1,
6902 hasLargeEqSystems, {}, {}, unitDefinitions);
6903 else
6904 ✗ Error.addInternalError("createModelInfo failed", sourceInfo());
6905 ✗ fail();
6906 end try;
6907 end createModelInfo;
6908
6909 protected function createVarInfo
6910 input BackendDAE.BackendDAE dlow;
6911 input Integer nx;
6912 input Integer ny;
6913 input Integer ndy;
6914 input Integer np;
6915 input Integer na;
6916 input Integer next;
6917 input Integer numOutVars;
6918 input Integer numInVars;
6919 input Integer ny_int;
6920 input Integer np_int;
6921 input Integer na_int;
6922 input Integer ny_bool;
6923 input Integer np_bool;
6924 input Integer na_bool;
6925 input Integer ny_string;
6926 input Integer np_string;
6927 input Integer na_string;
6928 input Integer numStateSets;
6929 input Integer numOptimizeConstraints;
6930 input Integer numOptimizeFinalConstraints;
6931 input Integer numRealInputVars;
6932 output SimCode.VarInfo varInfo;
6933 protected
6934 Integer numZeroCrossings, numTimeEvents, numRelations, numMathEventFunctions;
6935 algorithm
6936 1069 (numZeroCrossings, numTimeEvents, numRelations, numMathEventFunctions) := BackendDAEUtil.numberOfZeroCrossings(dlow);
6937 1069 varInfo := SimCode.VARINFO(numZeroCrossings, numTimeEvents, numRelations, numMathEventFunctions, nx, ny, ndy, ny_int, ny_bool, na, na_int, na_bool, np, np_int, np_bool, numOutVars, numInVars,
6938 next, ny_string, np_string, na_string, 0, 0, 0, 0, numStateSets,0,numOptimizeConstraints, numOptimizeFinalConstraints, 0, 0, 0, numRealInputVars, 0, 0);
6939 end createVarInfo;
6940
6941 protected function getNumberOfRealInputs
6942 "Get number of real inputs which will be used for Fmi cs to initialize size of real input"
6943 input list<SimCodeVar.SimVar> inputVars;
6944 output Integer numRealInputs = 0;
6945 algorithm
6946 //numScalars := List.applyAndFold(vars, intAdd, SimCodeUtilShared.getNumElems, 0);
6947
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 1069 times.
1370 for var in inputVars loop
6948
2/2
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 8 times.
301 if isRealInput(var) then
6949 293 numRealInputs := numRealInputs + 1;
6950 end if;
6951 end for;
6952 end getNumberOfRealInputs;
6953
6954 protected function isRealInput
6955 input SimCodeVar.SimVar var;
6956 output Boolean isReal;
6957 algorithm
6958 isReal := match var
6959 case SimCodeVar.SIMVAR(type_ = DAE.T_REAL()) then true; else false;
6960 end match;
6961 end isRealInput;
6962
6963 protected function evaluateStartValues"evaluates functions in the start values in the variableAttributes"
6964 input BackendDAE.Var inVar;
6965 input BackendDAE.Shared inShared;
6966 output BackendDAE.Var outVar;
6967 output BackendDAE.Shared outShared;
6968 algorithm
6969 (outVar,outShared) := matchcontinue(inVar,inShared)
6970 local
6971 Option<DAE.Exp> o1;
6972 Option<DAE.VariableAttributes> o2;
6973 DAE.Exp startValue, startValue_;
6974 list<DAE.Exp> exps;
6975 DAE.VariableAttributes attr, attr_;
6976 Values.Value value;
6977 FCore.Cache cache;
6978 FCore.Graph graph;
6979
6980 case(BackendDAE.VAR(bindExp = o1, values = o2), BackendDAE.SHARED(cache=cache, graph=graph))
6981 algorithm
6982
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 242305 times.
✓ Branch 2 taken 179536 times.
✓ Branch 3 taken 62769 times.
242305 if isSome(o1) then
6983 179536 startValue := Util.getOption(o1);
6984
6985 // If call with constant arguments then evaluate
6986 startValue_ := match startValue
6987 local DAE.Exp startValue1;
6988 case DAE.CALL(expLst=exps) guard Expression.isConstWorkList(exps)
6989 algorithm
6990 76 (_,value) := Ceval.ceval(cache, graph, startValue, false, Absyn.NO_MSG(),0);
6991 62 startValue1 := ValuesUtil.valueExp(value);
6992 then startValue1;
6993 case DAE.ASUB(DAE.CALL(expLst=exps),_) guard Expression.isConstWorkList(exps)
6994 algorithm
6995 ✗ (_,value) := Ceval.ceval(cache, graph, startValue, false, Absyn.NO_MSG(),0);
6996 ✗ startValue1 := ValuesUtil.valueExp(value);
6997 then startValue1;
6998 else startValue;
6999 end match;
7000
7001
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 179460 times.
179522 if not referenceEq(startValue, startValue_) then
7002 62 inVar.bindExp := SOME(startValue_);
7003 end if;
7004 end if;
7005
7006
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 242291 times.
✓ Branch 2 taken 242118 times.
✓ Branch 3 taken 173 times.
242291 if isSome(o2) then
7007 242118 attr := Util.getOption(o2);
7008 242118 attr_ := evaluateVariableAttributes(attr, inShared);
7009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 242118 times.
242118 if not referenceEq(attr, attr_) then
7010 ✗ inVar.values := SOME(attr_);
7011 end if;
7012 end if;
7013 then (inVar,inShared);
7014
7015 else
7016 14 then (inVar,inShared);
7017 end matchcontinue;
7018 end evaluateStartValues;
7019
7020 protected function evaluateVariableAttributes"evaluates functions in the start values, if necessary"
7021 input DAE.VariableAttributes attrIn;
7022 input BackendDAE.Shared shared;
7023 output DAE.VariableAttributes attrOut;
7024 algorithm
7025 attrOut := matchcontinue(attrIn, shared)
7026 local
7027 DAE.Exp exp, exp_;
7028 list<DAE.Exp> exps;
7029 Values.Value value;
7030 FCore.Cache cache;
7031 FCore.Graph graph;
7032
7033 case(DAE.VAR_ATTR_REAL(start=SOME(exp)), BackendDAE.SHARED(cache=cache, graph=graph))
7034 algorithm
7035 // If call with constant arguments then evaluate
7036 exp_ := match exp
7037 local DAE.Exp exp1;
7038 case DAE.CALL(expLst=exps) guard Expression.isConstWorkList(exps)
7039 algorithm
7040 ✗ (_,value) := Ceval.ceval(cache, graph, exp, false, Absyn.NO_MSG(),0);
7041 ✗ exp1 := ValuesUtil.valueExp(value);
7042 then exp1;
7043 case DAE.ASUB(DAE.CALL(expLst=exps),_) guard Expression.isConstWorkList(exps)
7044 algorithm
7045 ✗ (_,value) := Ceval.ceval(cache, graph, exp, false, Absyn.NO_MSG(),0);
7046 ✗ exp1 := ValuesUtil.valueExp(value);
7047 then exp1;
7048 else exp;
7049 end match;
7050
7051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68675 times.
68675 if not referenceEq(exp, exp_) then
7052 ✗ attrIn.start := SOME(exp);
7053 end if;
7054 then attrIn;
7055 else
7056 then attrIn;
7057 end matchcontinue;
7058 end evaluateVariableAttributes;
7059
7060 protected function preCalculateStartValues"calculates start values of variables which have none. The calculation is based on the start values of the vars in the assigned equation.
7061 This is a possible solution to equip vars with proper start values (would be computed anyway).
7062 In initial systems are nonlinear systems that use function calls that fail if the input has no proper start value.
7063 If the var is a torn var, there is no way to compute the proper start value before evaluating these function calls. The tearing method could consider this.
7064 author:Waurich TUD 2015-01"
7065 input BackendDAE.EqSystem systIn;
7066 input BackendDAE.Variables globalKnownVars;
7067 input BackendDAE.Shared shared;
7068 output BackendDAE.EqSystem systOut;
7069 protected
7070 list<Integer> varMap;
7071 array<Integer> varMapArr;
7072 BackendDAE.Variables vars, vars1;
7073 BackendDAE.EquationArray eqs;
7074 BackendDAE.AdjacencyMatrix mStart;
7075 BackendDAE.AdjacencyMatrixT mTStart;
7076 BackendDAE.EqSystem syst;
7077 list<BackendDAE.Var> varLst, noStartVarLst;
7078
7079 list<tuple<Integer,BackendDAE.VarKind>> stateInfo;
7080 list<Integer> stateIdcs;
7081 list<BackendDAE.VarKind> stateKinds;
7082 algorithm
7083 3916 vars := systIn.orderedVars;
7084 // set the varkInd for states to variable, reverse this later with the help of the stateinfo
7085 3916 stateInfo := List.fold1(List.intRange(BackendVariable.varsSize(vars)),getStateInfo,vars,{});// which var is a state and save the kind
7086 3916 (vars,_) := BackendVariable.traverseBackendDAEVarsWithUpdate(vars,setVarKindForStates,BackendDAE.VARIABLE());
7087
7088 // replace every var or param by its startvalue or binding, make a system of variables withput startvalues
7089
7090 3916 varLst := BackendVariable.varList(vars);
7091 3916 varMap := List.intRange(BackendVariable.varsSize(vars));
7092 3916 (noStartVarLst,varMap) := List.filterOnTrueSync(varLst, BackendVariable.varHasNoStartValue, varMap);
7093
7094 // insert start values for crefs and build adjacency matrix
7095 //BackendDump.dumpVariables(vars,"VAR BEFORE");
7096 //BackendDump.dumpEquationList(eqLst,"EQS BEFORE");
7097 3916 eqs := BackendEquation.copyEquationArray(systIn.orderedEqs);
7098 3916 BackendDAEUtil.traverseBackendDAEExpsEqns(eqs,replaceCrefWithStartValue,globalKnownVars);
7099 3916 BackendDAEUtil.traverseBackendDAEExpsEqns(eqs,replaceCrefWithStartValue,vars);
7100 //BackendDump.dumpEquationList(eqLst,"EQS AFTER");
7101 3916 vars1 := BackendVariable.listVar1(noStartVarLst);
7102 3916 syst := BackendDAEUtil.createEqSystem(vars1, eqs);
7103 3916 (syst, mStart, mTStart) := BackendDAEUtil.getAdjacencyMatrix(syst,BackendDAE.NORMAL(),NONE(), BackendDAEUtil.isInitializationDAE(shared));
7104 //BackendDump.dumpAdjacencyMatrix(mStart);
7105 //BackendDump.dumpAdjacencyMatrixT(mTStart);
7106 // solve equations for new start values and assign start values to variables
7107 3916 varMapArr := listArray(varMap);
7108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3916 times.
7832 vars := preCalculateStartValues1(List.intRange(arrayLength(mStart)), mStart, mTStart, varMapArr, eqs, vars);
7109
7110 // reset the varKinds for the states
7111 3916 stateIdcs := List.map(stateInfo, Util.tuple21);
7112 3916 stateKinds := List.map(stateInfo, Util.tuple22);
7113 3916 vars := List.threadFold(stateIdcs, stateKinds,BackendVariable.setVarKindForVar, vars);
7114
7115 //evaluate function calls in variable attributes (start-value)
7116 3916 (vars,_) := BackendVariable.traverseBackendDAEVarsWithUpdate(vars,evaluateStartValues,shared);
7117 //BackendDump.dumpVariables(vars,"VAR AFTER");
7118 3916 systOut := BackendDAEUtil.setEqSystVars(systIn, vars);
7119 end preCalculateStartValues;
7120
7121 protected function preCalculateStartValues1"try to solve the start equation for a var and set the resulting start value for it."
7122 input list<Integer> eqIndexes; // to be analyzed
7123 input BackendDAE.AdjacencyMatrix m;
7124 input BackendDAE.AdjacencyMatrix mT;
7125 input array<Integer> varMap;
7126 input BackendDAE.EquationArray eqs;
7127 input BackendDAE.Variables varsIn;
7128 output BackendDAE.Variables varArr = varsIn;
7129 protected
7130 Integer eqIdx, varIdx, varIdx0;
7131 list<Integer> rest, newEqIdcs, workList={};
7132 list<list<Integer>> mEntries;
7133 BackendDAE.Equation eq;
7134 BackendDAE.EquationArray eqArr;
7135 BackendDAE.Var var;
7136 list<BackendDAE.Equation> eqLst;
7137 DAE.ComponentRef cref;
7138 DAE.Exp lhs,rhs;
7139 algorithm
7140 // Implement a FIFO queue using two lists:
7141 // 'rest' contains the elements in the correct order while 'workList'
7142 // contains the rest of the elements in reverse order (in order to
7143 // easier add new elements to the queue)
7144 rest := eqIndexes;
7145
4/4
✓ Branch 0 taken 4653 times.
✓ Branch 1 taken 77160 times.
✓ Branch 2 taken 737 times.
✓ Branch 3 taken 3916 times.
81813 while not listEmpty(rest) or not listEmpty(workList) loop
7146
2/2
✓ Branch 0 taken 737 times.
✓ Branch 1 taken 77160 times.
77897 if listEmpty(rest) then
7147 737 rest := Dangerous.listReverseInPlace(workList);
7148 workList := {};
7149 end if;
7150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77897 times.
77897 eqIdx::rest := rest;
7151 try
7152
4/4
✓ Branch 1 taken 11946 times.
✓ Branch 2 taken 65951 times.
✓ Branch 3 taken 37272 times.
✓ Branch 4 taken 28679 times.
88456 {varIdx0} := arrayGet(m,eqIdx);
7153 28679 varIdx := arrayGet(varMap,intAbs(varIdx0));
7154 28679 var := BackendVariable.getVarAt(varArr,varIdx);
7155 28679 cref := BackendVariable.varCref(var);
7156 28679 eq := BackendEquation.get(eqs,eqIdx);
7157 //print("solve eq("+intString(eqIdx)+"): ");
7158 //BackendDump.printEquationList({eq});
7159 //print(" for var("+intString(varIdx0)+"): "+ComponentReferenceBasics.printComponentRefStr(cref)+"\n");
7160 28679 rhs := BackendEquation.getEquationRHS(eq);
7161 28371 lhs := BackendEquation.getEquationLHS(eq);
7162
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 26273 times.
28371 (rhs, {}) := ExpressionSolve.solve(lhs,rhs,Expression.crefExp(cref));
7163
2/2
✓ Branch 1 taken 10559 times.
✓ Branch 2 taken 15714 times.
26273 true := Expression.isScalarConst(rhs); // if this equation solves a variable, set this as a start value
7164 15714 var := BackendVariable.setVarStartValue(var,rhs);
7165 // Side-effect here. What if the rest fails?
7166 15714 varArr := BackendVariable.setVarAt(varArr,varIdx,var);
7167
7168 //check these equations again
7169 15714 newEqIdcs := arrayGet(mT,varIdx0);
7170 15714 newEqIdcs := List.deleteMemberOnTrue(eqIdx,newEqIdcs,intEq);
7171 15714 workList := List.append_reverse(newEqIdcs,workList);
7172 //print("check these equations again: "+stringDelimitList(List.map(newEqIdcs,intString),", ")+"\n");
7173 // replace the var with the new start value in these equations
7174 15714 eqLst := List.map1r(newEqIdcs,BackendEquation.get,eqs);
7175 15714 (eqLst,_) := BackendEquation.traverseExpsOfEquationList(eqLst,replaceCrefWithStartValue,varArr);
7176 15714 eqArr := List.threadFold(newEqIdcs,eqLst,BackendEquation.setAtIndexFirst,eqs);
7177 // update the adjacencyMatrix m and remove the idcs for the calculated var
7178 15714 mEntries := List.map1(newEqIdcs,Array.getIndexFirst,m);
7179
4/4
✓ Branch 0 taken 25200 times.
✓ Branch 1 taken 15714 times.
✓ Branch 2 taken 25200 times.
✓ Branch 3 taken 15714 times.
40914 mEntries := list(List.deleteMemberOnTrue(varIdx0, e, intEq) for e in mEntries);
7180 15714 List.threadMap1_0(newEqIdcs,mEntries,Array.updateIndexFirst,m);
7181 else
7182 end try;
7183 end while;
7184
7185 end preCalculateStartValues1;
7186
7187 protected function artificialVarKind "an artificial var is introduced during compilation and has a start-value that does not come from the model"
7188 input BackendDAE.VarKind inVarKind;
7189 output Boolean isVar;
7190 algorithm
7191 isVar := match inVarKind
7192 case BackendDAE.VARIABLE() then false;
7193 case BackendDAE.PARAM() then false;
7194 case BackendDAE.CONST() then false;
7195 case BackendDAE.DISCRETE() then false;
7196 case BackendDAE.STATE() then false;
7197 case BackendDAE.ALG_STATE() then false;
7198 case BackendDAE.DUMMY_STATE() then false;
7199 else true;
7200 end match;
7201 end artificialVarKind;
7202
7203 protected function replaceCrefWithStartValue "replaces a cref with its constant start value. Only if the BackendDAE.Varkind is not artificial in order to avoid guess-start values
7204 Waurich 2015-01"
7205 input DAE.Exp expIn;
7206 input BackendDAE.Variables varsIn;
7207 output DAE.Exp expOut;
7208 output BackendDAE.Variables varsOut;
7209 algorithm
7210 (expOut,varsOut) := matchcontinue expIn
7211 local
7212 Integer idx;
7213 Real r;
7214 Option<tuple<DAE.Exp,Integer,Integer>> optionExpisASUB;
7215 BackendDAE.Var var;
7216 DAE.ComponentRef cref;
7217 DAE.Exp exp, exp1, exp2, exp3, startTime, exp1_, exp2_, exp3_;
7218 DAE.Operator op;
7219 list<DAE.Exp> expLst;
7220
7221 case DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time"))
7222 algorithm
7223 then (DAE.RCONST(0.0),varsIn);
7224
7225 case DAE.CREF(componentRef=cref)
7226 algorithm
7227 541588 (var,_) := BackendVariable.getVarSingle(cref,varsIn);
7228
2/2
✓ Branch 2 taken 43060 times.
✓ Branch 3 taken 320066 times.
363126 true := not artificialVarKind(BackendVariable.varKind(var));// if its not of kind variable(), it is something artificial (DUMMY_DER,...) and the start value is not model based in that case
7229 // print("VAR: "+BackendDump.varString(var)+" -->");
7230
2/2
✓ Branch 1 taken 57028 times.
✓ Branch 2 taken 263038 times.
320066 if BackendVariable.varHasBindExp(var) /*and Expression.isConst(BackendVariable.varBindExp(var))*/ then
7231 57028 exp := BackendVariable.varBindExp(var);
7232
1/2
✓ Branch 1 taken 57028 times.
✗ Branch 2 not taken.
57028 if 0 <> ExpressionBasics.compare(exp, expIn) then
7233 // Or should this be an error? Replacing the start-value by itself...
7234 57028 exp := replaceCrefWithStartValue(exp,varsIn);
7235 end if;
7236 elseif BackendVariable.varHasStartValue(var) then
7237 105603 exp := BackendVariable.varStartValue(var);
7238 else
7239 exp := expIn;
7240 end if;
7241 //print(" has START:"+ ExpressionBasics.printExpStr(exp)+"\n");
7242
2/2
✓ Branch 1 taken 212436 times.
✓ Branch 2 taken 107630 times.
320066 exp := if Expression.isConst(exp) then exp else expIn;
7243 then (exp,varsIn);
7244
7245 case DAE.CALL(path=Absyn.IDENT("sample"), expLst=expLst)
7246 algorithm
7247 181 startTime := listGet(expLst,2);
7248 181 startTime := replaceCrefWithStartValue(startTime,varsIn);
7249
2/2
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 121 times.
181 if Expression.isZero(startTime) then
7250 exp := DAE.BCONST(true);
7251 else
7252 exp := expIn;
7253 end if;
7254 then (exp,varsIn);
7255
7256 case DAE.BINARY(exp1=exp1,operator=op,exp2=exp2)
7257 algorithm
7258 576958 exp1_ := replaceCrefWithStartValue(exp1,varsIn);
7259 576958 exp2_ := replaceCrefWithStartValue(exp2,varsIn);
7260
2/2
✓ Branch 0 taken 145730 times.
✓ Branch 1 taken 431228 times.
576958 if referenceEq(exp1, exp1_) and referenceEq(exp2,exp2_) then
7261 exp := expIn;
7262 else
7263 145730 exp := DAE.BINARY(exp1_,op,exp2_);
7264 end if;
7265 then (exp,varsIn);
7266
7267 case DAE.LBINARY(exp1=exp1,operator=op,exp2=exp2)
7268 algorithm
7269 7973 exp1_ := replaceCrefWithStartValue(exp1,varsIn);
7270 7973 exp2_ := replaceCrefWithStartValue(exp2,varsIn);
7271
2/2
✓ Branch 0 taken 868 times.
✓ Branch 1 taken 7105 times.
7973 if referenceEq(exp1, exp1_) and referenceEq(exp2,exp2_) then
7272 exp := expIn;
7273 else
7274 868 exp := DAE.LBINARY(exp1_,op,exp2_);
7275 end if;
7276 then (exp,varsIn);
7277
7278 // time > -1.0 or similar
7279 case DAE.RELATION(exp1=DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time")),operator=DAE.GREATER(),exp2=DAE.RCONST(real=r))
7280 algorithm
7281
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 4 times.
53 true := realLe(r,0.0);
7282 then (expIn,varsIn);
7283
7284 // time >= -1.0 or similar
7285 case DAE.RELATION(exp1=DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time")),operator=DAE.GREATEREQ(),exp2=DAE.RCONST(real=r))
7286 algorithm
7287
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 true := realLe(r,0.0);
7288 then (expIn,varsIn);
7289
7290 // -1.0 < time or similar
7291 case DAE.RELATION(exp1=DAE.RCONST(real=r),operator=DAE.LESS(),exp2=DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time")))
7292 algorithm
7293 ✗ true := realLe(r,0.0);
7294 then (expIn,varsIn);
7295
7296 // -1.0 <= time or similar
7297 case DAE.RELATION(exp1=DAE.RCONST(real=r),operator=DAE.LESSEQ(),exp2=DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time")))
7298 algorithm
7299 ✗ true := realLe(r,0.0);
7300 then (expIn,varsIn);
7301
7302 case DAE.RELATION(exp1=exp1,operator=op,exp2=exp2,index=idx,optionExpisASUB=optionExpisASUB)
7303 algorithm
7304 7512 exp1_ := replaceCrefWithStartValue(exp1,varsIn);
7305 7512 exp2_ := replaceCrefWithStartValue(exp2,varsIn);
7306
2/2
✓ Branch 0 taken 2316 times.
✓ Branch 1 taken 5196 times.
7512 if referenceEq(exp1, exp1_) and referenceEq(exp2,exp2_) then
7307 exp := expIn;
7308 else
7309 2316 exp := DAE.RELATION(exp1_,op,exp2_,idx,optionExpisASUB);
7310 end if;
7311 then (exp,varsIn);
7312
7313 case DAE.IFEXP(expCond=exp1,expThen=exp2,expElse=exp3)
7314 algorithm
7315 //print("IFEXP: "+ExpressionDump.dumpExpStr(expIn,0)+"\n");
7316 12057 exp1_ := replaceCrefWithStartValue(exp1,varsIn);
7317 12057 exp2_ := replaceCrefWithStartValue(exp2,varsIn);
7318 12057 exp3_ := replaceCrefWithStartValue(exp3,varsIn);
7319
4/4
✓ Branch 0 taken 7755 times.
✓ Branch 1 taken 4302 times.
✓ Branch 2 taken 915 times.
✓ Branch 3 taken 6840 times.
12057 if referenceEq(exp1, exp1_) and referenceEq(exp2,exp2_) and referenceEq(exp3,exp3_) then
7320 exp := expIn;
7321 else
7322 5217 exp := DAE.IFEXP(exp1_,exp2_,exp3_);
7323 end if;
7324 then (exp,varsIn);
7325
7326 else
7327 algorithm
7328 //print("Without START:"+ ExpressionBasics.printExpStr(expIn)+"\n");
7329 then (expIn,varsIn);
7330
7331 end matchcontinue;
7332 end replaceCrefWithStartValue;
7333
7334 protected function setVarKindForStates
7335 input BackendDAE.Var inVar;
7336 input BackendDAE.VarKind kindIn;
7337 output BackendDAE.Var outVar;
7338 output BackendDAE.VarKind kindOut;
7339 algorithm
7340 (outVar,kindOut) := match inVar
7341 local
7342 BackendDAE.Var var;
7343 case BackendDAE.VAR(varKind=BackendDAE.STATE(index=1))
7344 algorithm
7345 4270 var := BackendVariable.setVarKind(inVar,kindIn);
7346 then (var,kindIn);
7347 else
7348 then
7349 (inVar,kindIn);
7350 end match;
7351 end setVarKindForStates;
7352
7353 protected function getStateInfo
7354 input Integer idx;
7355 input BackendDAE.Variables vars;
7356 input list<tuple<Integer,BackendDAE.VarKind>> stateInfoIn;
7357 output list<tuple<Integer,BackendDAE.VarKind>> stateInfoOut;
7358 algorithm
7359 stateInfoOut := matchcontinue stateInfoIn
7360 local
7361 BackendDAE.Var var;
7362 BackendDAE.VarKind kind;
7363 case _
7364 algorithm
7365 61719 var := BackendVariable.getVarAt(vars,idx);
7366
2/2
✓ Branch 1 taken 57449 times.
✓ Branch 2 taken 4270 times.
61719 true := BackendVariable.isStateVar(var);
7367 4270 kind := BackendVariable.varKind(var);
7368 4270 then ((idx,kind)::stateInfoIn);
7369 else
7370 then (stateInfoIn);
7371 end matchcontinue;
7372 end getStateInfo;
7373
7374 protected type SimVarsIndex = enumeration(
7375 // In special order for fmi: real => intger => boolean => string => external
7376 state,
7377 derivative,
7378 alg,
7379 discreteAlg,
7380 realOptimizeConstraints,
7381 realOptimizeFinalConstraints,
7382
7383 param,
7384 alias,
7385
7386 intAlg,
7387 intParam,
7388 intAlias,
7389
7390 boolAlg,
7391 boolParam,
7392 boolAlias,
7393
7394 stringAlg,
7395 stringParam,
7396 stringAlias,
7397
7398 extObj,
7399
7400 inputs,
7401 outputs,
7402
7403 const,
7404 intConst,
7405 boolConst,
7406 stringConst,
7407
7408 sensitivity,
7409 setcvars,
7410 datareconinputvars,
7411 setBVars,
7412 jacobian,
7413 seed
7414 );
7415
7416 protected function createVars
7417 input BackendDAE.BackendDAE inSimDAE "simulation";
7418 input BackendDAE.BackendDAE inInitDAE "initialization";
7419 input list<SimCodeVar.SimVar> tempvars;
7420 input Option<BackendDAE.BackendDAE> inInitDAE_lambda0 = NONE() "homotopy initialization at lambda = 0";
7421 output SimCodeVar.SimVars outVars;
7422 output list<SimCode.UnitDefinition> unitDefinitions = {} "list of unitDefintions which are exported in modelDescription.xml";
7423 protected
7424 BackendDAE.Variables globalKnownVars1, globalKnownVars2;
7425 BackendDAE.Variables localKnownVars1, localKnownVars2;
7426 BackendDAE.Variables extvars1, extvars2;
7427 BackendDAE.Variables aliasVars1, aliasVars2;
7428 BackendDAE.EqSystems systs1, systs2;
7429 BackendDAE.Shared shared;
7430 Mutable<HashSet.HashSet> hs;
7431 Unit.UnitToStringTable unitStrings = UnorderedMap.new<String>(Unit.hash, Unit.isEqual);
7432 array<list<SimCodeVar.SimVar>> simVars = arrayCreate(size(SimVarsIndex,1), {});
7433 Integer primeSize;
7434 list<DAE.ComponentRef> iterationVarsLst;
7435 Option<UnorderedSet<DAE.ComponentRef>> iterationVars;
7436 Option<DAE.Exp> timeInterval = NONE();
7437
7438 constant Boolean debug = false;
7439 algorithm
7440 1069 BackendDAE.DAE(eqs=systs1, shared=shared as BackendDAE.SHARED(globalKnownVars=globalKnownVars1, localKnownVars=localKnownVars1, externalObjects=extvars1, aliasVars=aliasVars1)) := inSimDAE;
7441 1069 BackendDAE.DAE(eqs=systs2, shared=BackendDAE.SHARED(globalKnownVars=globalKnownVars2, localKnownVars=localKnownVars2, externalObjects=extvars2, aliasVars=aliasVars2)) := inInitDAE;
7442
7443 // get all iterationVars from initialization DAE which are needed for FMI-2.0 exports
7444 1069 (_, iterationVarsLst) := BackendDAEOptimize.listAllIterationVariables0(inInitDAE.eqs);
7445
2/2
✓ Branch 0 taken 362 times.
✓ Branch 1 taken 707 times.
1069 iterationVars := if listEmpty(iterationVarsLst) then NONE() else SOME(UnorderedSet.fromList(iterationVarsLst, ComponentReferenceBasics.hashComponentRef, ComponentReferenceBasics.crefEqual));
7446
7447 1069 primeSize := Util.nextPrime(
7448 integer(1.4*(
7449 BackendVariable.varsSize(globalKnownVars1)+BackendVariable.varsSize(globalKnownVars2)+
7450 BackendVariable.varsSize(localKnownVars1)+BackendVariable.varsSize(localKnownVars2)+
7451 BackendVariable.varsSize(aliasVars1)+BackendVariable.varsSize(aliasVars2)+
7452 BackendVariable.varsSize(extvars1)+BackendVariable.varsSize(extvars2)+
7453 BackendDAEUtil.daeSize(inSimDAE)+BackendDAEUtil.daeSize(inInitDAE)
7454 )));
7455 1069 hs := Mutable.create(HashSet.emptyHashSetSized(primeSize));
7456
7457
2/2
✓ Branch 1 taken 1058 times.
✓ Branch 2 taken 11 times.
1069 if not Flags.isSet(Flags.NO_START_CALC) then
7458 1058 systs1 := List.map2(systs1, preCalculateStartValues, globalKnownVars1, shared);
7459 1058 (globalKnownVars1, _) := BackendVariable.traverseBackendDAEVarsWithUpdate(globalKnownVars1, evaluateStartValues, shared);
7460 //systs2 := List.map1(systs2, preCalculateStartValues, globalKnownVars2);
7461 if debug then execStat("createVars: evaluateStartValues"); end if;
7462 end if;
7463
7464 // ### simulation ###
7465 // Extract from variable list
7466
4/4
✓ Branch 0 taken 3927 times.
✓ Branch 1 taken 1069 times.
✓ Branch 2 taken 3927 times.
✓ Branch 3 taken 1069 times.
4996 simVars := List.fold1(list(BackendVariable.daeVars(syst) for syst in systs1), BackendVariable.traverseBackendDAEVars, function extractVarsFromList(aliasVars=aliasVars1, vars=globalKnownVars1, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7467 if debug then execStat("createVars: variable list"); end if;
7468
7469 // Extract from known variable list
7470 1069 simVars := BackendVariable.traverseBackendDAEVars(globalKnownVars1, function extractVarsFromList(aliasVars=aliasVars1, vars=globalKnownVars1, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7471 if debug then execStat("createVars: known variable list"); end if;
7472
7473 // Extract from localKnownVars variable list
7474 1069 simVars := BackendVariable.traverseBackendDAEVars(localKnownVars1, function extractVarsFromList(aliasVars=aliasVars1, vars=globalKnownVars1, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7475 if debug then execStat("createVars: local known variables list"); end if;
7476
7477 // Extract from removed variable list
7478 1069 simVars := BackendVariable.traverseBackendDAEVars(aliasVars1, function extractVarsFromList(aliasVars=aliasVars1, vars=globalKnownVars1, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7479 if debug then execStat("createVars: removed variables list"); end if;
7480
7481 // Extract from external object list
7482 1069 simVars := BackendVariable.traverseBackendDAEVars(extvars1, function extractVarsFromList(aliasVars=aliasVars1, vars=globalKnownVars1, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7483 if debug then execStat("createVars: external object list"); end if;
7484
7485
7486 // ### initialization ###
7487 // Extract from variable list
7488
4/4
✓ Branch 0 taken 44679 times.
✓ Branch 1 taken 1069 times.
✓ Branch 2 taken 44679 times.
✓ Branch 3 taken 1069 times.
45748 simVars := List.fold1(list(BackendVariable.daeVars(syst) for syst in systs2), BackendVariable.traverseBackendDAEVars, function extractVarsFromList(aliasVars=aliasVars2, vars=globalKnownVars2, hs=hs, timeInterval=NONE(), iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7489 if debug then execStat("createVars: variable list (init)"); end if;
7490
7491 // Extract from known variable list
7492 1069 simVars := BackendVariable.traverseBackendDAEVars(globalKnownVars2, function extractVarsFromList(aliasVars=aliasVars2, vars=globalKnownVars2, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7493 if debug then execStat("createVars: known variable list (init)"); end if;
7494
7495 // Extract from localKnownVars variable list
7496 1069 simVars := BackendVariable.traverseBackendDAEVars(localKnownVars2, function extractVarsFromList(aliasVars=aliasVars2, vars=globalKnownVars2, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7497 if debug then execStat("createVars: local known variables list (init)"); end if;
7498
7499 // Extract from removed variable list
7500 1069 simVars := BackendVariable.traverseBackendDAEVars(aliasVars2, function extractVarsFromList(aliasVars=aliasVars2, vars=globalKnownVars2, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7501 if debug then execStat("createVars: removed variables list (init)"); end if;
7502
7503 // Extract from external object list
7504 1069 simVars := BackendVariable.traverseBackendDAEVars(extvars2, function extractVarsFromList(aliasVars=aliasVars2, vars=globalKnownVars2, hs=hs, timeInterval=shared.timeInterval, iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7505 if debug then execStat("createVars: external object list (init)"); end if;
7506
7507 // ### initialization at lambda = 0 ###
7508 // Its loops can be torn differently and introduce helper variables of their own.
7509
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1069 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 1036 times.
1069 if isSome(inInitDAE_lambda0) then
7510 33 SOME(BackendDAE.DAE(eqs=systs2, shared=BackendDAE.SHARED(globalKnownVars=globalKnownVars2, aliasVars=aliasVars2))) := inInitDAE_lambda0;
7511
4/4
✓ Branch 0 taken 2225 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 2225 times.
✓ Branch 3 taken 33 times.
2258 simVars := List.fold1(list(BackendVariable.daeVars(syst) for syst in systs2), BackendVariable.traverseBackendDAEVars, function extractVarsFromList(aliasVars=aliasVars2, vars=globalKnownVars2, hs=hs, timeInterval=NONE(), iterationVars=iterationVars, unitStrings=unitStrings), simVars);
7512 if debug then execStat("createVars: variable list (init lambda0)"); end if;
7513 end if;
7514
7515 1069 addTempVars(simVars, tempvars);
7516 if debug then execStat("createVars: addTempVars"); end if;
7517 //BaseHashSet.printHashSet(hs);
7518
7519 // sort variables on index
7520 1069 sortSimvars(simVars);
7521 if debug then execStat("createVars: sortSimVars"); end if;
7522
7523
4/4
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 1017 times.
✓ Branch 5 taken 48 times.
✓ Branch 6 taken 4 times.
1069 if (stringEqual(Config.simCodeTarget(), "Cpp")) then
7524 48 extendIncompleteArray(simVars);
7525 if debug then execStat("createVars: Cpp, extendIncompleteArray"); end if;
7526 end if;
7527
7528 // Index of algebraic and parameters need to fix due to separation of integer variables
7529 1069 fixIndex(simVars);
7530 1069 setVariableIndex(simVars);
7531
7532 // get the list of unitDefintions from simVars
7533 1069 unitDefinitions := getFmiUnitDefinitions(simVars);
7534
7535 if debug then execStat("createVars: fix and set index"); end if;
7536
7537 1069 outVars := SimCodeVar.SIMVARS(
7538 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.state)),
7539 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.derivative)),
7540 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.alg)),
7541 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.discreteAlg)),
7542 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.intAlg)),
7543 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.boolAlg)),
7544 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.inputs)),
7545 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.outputs)),
7546 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.alias)),
7547 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.intAlias)),
7548 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.boolAlias)),
7549 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.param)),
7550 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.intParam)),
7551 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.boolParam)),
7552 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.stringAlg)),
7553 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.stringParam)),
7554 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.stringAlias)),
7555 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.extObj)),
7556 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.const)),
7557 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.intConst)),
7558 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.boolConst)),
7559 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.stringConst)),
7560 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.jacobian)),
7561 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.seed)),
7562 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.realOptimizeConstraints)),
7563 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.realOptimizeFinalConstraints)),
7564 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.sensitivity)),
7565 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.setcvars)),
7566 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.datareconinputvars)),
7567 Dangerous.arrayGetNoBoundsChecking(simVars, Integer(SimVarsIndex.setBVars))
7568 );
7569 1069 GCExt.free(simVars);
7570 end createVars;
7571
7572 protected function extractVarsFromList
7573 input output BackendDAE.Var var;
7574 input output array<list<SimCodeVar.SimVar>> simVars;
7575 input BackendDAE.Variables aliasVars, vars;
7576 input Mutable<HashSet.HashSet> hs;
7577 input Option<DAE.Exp> timeInterval "from experiment annotation Interval, used for derivative nominal";
7578 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars "optional set of iterationVars in InitializationMode";
7579 input Unit.UnitToStringTable unitStrings;
7580 algorithm
7581
6/6
✓ Branch 1 taken 1542 times.
✓ Branch 2 taken 483133 times.
✓ Branch 4 taken 332 times.
✓ Branch 5 taken 482801 times.
✓ Branch 8 taken 125835 times.
✓ Branch 9 taken 356966 times.
484675 if if ComponentReference.isPreCref(var.varName) or ComponentReference.isStartCref(var.varName) then false else not BaseHashSet.has(var.varName, Mutable.access(hs)) then
7582 /* ignore variable, since they are treated by kind in the codegen */
7583
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 356966 times.
356966 if not BackendVariable.isAlgebraicOldState(var) then
7584 356966 extractVarFromVar(var, aliasVars, vars, simVars, hs, timeInterval, iterationVars, unitStrings);
7585 end if;
7586 // print("Added " + ComponentReferenceBasics.printComponentRefStr(inVar.varName) + "\n");
7587 //else
7588 // print("Skiped " + ComponentReferenceBasics.printComponentRefStr(inVar.varName) + "\n");
7589 end if;
7590 end extractVarsFromList;
7591
7592 // one dlow var can result in multiple simvars: input and output are a subset
7593 // of algvars for example
7594 protected function extractVarFromVar
7595 input BackendDAE.Var dlowVar;
7596 input BackendDAE.Variables inAliasVars;
7597 input BackendDAE.Variables inVars;
7598 input array<list<SimCodeVar.SimVar>> simVars;
7599 input Mutable<HashSet.HashSet> hs "all processed crefs";
7600 input Option<DAE.Exp> timeInterval "from experiment annotation Interval, used for derivative nominal";
7601 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars "optional set of iterationVars in InitializationMode" ;
7602 input Unit.UnitToStringTable unitStrings;
7603 protected
7604 list<DAE.ComponentRef> scalar_crefs;
7605 BackendDAE.Var scalarVar;
7606 DAE.Exp binding;
7607 list<Option<DAE.Exp>> scalar_bindings;
7608 Option<DAE.Exp> binding_opt;
7609 DAE.ComponentRef cref;
7610 algorithm
7611 // if it is an array parameter split it up. Do not do it for Cpp runtime, they can handle array parameters
7612
2/2
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 356836 times.
356966 if Types.isArray(dlowVar.varType) then
7613 130 scalar_crefs := ComponentReference.expandCref(dlowVar.varName, false);
7614
7615 // try to scalarize bindings
7616 try
7617 scalar_bindings := match dlowVar.bindExp
7618
4/4
✓ Branch 1 taken 246 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 246 times.
✓ Branch 4 taken 29 times.
275 case SOME(binding as DAE.ARRAY()) then list(SOME(b) for b in Expression.expandArray(binding));
7619 ✗ case SOME(binding as DAE.MATRIX()) then list(SOME(b) for b in Expression.expandArray(binding));
7620 101 else List.fill(dlowVar.bindExp, listLength(scalar_crefs));
7621 end match;
7622
7623 // fail if they are not of equal length
7624
2/2
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 129 times.
130 if listLength(scalar_bindings) <> listLength(scalar_crefs) then fail(); end if;
7625 else
7626 1 scalar_bindings := List.fill(dlowVar.bindExp, listLength(scalar_crefs));
7627 end try;
7628
7629
7630
3/4
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 96 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34 times.
130 if Config.simCodeTarget() <> "Cpp" then
7631 // Make sure the array does not get expanded again. The check for existence is made by the caller
7632 // of this function, extractVarsFromList. Which checks for the whole unxpanded array, which is never
7633 // actually added by itslef. So add it here manually.
7634 // We can do a check in extractVarFromVar2 for each expanded var as well.
7635 // However that means we do the exapnsion of the array for nothing. So add it here so that it does
7636 // not get expanded again (and every entry checked again).
7637 96 Mutable.update(hs, BaseHashSet.add(dlowVar.varName, Mutable.access(hs)));
7638
2/2
✓ Branch 1 taken 511 times.
✓ Branch 2 taken 96 times.
703 for tpl in List.zip(scalar_crefs, scalar_bindings) loop
7639 511 (cref, binding_opt) := tpl;
7640 // extract the expanded sim var
7641 511 scalarVar := BackendVariable.copyVarNewName(cref, dlowVar);
7642 511 scalarVar.bindExp := binding_opt;
7643 scalarVar.varType := ComponentReference.crefTypeFull(cref);
7644 511 extractVarFromVar2(scalarVar, inAliasVars, inVars, simVars, hs, timeInterval, iterationVars, unitStrings);
7645 end for;
7646 else
7647 // extract the sim var
7648 34 extractVarFromVar2(dlowVar, inAliasVars, inVars, simVars, hs, timeInterval, iterationVars, unitStrings);
7649 // add expanded array elements to processed crefs to avoid their redeclaration
7650 // as they may appear again as algebraic variables of the initialization problem
7651
2/2
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 34 times.
220 for cref in scalar_crefs loop
7652 186 Mutable.update(hs, BaseHashSet.add(cref, Mutable.access(hs)));
7653 end for;
7654 end if;
7655 else
7656 // extract the sim var
7657 356836 extractVarFromVar2(dlowVar, inAliasVars, inVars, simVars, hs, timeInterval, iterationVars, unitStrings);
7658 end if;
7659 end extractVarFromVar;
7660
7661 protected function getExportVar
7662 input BackendDAE.Var var;
7663 output Option<DAE.ComponentRef> exportVar = NONE();
7664 algorithm
7665
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 357381 times.
357381 if Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_NONE then
7666 // All variables will be exposed, even variables that are
7667 // introduced by the symbolic transformations. Hence, this is
7668 // intended to be used for debugging.
7669 ✗ exportVar := SOME(var.varName);
7670 elseif Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_INTERNAL then
7671 // All internal variables introduced by the symbolic
7672 // transformations are filtered out. Only the variables from the
7673 // actual Modelica model are exposed (with minor exceptions, e.g.
7674 // for state sets).
7675
4/6
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 8 times.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
9 if not (ComponentReference.isInternalCref(var.varName) and (not BackendVariable.isStateVar(var) and not BackendVariable.isClockedStateVar(var))) then
7676 8 exportVar := SOME(var.varName);
7677 end if;
7678 elseif Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_PROTECTED then
7679 // All protected model variables will be filtered out in addition
7680 // to --fmiFilter=internal (with minor exceptions. e.g.
7681 // for state sets.clocked states and previous vars)
7682
6/6
✓ Branch 1 taken 6455 times.
✓ Branch 2 taken 350910 times.
✓ Branch 4 taken 6423 times.
✓ Branch 5 taken 32 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 6421 times.
357365 if not (ComponentReference.isInternalCref(var.varName) and (not BackendVariable.isStateVar(var) and not BackendVariable.isClockedStateVar(var))) then
7683
8/8
✓ Branch 1 taken 77659 times.
✓ Branch 2 taken 273285 times.
✓ Branch 4 taken 77558 times.
✓ Branch 5 taken 101 times.
✓ Branch 7 taken 77557 times.
✓ Branch 8 taken 1 time.
✓ Branch 10 taken 1 time.
✓ Branch 11 taken 77556 times.
350944 if not (BackendVariable.isProtected(var) and (not BackendVariable.isStateVar(var) and not BackendVariable.isClockedStateVar(var) and not ComponentReference.isPreviousCref(var.varName))) then
7684 273388 exportVar := SOME(var.varName);
7685 end if;
7686 end if;
7687 elseif Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_BLACKBOX then
7688 // This option is used to hide everything except for inputs and
7689 // outputs. Additional variables that need to be present in the
7690 // modelDescription file for structrial reasons will have
7691 // concealed names.
7692
4/4
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 5 times.
7 if BackendVariable.isInput(var) or BackendVariable.isOutputVar(var) then
7693 2 exportVar := SOME(var.varName);
7694 elseif BackendVariable.isStateVar(var) or BackendVariable.isClockedStateVar(var) then
7695 1 exportVar := SOME(ComponentReference.getConcealedCref());
7696 end if;
7697 else
7698 ✗ Error.addInternalError("Unknown value detected for --fmiFilter", sourceInfo());
7699 ✗ fail();
7700 end if;
7701 end getExportVar;
7702
7703 // one dlow var can result in multiple simvars: input and output are a subset
7704 // of algvars for example
7705 protected function extractVarFromVar2
7706 input BackendDAE.Var dlowVar;
7707 input BackendDAE.Variables inAliasVars;
7708 input BackendDAE.Variables inVars;
7709 input array<list<SimCodeVar.SimVar>> simVars;
7710 input Mutable<HashSet.HashSet> hs "all processed crefs";
7711 input Option<DAE.Exp> timeInterval "from experiment annotation Interval, used for derivative nominal";
7712 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars "optional set of iterationVars in InitializationMode" ;
7713 input Unit.UnitToStringTable unitStrings;
7714 protected
7715 SimCodeVar.SimVar simVar;
7716 SimCodeVar.SimVar derivSimvar;
7717 Boolean isalias, isAlg, isParam, isConst;
7718 DAE.ComponentRef name;
7719 algorithm
7720 357381 simVar := dlowvarToSimvar(dlowVar, SOME(inAliasVars), inVars, iterationVars);
7721 357381 isalias := isAliasVar(simVar);
7722
7723 357381 simVar.exportVar := getExportVar(dlowVar);
7724
7725 // filter parameters of type string that doesn't have constant start values
7726
7/8
✓ Branch 1 taken 1717 times.
✓ Branch 2 taken 355664 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1717 times.
✓ Branch 5 taken 1714 times.
✓ Branch 6 taken 3 times.
✓ Branch 9 taken 243 times.
✓ Branch 10 taken 1471 times.
357381 if BackendVariable.isStringParam(dlowVar) and isSome(simVar.initialValue) and not Expression.isEvaluatedConst(Util.getOption(simVar.initialValue)) then
7727 243 simVar.exportVar := NONE();
7728 end if;
7729
7730 // update HashSet
7731 357381 Mutable.update(hs, BaseHashSet.add(simVar.name, Mutable.access(hs)));
7732
5/6
✓ Branch 0 taken 253558 times.
✓ Branch 1 taken 103823 times.
✓ Branch 3 taken 246035 times.
✓ Branch 4 taken 7523 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 246035 times.
357381 if (not isalias) and (BackendVariable.isStateVar(dlowVar) or BackendVariable.isAlgState(dlowVar)) then
7733 7523 derivSimvar := derVarFromStateVar(simVar, timeInterval, unitStrings, iterationVars);
7734 7523 Mutable.update(hs, BaseHashSet.add(derivSimvar.name, Mutable.access(hs)));
7735 else
7736 derivSimvar := simVar; // Just in case
7737 end if;
7738
7739 //print("\n name :" + ComponentReferenceBasics.printComponentRefStr(simVar.name) + "===>" + anyString(simVar.varKind) + "\n");
7740 // If it is an input variable, we give it an index
7741
4/4
✓ Branch 0 taken 253558 times.
✓ Branch 1 taken 103823 times.
✓ Branch 3 taken 301 times.
✓ Branch 4 taken 253257 times.
357381 if (not isalias) and BackendVariable.isVarOnTopLevelAndInputNoDerInput(dlowVar) then
7742 simVar := match simVar
7743 case SimCodeVar.SIMVAR()
7744 algorithm
7745 602 simVar.inputIndex := SOME(arrayCreate(1,-2));
7746 then simVar;
7747 else
7748 algorithm
7749 ✗ Error.addInternalError("Failed to SimCodeUtil.extractVarFromVar of input variable", sourceInfo());
7750 ✗ then fail();
7751 end match;
7752 end if;
7753
7754 // figure out in which lists to put it
7755 357381 isAlg := BackendVariable.isVarAlg(dlowVar);
7756 357381 isParam := BackendVariable.isParam(dlowVar);
7757 357381 isConst := BackendVariable.isConst(dlowVar);
7758
7759 // for inputs and outputs we have additional lists
7760
2/2
✓ Branch 1 taken 301 times.
✓ Branch 2 taken 357080 times.
357381 if BackendVariable.isVarOnTopLevelAndInputNoDerInput(dlowVar) then
7761 301 addSimVar(simVar, SimVarsIndex.inputs, simVars);
7762 end if;
7763
2/2
✓ Branch 1 taken 470 times.
✓ Branch 2 taken 356911 times.
357381 if BackendVariable.isVarOnTopLevelAndOutput(dlowVar) then
7764 470 addSimVar(simVar, SimVarsIndex.outputs, simVars);
7765 end if;
7766 // check if alias
7767
2/2
✓ Branch 0 taken 103823 times.
✓ Branch 1 taken 253558 times.
357381 if isalias then
7768
2/2
✓ Branch 1 taken 99041 times.
✓ Branch 2 taken 4782 times.
103823 if Types.isReal(dlowVar.varType) then
7769 99041 addSimVar(simVar, SimVarsIndex.alias, simVars);
7770 elseif Types.isInteger(dlowVar.varType) or Types.isEnumeration(dlowVar.varType) then
7771 3141 addSimVar(simVar, SimVarsIndex.intAlias, simVars);
7772 elseif Types.isBoolean(dlowVar.varType) then
7773 1619 addSimVar(simVar, SimVarsIndex.boolAlias, simVars);
7774 elseif Types.isString(dlowVar.varType) then
7775 9 addSimVar(simVar, SimVarsIndex.stringAlias, simVars);
7776 end if;
7777 // check for states
7778 elseif BackendVariable.isStateVar(dlowVar) or BackendVariable.isAlgState(dlowVar) then
7779 7523 addSimVar(simVar, SimVarsIndex.state, simVars);
7780 7523 addSimVar(derivSimvar, SimVarsIndex.derivative, simVars);
7781 // check for algebraic varibales
7782 elseif isAlg or isParam or isConst then
7783 // Real vars
7784
2/2
✓ Branch 1 taken 214809 times.
✓ Branch 2 taken 31094 times.
245903 if Types.isReal(dlowVar.varType) then
7785
2/2
✓ Branch 0 taken 96021 times.
✓ Branch 1 taken 118788 times.
214809 if isAlg then
7786
2/2
✓ Branch 1 taken 976 times.
✓ Branch 2 taken 95045 times.
96021 if BackendVariable.isVarDiscrete(dlowVar) then
7787 976 addSimVar(simVar, SimVarsIndex.discreteAlg, simVars);
7788 else
7789 95045 addSimVar(simVar, SimVarsIndex.alg, simVars);
7790 end if;
7791 elseif isParam then
7792 113762 addSimVar(simVar, SimVarsIndex.param, simVars);
7793 elseif isConst then
7794 5026 addSimVar(simVar, SimVarsIndex.const, simVars);
7795 end if;
7796 // Integer vars
7797 elseif Types.isInteger(dlowVar.varType) or Types.isEnumeration(dlowVar.varType) then
7798
2/2
✓ Branch 0 taken 4646 times.
✓ Branch 1 taken 10478 times.
15124 if isAlg then
7799 4646 addSimVar(simVar, SimVarsIndex.intAlg, simVars);
7800 elseif isParam then
7801 8333 addSimVar(simVar, SimVarsIndex.intParam, simVars);
7802 elseif isConst then
7803 2145 addSimVar(simVar, SimVarsIndex.intConst, simVars);
7804 end if;
7805 // Boolean vars
7806 elseif Types.isBoolean(dlowVar.varType) then
7807
2/2
✓ Branch 0 taken 2332 times.
✓ Branch 1 taken 11847 times.
14179 if isAlg then
7808 2332 addSimVar(simVar, SimVarsIndex.boolAlg, simVars);
7809 elseif isParam then
7810 11280 addSimVar(simVar, SimVarsIndex.boolParam, simVars);
7811 elseif isConst then
7812 567 addSimVar(simVar, SimVarsIndex.boolConst, simVars);
7813 end if;
7814 // String vars
7815 elseif Types.isString(dlowVar.varType) then
7816
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1750 times.
1791 if isAlg then
7817 41 addSimVar(simVar, SimVarsIndex.stringAlg, simVars);
7818 elseif isParam then
7819 1717 addSimVar(simVar, SimVarsIndex.stringParam, simVars);
7820 elseif isConst then
7821 33 addSimVar(simVar, SimVarsIndex.stringConst, simVars);
7822 end if;
7823 else
7824 ✗ Error.addInternalError("Failed to find SimVar list for Var: " + BackendDump.varString(dlowVar), sourceInfo());
7825 end if;
7826 // external objects
7827 elseif BackendVariable.isExtObj(dlowVar) then
7828 62 addSimVar(simVar, SimVarsIndex.extObj, simVars);
7829 // optimize constraints
7830 elseif BackendVariable.isRealOptimizeConstraintsVars(dlowVar) then
7831 39 addSimVar(simVar, SimVarsIndex.realOptimizeConstraints, simVars);
7832 // optimize final constraints vars
7833 elseif BackendVariable.isRealOptimizeFinalConstraintsVars(dlowVar) then
7834 15 addSimVar(simVar, SimVarsIndex.realOptimizeFinalConstraints, simVars);
7835 elseif BackendVariable.isOptInputVar(dlowVar) then
7836 16 addSimVar(simVar, SimVarsIndex.alg, simVars);
7837 elseif BackendVariable.isDAEmodeVar(dlowVar) then
7838 // skip, they are only used localy in daeMode
7839 else
7840 ✗ Error.addInternalError("Failed to find the correct SimVar list for Var: " + BackendDump.varString(dlowVar), sourceInfo());
7841 end if;
7842 end extractVarFromVar2;
7843
7844
7845 protected function addSimVar
7846 input SimCodeVar.SimVar simVar;
7847 input SimVarsIndex index;
7848 input array<list<SimCodeVar.SimVar>> simVars;
7849 algorithm
7850 365662 Dangerous.arrayUpdateNoBoundsChecking(simVars, Integer(index), simVar::Dangerous.arrayGetNoBoundsChecking(simVars, Integer(index)));
7851 end addSimVar;
7852
7853 protected function derVarFromStateVar
7854 input SimCodeVar.SimVar state;
7855 input Option<DAE.Exp> timeInterval "from experiment annotation Interval, used for derivative nominal";
7856 input Unit.UnitToStringTable unitStrings "filled by Unit.addKnownUnitsInverse on first use";
7857 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars = NONE() "optional set of iterationVars in InitializationMode";
7858 output SimCodeVar.SimVar deriv = state;
7859 protected
7860 Unit.Unit unit;
7861 DAE.Exp nominal;
7862 algorithm
7863 7523 deriv.arrayCref := Util.applyOption(deriv.arrayCref, ComponentReference.crefPrefixDer);
7864 deriv.name := ComponentReference.crefPrefixDer(deriv.name);
7865 deriv.varKind := BackendDAE.STATE_DER();
7866
3/4
✓ Branch 0 taken 2523 times.
✓ Branch 1 taken 5000 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2523 times.
7523 if deriv.comment <> "" then
7867 10000 deriv.comment := "der(" + deriv.comment + ")";
7868 end if;
7869 try
7870 7523 unit := Unit.parseUnitString(deriv.unit);
7871 1988 unit := Unit.unitDiv(unit, NFUnit.SECOND);
7872
2/2
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 1780 times.
1988 if UnorderedMap.isEmpty(unitStrings) then
7873 208 Unit.addKnownUnitsInverse(unitStrings);
7874 end if;
7875 1988 deriv.unit := Unit.unitString(unit, unitStrings);
7876 else
7877 5535 deriv.unit := "";
7878 end try;
7879 7523 deriv.displayUnit := "";
7880 deriv.minValue := NONE();
7881 deriv.maxValue := NONE();
7882
7883 // Only give nominal to iteration variables
7884
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 7523 times.
✓ Branch 2 taken 1949 times.
✓ Branch 3 taken 5574 times.
✓ Branch 6 taken 261 times.
✓ Branch 7 taken 1688 times.
7523 if isSome(iterationVars) and UnorderedSet.contains(deriv.name, Util.getOption(iterationVars)) then
7885 // guess a nominal value for the derivative, if we have that information
7886 // der(x).nominal = x.nominal/simulationInterval
7887 // otherwise just keep the nominal value of the state
7888
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
✓ Branch 2 taken 255 times.
✓ Branch 3 taken 6 times.
261 if isSome(timeInterval) then
7889 255 nominal := Expression.makeDiv(Util.getOptionOrDefault(deriv.nominalValue, DAE.RCONST(1.0)), Util.getOption(timeInterval));
7890 510 deriv.nominalValue := SOME(ExpressionSimplify.simplify(nominal));
7891 end if;
7892 else
7893 7262 deriv.nominalValue := NONE();
7894 end if;
7895
7896 7523 deriv.isFixed := false;
7897 deriv.aliasvar := SimCodeVar.NOALIAS();
7898 deriv.causality := SOME(SimCodeVar.LOCAL());
7899 deriv.variable_index := NONE();
7900 deriv.isValueChangeable := false;
7901 deriv.variability := SOME(SimCodeVar.CONTINUOUS());
7902 // derivativeVars can be either APPROX or CALUCALTED
7903
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 7523 times.
✓ Branch 2 taken 1949 times.
✓ Branch 3 taken 5574 times.
✓ Branch 6 taken 261 times.
✓ Branch 7 taken 1688 times.
7523 if isSome(iterationVars) and UnorderedSet.contains(deriv.name, Util.getOption(iterationVars)) then // Check Variable is an iterationVar
7904 261 deriv.initial_ := SOME(SimCodeVar.APPROX());
7905 deriv.initialValue := SOME(DAE.RCONST(0.0));
7906 else
7907 7262 deriv.initial_ := SOME(SimCodeVar.CALCULATED()); // default value
7908 deriv.initialValue := NONE();
7909 end if;
7910 // check for fmiFilter = blackBox and generate concealed names for derivative vars
7911
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 7522 times.
7523 if Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_BLACKBOX then
7912 2 deriv.exportVar := SOME(ComponentReference.getConcealedCref());
7913 else
7914 7522 deriv.exportVar := SOME(deriv.name);
7915 end if;
7916 end derVarFromStateVar;
7917
7918 public function dumpVarLst"dumps a list of SimVars to stdout.
7919 author:Waurich TUD 2014-05"
7920 input list<SimCodeVar.SimVar> varLst;
7921 input String header;
7922 protected
7923 SimCodeVar.SimVar var;
7924 algorithm
7925
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 25 times.
206 if not listEmpty(varLst) then
7926 25 print(header+"\n----------------------\n");
7927
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 25 times.
194 for var in varLst loop
7928 169 print(SimCodeCodegenUtil.simVarString(var)+"\n");
7929 end for;
7930 end if;
7931 end dumpVarLst;
7932
7933 public function printVarLstCrefs
7934 input list<SimCodeVar.SimVar> inVars;
7935 output String str;
7936 protected
7937 DAE.ComponentRef cref;
7938 SimCodeVar.SimVar var;
7939 algorithm
7940 str := "\t\tcrefs: ";
7941 ✗ for var in inVars loop
7942 ✗ SimCodeVar.SIMVAR(name= cref) := var;
7943 ✗ str := str + ComponentReference.debugPrintComponentRefTypeStr(cref) + " , ";
7944 end for;
7945 end printVarLstCrefs;
7946
7947 protected function dumpVariablesString "dumps a list of SimCode.Variables to stdout.
7948 author: Waurich TUD 2014-09"
7949 input list<SimCodeFunction.Variable> vars;
7950 input String delimiter;
7951 algorithm
7952 () := match vars
7953 local
7954 String s1,s2;
7955 DAE.ComponentRef cref;
7956 DAE.Type ty;
7957 DAE.VarKind kind;
7958 list<SimCodeFunction.Variable> rest;
7959 case {}
7960 algorithm
7961 then();
7962 case SimCodeFunction.VARIABLE(name=cref,ty=ty,kind=kind)::rest
7963 algorithm
7964 6 (s1,_) := DAEDump.printTypeStr(ty);
7965 6 s1 := TypesDump.printTypeStr(ty);
7966 6 s2 := DAEDump.dumpKindStr(kind);
7967 6 print(ComponentReferenceBasics.printComponentRefStr(cref)+" ("+s1+", "+s2+") "+delimiter);
7968 6 dumpVariablesString(rest,delimiter);
7969 then ();
7970 case SimCodeFunction.FUNCTION_PTR(name=s1)::rest
7971 algorithm
7972 ✗ print("<func> " + s1 + delimiter);
7973 ✗ dumpVariablesString(rest,delimiter);
7974 then ();
7975 else
7976 algorithm
7977 ✗ print("<unknown>" + delimiter);
7978 then ();
7979 end match;
7980 end dumpVariablesString;
7981
7982 public function dumpModelInfo"dumps the SimVars to stdout
7983 author:Waurich TUD 2014-05"
7984 input SimCode.ModelInfo modelInfo;
7985 protected
7986 Integer nsv,nalgv;
7987 SimCode.VarInfo varInfo;
7988 SimCodeVar.SimVars simVars;
7989 list<SimCodeVar.SimVar> stateVars;
7990 list<SimCodeVar.SimVar> derivativeVars;
7991 list<SimCodeVar.SimVar> algVars;
7992 list<SimCodeVar.SimVar> discreteAlgVars;
7993 list<SimCodeVar.SimVar> intAlgVars;
7994 list<SimCodeVar.SimVar> boolAlgVars;
7995 list<SimCodeVar.SimVar> aliasVars;
7996 list<SimCodeVar.SimVar> intAliasVars;
7997 list<SimCodeVar.SimVar> paramVars;
7998 list<SimCodeVar.SimVar> boolParamVars;
7999 list<SimCodeVar.SimVar> intParamVars;
8000 list<SimCodeVar.SimVar> extObjVars;
8001 list<SimCodeVar.SimVar> constVars;
8002 list<SimCodeVar.SimVar> intConstVars;
8003 list<SimCodeVar.SimVar> stringConstVars;
8004 list<SimCodeFunction.Function> functions;
8005 algorithm
8006 7 SimCode.MODELINFO(vars=simVars, varInfo=varInfo, functions=functions) := modelInfo;
8007 7 SimCodeVar.SIMVARS(stateVars=stateVars,derivativeVars=derivativeVars,algVars=algVars,boolAlgVars=boolAlgVars,intAlgVars=intAlgVars,discreteAlgVars=discreteAlgVars,aliasVars=aliasVars,intAliasVars=intAliasVars,
8008 paramVars=paramVars,intParamVars=intParamVars,boolParamVars=boolParamVars, extObjVars=extObjVars,constVars=constVars,intConstVars=intConstVars,stringConstVars=stringConstVars) := simVars;
8009 7 SimCode.VARINFO(numStateVars=nsv,numAlgVars=nalgv) := varInfo;
8010 7 dumpVarLst(stateVars,"stateVars ("+intString(nsv)+")");
8011 7 dumpVarLst(derivativeVars,"derivativeVars");
8012 7 dumpVarLst(algVars,"algVars ("+intString(nalgv)+")");
8013 7 dumpVarLst(discreteAlgVars,"discreteAlgVars");
8014 7 dumpVarLst(intAlgVars,"intAlgVars");
8015 7 dumpVarLst(boolAlgVars,"boolAlgVars");
8016 7 dumpVarLst(aliasVars,"aliasVars");
8017 7 dumpVarLst(intAliasVars,"intAliasVars");
8018 7 dumpVarLst(paramVars,"paramVars");
8019 7 dumpVarLst(intParamVars,"intParamVars");
8020 7 dumpVarLst(boolParamVars,"boolParamVars");
8021 7 dumpVarLst(extObjVars,"extObjVars");
8022 7 dumpVarLst(constVars,"constVars");
8023 7 dumpVarLst(intConstVars,"intConstVars");
8024 7 dumpVarLst(stringConstVars,"stringConstVars");
8025 7 print("functions:\n-----------\n\n");
8026 7 dumpFunctions(functions);
8027 end dumpModelInfo;
8028
8029 protected function dumpFunctions
8030 input list<SimCodeFunction.Function> functions;
8031 algorithm
8032 () := match functions
8033 local
8034 Absyn.Path path;
8035 list<SimCodeFunction.Function> rest;
8036 list<SimCodeFunction.Variable> outVars,functionArguments,variableDeclarations,funArgs, locals;
8037 case {}
8038 algorithm
8039 then ();
8040 case SimCodeFunction.FUNCTION(name=path,outVars=outVars,functionArguments=functionArguments,variableDeclarations=variableDeclarations)::rest
8041 algorithm
8042 1 print("Function: "+AbsynUtil.pathStringNoQual(path)+"\n");
8043 1 print("\toutVars: ");
8044 1 dumpVariablesString(outVars," , ");
8045 1 print("\n\tfunctionArguments: ");
8046 1 dumpVariablesString(functionArguments," , ");
8047 1 print("\n\tvariableDeclarations: ");
8048 1 dumpVariablesString(variableDeclarations," , ");
8049 1 print("\n");
8050 1 dumpFunctions(rest);
8051 then ();
8052 case SimCodeFunction.PARALLEL_FUNCTION(name=path)::rest
8053 algorithm
8054 ✗ print("Parallel Function: "+AbsynUtil.pathStringNoQual(path)+"\n");
8055 ✗ dumpFunctions(rest);
8056 then ();
8057 case SimCodeFunction.KERNEL_FUNCTION(name=path)::rest
8058 algorithm
8059 ✗ print("Kernel Function: "+AbsynUtil.pathStringNoQual(path)+"\n");
8060 ✗ dumpFunctions(rest);
8061 then ();
8062 case SimCodeFunction.EXTERNAL_FUNCTION(name=path,outVars=outVars)::rest
8063 algorithm
8064 1 print("External Function: "+AbsynUtil.pathStringNoQual(path)+"\n");
8065 1 print("\toutVars: ");
8066 1 dumpVariablesString(outVars," , ");
8067 1 print("\n");
8068 1 dumpFunctions(rest);
8069 then ();
8070 case SimCodeFunction.RECORD_CONSTRUCTOR(name=path, funArgs=funArgs, locals=locals)::rest
8071 algorithm
8072 ✗ print("Record: "+AbsynUtil.pathStringNoQual(path)+"\n");
8073 ✗ print("\tfunArgs: ");
8074 ✗ dumpVariablesString(funArgs," , ");
8075 ✗ print("\n\tlocals: ");
8076 ✗ dumpVariablesString(locals," , ");
8077 ✗ print("\n");
8078 ✗ dumpFunctions(rest);
8079 then ();
8080 end match;
8081 end dumpFunctions;
8082
8083 public function dumpSimEqSystemLst
8084 input list<SimCode.SimEqSystem> eqSysLstIn;
8085 input String delimiter;
8086 protected
8087 SimCode.SimEqSystem sys;
8088 algorithm
8089
2/2
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 195 times.
513 for sys in eqSysLstIn loop
8090 318 dumpSimEqSystem(sys);
8091 318 print(delimiter);
8092 end for;
8093 end dumpSimEqSystemLst;
8094
8095
8096 public function simEqSystemString
8097 "outputs a string representation of the given SimEqSystem.
8098 author:Waurich TUD 2016-04"
8099 input SimCode.SimEqSystem eqSysIn;
8100 output String str;
8101 algorithm
8102 str := matchcontinue eqSysIn
8103 local
8104 Integer idx,idxLS,idxNLS,idxMS;
8105 String s;
8106 list<String> sLst;
8107 DAE.Exp exp,lhs,iterator,startIt,endIt;
8108 DAE.ComponentRef cref;
8109 SimCode.SimEqSystem cont;
8110 list<DAE.ComponentRef> crefs;
8111 list<DAE.Statement> stmts;
8112 list<SimCode.SimEqSystem> discEqs,eqs,residual;
8113 list<SimCodeVar.SimVar> vars;
8114 list<DAE.Exp> beqs;
8115 Option<SimCode.JacobianMatrix> jac;
8116 Option<SimCode.SimEqSystem> elseWhen;
8117 list<BackendDAE.WhenOperator> whenStmtLst;
8118 BackendDAE.Constraints cons;
8119
8120 case SimCode.SES_RESIDUAL(index=idx,exp=exp)
8121 algorithm
8122 106 s := intString(idx) +": "+ ExpressionBasics.printExpStr(exp)+" (RESIDUAL)";
8123 then s;
8124
8125 case SimCode.SES_FOR_RESIDUAL(index=idx,exp=exp)
8126 algorithm
8127 ✗ s := intString(idx) +": "+ ExpressionBasics.printExpStr(exp)+" (FOR_RESIDUAL)";
8128 then s;
8129
8130 case SimCode.SES_GENERIC_RESIDUAL(index=idx,exp=exp)
8131 algorithm
8132 ✗ s := intString(idx) +": "+ ExpressionBasics.printExpStr(exp)+" (GENERIC_RESIDUAL)";
8133 then s;
8134
8135 case SimCode.SES_SIMPLE_ASSIGN(index=idx,cref=cref,exp=exp)
8136 algorithm
8137 236 s := intString(idx) +": "+ ComponentReferenceBasics.printComponentRefStr(cref) + "=" + ExpressionBasics.printExpStr(exp) + " [" +DAEDump.daeTypeStr(Expression.typeof(exp))+ "]";
8138 then s;
8139
8140 case SimCode.SES_SIMPLE_ASSIGN_CONSTRAINTS(index=idx,cref=cref,exp=exp,cons=cons)
8141 algorithm
8142 ✗ s := intString(idx) +": "+ ComponentReferenceBasics.printComponentRefStr(cref) + "=" + ExpressionBasics.printExpStr(exp) + " [constraints: " + ExpressionDump.constraintDTlistToString(cons, "") + "]" + " [" +DAEDump.daeTypeStr(Expression.typeof(exp))+ "]";
8143 then s;
8144
8145 case SimCode.SES_ARRAY_CALL_ASSIGN(index=idx,lhs=lhs,exp=exp)
8146 algorithm
8147 2 s := intString(idx) +": "+ ExpressionBasics.printExpStr(lhs) + "=" + ExpressionBasics.printExpStr(exp) + " [" +DAEDump.daeTypeStr(Expression.typeof(exp))+ "]";
8148 then s;
8149
8150 case SimCode.SES_IFEQUATION(index=idx)
8151 algorithm
8152 ✗ s := intString(idx) +": "+ " (IF)";
8153 then s;
8154
8155 case SimCode.SES_ALGORITHM(index=idx,statements=stmts)
8156 algorithm
8157 26 sLst := List.map(stmts,DAEDump.ppStatementStr);
8158 26 s := intString(idx) +": "+ List.foldr(sLst, stringAppend, "");
8159 then s;
8160
8161 case SimCode.SES_INVERSE_ALGORITHM(index=idx,statements=stmts) algorithm
8162 ✗ sLst := List.map(stmts, DAEDump.ppStatementStr);
8163 ✗ s := intString(idx) +": "+ List.foldr(sLst, stringAppend, "");
8164 then s;
8165
8166 // no dynamic tearing
8167 case SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(index=idx, indexLinearSystem=idxLS, vars=vars, beqs=beqs, residual=residual, jacobianMatrix=jac), NONE())
8168 algorithm
8169
2/4
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
2 s := intString(idx) +": "+ " (LINEAR) index:"+intString(idxLS)+" jacobian: "+boolString(isSome(jac))+"\n";
8170 2 s := s+"\tvariables:\n"+stringDelimitList(List.map(vars,SimCodeCodegenUtil.simVarString),"\n");
8171 2 s := s+"\n\tb-vector:\n"+stringDelimitList(List.map(beqs,ExpressionBasics.printExpStr),"\n");
8172 2 s := s+ "\t";
8173 2 s := s+stringDelimitList(List.map(residual,simEqSystemString),"\n\t");
8174 2 s := s+"\n";
8175 then s;
8176
8177 // dynamic tearing
8178 case SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(index=idx, indexLinearSystem=idxLS, vars=vars, beqs=beqs, residual=residual, jacobianMatrix=jac), SOME(SimCode.LINEARSYSTEM()))
8179 algorithm
8180 ✗ s := "strict set:\n"+intString(idx) +": "+ " (LINEAR) index:"+intString(idxLS)+" jacobian: "+boolString(isSome(jac))+"\n";
8181 ✗ s := s+"\tvariables:\n\t"+stringDelimitList(List.map(vars,SimCodeCodegenUtil.simVarString),"\t\n");
8182 ✗ s := s+"\n\tb-vector:\n"+stringDelimitList(List.map(beqs,ExpressionBasics.printExpStr),"\t\n");
8183 ✗ s := s+ "\t";
8184 ✗ s := s+stringDelimitList(List.map(residual,simEqSystemString),"\n\t");
8185 ✗ s := s+"\n";
8186 then s;
8187
8188 // no dynamic tearing
8189 case SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(index=idx,indexNonLinearSystem=idxNLS,jacobianMatrix=jac,eqs=eqs, crefs=crefs), NONE())
8190 algorithm
8191
3/4
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 13 times.
23 s := intString(idx) +": "+ " (NONLINEAR) index:"+intString(idxNLS)+" jacobian: "+boolString(isSome(jac))+"\n";
8192 18 s := s+"crefs: "+stringDelimitList(List.map(crefs,ComponentReferenceBasics.printComponentRefStr)," , ")+"\n";
8193 18 s := s+"\t";
8194 18 s := s+stringDelimitList(List.map(eqs,simEqSystemString),"\n\t");
8195 18 s := s+"\n";
8196 then s;
8197
8198 // dynamic tearing
8199 case SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(index=idx,indexNonLinearSystem=idxNLS,jacobianMatrix=jac,eqs=eqs, crefs=crefs), SOME(SimCode.NONLINEARSYSTEM()))
8200 algorithm
8201 ✗ s := "strict set:\n"+intString(idx) +": "+ " (NONLINEAR) index:"+intString(idxNLS)+" jacobian: "+boolString(isSome(jac))+"\n";
8202 ✗ s := s+"crefs: "+stringDelimitList(List.map(crefs,ComponentReferenceBasics.printComponentRefStr)," , ")+"\n";
8203 ✗ s := s+"\t";
8204 ✗ s := s+stringDelimitList(List.map(eqs,simEqSystemString),"\n\t");
8205 ✗ s := s+"\n";
8206 then s;
8207
8208 case SimCode.SES_MIXED(index=idx,indexMixedSystem=idxMS, cont=cont, discEqs=eqs)
8209 algorithm
8210 ✗ s := intString(idx) +": "+ " (MIXED) index:"+intString(idxMS)+"\n";
8211 ✗ s := s + simEqSystemString(cont);
8212 ✗ s := s+stringDelimitList(List.map(eqs,simEqSystemString),"\n\t");
8213 then s;
8214
8215 case SimCode.SES_WHEN(index=idx, conditions=crefs, whenStmtLst = whenStmtLst, elseWhen=elseWhen)
8216 algorithm
8217 ✗ s := intString(idx) +": "+ " WHEN:( ";
8218 ✗ s := s+ stringDelimitList(List.map(crefs,ComponentReference.crefStr),", ") + " ) then: ";
8219 ✗ s := s +dumpWhenOps(whenStmtLst);
8220 ✗ if isSome(elseWhen) then
8221 ✗ s := s + " ELSEWHEN: ";
8222 ✗ s := s + simEqSystemString(Util.getOption(elseWhen));
8223 end if;
8224 then s;
8225
8226 case SimCode.SES_FOR_LOOP(index=idx,iter=iterator, startIt=startIt, endIt=endIt, cref=cref, exp=exp)
8227 algorithm
8228 ✗ s := intString(idx) +" FOR-LOOP: "+" for "+ExpressionBasics.printExpStr(iterator)+" in ("+ExpressionBasics.printExpStr(startIt)+":"+ExpressionBasics.printExpStr(endIt)+") loop\n";
8229 ✗ s := s+ComponentReferenceBasics.printComponentRefStr(cref) + "=" + ExpressionBasics.printExpStr(exp)+"[" +DAEDump.daeTypeStr(Expression.typeof(exp))+ "]\n";
8230 ✗ s := s+"end for;";
8231 then s;
8232
8233 case SimCode.SES_FOR_EQUATION(index=idx,iter=iterator, startIt=startIt, endIt=endIt, body=eqs)
8234 algorithm
8235 ✗ s := intString(idx) +" FOR-EQUATION: "+" for "+ExpressionBasics.printExpStr(iterator)+" in ("+ExpressionBasics.printExpStr(startIt)+":"+ExpressionBasics.printExpStr(endIt)+") loop\n";
8236 ✗ s := s+stringDelimitList(List.map(eqs,simEqSystemString),"\n\t");
8237 ✗ s := s+"end for;";
8238 then s;
8239
8240 case SimCode.SES_ALIAS()
8241 algorithm
8242 40 s := String(eqSysIn.index) +": alias of "+ String(eqSysIn.aliasOf);
8243 then s;
8244
8245 case SimCode.SES_RESIZABLE_ASSIGN()
8246 algorithm
8247 8 s := intString(eqSysIn.index) +": "+ " (SES_RESIZABLE_ASSIGN) " + " call index: " + intString(eqSysIn.call_index) + "\n";
8248 then s;
8249
8250 case SimCode.SES_GENERIC_ASSIGN()
8251 algorithm
8252 ✗ s := intString(eqSysIn.index) +": "+ " (SES_GENERIC_ASSIGN) " + " call index: " + intString(eqSysIn.call_index) + "\n";
8253 ✗ s := s + "\tindices: " + List.toString(eqSysIn.scal_indices, intString, List.Style.FLAT_CURLY_SHORT) + "\n";
8254 then s;
8255
8256 case SimCode.SES_ENTWINED_ASSIGN()
8257 algorithm
8258 ✗ s := intString(eqSysIn.index) +": "+ " (SES_ENTWINED_ASSIGN)\n";
8259 ✗ s := s + "\tcall order: " + List.toString(eqSysIn.call_order, intString, List.Style.FLAT_CURLY_SHORT) + "\n";
8260 ✗ s := s + List.toString(eqSysIn.single_calls, simEqSystemString, List.Style.NEWLINE_TAB);
8261 ✗ s := s + "\n";
8262 then s;
8263
8264 else
8265 then
8266 "SOMETHING DIFFERENT\n";
8267 end matchcontinue;
8268 end simEqSystemString;
8269
8270
8271 public function dumpSimEqSystem "dumps the given SimEqSystem.
8272 author:Waurich TUD 2013-11"
8273 input SimCode.SimEqSystem eqSysIn;
8274 algorithm
8275 () := matchcontinue eqSysIn
8276 local
8277 Integer idx2,idxLS2,idxNLS2;
8278 list<DAE.ComponentRef> crefs,crefs2;
8279 list<SimCode.SimEqSystem> eqs,eqs2,residual,residual2;
8280 list<tuple<Integer, Integer, SimCode.SimEqSystem>> simJac,simJac2;
8281 Option<SimCode.JacobianMatrix> jac,jac2;
8282
8283 // no dynamic tearing
8284 case SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(jacobianMatrix=jac, simJac=simJac), NONE())
8285 algorithm
8286 2 print(simEqSystemString(eqSysIn));
8287 2 dumpJacobianMatrix(jac);
8288 2 print("\tsimJac:\n");
8289 2 dumpSimJac(simJac);
8290 then ();
8291
8292 // dynamic tearing
8293 case SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(jacobianMatrix=jac, simJac=simJac), SOME(SimCode.LINEARSYSTEM(index=idx2,indexLinearSystem=idxLS2, residual=residual2, jacobianMatrix=jac2, simJac=simJac2)))
8294 algorithm
8295 ✗ print(simEqSystemString(eqSysIn));
8296 ✗ print("\n\tsimJac:\n");
8297 ✗ dumpSimJac(simJac);
8298 ✗ dumpJacobianMatrix(jac);
8299 ✗ print("\ncasual set:\n" + intString(idx2) +": "+ " (LINEAR) index:"+intString(idxLS2)+" jacobian: "+boolString(isSome(jac))+"\n");
8300 ✗ print("\t");
8301 ✗ dumpSimEqSystemLst(residual2,"\n\t");
8302 ✗ print("\n\tsimJac:\n");
8303 ✗ dumpSimJac(simJac2);
8304 ✗ dumpJacobianMatrix(jac2);
8305 then ();
8306
8307 // no dynamic tearing
8308 case SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(jacobianMatrix=jac), NONE())
8309 algorithm
8310 18 print(simEqSystemString(eqSysIn));
8311 18 dumpJacobianMatrix(jac);
8312 then ();
8313
8314 // dynamic tearing
8315 case SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(jacobianMatrix=jac), SOME(SimCode.NONLINEARSYSTEM(index=idx2,indexNonLinearSystem=idxNLS2,jacobianMatrix=jac2,eqs=eqs2, crefs=crefs2)))
8316 algorithm
8317 ✗ print(simEqSystemString(eqSysIn));
8318 ✗ dumpJacobianMatrix(jac);
8319 ✗ print("\ncasual set:\n" + intString(idx2) +": "+ " (NONLINEAR) index:"+intString(idxNLS2)+" jacobian: "+boolString(isSome(jac2))+"\n");
8320 ✗ print("\t\tcrefs: "+stringDelimitList(List.map(crefs2,ComponentReferenceBasics.printComponentRefStr)," , ")+"\n");
8321 ✗ print("\t");
8322 ✗ dumpSimEqSystemLst(eqs2,"\n\t");
8323 ✗ print("\n");
8324 ✗ dumpJacobianMatrix(jac2);
8325 then ();
8326
8327 else
8328 algorithm
8329 298 print(simEqSystemString(eqSysIn));
8330 then ();
8331 end matchcontinue;
8332 end dumpSimEqSystem;
8333
8334 protected function dumpSimJac
8335 input list<tuple<Integer, Integer, SimCode.SimEqSystem>> simJac;
8336 protected
8337 Integer i1, i2;
8338 String res;
8339 SimCode.SimEqSystem simEqSys;
8340 tuple<Integer, Integer, SimCode.SimEqSystem> tpl;
8341 algorithm
8342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if listEmpty(simJac) then res := "no simJac";
8343 else res := "";
8344 end if;
8345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for tpl in simJac loop
8346 ✗ (i1,i2,simEqSys) := tpl;
8347 ✗ print(res + "["+intString(i1) + ", " + intString(i2)+ "] ->");
8348 ✗ dumpSimEqSystem(simEqSys);
8349 end for;
8350 2 print("\n");
8351 end dumpSimJac;
8352
8353 protected function dumpWhenOps
8354 input list<BackendDAE.WhenOperator> whenStmtLst;
8355 output String res;
8356 protected
8357 BackendDAE.WhenOperator e;
8358 algorithm
8359 res := "";
8360 ✗ for whenOps in whenStmtLst loop
8361 res := match whenOps
8362 case e as BackendDAE.ASSIGN()
8363 ✗ then res + ExpressionBasics.printExpStr(e.left) + " = " + ExpressionBasics.printExpStr(e.right) + "["+ DAEDump.daeTypeStr(Expression.typeof(e.right)) + "]";
8364 case e as BackendDAE.REINIT()
8365 ✗ then res + "reinit(" + ComponentReference.debugPrintComponentRefTypeStr(e.stateVar) + ", " + ExpressionBasics.printExpStr(e.value) + ") ["+ DAEDump.daeTypeStr(Expression.typeof(e.value)) + "]";
8366 case e as BackendDAE.ASSERT()
8367 ✗ then res + "assert(" + ExpressionBasics.printExpStr(e.condition) + ExpressionBasics.printExpStr(e.message) + ExpressionBasics.printExpStr(e.level) + ")";
8368 case e as BackendDAE.TERMINATE()
8369 ✗ then res + "terminate(" + ExpressionBasics.printExpStr(e.message) + ")";
8370 case e as BackendDAE.NORETCALL()
8371 ✗ then res + ExpressionBasics.printExpStr(e.exp) + " ["+ DAEDump.daeTypeStr(Expression.typeof(e.exp)) + "]";
8372 end match;
8373 end for;
8374 end dumpWhenOps;
8375
8376 protected function dumpJacobianMatrixLst
8377 "Takes a list and a function which does not return a value. The function is
8378 probably a function with side effects, like print."
8379 input list<SimCode.JacobianMatrix> simjacs;
8380 algorithm
8381 ✗ for jac in simjacs loop
8382 ✗ print("\nsymbolic directional derivative:\n");
8383 ✗ dumpJacobianMatrix(SOME(jac));
8384 ✗ print("\n");
8385 end for;
8386 end dumpJacobianMatrixLst;
8387
8388 protected function dumpJacobianMatrix
8389 input Option<SimCode.JacobianMatrix> jacOpt;
8390 algorithm
8391 () := match jacOpt
8392 local
8393 Integer idx;
8394 SimCode.JacobianMatrix jac;
8395 list<SimCode.JacobianColumn> cols;
8396 list<SimCode.SimEqSystem> colEqs;
8397 list<SimCodeVar.SimVar> colVars;
8398 case SOME(jac)
8399 algorithm
8400 94 SimCode.JAC_MATRIX(columns=cols, jacobianIndex=idx) := jac;
8401
4/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 94 times.
181 colEqs := List.flatten(list(a.columnEqns for a in cols));
8402
4/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 94 times.
181 colVars := List.flatten(list(a.columnVars for a in cols));
8403 94 print("\tJacobian idx: "+intString(idx)+"\n\t");
8404 94 dumpSimEqSystemLst(colEqs,"\n\t");
8405 94 print("\n");
8406 94 dumpVarLst(colVars,"columnVars("+intString(listLength(colVars))+")");
8407 then ();
8408 case NONE()
8409 then ();
8410 end match;
8411 end dumpJacobianMatrix;
8412
8413 protected function extObjInfoString
8414 input SimCode.ExtObjInfo info;
8415 protected
8416 list<SimCodeVar.SimVar> vars;
8417 list<SimCode.ExtAlias> aliases;
8418 DAE.ComponentRef cr1, cr2;
8419 algorithm
8420 7 SimCode.EXTOBJINFO(vars=vars, aliases=aliases) := info;
8421 7 dumpVarLst(vars,"external object info");
8422
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if not listEmpty(aliases) then
8423 ✗ print("external object aliase ("+intString(listLength(aliases))+")");
8424 ✗ for tpl in aliases loop
8425 ✗ (cr1,cr2) := tpl;
8426 ✗ print(ComponentReference.crefStr(cr1)+" = "+ComponentReference.crefStr(cr2));
8427 end for;
8428 ✗ print("\n");
8429 end if;
8430 end extObjInfoString;
8431
8432 protected function dumpClockPartition
8433 input SimCode.ClockedPartition clockPart;
8434 algorithm
8435 ✗ print("BaseClock:\n"+UNDERLINE+"\n"+ExpressionDump.clockKindString(clockPart.baseClock)+UNDERLINE+"\n\n");
8436 ✗ print(stringDelimitList(List.map(clockPart.subPartitions,subPartitionString),"\n\n")+"\n");
8437 ✗ print("\n");
8438 end dumpClockPartition;
8439
8440 protected function previousString"outputs a string representation if the boolean says the var is a previous var"
8441 input Boolean isPreviousVar;
8442 output String s;
8443 algorithm
8444 ✗ if isPreviousVar then
8445 s := " (PREVIOUS)";
8446 else
8447 s := " ";
8448 end if;
8449 end previousString;
8450
8451 protected function subPartitionString"outputs a string representation of a SimCode.SubPartition"
8452 input SimCode.SubPartition subPart;
8453 output String str;
8454 protected
8455 list<SimCodeVar.SimVar> simVars;
8456 list<Boolean> arePrevious;
8457 list<String> simVarStrings;
8458 algorithm
8459 ✗ simVars := List.map(subPart.vars,Util.tuple21);
8460 ✗ arePrevious := List.map(subPart.vars,Util.tuple22);
8461 ✗ simVarStrings := List.threadMap(List.map(simVars,SimCodeCodegenUtil.simVarString), List.map(arePrevious,previousString),stringAppend);
8462 str := "SubPartition Vars:\n"+UNDERLINE+"\n";
8463 ✗ str := str + stringDelimitList(simVarStrings,"\n")+"\n";
8464 ✗ str := str + "partition equations:\n"+UNDERLINE+"\n";
8465 ✗ str := str + stringDelimitList(List.map(subPart.equations,simEqSystemString),"\n") + "\n";
8466 ✗ str := str + "removedEquations equations:\n"+UNDERLINE+"\n";
8467 ✗ str := str + stringDelimitList(List.map(subPart.removedEquations,simEqSystemString),"\n");
8468 ✗ str := str + "SubClock:\n"+ BackendDump.subClockString(subPart.subClock) + "\n";
8469 ✗ str := str + "Hold Events: "+boolString(subPart.holdEvents);
8470 end subPartitionString;
8471
8472 public function dumpSimCodeDAEmodeDataString
8473 input Option<SimCode.DaeModeData> inDaeModedata;
8474 output String str = "";
8475 algorithm
8476 () := match inDaeModedata
8477 local
8478 SimCode.DaeModeData dmd;
8479 SimCode.SparsityPattern sparsity, sparsityT;
8480 case SOME(dmd) algorithm
8481 ✗ print("\ndaeMode:\n" + UNDERLINE + "\n");
8482 str := "residual Equations:\n"+UNDERLINE+"\n";
8483 ✗ print(str);
8484 ✗ dumpSimEqSystemLst(List.flatten(dmd.daeEquations),"\n");
8485 ✗ dumpVarLst(dmd.residualVars,"residualVars("+intString(listLength(dmd.residualVars))+")");
8486 ✗ dumpVarLst(dmd.algebraicVars,"algebraicDAEVars("+intString(listLength(dmd.algebraicVars))+")");
8487 ✗ dumpVarLst(dmd.auxiliaryVars,"auxVars("+intString(listLength(dmd.auxiliaryVars))+")");
8488 ✗ if isSome(dmd.sparsityPattern) then
8489 str := "Sparsity Pattern:\n"+UNDERLINE+"\n";
8490 ✗ print(str);
8491 ✗ SimCode.JAC_MATRIX(sparsity = sparsity, sparsityT=sparsityT) := Util.getOption(dmd.sparsityPattern);
8492 ✗ dumpSparsePatternInt(sparsity);
8493 str := "Sparsity Pattern Transposed:\n"+UNDERLINE+"\n";
8494 ✗ print(str);
8495 ✗ dumpSparsePatternInt(sparsityT);
8496 end if;
8497 then ();
8498 case NONE() then ();
8499 end match;
8500 end dumpSimCodeDAEmodeDataString;
8501
8502 public function dumpSimCodeDebug"prints the simcode debug output to std out."
8503 input SimCode.SimCode simCode;
8504 protected
8505 list<Option<SimCode.JacobianMatrix>> jacObs;
8506 algorithm
8507 7 print("\n\n*********************\n* SimCode Equations *\n*********************\n\n");
8508 7 print("\nallEquations:\n" + UNDERLINE + "\n\n");
8509 7 dumpSimEqSystemLst(simCode.allEquations,"\n");
8510 7 print(UNDERLINE + "\n\n\n");
8511 7 print("\nodeEquations ("+intString(listLength(simCode.odeEquations))+" systems):\n" + UNDERLINE + "\n");
8512 7 List.map1_0(simCode.odeEquations,dumpSimEqSystemLst,"\n");
8513 7 print(UNDERLINE + "\n\n\n");
8514 7 print("\nalgebraicEquations ("+intString(listLength(simCode.algebraicEquations))+" systems):\n" + UNDERLINE + "\n");
8515 7 List.map1_0(simCode.algebraicEquations,dumpSimEqSystemLst,"\n");
8516 7 print(UNDERLINE + "\n\n\n");
8517 7 print("clockPartitions ("+intString(listLength(simCode.clockedPartitions))+" systems):\n\n");
8518 7 List.map_0(simCode.clockedPartitions,dumpClockPartition);
8519 7 print(UNDERLINE + "\n\n\n");
8520 7 print("\ninitialEquations: ("+intString(listLength(simCode.initialEquations))+")\n"+ UNDERLINE+"\n");
8521 7 dumpSimEqSystemLst(simCode.initialEquations,"\n");
8522 7 print(UNDERLINE + "\n\n\n");
8523 7 print("\ninitialEquations_lambda0: ("+intString(listLength(simCode.initialEquations_lambda0))+")\n" + UNDERLINE + "\n");
8524 7 dumpSimEqSystemLst(simCode.initialEquations_lambda0,"\n");
8525
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (Flags.getConfigEnum(Flags.SYM_SOLVER) > 0) then
8526 ✗ print("\ninlineEquations: ("+intString(listLength(simCode.inlineEquations))+" systems)\n" + UNDERLINE + "\n");
8527 ✗ dumpSimEqSystemLst(simCode.inlineEquations,"\n");
8528 end if;
8529 7 print("\nremovedInitialEquations:\n" + UNDERLINE + "\n");
8530 7 dumpSimEqSystemLst(simCode.removedInitialEquations,"\n");
8531 7 print("\nstartValueEquations:\n" + UNDERLINE + "\n");
8532 7 dumpSimEqSystemLst(simCode.startValueEquations,"\n");
8533 7 print("\nnominalValueEquations:\n" + UNDERLINE + "\n");
8534 7 dumpSimEqSystemLst(simCode.nominalValueEquations,"\n");
8535 7 print("\nminValueEquations:\n" + UNDERLINE + "\n");
8536 7 dumpSimEqSystemLst(simCode.minValueEquations,"\n");
8537 7 print("\nmaxValueEquations:\n" + UNDERLINE + "\n");
8538 7 dumpSimEqSystemLst(simCode.maxValueEquations,"\n");
8539 7 print("\nparameterEquations:\n" + UNDERLINE + "\n");
8540 7 dumpSimEqSystemLst(simCode.parameterEquations,"\n");
8541 7 print("\nremovedEquations:\n" + UNDERLINE + "\n");
8542 7 dumpSimEqSystemLst(simCode.removedEquations,"\n");
8543 7 print("\nalgorithmAndEquationAsserts:\n" + UNDERLINE + "\n");
8544 7 dumpSimEqSystemLst(simCode.algorithmAndEquationAsserts,"\n");
8545 7 print("\nequationsForZeroCrossings:\n" + UNDERLINE + "\n");
8546 7 dumpSimEqSystemLst(simCode.equationsForZeroCrossings,"\n");
8547 7 print("\ngeneric calls:\n" + UNDERLINE + "\n");
8548 7 print(List.toString(simCode.generic_loop_calls, SimCodeCodegenUtil.simGenericCallString, List.Style.NEWLINE));
8549 7 print("\njacobianEquations:\n" + UNDERLINE + "\n");
8550 7 dumpSimEqSystemLst(simCode.jacobianEquations,"\n");
8551 7 extObjInfoString(simCode.extObjInfo);
8552 7 print("\njacobianMatrices:\n" + UNDERLINE + "\n");
8553 7 jacObs := List.map(simCode.jacobianMatrices,Util.makeOption);
8554 7 List.map_0(jacObs,dumpJacobianMatrix);
8555 7 print("\nmodelInfo:\n" + UNDERLINE + "\n");
8556 7 dumpModelInfo(simCode.modelInfo);
8557 7 dumpSimCodeDAEmodeDataString(simCode.daeModeData);
8558 end dumpSimCodeDebug;
8559
8560 protected function isAliasVar
8561 input SimCodeVar.SimVar var;
8562 output Boolean res;
8563 algorithm
8564 res :=
8565 match var
8566 case SimCodeVar.SIMVAR(aliasvar=SimCodeVar.NOALIAS())
8567 then false;
8568 else
8569 then true;
8570 end match;
8571 end isAliasVar;
8572
8573 protected function sortSimvars
8574 input array<list<SimCodeVar.SimVar>> simvars;
8575 protected
8576 Integer i = 0;
8577 array<Integer> arr;
8578 algorithm
8579
3/4
✓ Branch 0 taken 32070 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 32070 times.
✓ Branch 5 taken 1069 times.
33139 for i in SimVarsIndex loop
8580 32070 Dangerous.arrayUpdateNoBoundsChecking(simvars, Integer(i), List.sort(Dangerous.arrayGetNoBoundsChecking(simvars, Integer(i)), simVarCompareByCrefSubsAtEndlLexical));
8581 end for;
8582
2/2
✓ Branch 0 taken 301 times.
✓ Branch 1 taken 1069 times.
1370 for v in Dangerous.arrayGetNoBoundsChecking(simvars, Integer(SimVarsIndex.inputs)) loop
8583 // Set input indexes as they appear in the sorted order; is mutable since we need the same index in the other lists of vars...
8584 i := match v
8585 case SimCodeVar.SIMVAR(inputIndex=SOME(arr))
8586 algorithm
8587 301 arrayUpdate(arr, 1, i);
8588 301 then i + 1;
8589 else
8590 algorithm
8591 ✗ Error.addInternalError("Failed to update indexes of simvars", sourceInfo());
8592 ✗ then fail();
8593 end match;
8594 end for;
8595 end sortSimvars;
8596
8597 public function simVarCompareByCrefSubsAtEndlLexical
8598 "mahge:
8599 Compare two simvars by their name. i.e. component ref.
8600 we use it to make sure elements of a vectorized array stay contagious
8601 sto each other in the correct offest/order.
8602 N.B. subs are pushed to end. They are compared if only
8603 the two crefs' idents are the same"
8604 input SimCodeVar.SimVar var1;
8605 input SimCodeVar.SimVar var2;
8606 output Boolean outBool;
8607 protected
8608 DAE.ComponentRef cr1;
8609 DAE.ComponentRef cr2;
8610 algorithm
8611 2749539 cr1 := var1.name;
8612 2749539 cr2 := var2.name;
8613 2749539 outBool := ComponentReferenceBasics.crefLexicalGreaterSubsAtEnd(cr1,cr2);
8614 end simVarCompareByCrefSubsAtEndlLexical;
8615
8616 protected function extendIncompleteArray
8617 input array<list<SimCodeVar.SimVar>> simvars;
8618 protected
8619 list<SimCodeVar.SimVar> simVars;
8620 HashSet.HashSet set;
8621 algorithm
8622 // for runtime CPP also the incomplete arrays need one special element to generate the array
8623 // search all arrays with array information
8624 48 set := HashSet.emptyHashSet();
8625
8626
3/4
✓ Branch 0 taken 1440 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1440 times.
✓ Branch 5 taken 48 times.
1488 for i in SimVarsIndex loop
8627 1440 set := List.fold(Dangerous.arrayGetNoBoundsChecking(simvars, Integer(i)), collectArrayFirstVars, set);
8628 end for;
8629
8630 // add array information to incomplete arrays
8631
3/4
✓ Branch 0 taken 1440 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1440 times.
✓ Branch 5 taken 48 times.
1488 for i in SimVarsIndex loop
8632 1440 (simVars, set) := List.mapFold(Dangerous.arrayGetNoBoundsChecking(simvars, Integer(i)), setArrayElementnoFirst, set);
8633 Dangerous.arrayUpdateNoBoundsChecking(simvars, Integer(i), simVars);
8634 end for;
8635 end extendIncompleteArray;
8636
8637 protected function setArrayElementnoFirst
8638 "author: Frenkel TUD 2012-10"
8639 input SimCodeVar.SimVar iVar;
8640 input HashSet.HashSet iSet;
8641 output SimCodeVar.SimVar oVar;
8642 output HashSet.HashSet oSet;
8643 algorithm
8644 (oVar, oSet) := matchcontinue iVar
8645 local
8646 DAE.ComponentRef cr;
8647 SimCodeVar.SimVar var;
8648 HashSet.HashSet set;
8649 case SimCodeVar.SIMVAR(arrayCref=SOME(_))
8650 then
8651 (iVar, iSet);
8652 case SimCodeVar.SIMVAR(name=cr, numArrayElement=_::_, arrayCref=NONE())
8653 algorithm
8654
2/2
✓ Branch 1 taken 1919 times.
✓ Branch 2 taken 3837 times.
5756 _::_ := ComponentReference.crefLastSubs(cr);
8655 3837 cr := ComponentReferenceBasics.crefStripLastSubs(cr);
8656
2/2
✓ Branch 1 taken 3816 times.
✓ Branch 2 taken 21 times.
3837 false := BaseHashSet.has(cr, iSet);
8657 21 var := addSimVarArrayCref(iVar, cr);
8658 21 set := BaseHashSet.add(cr, iSet);
8659 then
8660 (var, set);
8661 else (iVar, iSet);
8662 end matchcontinue;
8663 end setArrayElementnoFirst;
8664
8665 protected function addSimVarArrayCref
8666 "author: Frenkel TUD 2012-10"
8667 input SimCodeVar.SimVar iVar;
8668 input DAE.ComponentRef arrayCref;
8669 output SimCodeVar.SimVar oVar = iVar;
8670 algorithm
8671 21 oVar.arrayCref := SOME(arrayCref);
8672 end addSimVarArrayCref;
8673
8674 protected function collectArrayFirstVars
8675 "author: Frenkel TUD 2012-10"
8676 input SimCodeVar.SimVar var;
8677 input HashSet.HashSet iSet;
8678 output HashSet.HashSet oSet;
8679 algorithm
8680 oSet := match var
8681 local
8682 DAE.ComponentRef cr;
8683 case SimCodeVar.SIMVAR(name=cr, arrayCref=SOME(_))
8684 algorithm
8685 1334 cr := ComponentReferenceBasics.crefStripLastSubs(cr);
8686 1334 then
8687 BaseHashSet.add(cr, iSet);
8688 else iSet;
8689 end match;
8690 end collectArrayFirstVars;
8691
8692 protected function fixIndex
8693 input array<list<SimCodeVar.SimVar>> simVars;
8694 protected
8695 Integer ix=0;
8696 list<SimCodeVar.SimVar> lst;
8697 Boolean isCpp = (Config.simCodeTarget() == "Cpp" );
8698 algorithm
8699 6414 for i in SimVarsIndex.state : SimVarsIndex.realOptimizeFinalConstraints loop
8700 6414 lst := Dangerous.arrayGetNoBoundsChecking(simVars,Integer(i));
8701
2/2
✓ Branch 0 taken 6126 times.
✓ Branch 1 taken 288 times.
6414 if not isCpp then
8702 6126 Dangerous.arrayUpdateNoBoundsChecking(simVars, Integer(i), rewriteIndex(lst, ix));
8703 6126 ix := ix + listLength(lst);
8704 else
8705 288 Dangerous.arrayUpdateNoBoundsChecking(simVars, Integer(i), rewriteIndexColumnMajor(lst, 0));
8706 end if;
8707 end for;
8708 19242 for i in SimVarsIndex.param : SimVarsIndex.stringConst loop // Skip jacobian, seed
8709 19242 Dangerous.arrayUpdateNoBoundsChecking(simVars, Integer(i), rewriteIndex(Dangerous.arrayGetNoBoundsChecking(simVars,Integer(i)), 0));
8710 end for;
8711 end fixIndex;
8712
8713 public function rewriteIndex
8714 input list<SimCodeVar.SimVar> inVars;
8715 output list<SimCodeVar.SimVar> outVars = {};
8716 input output Integer index;
8717 algorithm
8718
2/2
✓ Branch 1 taken 405149 times.
✓ Branch 2 taken 32387 times.
437536 for var in inVars loop
8719 405149 var.index := index;
8720 outVars := var::outVars;
8721 405149 index := index+1;
8722 end for;
8723 32387 outVars := Dangerous.listReverseInPlace(outVars);
8724 end rewriteIndex;
8725
8726 protected function rewriteIndexColumnMajor
8727 "alternative version of rewriteIndex considering column major storage order of multi-dimensional arrays"
8728 input list<SimCodeVar.SimVar> inVars;
8729 output list<SimCodeVar.SimVar> outVars = {};
8730 input output Integer index;
8731 protected
8732 list<DAE.Subscript> subs;
8733 list<Integer> arrayDimensions = {};
8734 Integer elementIndex;
8735 algorithm
8736
2/2
✓ Branch 0 taken 4646 times.
✓ Branch 1 taken 288 times.
4934 for var in inVars loop
8737 4646 subs := ComponentReference.crefLastSubs(var.name);
8738
2/2
✓ Branch 1 taken 494 times.
✓ Branch 2 taken 4152 times.
4646 if listLength(subs) > 1 then
8739 494 arrayDimensions := List.map(var.numArrayElement, stringInt);
8740 494 elementIndex := SimCodeUtilShared.getScalarElementIndex(subs, arrayDimensions);
8741 494 var.index := index - elementIndex + SimCodeCodegenUtil.convertIndexToColumnMajor(elementIndex, arrayDimensions);
8742 else
8743 4152 var.index := index;
8744 end if;
8745 outVars := var::outVars;
8746 4646 index := index + 1;
8747 end for;
8748 288 outVars := Dangerous.listReverseInPlace(outVars);
8749 end rewriteIndexColumnMajor;
8750
8751 protected function setVariableIndex
8752 input array<list<SimCodeVar.SimVar>> simVars;
8753 protected
8754 Integer index_=1;
8755 Integer fmi_index_=1;
8756 list<SimCodeVar.SimVar> lst;
8757 algorithm
8758 //special order for fmi: real => intger => boolean => string => external
8759 25656 for i in SimVarsIndex.state : SimVarsIndex.stringConst loop
8760 25656 (lst, index_, fmi_index_) := SimCodeCodegenUtil.setVariableIndexHelper(Dangerous.arrayGetNoBoundsChecking(simVars, Integer(i)), index_, fmi_index_);
8761 Dangerous.arrayUpdateNoBoundsChecking(simVars, Integer(i), lst);
8762 end for;
8763 end setVariableIndex;
8764
8765 protected function getFmiUnitDefinitions
8766 "returs the list<UnitDefinitions> which needs to exported in modelDescription.xml"
8767 input array<list<SimCodeVar.SimVar>> simVars;
8768 output list<SimCode.UnitDefinition> unitDefinitions = {};
8769 protected
8770 HashSetString.HashSet unitNameKeys;
8771 algorithm
8772 //special order for fmi: real => intger => boolean => string => external
8773 1069 unitNameKeys := HashSetString.emptyHashSet();
8774 25656 for i in SimVarsIndex.state : SimVarsIndex.stringConst loop
8775 25656 (unitDefinitions, unitNameKeys) := getFmiUnitDefinitionsHelper(Dangerous.arrayGetNoBoundsChecking(simVars, Integer(i)), unitDefinitions, unitNameKeys);
8776 end for;
8777 //print("\n Final Units List :" + anyString(unitDefinitions));
8778 end getFmiUnitDefinitions;
8779
8780 protected function getFmiUnitDefinitionsHelper
8781 "helper function which creates the list<UnitDefintions> to be exported in modelDescription.xml"
8782 input list<SimCodeVar.SimVar> inVars;
8783 input output list<SimCode.UnitDefinition> unitDefinitions;
8784 input output HashSetString.HashSet unitNameKeys;
8785 protected
8786 Unit.Unit unit;
8787 algorithm
8788
2/2
✓ Branch 0 taken 369057 times.
✓ Branch 1 taken 25656 times.
394713 for var in inVars loop
8789
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 369057 times.
✓ Branch 2 taken 285042 times.
✓ Branch 3 taken 84015 times.
369057 if isSome(var.exportVar) then
8790 // check if the var has unit and also check if the unit is already added to hashset
8791
5/6
✓ Branch 0 taken 117384 times.
✓ Branch 1 taken 167658 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 117384 times.
✓ Branch 6 taken 3831 times.
✓ Branch 7 taken 163827 times.
285042 if not stringEq(var.unit, "") and not BaseHashSet.has(var.unit, unitNameKeys) then
8792 3831 unitNameKeys := BaseHashSet.add(var.unit, unitNameKeys);
8793 try
8794 3831 unit := Unit.parseUnitString(var.unit); // get the SI- units information
8795 3831 unitDefinitions := SimCode.UNITDEFINITION(var.unit, transformUnitToBaseUnit(unit)) :: unitDefinitions;
8796 else
8797 // catch the units which are not calculated
8798 59 unitDefinitions := SimCode.UNITDEFINITION(var.unit, SimCode.NOBASEUNIT()) :: unitDefinitions;
8799 end try;
8800 end if;
8801 // A variable may only name a display unit that is itself declared.
8802
9/10
✓ Branch 0 taken 261395 times.
✓ Branch 1 taken 23647 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 261395 times.
✓ Branch 5 taken 6890 times.
✓ Branch 6 taken 16757 times.
✓ Branch 8 taken 6696 times.
✓ Branch 9 taken 194 times.
✓ Branch 11 taken 537 times.
✓ Branch 12 taken 22916 times.
285042 if not stringEq(var.displayUnit, "") and not stringEq(var.displayUnit, var.unit)
8803 and not BaseHashSet.has(var.displayUnit, unitNameKeys) then
8804 537 unitNameKeys := BaseHashSet.add(var.displayUnit, unitNameKeys);
8805 537 unitDefinitions := displayUnitDefinition(var.unit, var.displayUnit) :: unitDefinitions;
8806 end if;
8807 end if;
8808 end for;
8809 end getFmiUnitDefinitionsHelper;
8810
8811 protected function displayUnitDefinition
8812 "The display unit as a unit in its own right: the dimensions of the unit it
8813 displays, and the factor and offset taking a value in it to SI."
8814 input String unit;
8815 input String displayUnit;
8816 output SimCode.UnitDefinition definition;
8817 protected
8818 Integer s, m, kg, A, K, mol, cd;
8819 Real factor, offset, toUnit, toUnitOffset;
8820 Boolean converts;
8821 algorithm
8822 try
8823
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 536 times.
537 SimCode.BASEUNIT(s, m, kg, A, K, mol, cd, factor, offset) :=
8824 transformUnitToBaseUnit(Unit.parseUnitString(unit));
8825 // Compose value_unit = toUnit*value_display + toUnitOffset with the unit's
8826 // own value_SI = factor*value_unit + offset.
8827 536 (converts, toUnit, toUnitOffset) := SimCodeCodegenUtil.unitConversion(unit, displayUnit);
8828
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 535 times.
536 true := converts;
8829 535 definition := SimCode.UNITDEFINITION(displayUnit,
8830 SimCode.BASEUNIT(s, m, kg, A, K, mol, cd, factor*toUnit, factor*toUnitOffset + offset));
8831 else
8832 // No dimensions, so nothing nests it and no variable may name it.
8833 2 definition := SimCode.UNITDEFINITION(displayUnit, SimCode.NOBASEUNIT());
8834 end try;
8835 end displayUnitDefinition;
8836
8837 public function transformUnitToBaseUnit
8838 "translate Unit.UNIT to SimCode.BASEUNIT. NFUnit counts mass in grams, so the
8839 factor picks up 10^-3 per kg; the offset is already in SI."
8840 input Unit.Unit unit;
8841 output SimCode.BaseUnit baseUnit;
8842 protected
8843 Integer mol, cd, m, s, A, K, kg;
8844 Real factor, offset;
8845 algorithm
8846
3/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4308 times.
✓ Branch 3 taken 4308 times.
✗ Branch 4 not taken.
4368 Unit.UNIT(s, m, kg, A, K, mol, cd, factor, offset) := unit;
8847
2/4
✓ Branch 0 taken 4308 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4308 times.
4308 baseUnit := SimCode.BASEUNIT(s, m, kg, A, K, mol, cd, factor*10^(-3*kg), offset);
8848 end transformUnitToBaseUnit;
8849
8850 protected function getAliasVar
8851 input BackendDAE.Var inVar;
8852 input Option<BackendDAE.Variables> inAliasVars;
8853 output SimCodeVar.AliasVariable outAlias;
8854 algorithm
8855 outAlias :=
8856 matchcontinue (inVar, inAliasVars)
8857 local
8858 DAE.ComponentRef name;
8859 BackendDAE.Variables aliasVars;
8860 BackendDAE.Var var;
8861 DAE.Exp e;
8862 SimCodeVar.AliasVariable alias;
8863 case (BackendDAE.VAR(varName=name), SOME(aliasVars))
8864 algorithm
8865
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 103823 times.
363072 ((var :: _), _) := BackendVariable.getVar(name, aliasVars);
8866 // does not work
8867 // e = BaseHashTable.get(name, varMappings);
8868 103823 e := BackendVariable.varBindExp(var);
8869 103823 (e, _) := ExpressionSimplify.simplify(e);
8870 103823 alias := getAliasVar1(e, var);
8871 then alias;
8872 else SimCodeVar.NOALIAS();
8873 end matchcontinue;
8874 end getAliasVar;
8875
8876 protected function getAliasVar1
8877 input DAE.Exp inExp;
8878 input BackendDAE.Var inVar;
8879 output SimCodeVar.AliasVariable outAlias;
8880 algorithm
8881 outAlias :=
8882 matchcontinue inExp
8883 local
8884 DAE.ComponentRef name;
8885 Absyn.Path fname;
8886
8887 93041 case DAE.CREF(componentRef=name) then SimCodeVar.ALIAS(name);
8888 10528 case DAE.UNARY(operator=DAE.UMINUS(_), exp=DAE.CREF(componentRef=name)) then SimCodeVar.NEGATEDALIAS(name);
8889 ✗ case DAE.UNARY(operator=DAE.UMINUS_ARR(_), exp=DAE.CREF(componentRef=name)) then SimCodeVar.NEGATEDALIAS(name);
8890 254 case DAE.LUNARY(operator=DAE.NOT(_), exp=DAE.CREF(componentRef=name)) then SimCodeVar.NEGATEDALIAS(name);
8891 case DAE.CALL(path=fname, expLst={DAE.CREF(componentRef=name)})
8892 algorithm
8893 ✗ Builtin.isDer(fname);
8894 ✗ name := ComponentReference.crefPrefixDer(name);
8895 ✗ then SimCodeVar.ALIAS(name);
8896 case DAE.UNARY(operator=DAE.UMINUS(_), exp=DAE.CALL(path=fname, expLst={DAE.CREF(componentRef=name)}))
8897 algorithm
8898 ✗ Builtin.isDer(fname);
8899 ✗ name := ComponentReference.crefPrefixDer(name);
8900 ✗ then SimCodeVar.NEGATEDALIAS(name);
8901 case DAE.UNARY(operator=DAE.UMINUS_ARR(_), exp=DAE.CALL(path=fname, expLst={DAE.CREF(componentRef=name)}))
8902 algorithm
8903 ✗ Builtin.isDer(fname);
8904 ✗ name := ComponentReference.crefPrefixDer(name);
8905 ✗ then SimCodeVar.NEGATEDALIAS(name);
8906 else SimCodeVar.NOALIAS();
8907 end matchcontinue;
8908 end getAliasVar1;
8909
8910 protected function unparseCommentOptionNoAnnotationNoQuote
8911 input Option<SCode.Comment> absynComment;
8912 output String commentStr;
8913 algorithm
8914 commentStr := match absynComment
8915 case SOME(SCode.COMMENT(_, SOME(commentStr))) then commentStr;
8916 else "";
8917 end match;
8918 end unparseCommentOptionNoAnnotationNoQuote;
8919
8920 // =============================================================================
8921 // section for ???
8922 //
8923 // =============================================================================
8924
8925 /*mahge: kernel functions*/
8926
8927 protected function dlowvarToSimvar
8928 input BackendDAE.Var dlowVar;
8929 input Option<BackendDAE.Variables> optAliasVars;
8930 input BackendDAE.Variables inVars;
8931 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars = NONE(); // optional set of iterationVars in InitializationMode
8932 output SimCodeVar.SimVar simVar;
8933 algorithm
8934 simVar := match (dlowVar, inVars)
8935 local
8936 DAE.ComponentRef cr;
8937 BackendDAE.VarKind kind;
8938 list<DAE.Dimension> inst_dims;
8939 list<String> numArrayElement;
8940 Option<DAE.VariableAttributes> dae_var_attr;
8941 Option<DAE.Exp> hideResultExp;
8942 Option<SCode.Comment> comment;
8943 BackendDAE.Type tp;
8944 String commentStr, unit, displayUnit;
8945 Option<DAE.Exp> minValue, maxValue;
8946 Option<DAE.Exp> initVal;
8947 Option<DAE.Exp> nomVal;
8948 Boolean isFixed;
8949 DAE.Type type_;
8950 Boolean isDiscrete, isValueChangeable;
8951 Option<DAE.ComponentRef> arrayCref;
8952 SimCodeVar.AliasVariable aliasvar;
8953 DAE.ElementSource source;
8954 BackendDAE.Variables vars;
8955 SimCodeVar.Causality caus;
8956 SimCodeVar.Initial initial_;
8957 SimCodeVar.Variability variability;
8958 Boolean isProtected;
8959 Option<Boolean> hideResult;
8960 Boolean encrypted;
8961 Boolean relativeQuantity;
8962
8963 // constants should not arrive here but whatever
8964 // set initial value to binding expression
8965 case ((BackendDAE.VAR(varName = cr,
8966 varKind = kind as BackendDAE.CONST(),
8967 arryDim = inst_dims,
8968 values = dae_var_attr,
8969 hideResult = hideResultExp,
8970 comment = comment,
8971 varType = tp,
8972 source = source,
8973 encrypted = encrypted)), vars)
8974 algorithm
8975 7771 commentStr := unparseCommentOptionNoAnnotationNoQuote(comment);
8976 7771 (unit, displayUnit) := extractVarUnit(dae_var_attr);
8977 7771 isProtected := BackendVariable.isProtected(dlowVar);
8978 7771 hideResult := getHideResult(hideResultExp, cr, source);
8979 7771 initVal := dlowVar.bindExp;
8980 7771 isFixed := BackendVariable.varFixed(dlowVar);
8981 type_ := tp;
8982 7771 isDiscrete := BackendVariable.isVarDiscrete(dlowVar);
8983 7771 arrayCref := ComponentReference.getArrayCref(cr);
8984 7771 aliasvar := getAliasVar(dlowVar, optAliasVars);
8985 7771 numArrayElement := List.map(inst_dims, ExpressionDump.dimensionIntString);
8986 7771 isValueChangeable := BackendVariable.isChangeable(dlowVar);
8987 7771 caus := getCausality(dlowVar, vars, isValueChangeable);
8988 variability := SimCodeVar.CONSTANT();
8989 7771 initial_ := setInitialAttribute(dlowVar, variability, caus, isFixed, iterationVars, aliasvar, vars);
8990 7771 initVal := updateStartValue(dlowVar, initVal, initial_, caus);
8991 // fix ticket https://github.com/OpenModelica/OpenModelica/issues/12533
8992
2/2
✓ Branch 1 taken 5026 times.
✓ Branch 2 taken 2745 times.
7771 if BackendVariable.isRealVar(dlowVar) then
8993 5026 relativeQuantity := SCodeUtil.optCommentHasBooleanNamedAnnotationFalse(comment, "absoluteValue");
8994 else
8995 relativeQuantity := false;
8996 end if;
8997 then
8998 SimCodeVar.SIMVAR(cr, kind, commentStr, unit, displayUnit, -1 /* use -1 to get an error in simulation if something failed */,
8999 NONE(), NONE(), initVal, NONE(), isFixed, type_, isDiscrete, arrayCref, aliasvar, source, SOME(caus), NONE(), NONE(), numArrayElement, isValueChangeable, isProtected, hideResult, encrypted, NONE(), dlowVar.initNonlinear, NONE(), SOME(variability), SOME(initial_), NONE(), relativeQuantity,
9000 match dlowVar.connectorType case DAE.FLOW() then true; else false; end match);
9001
9002 case ((BackendDAE.VAR(varName = cr,
9003 varKind = kind as BackendDAE.PARAM(),
9004 arryDim = inst_dims,
9005 values = dae_var_attr,
9006 hideResult = hideResultExp,
9007 comment = comment,
9008 varType = tp,
9009 source = source,
9010 encrypted = encrypted)), vars)
9011 algorithm
9012 134816 commentStr := unparseCommentOptionNoAnnotationNoQuote(comment);
9013 134816 (unit, displayUnit) := extractVarUnit(dae_var_attr);
9014 134816 isProtected := BackendVariable.isProtected(dlowVar);
9015 134816 hideResult := getHideResult(hideResultExp, cr, source);
9016 134816 (minValue, maxValue) := getMinMaxValues(dlowVar);
9017 134816 initVal := getStartValue(dlowVar);
9018 134816 nomVal := getNominalValue(dlowVar);
9019 134816 isFixed := BackendVariable.varFixed(dlowVar);
9020 type_ := tp;
9021 134816 isDiscrete := BackendVariable.isVarDiscrete(dlowVar);
9022 134816 arrayCref := ComponentReference.getArrayCref(cr);
9023 134816 aliasvar := getAliasVar(dlowVar, optAliasVars);
9024 134816 numArrayElement := List.map(inst_dims, ExpressionDump.dimensionIntString);
9025 134816 isValueChangeable := BackendVariable.isChangeable(dlowVar);
9026 134816 caus := getCausality(dlowVar, vars, isValueChangeable);
9027 variability := SimCodeVar.FIXED(); // PARAMETERS()
9028 134816 initial_ := setInitialAttribute(dlowVar, variability, caus, isFixed, iterationVars, aliasvar, vars);
9029 134816 initVal := updateStartValue(dlowVar, initVal, initial_, caus);
9030 // fix ticket https://github.com/OpenModelica/OpenModelica/issues/12533
9031
2/2
✓ Branch 1 taken 113480 times.
✓ Branch 2 taken 21336 times.
134816 if BackendVariable.isRealVar(dlowVar) then
9032 113480 relativeQuantity := SCodeUtil.optCommentHasBooleanNamedAnnotationFalse(comment, "absoluteValue");
9033 else
9034 relativeQuantity := false;
9035 end if;
9036 then
9037 SimCodeVar.SIMVAR(cr, kind, commentStr, unit, displayUnit, -1 /* use -1 to get an error in simulation if something failed */,
9038 minValue, maxValue, initVal, nomVal, isFixed, type_, isDiscrete, arrayCref, aliasvar, source, SOME(caus), NONE(), NONE(), numArrayElement, isValueChangeable, isProtected, hideResult, encrypted, NONE(), dlowVar.initNonlinear, NONE(), SOME(variability), SOME(initial_), SOME(cr), relativeQuantity,
9039 match dlowVar.connectorType case DAE.FLOW() then true; else false; end match);
9040
9041 // Start value of states may be changeable
9042 case ((BackendDAE.VAR(varName = cr,
9043 varKind = kind as BackendDAE.STATE(),
9044 arryDim = inst_dims,
9045 values = dae_var_attr,
9046 hideResult = hideResultExp,
9047 comment = comment,
9048 varType = tp,
9049 source = source,
9050 encrypted = encrypted)), vars)
9051 algorithm
9052 () := match BackendVariable.varStateSelect(dlowVar)
9053 case DAE.NEVER() guard(BackendVariable.isNaturalState(dlowVar))
9054 algorithm
9055 ✗ Error.addSourceMessage(Error.STATE_STATESELECT_NEVER, {ComponentReferenceBasics.printComponentRefStr(cr)}, source.info);
9056 ✗ fail();
9057 then ();
9058 else ();
9059 end match;
9060 7523 commentStr := unparseCommentOptionNoAnnotationNoQuote(comment);
9061 7523 (unit, displayUnit) := extractVarUnit(dae_var_attr);
9062 7523 isProtected := BackendVariable.isProtected(dlowVar);
9063 7523 hideResult := getHideResult(hideResultExp, cr, source);
9064 7523 (minValue, maxValue) := getMinMaxValues(dlowVar);
9065 7523 initVal := getStartValue(dlowVar);
9066 7523 nomVal := getNominalValue(dlowVar);
9067 7523 isFixed := BackendVariable.varFixed(dlowVar);
9068 type_ := tp;
9069 7523 isDiscrete := BackendVariable.isVarDiscrete(dlowVar);
9070 7523 arrayCref := ComponentReference.getArrayCref(cr);
9071 7523 aliasvar := getAliasVar(dlowVar, optAliasVars);
9072 7523 numArrayElement := List.map(inst_dims, ExpressionDump.dimensionIntString);
9073 7523 isValueChangeable := BackendVariable.isChangeable(dlowVar);
9074 7523 caus := getCausality(dlowVar, vars, isValueChangeable);
9075 variability := SimCodeVar.CONTINUOUS(); // state() should be CONTINUOUS
9076 7523 initial_ := setInitialAttribute(dlowVar, variability, caus, isFixed, iterationVars, aliasvar, vars);
9077 7523 initVal := updateStartValue(dlowVar, initVal, initial_, caus);
9078 // fix ticket https://github.com/OpenModelica/OpenModelica/issues/12533
9079
1/2
✓ Branch 1 taken 7523 times.
✗ Branch 2 not taken.
7523 if BackendVariable.isRealVar(dlowVar) then
9080 7523 relativeQuantity := SCodeUtil.optCommentHasBooleanNamedAnnotationFalse(comment, "absoluteValue");
9081 else
9082 relativeQuantity := false;
9083 end if;
9084 then
9085 SimCodeVar.SIMVAR(cr, kind, commentStr, unit, displayUnit, -1 /* use -1 to get an error in simulation if something failed */,
9086 minValue, maxValue, initVal, nomVal, isFixed, type_, isDiscrete, arrayCref, aliasvar, source, SOME(caus), NONE(), NONE(), numArrayElement, isValueChangeable, isProtected, hideResult, encrypted, NONE(), dlowVar.initNonlinear, NONE(), SOME(variability), SOME(initial_), SOME(cr), relativeQuantity,
9087 match dlowVar.connectorType case DAE.FLOW() then true; else false; end match);
9088
9089 case ((BackendDAE.VAR(varName = cr,
9090 varKind = kind,
9091
9092 arryDim = inst_dims,
9093 values = dae_var_attr,
9094 hideResult = hideResultExp,
9095 comment = comment,
9096 varType = tp,
9097 source = source,
9098 encrypted = encrypted)), vars)
9099 algorithm
9100 () := match BackendVariable.varStateSelect(dlowVar)
9101 case DAE.ALWAYS()
9102 guard valueEq(kind, BackendDAE.VARIABLE()) and not ComponentReference.isPreviousCref(cr) /* TODO: Why are clocked variables continuous and not discrete? */
9103 algorithm
9104 4 Error.addSourceMessage(Error.NON_STATE_STATESELECT_ALWAYS, {ComponentReferenceBasics.printComponentRefStr(cr)}, source.info);
9105 then ();
9106 else ();
9107 end match;
9108 253316 commentStr := unparseCommentOptionNoAnnotationNoQuote(comment);
9109 253316 (unit, displayUnit) := extractVarUnit(dae_var_attr);
9110 253316 isProtected := BackendVariable.isProtected(dlowVar);
9111 253316 hideResult := getHideResult(hideResultExp, cr, source);
9112 253316 (minValue, maxValue) := getMinMaxValues(dlowVar);
9113 253316 initVal := getStartValue(dlowVar);
9114 253316 nomVal := getNominalValue(dlowVar);
9115 253316 isFixed := BackendVariable.varFixed(dlowVar);
9116 type_ := tp;
9117 253316 isDiscrete := BackendVariable.isVarDiscrete(dlowVar);
9118 253316 arrayCref := ComponentReference.getArrayCref(cr);
9119 253316 aliasvar := getAliasVar(dlowVar, optAliasVars);
9120 253316 numArrayElement := List.map(inst_dims, ExpressionDump.dimensionIntString);
9121 253316 isValueChangeable := BackendVariable.isChangeable(dlowVar);
9122 253316 caus := getCausality(dlowVar, vars, isValueChangeable);
9123 253316 variability := getVariabilityAttribute(dlowVar);
9124 253316 initial_ := setInitialAttribute(dlowVar, variability, caus, isFixed, iterationVars, aliasvar, vars);
9125 253316 initVal := updateStartValue(dlowVar, initVal, initial_, caus);
9126 // fix ticket https://github.com/OpenModelica/OpenModelica/issues/12533
9127
2/2
✓ Branch 1 taken 240764 times.
✓ Branch 2 taken 12552 times.
253316 if BackendVariable.isRealVar(dlowVar) then
9128 240764 relativeQuantity := SCodeUtil.optCommentHasBooleanNamedAnnotationFalse(comment, "absoluteValue");
9129 else
9130 relativeQuantity := false;
9131 end if;
9132 then
9133 SimCodeVar.SIMVAR(cr, kind, commentStr, unit, displayUnit, -1 /* use -1 to get an error in simulation if something failed */,
9134 minValue, maxValue, initVal, nomVal, isFixed, type_, isDiscrete, arrayCref, aliasvar, source, SOME(caus), NONE(), NONE(), numArrayElement, isValueChangeable, isProtected, hideResult, encrypted, NONE(), dlowVar.initNonlinear, NONE(), SOME(variability), SOME(initial_), SOME(cr), relativeQuantity,
9135 match dlowVar.connectorType case DAE.FLOW() then true; else false; end match);
9136 end match;
9137 end dlowvarToSimvar;
9138
9139 protected function getCausality
9140 input BackendDAE.Var dlowVar;
9141 input BackendDAE.Variables inVars;
9142 input Boolean isValueChangeable;
9143 output SimCodeVar.Causality caus;
9144 algorithm
9145 caus := matchcontinue (dlowVar, inVars, isValueChangeable)
9146 local
9147 DAE.ComponentRef cr;
9148 BackendDAE.Variables globalKnownVars;
9149 case (BackendDAE.VAR(varDirection = DAE.OUTPUT()), _, _) then SimCodeVar.OUTPUT();
9150 case (BackendDAE.VAR(varName = cr, varDirection = DAE.INPUT()), globalKnownVars, _)
9151 algorithm
9152 301 BackendVariable.getVar(cr, globalKnownVars);
9153 then SimCodeVar.INPUT();
9154 // move to SimCodeVar from CodegenFMUCommon.tpl inorder to calculate the initial attributes from fmi export
9155 case (BackendDAE.VAR(varKind = BackendDAE.PARAM()), _, true) then SimCodeVar.PARAMETER(); //causality = parameter
9156 case (BackendDAE.VAR(varKind = BackendDAE.PARAM()), _, false) then SimCodeVar.CALCULATED_PARAMETER(); // causality = calculatedParameter
9157 else SimCodeVar.LOCAL();
9158 //TODO! Handle causality="independant", from Fmi2.0 specification it is usually variable "time"
9159 end matchcontinue;
9160 end getCausality;
9161
9162 protected function setInitialAttribute
9163 " this function sets the initial attribute of variable based
9164 on the FMI 2.0 specification table for setting initial attribute
9165 which is needed for the FMI export for adding initial unknowns in modelStructure"
9166 input BackendDAE.Var dlow;
9167 input SimCodeVar.Variability variability;
9168 input SimCodeVar.Causality causality;
9169 input Boolean isFixed;
9170 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars;
9171 input SimCodeVar.AliasVariable aliasvar;
9172 input BackendDAE.Variables globalknownVars;
9173 output SimCodeVar.Initial initial_;
9174 algorithm
9175 initial_ := match (variability, causality)
9176 // variability=CONSTANT Vs causality = output and local
9177 case (SimCodeVar.CONSTANT(), SimCodeVar.OUTPUT()) then SimCodeVar.EXACT();
9178 case (SimCodeVar.CONSTANT(), SimCodeVar.LOCAL()) then SimCodeVar.EXACT();
9179
9180 // variability=FIXED Vs causality = parameter, calculatedParameter and local
9181 case (SimCodeVar.FIXED(), SimCodeVar.PARAMETER()) then SimCodeVar.EXACT();
9182 102074 case (SimCodeVar.FIXED(), SimCodeVar.CALCULATED_PARAMETER()) then getInitialAttributeHelperForParameters(dlow, isFixed, iterationVars);
9183 276 case (SimCodeVar.FIXED(), SimCodeVar.LOCAL()) then getInitialAttributeHelperForParameters(dlow, isFixed, iterationVars);
9184
9185 // TODO varkind= tunable Vs causality = parameter, calculatedParameter and local, same like PARAM()
9186
9187 // variability=DISCRETE Vs causality = output and local
9188 104 case (SimCodeVar.DISCRETE(), SimCodeVar.OUTPUT()) then getInitialAttributeHelper(dlow, isFixed, iterationVars);
9189 13368 case (SimCodeVar.DISCRETE(), SimCodeVar.LOCAL()) then getInitialAttributeHelper(dlow, isFixed, iterationVars);
9190
9191 // varkind=Continuous Vs causality = output and local
9192 916 case (SimCodeVar.CONTINUOUS(), SimCodeVar.OUTPUT()) then getInitialAttributeHelper(dlow, isFixed, iterationVars);
9193 245874 case (SimCodeVar.CONTINUOUS(), SimCodeVar.LOCAL()) then getInitialAttributeHelper(dlow, isFixed, iterationVars);
9194
9195 // cases to handle invalid combination where initial is not allowed
9196 case (_, _) then SimCodeVar.NONE_INITIAL();
9197 end match;
9198
9199 // at most one variable in an alias set can have initial=exact
9200
4/4
✓ Branch 1 taken 315211 times.
✓ Branch 2 taken 88215 times.
✓ Branch 4 taken 88121 times.
✓ Branch 5 taken 94 times.
403426 if valueEq(initial_, SimCodeVar.EXACT()) and not valueEq(aliasvar, SimCodeVar.NOALIAS()) then
9201 initial_ := SimCodeVar.CALCULATED();
9202 end if;
9203 end setInitialAttribute;
9204
9205 protected function getInitialAttributeHelperForParameters
9206 "function which returns the initial attribute of a variable
9207 with Variablity = parameter"
9208 input BackendDAE.Var var;
9209 input Boolean isFixed;
9210 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars "list of iterationvars from InitializationDAE";
9211 output SimCodeVar.Initial initial_;
9212 algorithm
9213
9/10
✓ Branch 0 taken 1691 times.
✓ Branch 1 taken 100659 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1691 times.
✓ Branch 4 taken 1434 times.
✓ Branch 5 taken 257 times.
✓ Branch 8 taken 48 times.
✓ Branch 9 taken 1386 times.
✓ Branch 11 taken 1 time.
✓ Branch 12 taken 47 times.
102350 if not isFixed and isSome(iterationVars) and
9214 UnorderedSet.contains(var.varName, Util.getOption(iterationVars)) and startValueIsConstOrNone(var) then
9215 initial_ := SimCodeVar.APPROX();
9216 else
9217 initial_ := SimCodeVar.CALCULATED(); // default value
9218 end if;
9219 end getInitialAttributeHelperForParameters;
9220
9221 protected function startValueIsConstOrNone
9222 "Returns true iff the start value of the given variable is NONE or a literal constant.
9223 It checks the binding in case there is no start value."
9224 input BackendDAE.Var var;
9225 output Boolean b = false;
9226 protected
9227 Option<DAE.Exp> start_value = getStartValue(var);
9228 algorithm
9229 //BackendDump.dumpVarList({var}, "startValueIsConstOrNone");
9230
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 56403 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 41946 times.
✓ Branch 5 taken 14457 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 41946 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 38586 times.
✓ Branch 11 taken 3360 times.
56403 if isNone(start_value) and isNone(var.bindExp) then
9231 b := true;
9232 elseif isNone(start_value) and isSome(var.bindExp) then
9233 38586 b := Expression.isEvaluatedConst(Util.getOption(var.bindExp));
9234 else
9235 14457 b := Expression.isEvaluatedConst(Util.getOption(start_value));
9236 end if;
9237 end startValueIsConstOrNone;
9238
9239 protected function getInitialAttributeHelper
9240 "Returns the initial attribute of a variable with variablity = continuous or discrete."
9241 input BackendDAE.Var var;
9242 input Boolean isFixed;
9243 input Option<UnorderedSet<DAE.ComponentRef>> iterationVars "optional set of iterationvars from InitializationDAE";
9244 output SimCodeVar.Initial initial_;
9245 algorithm
9246
4/4
✓ Branch 0 taken 53296 times.
✓ Branch 1 taken 206966 times.
✓ Branch 3 taken 5594 times.
✓ Branch 4 taken 47702 times.
260262 if isFixed and startValueIsConstOrNone(var) then
9247 initial_ := SimCodeVar.EXACT() "initialized with start value";
9248 elseif isSome(iterationVars) and UnorderedSet.contains(var.varName, Util.getOption(iterationVars)) and startValueIsConstOrNone(var) then
9249 initial_ := SimCodeVar.APPROX();
9250 else
9251 initial_ := SimCodeVar.CALCULATED() "default";
9252 end if;
9253 end getInitialAttributeHelper;
9254
9255 protected function getVariabilityAttribute
9256 "function which sets the Variabilty attribute for FMI2.0 export"
9257 input BackendDAE.Var var;
9258 output SimCodeVar.Variability variability;
9259 algorithm
9260
2/2
✓ Branch 1 taken 253040 times.
✓ Branch 2 taken 276 times.
253316 if BackendVariable.isParam(var) then
9261 variability := SimCodeVar.FIXED();
9262 elseif BackendVariable.isConst(var) then
9263 variability := SimCodeVar.CONSTANT();
9264 elseif BackendVariable.isVarDiscrete(var) or BackendVariable.isClockedStateVar(var) then
9265 variability := SimCodeVar.DISCRETE();
9266 // TODO SimCodeVar.TUNABLE()
9267 else
9268 variability := SimCodeVar.CONTINUOUS();
9269 end if;
9270 end getVariabilityAttribute;
9271
9272 protected function isInitialExactOrApprox
9273 "return true if the initial attribute is EXACT or APPROX else false"
9274 input SimCodeVar.Initial initial_;
9275 output Boolean val;
9276 algorithm
9277 val := match initial_
9278 case SimCodeVar.EXACT() then true;
9279 case SimCodeVar.APPROX() then true;
9280 else false;
9281 end match;
9282 end isInitialExactOrApprox;
9283
9284 protected function isCausalityInput
9285 "return true if the causality attribute is input else false"
9286 input SimCodeVar.Causality causality;
9287 output Boolean val;
9288 algorithm
9289 val := match causality
9290 case SimCodeVar.INPUT() then true;
9291 else false;
9292 end match;
9293 end isCausalityInput;
9294
9295 protected function setDefaultStartValue
9296 "function which sets default start Value for
9297 an expression based on type if does not exist "
9298 input DAE.Type type_;
9299 output Option<DAE.Exp> exp;
9300 algorithm
9301 exp := match type_
9302 case DAE.T_INTEGER() then SOME(DAE.ICONST(0));
9303 case DAE.T_REAL() then SOME(DAE.RCONST(0.0));
9304 case DAE.T_BOOL() then SOME(DAE.BCONST(false));
9305 case DAE.T_STRING() then SOME(DAE.SCONST(""));
9306 1 case DAE.T_ENUMERATION() then SOME(Types.getNthEnumLiteral(type_, 1));
9307 else NONE();
9308 end match;
9309 end setDefaultStartValue;
9310
9311 protected function startValueIsConstOrDefault
9312 "function which checks the exp has constant value otherwise
9313 assign default startValue based on type"
9314 input Option<DAE.Exp> start_value;
9315 input DAE.Type type_;
9316 output Option<DAE.Exp> outstart_value;
9317 algorithm
9318
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 985 times.
✓ Branch 2 taken 985 times.
✗ Branch 3 not taken.
985 if isNone(start_value) then
9319 outstart_value := NONE();
9320 elseif Expression.isConstValue(Util.getOption(start_value)) then
9321 outstart_value := start_value;
9322 else
9323 2 outstart_value := setDefaultStartValue(type_);
9324 end if;
9325 end startValueIsConstOrDefault;
9326
9327 protected function updateStartValue
9328 "FMI requires a literal start value for a variable that is initial=exact or
9329 approx, or an input; those get the type default when the model's start is
9330 missing or is an expression. Every other variable keeps its start expression:
9331 it is the same field the code generators read `$START.x` from, and the FMI
9332 templates render only a literal anyway."
9333 input BackendDAE.Var var;
9334 input output Option<DAE.Exp> startValue;
9335 input SimCodeVar.Initial initial_;
9336 input SimCodeVar.Causality causality;
9337 algorithm
9338
10/10
✓ Branch 1 taken 10660 times.
✓ Branch 2 taken 392766 times.
✓ Branch 5 taken 4084 times.
✓ Branch 6 taken 6576 times.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 4071 times.
✓ Branch 12 taken 7080 times.
✓ Branch 13 taken 3567 times.
✓ Branch 15 taken 7035 times.
✓ Branch 16 taken 45 times.
403426 if Flags.getConfigBool(Flags.BUILDING_FMU) and (FMI.isFMIVersion20() or FMI.isFMIVersion30())
9339 and (isInitialExactOrApprox(initial_) or isCausalityInput(causality)) then
9340 startValue := match startValue
9341 985 case SOME(_) then startValueIsConstOrDefault(startValue, var.varType);
9342 2627 else setDefaultStartValue(var.varType);
9343 end match;
9344 end if;
9345 end updateStartValue;
9346
9347 protected function traversingdlowvarToSimvarFold
9348 input BackendDAE.Var v;
9349 input tuple<list<SimCodeVar.SimVar>, BackendDAE.Variables> inTpl;
9350 output tuple<list<SimCodeVar.SimVar>, BackendDAE.Variables> outTpl;
9351 algorithm
9352 3889 (_, outTpl) := traversingdlowvarToSimvar(v, inTpl);
9353 end traversingdlowvarToSimvarFold;
9354
9355 public function traversingdlowvarToSimvar
9356 input output BackendDAE.Var var;
9357 input tuple<list<SimCodeVar.SimVar>, BackendDAE.Variables> inTpl;
9358 output tuple<list<SimCodeVar.SimVar>, BackendDAE.Variables> outTpl;
9359 protected
9360 list<SimCodeVar.SimVar> sv_lst;
9361 SimCodeVar.SimVar sv;
9362 BackendDAE.Variables vars;
9363 algorithm
9364 26489 (sv_lst, vars) := inTpl;
9365 26489 sv := dlowvarToSimvar(var, NONE(), vars);
9366 26489 outTpl := (sv::sv_lst, vars);
9367 end traversingdlowvarToSimvar;
9368
9369 public function getMatchingExpsList
9370 input list<DAE.Exp> inExps;
9371 input MatchFn inFn;
9372 output list<DAE.Exp> outExpLst;
9373 partial function MatchFn
9374 input DAE.Exp inExp;
9375 input list<DAE.Exp> inExps;
9376 output DAE.Exp outExp;
9377 output list<DAE.Exp> outExps;
9378 end MatchFn;
9379 algorithm
9380 ✗ (_, outExpLst) := Expression.traverseExpList(inExps, inFn, {});
9381 end getMatchingExpsList;
9382
9383 protected function extractVarUnit "author: asodja, 2010-03-11
9384 Extract variable's unit and displayUnit as strings from
9385 DAE.VariablesAttributes structures."
9386 input Option<DAE.VariableAttributes> var_attr;
9387 output String unitStr;
9388 output String displayUnitStr;
9389 algorithm
9390 (unitStr, displayUnitStr) := matchcontinue var_attr
9391 local
9392 Option<DAE.Exp> uexp, duexp;
9393 case SOME(DAE.VAR_ATTR_REAL(unit = uexp, displayUnit=duexp))
9394 algorithm
9395 355461 unitStr := extractVarUnitStr(uexp);
9396 355436 displayUnitStr := extractVarUnitStr(duexp);
9397 then (unitStr, displayUnitStr);
9398 else ("", "");
9399 end matchcontinue;
9400 end extractVarUnit;
9401
9402 protected function extractVarUnitStr "author: asodja, 2010-03-11
9403 Extract variable's unit and displayUnit as strings from
9404 DAE.VariablesAttributes structures."
9405 input Option<DAE.Exp> exp;
9406 output String str;
9407 protected
9408 DAE.Exp e;
9409 algorithm
9410
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 710897 times.
✓ Branch 2 taken 248406 times.
✓ Branch 3 taken 462491 times.
710897 if isSome(exp) then
9411 248406 SOME(e) := exp;
9412 // TODO: When not expanding an array variable we might get an array
9413 // expression here, which can't really be handled properly right now.
9414 // For now just take the first scalar value and hope for the best.
9415 248406 e := Expression.arrayFirstScalar(e);
9416
9417 str := match e
9418 248381 case DAE.SCONST() then e.string;
9419 else
9420 algorithm
9421 25 Error.addInternalError("Unexpected expression (should have been handled earlier, probably in the front-end. Unit/displayUnit expression is not a string literal: " + ExpressionBasics.printExpStr(e), sourceInfo());
9422 25 then
9423 fail();
9424 end match;
9425 else
9426 str := "";
9427 end if;
9428 end extractVarUnitStr;
9429
9430 protected function getMinMaxValues "extract min/max values from BackendDAE.Variable"
9431 input BackendDAE.Var inDAELowVar;
9432 output Option<DAE.Exp> outMinValue;
9433 output Option<DAE.Exp> outMaxValue;
9434 algorithm
9435 // Real, Integer and enumeration variables can all carry min/max (see #15947).
9436 (outMinValue, outMaxValue) := match inDAELowVar.varType
9437 361767 case DAE.T_REAL() then DAEUtil.getMinMaxValues(inDAELowVar.values);
9438 13384 case DAE.T_INTEGER() then DAEUtil.getMinMaxValues(inDAELowVar.values);
9439 2972 case DAE.T_ENUMERATION() then DAEUtil.getMinMaxValues(inDAELowVar.values);
9440 17532 else (NONE(), NONE());
9441 end match;
9442 end getMinMaxValues;
9443
9444 protected function getStartValue "Extract initial value from BackendDAE.Var, if it has any"
9445 input BackendDAE.Var daelowVar;
9446 output Option<DAE.Exp> initVal;
9447 algorithm
9448 initVal := matchcontinue daelowVar
9449 local
9450 Option<DAE.VariableAttributes> dae_var_attr;
9451 DAE.Exp e;
9452 DAE.Type tp;
9453
9454 // Don't extract bindings of scalar parameters to tuples or records (#10505).
9455 // They are treated by createParameterEquations calling createSimEqsForGlobalKnownVars.
9456 case BackendDAE.VAR(varKind = BackendDAE.PARAM(), tplExp = SOME(_))
9457 then NONE();
9458
9459 case BackendDAE.VAR(varKind = BackendDAE.VARIABLE(), values = dae_var_attr) algorithm
9460 239510 e := DAEUtil.getStartAttrFail(dae_var_attr);
9461 then SOME(e);
9462
9463 case BackendDAE.VAR(varKind = BackendDAE.DISCRETE(), values = dae_var_attr) algorithm
9464 18337 e := DAEUtil.getStartAttrFail(dae_var_attr);
9465 then SOME(e);
9466
9467 case BackendDAE.VAR(varKind = BackendDAE.STATE(), values = dae_var_attr) algorithm
9468 14314 e := DAEUtil.getStartAttrFail(dae_var_attr);
9469 then SOME(e);
9470
9471 case BackendDAE.VAR(varKind = BackendDAE.ALG_STATE(), values = dae_var_attr) algorithm
9472 715 e := DAEUtil.getStartAttrFail(dae_var_attr);
9473 then SOME(e);
9474
9475 case BackendDAE.VAR(varKind = BackendDAE.DUMMY_DER(), values = dae_var_attr) algorithm
9476 8638 e := DAEUtil.getStartAttrFail(dae_var_attr);
9477 then SOME(e);
9478
9479 case BackendDAE.VAR(varKind = BackendDAE.DUMMY_STATE(), values = dae_var_attr) algorithm
9480 10086 e := DAEUtil.getStartAttrFail(dae_var_attr);
9481 then SOME(e);
9482
9483 // C RUNTIME
9484 // Parameters with binding
9485 case BackendDAE.VAR(varKind = BackendDAE.PARAM(), bindExp = SOME(e)) guard not stringEq(Config.simCodeTarget(), "Cpp")
9486 then SOME(e);
9487
9488 // C RUNTIME
9489 // Parameters without binding. Investigate if it has start value
9490 case BackendDAE.VAR(varKind = BackendDAE.PARAM(), values = dae_var_attr, varType = tp) guard not stringEq(Config.simCodeTarget(), "Cpp") algorithm
9491 1027 e := DAEUtil.getStartAttr(dae_var_attr, tp);
9492 then SOME(e);
9493
9494 // CPP RUNTIME
9495 // Parameters with constant binding
9496 case BackendDAE.VAR(varKind = BackendDAE.PARAM(), bindExp = SOME(e)) guard Expression.isConst(e) and stringEq(Config.simCodeTarget(), "Cpp")
9497 then SOME(e);
9498
9499 // CPP RUNTIME
9500 // Parameters without constant binding. Investigate if it has start value
9501 case BackendDAE.VAR(varKind = BackendDAE.PARAM(), values = dae_var_attr) guard stringEq(Config.simCodeTarget(), "Cpp") algorithm
9502 745 e := DAEUtil.getStartAttrFail(dae_var_attr);
9503 then SOME(e);
9504
9505 case BackendDAE.VAR(varKind = BackendDAE.EXTOBJ(_), bindExp = SOME(e))
9506 then SOME(e);
9507
9508 case BackendDAE.VAR(values = dae_var_attr) guard(BackendVariable.isVarNonDiscreteAlg(daelowVar))
9509 208435 then SOME(DAEUtil.getStartAttrFail(dae_var_attr));
9510
9511 else NONE();
9512 end matchcontinue;
9513 end getStartValue;
9514
9515 protected function getNominalValue "Extract nominal value from BackendDAE.Variable, if it has any"
9516 input BackendDAE.Var daelowVar;
9517 output Option<DAE.Exp> nomVal;
9518 algorithm
9519 nomVal := matchcontinue daelowVar
9520 local
9521 Option<DAE.VariableAttributes> dae_var_attr;
9522 DAE.Exp e;
9523
9524 case BackendDAE.VAR(varType = DAE.T_REAL(), values = dae_var_attr) algorithm
9525 361767 e := DAEUtil.getNominalAttrFail(dae_var_attr);
9526 // lochel: #2597
9527 // true = Expression.isConstValue(e);
9528 then SOME(e);
9529
9530 else NONE();
9531 end matchcontinue;
9532 end getNominalValue;
9533
9534 public function functionPath
9535 input SimCodeFunction.Function fn;
9536 output Absyn.Path name;
9537 algorithm
9538 name := match fn
9539 case SimCodeFunction.FUNCTION(name=name) then name;
9540 case SimCodeFunction.PARALLEL_FUNCTION(name=name) then name;
9541 case SimCodeFunction.KERNEL_FUNCTION(name=name) then name;
9542 case SimCodeFunction.EXTERNAL_FUNCTION(name=name) then name;
9543 case SimCodeFunction.RECORD_CONSTRUCTOR(name=name) then name;
9544 end match;
9545 end functionPath;
9546
9547
9548 protected function adjustStatesForInlineSolver
9549 input list<SimCodeVar.SimVar> inStates;
9550 output list<SimCodeVar.SimVar> outStates = {};
9551 algorithm
9552 try
9553
2/2
✓ Branch 1 taken 350 times.
✓ Branch 2 taken 12 times.
362 for var in inStates loop
9554 350 var.name := ComponentReference.appendStringLastIdent("$Old", var.name);
9555 350 var.varKind := BackendDAE.ALG_STATE_OLD();
9556 outStates := var::outStates;
9557 end for;
9558 else
9559 ✗ Error.addMessage(Error.INTERNAL_ERROR,{"SimCodeUtil.adjustStatesForInlineSolver failed"});
9560 ✗ fail();
9561 end try;
9562 end adjustStatesForInlineSolver;
9563
9564 /**************************************/
9565 /************* for index ***************/
9566
9567 protected function setVariableDerIndex "
9568 Author bz 2008-06
9569 This function investigates the system of equations finding an order for derivative variables.
9570 It only selects variables that have an derivative order, order=0 (no derivative) will not be included.
9571 "
9572 input BackendDAE.BackendDAE inDlow;
9573 input BackendDAE.EqSystems inEqSystems;
9574 output list<tuple<DAE.ComponentRef, Integer>> outOrder;
9575 algorithm outOrder := matchcontinue inEqSystems
9576 local
9577 list<tuple<DAE.ComponentRef, Integer>> variableIndex;
9578 list<tuple<DAE.ComponentRef, Integer>> variableIndex2;
9579 list<tuple<DAE.ComponentRef, Integer>> variableIndex3;
9580 BackendDAE.EqSystem syst;
9581 BackendDAE.EqSystems systs;
9582 case {}
9583 then
9584 {};
9585 case syst::systs
9586 algorithm
9587 ✗ if Flags.isSet(Flags.FAILTRACE) then
9588 ✗ print(" set variabale der index for eqsystem"+ "\n");
9589 end if;
9590 ✗ variableIndex := setVariableDerIndex2(inDlow, syst);
9591 ✗ variableIndex2 := setVariableDerIndex(inDlow, systs);
9592 ✗ variableIndex3 := listAppend(variableIndex, variableIndex2);
9593 then variableIndex3;
9594 else
9595 algorithm
9596 ✗ print(" Failure in setVariableDerIndex\n");
9597 ✗ then fail();
9598 end matchcontinue;
9599 end setVariableDerIndex;
9600
9601
9602 protected function setVariableDerIndex2 "
9603 Author bz 2008-06
9604 This function investigates the system of equations finding an order for derivative variables.
9605 It only selects variables that have an derivative order, order=0 (no derivative) will not be included.
9606 "
9607 input BackendDAE.BackendDAE inDlow;
9608 input BackendDAE.EqSystem syst;
9609 output list<tuple<DAE.ComponentRef, Integer>> outOrder;
9610 algorithm outOrder := matchcontinue syst
9611 local
9612 BackendDAE.Variables dovars;
9613 BackendDAE.EquationArray deqns;
9614 list<BackendDAE.Equation> eqns;
9615 list<BackendDAE.Var> vars;
9616 list<DAE.Exp> derExps;
9617 list<tuple<DAE.ComponentRef, Integer>> variableIndex;
9618 list<list<DAE.ComponentRef>> firstOrderVars;
9619 list<DAE.ComponentRef> firstOrderVarsFiltered;
9620 case _
9621 algorithm
9622 ✗ if Flags.isSet(Flags.FAILTRACE) then
9623 ✗ print(" set variabale der index"+ "\n");
9624 end if;
9625 ✗ dovars := BackendVariable.daeVars(syst);
9626 ✗ deqns := BackendEquation.getEqnsFromEqSystem(syst);
9627 ✗ vars := BackendVariable.varList(dovars);
9628 ✗ eqns := BackendEquation.equationList(deqns);
9629 ✗ derExps := makeCallDerExp(vars);
9630 ✗ if Flags.isSet(Flags.FAILTRACE) then
9631 ✗ print(" possible der exp: " + stringDelimitList(List.map(derExps, ExpressionBasics.printExpStr), ", ") + "\n");
9632 end if;
9633 ✗ eqns := flattenEqns(eqns, inDlow);
9634 // eq_str=dumpEqLst(eqns);
9635 // fcall(Flags.FAILTRACE, print, "filtered eq's " + eq_str + "\n");
9636 ✗ (variableIndex, firstOrderVars) := List.map2_2(derExps, locateDerAndSerachOtherSide, eqns, eqns);
9637 ✗ if Flags.isSet(Flags.FAILTRACE) then
9638 ✗ print("united variables\n");
9639 end if;
9640 ✗ firstOrderVarsFiltered := List.fold(firstOrderVars, List.union, {});
9641 ✗ if Flags.isSet(Flags.FAILTRACE) then
9642 ✗ print("list fold variables\n");
9643 end if;
9644 ✗ variableIndex := setFirstOrderInSecondOrderVarIndex(variableIndex, firstOrderVarsFiltered);
9645 // fcall(Flags.FAILTRACE, print, "Deriving Variable indexis:\n" + dumpVariableindex(variableIndex) + "\n");
9646 then
9647 variableIndex;
9648 else
9649 algorithm
9650 ✗ print(" Failure in setVariableDerIndex2\n");
9651 ✗ then fail();
9652 end matchcontinue;
9653 end setVariableDerIndex2;
9654
9655
9656
9657
9658 protected function flattenEqns "
9659 This function flattens all equations
9660 "
9661 input list<BackendDAE.Equation> eqns;
9662 input BackendDAE.BackendDAE dlow;
9663 output list<BackendDAE.Equation> oeqns;
9664 algorithm oeqns := matchcontinue eqns
9665 local
9666 BackendDAE.Equation eq;
9667 list<BackendDAE.Equation> rest, rec;
9668 String str;
9669 case {} then {};
9670 case (eq as BackendDAE.EQUATION()) ::rest
9671 algorithm
9672 ✗ rec := flattenEqns(rest, dlow);
9673 ✗ rec := List.unionElt(eq, rec);
9674 then
9675 rec;
9676 case (eq as BackendDAE.WHEN_EQUATION()) ::rest
9677 algorithm
9678 ✗ str := BackendDump.equationString(eq);
9679 ✗ if Flags.isSet(Flags.FAILTRACE) then
9680 ✗ print("Found When eq " + str + "\n");
9681 end if;
9682 ✗ rec := flattenEqns(rest, dlow);
9683 // rec = List.unionElt(eq, rec);
9684 then
9685 rec;
9686 case (eq as BackendDAE.ALGORITHM()) ::rest
9687 algorithm
9688 // str = DAELow.equationStr(eq);
9689 ✗ rec := flattenEqns(rest, dlow);
9690 ✗ rec := List.unionElt(eq, rec);
9691 then
9692 rec;
9693 case (eq as BackendDAE.ARRAY_EQUATION()) ::rest
9694 algorithm
9695 // str = DAELow.equationStr(eq);
9696 ✗ rec := flattenEqns(rest, dlow);
9697 ✗ rec := List.unionElt(eq, rec);
9698 then
9699 rec;
9700 case (eq as BackendDAE.COMPLEX_EQUATION()) ::rest
9701 algorithm
9702 // str = DAELow.equationStr(eq);
9703 ✗ rec := flattenEqns(rest, dlow);
9704 ✗ rec := List.unionElt(eq, rec);
9705 then
9706 rec;
9707 case _::_
9708 algorithm
9709 // str = BackendDAE.equationStr(eq);
9710 ✗ true := Flags.isSet(Flags.FAILTRACE);
9711 ✗ print(" FAILURE IN flattenEqns possible unsupported equation...\n" /*+ str*/);
9712 ✗ then
9713 fail();
9714 end matchcontinue;
9715 end flattenEqns;
9716
9717 protected function makeCallDerExp "
9718 Author bz 2008-06
9719 For all state-variables, generate an der(var) expression.
9720 "
9721 input list<BackendDAE.Var> inVars;
9722 output list<DAE.Exp> outDerExps;
9723 algorithm outDerExps := matchcontinue inVars
9724 local
9725 list<BackendDAE.Var> vars;
9726 list<DAE.Exp> rec;
9727 DAE.ComponentRef cr;
9728 case {} then {};
9729 case (BackendDAE.VAR(varKind = BackendDAE.STATE(), varName = cr))::vars
9730 algorithm
9731 // true = DAELow.isStateVar(v);
9732 ✗ rec := makeCallDerExp(vars);
9733 ✗ then
9734 DAE.CALL(Absyn.IDENT("der"), {DAE.CREF(cr, DAE.T_REAL_DEFAULT)}, DAE.callAttrBuiltinReal)::rec;
9735 // case((v as DAELow.VAR(varKind = DAELow.DUMMY_STATE(), varName = cr))::vars)
9736 // equation
9737 // true = DAELow.isStateVar(v);
9738 // rec = makeCallDerExp(vars);
9739 // then
9740 // DAE.CALL(Absyn.IDENT("der"), {DAE.CREF(cr, DAE.T_UNKNOWN_DEFAULT)}, false, false, DAE.T_UNKNOWN_DEFAULT, DAE.NO_INLINE())::rec;
9741 case _::vars
9742 algorithm
9743 ✗ rec := makeCallDerExp(vars);
9744 then
9745 rec;
9746 end matchcontinue;
9747 end makeCallDerExp;
9748
9749 protected function locateDerAndSerachOtherSide "
9750 Author bz 2008-06
9751 helper function for setVariableDerIndex, locates the equation(/s) containing the current derivate.
9752 From there search for the variable beeing derived, exclude 'current equation'
9753 "
9754 input DAE.Exp derExp;
9755 input list<BackendDAE.Equation> inEqns;
9756 input list<BackendDAE.Equation> inEqnsOrg;
9757 output tuple<DAE.ComponentRef, Integer> out;
9758 output list<DAE.ComponentRef> sysOrdOneVars;
9759 algorithm (out, sysOrdOneVars) := matchcontinue(derExp, inEqns)
9760 local
9761 DAE.Exp e1, e2, deriveVar;
9762 list<BackendDAE.Equation> eqs, eqsOrg;
9763 BackendDAE.Equation eq;
9764 list<DAE.ComponentRef> crefs;
9765 DAE.ComponentRef cr;
9766 Integer rec, i1;
9767 tuple<DAE.ComponentRef, Integer> highestIndex;
9768
9769 ✗ case((DAE.CALL( expLst = {DAE.CREF(cr, _)})), {}) then ((cr, 0), {});
9770 case((DAE.CALL( expLst = {deriveVar as DAE.CREF(cr, _)})), (eq as BackendDAE.EQUATION(exp=e1, scalar=e2))::eqs)
9771 algorithm
9772 ✗ true := ExpressionBasics.expEqual(e1, derExp);
9773 ✗ eqsOrg := List.removeOnTrue(eq, valueEq, inEqnsOrg);
9774 ✗ if Flags.isSet(Flags.FAILTRACE) then
9775 ✗ print("\nFound equation containing " + ExpressionBasics.printExpStr(derExp) + " Other side: " + ExpressionBasics.printExpStr(e2) + ", extracted crefs: " + ExpressionBasics.printExpStr(deriveVar) + "\n");
9776 end if;
9777 ✗ (rec, crefs) := locateDerAndSerachOtherSide2(DAE.CALL(Absyn.IDENT("der"), {e2}, DAE.callAttrBuiltinReal), eqsOrg);
9778 ✗ (highestIndex as (_, i1), _) := locateDerAndSerachOtherSide(derExp, eqs, eqsOrg);
9779 ✗ rec := rec+1;
9780 ✗ highestIndex := if i1>rec then highestIndex else (cr, rec-1);
9781 // highestIndex = (cr, 1);
9782 ✗ then
9783 (highestIndex, crefs);
9784 case((DAE.CALL( expLst = {deriveVar as DAE.CREF(cr, _)})), (eq as BackendDAE.EQUATION(exp=e1, scalar=e2))::eqs)
9785 algorithm
9786 ✗ true := ExpressionBasics.expEqual(e2, derExp);
9787 ✗ eqsOrg := List.removeOnTrue(eq, valueEq, inEqnsOrg);
9788 ✗ if Flags.isSet(Flags.FAILTRACE) then
9789 ✗ print("\nFound equation containing " + ExpressionBasics.printExpStr(derExp) + " Other side: " + ExpressionBasics.printExpStr(e1) + ", extracted crefs: " + ExpressionBasics.printExpStr(deriveVar) + "\n");
9790 end if;
9791 ✗ (rec, crefs) := locateDerAndSerachOtherSide2(DAE.CALL(Absyn.IDENT("der"), {e1}, DAE.callAttrBuiltinReal), eqsOrg);
9792 ✗ (highestIndex as (_, i1), _) := locateDerAndSerachOtherSide(derExp, eqs, eqsOrg);
9793 ✗ rec := rec+1;
9794 ✗ highestIndex := if i1>rec then highestIndex else (cr, rec-1);
9795 // highestIndex = (cr, 1);
9796 ✗ then
9797 (highestIndex, crefs);
9798 case(_, (BackendDAE.EQUATION(exp=e1, scalar=e2))::eqs)
9799 algorithm
9800 ✗ false := ExpressionBasics.expEqual(e1, derExp);
9801 ✗ false := ExpressionBasics.expEqual(e2, derExp);
9802 ✗ (highestIndex, crefs) := locateDerAndSerachOtherSide(derExp, eqs, inEqnsOrg);
9803 then
9804 (highestIndex, crefs);
9805 case(_, (BackendDAE.ARRAY_EQUATION(left=e1, right=e2))::eqs)
9806 algorithm
9807 ✗ false := ExpressionBasics.expEqual(e1, derExp);
9808 ✗ false := ExpressionBasics.expEqual(e2, derExp);
9809 ✗ (highestIndex, crefs) := locateDerAndSerachOtherSide(derExp, eqs, inEqnsOrg);
9810 then
9811 (highestIndex, crefs);
9812 case(_, (BackendDAE.COMPLEX_EQUATION(left=e1, right=e2))::eqs)
9813 algorithm
9814 ✗ false := ExpressionBasics.expEqual(e1, derExp);
9815 ✗ false := ExpressionBasics.expEqual(e2, derExp);
9816 ✗ (highestIndex, crefs) := locateDerAndSerachOtherSide(derExp, eqs, inEqnsOrg);
9817 then
9818 (highestIndex, crefs);
9819 case(_, (BackendDAE.IF_EQUATION())::eqs)
9820 algorithm
9821 ✗ if Flags.isSet(Flags.FAILTRACE) then
9822 ✗ print("\nFound if equation is not supported yet searching for varibale index\n");
9823 end if;
9824 ✗ (highestIndex, crefs) := locateDerAndSerachOtherSide(derExp, eqs, inEqnsOrg);
9825 then
9826 (highestIndex, crefs);
9827 case(_, (BackendDAE.ALGORITHM())::eqs)
9828 algorithm
9829 ✗ if Flags.isSet(Flags.FAILTRACE) then
9830 ✗ print("\nFound algorithm is not supported yet searching for varibale index\n");
9831 end if;
9832 ✗ (highestIndex, crefs) := locateDerAndSerachOtherSide(derExp, eqs, inEqnsOrg);
9833 then
9834 (highestIndex, crefs);
9835
9836 end matchcontinue;
9837 end locateDerAndSerachOtherSide;
9838
9839 protected function locateDerAndSerachOtherSide2 "
9840 Author bz 2008-06
9841 helper function for locateDerAndSerachOtherSide"
9842 input DAE.Exp inDer;
9843 input list<BackendDAE.Equation> inEqns;
9844 output Integer oi;
9845 output list<DAE.ComponentRef> firstOrderDers;
9846 algorithm (oi, firstOrderDers) := matchcontinue inDer
9847 case DAE.CALL(expLst = {DAE.CREF(_, _)})
9848 algorithm
9849 ✗ (oi, firstOrderDers) := locateDerAndSerachOtherSide22(inDer, inEqns);
9850 then
9851 (oi, firstOrderDers);
9852 ✗ else (0, {});
9853 end matchcontinue;
9854 end locateDerAndSerachOtherSide2;
9855
9856 protected function locateDerAndSerachOtherSide22 "
9857 Author bz 2008-06
9858 recursivly search equations for der(..) expressions.
9859 When found, return 1... this since we are only interested in second order system, at most.
9860 If we do not find any more derivative, 0 is returned.
9861 "
9862 input DAE.Exp inDer;
9863 input list<BackendDAE.Equation> inEqns;
9864 output Integer oi;
9865 output list<DAE.ComponentRef> firstOrderDers;
9866 algorithm (oi, firstOrderDers) := matchcontinue inEqns
9867 local
9868 DAE.Exp e1, e2;
9869 DAE.ComponentRef cr;
9870 list<BackendDAE.Equation> rest;
9871 ✗ case {} then (0, {});
9872 case BackendDAE.EQUATION(exp=e1, scalar=e2)::_
9873 algorithm
9874 ✗ true := ExpressionBasics.expEqual(inDer, e1);
9875 ✗ {cr} := Expression.extractCrefsFromExp(e1);
9876 ✗ if Flags.isSet(Flags.FAILTRACE) then
9877 ✗ BackendDump.debugStrExpStrExpStrExpStr(" found derivative for ", inDer, " in equation ", e1, " = ", e2, "\n");
9878 end if;
9879 ✗ then
9880 (1, {cr});
9881 case BackendDAE.EQUATION(exp=e1, scalar=e2)::_
9882 algorithm
9883 ✗ true := ExpressionBasics.expEqual(inDer, e2);
9884 ✗ {cr} := Expression.extractCrefsFromExp(e2);
9885 ✗ if Flags.isSet(Flags.FAILTRACE) then
9886 ✗ BackendDump.debugStrExpStrExpStrExpStr(" found derivative for ", inDer, " in equation ", e1, " = ", e2, "\n");
9887 end if;
9888 ✗ then
9889 (1, {cr});
9890 case BackendDAE.EQUATION(exp=e1, scalar=e2)::rest
9891 algorithm
9892 ✗ if Flags.isSet(Flags.FAILTRACE) then
9893 ✗ BackendDump.debugExpStrExpStrExpStr(inDer, " NOT contained in ", e1, " = ", e2, "\n");
9894 end if;
9895 ✗ (oi, firstOrderDers) := locateDerAndSerachOtherSide22(inDer, rest);
9896 then
9897 (oi, firstOrderDers);
9898 end matchcontinue;
9899 end locateDerAndSerachOtherSide22;
9900
9901 protected function setFirstOrderInSecondOrderVarIndex "
9902 Author bz 2008-06
9903 "
9904 input list<tuple<DAE.ComponentRef, Integer>> inRefs;
9905 input list<DAE.ComponentRef> firstOrderInSec;
9906 output list<tuple<DAE.ComponentRef, Integer>> outRefs;
9907 algorithm outRefs := matchcontinue inRefs
9908 local
9909 list<tuple<DAE.ComponentRef, Integer>> rest;
9910 Integer idx;
9911 DAE.ComponentRef cr;
9912
9913 case {} then {};
9914 case (cr, _)::rest
9915 algorithm
9916 ✗ true := List.any(firstOrderInSec, function ComponentReferenceBasics.crefEqual(inComponentRef2 = cr));
9917 ✗ rest := setFirstOrderInSecondOrderVarIndex(rest, firstOrderInSec);
9918 ✗ then
9919 (cr, 2)::rest;
9920 case (cr, 1)::rest
9921 algorithm
9922 ✗ rest := setFirstOrderInSecondOrderVarIndex(rest, firstOrderInSec);
9923 ✗ then
9924 (cr, 1)::rest;
9925 case (cr, idx)::rest
9926 algorithm
9927 ✗ rest := setFirstOrderInSecondOrderVarIndex(rest, firstOrderInSec);
9928 ✗ then
9929 (cr, idx)::rest;
9930 end matchcontinue;
9931 end setFirstOrderInSecondOrderVarIndex;
9932
9933 /********* for dimension *******/
9934
9935 protected function calculateVariableDimensions "
9936 Calcuates the dimension of the statevaribale with order 0, 1, 2
9937 "
9938 input list<tuple<DAE.ComponentRef, Integer>> in_vars;
9939 input Integer inNvar1;
9940 input Integer inNvar2;
9941 output Integer OutInteger1; // number of ordinary differential equations of 1st order
9942 output Integer OutInteger2; // number of ordinary differential equations of 2st order
9943
9944 algorithm (OutInteger1, OutInteger2) := match in_vars
9945 local
9946 list<tuple<DAE.ComponentRef, Integer>> rest;
9947 case {} then (inNvar1, inNvar2);
9948 case (_, 0)::rest
9949 ✗ then
9950 calculateVariableDimensions(rest,inNvar1+1,inNvar2);
9951 case (_, _)::rest
9952 ✗ then
9953 calculateVariableDimensions(rest,inNvar1,inNvar2+1);
9954 end match;
9955 end calculateVariableDimensions;
9956
9957 /********************/
9958 protected function dimensions
9959
9960 input BackendDAE.BackendDAE dae_low;
9961 output Integer OutInteger1; // number of ordinary differential equations of 1st order
9962 output Integer OutInteger2; // number of ordinary differential equations of 2st order
9963 algorithm (OutInteger1, OutInteger2):= matchcontinue dae_low
9964 local
9965 Integer nvar1, nvar2;
9966 list<tuple<DAE.ComponentRef, Integer>> ordered_states;
9967 BackendDAE.EqSystems eqsystems;
9968 case BackendDAE.DAE(eqs=eqsystems)
9969 algorithm
9970 ✗ ordered_states:=setVariableDerIndex(dae_low, eqsystems);
9971 ✗ (nvar1, nvar2):=calculateVariableDimensions(ordered_states,0,0);
9972 then
9973 (nvar1, nvar2);
9974 else
9975 ✗ algorithm print(" failure in dimensions\n"); then fail();
9976 end matchcontinue;
9977 end dimensions;
9978
9979 /******************/
9980 /******************/
9981
9982 protected function compareSimVarName
9983 input SimCodeVar.SimVar var1;
9984 input SimCodeVar.SimVar var2;
9985 output Boolean result;
9986 protected
9987 DAE.ComponentRef name1, name2;
9988 algorithm
9989 ✗ SimCodeVar.SIMVAR(name = name1) := var1;
9990 ✗ SimCodeVar.SIMVAR(name = name2) := var2;
9991 ✗ result := ComponentReferenceBasics.crefEqual(name1, name2);
9992 end compareSimVarName;
9993
9994 public function compareVarIndexGt
9995 input SimCodeVar.SimVar var1;
9996 input SimCodeVar.SimVar var2;
9997 output Boolean result;
9998 protected
9999 Integer index1, index2;
10000 algorithm
10001
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 82128 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82128 times.
82128 SimCodeVar.SIMVAR(variable_index=SOME(index1)) := var1;
10002
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 82128 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82128 times.
82128 SimCodeVar.SIMVAR(variable_index=SOME(index2)) := var2;
10003 82128 result := index1 > index2;
10004 end compareVarIndexGt;
10005
10006 public function compareSimVarTupleIndexGt<anyT>
10007 input tuple<SimCodeVar.SimVar, anyT> var1;
10008 input tuple<SimCodeVar.SimVar, anyT> var2;
10009 output Boolean result;
10010 protected
10011 Integer index1, index2;
10012 algorithm
10013 ✗ (SimCodeVar.SIMVAR(variable_index=SOME(index1)),_) := var1;
10014 ✗ (SimCodeVar.SIMVAR(variable_index=SOME(index2)),_) := var2;
10015 ✗ result := index1 > index2;
10016 end compareSimVarTupleIndexGt;
10017
10018 protected function getFilesFromSimVar
10019 input output SimCodeVar.SimVar var;
10020 input SimCode.Files inFiles;
10021 output SimCode.Files outFiles;
10022 algorithm
10023 ✗ outFiles := getFilesFromDAEElementSource(var.source, inFiles);
10024 end getFilesFromSimVar;
10025
10026 protected function getFilesFromSimVars
10027 input SimCodeVar.SimVars inSimVars;
10028 input SimCode.Files inFiles;
10029 output SimCode.Files outFiles;
10030 algorithm
10031 outFiles := match(inSimVars, inFiles)
10032 local
10033 SimCode.Files files;
10034 list<SimCodeVar.SimVar> stateVars, derivativeVars, algVars, discreteAlgVars, intAlgVars, boolAlgVars, inputVars, outputVars, aliasVars, intAliasVars,
10035 boolAliasVars, paramVars, intParamVars, boolParamVars, stringAlgVars, stringParamVars, stringAliasVars,
10036 extObjVars, constVars, intConstVars, boolConstVars, stringConstVars, jacobianVars, seedVars, realOptimizeConstraintsVars, realOptimizeFinalConstraintsVars, sensitivityVars;
10037
10038 case (SimCodeVar.SIMVARS(stateVars, derivativeVars, algVars, discreteAlgVars, intAlgVars, boolAlgVars, inputVars, outputVars, aliasVars, intAliasVars, boolAliasVars,
10039 paramVars, intParamVars, boolParamVars, stringAlgVars, stringParamVars, stringAliasVars, extObjVars, constVars, intConstVars, boolConstVars, stringConstVars, jacobianVars, seedVars, realOptimizeConstraintsVars, realOptimizeFinalConstraintsVars, sensitivityVars),
10040 files)
10041 algorithm
10042 ✗ (_, files) := List.mapFoldList(
10043 {stateVars, derivativeVars, algVars, discreteAlgVars, intAlgVars, boolAlgVars, inputVars, outputVars, aliasVars, intAliasVars, boolAliasVars,
10044 paramVars, intParamVars, boolParamVars, stringAlgVars, stringParamVars, stringAliasVars, extObjVars, constVars, intConstVars, boolConstVars, stringConstVars, jacobianVars, seedVars, realOptimizeConstraintsVars, realOptimizeFinalConstraintsVars, sensitivityVars},
10045 getFilesFromSimVar, files);
10046 ✗ then
10047 files;
10048 end match;
10049 end getFilesFromSimVars;
10050
10051 protected function getFilesFromFunctions
10052 input list<SimCodeFunction.Function> functions;
10053 input SimCode.Files inFiles;
10054 output SimCode.Files outFiles;
10055 algorithm
10056 outFiles := match(functions, inFiles)
10057 local
10058 SimCode.Files files;
10059 list<SimCodeFunction.Function> rest;
10060 SourceInfo info;
10061
10062 // handle empty
10063 case ({}, files) then files;
10064
10065 // handle FUNCTION
10066 case (SimCodeFunction.FUNCTION(info = info)::rest, files)
10067 algorithm
10068 ✗ files := getFilesFromAbsynInfo(info, files);
10069 ✗ files := getFilesFromFunctions(rest, files);
10070 then
10071 files;
10072
10073 // handle EXTERNAL_FUNCTION
10074 case (SimCodeFunction.EXTERNAL_FUNCTION(info = info)::rest, files)
10075 algorithm
10076 ✗ files := getFilesFromAbsynInfo(info, files);
10077 ✗ files := getFilesFromFunctions(rest, files);
10078 then
10079 files;
10080
10081 // handle RECORD_CONSTRUCTOR
10082 case (SimCodeFunction.RECORD_CONSTRUCTOR(info = info)::rest, files)
10083 algorithm
10084 ✗ files := getFilesFromAbsynInfo(info, files);
10085 ✗ files := getFilesFromFunctions(rest, files);
10086 then
10087 files;
10088 end match;
10089 end getFilesFromFunctions;
10090
10091 protected function getFilesFromSimEqSystemOpt
10092 input Option<SimCode.SimEqSystem> inSimEqSystemOpt;
10093 input SimCode.Files inFiles;
10094 output SimCode.Files outFiles;
10095 algorithm
10096 outFiles := match(inSimEqSystemOpt, inFiles)
10097 local
10098 SimCode.Files files;
10099 SimCode.SimEqSystem sys;
10100
10101 case (NONE(), files) then files;
10102 case (SOME(sys), files)
10103 algorithm
10104 ✗ (_, files) := getFilesFromSimEqSystem(sys, files);
10105 ✗ then
10106 files;
10107 end match;
10108 end getFilesFromSimEqSystemOpt;
10109
10110 protected function getFilesFromSimEqSystem
10111 input SimCode.SimEqSystem inSimEqSystem;
10112 input SimCode.Files inFiles;
10113 output SimCode.SimEqSystem outSimEqSystem;
10114 output SimCode.Files outFiles;
10115 algorithm
10116 (outSimEqSystem, outFiles) := match(inSimEqSystem, inFiles)
10117 local
10118 SimCode.Files files;
10119 DAE.ElementSource source;
10120 list<DAE.Statement> statements;
10121 list<SimCodeVar.SimVar> vars;
10122 list<tuple<Integer, Integer, SimCode.SimEqSystem>> simJac;
10123 list<SimCode.SimEqSystem> systems;
10124 SimCode.SimEqSystem system;
10125 Option<SimCode.SimEqSystem> systemOpt;
10126 list<BackendDAE.WhenOperator> whenStmtLst;
10127
10128 case (SimCode.SES_RESIDUAL(source = source), files)
10129 algorithm
10130 ✗ files := getFilesFromDAEElementSource(source, files);
10131 then
10132 (inSimEqSystem, files);
10133
10134 case (SimCode.SES_FOR_RESIDUAL(source = source), files)
10135 algorithm
10136 ✗ files := getFilesFromDAEElementSource(source, files);
10137 then
10138 (inSimEqSystem, files);
10139
10140 case (SimCode.SES_GENERIC_RESIDUAL(source = source), files)
10141 algorithm
10142 ✗ files := getFilesFromDAEElementSource(source, files);
10143 then
10144 (inSimEqSystem, files);
10145
10146 case (SimCode.SES_SIMPLE_ASSIGN(source = source), files)
10147 algorithm
10148 ✗ files := getFilesFromDAEElementSource(source, files);
10149 then
10150 (inSimEqSystem, files);
10151
10152 case (SimCode.SES_SIMPLE_ASSIGN_CONSTRAINTS(source = source), files)
10153 algorithm
10154 ✗ files := getFilesFromDAEElementSource(source, files);
10155 then
10156 (inSimEqSystem, files);
10157
10158 case (SimCode.SES_ARRAY_CALL_ASSIGN(source = source), files)
10159 algorithm
10160 ✗ files := getFilesFromDAEElementSource(source, files);
10161 then
10162 (inSimEqSystem, files);
10163
10164 case (SimCode.SES_ALGORITHM(statements=statements), files)
10165 algorithm
10166 ✗ files := getFilesFromStatements(statements, files);
10167 then
10168 (inSimEqSystem, files);
10169
10170 case (SimCode.SES_INVERSE_ALGORITHM(statements=statements), files)
10171 algorithm
10172 ✗ files := getFilesFromStatements(statements, files);
10173 then
10174 (inSimEqSystem, files);
10175
10176 case (SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(vars = vars, simJac = simJac)), files)
10177 algorithm
10178 ✗ (_, files) := List.mapFold(vars, getFilesFromSimVar, files);
10179 ✗ systems := List.map(simJac, Util.tuple33);
10180 ✗ files := getFilesFromSimEqSystems({systems}, files);
10181 then
10182 (inSimEqSystem, files);
10183
10184 case (SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(eqs = systems)), files)
10185 algorithm
10186 ✗ files := getFilesFromSimEqSystems({systems}, files);
10187 then
10188 (inSimEqSystem, files);
10189
10190 case (SimCode.SES_MIXED(cont = system, discVars = vars, discEqs = systems), files)
10191 algorithm
10192 ✗ (_, files) := List.mapFold(vars, getFilesFromSimVar, files);
10193 ✗ files := getFilesFromSimEqSystems({system::systems}, files);
10194 then
10195 (inSimEqSystem, files);
10196
10197 case (SimCode.SES_WHEN(source = source, whenStmtLst = whenStmtLst, elseWhen = systemOpt), files)
10198 algorithm
10199 ✗ files := getFilesFromDAEElementSource(source, files);
10200 ✗ files := getFilesFromWhenOperators(whenStmtLst, files);
10201 ✗ files := getFilesFromSimEqSystemOpt(systemOpt, files);
10202 then
10203 (inSimEqSystem, files);
10204
10205 end match;
10206 end getFilesFromSimEqSystem;
10207
10208 protected function getFilesFromSimEqSystems
10209 input list<list<SimCode.SimEqSystem>> inSimEqSystems;
10210 input SimCode.Files inFiles;
10211 output SimCode.Files outFiles;
10212 algorithm
10213 ✗ (_, outFiles) := List.mapFoldList(inSimEqSystems, getFilesFromSimEqSystem, inFiles);
10214 end getFilesFromSimEqSystems;
10215
10216 protected function getFilesFromStatementsElse
10217 input DAE.Else inElse;
10218 input SimCode.Files inFiles;
10219 output SimCode.Files outFiles;
10220 algorithm
10221 outFiles := match(inElse, inFiles)
10222 local
10223 SimCode.Files files;
10224 list<DAE.Statement> stmts;
10225 DAE.Else elsePart;
10226
10227 case (DAE.NOELSE(), files) then files;
10228
10229 case (DAE.ELSEIF(statementLst = stmts, else_ = elsePart), files)
10230 algorithm
10231 ✗ files := getFilesFromStatements(stmts, files);
10232 ✗ files := getFilesFromStatementsElse(elsePart, files);
10233 then
10234 files;
10235
10236 case (DAE.ELSE(statementLst = stmts), files)
10237 algorithm
10238 ✗ files := getFilesFromStatements(stmts, files);
10239 then
10240 files;
10241 end match;
10242 end getFilesFromStatementsElse;
10243
10244 protected function getFilesFromStatementsElseWhen
10245 input Option<DAE.Statement> inStatementOpt;
10246 input SimCode.Files inFiles;
10247 output SimCode.Files outFiles;
10248 algorithm
10249 outFiles := match(inStatementOpt, inFiles)
10250 local
10251 SimCode.Files files;
10252 DAE.Statement stmt;
10253
10254 case (NONE(), files) then files;
10255 ✗ case (SOME(stmt), files) then getFilesFromStatements({stmt}, files);
10256 end match;
10257 end getFilesFromStatementsElseWhen;
10258
10259 protected function getFilesFromStatements
10260 input list<DAE.Statement> inStatements;
10261 input SimCode.Files inFiles;
10262 output SimCode.Files outFiles;
10263 algorithm
10264 outFiles := match(inStatements, inFiles)
10265 local
10266 SimCode.Files files;
10267 DAE.ElementSource source;
10268 list<DAE.Statement> rest, stmts;
10269 DAE.Else elsePart;
10270 Option<DAE.Statement> elseWhen;
10271
10272 // handle empty
10273 case ({}, files) then files;
10274
10275 case (DAE.STMT_ASSIGN(source = source)::rest, files)
10276 algorithm
10277 ✗ files := getFilesFromDAEElementSource(source, files);
10278 ✗ files := getFilesFromStatements(rest, files);
10279 then
10280 files;
10281
10282 case (DAE.STMT_TUPLE_ASSIGN(source = source)::rest, files)
10283 algorithm
10284 ✗ files := getFilesFromDAEElementSource(source, files);
10285 ✗ files := getFilesFromStatements(rest, files);
10286 then
10287 files;
10288
10289 case (DAE.STMT_ASSIGN_ARR(source = source)::rest, files)
10290 algorithm
10291 ✗ files := getFilesFromDAEElementSource(source, files);
10292 ✗ files := getFilesFromStatements(rest, files);
10293 then
10294 files;
10295
10296 case (DAE.STMT_IF(source = source, statementLst = stmts, else_ = elsePart)::rest, files)
10297 algorithm
10298 ✗ files := getFilesFromDAEElementSource(source, files);
10299 ✗ files := getFilesFromStatements(stmts, files);
10300 ✗ files := getFilesFromStatementsElse(elsePart, files);
10301 ✗ files := getFilesFromStatements(rest, files);
10302 then
10303 files;
10304
10305 case (DAE.STMT_FOR(source = source, statementLst = stmts)::rest, files)
10306 algorithm
10307 ✗ files := getFilesFromDAEElementSource(source, files);
10308 ✗ files := getFilesFromStatements(stmts, files);
10309 ✗ files := getFilesFromStatements(rest, files);
10310 then
10311 files;
10312
10313 case (DAE.STMT_PARFOR(source = source, statementLst = stmts)::rest, files)
10314 algorithm
10315 ✗ files := getFilesFromDAEElementSource(source, files);
10316 ✗ files := getFilesFromStatements(stmts, files);
10317 ✗ files := getFilesFromStatements(rest, files);
10318 then
10319 files;
10320
10321 case (DAE.STMT_WHILE(source = source, statementLst = stmts)::rest, files)
10322 algorithm
10323 ✗ files := getFilesFromDAEElementSource(source, files);
10324 ✗ files := getFilesFromStatements(stmts, files);
10325 ✗ files := getFilesFromStatements(rest, files);
10326 then
10327 files;
10328
10329 case (DAE.STMT_WHEN(source = source, statementLst = stmts, elseWhen = elseWhen)::rest, files)
10330 algorithm
10331 ✗ files := getFilesFromDAEElementSource(source, files);
10332 ✗ files := getFilesFromStatements(stmts, files);
10333 ✗ files := getFilesFromStatementsElseWhen(elseWhen, files);
10334 ✗ files := getFilesFromStatements(rest, files);
10335 then
10336 files;
10337
10338 case (DAE.STMT_ASSERT(source = source)::rest, files)
10339 algorithm
10340 ✗ files := getFilesFromDAEElementSource(source, files);
10341 ✗ files := getFilesFromStatements(rest, files);
10342 then
10343 files;
10344
10345 case (DAE.STMT_TERMINATE(source = source)::rest, files)
10346 algorithm
10347 ✗ files := getFilesFromDAEElementSource(source, files);
10348 ✗ files := getFilesFromStatements(rest, files);
10349 then
10350 files;
10351
10352 case (DAE.STMT_REINIT(source = source)::rest, files)
10353 algorithm
10354 ✗ files := getFilesFromDAEElementSource(source, files);
10355 ✗ files := getFilesFromStatements(rest, files);
10356 then
10357 files;
10358
10359 case (DAE.STMT_NORETCALL(source = source)::rest, files)
10360 algorithm
10361 ✗ files := getFilesFromDAEElementSource(source, files);
10362 ✗ files := getFilesFromStatements(rest, files);
10363 then
10364 files;
10365
10366 case (DAE.STMT_RETURN(source = source)::rest, files)
10367 algorithm
10368 ✗ files := getFilesFromDAEElementSource(source, files);
10369 ✗ files := getFilesFromStatements(rest, files);
10370 then
10371 files;
10372
10373 case (DAE.STMT_BREAK(source = source)::rest, files)
10374 algorithm
10375 ✗ files := getFilesFromDAEElementSource(source, files);
10376 ✗ files := getFilesFromStatements(rest, files);
10377 then
10378 files;
10379
10380 case (DAE.STMT_FAILURE(source = source, body = stmts)::rest, files)
10381 algorithm
10382 ✗ files := getFilesFromDAEElementSource(source, files);
10383 ✗ files := getFilesFromStatements(stmts, files);
10384 ✗ files := getFilesFromStatements(rest, files);
10385 then
10386 files;
10387
10388 end match;
10389 end getFilesFromStatements;
10390
10391 protected function getFilesFromWhenOperators
10392 input list<BackendDAE.WhenOperator> inWhenOperators;
10393 input SimCode.Files inFiles;
10394 output SimCode.Files outFiles;
10395 algorithm
10396 outFiles := match(inWhenOperators, inFiles)
10397 local
10398 SimCode.Files files;
10399 DAE.ElementSource source;
10400 list<BackendDAE.WhenOperator> rest;
10401
10402 // handle empty
10403 case ({}, files) then files;
10404
10405 case (BackendDAE.ASSIGN(source = source)::rest, files)
10406 algorithm
10407 ✗ files := getFilesFromDAEElementSource(source, files);
10408 ✗ files := getFilesFromWhenOperators(rest, files);
10409 then
10410 files;
10411
10412 case (BackendDAE.REINIT(source = source)::rest, files)
10413 algorithm
10414 ✗ files := getFilesFromDAEElementSource(source, files);
10415 ✗ files := getFilesFromWhenOperators(rest, files);
10416 then
10417 files;
10418
10419 case (BackendDAE.ASSERT(source = source)::rest, files)
10420 algorithm
10421 ✗ files := getFilesFromDAEElementSource(source, files);
10422 ✗ files := getFilesFromWhenOperators(rest, files);
10423 then
10424 files;
10425
10426 case (BackendDAE.TERMINATE(source = source)::rest, files)
10427 algorithm
10428 ✗ files := getFilesFromDAEElementSource(source, files);
10429 ✗ files := getFilesFromWhenOperators(rest, files);
10430 then
10431 files;
10432
10433 case (BackendDAE.NORETCALL(source = source)::rest, files)
10434 algorithm
10435 ✗ files := getFilesFromDAEElementSource(source, files);
10436 ✗ files := getFilesFromWhenOperators(rest, files);
10437 then
10438 files;
10439
10440 end match;
10441 end getFilesFromWhenOperators;
10442
10443 protected function getFilesFromExtObjInfo
10444 input SimCode.ExtObjInfo inExtObjInfo;
10445 input SimCode.Files inFiles;
10446 output SimCode.Files outFiles;
10447 algorithm
10448 ✗ (_, outFiles) := List.mapFold(inExtObjInfo.vars, getFilesFromSimVar, inFiles);
10449 end getFilesFromExtObjInfo;
10450
10451 protected function getFilesFromJacobianMatrices
10452 input list<SimCode.JacobianMatrix> inJacobianMatrices;
10453 input SimCode.Files inFiles;
10454 output SimCode.Files outFiles;
10455 algorithm
10456 outFiles := match(inJacobianMatrices, inFiles)
10457 local
10458 SimCode.Files files;
10459 list<SimCode.JacobianMatrix> rest;
10460 list<SimCode.JacobianColumn> onemat;
10461
10462 // handle empty
10463 case ({}, files) then files;
10464
10465 // handle rest
10466 case (SimCode.JAC_MATRIX(columns=onemat)::rest, files)
10467 algorithm
10468 ✗ files := getFilesFromJacobianMatrix(onemat, files);
10469 ✗ files := getFilesFromJacobianMatrices(rest, files);
10470 then
10471 files;
10472
10473 end match;
10474 end getFilesFromJacobianMatrices;
10475
10476 protected function getFilesFromJacobianMatrix
10477 input list<SimCode.JacobianColumn> inJacobianMatrices;
10478 input SimCode.Files inFiles;
10479 output SimCode.Files outFiles;
10480 algorithm
10481 outFiles := match(inJacobianMatrices, inFiles)
10482 local
10483 SimCode.Files files;
10484 list<SimCode.JacobianColumn> rest;
10485 list<SimCode.SimEqSystem> systems;
10486 list<SimCodeVar.SimVar> vars;
10487
10488 // handle empty
10489 case ({}, files) then files;
10490
10491 // handle rest
10492 case (SimCode.JAC_COLUMN(columnEqns=systems, columnVars=vars)::rest, files)
10493 algorithm
10494 ✗ files := getFilesFromSimEqSystems({systems}, files);
10495 ✗ (_, files) := List.mapFold(vars, getFilesFromSimVar, files);
10496 ✗ files := getFilesFromJacobianMatrix(rest, files);
10497 then
10498 files;
10499
10500 end match;
10501 end getFilesFromJacobianMatrix;
10502
10503 protected function collectAllFiles
10504 input SimCode.SimCode inSimCode;
10505 output SimCode.SimCode outSimCode = inSimCode;
10506 protected
10507 SimCode.ModelInfo modelInfo;
10508 SimCode.Files files = {} "all the files from SourceInfo and DAE.ELementSource";
10509 algorithm
10510 ✗ if not Config.acceptMetaModelicaGrammar() then
10511 ✗ modelInfo := outSimCode.modelInfo;
10512 ✗ files := getFilesFromSimVars(modelInfo.vars, files);
10513 ✗ files := getFilesFromFunctions(modelInfo.functions, files);
10514 ✗ files := getFilesFromSimEqSystems( outSimCode.allEquations :: outSimCode.startValueEquations :: outSimCode.nominalValueEquations
10515 :: outSimCode.minValueEquations :: outSimCode.maxValueEquations :: outSimCode.parameterEquations
10516 :: outSimCode.removedEquations :: outSimCode.algorithmAndEquationAsserts
10517 :: outSimCode.odeEquations, files );
10518 ✗ files := getFilesFromSimEqSystems(outSimCode.algebraicEquations, files);
10519 ✗ files := getFilesFromExtObjInfo(outSimCode.extObjInfo, files);
10520 ✗ files := getFilesFromJacobianMatrices(outSimCode.jacobianMatrices, files);
10521 ✗ files := List.sort(files, greaterFileInfo);
10522 ✗ outSimCode.modelInfo := modelInfo;
10523 end if;
10524 end collectAllFiles;
10525
10526 protected function getFilesFromDAEElementSource
10527 input DAE.ElementSource inSource;
10528 input SimCode.Files inFiles;
10529 output SimCode.Files outFiles;
10530 algorithm
10531 ✗ outFiles := getFilesFromAbsynInfo(inSource.info, inFiles);
10532 end getFilesFromDAEElementSource;
10533
10534 protected function getFilesFromAbsynInfo
10535 input SourceInfo inInfo;
10536 input SimCode.Files inFiles;
10537 output SimCode.Files outFiles;
10538 protected
10539 SimCode.FileInfo fi;
10540 algorithm
10541 ✗ fi := SimCode.FILEINFO(inInfo.fileName, inInfo.isReadOnly);
10542 // add it only if is not already there!
10543 ✗ outFiles := List.consOnTrue(not listMember(fi, inFiles), fi, inFiles);
10544 end getFilesFromAbsynInfo;
10545
10546 protected function equalFileInfo
10547 "compare to SimCode.FileInfo and return true if the filenames are equal, isReadOnly is ignored here"
10548 input SimCode.FileInfo inFileInfo1;
10549 input SimCode.FileInfo inFileInfo2;
10550 output Boolean isMatch;
10551 protected
10552 String f1, f2;
10553 algorithm
10554 ✗ SimCode.FILEINFO(f1, _) := inFileInfo1;
10555 ✗ SimCode.FILEINFO(f2, _) := inFileInfo2;
10556 ✗ isMatch := stringEq(f1, f2);
10557 end equalFileInfo;
10558
10559 protected function greaterFileInfo
10560 "compare to SimCode.FileInfo and returns true if the fileName1 is greater than fileName2, isReadOnly is ignored here"
10561 input SimCode.FileInfo inFileInfo1;
10562 input SimCode.FileInfo inFileInfo2;
10563 output Boolean isGreater;
10564 protected
10565 String f1, f2;
10566 Integer compare;
10567 algorithm
10568 ✗ SimCode.FILEINFO(f1, _) := inFileInfo1;
10569 ✗ SimCode.FILEINFO(f2, _) := inFileInfo2;
10570 ✗ compare := stringCompare(f1, f2);
10571 ✗ isGreater := intGt(compare, 0);
10572 end greaterFileInfo;
10573
10574 protected function getFileIndexFromFiles
10575 "fetch the index in the list of files"
10576 input String file;
10577 input SimCode.Files files;
10578 output Integer index;
10579 algorithm
10580 ✗ index := List.position1OnTrue(files, equalFileInfo, SimCode.FILEINFO(file, false))-1 "shift to zero-based index";
10581 end getFileIndexFromFiles;
10582
10583 public function fileName2fileIndex
10584 "Used by templates to find a fileIndex for given fileName"
10585 input String inFileName;
10586 input SimCode.Files inFiles;
10587 output Integer outFileIndex;
10588 algorithm
10589 outFileIndex := matchcontinue(inFileName, inFiles)
10590 local
10591 String file;
10592 SimCode.Files files;
10593 Integer index;
10594
10595 case (file, files)
10596 algorithm
10597 ✗ index := getFileIndexFromFiles(file, files);
10598 then
10599 index;
10600
10601 else
10602 algorithm
10603 // errstr = "Template did not find the file: "+ file + " in the SimCode.modelInfo.files.";
10604 // Error.addInternalError(errstr, sourceInfo());
10605 then
10606 -1;
10607 end matchcontinue;
10608 end fileName2fileIndex;
10609
10610 protected function makeEqualLengthLists
10611 "Greedy algorithm for scheduling. Very simple:
10612 Calculate the weight of each eq.system, sort these s.t.
10613 the most expensive system is treated first. Add
10614 this eq.system to the block with the least cost at the moment.
10615 "
10616 input list<list<SimCode.SimEqSystem>> inLst;
10617 input Integer i;
10618 output list<list<SimCode.SimEqSystem>> olst;
10619 algorithm
10620 olst := matchcontinue (inLst, i)
10621 local
10622 list<SimCode.SimEqSystem> l;
10623 PriorityQueue.T q;
10624 list<tuple<Integer, list<SimCode.SimEqSystem>>> prios;
10625 list<list<SimCode.SimEqSystem>> lst;
10626
10627 case (lst, _)
10628 algorithm
10629
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2120 times.
2120 false := Flags.isSet(Flags.PTHREADS);
10630 2120 l := List.flatten(lst);
10631 then l::{};
10632 case (lst, 0) then lst;
10633 case (lst, 1)
10634 algorithm
10635 ✗ l := List.flatten(lst);
10636 /* eq_str = Tpl.tplString2(SimCodeDump.dumpEqsSys, l, false);
10637 print(eq_str); */
10638 then l::{};
10639 case (lst, _)
10640 algorithm
10641 ✗ q := List.fold(List.fill((0, {}), i), PriorityQueue.insert, PriorityQueue.empty);
10642 ✗ prios := List.map(lst, calcPriority);
10643 ✗ q := List.fold(prios, makeEqualLengthLists2, q);
10644 ✗ lst := List.map(PriorityQueue.elements(q), Util.tuple22);
10645 then lst;
10646 end matchcontinue;
10647 end makeEqualLengthLists;
10648
10649 protected function makeEqualLengthLists2
10650 input tuple<Integer, list<SimCode.SimEqSystem>> elt;
10651 input PriorityQueue.T iq;
10652 output PriorityQueue.T oq;
10653 algorithm
10654 oq := match (elt, iq)
10655 local
10656 list<SimCode.SimEqSystem> l1, l2;
10657 Integer i1, i2;
10658 PriorityQueue.T q;
10659
10660 case ((i1, l1), q)
10661 algorithm
10662 // print("priorities before: " + stringDelimitList(List.mapMap(PriorityQueue.elements(q), Util.tuple21, intString), ", ") + "\n");
10663 ✗ (q, (i2, l2)) := PriorityQueue.deleteAndReturnMin(q);
10664 // print("priorities (popped): " + stringDelimitList(List.mapMap(PriorityQueue.elements(q), Util.tuple21, intString), ", ") + "\n");
10665 ✗ q := PriorityQueue.insert((i1+i2, listAppend(l2, l1)), q);
10666 // print("priorities after (i1=" + intString(i1) + "): " + stringDelimitList(List.mapMap(PriorityQueue.elements(q), Util.tuple21, intString), ", ") + "\n");
10667 then q;
10668 end match;
10669 end makeEqualLengthLists2;
10670
10671 protected function calcPriority
10672 input list<SimCode.SimEqSystem> eqs;
10673 output tuple<Integer, list<SimCode.SimEqSystem>> prio;
10674 protected
10675 Integer i;
10676 algorithm
10677 ✗ (_, i) := traverseExpsEqSystems(eqs, Expression.complexityTraverse, 1 /* Each system has cost 1 even if it's as simple as der(x)=1.0 */, {});
10678 ✗ prio := (i, eqs);
10679 end calcPriority;
10680
10681 public function findSimCodeLiterals
10682 "Replaces the literals in simCode by shared literals and returns them all."
10683 input output SimCode.SimCode simCode;
10684 input tuple<Integer, UnorderedMap<DAE.Exp, Integer>, list<DAE.Exp>> inLiterals;
10685 output list<DAE.Exp> literals;
10686 protected
10687 UnorderedMap<DAE.Exp, Integer> uses;
10688 algorithm
10689 1069 (_, uses) := traverseExpsSimCode(simCode, SimCodeFunctionUtil.countStringUses, SimCodeFunctionUtil.newExpIndexMap());
10690 1069 (simCode, (_, _, literals)) := traverseExpsSimCode(simCode, function SimCodeFunctionUtil.findLiteralsHelperKeepSingle(uses = uses), inLiterals);
10691 1069 literals := listReverse(literals);
10692 end findSimCodeLiterals;
10693
10694 public function traverseExpsSimCode
10695 input SimCode.SimCode simCode;
10696 input Func func;
10697 input A ia;
10698 output SimCode.SimCode outSimCode = simCode;
10699 output A oa;
10700 replaceable type A subtypeof Any;
10701 partial function Func
10702 input DAE.Exp inExp;
10703 input A inTypeA;
10704 output DAE.Exp outExp;
10705 output A outA;
10706 end Func;
10707 protected
10708 list<DAE.Exp> literals;
10709 list<SimCode.SimEqSystem> eqs;
10710 list<list<SimCode.SimEqSystem>> eqs1;
10711 list<SimCode.ClockedPartition> partitions;
10712 algorithm
10713 2138 (literals, oa) := List.mapFold(outSimCode.literals, func, ia);
10714 2138 outSimCode.literals := literals;
10715 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.allEquations, func, oa, {});
10716 2138 outSimCode.allEquations := eqs;
10717 2138 (partitions, oa) := List.map1Fold(outSimCode.clockedPartitions, traverseExpsPartition, func, oa);
10718 2138 outSimCode.clockedPartitions := partitions;
10719 2138 (eqs1, oa) := traverseExpsEqSystemsList(outSimCode.odeEquations, func, oa, {});
10720 2138 outSimCode.odeEquations := eqs1;
10721 2138 (eqs1, oa) := traverseExpsEqSystemsList(outSimCode.algebraicEquations, func, oa, {});
10722 2138 outSimCode.algebraicEquations := eqs1;
10723 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.initialEquations, func, oa, {});
10724 2138 outSimCode.initialEquations := eqs;
10725 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.removedInitialEquations, func, oa, {});
10726 2138 outSimCode.removedInitialEquations := eqs;
10727 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.startValueEquations, func, oa, {});
10728 2138 outSimCode.startValueEquations := eqs;
10729 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.nominalValueEquations, func, oa, {});
10730 2138 outSimCode.nominalValueEquations := eqs;
10731 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.minValueEquations, func, oa, {});
10732 2138 outSimCode.minValueEquations := eqs;
10733 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.maxValueEquations, func, oa, {});
10734 2138 outSimCode.maxValueEquations := eqs;
10735 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.parameterEquations, func, oa, {});
10736 2138 outSimCode.parameterEquations := eqs;
10737 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.removedEquations, func, oa, {});
10738 2138 outSimCode.removedEquations := eqs;
10739 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.algorithmAndEquationAsserts, func, oa, {});
10740 2138 outSimCode.algorithmAndEquationAsserts := eqs;
10741 2138 (eqs, oa) := traverseExpsEqSystems(outSimCode.jacobianEquations, func, oa, {});
10742
1/2
✓ Branch 0 taken 2138 times.
✗ Branch 1 not taken.
2138 outSimCode.jacobianEquations := eqs;
10743 /* TODO:zeroCrossing */
10744 /* TODO:discreteModelVars */
10745 /* TODO:extObjInfo */
10746 /* TODO:delayedExps */
10747 end traverseExpsSimCode;
10748
10749 protected function traverseExpsPartition
10750 input SimCode.ClockedPartition simPartition;
10751 input Func func;
10752 input A ia;
10753 output SimCode.ClockedPartition outSimPartition = simPartition;
10754 output A oa;
10755 replaceable type A subtypeof Any;
10756 partial function Func
10757 input DAE.Exp inExp;
10758 input A inTypeA;
10759 output DAE.Exp outExp;
10760 output A outA;
10761 end Func;
10762 protected
10763 DAE.ClockKind clk;
10764 list<SimCode.SubPartition> subPartitions;
10765 algorithm
10766
3/4
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 46 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 92 times.
92 (DAE.CLKCONST(clk), oa) := func(DAE.CLKCONST(simPartition.baseClock), ia);
10767 92 (subPartitions, oa) := List.map1Fold(simPartition.subPartitions, traverseExpsSubPartition, func, oa);
10768 92 outSimPartition.baseClock := clk;
10769 outSimPartition.subPartitions := subPartitions;
10770 end traverseExpsPartition;
10771
10772 protected function traverseExpsSubPartition
10773 input SimCode.SubPartition subPartition;
10774 input Func func;
10775 input A ia;
10776 output SimCode.SubPartition outSubPartition = subPartition;
10777 output A oa;
10778 replaceable type A subtypeof Any;
10779 partial function Func
10780 input DAE.Exp inExp;
10781 input A inTypeA;
10782 output DAE.Exp outExp;
10783 output A outA;
10784 end Func;
10785 protected
10786 list<SimCode.SimEqSystem> eqs;
10787 algorithm
10788 122 (eqs, oa) := traverseExpsEqSystems(subPartition.equations, func, ia, {});
10789 122 outSubPartition.equations := eqs;
10790 122 (eqs, oa) := traverseExpsEqSystems(subPartition.removedEquations, func, oa, {});
10791
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
122 outSubPartition.removedEquations := eqs;
10792 end traverseExpsSubPartition;
10793
10794 protected function traverseExpsEqSystemsList
10795 input list<list<SimCode.SimEqSystem>> ieqs;
10796 input Func func;
10797 input A ia;
10798 input list<list<SimCode.SimEqSystem>> acc;
10799 output list<list<SimCode.SimEqSystem>> oeqs;
10800 output A oa;
10801 replaceable type A subtypeof Any;
10802 partial function Func
10803 input DAE.Exp inExp;
10804 input A inTypeA;
10805 output DAE.Exp outExp;
10806 output A outA;
10807 end Func;
10808 algorithm
10809 (oeqs, oa) := match (ieqs, ia)
10810 local
10811 list<SimCode.SimEqSystem> eq;
10812 A a;
10813 list<list<SimCode.SimEqSystem>> eqs;
10814
10815
1/2
✓ Branch 1 taken 4276 times.
✗ Branch 2 not taken.
4276 case ({}, a) then (listReverse(acc), a);
10816 case (eq::eqs, a)
10817 algorithm
10818 2762 (eq, a) := traverseExpsEqSystems(eq, func, a, {});
10819 2762 (oeqs, a) := traverseExpsEqSystemsList(eqs, func, a, eq::acc);
10820 then (oeqs, a);
10821 end match;
10822 end traverseExpsEqSystemsList;
10823
10824 protected function traverseExpsEqSystems
10825 input list<SimCode.SimEqSystem> ieqs;
10826 input Func func;
10827 input A ia;
10828 input list<SimCode.SimEqSystem> acc;
10829 output list<SimCode.SimEqSystem> oeqs;
10830 output A oa = ia;
10831 replaceable type A subtypeof Any;
10832 partial function Func
10833 input DAE.Exp inExp;
10834 input A inTypeA;
10835 output DAE.Exp outExp;
10836 output A outA;
10837 end Func;
10838 protected
10839 SimCode.SimEqSystem teq;
10840 list<SimCode.SimEqSystem> racc = acc;
10841 algorithm
10842
2/2
✓ Branch 0 taken 742654 times.
✓ Branch 1 taken 28554 times.
771208 for eq in ieqs loop
10843 742654 (teq, oa) := traverseExpsEqSystem(eq, func, oa);
10844 racc := teq :: racc;
10845 end for;
10846 28554 oeqs := listReverse(racc);
10847 end traverseExpsEqSystems;
10848
10849 protected function traverseStmtExp
10850 input DAE.Exp inExp;
10851 input DAE.Statement inStmt;
10852 input A inArg;
10853 input Func func;
10854 output DAE.Exp outExp;
10855 output A outArg;
10856 replaceable type A subtypeof Any;
10857 partial function Func
10858 input DAE.Exp inExp;
10859 input A inTypeA;
10860 output DAE.Exp outExp;
10861 output A outA;
10862 end Func;
10863 algorithm
10864
2/2
✓ Branch 0 taken 130954 times.
✓ Branch 1 taken 131204 times.
262158 (outExp, outArg) := func(inExp, inArg);
10865 end traverseStmtExp;
10866
10867 protected function traverseExpsEqSystem
10868 input SimCode.SimEqSystem eq;
10869 input Func func;
10870 input A ia;
10871 output SimCode.SimEqSystem oeq;
10872 output A oa;
10873 replaceable type A subtypeof Any;
10874 partial function Func
10875 input DAE.Exp inExp;
10876 input A inTypeA;
10877 output DAE.Exp outExp;
10878 output A outA;
10879 end Func;
10880 algorithm
10881 (oeq, oa) := match (eq, ia)
10882 local
10883 A a;
10884 DAE.ComponentRef cr;
10885 DAE.ElementSource source;
10886 DAE.Exp exp, exp_, leftexp;
10887 SimCode.SimEqSystem eq_;
10888 Integer index, res_index;
10889 BackendDAE.Constraints cons;
10890 BackendDAE.EquationAttributes eqAttr;
10891 list<DAE.Statement> stmts;
10892
10893 case (SimCode.SES_RESIDUAL(index, res_index, exp, source, eqAttr), a) algorithm
10894
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
56 (exp_, a) := func(exp, a);
10895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if referenceEq(exp,exp_) then
10896 eq_ := eq;
10897 else
10898 ✗ eq_ := SimCode.SES_RESIDUAL(index, res_index, exp_, source, eqAttr);
10899 end if;
10900 56 then (eq_, a);
10901
10902 case (SimCode.SES_FOR_RESIDUAL(index, res_index, _, exp, source, eqAttr), a) algorithm
10903 ✗ (exp_, a) := func(exp, a);
10904 ✗ if referenceEq(exp,exp_) then
10905 eq_ := eq;
10906 else
10907 ✗ eq_ := SimCode.SES_FOR_RESIDUAL(index, res_index, eq.iterators, exp_, source, eqAttr);
10908 end if;
10909 ✗ then (eq_, a);
10910
10911 case (SimCode.SES_GENERIC_RESIDUAL(index, res_index, _, _, exp, source, eqAttr), a) algorithm
10912 ✗ (exp_, a) := func(exp, a);
10913 ✗ if referenceEq(exp,exp_) then
10914 eq_ := eq;
10915 else
10916 ✗ eq_ := SimCode.SES_GENERIC_RESIDUAL(index, res_index, eq.scal_indices, eq.iterators, exp_, source, eqAttr);
10917 end if;
10918 ✗ then (eq_, a);
10919
10920 case (SimCode.SES_SIMPLE_ASSIGN(index, cr, exp, source, eqAttr), a) algorithm
10921
2/2
✓ Branch 0 taken 259947 times.
✓ Branch 1 taken 274821 times.
534768 (exp_, a) := func(exp, a);
10922
2/2
✓ Branch 0 taken 23499 times.
✓ Branch 1 taken 511269 times.
534768 if referenceEq(exp,exp_) then
10923 eq_ := eq;
10924 else
10925 23499 eq_ := SimCode.SES_SIMPLE_ASSIGN(index, cr, exp_, source, eqAttr);
10926 end if;
10927 534768 then (eq_, a);
10928
10929 case (SimCode.SES_SIMPLE_ASSIGN_CONSTRAINTS(index, cr, exp, source, cons, eqAttr), a) algorithm
10930 ✗ (exp_, a) := func(exp, a);
10931 ✗ if referenceEq(exp,exp_) then
10932 eq_ := eq;
10933 else
10934 ✗ eq_ := SimCode.SES_SIMPLE_ASSIGN_CONSTRAINTS(index, cr, exp_, source, cons, eqAttr);
10935 end if;
10936 ✗ then (eq_, a);
10937
10938 case (SimCode.SES_ARRAY_CALL_ASSIGN(index, leftexp, exp, source, eqAttr), a) algorithm
10939
2/2
✓ Branch 0 taken 718 times.
✓ Branch 1 taken 718 times.
1436 (leftexp, a) := func(leftexp, a);
10940
2/2
✓ Branch 0 taken 718 times.
✓ Branch 1 taken 718 times.
1436 (exp, a) := func(exp, a);
10941 1436 then (SimCode.SES_ARRAY_CALL_ASSIGN(index, leftexp, exp, source, eqAttr), a);
10942
10943 case (SimCode.SES_IFEQUATION(), a)
10944 /* TODO: Me */
10945 then (eq, a);
10946
10947 case (SimCode.SES_ALGORITHM(), a)
10948 algorithm
10949 79372 (stmts, a) := DAEUtil.traverseDAEStmts(eq.statements, function traverseStmtExp(func = func), a);
10950 79372 eq_ := SimCode.SES_ALGORITHM(eq.index, stmts, eq.eqAttr);
10951 79372 then (eq_, a);
10952
10953 case (SimCode.SES_INVERSE_ALGORITHM(), a)
10954 algorithm
10955 ✗ (stmts, a) := DAEUtil.traverseDAEStmts(eq.statements, function traverseStmtExp(func = func), a);
10956 ✗ eq_ := SimCode.SES_INVERSE_ALGORITHM(eq.index, stmts, eq.knownOutputCrefs, eq.insideNonLinearSystem, eq.eqAttr);
10957 ✗ then (eq_, a);
10958
10959 case (SimCode.SES_LINEAR(), a)
10960 /* TODO: Me */
10961 then (eq, a);
10962
10963 case (SimCode.SES_NONLINEAR(), a)
10964 /* TODO: Me */
10965 then (eq, a);
10966
10967 case (SimCode.SES_MIXED(), a)
10968 /* TODO: Me */
10969 then (eq, a);
10970
10971 case (SimCode.SES_WHEN(), a)
10972 /* TODO: Me */
10973 then (eq, a);
10974
10975 case (SimCode.SES_FOR_LOOP(), a)
10976 /* TODO: Me */
10977 then (eq, a);
10978
10979 case (SimCode.SES_FOR_EQUATION(), a)
10980 /* TODO: Me */
10981 then (eq, a);
10982
10983 case (SimCode.SES_ALIAS(), a)
10984 then (eq, a);
10985
10986 else
10987 algorithm
10988 ✗ Error.addInternalError(getInstanceName() + " got unknown equation", sourceInfo());
10989 ✗ then fail();
10990 end match;
10991 end traverseExpsEqSystem;
10992
10993 protected function setSimCodeLiterals
10994 input SimCode.SimCode simCode;
10995 input list<DAE.Exp> literals;
10996 output SimCode.SimCode outSimCode = simCode;
10997 algorithm
10998 1060 outSimCode.literals := literals;
10999 end setSimCodeLiterals;
11000
11001
11002
11003 protected function eqSystemWCET
11004 "Calculate the estimated worst-case execution time of the system for partitioning"
11005 input SimCode.SimEqSystem eqs;
11006 output tuple<SimCode.SimEqSystem, Integer> tpl;
11007 protected
11008 Integer i;
11009 algorithm
11010 ✗ (_, i) := traverseExpsEqSystems({eqs}, Expression.complexityTraverse, 0, {});
11011 ✗ tpl := (eqs, i);
11012 end eqSystemWCET;
11013
11014 protected function getHideResult
11015 "Returns the value of the hideResult attribute."
11016 input Option<DAE.Exp> hideResultExp;
11017 input DAE.ComponentRef name;
11018 input DAE.ElementSource source;
11019 output Option<Boolean> hideResult;
11020 algorithm
11021 hideResult := match hideResultExp
11022 case NONE() then NONE();
11023 case SOME(DAE.BCONST(false)) then SOME(false);
11024 case SOME(DAE.BCONST(true)) then SOME(true);
11025 else
11026 algorithm
11027 2 Error.addSourceMessage(Error.HIDE_RESULT_NOT_EVALUATED,
11028 {ComponentReferenceBasics.printComponentRefStr(name)}, ElementSource.getInfo(source));
11029 then NONE();
11030 end match;
11031 end getHideResult;
11032
11033 public function createIdxSCVarMapping "author: marcusw
11034 Create a mapping from the SCVar-Index (array-Index) to the SCVariable, as it is used in the c-runtime."
11035 input SimCodeVar.SimVars simVars;
11036 output array<Option<SimCodeVar.SimVar>> outMapping;
11037 protected
11038 Integer numStateVars;
11039 list<SimCodeVar.SimVar> stateVars;
11040 list<SimCodeVar.SimVar> derivativeVars;
11041 list<SimCodeVar.SimVar> algVars;
11042 list<SimCodeVar.SimVar> discreteAlgVars;
11043 list<SimCodeVar.SimVar> intAlgVars;
11044 list<SimCodeVar.SimVar> boolAlgVars;
11045 list<SimCodeVar.SimVar> inputVars;
11046 list<SimCodeVar.SimVar> outputVars;
11047 list<SimCodeVar.SimVar> aliasVars;
11048 list<SimCodeVar.SimVar> intAliasVars;
11049 list<SimCodeVar.SimVar> boolAliasVars;
11050 list<SimCodeVar.SimVar> paramVars;
11051 list<SimCodeVar.SimVar> intParamVars;
11052 list<SimCodeVar.SimVar> boolParamVars;
11053 list<SimCodeVar.SimVar> stringAlgVars;
11054 list<SimCodeVar.SimVar> stringParamVars;
11055 list<SimCodeVar.SimVar> stringAliasVars;
11056 list<SimCodeVar.SimVar> extObjVars;
11057 list<SimCodeVar.SimVar> constVars;
11058 list<SimCodeVar.SimVar> intConstVars;
11059 list<SimCodeVar.SimVar> boolConstVars;
11060 list<SimCodeVar.SimVar> stringConstVars;
11061 list<SimCodeVar.SimVar> jacobianVars;
11062 list<SimCodeVar.SimVar> seedVars;
11063 list<SimCodeVar.SimVar> realOptimizeConstraintsVars;
11064 list<SimCodeVar.SimVar> realOptimizeFinalConstraintsVars;
11065 list<tuple<Integer,SimCodeVar.SimVar>> idxSimVarMappingTplList;
11066 Integer highestIdx, varCount;
11067 array<Option<SimCodeVar.SimVar>> mappingArray;
11068 algorithm
11069 8 SimCodeVar.SIMVARS(stateVars, derivativeVars, algVars, discreteAlgVars, intAlgVars, boolAlgVars, inputVars,
11070 outputVars, aliasVars, intAliasVars, boolAliasVars, paramVars, intParamVars, boolParamVars,
11071 stringAlgVars, stringParamVars, stringAliasVars, extObjVars, constVars, intConstVars, boolConstVars,
11072 stringConstVars, jacobianVars, seedVars, realOptimizeConstraintsVars, realOptimizeFinalConstraintsVars,
11073 _) := simVars;
11074
11075 8 numStateVars := listLength(stateVars);
11076 varCount := 0;
11077 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(stateVars, createAllSCVarMapping0, varCount, {},0);
11078 varCount := varCount + numStateVars;
11079 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(derivativeVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11080 8 varCount := varCount + numStateVars;
11081 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(algVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11082 8 varCount := varCount + listLength(algVars);
11083 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(discreteAlgVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11084 8 varCount := varCount + listLength(discreteAlgVars);
11085 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(intAlgVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11086 8 varCount := varCount + listLength(intAlgVars);
11087 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(boolAlgVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11088 8 varCount := varCount + listLength(boolAlgVars);
11089 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(stringAlgVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11090 8 varCount := varCount + listLength(stringAlgVars);
11091 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(inputVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11092 8 varCount := varCount + listLength(inputVars);
11093 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(outputVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11094 8 varCount := varCount + listLength(outputVars);
11095 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(aliasVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11096 8 varCount := varCount + listLength(aliasVars);
11097 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(intAliasVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11098 8 varCount := varCount + listLength(intAliasVars);
11099 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(boolAliasVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11100 8 varCount := varCount + listLength(boolAliasVars);
11101 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(stringAliasVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11102 8 varCount := varCount + listLength(stringAliasVars);
11103 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(paramVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11104 8 varCount := varCount + listLength(paramVars);
11105 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(intParamVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11106 8 varCount := varCount + listLength(intParamVars);
11107 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(boolParamVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11108 8 varCount := varCount + listLength(boolParamVars);
11109 8 (idxSimVarMappingTplList, highestIdx) := List.fold21(stringParamVars, createAllSCVarMapping0, varCount, idxSimVarMappingTplList,highestIdx);
11110 8 varCount := varCount + listLength(stringParamVars);
11111
11112 8 mappingArray := arrayCreate(highestIdx, NONE());
11113 8 mappingArray := List.fold(idxSimVarMappingTplList, createAllSCVarMapping1, mappingArray);
11114 outMapping := mappingArray;
11115 end createIdxSCVarMapping;
11116
11117 protected function createAllSCVarMapping0 "author: marcusw
11118 Append the given variable to the Index/SimVar-List."
11119 input SimCodeVar.SimVar iSimVar;
11120 input Integer iOffset; //an offset that should be added to the index (necessary for state derivatives)
11121 input output list<tuple<Integer,SimCodeVar.SimVar>> iMapping;
11122 input output Integer highestIdx;
11123 protected
11124 Integer simVarIdx;
11125 algorithm
11126 //print("createAllSCVarMapping0: Mapping variable\n");
11127 //dumpVar(iSimVar);
11128 //print(" to index " + intString(simVarIdx) + "\n");
11129 5606 SimCodeVar.SIMVAR(index=simVarIdx) := iSimVar;
11130 5606 simVarIdx := simVarIdx + 1 + iOffset;
11131 5606 highestIdx := if intGt(simVarIdx, highestIdx) then simVarIdx else highestIdx;
11132 5606 iMapping := (simVarIdx, iSimVar)::iMapping;
11133 //print("createAllSCVarMapping0: Mapping-Length: " + intString(listLength(iMapping)) + "\n");
11134 end createAllSCVarMapping0;
11135
11136 protected function createAllSCVarMapping1 "author: marcusw
11137 Set the arrayIndex (iMapping) to the value given by the tuple."
11138 input tuple<Integer,SimCodeVar.SimVar> iSimVarIdxTpl; //<idx, elem>
11139 input array<Option<SimCodeVar.SimVar>> iMapping;
11140 output array<Option<SimCodeVar.SimVar>> outMapping;
11141 protected
11142 Integer simVarIdx;
11143 SimCodeVar.SimVar simVar;
11144 algorithm
11145 5606 (simVarIdx,simVar) := iSimVarIdxTpl;
11146 5606 outMapping := arrayUpdate(iMapping,simVarIdx,SOME(simVar));
11147 end createAllSCVarMapping1;
11148
11149 public function equationIndexEqual
11150 input SimCode.SimEqSystem eq1;
11151 input SimCode.SimEqSystem eq2;
11152 output Boolean isEqual;
11153 algorithm
11154 ✗ isEqual := intEq(SimCodeCodegenUtil.simEqSystemIndex(eq1),SimCodeCodegenUtil.simEqSystemIndex(eq2));
11155 end equationIndexEqual;
11156
11157 //--------------------------
11158 // backendMapping section
11159 //--------------------------
11160
11161 protected function setUpBackendMapping"sets up a BackendMapping type with empty eq and varmappings and empty adjacency matrices.
11162 author: Waurich TUD 2014-04"
11163 input BackendDAE.BackendDAE dae;
11164 output SimCode.BackendMapping mapping;
11165 algorithm
11166 mapping := matchcontinue dae
11167 local
11168 Integer sizeE,sizeV;
11169 array<Integer> eqMatch, varMatch;
11170 array<list<Integer>> tree;
11171 BackendDAE.EqSystems eqs;
11172 BackendDAE.AdjacencyMatrix m;
11173 BackendDAE.AdjacencyMatrixT mt;
11174 list<tuple<Integer,Integer>> varMap;
11175 list<tuple<Integer,list<Integer>>> eqMap;
11176 array<list<SimCodeVar.SimVar>> simVarMapping;
11177 list<tuple<Integer,Integer,BackendDAE.AdjacencyMatrix,BackendDAE.AdjacencyMatrixT,array<Integer>,array<Integer>>> tpl;
11178 case _
11179 algorithm
11180 1060 BackendDAE.DAE(eqs=eqs) := dae;
11181
1/2
✓ Branch 1 taken 1060 times.
✗ Branch 2 not taken.
2120 tpl := List.map1(eqs,setUpSystMapping,BackendDAEUtil.isInitializationDAE(dae.shared));
11182 1060 sizeE := List.applyAndFold(tpl,intAdd,Util.tuple61,0);
11183 1060 sizeV := List.applyAndFold(tpl,intAdd,Util.tuple62,0);
11184 eqMap := {};
11185 varMap := {};
11186 1060 simVarMapping := arrayCreate(sizeV,{});
11187 1060 eqMatch := arrayCreate(sizeE,0);
11188 1060 varMatch := arrayCreate(sizeV,0);
11189 1060 m := arrayCreate(sizeE,{});
11190 1060 mt := arrayCreate(sizeV,{});
11191 1060 (_,_,m,mt,eqMatch,varMatch) := List.fold(tpl,appendAdjacencyMatrices,(0,0,m,mt,eqMatch,varMatch));
11192 1060 tree := arrayCreate(sizeE,{});
11193 1060 tree := List.fold4(List.intRange(sizeE),setUpEqTree,m,mt,eqMatch,varMatch,tree);
11194 1060 tree := Array.map(tree,List.unique);
11195 1060 mapping := SimCode.BACKENDMAPPING(m,mt,eqMap,varMap,eqMatch,varMatch,tree,simVarMapping);
11196 then
11197 mapping;
11198 else
11199 SimCode.NO_MAPPING();
11200 end matchcontinue;
11201 end setUpBackendMapping;
11202
11203 protected function setUpEqTree" builds the tree graph. the index depicts an equation and the entry depicts the direct predecessors.
11204 author:Waurich TUD 2014-04"
11205 input Integer beq;
11206 input BackendDAE.AdjacencyMatrix m;
11207 input BackendDAE.AdjacencyMatrixT mt;
11208 input array<Integer> eqMatch;
11209 input array<Integer> varMatch;
11210 input array<list<Integer>> treeIn;
11211 output array<list<Integer>> treeOut;
11212 protected
11213 Integer assVar;
11214 list<Integer> preEqs,depVars;
11215 algorithm
11216 53029 assVar := arrayGet(eqMatch,beq);
11217 53029 depVars := arrayGet(m,beq);
11218 53029 depVars := List.filter1OnTrue(depVars,setUpEqTree_Help,assVar);
11219 53029 preEqs := List.map1(depVars,Array.getIndexFirst,varMatch);
11220 53029 arrayUpdate(treeIn, beq, listAppend(treeIn[beq], preEqs));
11221 treeOut := treeIn;
11222 end setUpEqTree;
11223
11224 protected function setUpEqTree_Help
11225 input Integer iVal;
11226 input Integer iRef;
11227 output Boolean oBool;
11228 algorithm
11229 194424 oBool := intGt(iVal, 0) and intNe(iVal, iRef);
11230 end setUpEqTree_Help;
11231
11232 protected function appendAdjacencyMatrices"appends the adjacencymatrices for the different equation systems.
11233 the indeces are raised according to the number of equations and vars in the previous systems
11234 author:Waurich TUD 2014-04"
11235 input tuple<Integer,Integer,BackendDAE.AdjacencyMatrix,BackendDAE.AdjacencyMatrixT,array<Integer>,array<Integer>> tplIn;
11236 input tuple<Integer,Integer,BackendDAE.AdjacencyMatrix,BackendDAE.AdjacencyMatrixT,array<Integer>,array<Integer>> foldIn;
11237 output tuple<Integer,Integer,BackendDAE.AdjacencyMatrix,BackendDAE.AdjacencyMatrixT,array<Integer>,array<Integer>> foldOut;
11238 algorithm
11239 foldOut := match(tplIn,foldIn)
11240 local
11241 Integer sizeE,sizeV,addV,addE;
11242 array<Integer> eqMatch,varMatch,eqMatchIn,varMatchIn;
11243 BackendDAE.AdjacencyMatrix mIn,m;
11244 BackendDAE.AdjacencyMatrixT mtIn,mt;
11245 case((addE,addV,m,mt,eqMatch,varMatch),(sizeE,sizeV,mIn,mtIn,eqMatchIn,varMatchIn))
11246 algorithm
11247 3918 m := Array.map1(m,addIntLst,sizeV);
11248 3918 mt := Array.map1(mt,addIntLst,sizeE);
11249 3918 eqMatch := Array.map1(eqMatch,intAdd,sizeV);
11250 3918 varMatch := Array.map1(varMatch,intAdd,sizeE);
11251 3918 mIn := List.fold2(List.intRange(addE),updateInAdjacencyMatrix,sizeE,m,mIn);
11252 3918 mtIn := List.fold2(List.intRange(addV),updateInAdjacencyMatrix,sizeV,mt,mtIn);
11253 3918 eqMatchIn := List.fold2(List.intRange(addE),updateInMatching,sizeE,eqMatch,eqMatchIn);
11254 3918 varMatchIn := List.fold2(List.intRange(addV),updateInMatching,sizeV,varMatch,varMatchIn);
11255 3918 then
11256 ((sizeE+addE,sizeV+addV,mIn,mtIn,eqMatchIn,varMatchIn));
11257 end match;
11258 end appendAdjacencyMatrices;
11259
11260 protected function updateInAdjacencyMatrix"updates a row in an adajcency matrix. thw row indeces are raised by the offset
11261 author: Waurich TUD 2014-04"
11262 input Integer idx;
11263 input Integer offset;
11264 input BackendDAE.AdjacencyMatrix mAppend;
11265 input BackendDAE.AdjacencyMatrix mIn;
11266 output BackendDAE.AdjacencyMatrix mOut;
11267 protected
11268 list<Integer> entry;
11269 algorithm
11270 115118 entry := arrayGet(mAppend,idx);
11271 115118 mOut := arrayUpdate(mIn,idx+offset,entry);
11272 end updateInAdjacencyMatrix;
11273
11274 protected function updateInMatching"updates an entry in the matching. the indeces are raised by the offset
11275 author: Waurich TUD 2014-04"
11276 input Integer idx;
11277 input Integer offset;
11278 input array<Integer> matchingAppend;
11279 input array<Integer> matchingIn;
11280 output array<Integer> matchingOut;
11281 protected
11282 Integer entry;
11283 algorithm
11284 115118 entry := arrayGet(matchingAppend,idx);
11285 115118 matchingOut := arrayUpdate(matchingIn,idx+offset,entry);
11286 end updateInMatching;
11287
11288 protected function addIntLst"add an integer to every entry in the lst
11289 author:Waurich TUD 2014-04"
11290 input list<Integer> lstIn;
11291 input Integer x;
11292 output list<Integer> lstOut;
11293 algorithm
11294 115118 lstOut := List.map1(lstIn,intAdd,x);
11295 end addIntLst;
11296
11297 protected function setUpSystMapping"gets the mapping information for every system of equations in the backenddae.
11298 author:Waurich TUD 2014-04"
11299 input BackendDAE.EqSystem dae;
11300 input Boolean isInitial;
11301 output tuple<Integer,Integer,BackendDAE.AdjacencyMatrix,BackendDAE.AdjacencyMatrixT,array<Integer>,array<Integer>> outTpl;
11302 protected
11303 Integer sizeV,sizeE;
11304 array<Integer> ass1, ass2;
11305 BackendDAE.AdjacencyMatrix m;
11306 BackendDAE.AdjacencyMatrixT mt;
11307 BackendDAE.Matching matching;
11308 algorithm
11309 outTpl := matchcontinue dae
11310 case _
11311 algorithm
11312
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3918 times.
✓ Branch 2 taken 3917 times.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
3918 BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt),matching=matching):= dae;
11313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 BackendDAE.MATCHING(ass1=ass1,ass2=ass2) := matching;
11314 1 sizeE := BackendDAEUtil.equationArraySizeDAE(dae);
11315 1 sizeV := BackendVariable.daenumVariables(dae);
11316 1 then
11317 ((sizeE,sizeV,m,mt,ass2,ass1));
11318 case _
11319 algorithm
11320
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3917 times.
✓ Branch 2 taken 3917 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3917 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3917 times.
3917 BackendDAE.EQSYSTEM(m=NONE(),mT=NONE(),matching=matching) := dae;
11321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3917 times.
3917 BackendDAE.MATCHING(ass1=ass1,ass2=ass2) := matching;
11322 3917 (_,m,mt) := BackendDAEUtil.getAdjacencyMatrix(dae,BackendDAE.NORMAL(),NONE(),isInitial);
11323 3917 sizeE := BackendDAEUtil.equationArraySizeDAE(dae);
11324 3917 sizeV := BackendVariable.daenumVariables(dae);
11325 3917 then
11326 ((sizeE,sizeV,m,mt,ass2,ass1));
11327 end matchcontinue;
11328 end setUpSystMapping;
11329
11330 protected function setBackendVarMapping
11331 "sets the varmapping in the backendmapping.
11332 author:Waurich TUD 2014-04"
11333 input BackendDAE.BackendDAE dae;
11334 input SimCode.HashTableCrefToSimVar ht;
11335 input SimCode.ModelInfo modelInfo;
11336 input SimCode.BackendMapping bmapIn;
11337 output SimCode.BackendMapping bmapOut;
11338 algorithm
11339 bmapOut := matchcontinue bmapIn
11340 local
11341 array<Integer> eqMatch,varMatch;
11342 array<list<Integer>> tree;
11343 SimCode.VarInfo varInfo;
11344 SimCodeVar.SimVars allVars;
11345 list<Integer> bVarIdcs,simVarIdcs;
11346 list<BackendDAE.EqSystem> eqs;
11347 list<BackendDAE.Var> vars;
11348 list<DAE.ComponentRef> crefs;
11349 list<SimCodeVar.SimVar> simVars;
11350 list<tuple<Integer,list<Integer>>> eqMapping;
11351 list<tuple<Integer,Integer>> varMapping;
11352 BackendDAE.AdjacencyMatrix m;
11353 BackendDAE.AdjacencyMatrixT mt;
11354 array<list<SimCodeVar.SimVar>> simVarMapping;
11355 SimCode.HashTableCrefToSimVar htStates;
11356 Integer size;
11357 case _
11358 algorithm
11359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1060 times.
1060 SimCode.BACKENDMAPPING(m=m,mT=mt,eqMapping=eqMapping,varMapping=varMapping,eqMatch=eqMatch,varMatch=varMatch,eqTree=tree,simVarMapping=simVarMapping) := bmapIn;
11360 1060 BackendDAE.DAE(eqs=eqs) := dae;
11361
11362 //get Backend vars and index
11363 1060 vars := BackendVariable.equationSystemsVarsLst(eqs);
11364 1060 crefs := List.map(vars,BackendVariable.varCref);
11365 1060 size := listLength(crefs);
11366 1060 bVarIdcs := List.intRange(size);
11367 1060 simVars := List.map1(crefs,BaseHashTable.get,ht);
11368
11369 // get states and create hash table
11370 1060 SimCode.MODELINFO(varInfo=varInfo,vars=allVars) := modelInfo;
11371 1060 htStates := List.fold(allVars.stateVars, HashTableCrefSimVar.addSimVarToHashTable, HashTableCrefSimVar.emptyHashTableSized(1+integer(1.4*size)));
11372
11373 // produce mapping
11374 1060 simVarIdcs := List.map2(simVars,getSimVarIndex,varInfo,htStates);
11375 1060 varMapping := makeVarMapTuple(simVarIdcs,bVarIdcs,{});
11376 1060 List.fold1(simVars, fillSimVarMapping, simVarMapping, 1);
11377 //print(stringDelimitList(List.map(crefs,ComponentReferenceBasics.printComponentRefStr),"\n")+"\n");
11378 //List.map_0(simVars,dumpVar);
11379 1060 then
11380 SimCode.BACKENDMAPPING(m,mt,eqMapping,varMapping,eqMatch,varMatch,tree,simVarMapping);
11381 else
11382 SimCode.NO_MAPPING();
11383 end matchcontinue;
11384 end setBackendVarMapping;
11385
11386 protected function fillSimVarMapping "adds the given simvar to the mapping.
11387 author:marcusw"
11388 input SimCodeVar.SimVar iSimVar;
11389 input array<list<SimCodeVar.SimVar>> iSimVarMapping;
11390 input Integer iVarIdx;
11391 output Integer oVarIdx;
11392 algorithm
11393 62089 arrayUpdate(iSimVarMapping, iVarIdx, {iSimVar});
11394 62089 oVarIdx := iVarIdx + 1;
11395 end fillSimVarMapping;
11396
11397 protected function getSimVarIndex
11398 "gets the index from a SimVar and calculates the place in the localData array
11399 author:Waurich TUD 2014-04"
11400 input SimCodeVar.SimVar var;
11401 input SimCode.VarInfo varInfo;
11402 input SimCode.HashTableCrefToSimVar htStates;
11403 output Integer idx;
11404 protected
11405 Integer offset;
11406 algorithm
11407
2/2
✓ Branch 1 taken 4272 times.
✓ Branch 2 taken 57817 times.
62089 if BaseHashTable.hasKey(var.name, htStates) then
11408 4272 idx := var.index;
11409 else
11410 57817 offset := varInfo.numStateVars;
11411 57817 idx := var.index;
11412 57817 idx := idx+2*offset;
11413 end if;
11414 end getSimVarIndex;
11415
11416 protected function makeVarMapTuple"builds a tuple for the varMapping. ((simvarindex,backendvarindex))
11417 author:Waurich TUD 2014-04"
11418 input list<Integer> sVar;
11419 input list<Integer> bVar;
11420 input list<tuple<Integer,Integer>> foldIn;
11421 output list<tuple<Integer,Integer>> foldOut;
11422 algorithm
11423 foldOut := match(sVar, bVar)
11424 local
11425 Integer i1,i2;
11426 list<Integer> rest1,rest2;
11427 list<tuple<Integer,Integer>> fold;
11428 case({}, {})
11429 then
11430 foldIn;
11431 case(i1::rest1, i2::rest2)
11432 algorithm
11433 124178 fold := makeVarMapTuple(rest1,rest2,(i1,i2)::foldIn);
11434 then
11435 fold;
11436 end match;
11437 end makeVarMapTuple;
11438
11439 protected function setEqMapping"updates the equation mapping for a given pair of simeqs and backend eqs.
11440 author:Waurich TUD 2014-04"
11441 input list<Integer> simEqs;
11442 input list<Integer> bEq;
11443 input SimCode.BackendMapping mapIn;
11444 output SimCode.BackendMapping mapOut;
11445 algorithm
11446 mapOut := match mapIn
11447 local
11448 array<Integer> eqMatch,varMatch;
11449 array<list<Integer>> tree;
11450 list<tuple<Integer,list<Integer>>> eqMapping;
11451 list<tuple<Integer,Integer>> varMapping;
11452 BackendDAE.AdjacencyMatrix m;
11453 BackendDAE.AdjacencyMatrixT mt;
11454 array<list<SimCodeVar.SimVar>> simVarMapping;
11455 case SimCode.BACKENDMAPPING(m=m,mT=mt,eqMapping=eqMapping,varMapping=varMapping,eqMatch=eqMatch,varMatch=varMatch,eqTree=tree,simVarMapping=simVarMapping)
11456 algorithm
11457 39284 eqMapping := List.fold1(simEqs, appendEqIdcs, bEq, eqMapping);
11458 39284 then
11459 SimCode.BACKENDMAPPING(m,mt,eqMapping,varMapping,eqMatch,varMatch,tree,simVarMapping);
11460 case SimCode.NO_MAPPING()
11461 then
11462 mapIn;
11463 end match;
11464 end setEqMapping;
11465
11466 protected function appendEqIdcs"appends an equation mapping tuple to the mapping list.
11467 author:Waurich TUD 2014-04"
11468 input Integer iCurrentIdx;
11469 input list<Integer> iEqIdx;
11470 input list<tuple<Integer, list<Integer>>> iSccIdc;
11471 output list<tuple<Integer, list<Integer>>> oSccIdc;
11472 algorithm
11473 39708 oSccIdc:=(iCurrentIdx,iEqIdx)::iSccIdc;
11474 end appendEqIdcs;
11475
11476 public function getSimVarsInSimEq"gets the indeces for the simVars occuring in the given simEq
11477 author:Waurich TUD 2014-04"
11478 input Integer simEq;
11479 input SimCode.BackendMapping map;
11480 input Integer opt; //1: get all indeces from the adjacencyMatrix, 2: get only positive entries, 3: get only negative entries
11481 output list<Integer> simVars;
11482 protected
11483 list<Integer> bVars,bEqs;
11484 list<list<Integer>> bVarsLst;
11485 list<tuple<Integer,list<Integer>>> eqMapping;
11486 list<tuple<Integer,Integer>> varMapping;
11487 BackendDAE.AdjacencyMatrix m;
11488 BackendDAE.AdjacencyMatrixT mt;
11489 algorithm
11490 ✗ SimCode.BACKENDMAPPING(m=m,mT=mt,eqMapping=eqMapping,varMapping=varMapping) := map;
11491 ✗ bEqs := getBackendEqsForSimEq(simEq,map);
11492 ✗ bVarsLst := List.map1(bEqs,Array.getIndexFirst,m);
11493 ✗ bVars := List.flatten(bVarsLst);
11494 ✗ bVars := if intEq(opt,2) then List.filter1OnTrue(bVars,intGt,0) else bVars;
11495 ✗ bVars := if intEq(opt,3) then List.filter1OnTrue(bVars,intLt,0) else bVars;
11496 ✗ if not List.isMemberOnTrue(opt,{1,2,3},intEq) then
11497 ✗ print("invalid option for getSimVarsInSimEq\n");
11498 end if;
11499 ✗ bVars := List.unique(bVars);
11500 ✗ bVars := List.map(bVars,intAbs);
11501 ✗ simVars := List.map1(bVars,getSimVarForBackendVar,map);
11502 end getSimVarsInSimEq;
11503
11504 public function getSimEqsOfSimVar"gets the indeces for the simEqs for the given simVar
11505 author:Waurich TUD 2014-04"
11506 input Integer simVar;
11507 input SimCode.BackendMapping map;
11508 input Integer opt; //1: complete adjacency matrix row, 2: only positive entries, 3: only negative entries
11509 output list<Integer> simEqs;
11510 protected
11511 Integer bVar;
11512 list<Integer> bEqs;
11513 list<tuple<Integer,list<Integer>>> eqMapping;
11514 list<tuple<Integer,Integer>> varMapping;
11515 BackendDAE.AdjacencyMatrix m;
11516 BackendDAE.AdjacencyMatrixT mt;
11517 algorithm
11518 ✗ SimCode.BACKENDMAPPING(m=m,mT=mt,eqMapping=eqMapping,varMapping=varMapping) := map;
11519 ✗ bVar := getBackendVarForSimVar(simVar,map);
11520 ✗ bEqs := arrayGet(mt,bVar);
11521 ✗ bEqs := if intEq(opt,2) then List.filter1OnTrue(bEqs,intGt,0) else bEqs;
11522 ✗ bEqs := if intEq(opt,3) then List.filter1OnTrue(bEqs,intLt,0) else bEqs;
11523 ✗ if not List.isMemberOnTrue(opt,{1,2,3},intEq) then
11524 ✗ print("invalid option for getSimEqsOfSimVar\n");
11525 end if;
11526 ✗ bEqs := List.map(bEqs,intAbs);
11527 ✗ simEqs := List.map1(bEqs,getSimEqsForBackendEqs,map);
11528 ✗ simEqs := List.unique(simEqs);
11529 end getSimEqsOfSimVar;
11530
11531 public function getReqSimEqSysForSimVar
11532 input Integer simVar;
11533 input SimCode.SimCode simCode;
11534 output list<SimCode.SimEqSystem> ses;
11535 protected
11536 list<Integer> sesIdcs;
11537 list<SimCode.SimEqSystem> sesLst;
11538 SimCode.BackendMapping bmap;
11539 Option<SimCode.BackendMapping> bmapOpt;
11540 algorithm
11541 ✗ SimCode.SIMCODE(allEquations=sesLst, backendMapping=bmapOpt) := simCode;
11542 ✗ bmap := Util.getOption(bmapOpt);
11543 ✗ sesIdcs := getReqSimEqsForSimVar(simVar,bmap);
11544 ✗ ses := List.map1(sesIdcs,SimCodeCodegenUtil.getSimEqSysForIndex,sesLst);
11545 end getReqSimEqSysForSimVar;
11546
11547 public function getSimVarMappingOfBackendMapping "author: mwalther
11548 Get the sim var mapping that is stored in the given backend-mapping. If the backend-mapping
11549 has no simVarMapping, an empty array is returned.."
11550 input Option<SimCode.BackendMapping> iBackendMappingOpt;
11551 output array<list<SimCodeVar.SimVar>> oSimVarMapping;
11552 protected
11553 array<list<SimCodeVar.SimVar>> simVarMapping;
11554 algorithm
11555 oSimVarMapping := match iBackendMappingOpt
11556 case SOME(SimCode.BACKENDMAPPING(simVarMapping=simVarMapping))
11557 then simVarMapping;
11558 else
11559 ✗ then arrayCreate(0, {});
11560 end match;
11561 end getSimVarMappingOfBackendMapping;
11562
11563 public function getReqSimEqsForSimVar"outputs the indeces for the required simEqSys for the indexed SimVar
11564 author:Waurich TUD 2014-04"
11565 input Integer simVar;
11566 input SimCode.BackendMapping map;
11567 output list<Integer> simEqs;
11568 protected
11569 Integer bVar,bEq;
11570 list<Integer> beqs;
11571 array<Integer> eqMatch,varMatch;
11572 array<list<Integer>> tree;
11573 BackendDAE.AdjacencyMatrix m;
11574 BackendDAE.AdjacencyMatrixT mt;
11575 algorithm
11576 ✗ SimCode.BACKENDMAPPING(m=m,mT=mt,eqMatch=eqMatch,varMatch=varMatch,eqTree=tree) := map;
11577 ✗ bVar := getBackendVarForSimVar(simVar,map);
11578 ✗ bEq := arrayGet(varMatch,bVar);
11579 ✗ beqs := collectReqSimEqs(bEq,tree,{});
11580 ✗ simEqs := List.map1(beqs,getSimEqsForBackendEqs,map);
11581 ✗ simEqs := List.unique(simEqs);
11582 end getReqSimEqsForSimVar;
11583
11584 public function getAssignedSimEqSysIdx"gets the index of the assigned simEqSys for the given simVar idx
11585 author:Waurich TUD 2014-06"
11586 input Integer simVarIdx;
11587 input SimCode.BackendMapping map;
11588 output Integer simEqSysIdx;
11589 protected
11590 Integer bVarIdx,bEqIdx;
11591 array<Integer> varMatch;
11592 algorithm
11593 ✗ bVarIdx := getBackendVarForSimVar(simVarIdx,map);
11594 ✗ SimCode.BACKENDMAPPING(varMatch = varMatch) := map;
11595 ✗ bEqIdx := arrayGet(varMatch,bVarIdx);
11596 ✗ simEqSysIdx := getSimEqsForBackendEqs(bEqIdx,map);
11597 end getAssignedSimEqSysIdx;
11598
11599 protected function collectReqSimEqs"gets the previously required equations from the tree and gets the required equations for them and so on
11600 author:Waurich TUD 2014-04"
11601 input Integer eq;
11602 input array<list<Integer>> tree;
11603 input list<Integer> eqsIn;
11604 output list<Integer> eqsOut;
11605 protected
11606 list<Integer> preEqs,reqEqs;
11607 algorithm
11608 ✗ preEqs := arrayGet(tree,eq);
11609 ✗ (_,preEqs,_) := List.intersection1OnTrue(preEqs,eqsIn,intEq);
11610 ✗ reqEqs := listAppend(preEqs,eqsIn);
11611 ✗ eqsOut := List.fold1(preEqs,collectReqSimEqs,tree,reqEqs);
11612 end collectReqSimEqs;
11613
11614 protected function getBackendVarForSimVar"outputs the backendVar indeces for the given SimVar index
11615 author:Waurich TUD 2014-04"
11616 input Integer simVar;
11617 input SimCode.BackendMapping map;
11618 output Integer bVar;
11619 protected
11620 list<tuple<Integer,Integer>> varMapping;
11621 algorithm
11622 ✗ SimCode.BACKENDMAPPING(varMapping=varMapping) := map;
11623 ✗ (_,bVar):= List.getMemberOnTrue(simVar,varMapping,findSimVar);
11624 end getBackendVarForSimVar;
11625
11626 protected function getSimVarForBackendVar"outputs the SimVar indeces for the given backendVar index
11627 author:Waurich TUD 2014-04"
11628 input Integer bVar;
11629 input SimCode.BackendMapping map;
11630 output Integer simVar;
11631 protected
11632 list<tuple<Integer,Integer>> varMapping;
11633 algorithm
11634 ✗ SimCode.BACKENDMAPPING(varMapping=varMapping) := map;
11635 ✗ (simVar,_):= List.getMemberOnTrue(bVar,varMapping,findBackendVar);
11636 end getSimVarForBackendVar;
11637
11638 protected function getBackendEqsForSimEq"outputs the backendEq indeces for the given SimEqSys index
11639 author:Waurich TUD 2014-04"
11640 input Integer simEq;
11641 input SimCode.BackendMapping map;
11642 output list<Integer> bEqs;
11643 protected
11644 list<tuple<Integer,list<Integer>>> eqMapping;
11645 algorithm
11646 ✗ SimCode.BACKENDMAPPING(eqMapping=eqMapping) := map;
11647 ✗ (_,bEqs):= List.getMemberOnTrue(simEq,eqMapping,findSimEqs);
11648 end getBackendEqsForSimEq;
11649
11650 protected function getSimEqsForBackendEqs"outputs the simEqSys index for the given backendEquation index
11651 author:Waurich TUD 2014-04"
11652 input Integer bEq;
11653 input SimCode.BackendMapping map;
11654 output Integer simEq;
11655 protected
11656 list<tuple<Integer,list<Integer>>> eqMapping;
11657 algorithm
11658 ✗ SimCode.BACKENDMAPPING(eqMapping=eqMapping) := map;
11659 ✗ (simEq,_):= List.getMemberOnTrue(bEq,eqMapping,findBEqs);
11660 end getSimEqsForBackendEqs;
11661
11662 protected function findSimVar"outputs true if the tuple contains mapping information about the SimVar
11663 author:Waurich TUD 2014-04"
11664 input Integer simVar;
11665 input tuple<Integer,Integer> varTpl;
11666 output Boolean b;
11667 protected
11668 Integer simVar1;
11669 algorithm
11670 ✗ (simVar1,_) := varTpl;
11671 ✗ b := intEq(simVar,simVar1);
11672 end findSimVar;
11673
11674 protected function findBackendVar"outputs true if the tuple contains mapping information about the SimVar
11675 author:Waurich TUD 2014-04"
11676 input Integer bVar;
11677 input tuple<Integer,Integer> varTpl;
11678 output Boolean b;
11679 protected
11680 Integer bVar1;
11681 algorithm
11682 ✗ (_,bVar1) := varTpl;
11683 ✗ b := intEq(bVar,bVar1);
11684 end findBackendVar;
11685
11686 protected function findSimEqs"outputs true if the tuple contains mapping information about the SimEquation
11687 author:Waurich TUD 2014-04"
11688 input Integer simEq;
11689 input tuple<Integer,list<Integer>> eqTpl;
11690 output Boolean b;
11691 protected
11692 Integer simEq1;
11693 algorithm
11694 ✗ (simEq1,_) := eqTpl;
11695 ✗ b := intEq(simEq,simEq1);
11696 end findSimEqs;
11697
11698 protected function findBEqs"outputs true if the tuple contains mapping information about the backend equation
11699 author:Waurich TUD 2014-04"
11700 input Integer bEq;
11701 input tuple<Integer,list<Integer>> eqTpl;
11702 output Boolean b;
11703 protected
11704 list<Integer> bEq1;
11705 algorithm
11706 ✗ (_,bEq1) := eqTpl;
11707 ✗ b := listMember(bEq,bEq1);
11708 end findBEqs;
11709
11710 public function getAssignedCrefsOfSimEq"gets the crefs of the vars that are assigned (the lhs) of the simEqSystems
11711 author:Waurich TUD 2014-05"
11712 input Integer idx;
11713 input SimCode.SimCode simCode;
11714 output list<DAE.ComponentRef> crefsOut;
11715 algorithm
11716 crefsOut := match simCode
11717 local
11718 SimCode.SimEqSystem simEqSyst;
11719 list<SimCode.SimEqSystem> allEqs;
11720 list<DAE.ComponentRef> crefs;
11721 case SimCode.SIMCODE(allEquations=allEqs)
11722 algorithm
11723 ✗ simEqSyst := List.getMemberOnTrue(idx,allEqs,SimCodeCodegenUtil.indexIsEqual);
11724 ✗ crefs := SimCodeCodegenUtil.getSimEqSystemCrefsLHS(simEqSyst);
11725 then crefs;
11726 end match;
11727 end getAssignedCrefsOfSimEq;
11728
11729 public function replaceSimVarName "updates the name of simVarIn.
11730 author:Waurich TUD 2014-05"
11731 input DAE.ComponentRef cref;
11732 input SimCodeVar.SimVar simVarIn;
11733 output SimCodeVar.SimVar simVarOut = simVarIn;
11734 algorithm
11735 13501 simVarOut.name := cref;
11736 simVarOut.arrayCref := ComponentReference.getArrayCref(cref);
11737 end replaceSimVarName;
11738
11739 public function replaceSimVarIndex "updates the index of simVarIn.
11740 author:Waurich TUD 2014-05"
11741 input Integer idx;
11742 input SimCodeVar.SimVar simVarIn;
11743 output SimCodeVar.SimVar simVarOut = simVarIn;
11744 algorithm
11745 ✗ simVarOut.index := idx;
11746 end replaceSimVarIndex;
11747
11748 public function addSimVarToAlgVars
11749 input SimCodeVar.SimVar simVar;
11750 input SimCode.SimCode simCodeIn;
11751 output SimCode.SimCode simCodeOut = simCodeIn;
11752 protected
11753 SimCode.ModelInfo modelInfo;
11754 SimCodeVar.SimVars vars;
11755 algorithm
11756 ✗ modelInfo := simCodeOut.modelInfo;
11757 ✗ vars := modelInfo.vars;
11758 ✗ vars.algVars := listAppend(vars.algVars, {simVar});
11759 ✗ modelInfo.vars := vars;
11760 ✗ simCodeOut.modelInfo := modelInfo;
11761 end addSimVarToAlgVars;
11762
11763 public function addSimEqSysToODEquations "adds the given simEqSys to both to allEquations and odeEquations"
11764 input SimCode.SimEqSystem simEqSys;
11765 input Integer sysIdx;
11766 input SimCode.SimCode simCodeIn;
11767 output SimCode.SimCode simCodeOut = simCodeIn;
11768 protected
11769 list<SimCode.SimEqSystem> odes;
11770 algorithm
11771 ✗ odes := listGet(simCodeOut.odeEquations, sysIdx);
11772 odes := simEqSys::odes;
11773 ✗ simCodeOut.odeEquations := List.set(simCodeOut.odeEquations, sysIdx, odes);
11774 simCodeOut.allEquations := simEqSys::simCodeOut.allEquations;
11775 end addSimEqSysToODEquations;
11776
11777 public function addSimEqSysToInitialEquations"adds the given simEqSys to both to the initialEquations"
11778 input SimCode.SimEqSystem simEqSys;
11779 input SimCode.SimCode simCodeIn;
11780 output SimCode.SimCode simCodeOut = simCodeIn;
11781 algorithm
11782 ✗ simCodeOut.initialEquations := listAppend(simCodeOut.initialEquations, {simEqSys});
11783 end addSimEqSysToInitialEquations;
11784
11785 public function replaceODEandALLequations"replaces both allEquations and odeEquations"
11786 input list<SimCode.SimEqSystem> allEqs;
11787 input list<list<SimCode.SimEqSystem>> odeEqs;
11788 input SimCode.SimCode simCodeIn;
11789 output SimCode.SimCode simCodeOut = simCodeIn;
11790 algorithm
11791 ✗ simCodeOut.allEquations := allEqs;
11792 simCodeOut.odeEquations := odeEqs;
11793 end replaceODEandALLequations;
11794
11795 public function replaceModelInfo "replaces the ModelInfo in SimCode"
11796 input SimCode.ModelInfo modelInfoIn;
11797 input SimCode.SimCode simCodeIn;
11798 output SimCode.SimCode simCodeOut = simCodeIn;
11799 algorithm
11800 ✗ simCodeOut.modelInfo := modelInfoIn;
11801 end replaceModelInfo;
11802
11803 public function replaceSimEqSysIndex "updated the index of the given SimEqSysIn.
11804 author:Waurich TUD 2014-05"
11805 input SimCode.SimEqSystem simEqSysIn;
11806 input Integer inputIndex;
11807 output SimCode.SimEqSystem simEqSysOut;
11808 algorithm
11809 simEqSysOut := match simEqSysIn
11810 local
11811 SimCode.LinearSystem lSystem;
11812 SimCode.NonlinearSystem nlSystem;
11813 SimCode.SimEqSystem simEqSys;
11814
11815 case simEqSys as SimCode.SES_RESIDUAL()
11816 algorithm
11817 ✗ simEqSys.index := inputIndex;
11818 then simEqSys;
11819
11820 case simEqSys as SimCode.SES_FOR_RESIDUAL()
11821 algorithm
11822 ✗ simEqSys.index := inputIndex;
11823 then simEqSys;
11824
11825 case simEqSys as SimCode.SES_GENERIC_RESIDUAL()
11826 algorithm
11827 ✗ simEqSys.index := inputIndex;
11828 then simEqSys;
11829
11830 case simEqSys as SimCode.SES_SIMPLE_ASSIGN()
11831 algorithm
11832 ✗ simEqSys.index := inputIndex;
11833 then simEqSys;
11834
11835 case simEqSys as SimCode.SES_SIMPLE_ASSIGN_CONSTRAINTS()
11836 algorithm
11837 ✗ simEqSys.index := inputIndex;
11838 then simEqSys;
11839
11840 case simEqSys as SimCode.SES_ARRAY_CALL_ASSIGN()
11841 algorithm
11842 ✗ simEqSys.index := inputIndex;
11843 then simEqSys;
11844
11845 case simEqSys as SimCode.SES_IFEQUATION()
11846 algorithm
11847 ✗ simEqSys.index := inputIndex;
11848 then simEqSys;
11849
11850 case simEqSys as SimCode.SES_ALGORITHM()
11851 algorithm
11852 ✗ simEqSys.index := inputIndex;
11853 then simEqSys;
11854
11855 case simEqSys as SimCode.SES_INVERSE_ALGORITHM()
11856 algorithm
11857 ✗ simEqSys.index := inputIndex;
11858 then simEqSys;
11859
11860 // WARNING: dynamic tearing not handled
11861 case simEqSys as SimCode.SES_LINEAR(lSystem=lSystem)
11862 algorithm
11863 ✗ lSystem.index := inputIndex;
11864 ✗ simEqSys.lSystem := lSystem;
11865 then simEqSys;
11866
11867 // WARNING: dynamic tearing not handled
11868 case simEqSys as SimCode.SES_NONLINEAR(nlSystem=nlSystem)
11869 algorithm
11870 ✗ nlSystem.index := inputIndex;
11871 ✗ simEqSys.nlSystem := nlSystem;
11872 then simEqSys;
11873
11874 case simEqSys as SimCode.SES_MIXED()
11875 algorithm
11876 ✗ simEqSys.index := inputIndex;
11877 then simEqSys;
11878
11879 case simEqSys as SimCode.SES_WHEN()
11880 algorithm
11881 ✗ simEqSys.index := inputIndex;
11882 then simEqSys;
11883
11884 case simEqSys as SimCode.SES_FOR_LOOP()
11885 algorithm
11886 ✗ simEqSys.index := inputIndex;
11887 then simEqSys;
11888 end match;
11889 end replaceSimEqSysIndex;
11890
11891 public function getLSindex"outputs the index of the SES_LINEAR or -1"
11892 input SimCode.SimEqSystem simEqSys;
11893 output Integer lsIdx;
11894 algorithm
11895 lsIdx := match simEqSys
11896 local
11897 Integer idx;
11898 case SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(indexLinearSystem=idx))
11899 then idx;
11900 else
11901 then -1;
11902 end match;
11903 end getLSindex;
11904
11905 public function getNLSindex"outputs the index of the SES_NONLINEAR or -1"
11906 input SimCode.SimEqSystem simEqSys;
11907 output Integer nlsIdx;
11908 algorithm
11909 nlsIdx := match simEqSys
11910 local
11911 Integer idx;
11912 case SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(indexNonLinearSystem=idx))
11913 then idx;
11914 else
11915 then -1;
11916 end match;
11917 end getNLSindex;
11918
11919 public function getMixedindex"outputs the index of the SES_MIXED or -1"
11920 input SimCode.SimEqSystem simEqSys;
11921 output Integer mIdx;
11922 algorithm
11923 mIdx := match simEqSys
11924 local
11925 Integer idx;
11926 case SimCode.SES_MIXED(indexMixedSystem=idx)
11927 then idx;
11928 else
11929 then -1;
11930 end match;
11931 end getMixedindex;
11932
11933 public function getRemovedEquationSimEqSysIdxes"gets the simEqSystem - indeces for teh removedEquations
11934 author: Waurich TUD 2014-07"
11935 input SimCode.SimCode simCode;
11936 output list<Integer> simEqSysIdcs;
11937 protected
11938 list<SimCode.SimEqSystem> remEqs;
11939 algorithm
11940 8 SimCode.SIMCODE(removedEquations=remEqs) := simCode;
11941 8 simEqSysIdcs := List.map(remEqs,SimCodeCodegenUtil.simEqSystemIndex);
11942 end getRemovedEquationSimEqSysIdxes;
11943
11944 public function dumpIdxScVarMapping
11945 input array<Option<SimCodeVar.SimVar>> iMapping;
11946 algorithm
11947 ✗ print("Idx-ScVar-Mapping:\n");
11948 ✗ Array.fold(iMapping, dumpIdxScVarMapping0, 1);
11949 end dumpIdxScVarMapping;
11950
11951 protected function dumpIdxScVarMapping0
11952 input Option<SimCodeVar.SimVar> iVar;
11953 input Integer iIdx;
11954 output Integer oIdx;
11955 protected
11956 DAE.ComponentRef name;
11957 String refString;
11958 algorithm
11959 oIdx := match iVar
11960 case SOME(SimCodeVar.SIMVAR(name=name))
11961 algorithm
11962 ✗ print("Idx: " + intString(iIdx) + " -- ");
11963 ✗ refString := ComponentReferenceBasics.printComponentRefStr(name);
11964 ✗ print(refString + "\n");
11965 ✗ then iIdx + 1;
11966 ✗ else iIdx + 1;
11967 end match;
11968 end dumpIdxScVarMapping0;
11969
11970 protected function dumpBackendMapping"dump function for the backendmapping
11971 author:Waurich TUD 2014-04"
11972 input SimCode.BackendMapping mapIn;
11973 protected
11974 array<Integer> eqMatch,varMatch;
11975 array<list<Integer>> tree;
11976 list<tuple<Integer,list<Integer>>> eqMapping;
11977 list<tuple<Integer,Integer>> varMapping;
11978 BackendDAE.AdjacencyMatrix m;
11979 BackendDAE.AdjacencyMatrixT mt;
11980 array<list<SimCodeVar.SimVar>> simVarMapping;
11981 algorithm
11982 ✗ SimCode.BACKENDMAPPING(m=m,mT=mt,eqMapping=eqMapping,varMapping=varMapping,eqMatch=eqMatch,varMatch=varMatch,eqTree=tree,simVarMapping=simVarMapping) := mapIn;
11983 ✗ dumpEqMapping(eqMapping);
11984 /*
11985 dumpVarMapping(varMapping);
11986 print("\nthe adjacency Matrix (backendIndices)\n");
11987 BackendDump.dumpAdjacencyMatrix(m);
11988 BackendDump.dumpAdjacencyMatrixT(mt);
11989 print("\nvars matched to eq (backend indeces)\n");
11990 BackendDump.dumpMatching(varMatch);
11991 print("\nequations tree (rows:backendEqs, entrys: list of required backend equations)");
11992 BackendDump.dumpAdjacencyMatrix(tree);
11993 */
11994 end dumpBackendMapping;
11995
11996 protected function dumpEqMapping"dump function for the equation mapping
11997 author:Waurich TUD 2014-04"
11998 input list<tuple<Integer,list<Integer>>> eqMapping;
11999 protected
12000 list<tuple<Integer,list<Integer>>> lst;
12001 list<String> s;
12002 algorithm
12003 ✗ lst := listReverse(eqMapping);
12004 ✗ print("------------\n");
12005 ✗ print("BackendEquation ---> SimEqSys\n");
12006 ✗ (s,_) := List.mapFold(lst,dumpEqMappingTuple,1);
12007 ✗ print(stringDelimitList(s,"\n"));
12008 ✗ print("\n------------\n");
12009 ✗ print("\n");
12010 end dumpEqMapping;
12011
12012 protected function dumpVarMapping"dump function for the variable mapping.
12013 author:Waurich TUD 2014-04"
12014 input list<tuple<Integer,Integer>> varMapping;
12015 protected
12016 list<tuple<Integer,Integer>> lst;
12017 list<String> s;
12018 algorithm
12019 ✗ lst := listReverse(varMapping);
12020 ✗ print("------------\n");
12021 ✗ print("BackendVar ---> SimVar\n");
12022 ✗ (s,_) := List.mapFold(lst,dumpVarMappingTuple,1);
12023 ✗ print(stringDelimitList(s,"\n"));
12024 ✗ print("\n------------\n");
12025 ✗ print("\n");
12026 end dumpVarMapping;
12027
12028 protected function dumpEqMappingTuple"outputs a string for a equation mapping tuple.
12029 author:Waurich TUD 2014-04"
12030 input tuple<Integer,list<Integer>> tpl;
12031 input Integer noIn;
12032 output String s;
12033 output Integer noOut;
12034 protected
12035 Integer i1;
12036 list<Integer> lst;
12037 algorithm
12038 ✗ (i1,lst) := tpl;
12039 ✗ s := intString(noIn)+"): "+stringDelimitList(List.map(lst,intString),",")+" ---> "+intString(i1);
12040 ✗ noOut := noIn+1;
12041 end dumpEqMappingTuple;
12042
12043 protected function dumpVarMappingTuple"outputs a string for a variable mapping tuple.
12044 author:Waurich TUD 2014-04"
12045 input tuple<Integer,Integer> tpl;
12046 input Integer noIn;
12047 output String s;
12048 output Integer noOut;
12049 protected
12050 Integer i1, i2;
12051 algorithm
12052 ✗ (i1,i2) := tpl;
12053 ✗ s := intString(noIn)+"): "+intString(i2)+" ---> "+intString(i1);
12054 ✗ noOut := noIn+1;
12055 end dumpVarMappingTuple;
12056
12057
12058 public function createFMISimulationFlags
12059 "Function reads FMI simulation flags from user input --fmiFlags
12060 and creates FmiSimulationFlags record for code generation.
12061 Author: AnHeuermann"
12062 input Boolean printWarning = true;
12063 output Option<SimCode.FmiSimulationFlags> fmiSimulationFlags;
12064 protected
12065 list<String> fmiFlagsList;
12066 String pathToFile;
12067 String msg;
12068 String tmpName, tmpValue;
12069 list<String> tmpSplitted, tmpRest;
12070 list<tuple<String,String>> nameValueTuples = {} ;
12071 algorithm
12072 167 fmiFlagsList := Flags.getConfigStringList(Flags.FMI_FLAGS);
12073
12074 // No flag given
12075 // --fmiFlags or --fmiFlags=none
12076
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 157 times.
167 if listEmpty(fmiFlagsList) then
12077 fmiSimulationFlags := NONE();
12078 elseif listLength(fmiFlagsList) == 1 and stringEqual(listHead(fmiFlagsList), "none") then
12079 fmiSimulationFlags := NONE();
12080
12081 // Default case
12082 // --fmiFlags=default
12083 elseif listLength(fmiFlagsList) == 1 and stringEqual(listHead(fmiFlagsList), "default") then
12084 fmiSimulationFlags := SOME(SimCode.defaultFmiSimulationFlags);
12085
12086 // User supplied file
12087 // --fmiFlags=path/to/*.json
12088 elseif listLength(fmiFlagsList) == 1 and stringEqual( List.last(Util.stringSplitAtChar(listHead(fmiFlagsList),".")) , "json" ) then
12089 ✗ pathToFile := listHead(fmiFlagsList);
12090 ✗ if System.regularFileExists(pathToFile) then
12091 ✗ fmiSimulationFlags := SOME(SimCode.FMI_SIMULATION_FLAGS_FILE(path=pathToFile));
12092 ✗ return;
12093 elseif System.regularFileExists(Util.absoluteOrRelative(pathToFile)) then
12094 ✗ fmiSimulationFlags := SOME(SimCode.FMI_SIMULATION_FLAGS_FILE(path=Util.absoluteOrRelative(pathToFile)));
12095 ✗ return;
12096 else
12097 ✗ if printWarning then
12098 ✗ msg := "Could not find file \"" + pathToFile + "\nIgnoring \"--fmiFlags=" + pathToFile + "\" and using default setting.\n";
12099 ✗ Error.addCompilerWarning(msg);
12100 end if;
12101 fmiSimulationFlags := SOME(SimCode.defaultFmiSimulationFlags);
12102 ✗ return;
12103 end if;
12104
12105 // User supplied flags
12106 // --fmiFlags=s:cvode,nls:homotopy
12107 else
12108
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for flag in fmiFlagsList loop
12109 // A flag that takes no value is its name alone (`noRestart`); a value may
12110 // itself contain a colon.
12111 10 tmpSplitted := Util.stringSplitAtChar(flag,":");
12112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if listEmpty(tmpSplitted) then
12113 ✗ if printWarning then
12114 ✗ msg := "Can't process flag \"" + flag + "\".\nIt names no simulation flag.\n";
12115 ✗ Error.addCompilerWarning(msg);
12116 end if;
12117 ✗ continue;
12118 end if;
12119 10 tmpName :: tmpRest := tmpSplitted;
12120 10 tmpValue := stringDelimitList(tmpRest, ":");
12121
12122 // Save value
12123
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
10 if stringEqual(tmpName, "s") then
12124 // euler/cvode is what C's FMI2CS_initializeSolverData accepts; another
12125 // target links its own driver and validates against its own solver set.
12126
6/12
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 10 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 10 times.
10 if Config.simCodeTarget() == "C"
12127 and not stringEqual(tmpValue, "euler") and not stringEqual(tmpValue, "cvode") then
12128 ✗ if printWarning then
12129 ✗ msg := "Unknown value \"" + tmpValue + "\" for flag \"s\".";
12130 ✗ Error.addCompilerWarning(msg);
12131 end if;
12132 end if;
12133 else
12134 ✗ if printWarning then
12135 ✗ msg := "Adding unknown FMU simulation flag \"" + tmpName + "\" .";
12136 ✗ Error.addCompilerWarning(msg);
12137 end if;
12138 end if;
12139 10 nameValueTuples := (tmpName, tmpValue) :: nameValueTuples;
12140 end for;
12141 10 nameValueTuples := Dangerous.listReverseInPlace(nameValueTuples);
12142 10 fmiSimulationFlags := SOME(SimCode.FMI_SIMULATION_FLAGS(nameValueTuples));
12143 end if;
12144 end createFMISimulationFlags;
12145
12146 public function createFMIModelStructure
12147 " function detectes the model stucture for FMI 2.0
12148 by analyzing the symbolic jacobian matrices and sparsity pattern"
12149 input BackendDAE.SymbolicJacobians inSymjacs;
12150 input SimCode.ModelInfo inModelInfo;
12151 input Integer inUniqueEqIndex;
12152 input BackendDAE.BackendDAE inInitDAE;
12153 input BackendDAE.BackendDAE inSimDAE;
12154 output list<SimCode.JacobianMatrix> symJacFMI = {};
12155 output Option<SimCode.FmiModelStructure> outFmiModelStructure;
12156 output SimCode.ModelInfo outModelInfo = inModelInfo;
12157 output list<SimCode.JacobianMatrix> symJacs = {};
12158 output Integer uniqueEqIndex = inUniqueEqIndex;
12159 output AvlTreePathFunction.Tree outFmiDerInitFuncTree = AvlTreePathFunction.new() "functions the FMIDERINIT jacobian calls, may hold functions created by the differentiation";
12160 protected
12161 BackendDAE.SparsePatternCrefs spTA, spTA1;
12162 SimCode.SparsityPattern sparseInts;
12163 list<SimCode.FmiUnknown> allUnknowns, derivatives, outputs, discreteStates, allInitialUnknowns;
12164 list<SimCodeVar.SimVar> varsA, varsB, varsC, varsD, clockedStates, allOutputVars, allParamVars, tmpInitialUnknowns;
12165 list<DAE.ComponentRef> diffCrefsA, diffCrefsA1, diffedCrefsA, diffedCrefsA1, derdiffCrefsA;
12166 Option<BackendDAE.SymbolicJacobian> optcontPartDer, optinitialPartDer;
12167 BackendDAE.SparsePattern spPattern, spPattern1;
12168 BackendDAE.SparseColoring spColors, spColors1;
12169 BackendDAE.NonlinearPattern nlPattern;
12170 BackendDAE.SymbolicJacobians contPartDer, initPartDer;
12171 SimCode.JacobianMatrix contSimJac, initSimJac;
12172 Option<SimCode.JacobianMatrix> contPartSimDer, initPartSimDer = NONE();
12173 SimCodeVar.SimVars vars;
12174 SimCode.HashTableCrefToSimVar crefSimVarHT;
12175 BackendDAE.SymbolicJacobians fmiDerInit = {};
12176 list<SimCode.JacobianMatrix> symJacsInit={}, symJacFMIINIT={};
12177 list<tuple<Integer, DAE.ComponentRef>> sortedUnknownCrefs = {}, sortedknownCrefs = {};
12178 algorithm
12179 try
12180 //print("Start creating createFMIModelStructure\n");
12181 // combine the transposed sparse pattern of matrix A and B
12182 // to obtain dependencies for the derivativesq
12183
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 80 times.
83 SOME((optcontPartDer, spPattern as (_, spTA, (diffCrefsA, diffedCrefsA),_), spColors, nlPattern)) := SymbolicJacobian.getJacobianMatrixbyName(inSymjacs, "FMIDER");
12184
12185 80 crefSimVarHT := SimCodeCodegenUtil.createCrefToSimVarHT(inModelInfo);
12186 //print("-- Got matrices\n");
12187 80 (spTA, derdiffCrefsA) := translateSparsePatterCref2DerCref(spTA, crefSimVarHT, {}, {});
12188 //print("-- translateSparsePatterCref2DerCref matrices AB\n");
12189
12190 // collect all variable
12191 80 varsA := getSimVars2Crefs(diffedCrefsA, crefSimVarHT);
12192 80 varsB := getSimVars2Crefs(derdiffCrefsA, crefSimVarHT);
12193 80 varsC := listAppend(varsA, varsB);
12194 80 varsD := getSimVars2Crefs(diffCrefsA, crefSimVarHT);
12195 80 varsA := listAppend(varsC, varsD);
12196 //print("-- created vars for AB\n");
12197 80 sparseInts := sortSparsePattern(varsA, spTA, true);
12198 //print("-- sorted vars for AB\n");
12199 80 allUnknowns := translateSparsePatterInts2FMIUnknown(sparseInts, {});
12200
12201 // get derivatives pattern
12202 80 derivatives := fmiUnknownsOf(inModelInfo.vars.derivativeVars, allUnknowns);
12203
12204 // get output pattern
12205 80 varsA := List.filterOnTrue(inModelInfo.vars.algVars, isOutputSimVar);
12206 80 varsB := List.filterOnTrue(inModelInfo.vars.intAlgVars, isOutputSimVar); // check for outputs in intAlgVar
12207 80 varsC := List.filterOnTrue(inModelInfo.vars.boolAlgVars, isOutputSimVar); // check for outputs in boolAlgVar
12208 80 varsD := List.filterOnTrue(inModelInfo.vars.stringAlgVars, isOutputSimVar); // check for outputs in stringAlgVars
12209 80 allOutputVars := listAppend(listAppend(varsA,varsB),listAppend(varsC,varsD));
12210 80 outputs := fmiUnknownsOf(allOutputVars, allUnknowns);
12211
12212 // get discrete states pattern
12213 80 clockedStates := List.filterOnTrue(inModelInfo.vars.algVars, isClockedStateSimVar);
12214 80 discreteStates := fmiUnknownsOf(clockedStates, allUnknowns);
12215
12216 // discreteStates
12217
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 67 times.
80 if not checkForEmptyBDAE(optcontPartDer) then
12218 13 contPartDer := {(optcontPartDer,spPattern,spColors, nlPattern)};
12219
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
13 ({contSimJac}, uniqueEqIndex) := createSymbolicJacobianssSimCode(contPartDer, crefSimVarHT, uniqueEqIndex, {"FMIDER"}, {});
12220 // collect algebraic loops and symjacs for FMIDer
12221
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
13 ({contSimJac}, outModelInfo, symJacs) := addAlgebraicLoopsModelInfoSymJacs({contSimJac}, inModelInfo);
12222 contPartSimDer := SOME(contSimJac);
12223 // set partition index to number of clocks (max index) for now
12224 // TODO: use actual clock indices to support multirate systems
12225 13 symJacFMI := {rewriteJacPartIdx(contSimJac, inModelInfo.nSubClocks)};
12226 else
12227 contPartSimDer := NONE();
12228 end if;
12229
12230 // prepare FMI initialUnknowns list
12231 tmpInitialUnknowns := {};
12232
12233 // Condition-1: causality = "output" and (initial = approx or calculated)
12234 80 tmpInitialUnknowns := List.filterCons(allOutputVars, isInitialApproxOrCalculatedSimVar, tmpInitialUnknowns);
12235
12236 // Condition-2: causality = "calculatedParameter"
12237 80 allParamVars := getAllParamSimVars(inModelInfo);
12238 80 tmpInitialUnknowns := List.filterCons(allParamVars, isCausalityCalculatedParameterSimVar, tmpInitialUnknowns);
12239
12240 // Condition-3: continuous-time states with (initial = approx or calculated)
12241 80 tmpInitialUnknowns := List.filterCons(inModelInfo.vars.stateVars, isInitialApproxOrCalculatedSimVar, tmpInitialUnknowns);
12242
12243 // Condition-4: state derivatives with (initial = approx or calculated)
12244 80 tmpInitialUnknowns := List.filterCons(inModelInfo.vars.derivativeVars, isInitialApproxOrCalculatedSimVar, tmpInitialUnknowns);
12245
12246 80 tmpInitialUnknowns := Dangerous.listReverseInPlace(tmpInitialUnknowns);
12247 //dumpVarLst(tmpInitialUnknowns, "InitialUnknownList");
12248
12249 // get FMI initialUnknowns list with dependencies
12250
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 6 times.
80 if not listEmpty(tmpInitialUnknowns) then
12251 74 (allInitialUnknowns, fmiDerInit, sortedUnknownCrefs, sortedknownCrefs, outFmiDerInitFuncTree) := getFmiInitialUnknowns(inInitDAE, inSimDAE, crefSimVarHT, tmpInitialUnknowns);
12252 else
12253 allInitialUnknowns := {};
12254 end if;
12255
12256 // get jacobian matrix FMIDERINT
12257
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 11 times.
80 if not listEmpty(fmiDerInit) then
12258
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
69 SOME((optinitialPartDer, spPattern1 as (_, spTA1, (diffCrefsA1, diffedCrefsA1),_), spColors1, nlPattern)) := SymbolicJacobian.getJacobianMatrixbyName(fmiDerInit, "FMIDERINIT");
12259 // partial derivatives for fmu's during enter_initialization_mode and exit_initialization_mode
12260
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 57 times.
69 if not checkForEmptyBDAE(optinitialPartDer) then
12261 12 initPartDer := {(optinitialPartDer, spPattern1, spColors1, nlPattern)};
12262
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 ({initSimJac}, uniqueEqIndex) := createSymbolicJacobianssSimCode(initPartDer, crefSimVarHT, uniqueEqIndex, {"FMIDERINIT"}, {});
12263 // collect algebraic loops and symjacs for FMIDer
12264
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 ({initSimJac}, _, symJacsInit) := addAlgebraicLoopsModelInfoSymJacs({initSimJac}, inModelInfo);
12265 12 initPartSimDer := SOME(initSimJac);
12266 // set partition index to number of clocks (max index) for now
12267 // TODO: use actual clock indices to support multirate systems
12268 12 symJacFMIINIT := {rewriteJacPartIdx(initSimJac, inModelInfo.nSubClocks)};
12269 // append the jacobian matrix of initDAE with simDAE
12270 12 symJacFMI := listAppend(symJacFMIINIT, symJacFMI);
12271 12 symJacs := listAppend(symJacsInit, symJacs);
12272 end if;
12273 end if;
12274
12275 80 outFmiModelStructure :=
12276 SOME(
12277 SimCode.FMIMODELSTRUCTURE(
12278 SimCode.FMIOUTPUTS(outputs),
12279 SimCode.FMIDERIVATIVES(derivatives),
12280 contPartSimDer,
12281 initPartSimDer,
12282 SimCode.FMIDISCRETESTATES(discreteStates),
12283 SimCode.FMIINITIALUNKNOWNS(allInitialUnknowns, sortedUnknownCrefs, sortedknownCrefs),
12284 fmi3ArrayGroups(inModelInfo, derivatives)));
12285 else
12286 // create empty model structure
12287 try
12288 // create empty derivatives dependencies
12289
4/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
5 derivatives := list(SimCode.FMIUNKNOWN(SimCodeCodegenUtil.getVariableFMIIndex(v), {}, {})
12290 for v in getScalarVars(inModelInfo.vars.derivativeVars));
12291
12292 // create empty output dependencies
12293 3 varsA := List.filterOnTrue(inModelInfo.vars.algVars, isOutputSimVar);
12294
4/4
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 3 times.
20 outputs := list(SimCode.FMIUNKNOWN(SimCodeCodegenUtil.getVariableFMIIndex(v), {}, {})
12295 for v in getScalarVars(varsA));
12296
12297 // create empty clockedStates dependencies
12298 3 clockedStates := List.filterOnTrue(inModelInfo.vars.algVars, isClockedStateSimVar);
12299
4/4
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 52 times.
✓ Branch 4 taken 3 times.
55 discreteStates := list(SimCode.FMIUNKNOWN(SimCodeCodegenUtil.getVariableFMIIndex(v), {}, {})
12300 for v in getScalarVars(clockedStates));
12301
12302 // Compute the InitialUnknowns even though the symbolic Jacobian (and thus
12303 // the dependency information) is missing. Omitting the dependencies is valid
12304 // according to the FMI specification; the importer then assumes a dependency
12305 // on all knowns. The InitialUnknowns are mandatory in FMI 2.0 and 3.0. The
12306 // list consists of (per the FMI spec):
12307 // 1. outputs with initial = approx or calculated
12308 // 2. calculatedParameters
12309 // 3. continuous-time states with initial = approx or calculated
12310 // 4. state derivatives with initial = approx or calculated
12311 3 varsA := List.filterOnTrue(inModelInfo.vars.algVars, isOutputSimVar);
12312 3 varsB := List.filterOnTrue(inModelInfo.vars.intAlgVars, isOutputSimVar);
12313 3 varsC := List.filterOnTrue(inModelInfo.vars.boolAlgVars, isOutputSimVar);
12314 3 varsD := List.filterOnTrue(inModelInfo.vars.stringAlgVars, isOutputSimVar);
12315 3 allOutputVars := getScalarVars(listAppend(listAppend(varsA, varsB), listAppend(varsC, varsD)));
12316 tmpInitialUnknowns := {};
12317 3 tmpInitialUnknowns := List.filterCons(allOutputVars, isInitialApproxOrCalculatedSimVar, tmpInitialUnknowns);
12318 3 tmpInitialUnknowns := List.filterCons(getScalarVars(getAllParamSimVars(inModelInfo)), isCausalityCalculatedParameterSimVar, tmpInitialUnknowns);
12319 // A continuous state with a fixed start value has initial = exact (a known),
12320 // so it is not an initial unknown; an unfixed start makes it initial = approx.
12321 3 tmpInitialUnknowns := List.filterCons(getScalarVars(inModelInfo.vars.stateVars), isStateInitialUnknownSimVar, tmpInitialUnknowns);
12322 3 tmpInitialUnknowns := List.filterCons(getScalarVars(inModelInfo.vars.derivativeVars), isInitialApproxOrCalculatedSimVar, tmpInitialUnknowns);
12323 3 tmpInitialUnknowns := Dangerous.listReverseInPlace(tmpInitialUnknowns);
12324
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 3 times.
24 allInitialUnknowns := list(SimCode.FMIUNKNOWN(SimCodeCodegenUtil.getVariableFMIIndex(v), {}, {}) for v in tmpInitialUnknowns);
12325
12326 contPartSimDer := NONE();
12327 3 initPartSimDer := NONE();
12328 3 outFmiModelStructure :=
12329 SOME(
12330 SimCode.FMIMODELSTRUCTURE(
12331 SimCode.FMIOUTPUTS(outputs),
12332 SimCode.FMIDERIVATIVES(derivatives),
12333 contPartSimDer,
12334 initPartSimDer,
12335 SimCode.FMIDISCRETESTATES(discreteStates),
12336 SimCode.FMIINITIALUNKNOWNS(allInitialUnknowns, {}, {}),
12337 fmi3ArrayGroups(inModelInfo)));
12338 else
12339 ✗ Error.addInternalError("SimCodeUtil.createFMIModelStructure failed", sourceInfo());
12340 ✗ fail();
12341 end try;
12342 end try;
12343 end createFMIModelStructure;
12344
12345 protected function collectUsedFmiDerInitFunctions
12346 "returns the functions of the given tree that the FMIDERINIT jacobian equations call"
12347 input BackendDAE.SymbolicJacobians fmiDerInit;
12348 input AvlTreePathFunction.Tree fmiDerInitFuncTree;
12349 output AvlTreePathFunction.Tree usedFuncs = AvlTreePathFunction.new();
12350 protected
12351 BackendDAE.BackendDAE jacDAE;
12352 algorithm
12353
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 69 times.
138 for jac in fmiDerInit loop
12354 () := match jac
12355 case (SOME((jacDAE, _, _, _, _, _)), _, _, _)
12356 algorithm
12357 69 usedFuncs := BackendDAEOptimize.removeUnusedFunctions(jacDAE.eqs, jacDAE.shared, {}, fmiDerInitFuncTree, usedFuncs);
12358 then ();
12359 else ();
12360 end match;
12361 end for;
12362 end collectUsedFmiDerInitFunctions;
12363
12364 protected function addFmiDerInitFunctions
12365 "The FMIDERINIT jacobian is created after the functions have been elaborated, and
12366 differentiating it symbolically can call functions that nothing else in the model calls,
12367 e.g. a partial derivative created on the fly or the function of a derivative annotation
12368 that got removed by removeUnusedFunctions. Elaborate those and add them here, otherwise
12369 the generated code calls functions that are never defined."
12370 input Absyn.Program program;
12371 input AvlTreePathFunction.Tree fmiDerInitFuncTree "functions the FMIDERINIT jacobian calls";
12372 input AvlTreePathFunction.Tree elaboratedFuncTree "functions that are elaborated already";
12373 input output SimCode.ModelInfo modelInfo;
12374 input output tuple<Integer, UnorderedMap<DAE.Exp, Integer>, list<DAE.Exp>> literals;
12375 input list<SimCodeFunction.RecordDeclaration> recordDecls;
12376 output list<SimCodeFunction.RecordDeclaration> outRecordDecls = recordDecls;
12377 protected
12378 list<DAE.Function> newFuncs;
12379 list<DAE.Exp> lits;
12380 list<SimCodeFunction.Function> simFuncs;
12381 list<SimCodeFunction.RecordDeclaration> newRecordDecls;
12382 list<String> knownRecordDecls;
12383 algorithm
12384 // keep the ones that are not elaborated yet
12385
7/8
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 9 taken 1 time.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 83 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 83 times.
86 newFuncs := list(func for func guard
12386 isNone(AvlTreePathFunction.getOpt(elaboratedFuncTree, DAEUtil.functionName(func)))
12387 in DAEUtil.getFunctionList(fmiDerInitFuncTree));
12388
12389
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 2 times.
83 if listEmpty(newFuncs) then
12390 81 return;
12391 end if;
12392
12393 // same treatment the elaborated functions got in SimCodeUtilShared.createFunctions,
12394 // continuing the literal count so the indices of the existing literals still hold
12395 2 newFuncs := Inline.inlineCallsInFunctions(newFuncs, (NONE(), {DAE.NORM_INLINE(), DAE.AFTER_INDEX_RED_INLINE()}));
12396 2 (newFuncs, literals) := DAEUtil.traverseDAEFunctions(newFuncs, SimCodeFunctionUtil.findLiteralsHelper, literals);
12397 2 (_, _, lits) := literals;
12398 2 (simFuncs, newRecordDecls) := SimCodeFunctionUtil.elaborateFunctions(program, newFuncs, {}, lits, {});
12399
12400 2 modelInfo.functions := listAppend(modelInfo.functions, simFuncs);
12401
12402 // add the record declarations that are not declared already, the new ones are sorted
12403 // by their dependencies already and nothing declared before can depend on them
12404
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 knownRecordDecls := list(recordDeclarationName(rd) for rd in recordDecls);
12405
2/6
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
2 newRecordDecls := list(rd for rd guard
12406 not listMember(recordDeclarationName(rd), knownRecordDecls) in newRecordDecls);
12407 2 outRecordDecls := listAppend(recordDecls, newRecordDecls);
12408 end addFmiDerInitFunctions;
12409
12410 protected function recordDeclarationName
12411 "returns the name a record declaration is generated under"
12412 input SimCodeFunction.RecordDeclaration recordDecl;
12413 output String name;
12414 algorithm
12415 name := match recordDecl
12416 ✗ case SimCodeFunction.RECORD_DECL_FULL() then recordDecl.name;
12417 ✗ case SimCodeFunction.RECORD_DECL_ADD_CONSTRCTOR() then recordDecl.ctor_name;
12418 ✗ case SimCodeFunction.RECORD_DECL_DEF() then AbsynUtil.pathString(recordDecl.path);
12419 end match;
12420 end recordDeclarationName;
12421
12422 protected function isInitialApproxOrCalculatedSimVar
12423 "return true if the initial attribute is CALCULATED or APPROX else false"
12424 input SimCodeVar.SimVar simVar;
12425 output Boolean outBoolean;
12426 protected
12427 SimCodeVar.Causality default_causality = SimCodeVar.LOCAL();
12428 SimCodeVar.Variability default_variability = SimCodeVar.CONTINUOUS();
12429 SimCodeVar.Initial default_initial;
12430 algorithm
12431 outBoolean := match simVar
12432 case SimCodeVar.SIMVAR(initial_ = SOME(SimCodeVar.CALCULATED())) then true;
12433 case SimCodeVar.SIMVAR(initial_ = SOME(SimCodeVar.APPROX())) then true;
12434 // Calculate the initial_ attribute as we set to NONE(),
12435 // TODO should find a better way to clearup the fmi atttributes after calculating the FMI Initial unknowns
12436 case SimCodeVar.SIMVAR(initial_ = NONE())
12437 algorithm
12438 10 default_initial := SimCodeCodegenUtil.getDefaultFmiInitialAttribute(Util.getOptionOrDefault(simVar.variability, default_variability), Util.getOptionOrDefault(simVar.causality, default_causality));
12439 10 outBoolean := isInitialApproxOrCalculated(default_initial);
12440 then
12441 outBoolean;
12442 else false;
12443 end match;
12444 end isInitialApproxOrCalculatedSimVar;
12445
12446 protected function isStateInitialUnknownSimVar
12447 "A continuous-time state is an FMI initial unknown unless its start value is
12448 fixed: a fixed start makes the state initial = exact (a known), an unfixed
12449 start makes it initial = approx (an unknown). This mirrors the initial
12450 attribute emitted for states by the FMI templates."
12451 input SimCodeVar.SimVar simVar;
12452 output Boolean outBoolean;
12453 algorithm
12454 outBoolean := match simVar
12455 9 case SimCodeVar.SIMVAR(varKind = BackendDAE.STATE()) then not simVar.isFixed;
12456 ✗ else isInitialApproxOrCalculatedSimVar(simVar);
12457 end match;
12458 end isStateInitialUnknownSimVar;
12459
12460 protected function isInitialApproxOrCalculated
12461 "return true if the initial attribute is CALCULATED or APPROX else false"
12462 input SimCodeVar.Initial initial_;
12463 output Boolean outBoolean;
12464 algorithm
12465 outBoolean := match initial_
12466 case SimCodeVar.APPROX() then true;
12467 case SimCodeVar.CALCULATED() then true;
12468 else false;
12469 end match;
12470 end isInitialApproxOrCalculated;
12471
12472 protected function isCausalityCalculatedParameterSimVar
12473 "return true if the causality attribute is CALCULATED_PARAMETER else false"
12474 input SimCodeVar.SimVar inVar;
12475 output Boolean outBoolean;
12476 algorithm
12477 outBoolean := match inVar
12478 case SimCodeVar.SIMVAR(causality = SOME(SimCodeVar.CALCULATED_PARAMETER())) then true;
12479 else false;
12480 end match;
12481 end isCausalityCalculatedParameterSimVar;
12482
12483 protected function getCrefFromSimVar
12484 "return the cref from SimVar"
12485 input SimCodeVar.SimVar inSimVar;
12486 output DAE.ComponentRef outCref = inSimVar.name;
12487 end getCrefFromSimVar;
12488
12489 protected function isInitialExact
12490 "return true if the initial attribute is EXACT else false"
12491 input SimCodeVar.Initial initial_;
12492 output Boolean outBoolean;
12493 algorithm
12494 outBoolean := match initial_
12495 case SimCodeVar.EXACT() then true;
12496 else false;
12497 end match;
12498 end isInitialExact;
12499
12500 protected function getFmiInitialUnknowns
12501 "extracts the list of fmi InitialUnknowns and their dependencies
12502 defined in the modelDescription.xml under <InitialUnknowns> </InitialUnknowns>"
12503 input BackendDAE.BackendDAE inInitDAE "initialization-DAE";
12504 input BackendDAE.BackendDAE inSimDAE "simulation-DAE";
12505 input SimCode.HashTableCrefToSimVar crefSimVarHT;
12506 input list<SimCodeVar.SimVar> initialUnknownList;
12507 output list<SimCode.FmiUnknown> outFmiUnknownlist;
12508 output BackendDAE.SymbolicJacobians fmiDerInit = {} "partial derivative of initDAE";
12509 output list<tuple<Integer, DAE.ComponentRef>> sortedUnknownCrefs = {} "sorted crefs of unknowns";
12510 output list<tuple<Integer, DAE.ComponentRef>> sortedknownCrefs = {} "sorted crefs of knowns";
12511 output AvlTreePathFunction.Tree fmiDerInitFuncTree = AvlTreePathFunction.new() "functions the partial derivative of initDAE calls";
12512 protected
12513 list<DAE.ComponentRef> initialUnknownCrefs, indepCrefs, depCrefs, crefs;
12514 DAE.ComponentRef cref;
12515 BackendDAE.BackendDAE tmpBDAE;
12516 list<BackendDAE.Var> orderedVars, indepVars, depVars, fmiDerInitIndepVars, fmiDerInitDepVars;
12517 BackendDAE.SparsePattern sparsePattern;
12518 BackendDAE.SparseColoring sparseColoring;
12519 BackendDAE.SparsePatternCrefs rowspt;
12520 SimCode.SparsityPattern sparseInts;
12521 list<SimCodeVar.SimVar> vars1, vars2;
12522 BackendDAE.Shared shared;
12523 BackendDAE.EqSystem currentSystem;
12524 BackendDAE.EqSystems eqs;
12525 DAE.Exp lhs, rhs;
12526 BackendDAE.Equation eqn;
12527 BackendDAE.AdjacencyMatrix outAdjacencyMatrix;
12528 BackendDAE.StrongComponents comps;
12529 array<list<Integer>> mapEqnIncRow;
12530 array<Integer> match1,match2,mapIncRowEqn;
12531 Boolean debug = false;
12532 UnorderedSet<DAE.ComponentRef> initialUnknowns, indepCrefSet;
12533 algorithm
12534 74 initialUnknownCrefs := List.map(initialUnknownList, getCrefFromSimVar); // extract cref from initialUnknownsList
12535 74 initialUnknowns := UnorderedSet.fromList(initialUnknownCrefs,
12536 ComponentReferenceBasics.hashComponentRef, ComponentReferenceBasics.crefEqual);
12537
12538 if debug then
12539 print ("\n FmiInitialUnknownsDependencyList :" + ComponentReferenceBasics.printComponentRefListStr(initialUnknownCrefs));
12540 end if;
12541
12542 //prepare initialization DAE
12543 74 tmpBDAE := BackendDAEUtil.copyBackendDAE(inInitDAE);
12544 74 tmpBDAE := BackendDAEOptimize.collapseIndependentBlocks(tmpBDAE);
12545
12546
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 74 times.
74 BackendDAE.DAE(currentSystem::{},shared) := tmpBDAE;
12547 if debug then
12548 BackendDump.dumpVariables(currentSystem.orderedVars,"orderedVariables");
12549 BackendDump.dumpEquationArray(currentSystem.orderedEqs,"orderedEquation");
12550 BackendDump.dumpVariables(shared.globalKnownVars,"globalknownVars");
12551 BackendDump.dumpVariables(inSimDAE.shared.globalKnownVars,"SimulationGlobalknownVars");
12552 end if;
12553
12554 // traverse the simulation DAE globalknownVars and update the initialization DAE with new equations and vars
12555
2/2
✓ Branch 1 taken 5441 times.
✓ Branch 2 taken 74 times.
5515 for var in BackendVariable.varList(inSimDAE.shared.globalKnownVars) loop
12556 // check for param Vars, as we are only interested in causality = parameters
12557
4/4
✓ Branch 1 taken 2640 times.
✓ Branch 2 taken 2801 times.
✓ Branch 4 taken 2528 times.
✓ Branch 5 taken 112 times.
5441 if BackendVariable.isParam(var) and not BackendVariable.containsCref(var.varName, currentSystem.orderedVars) then
12558 2528 lhs := BackendVariable.varExp(var);
12559 2528 rhs := BackendVariable.varBindExpStartValueNoFail(var) "bindings are optional";
12560 2528 eqn := BackendDAE.EQUATION(lhs, rhs, DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_BINDING);
12561 2528 BackendEquation.add(eqn, currentSystem.orderedEqs);
12562 //var := BackendVariable.setBindExp(var,NONE());
12563 //var := BackendVariable.setVarFixed(var,false);
12564 //var := BackendVariable.setVarKind(var, BackendDAE.VARIABLE());
12565 2528 currentSystem := BackendVariable.addVarDAE(var, currentSystem);
12566 elseif not BackendVariable.containsCref(var.varName, currentSystem.orderedVars) then
12567 69 shared := BackendVariable.addGlobalKnownVarDAE(var, shared);
12568 end if;
12569 end for;
12570
12571 // Calculate adjacencyMatrix, with the newly added equations and vars. The
12572 // function tree is what the BLT sorting below passes, so one matrix serves both.
12573 148 (currentSystem, outAdjacencyMatrix, _, mapEqnIncRow, mapIncRowEqn) := BackendDAEUtil.getAdjacencyMatrixScalar(
12574 currentSystem, BackendDAE.NORMAL(), SOME(BackendDAEUtil.getFunctions(shared)), BackendDAEUtil.isInitializationDAE(shared));
12575 // Perform the match on the adjacencyMatrix
12576 74 (match1, match2) := Matching.PerfectMatching(outAdjacencyMatrix);
12577 74 comps := BackendDAEUtil.getStrongComponents(currentSystem);
12578
1/2
✓ Branch 1 taken 74 times.
✗ Branch 2 not taken.
148 currentSystem.matching := BackendDAE.MATCHING(match1, match2, comps);
12579
12580 // All causalizeDAE would still do on a matched system is sort it into BLT form,
12581 // rebuilding the adjacency matrix to get there.
12582
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 if listEmpty(comps) then
12583 74 (currentSystem, _) := BackendDAETransform.strongComponentsScalar(currentSystem, shared, mapEqnIncRow, mapIncRowEqn);
12584 end if;
12585 74 tmpBDAE := BackendDAE.DAE({currentSystem}, shared);
12586
12587 if debug then
12588 BackendDump.dumpBackendDAE(tmpBDAE, "Check Initilization DAE");
12589 end if;
12590
12591 74 orderedVars := BackendVariable.equationSystemsVarsLst(tmpBDAE.eqs); // extract ordered vars
12592
12593 74 indepVars := {}; // vars with causality = input and initial = approx or calculated, causality = calculatedParameter, states and derivative vars with initial = approx or calculated
12594 depVars := {}; // vars with causality = input and initial = exact
12595
12596 74 (depVars, indepVars) := getDepAndIndepVarsForInitialUnknowns(orderedVars, depVars, indepVars, initialUnknowns, crefSimVarHT);
12597 // search in globalKnownVars as they contains inputs and parameters with inital = exact
12598 74 (depVars, indepVars) := getDepAndIndepVarsForInitialUnknowns(BackendVariable.varList(tmpBDAE.shared.globalKnownVars), depVars, indepVars, initialUnknowns, crefSimVarHT);
12599
12600 if debug then
12601 BackendDump.dumpVarList(depVars, "depVars");
12602 BackendDump.dumpVarList(indepVars, "indepVars");
12603 end if;
12604
12605 // (fmiDerInit, _) := SymbolicJacobian.createFMIModelDerivativesForInitialization(tmpBDAE, inSimDAE, depVars, indepVars, currentSystem.orderedVars);
12606 //tmpBDAE1 := BackendDAEUtil.copyBackendDAE(tmpBDAE);
12607
12608 // Calculate the dependecies of initialUnknowns
12609 74 (sparsePattern, sparseColoring) := SymbolicJacobian.generateSparsePattern(tmpBDAE, indepVars, depVars, withColoring = not Flags.isSet(Flags.DIS_SYMJAC_FMI20));
12610 if debug then
12611 dumpFmiInitialUnknownsDependencies(sparsePattern, "FmiInitialUnknownDependency");
12612 end if;
12613
12614 // collect all variables from sparsePattern
12615 74 (_, rowspt, (indepCrefs, depCrefs), _) := sparsePattern;
12616 74 vars1 := getSimVars2Crefs(simVarCrefs(indepCrefs, crefSimVarHT), crefSimVarHT);
12617 74 vars2 := getSimVars2Crefs(simVarCrefs(depCrefs, crefSimVarHT), crefSimVarHT);
12618
12619 74 vars2 := listAppend(vars1, vars2);
12620
12621 // collect the dependency list from sparse pattern
12622 indepCrefs := {};
12623 depCrefs := {};
12624 74 indepCrefSet := UnorderedSet.new(ComponentReferenceBasics.hashComponentRef, ComponentReferenceBasics.crefEqual);
12625
2/2
✓ Branch 0 taken 2248 times.
✓ Branch 1 taken 74 times.
2322 for i in rowspt loop
12626 2248 (cref, crefs) := i;
12627 depCrefs := cref :: depCrefs;
12628
2/2
✓ Branch 0 taken 1074 times.
✓ Branch 1 taken 2248 times.
3322 for cr in crefs loop
12629
2/2
✓ Branch 1 taken 480 times.
✓ Branch 2 taken 594 times.
1074 if UnorderedSet.add(cr, indepCrefSet) then
12630 indepCrefs := cr :: indepCrefs;
12631 end if;
12632 end for;
12633 end for;
12634
12635 //print("\nUnknownVars :" + ComponentReferenceBasics.printComponentRefListStr(depCrefs));
12636 //print("\nknownVars :" + ComponentReferenceBasics.printComponentRefListStr(indepCrefs));
12637
12638 // generate Partial derivative for initDAE here, as we have the list of all depVars and inDepVars
12639
4/6
✓ Branch 1 taken 74 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 69 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
74 if not Flags.isSet(Flags.FMI20_DEPENDENCIES) and not stringEq(Config.simCodeTarget(), "Cpp") then
12640 69 fmiDerInitDepVars := getDependentAndIndepentVarsForJacobian(depCrefs, BackendVariable.listVar(orderedVars), crefSimVarHT);
12641 69 fmiDerInitIndepVars := getDependentAndIndepentVarsForJacobian(indepCrefs, BackendVariable.listVar(orderedVars), crefSimVarHT);
12642 if debug then
12643 BackendDump.dumpVarList(fmiDerInitDepVars, "fmiDerInit_unknownVars");
12644 BackendDump.dumpVarList(fmiDerInitIndepVars, "fmiDerInit_knownVars");
12645 end if;
12646 69 (fmiDerInit, fmiDerInitFuncTree) := SymbolicJacobian.createFMIModelDerivativesForInitialization(inInitDAE, inSimDAE, fmiDerInitDepVars, fmiDerInitIndepVars, currentSystem.orderedVars, sparsePattern, sparseColoring);
12647 // the jacobian can call functions that nothing else calls, keep track of them so that
12648 // they can be elaborated later on, the tree of initDAE itself is not filtered at all
12649 69 fmiDerInitFuncTree := collectUsedFmiDerInitFunctions(fmiDerInit, fmiDerInitFuncTree);
12650
12651 // sort the cref according to FMIINDEX, to be used by fmi2GetDirectionalDerivative()
12652 69 sortedknownCrefs := sortInitialUnknowsSimVars(getSimVars2Crefs(indepCrefs, crefSimVarHT));
12653 69 sortedUnknownCrefs := sortInitialUnknowsSimVars(getSimVars2Crefs(depCrefs, crefSimVarHT));
12654 end if;
12655
12656 // sort the vars with FMI Index
12657 74 sparseInts := sortSparsePattern(vars2, expandSparsePatternCrefs(rowspt, crefSimVarHT), true);
12658 // populate the FmiInitial unknowns according to FMI ModelDescription.xml format
12659 74 outFmiUnknownlist := translateSparsePatterInts2FMIUnknown(sparseInts, {});
12660 end getFmiInitialUnknowns;
12661
12662 protected function simVarCrefs
12663 "The SimVar names of backend variables: a whole array or record the SimVars
12664 are scalarized to becomes its elements."
12665 input list<DAE.ComponentRef> crefs;
12666 input SimCode.HashTableCrefToSimVar crefSimVarHT;
12667 output list<DAE.ComponentRef> outCrefs = {};
12668 protected
12669 SimCodeVar.SimVar sv;
12670 Boolean aggregate;
12671 algorithm
12672
2/2
✓ Branch 1 taken 16289 times.
✓ Branch 2 taken 11848 times.
28137 for cr in crefs loop
12673 aggregate := match ComponentReference.crefLastType(cr)
12674 case DAE.T_ARRAY() then true;
12675 case DAE.T_COMPLEX() then true;
12676 else false;
12677 end match;
12678 try
12679 // the table maps a whole-array cref to its first element's SimVar
12680
2/2
✓ Branch 0 taken 6521 times.
✓ Branch 1 taken 9768 times.
16289 true := aggregate;
12681 9768 sv := BaseHashTable.get(cr, crefSimVarHT);
12682
2/2
✓ Branch 1 taken 9456 times.
✓ Branch 2 taken 42 times.
9498 outCrefs := if ComponentReferenceBasics.crefEqual(sv.name, cr) then cr :: outCrefs
12683 else List.append_reverse(ComponentReference.expandCref(cr, true), outCrefs);
12684 else
12685 outCrefs := cr :: outCrefs;
12686 end try;
12687 end for;
12688 11848 outCrefs := listReverse(outCrefs);
12689 end simVarCrefs;
12690
12691 protected function expandSparsePatternCrefs
12692 "The rows in SimVar names: one row per element of an array unknown."
12693 input BackendDAE.SparsePatternCrefs rows;
12694 input SimCode.HashTableCrefToSimVar crefSimVarHT;
12695 output BackendDAE.SparsePatternCrefs outRows = {};
12696 protected
12697 DAE.ComponentRef cref;
12698 list<DAE.ComponentRef> crefs, deps;
12699 algorithm
12700
2/2
✓ Branch 0 taken 2248 times.
✓ Branch 1 taken 74 times.
2322 for row in rows loop
12701 2248 (cref, crefs) := row;
12702 2248 deps := simVarCrefs(crefs, crefSimVarHT);
12703
2/2
✓ Branch 1 taken 2319 times.
✓ Branch 2 taken 2248 times.
4567 for cr in simVarCrefs({cref}, crefSimVarHT) loop
12704 2319 outRows := (cr, deps) :: outRows;
12705 end for;
12706 end for;
12707 74 outRows := listReverse(outRows);
12708 end expandSparsePatternCrefs;
12709
12710 protected function getDependentAndIndepentVarsForJacobian
12711 "function which returns the rows and columns vars for jacobian matrix which will
12712 be used to get partial derivatives of fmu's using fmi2GetDirectionalDerivative"
12713 input list<DAE.ComponentRef> crefs;
12714 input BackendDAE.Variables orderedVars;
12715 input SimCode.HashTableCrefToSimVar crefSimVarHT;
12716 output list<BackendDAE.Var> outVar = {};
12717 protected
12718 BackendDAE.Var var;
12719 SimCodeVar.SimVar simVar;
12720 algorithm
12721
2/2
✓ Branch 0 taken 2534 times.
✓ Branch 1 taken 138 times.
2672 for cr in crefs loop
12722 // check if var exist otherwise don't generate derivatives for those vars, it is possible sometimes
12723 // internal variables pops up in this list
12724 try
12725 2534 var := BackendVariable.getVarSingle(cr, orderedVars);
12726 2506 simVar := BaseHashTable.get(cr, crefSimVarHT);
12727 // Filter only Real vars that match the --fmiFilter flag
12728
5/6
✓ Branch 1 taken 2057 times.
✓ Branch 2 taken 449 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2057 times.
✓ Branch 5 taken 1429 times.
✓ Branch 6 taken 628 times.
2506 if BackendVariable.isRealVar(var) and isSome(simVar.exportVar) then
12729 outVar := var :: outVar;
12730 end if;
12731 else
12732 outVar := {};
12733 end try;
12734 end for;
12735 end getDependentAndIndepentVarsForJacobian;
12736
12737 protected function getDepAndIndepVarsForInitialUnknowns
12738 "function which extracts the depVars and indepVars from initiDAE
12739 depVars contains:
12740 causality = output and initial = approx or calculated
12741 causality = calculatedParameter
12742 state vars with initial = approx or calculated and
12743 derivative vars with initial = approx or calculated
12744 indepVars contains:
12745 causality = input
12746 initial = exact
12747 "
12748 input list<BackendDAE.Var> inVar;
12749 input list<BackendDAE.Var> depVars;
12750 input list<BackendDAE.Var> indepVars;
12751 input UnorderedSet<DAE.ComponentRef> initialUnknowns;
12752 input SimCode.HashTableCrefToSimVar crefSimVarHT;
12753 output list<BackendDAE.Var> outdepVars = depVars;
12754 output list<BackendDAE.Var> outindepVars = indepVars;
12755 protected
12756 DAE.ComponentRef cref;
12757 SimCodeVar.SimVar referenceVar;
12758 SimCodeVar.Variability variability;
12759 Boolean isConst = false;
12760 algorithm
12761
2/2
✓ Branch 0 taken 7204 times.
✓ Branch 1 taken 148 times.
7352 for var in inVar loop
12762 14408 cref := listHead(simVarCrefs({BackendVariable.varCref(var)}, crefSimVarHT));
12763 // get depVars, which is basically list of InitialUnknowns extracted according to FMI-2.0 specification from SimVar,
12764
2/2
✓ Branch 1 taken 2248 times.
✓ Branch 2 taken 4956 times.
7204 if UnorderedSet.contains(cref, initialUnknowns) then
12765 outdepVars := var::outdepVars;
12766 end if;
12767 // get indepVars, which is bascially list of vars with causality = input or initial = exact
12768 try
12769 7204 referenceVar := BaseHashTable.get(cref, crefSimVarHT); // lookup in the SimVar to get causality and initial attribute
12770 // Ignore constant variables for now, they are not in the modelDescription.xml
12771 isConst := match referenceVar.variability
12772 case SOME(SimCodeVar.Variability.CONSTANT()) then true;
12773 else false;
12774 end match;
12775
4/4
✓ Branch 1 taken 6855 times.
✓ Branch 2 taken 40 times.
✓ Branch 4 taken 3475 times.
✓ Branch 5 taken 3380 times.
6895 if not isConst and (isCausalityInputSimVar(referenceVar) or isInitialExactSimVar(referenceVar)) then
12776 outindepVars := var :: outindepVars;
12777 end if;
12778 else
12779 // have to investigate this part little bit more, when unable to find the referenceVar in SimDAE, as they are removed from the initDAE
12780 end try;
12781 end for;
12782 end getDepAndIndepVarsForInitialUnknowns;
12783
12784 protected function isCausalityInputSimVar
12785 "return true if the causality attribute is INPUT else false"
12786 input SimCodeVar.SimVar simVar;
12787 output Boolean outBoolean;
12788 algorithm
12789 outBoolean := match simVar
12790 case SimCodeVar.SIMVAR(causality = SOME(SimCodeVar.INPUT())) then true;
12791 else false;
12792 end match;
12793 end isCausalityInputSimVar;
12794
12795 protected function isInitialExactSimVar
12796 "return true if the initial attribute is EXACT() else false"
12797 input SimCodeVar.SimVar simVar;
12798 output Boolean outBoolean;
12799 protected
12800 SimCodeVar.Causality default_causality = SimCodeVar.LOCAL();
12801 SimCodeVar.Variability default_variability = SimCodeVar.CONTINUOUS();
12802 SimCodeVar.Initial default_initial;
12803 algorithm
12804 outBoolean := match simVar
12805 case SimCodeVar.SIMVAR(initial_= SOME(SimCodeVar.EXACT())) then true;
12806 // Calculate the initial_ attribute as we set to NONE(),
12807 // TODO should find a better way to clearup the fmi atttributes after calculating the FMI Initial unknowns
12808 case SimCodeVar.SIMVAR(initial_= NONE())
12809 algorithm
12810 ✗ default_initial := SimCodeCodegenUtil.getDefaultFmiInitialAttribute(Util.getOptionOrDefault(simVar.variability, default_variability), Util.getOptionOrDefault(simVar.causality, default_causality));
12811 ✗ outBoolean := isInitialExact(default_initial);
12812 then
12813 outBoolean;
12814 else false;
12815 end match;
12816 end isInitialExactSimVar;
12817
12818 protected function dumpFmiInitialUnknownsDependencies
12819 "dumps the initial unknowns dependencies for FMI-2.0"
12820 input BackendDAE.SparsePattern sparsePattern;
12821 input String heading = "";
12822 protected
12823 list<tuple<DAE.ComponentRef, list<DAE.ComponentRef>>> rowspT;
12824 DAE.ComponentRef var;
12825 list<DAE.ComponentRef> dependencylist;
12826 algorithm
12827 ✗ print(heading+ "\n" + UNDERLINE + "\n");
12828 ✗ (_, rowspT, _, _) := sparsePattern;
12829 ✗ for i in rowspT loop
12830 ✗ (var, dependencylist) := i;
12831 ✗ print(ComponentReferenceBasics.printComponentRefStr(var) + "=====>" + ComponentReferenceBasics.printComponentRefListStr(dependencylist) + "\n");
12832 end for;
12833 end dumpFmiInitialUnknownsDependencies;
12834
12835 public function getAllParamSimVars
12836 "function which gets all integer, string, bool and Real Parameter
12837 Vars from modelInfo"
12838 input SimCode.ModelInfo inModelInfo;
12839 output list<SimCodeVar.SimVar> allParamVars = {};
12840 algorithm
12841 88 allParamVars := listAppend(listAppend(inModelInfo.vars.paramVars,inModelInfo.vars.intParamVars),listAppend(inModelInfo.vars.boolParamVars,inModelInfo.vars.stringParamVars));
12842 end getAllParamSimVars;
12843
12844 protected function isClockedStateSimVar
12845 "Returns true for discrete state variable, false otherwise."
12846 input SimCodeVar.SimVar inVar;
12847 output Boolean outBoolean;
12848 algorithm
12849 outBoolean := match inVar
12850 case SimCodeVar.SIMVAR(varKind = BackendDAE.CLOCKED_STATE(_)) then true;
12851 else false;
12852 end match;
12853 end isClockedStateSimVar;
12854
12855 protected function isOutputSimVar
12856 "Returns true for output variable, false otherwise."
12857 input SimCodeVar.SimVar inVar;
12858 output Boolean outBoolean;
12859 algorithm
12860 outBoolean := match inVar
12861 case SimCodeVar.SIMVAR(causality = SOME(SimCodeVar.OUTPUT())) then true;
12862 else false;
12863 end match;
12864 end isOutputSimVar;
12865
12866 protected function fmiUnknownsOf
12867 "The unknowns that are one of the variables, in the unknowns' order."
12868 input list<SimCodeVar.SimVar> vars;
12869 input list<SimCode.FmiUnknown> unknowns;
12870 output list<SimCode.FmiUnknown> selected;
12871 protected
12872 UnorderedSet<Integer> indices = UnorderedSet.new(Util.id, intEq, Util.nextPrime(listLength(vars)));
12873 algorithm
12874
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 240 times.
409 for v in vars loop
12875 169 UnorderedSet.add(SimCodeCodegenUtil.getVariableFMIIndex(v), indices);
12876 end for;
12877
6/6
✓ Branch 1 taken 467 times.
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 636 times.
✓ Branch 4 taken 240 times.
✓ Branch 5 taken 169 times.
✓ Branch 6 taken 240 times.
876 selected := list(u for u guard UnorderedSet.contains(u.index, indices) in unknowns);
12878 end fmiUnknownsOf;
12879
12880 protected function translateSparsePatterInts2FMIUnknown
12881 "function translates simVar integers to fmi unknowns."
12882 input SimCode.SparsityPattern inSparsePattern;
12883 input list<SimCode.FmiUnknown> inAccum;
12884 output list<SimCode.FmiUnknown> outFmiUnknown;
12885 algorithm
12886 outFmiUnknown := match inSparsePattern
12887 local
12888 SimCode.SparsityPattern rest;
12889 Integer unknown;
12890 list<Integer> dependencies;
12891 list<String> dependenciesKind;
12892
12893 154 case {} then listReverse(inAccum);
12894
12895 case ((unknown, dependencies))::rest
12896 algorithm
12897 // for now dependenciesKind is set to dependent
12898 1685 dependenciesKind := List.fill("dependent", listLength(dependencies));
12899 3370 then
12900 translateSparsePatterInts2FMIUnknown(rest, SimCode.FMIUNKNOWN(unknown, dependencies, dependenciesKind)::inAccum);
12901
12902 end match;
12903 end translateSparsePatterInts2FMIUnknown;
12904
12905 protected function translateSparsePatterCref2DerCref
12906 "function translates the first cref of sparse pattern to der(cref)"
12907 input BackendDAE.SparsePatternCrefs sparsePattern;
12908 input SimCode.HashTableCrefToSimVar inSimVarHT;
12909 input BackendDAE.SparsePatternCrefs inAccum;
12910 input list<DAE.ComponentRef> inAccum2;
12911 output BackendDAE.SparsePatternCrefs outSparsePattern;
12912 output list<DAE.ComponentRef> outDerCrefs;
12913 algorithm
12914 (outSparsePattern, outDerCrefs) := match sparsePattern
12915 local
12916 DAE.ComponentRef cref;
12917 list<DAE.ComponentRef> crefs;
12918 BackendDAE.SparsePatternCrefs rest;
12919 SimCodeVar.SimVar simVar;
12920
12921 80 case {} then (listReverse(inAccum), listReverse(inAccum2));
12922
12923 case ((cref, crefs))::rest
12924 algorithm
12925 212 simVar := BaseHashTable.get(cref, inSimVarHT);
12926
2/2
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 114 times.
212 if BackendVariable.isVarKindState(simVar.varKind) then
12927 98 cref := ComponentReference.crefPrefixDer(cref);
12928 end if;
12929 424 then
12930 translateSparsePatterCref2DerCref(rest, inSimVarHT, (cref, crefs)::inAccum, cref::inAccum2);
12931
12932 end match;
12933 end translateSparsePatterCref2DerCref;
12934
12935 protected function mergeSparsePatter
12936 input BackendDAE.SparsePatternCrefs inA;
12937 input BackendDAE.SparsePatternCrefs inB;
12938 input BackendDAE.SparsePatternCrefs inAccum;
12939 output BackendDAE.SparsePatternCrefs out;
12940 algorithm
12941 out := match(inA, inB)
12942 local
12943 BackendDAE.SparsePatternCrefs restA, restB;
12944 DAE.ComponentRef crefA, crefB;
12945 list<DAE.ComponentRef> listA, listB, listOut;
12946
12947 ✗ case ({}, {}) then listReverse(inAccum);
12948
12949 case ({}, _) then inB;
12950
12951 case (_, {}) then inA;
12952
12953 case (( (crefA, listA) )::restA, ((crefB, listB))::restB)
12954 algorithm
12955 ✗ true := ComponentReferenceBasics.crefEqual(crefA, crefB);
12956 ✗ listOut := List.unionOnTrue(listA, listB, ComponentReferenceBasics.crefEqual);
12957 ✗ then
12958 mergeSparsePatter(restA, restB, (crefA,listOut)::inAccum);
12959 end match;
12960 end mergeSparsePatter;
12961
12962 protected
12963 protected
12964 public
12965 protected
12966 protected
12967 function getScalarVars
12968 "Expand all arrays in a vector of SimVars. author: rfranke"
12969 input list<SimCodeVar.SimVar> inVars;
12970 output list<SimCodeVar.SimVar> outVars;
12971 algorithm
12972 outVars := {};
12973
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 21 times.
55 for var in listReverse(inVars) loop
12974 34 outVars := listAppend(SimCodeCodegenUtil.getScalarElements(var), outVars);
12975 end for;
12976 end getScalarVars;
12977
12978
12979
12980 public function exportDaeAlgebraicStates
12981 "fmi-ls-dae: the algebraic states are unknowns the importer sets, so they are in
12982 the model description whatever --fmiFilter hides, as the states are."
12983 input output SimCode.ModelInfo modelInfo;
12984 input list<SimCodeVar.SimVar> algebraicStateVars;
12985 protected
12986 HashSet.HashSet crefs = HashSet.emptyHashSet();
12987 SimCodeVar.SimVars vars;
12988 algorithm
12989 ✗ for v in algebraicStateVars loop
12990 ✗ crefs := BaseHashSet.add(v.name, crefs);
12991 end for;
12992 ✗ vars := modelInfo.vars;
12993 ✗ vars.algVars := list(exportIfAlgebraicState(v, crefs) for v in vars.algVars);
12994 ✗ modelInfo.vars := vars;
12995 end exportDaeAlgebraicStates;
12996
12997 protected function exportIfAlgebraicState
12998 input output SimCodeVar.SimVar v;
12999 input HashSet.HashSet crefs;
13000 algorithm
13001 ✗ if isNone(v.exportVar) and BaseHashSet.has(v.name, crefs) then
13002 ✗ v.exportVar := SOME(if Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_BLACKBOX
13003 then ComponentReference.getConcealedCref() else v.name);
13004 end if;
13005 end exportIfAlgebraicState;
13006
13007 public constant String FMI_LS_DAE_DRAFT_DATE = "2026-09-02";
13008 public constant String FMI_LS_DAE_DRAFT_COMMIT = "78313f4";
13009
13010
13011 protected function getHighestDerivation"computes the highest derivative among all states. this includes derivatives of derivatives as well
13012 author: waurich TUD 2015-05"
13013 input BackendDAE.BackendDAE inDAE;
13014 output Integer highestDerivation;
13015 protected
13016 list<BackendDAE.Var> vars, states;
13017 array<Integer> ders, depth;
13018 BackendDAE.Variables allStates;
13019 BackendDAE.Var var;
13020 Integer index, pos, length, curIndex;
13021 DAE.ComponentRef derCref;
13022 algorithm
13023 ✗ vars := BackendDAEUtil.getAllVarLst(inDAE);
13024 ✗ states := List.filterOnTrue(vars, BackendVariable.isStateVar);
13025 ✗ length := listLength(states);
13026 ✗ if length==0 then
13027 highestDerivation := 0;
13028 ✗ return;
13029 end if;
13030 ✗ ders := arrayCreate(length,-1 /* Has no derivative */);
13031 ✗ depth := arrayCreate(length,-1 /* Not visited */);
13032 ✗ allStates := BackendVariable.listVar1(states);
13033 // Setup data structures for a dynamic programming algorithm
13034 curIndex := 1;
13035 ✗ for state in states loop
13036 // (_, {curIndex}) := BackendVariable.getVar(state.varName, allStates); // They are all already in order
13037 () := matchcontinue state
13038 case BackendDAE.VAR(varKind=BackendDAE.STATE(index=index /* TODO: Do we need the number of times it was differentiated? */, derName = SOME(derCref)))
13039 algorithm
13040 ✗ (var,pos) := BackendVariable.getVarSingle(derCref, allStates);
13041 ✗ if not BackendVariable.varEqual(state, var) then
13042 ✗ arrayUpdate(ders, curIndex, pos);
13043 else
13044 ✗ arrayUpdate(depth, curIndex, 0);
13045 end if;
13046 then ();
13047 case BackendDAE.VAR()
13048 algorithm
13049 ✗ arrayUpdate(depth, curIndex, 0);
13050 then ();
13051 end matchcontinue;
13052 ✗ curIndex := curIndex+1;
13053 end for;
13054 // Visit all states, calculating the depth of each one, remembering the result
13055 ✗ for i in 1:length loop
13056 ✗ getHighestDerivationVisit(i, ders, depth);
13057 end for;
13058 ✗ highestDerivation := max(i for i in depth);
13059 ✗ GCExt.free(ders);
13060 ✗ GCExt.free(depth);
13061 end getHighestDerivation;
13062
13063 protected function getHighestDerivationVisit "Uses stack depth of at most max depth"
13064 input Integer i;
13065 input array<Integer> ders;
13066 input array<Integer> depth;
13067 output Integer d=arrayGet(depth, i);
13068 algorithm
13069 ✗ if d >= 0 then
13070 ✗ return;
13071 elseif d == -2 then
13072 d := 0;
13073 ✗ return;
13074 end if;
13075 ✗ arrayUpdate(depth, i, -2);
13076 ✗ d := getHighestDerivationVisit(arrayGet(ders,i), ders, depth);
13077 ✗ arrayUpdate(depth, i, d);
13078 end getHighestDerivationVisit;
13079
13080 protected function hasLargeEquationSystems "Returns true if the model contains large linear or nonlinear equation
13081 systems that are crucial for performance. If the model has a large linear or nonlinear system, the use of Lapack is prefered.
13082 Otherwise the use of dgesv (OMCompiler/3rdParty/) is prefered.
13083 author: marcusw, mflehmig TUD 2015-12"
13084 input BackendDAE.BackendDAE iDlow "simulation";
13085 input BackendDAE.BackendDAE iInitDAE "initialization";
13086 output Boolean oHasLargeEqSystem;
13087 protected
13088 Boolean hasLargeEqSystem = false;
13089 list<BackendDAE.EqSystem> eqs = {};
13090 algorithm
13091 1069 BackendDAE.DAE(eqs=eqs) := iDlow;
13092
2/2
✓ Branch 0 taken 3927 times.
✓ Branch 1 taken 1069 times.
4996 for eqsys in eqs loop
13093
2/2
✓ Branch 0 taken 3926 times.
✓ Branch 1 taken 1 time.
3927 if(boolNot(hasLargeEqSystem)) then
13094 3926 hasLargeEqSystem := hasLargeEquationSystems1(BackendDAEUtil.getStrongComponents(eqsys));
13095 end if;
13096 end for;
13097
13098 // If we found a large system, we do not need to search in iInitDAE.
13099
2/2
✓ Branch 0 taken 1053 times.
✓ Branch 1 taken 16 times.
1069 if(boolNot(hasLargeEqSystem)) then
13100 1053 BackendDAE.DAE(eqs=eqs) := iInitDAE;
13101
2/2
✓ Branch 0 taken 34395 times.
✓ Branch 1 taken 1053 times.
35448 for eqsys in eqs loop
13102
2/2
✓ Branch 0 taken 33415 times.
✓ Branch 1 taken 980 times.
34395 if(boolNot(hasLargeEqSystem)) then
13103 33415 hasLargeEqSystem := hasLargeEquationSystems1(BackendDAEUtil.getStrongComponents(eqsys));
13104 end if;
13105 end for;
13106 end if;
13107
13108 // Output information if flag dump_dgesv is set.
13109
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1069 times.
1069 if(Flags.isSet(Flags.DUMP_DGESV)) then
13110 ✗ if(boolNot(hasLargeEqSystem)) then
13111 ✗ print("This model has no large linear or nonlinear equation system, thus the use of dgesv (OMCompiler/3rdParty/) is prefered.\n");
13112 else
13113 ✗ print("This model has at least one large or nonlinear linear equation system, thus the use of Lapack is prefered.\n");
13114 end if;
13115 end if;
13116
13117 oHasLargeEqSystem := hasLargeEqSystem;
13118 end hasLargeEquationSystems;
13119
13120 protected function hasLargeEquationSystems1 "Helper function, that really returns true if the model
13121 contains large linear or non-linear equation systems that are crucial for performance. Heuristic value: 10.
13122 author: marcusw, mflehmig TUD 2015-12"
13123 input BackendDAE.StrongComponents iComps;
13124 output Boolean oHasLargeEquationSystems;
13125 protected
13126 Boolean hasLargeEqSystem = false;
13127 list<Integer> vars;
13128 algorithm
13129
2/2
✓ Branch 0 taken 113423 times.
✓ Branch 1 taken 37341 times.
150764 for comp in iComps loop
13130
2/2
✓ Branch 0 taken 108055 times.
✓ Branch 1 taken 5368 times.
113423 if(boolNot(hasLargeEqSystem)) then
13131
3/4
✓ Branch 1 taken 107930 times.
✓ Branch 2 taken 125 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 107930 times.
108055 if(boolOr(BackendDAEUtil.isLinearEqSystemComp(comp), BackendDAEUtil.isNonLinearEqSystemComp(comp))) then
13132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 BackendDAE.EQUATIONSYSTEM(vars=vars) := comp;
13133 125 hasLargeEqSystem := intGt(listLength(vars), 10);
13134 //print("DGESV1: " + intString(listLength(vars)) + "\n");
13135 else
13136
4/4
✓ Branch 1 taken 107097 times.
✓ Branch 2 taken 833 times.
✓ Branch 4 taken 677 times.
✓ Branch 5 taken 106420 times.
107930 if(boolOr(BackendDAEUtil.isLinearTornSystemComp(comp), BackendDAEUtil.isNonLinearTornSystemComp(comp))) then
13137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1510 times.
1510 BackendDAE.TORNSYSTEM(BackendDAE.TEARINGSET(tearingvars=vars)) := comp;
13138 1510 hasLargeEqSystem := intGt(listLength(vars), 10);
13139 //print("DGESV2: " + intString(listLength(vars)) + "\n");
13140 end if;
13141 end if;
13142 end if;
13143 end for;
13144 oHasLargeEquationSystems := hasLargeEqSystem;
13145 end hasLargeEquationSystems1;
13146
13147
13148 protected function createSimVarsForSensitivities
13149 "Function create variables for sensitivities calculation. It creates for every
13150 state Np(=size of real primary parameters) variables.
13151 "
13152 input list<SimCodeVar.SimVar> inStateSimVars;
13153 input list<SimCodeVar.SimVar> inParamSimVars;
13154 input Integer nFixedParameters;
13155 output list<SimCodeVar.SimVar> outSimCodeVars;
13156 output Integer countSensitivityParams = 0;
13157 protected
13158 constant Boolean debug = false;
13159 BackendDAE.Variables tmpVariables, emptyVars;
13160 BackendDAE.Var var;
13161 DAE.ComponentRef cref;
13162 list<SimCodeVar.SimVar> sensitivityParams = {};
13163 algorithm
13164 1 emptyVars := BackendVariable.emptyVars();
13165 1 tmpVariables := BackendVariable.emptyVarsSized(listLength(inStateSimVars)*nFixedParameters);
13166
13167
2/2
✓ Branch 0 taken 1483 times.
✓ Branch 1 taken 1 time.
1484 for param in inParamSimVars loop
13168 // take for now only parameters that are changeable and topLevel
13169
4/4
✓ Branch 0 taken 1132 times.
✓ Branch 1 taken 351 times.
✓ Branch 3 taken 96 times.
✓ Branch 4 taken 1036 times.
1483 if param.isValueChangeable and ComponentReference.crefIsIdent(param.name) then
13170 96 countSensitivityParams := countSensitivityParams+1;
13171 sensitivityParams := param::sensitivityParams;
13172
2/2
✓ Branch 0 taken 3936 times.
✓ Branch 1 taken 96 times.
4032 for state in inStateSimVars loop
13173 // create cref
13174 3936 cref := ComponentReferenceBasics.makeCrefIdent("$Sensitivities", DAE.T_REAL_DEFAULT, {});
13175 3936 cref := ComponentReference.joinCrefs(cref, param.name);
13176 3936 cref := ComponentReference.joinCrefs(cref, state.name);
13177
13178 if debug then
13179 print("createSimVarsForSensitivities for Var: " + ComponentReference.crefStr(cref) + "\n");
13180 end if;
13181 // create var
13182 3936 var := BackendVariable.makeVar(cref);
13183
13184 // add var to varibales
13185 3936 tmpVariables := BackendVariable.addNewVar(var, tmpVariables);
13186 end for;
13187 end if;
13188 end for;
13189 // generate SimCode vars
13190 1 (outSimCodeVars, _) := BackendVariable.traverseBackendDAEVars(tmpVariables, traversingdlowvarToSimvar, ({}, emptyVars));
13191 1 outSimCodeVars := listReverse(outSimCodeVars);
13192 1 outSimCodeVars := listAppend(listReverse(sensitivityParams), outSimCodeVars);
13193 end createSimVarsForSensitivities;
13194
13195 /*****************************************************************************************************
13196 FMU EXPERIMENTAL
13197 author: F. Bergero. 12/10/2015
13198 *****************************************************************************************************/
13199
13200
13201 public function getFunctionIndex
13202 output list<String> files;
13203 protected
13204 DoubleEnded.MutableList<String> delst;
13205 algorithm
13206 30377 delst := getGlobalRoot(Global.codegenFunctionList);
13207 30377 files := DoubleEnded.toListAndClear(delst);
13208 end getFunctionIndex;
13209
13210
13211
13212
13213 protected function simvarGraterThan
13214 input SimCodeVar.SimVar v1,v2;
13215 output Boolean b;
13216 protected
13217 Integer t1,t2,k1,k2;
13218 // Sort according to type, varkind, index
13219 algorithm
13220 ✗ k1 := valueConstructor(v1.varKind);
13221 ✗ k2 := valueConstructor(v2.varKind);
13222 ✗ t1 := valueConstructor(v1.type_);
13223 ✗ t2 := valueConstructor(v2.type_);
13224 ✗ b := if t1==t2 then
13225 (if k1==k2 then v1.index > v2.index else k1>k2)
13226 else t1>t2;
13227 end simvarGraterThan;
13228
13229 protected function crefSimCodeIndexGreaterThan
13230 input DAE.ComponentRef cr1, cr2;
13231 input SimCode.SimCode simCode;
13232 output Boolean b;
13233 protected
13234 SimCodeVar.SimVar v1, v2;
13235 algorithm
13236 ✗ v1 := SimCodeCodegenUtil.cref2simvar(cr1, simCode);
13237 ✗ v2 := SimCodeCodegenUtil.cref2simvar(cr2, simCode);
13238 ✗ b := simvarGraterThan(v1, v2);
13239 end crefSimCodeIndexGreaterThan;
13240
13241 public function getValueReferenceMapping
13242 input SimCode.ModelInfo modelInfo;
13243 output AvlTreeCRToInt.Tree tree;
13244 protected
13245 Integer i;
13246 SimCodeVar.SimVars vars;
13247 algorithm
13248 91 tree := AvlTreeCRToInt.EMPTY();
13249 91 vars := modelInfo.vars;
13250 91 (i,tree) := getValueReferenceMapping2(vars.stateVars, 0, tree);
13251 91 (i,tree) := getValueReferenceMapping2(vars.derivativeVars, i, tree);
13252 91 (i,tree) := getValueReferenceMapping2(vars.algVars, i, tree);
13253 91 (i,tree) := getValueReferenceMapping2(vars.discreteAlgVars, i, tree);
13254 91 (i,tree) := getValueReferenceMapping2(vars.paramVars, i, tree);
13255 91 (i,tree) := getValueReferenceMapping2(vars.aliasVars, i, tree);
13256
13257 91 (i,tree) := getValueReferenceMapping2(vars.intAlgVars, 0, tree);
13258 91 (i,tree) := getValueReferenceMapping2(vars.intParamVars, i, tree);
13259 91 (i,tree) := getValueReferenceMapping2(vars.intAliasVars, i, tree);
13260
13261 91 (i,tree) := getValueReferenceMapping2(vars.boolAlgVars, 0, tree);
13262 91 (i,tree) := getValueReferenceMapping2(vars.boolParamVars, i, tree);
13263 91 (i,tree) := getValueReferenceMapping2(vars.boolAliasVars, i, tree);
13264
13265 91 (i,tree) := getValueReferenceMapping2(vars.stringAlgVars, 0, tree);
13266 91 (i,tree) := getValueReferenceMapping2(vars.stringParamVars, i, tree);
13267 91 (i,tree) := getValueReferenceMapping2(vars.stringAliasVars, i, tree);
13268
13269 // external objects are exported as FMI 3.0 Binary variables; own base-type block
13270 91 (i,tree) := getValueReferenceMapping2(vars.extObjVars, 0, tree);
13271 end getValueReferenceMapping;
13272
13273 public function createMinimalFMIModelStructure
13274 "Build a minimal FMI ModelStructure (continuous state derivatives, outputs and
13275 initial unknowns, without dependency information) directly from the SimVars.
13276 Used by the new backend FMU export, which does not have the old BackendDAE
13277 that createFMIModelStructure needs. Without at least the
13278 ContinuousStateDerivative entries an FMI 3.0 Model Exchange master cannot
13279 drive the integration; the InitialUnknowns are mandatory in FMI 2.0 and 3.0."
13280 input SimCode.ModelInfo modelInfo;
13281 output Option<SimCode.FmiModelStructure> outStructure;
13282 protected
13283 list<SimCode.FmiUnknown> derivs, outs, initialUnknowns;
13284 list<SimCodeVar.SimVar> iu;
13285 algorithm
13286
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 5 times.
12 derivs := list(SimCode.FMIUNKNOWN(SimCodeCodegenUtil.getVariableFMIIndex(v), {}, {}) for v in modelInfo.vars.derivativeVars);
13287
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5 times.
8 outs := list(SimCode.FMIUNKNOWN(SimCodeCodegenUtil.getVariableFMIIndex(v), {}, {}) for v in modelInfo.vars.outputVars);
13288
13289 // InitialUnknowns according to the FMI specification, but without dependency
13290 // information (the new backend FMU export does not compute the FMIDER
13291 // Jacobian here). Omitting the dependencies is valid; the importer then
13292 // assumes a dependency on all knowns. The list consists of:
13293 // 1. outputs with initial = approx or calculated
13294 // 2. calculatedParameters
13295 // 3. continuous-time states with initial = approx or calculated
13296 // 4. state derivatives with initial = approx or calculated
13297 iu := {};
13298 5 iu := List.filterCons(modelInfo.vars.outputVars, isInitialApproxOrCalculatedSimVar, iu);
13299 5 iu := List.filterCons(getAllParamSimVars(modelInfo), isCausalityCalculatedParameterSimVar, iu);
13300 // A continuous state with a fixed start value has initial = exact (a known),
13301 // so it is not an initial unknown. The fixed attribute is used instead of
13302 // initial_ because the non-scalarized array backend does not populate
13303 // initial_ for states (see FmiInitialAttribute3 in CodegenFMU3.tpl).
13304 5 iu := List.filterCons(modelInfo.vars.stateVars, isStateInitialUnknownSimVar, iu);
13305 5 iu := List.filterCons(modelInfo.vars.derivativeVars, isInitialApproxOrCalculatedSimVar, iu);
13306 5 iu := Dangerous.listReverseInPlace(iu);
13307
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 5 times.
16 initialUnknowns := list(SimCode.FMIUNKNOWN(SimCodeCodegenUtil.getVariableFMIIndex(v), {}, {}) for v in iu);
13308
13309 5 outStructure := SOME(SimCode.FMIMODELSTRUCTURE(
13310 SimCode.FMIOUTPUTS(outs),
13311 SimCode.FMIDERIVATIVES(derivs),
13312 NONE(),
13313 NONE(),
13314 SimCode.FMIDISCRETESTATES({}),
13315 SimCode.FMIINITIALUNKNOWNS(initialUnknowns, {}, {}),
13316 fmi3ArrayGroups(modelInfo)));
13317 end createMinimalFMIModelStructure;
13318
13319 protected function fmi3ArrayGroups
13320 "The arrays the FMI 3.0 modelDescription.xml lists as one variable each:
13321 all elements exported, consecutive in row-major order and alike but for the
13322 start value; a state array only together with its derivative array, and
13323 only if that loses none of the derivatives' dependencies."
13324 input SimCode.ModelInfo modelInfo;
13325 input list<SimCode.FmiUnknown> derivatives = {};
13326 output list<SimCode.FmiArray> arrays = {};
13327 protected
13328 SimCodeVar.SimVars vars = modelInfo.vars;
13329 UnorderedSet<DAE.ComponentRef> aliasTargets;
13330 UnorderedMap<DAE.ComponentRef, SimCode.FmiArray> ders;
13331 list<SimCode.FmiArray> stateArrays;
13332 list<tuple<SimCode.FmiArray, SimCode.FmiArray>> pairs = {};
13333 UnorderedSet<Integer> lossy;
13334 SimCode.FmiArray a, d;
13335 algorithm
13336
6/8
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 72 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 time.
✗ Branch 12 not taken.
✓ Branch 13 taken 15 times.
88 if not FMI.isFMIVersion30() or Config.simCodeTarget() == "Cpp" or Flags.getConfigBool(Flags.DAE_MODE) then
13337 73 return;
13338 end if;
13339 15 aliasTargets := UnorderedSet.new(ComponentReferenceBasics.hashComponentRef, ComponentReferenceBasics.crefEqual);
13340
2/2
✓ Branch 4 taken 60 times.
✓ Branch 5 taken 15 times.
75 for lst in {vars.aliasVars, vars.intAliasVars, vars.boolAliasVars, vars.stringAliasVars} loop
13341
2/2
✓ Branch 0 taken 1322 times.
✓ Branch 1 taken 60 times.
1382 for v in lst loop
13342
2/2
✓ Branch 1 taken 808 times.
✓ Branch 2 taken 514 times.
1322 if SimCodeCodegenUtil.isFMI3NestableAlias(v) then
13343 808 UnorderedSet.add(getAliasVarCref(v), aliasTargets);
13344 end if;
13345 end for;
13346 end for;
13347 15 stateArrays := fmi3ArraysOfList(vars.stateVars, aliasTargets);
13348 15 ders := UnorderedMap.new<SimCode.FmiArray>(ComponentReferenceBasics.hashComponentRef, ComponentReferenceBasics.crefEqual);
13349
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 15 times.
16 for a in fmi3ArraysOfList(vars.derivativeVars, aliasTargets) loop
13350 1 UnorderedMap.add(a.first, a, ders);
13351 end for;
13352
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 for sa in stateArrays loop
13353 pairs := match UnorderedMap.get(ComponentReference.crefPrefixDer(sa.first), ders)
13354 ✗ case SOME(d) then (sa, d) :: pairs;
13355 else pairs;
13356 end match;
13357 end for;
13358 15 lossy := fmi3LossyStateArrays(pairs, derivatives);
13359
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 for p in listReverse(pairs) loop
13360 ✗ (a, d) := p;
13361 ✗ if not UnorderedSet.contains(a.fmiIndex, lossy) then
13362 arrays := d :: a :: arrays;
13363 end if;
13364 end for;
13365
2/2
✓ Branch 9 taken 135 times.
✓ Branch 10 taken 15 times.
150 for lst in {vars.algVars, vars.discreteAlgVars, vars.paramVars, vars.intAlgVars, vars.intParamVars,
13366 vars.boolAlgVars, vars.boolParamVars, vars.stringAlgVars, vars.stringParamVars} loop
13367 135 arrays := List.append_reverse(fmi3ArraysOfList(lst, aliasTargets), arrays);
13368 end for;
13369 15 arrays := listReverse(arrays);
13370 end fmi3ArrayGroups;
13371
13372 protected function fmi3LossyStateArrays
13373 "The state arrays, by first FMI index, that listed as one variable would look
13374 denser than they are: <ModelStructure> can only say that an array's derivative
13375 depends on whole arrays."
13376 input list<tuple<SimCode.FmiArray, SimCode.FmiArray>> pairs "state and derivative array";
13377 input list<SimCode.FmiUnknown> derivatives;
13378 output UnorderedSet<Integer> lossy = UnorderedSet.new(Util.id, intEq);
13379 protected
13380 UnorderedMap<Integer, Integer> stateOf = UnorderedMap.new<Integer>(Util.id, intEq);
13381 UnorderedMap<Integer, Integer> sizeOf = UnorderedMap.new<Integer>(Util.id, intEq);
13382 UnorderedMap<Integer, Integer> derOf = UnorderedMap.new<Integer>(Util.id, intEq);
13383 type Deps = list<Integer>;
13384 UnorderedMap<Integer, Deps> depsOf = UnorderedMap.new<Deps>(Util.id, intEq);
13385 UnorderedMap<Integer, Integer> hits;
13386 SimCode.FmiArray a, d;
13387 list<Integer> ds;
13388 Integer s, n;
13389 algorithm
13390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 for p in pairs loop
13391 ✗ (a, d) := p;
13392 ✗ UnorderedMap.add(a.fmiIndex, a.numElements, sizeOf);
13393 ✗ for k in 0:a.numElements - 1 loop
13394 ✗ UnorderedMap.add(a.fmiIndex + k, a.fmiIndex, stateOf);
13395 ✗ UnorderedMap.add(d.fmiIndex + k, a.fmiIndex, derOf);
13396 end for;
13397 end for;
13398
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 15 times.
38 for u in derivatives loop
13399 23 ds := List.sortedUnique(List.sort(u.dependencies, intGt), intEq);
13400 23 hits := UnorderedMap.new<Integer>(Util.id, intEq);
13401
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 23 times.
62 for dep in ds loop
13402 39 s := UnorderedMap.getOrDefault(dep, stateOf, 0);
13403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if s > 0 then
13404 ✗ UnorderedMap.add(s, UnorderedMap.getOrDefault(s, hits, 0) + 1, hits);
13405 end if;
13406 end for;
13407
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
23 for h in UnorderedMap.toList(hits) loop
13408 ✗ (s, n) := h;
13409 ✗ if n <> UnorderedMap.getOrFail(s, sizeOf) then
13410 ✗ UnorderedSet.add(s, lossy);
13411 end if;
13412 end for;
13413 23 s := UnorderedMap.getOrDefault(u.index, derOf, 0);
13414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if s > 0 then
13415 _ := match UnorderedMap.get(s, depsOf)
13416 local list<Integer> first;
13417 case SOME(first)
13418 algorithm
13419 ✗ if not List.isEqualOnTrue(first, ds, intEq) then
13420 ✗ UnorderedSet.add(s, lossy);
13421 end if;
13422 then ();
13423 else
13424 algorithm
13425 ✗ UnorderedMap.add(s, ds, depsOf);
13426 then ();
13427 end match;
13428 end if;
13429 end for;
13430 end fmi3LossyStateArrays;
13431
13432 protected function getAliasVarCref
13433 input SimCodeVar.SimVar var;
13434 output DAE.ComponentRef cref;
13435 algorithm
13436 cref := match var.aliasvar
13437 local DAE.ComponentRef cr;
13438 case SimCodeVar.ALIAS(varName = cr) then cr;
13439 case SimCodeVar.NEGATEDALIAS(varName = cr) then cr;
13440 ✗ else var.name;
13441 end match;
13442 end getAliasVarCref;
13443
13444 protected function fmi3ArraysOfList
13445 input list<SimCodeVar.SimVar> vars;
13446 input UnorderedSet<DAE.ComponentRef> aliasTargets;
13447 output list<SimCode.FmiArray> arrays = {};
13448 protected
13449 list<SimCodeVar.SimVar> rest = vars;
13450 SimCodeVar.SimVar v;
13451 Integer n;
13452 algorithm
13453
2/2
✓ Branch 0 taken 2021 times.
✓ Branch 1 taken 165 times.
2186 while not listEmpty(rest) loop
13454 2021 v :: rest := rest;
13455
6/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2021 times.
✓ Branch 2 taken 1499 times.
✓ Branch 3 taken 522 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 522 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 516 times.
2021 if isSome(v.arrayCref) and not listEmpty(v.numArrayElement) and not Types.isArray(v.type_) then
13456 516 n := fmi3ArrayRun(v, rest, aliasTargets);
13457
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 211 times.
516 if n > 1 then
13458 211 arrays := SimCode.FMIARRAY(v.name, SimCodeCodegenUtil.getVariableFMIIndex(v), n) :: arrays;
13459 211 rest := List.stripN(rest, n - 1);
13460 end if;
13461 end if;
13462 end while;
13463 165 arrays := listReverse(arrays);
13464 end fmi3ArraysOfList;
13465
13466 protected function fmi3ArrayRun
13467 "The size of first's array if the SimVars after it complete it, else 0."
13468 input SimCodeVar.SimVar first;
13469 input list<SimCodeVar.SimVar> rest;
13470 input UnorderedSet<DAE.ComponentRef> aliasTargets;
13471 output Integer n = 0;
13472 protected
13473 list<Integer> dims = list(stringInt(d) for d in first.numArrayElement);
13474 list<list<DAE.Subscript>> subs = fmi3ArraySubscripts(dims);
13475 list<SimCodeVar.SimVar> vars = rest;
13476 SimCodeVar.SimVar v;
13477 DAE.ComponentRef prefix = ComponentReferenceBasics.crefStripLastSubs(first.name);
13478 Integer fmiIndex = SimCodeCodegenUtil.getVariableFMIIndex(first);
13479 algorithm
13480
6/8
✓ Branch 1 taken 516 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 319 times.
✓ Branch 4 taken 197 times.
✓ Branch 8 taken 319 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 48 times.
✓ Branch 12 taken 271 times.
516 if listLength(subs) < 2 or fmiIndex <= 0
13481 or not ExpressionBasics.subscriptEqual(ComponentReference.crefLastSubs(first.name), listHead(subs))
13482 or not fmi3ArrayElementOk(first, first, aliasTargets, fmiIndex) then
13483 245 return;
13484 end if;
13485
2/2
✓ Branch 1 taken 627 times.
✓ Branch 2 taken 211 times.
838 for sub in listRest(subs) loop
13486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
627 if listEmpty(vars) then
13487 ✗ return;
13488 end if;
13489 627 v :: vars := vars;
13490 627 fmiIndex := fmiIndex + 1;
13491
9/10
✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
✓ Branch 2 taken 609 times.
✓ Branch 3 taken 18 times.
✓ Branch 6 taken 603 times.
✓ Branch 7 taken 6 times.
✓ Branch 10 taken 593 times.
✓ Branch 11 taken 10 times.
✓ Branch 13 taken 26 times.
✓ Branch 14 taken 567 times.
627 if isSome(v.arrayCref)
13492 or not ComponentReferenceBasics.crefEqual(ComponentReferenceBasics.crefStripLastSubs(v.name), prefix)
13493 or not ExpressionBasics.subscriptEqual(ComponentReference.crefLastSubs(v.name), sub)
13494 or not fmi3ArrayElementOk(first, v, aliasTargets, fmiIndex) then
13495 60 return;
13496 end if;
13497 end for;
13498 211 n := listLength(subs);
13499 end fmi3ArrayRun;
13500
13501 protected function fmi3ArraySubscripts
13502 "The subscripts of every element of an array with these dimensions, row major."
13503 input list<Integer> dims;
13504 output list<list<DAE.Subscript>> subs = {};
13505 protected
13506 Integer d;
13507 list<Integer> rest;
13508 list<list<DAE.Subscript>> tails;
13509 algorithm
13510 subs := match dims
13511 case {} then {{}};
13512 case d :: rest
13513 algorithm
13514 575 tails := fmi3ArraySubscripts(rest);
13515
1/2
✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
2287 for i in 1:d loop
13516
2/2
✓ Branch 1 taken 2043 times.
✓ Branch 2 taken 1712 times.
3755 for tail in tails loop
13517 2043 subs := (DAE.INDEX(DAE.ICONST(i)) :: tail) :: subs;
13518 end for;
13519 end for;
13520 575 then listReverse(subs);
13521 end match;
13522 end fmi3ArraySubscripts;
13523
13524 protected function fmi3ArrayElementOk
13525 input SimCodeVar.SimVar first;
13526 input SimCodeVar.SimVar v;
13527 input UnorderedSet<DAE.ComponentRef> aliasTargets;
13528 input Integer fmiIndex;
13529 output Boolean ok;
13530 algorithm
13531 ok := match (first.aliasvar, v.aliasvar)
13532 case (SimCodeVar.NOALIAS(), SimCodeVar.NOALIAS()) then true;
13533 else false;
13534 end match;
13535
35/62
✗ Branch 0 not taken.
✓ Branch 1 taken 912 times.
✓ Branch 2 taken 912 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 912 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 859 times.
✓ Branch 9 taken 53 times.
✓ Branch 11 taken 859 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 859 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 859 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 859 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 859 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 859 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 859 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 859 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 859 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 859 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 858 times.
✓ Branch 39 taken 1 time.
✓ Branch 40 taken 853 times.
✓ Branch 41 taken 5 times.
✓ Branch 42 taken 853 times.
✗ Branch 43 not taken.
✓ Branch 45 taken 853 times.
✗ Branch 46 not taken.
✓ Branch 48 taken 853 times.
✗ Branch 49 not taken.
✓ Branch 51 taken 853 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 853 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 853 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 853 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 853 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 853 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 853 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 853 times.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✓ Branch 70 taken 853 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 853 times.
✓ Branch 73 taken 838 times.
✓ Branch 74 taken 15 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 838 times.
912 ok := ok and isSome(v.exportVar) and SimCodeCodegenUtil.getVariableFMIIndex(v) == fmiIndex
13536 and not UnorderedSet.contains(v.name, aliasTargets)
13537 and valueEq(first.type_, v.type_) and fmi3SameVarKind(first.varKind, v.varKind)
13538 and first.comment == v.comment and first.unit == v.unit and first.displayUnit == v.displayUnit
13539 and valueEq(first.minValue, v.minValue) and valueEq(first.maxValue, v.maxValue)
13540 and valueEq(first.nominalValue, v.nominalValue)
13541 and first.isFixed == v.isFixed and first.isDiscrete == v.isDiscrete
13542 and valueEq(first.causality, v.causality) and valueEq(first.variability, v.variability)
13543 and valueEq(first.initial_, v.initial_)
13544 and first.isValueChangeable == v.isValueChangeable and first.isProtected == v.isProtected
13545 and valueEq(first.hideResult, v.hideResult) and first.isEncrypted == v.isEncrypted
13546 and first.relativeQuantity == v.relativeQuantity and first.isConnectorFlow == v.isConnectorFlow
13547 and valueEq(first.numArrayElement, v.numArrayElement)
13548 and isSome(first.initialValue) == isSome(v.initialValue)
13549 and fmi3ScalarStartOk(v);
13550 end fmi3ArrayElementOk;
13551
13552 protected function fmi3SameVarKind
13553 input BackendDAE.VarKind k1;
13554 input BackendDAE.VarKind k2;
13555 output Boolean same;
13556 algorithm
13557 same := match (k1, k2)
13558 case (BackendDAE.STATE(), BackendDAE.STATE()) then true;
13559 case (BackendDAE.STATE_DER(), BackendDAE.STATE_DER()) then true;
13560 case (BackendDAE.CLOCKED_STATE(), BackendDAE.CLOCKED_STATE()) then true;
13561 854 else valueEq(k1, k2);
13562 end match;
13563 end fmi3SameVarKind;
13564
13565 protected function fmi3ScalarStartOk
13566 "Where ArrayStartString3 emits a start, it must be one literal per element."
13567 input SimCodeVar.SimVar v;
13568 output Boolean ok = true;
13569 protected
13570 Boolean emitted;
13571 algorithm
13572 emitted := match (v.varKind, v.initial_)
13573 case (BackendDAE.STATE(), _) then true;
13574 case (_, SOME(SimCodeVar.EXACT())) then true;
13575 case (_, SOME(SimCodeVar.APPROX())) then true;
13576 672 else isCausalityInputSimVar(v);
13577 end match;
13578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 672 times.
672 if emitted then
13579 ok := match v.initialValue
13580 local DAE.Exp e;
13581 166 case SOME(e) then listLength(SimCodeCodegenUtil.getFMIArrayStartValues(e)) == 1;
13582 else true;
13583 end match;
13584 end if;
13585 end fmi3ScalarStartOk;
13586
13587 public function addFMI3Figures
13588 input SimCode.SimCode simCode;
13589 input String FMUVersion;
13590 output SimCode.SimCode outSimCode = simCode;
13591 algorithm
13592
2/2
✓ Branch 1 taken 75 times.
✓ Branch 2 taken 16 times.
91 if FMI.isFMIVersion30(FMUVersion) then
13593 16 outSimCode.fmiFigures := getFMI3Figures(simCode);
13594 end if;
13595 end addFMI3Figures;
13596
13597 public function getFMI3Figures
13598 "The model's Documentation(figures=...) annotation, resolved against the exported
13599 SimVars, for CodegenFMU3 to emit as the OpenModelica <Figures> vendor annotation.
13600 Curves that do not reference an exported variable (and plots/figures thereby left
13601 empty) are dropped; an empty result writes no annotation. C and wasm FMU export."
13602 input SimCode.SimCode simCode;
13603 output list<SimCode.FmiFigure> figures = {};
13604 protected
13605 Absyn.Program program;
13606 Absyn.Class cls;
13607 Option<list<Absyn.Exp>> ofigs;
13608 list<Absyn.Exp> figExps;
13609 list<tuple<String, DAE.ComponentRef>> nameMap;
13610 list<SimCode.FmiTerminal> terminals;
13611 SimCode.FmiFigure fig;
13612 algorithm
13613 16 program := SymbolTable.getAbsyn();
13614 try
13615 16 cls := ProgramUtil.getPathedClassInProgram(simCode.modelInfo.name, program);
13616 else
13617 ✗ return;
13618 end try;
13619 16 ofigs := AbsynUtil.getNamedAnnotationInClass(cls,
13620 Absyn.QUALIFIED("Documentation", Absyn.IDENT("figures")), figureExpsFromMod);
13621 figExps := match ofigs case SOME(figExps) then figExps; else {}; end match;
13622
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if listEmpty(figExps) then
13623 16 return;
13624 end if;
13625 ✗ nameMap := buildFmiFigureNameMap(simCode);
13626 ✗ terminals := SimCodeCodegenUtil.getFMI3Terminals(simCode);
13627 ✗ for e in figExps loop
13628 ✗ fig := fmiFigureFromExp(e, nameMap, terminals);
13629 ✗ if not listEmpty(fig.plots) then
13630 figures := fig :: figures;
13631 end if;
13632 end for;
13633 ✗ figures := listReverse(figures);
13634 end getFMI3Figures;
13635
13636 protected function figureExpsFromMod
13637 input Option<Absyn.Modification> mod;
13638 output list<Absyn.Exp> exps;
13639 algorithm
13640 exps := match mod
13641 local Absyn.Exp exp;
13642 ✗ case SOME(Absyn.CLASSMOD(eqMod = Absyn.EQMOD(exp = exp))) then figureExpElements(exp);
13643 else {};
13644 end match;
13645 end figureExpsFromMod;
13646
13647 protected function figureExpElements
13648 input Absyn.Exp exp;
13649 output list<Absyn.Exp> exps;
13650 algorithm
13651 exps := match exp
13652 ✗ case Absyn.ARRAY() then exp.arrayExp;
13653 else {exp};
13654 end match;
13655 end figureExpElements;
13656
13657 protected function buildFmiFigureNameMap "name -> cref over every exported SimVar, to resolve curve references"
13658 input SimCode.SimCode simCode;
13659 output list<tuple<String, DAE.ComponentRef>> nameMap = {};
13660 protected
13661 SimCodeVar.SimVars vars;
13662 list<SimCodeVar.SimVar> allVars;
13663 algorithm
13664 ✗ vars := simCode.modelInfo.vars;
13665 ✗ allVars := List.flatten({vars.stateVars, vars.derivativeVars, vars.algVars,
13666 vars.discreteAlgVars, vars.paramVars, vars.intAlgVars, vars.intParamVars,
13667 vars.boolAlgVars, vars.boolParamVars, vars.stringAlgVars, vars.stringParamVars,
13668 vars.aliasVars, vars.intAliasVars, vars.boolAliasVars, vars.stringAliasVars});
13669 ✗ for v in allVars loop
13670 ✗ nameMap := (ComponentReference.crefStr(v.name), v.name) :: nameMap;
13671 end for;
13672 end buildFmiFigureNameMap;
13673
13674 protected function fmiFigureFromExp
13675 input Absyn.Exp exp;
13676 input list<tuple<String, DAE.ComponentRef>> nameMap;
13677 input list<SimCode.FmiTerminal> terminals;
13678 output SimCode.FmiFigure figure;
13679 protected
13680 list<tuple<String, Absyn.Exp>> args;
13681 list<SimCode.FmiPlot> plots;
13682 algorithm
13683 ✗ args := figureArgs(exp, {"title", "identifier", "group", "preferred", "plots", "caption"});
13684 ✗ plots := fmiPlotsFromExp(figureArgExp(args, "plots"), nameMap, terminals);
13685 ✗ figure := SimCode.FMI_FIGURE(
13686 figureStrArg(args, "title"),
13687 figureStrArg(args, "group"),
13688 figureBoolFlag(args, "preferred"),
13689 figureStrArg(args, "caption"),
13690 plots);
13691 end fmiFigureFromExp;
13692
13693 protected function fmiPlotsFromExp
13694 input Option<Absyn.Exp> oexp;
13695 input list<tuple<String, DAE.ComponentRef>> nameMap;
13696 input list<SimCode.FmiTerminal> terminals;
13697 output list<SimCode.FmiPlot> plots = {};
13698 protected
13699 list<Absyn.Exp> elems;
13700 Option<SimCode.FmiPlot> op;
13701 algorithm
13702 ✗ elems := match oexp local Absyn.Exp e; case SOME(e) then figureExpElements(e); else {}; end match;
13703 ✗ for e in elems loop
13704 ✗ op := fmiPlotFromExp(e, nameMap, terminals);
13705 ✗ if isSome(op) then
13706 ✗ plots := Util.getOption(op) :: plots;
13707 end if;
13708 end for;
13709 ✗ plots := listReverse(plots);
13710 end fmiPlotsFromExp;
13711
13712 protected function fmiPlotFromExp
13713 "A resolved plot, or NONE() when no curve resolved to an exported variable."
13714 input Absyn.Exp exp;
13715 input list<tuple<String, DAE.ComponentRef>> nameMap;
13716 input list<SimCode.FmiTerminal> terminals;
13717 output Option<SimCode.FmiPlot> oplot;
13718 protected
13719 list<tuple<String, Absyn.Exp>> args;
13720 list<SimCode.FmiCurve> curves;
13721 algorithm
13722 ✗ args := figureArgs(exp, {"title", "identifier", "curves", "x", "y"});
13723 ✗ curves := fmiCurvesFromExp(figureArgExp(args, "curves"), nameMap);
13724 ✗ if listEmpty(curves) then
13725 oplot := NONE();
13726 else
13727 ✗ oplot := SOME(SimCode.FMI_PLOT(
13728 figureStrArg(args, "title"),
13729 curves,
13730 fmiAxisFromArg(figureArgExp(args, "x")),
13731 fmiAxisFromArg(figureArgExp(args, "y")),
13732 curvesCommonTerminal(curves, terminals)));
13733 end if;
13734 end fmiPlotFromExp;
13735
13736 protected function fmiCurvesFromExp
13737 input Option<Absyn.Exp> oexp;
13738 input list<tuple<String, DAE.ComponentRef>> nameMap;
13739 output list<SimCode.FmiCurve> curves = {};
13740 protected
13741 list<Absyn.Exp> elems;
13742 Option<SimCode.FmiCurve> oc;
13743 algorithm
13744 ✗ elems := match oexp local Absyn.Exp e; case SOME(e) then figureExpElements(e); else {}; end match;
13745 ✗ for e in elems loop
13746 ✗ oc := fmiCurveFromExp(e, nameMap);
13747 ✗ if isSome(oc) then
13748 ✗ curves := Util.getOption(oc) :: curves;
13749 end if;
13750 end for;
13751 ✗ curves := listReverse(curves);
13752 end fmiCurvesFromExp;
13753
13754 protected function fmiCurveFromExp
13755 "A resolved curve, or NONE() when y (or a given non-time x) is not an exported
13756 variable. Only plain variable references resolve, not derived expressions."
13757 input Absyn.Exp exp;
13758 input list<tuple<String, DAE.ComponentRef>> nameMap;
13759 output Option<SimCode.FmiCurve> ocurve = NONE();
13760 protected
13761 list<tuple<String, Absyn.Exp>> args;
13762 Option<DAE.ComponentRef> yref, xVar;
13763 DAE.ComponentRef yc;
13764 Boolean dropX;
13765 algorithm
13766 ✗ args := figureArgs(exp, {"x", "y", "legend"});
13767 ✗ yref := match figureArgExp(args, "y") local Absyn.Exp e; case SOME(e) then resolveFigureRef(e, nameMap); else NONE(); end match;
13768 ✗ if isNone(yref) then
13769 ✗ return;
13770 end if;
13771 ✗ SOME(yc) := yref;
13772 xVar := NONE();
13773 dropX := false;
13774 () := match figureArgExp(args, "x")
13775 local Absyn.Exp xe;
13776 case NONE() then ();
13777 case SOME(xe) guard isFigureTime(xe) then ();
13778 case SOME(xe)
13779 algorithm
13780 ✗ xVar := resolveFigureRef(xe, nameMap);
13781 ✗ dropX := isNone(xVar);
13782 then ();
13783 end match;
13784 ✗ if dropX then
13785 ✗ return;
13786 end if;
13787 ✗ ocurve := SOME(SimCode.FMI_CURVE(xVar, yc, figureStrArg(args, "legend")));
13788 end fmiCurveFromExp;
13789
13790 protected function fmiAxisFromArg
13791 input Option<Absyn.Exp> oexp;
13792 output SimCode.FmiFigureAxis axis;
13793 protected
13794 list<tuple<String, Absyn.Exp>> args;
13795 algorithm
13796 ✗ args := match oexp local Absyn.Exp e; case SOME(e) then figureArgs(e, {"min", "max", "unit", "label", "scale"}); else {}; end match;
13797 ✗ axis := SimCode.FMI_FIGURE_AXIS(
13798 figureStrArg(args, "label"),
13799 figureStrArg(args, "unit"),
13800 figureBoundArg(args, "min"),
13801 figureBoundArg(args, "max"),
13802 figureScaleIsLog(figureArgExp(args, "scale")));
13803 end fmiAxisFromArg;
13804
13805 protected function resolveFigureRef "the exported cref a curve x/y names, or NONE() if not a plain exported-var reference"
13806 input Absyn.Exp exp;
13807 input list<tuple<String, DAE.ComponentRef>> nameMap;
13808 output Option<DAE.ComponentRef> ocref;
13809 algorithm
13810 ocref := match exp
13811 local Absyn.ComponentRef acr;
13812 ✗ case Absyn.CREF(componentRef = acr) then lookupFigureName(nameMap, AbsynUtil.crefString(acr));
13813 else NONE();
13814 end match;
13815 end resolveFigureRef;
13816
13817 protected function isFigureTime
13818 input Absyn.Exp exp;
13819 output Boolean isTime;
13820 algorithm
13821 isTime := match exp
13822 local Absyn.ComponentRef acr;
13823 ✗ case Absyn.CREF(componentRef = acr) then stringEq(AbsynUtil.crefString(acr), "time");
13824 else false;
13825 end match;
13826 end isFigureTime;
13827
13828 protected function lookupFigureName
13829 input list<tuple<String, DAE.ComponentRef>> nameMap;
13830 input String key;
13831 output Option<DAE.ComponentRef> ocref = NONE();
13832 protected
13833 String k;
13834 DAE.ComponentRef c;
13835 algorithm
13836 ✗ for e in nameMap loop
13837 ✗ (k, c) := e;
13838 ✗ if stringEq(k, key) then
13839 ocref := SOME(c);
13840 ✗ return;
13841 end if;
13842 end for;
13843 end lookupFigureName;
13844
13845 protected function curvesCommonTerminal "the terminal shared by all curves y-vars, else NONE()"
13846 input list<SimCode.FmiCurve> curves;
13847 input list<SimCode.FmiTerminal> terminals;
13848 output Option<String> terminal = NONE();
13849 protected
13850 Option<String> t;
13851 Boolean first = true;
13852 algorithm
13853 ✗ for c in curves loop
13854 ✗ t := crefTerminalName(c.yVariable, terminals);
13855 ✗ if isNone(t) then
13856 terminal := NONE();
13857 ✗ return;
13858 end if;
13859 ✗ if first then
13860 terminal := t;
13861 first := false;
13862 elseif not stringEq(Util.getOption(t), Util.getOption(terminal)) then
13863 terminal := NONE();
13864 ✗ return;
13865 end if;
13866 end for;
13867 ✗ if first then
13868 terminal := NONE();
13869 end if;
13870 end curvesCommonTerminal;
13871
13872 protected function crefTerminalName
13873 input DAE.ComponentRef cref;
13874 input list<SimCode.FmiTerminal> terminals;
13875 output Option<String> name = NONE();
13876 protected
13877 String key;
13878 algorithm
13879 ✗ key := ComponentReference.crefStr(cref);
13880 ✗ for t in terminals loop
13881 ✗ for m in t.members loop
13882 ✗ if stringEq(ComponentReference.crefStr(m.variable), key) then
13883 ✗ name := SOME(t.name);
13884 ✗ return;
13885 end if;
13886 end for;
13887 end for;
13888 end crefTerminalName;
13889
13890 protected function figureArgs
13891 "Maps a record-constructor call's arguments to (fieldName, exp) pairs; positional
13892 args by declared field order, named args by name."
13893 input Absyn.Exp exp;
13894 input list<String> fieldNames;
13895 output list<tuple<String, Absyn.Exp>> args = {};
13896 protected
13897 list<Absyn.Exp> pos;
13898 list<Absyn.NamedArg> named;
13899 list<String> names = fieldNames;
13900 String name;
13901 algorithm
13902 () := match exp
13903 case Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(args = pos, argNames = named))
13904 algorithm
13905 ✗ for e in pos loop
13906 ✗ name :: names := names;
13907 ✗ args := (name, e) :: args;
13908 end for;
13909 ✗ for na in named loop
13910 ✗ args := (na.argName, na.argValue) :: args;
13911 end for;
13912 then ();
13913 else ();
13914 end match;
13915 end figureArgs;
13916
13917 protected function figureArgExp
13918 input list<tuple<String, Absyn.Exp>> args;
13919 input String name;
13920 output Option<Absyn.Exp> oexp = NONE();
13921 protected
13922 String n;
13923 Absyn.Exp e;
13924 algorithm
13925 ✗ for a in args loop
13926 ✗ (n, e) := a;
13927 ✗ if n == name then
13928 oexp := SOME(e);
13929 ✗ return;
13930 end if;
13931 end for;
13932 end figureArgExp;
13933
13934 protected function figureStrArg
13935 input list<tuple<String, Absyn.Exp>> args;
13936 input String name;
13937 output String value;
13938 algorithm
13939 value := match figureArgExp(args, name)
13940 local String s;
13941 case SOME(Absyn.STRING(value = s)) then s;
13942 else "";
13943 end match;
13944 end figureStrArg;
13945
13946 protected function figureBoolFlag
13947 input list<tuple<String, Absyn.Exp>> args;
13948 input String name;
13949 output Boolean value;
13950 algorithm
13951 value := match figureArgExp(args, name)
13952 local Boolean b;
13953 case SOME(Absyn.BOOL(value = b)) then b;
13954 else false;
13955 end match;
13956 end figureBoolFlag;
13957
13958 protected function figureBoundArg
13959 "An axis bound: NONE() when absent (auto), SOME when explicitly set."
13960 input list<tuple<String, Absyn.Exp>> args;
13961 input String name;
13962 output Option<Real> value;
13963 algorithm
13964 value := match figureArgExp(args, name)
13965 local Absyn.Exp e;
13966 ✗ case SOME(e) then SOME(figureExpReal(e));
13967 else NONE();
13968 end match;
13969 end figureBoundArg;
13970
13971 protected function figureExpReal
13972 input Absyn.Exp exp;
13973 output Real value;
13974 algorithm
13975 value := match exp
13976 local Integer i; String s;
13977 ✗ case Absyn.INTEGER(value = i) then intReal(i);
13978 ✗ case Absyn.REAL(value = s) then stringReal(s);
13979 ✗ case Absyn.UNARY(op = Absyn.UMINUS()) then -figureExpReal(exp.exp);
13980 else 0.0;
13981 end match;
13982 end figureExpReal;
13983
13984 protected function figureScaleIsLog
13985 "Whether an axis scale argument denotes the logarithmic scale (Scale.Log)."
13986 input Option<Absyn.Exp> oexp;
13987 output Boolean isLog;
13988 algorithm
13989 isLog := match oexp
13990 local Absyn.ComponentRef cr;
13991 ✗ case SOME(Absyn.CALL(function_ = cr)) then stringEq(AbsynUtil.crefIdent(cr), "Log");
13992 ✗ case SOME(Absyn.CREF(componentRef = cr)) then stringEq(AbsynUtil.crefIdent(cr), "Log");
13993 else false;
13994 end match;
13995 end figureScaleIsLog;
13996
13997 protected function getValueReferenceMapping2
13998 input list<SimCodeVar.SimVar> vars;
13999 input output Integer i;
14000 input output AvlTreeCRToInt.Tree tree;
14001 algorithm
14002
2/2
✓ Branch 0 taken 10046 times.
✓ Branch 1 taken 1456 times.
11502 for v in vars loop
14003 10046 tree := AvlTreeCRToInt.add(tree, v.name, i);
14004 // advance by the number of scalar elements so array variables occupy a
14005 // contiguous block of value references (getNumElems = 1 for scalars).
14006 10046 i := i + SimCodeUtilShared.getNumElems(v);
14007 end for;
14008 end getValueReferenceMapping2;
14009
14010 function getResources
14011 input list<Absyn.Class> classes;
14012 input BackendDAE.BackendDAE dlow1, dlow2;
14013 output list<String> resources;
14014 protected
14015 AvlSetString.Tree tree;
14016 list<DAE.Function> fns;
14017 Mutable<Boolean> unknownUri;
14018 partial function Func
14019 input output DAE.Exp e;
14020 input output AvlSetString.Tree tree;
14021 end Func;
14022 Func f1, f2;
14023 String file;
14024 algorithm
14025 86 fns := DAEUtil.getFunctionList(dlow1.shared.functionTree);
14026 86 tree := AvlSetString.EMPTY();
14027 86 unknownUri := Mutable.create(false);
14028 86 f1 := function findResources(unknownUri=unknownUri);
14029 86 f2 := function Expression.traverseSubexpressions(func=f1);
14030 86 (_,tree) := DAEUtil.traverseDAEFunctions(fns, f2, tree);
14031 86 tree := BackendDAEUtil.traverseBackendDAEExpsNoCopyWithUpdate(dlow1, f2, tree);
14032 86 tree := BackendDAEUtil.traverseBackendDAEExpsNoCopyWithUpdate(dlow2, f2, tree);
14033 86 resources := AvlSetString.listKeys(tree);
14034
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
86 if Mutable.access(unknownUri) then
14035 ✗ for cl in classes loop
14036 ✗ file := cl.info.fileName;
14037 ✗ if System.basename(file)=="package.mo" then
14038 ✗ resources:=System.dirname(file)::resources;
14039 end if;
14040 end for;
14041 end if;
14042 end getResources;
14043
14044 function findResources
14045 "Finds all literal expressions in the DAE"
14046 input output DAE.Exp e;
14047 input output AvlSetString.Tree tree;
14048 input Mutable<Boolean> unknownUri;
14049 protected
14050 String f;
14051 DAE.Exp e1;
14052 algorithm
14053 tree := match e
14054 ✗ case DAE.CALL(path=Absyn.IDENT("OpenModelica_fmuLoadResource"), expLst={DAE.SCONST(f)}) then AvlSetString.add(tree, f);
14055 case DAE.CALL(path=Absyn.IDENT("OpenModelica_uriToFilename"), expLst=e1::_)
14056 algorithm
14057 ✗ Error.addMessage(Error.FMI_URI_RESOLVE, {ExpressionBasics.printExpStr(e1)});
14058 ✗ Mutable.update(unknownUri, true);
14059 then tree;
14060 else tree;
14061 end match;
14062 end findResources;
14063
14064 function aliasSimEqSystems
14065 input output list<list<SimCode.SimEqSystem>> eqs;
14066 input output HashTableSimCodeEqCache.HashTable cache;
14067 algorithm
14068 2028 (eqs, cache) := List.mapFold(eqs, aliasSimEqs, cache);
14069 end aliasSimEqSystems;
14070
14071 function aliasSimEqs
14072 input output list<SimCode.SimEqSystem> eqs;
14073 input output HashTableSimCodeEqCache.HashTable cache;
14074 algorithm
14075 9439 (eqs, cache) := List.mapFold(eqs, aliasSimEq, cache);
14076 end aliasSimEqs;
14077
14078 function aliasSimEq
14079 input output SimCode.SimEqSystem eq;
14080 input output HashTableSimCodeEqCache.HashTable cache;
14081 protected
14082 Integer ix, aliasOf;
14083 algorithm
14084 341062 ix := SimCodeCodegenUtil.simEqSystemIndex(eq);
14085
2/2
✓ Branch 1 taken 104552 times.
✓ Branch 2 taken 236510 times.
341062 if BaseHashTable.hasKey(eq,cache) then
14086 104552 aliasOf := BaseHashTable.get(eq,cache);
14087
2/2
✓ Branch 0 taken 66769 times.
✓ Branch 1 taken 37783 times.
104552 if aliasOf <> ix then
14088 66769 eq := SimCode.SES_ALIAS(ix, BaseHashTable.get(eq,cache));
14089 end if;
14090 104552 return;
14091 end if;
14092 if match eq
14093 case SimCode.SES_SIMPLE_ASSIGN() then true;
14094 case SimCode.SES_ARRAY_CALL_ASSIGN() then true;
14095 case SimCode.SES_ALGORITHM(statements={DAE.STMT_NORETCALL()}) then true;
14096 // TODO: Check if LS / NLS are equal and alias the whole systems?
14097 else false;
14098 end match then
14099 195599 cache := BaseHashTable.add((eq,ix), cache);
14100 end if;
14101 end aliasSimEq;
14102
14103 public function generateRunnerBatScript
14104 "Always succeeds in order to clean-up external objects.
14105
14106 This function will generate a .bat file that can be used to launch the simulation
14107 executable on Windows. The bat file will set the necessary PATHs and then launches
14108 the executable."
14109 input SimCode.SimCode code;
14110 output String fileName;
14111 protected
14112 File.File file = File.File();
14113 algorithm
14114 fileName := matchcontinue code
14115 local
14116 String str, omdevPath, msysPath, mingwDir, installDir;
14117 Boolean isMSVC;
14118 list<String> locations_lst;
14119 case SimCode.SIMCODE()
14120 algorithm
14121 ✗ fileName := code.fileNamePrefix + ".bat";
14122 ✗ File.open(file, fileName, File.Mode.Write);
14123
14124 ✗ (locations_lst, _) := getDirectoriesForDLLsFromLinkLibs(code.makefileParams.libs);
14125
14126 ✗ installDir := Settings.getInstallationDirectoryPath();
14127 ✗ locations_lst := (installDir + "/bin") :: locations_lst;
14128 ✗ locations_lst := (installDir + "/lib/" + Config.targetTriple() + "/omc") :: locations_lst;
14129
14130 ✗ omdevPath := Util.makeValueOrDefault(System.readEnv, "OMDEV", Settings.getInstallationDirectoryPath());
14131 ✗ msysPath := omdevPath + "/tools/msys";
14132 ✗ mingwDir := System.openModelicaPlatform();
14133 ✗ isMSVC := 0 == System.stringFind(mingwDir, "msvc");
14134 ✗ if not isMSVC then
14135 ✗ locations_lst := (msysPath + "/" + mingwDir + "/bin") :: locations_lst;
14136 ✗ locations_lst := (msysPath + "/" + mingwDir + "/lib/gcc/" + System.gccDumpMachine() + "/" + System.gccVersion()) :: locations_lst;
14137 ✗ locations_lst := msysPath + "/usr/bin" :: locations_lst;
14138 end if;
14139
14140 ✗ locations_lst := listReverse(locations_lst);
14141
14142 ✗ str := "@echo off\n"
14143 + "setlocal\n"
14144 + "SET PATH=" + stringDelimitList(locations_lst, ";") + ";%PATH%\n"
14145 + "SET ERRORLEVEL=\n"
14146 + "CALL \"%CD%/" + code.fileNamePrefix + ".exe\" %*\n"
14147 + "SET RESULT=%ERRORLEVEL%\n"
14148 // One line, so %RESULT% is expanded before endlocal discards it.
14149 + "endlocal & EXIT /b %RESULT%\n";
14150 ✗ File.write(file, str);
14151 then fileName;
14152 else
14153 algorithm
14154 ✗ Error.addInternalError("SimCodeMain.generateRunnerBatScript failed", sourceInfo());
14155 then "";
14156 end matchcontinue;
14157 end generateRunnerBatScript;
14158
14159 function getDirectoriesForDLLsFromLinkLibs
14160 " Parse the makefileParams.libs and extract the necessary directories
14161 to be added to the PATH for finding dependenncy libraries (DLLs on Windows).
14162 NOTE: this function expects the 'link command' as the second argument. This will
14163 look something like
14164 {\"-LC:/Users/username/AppData/Roaming/.openmodelica/libraries/Buildings/Resources/Library/win64\",
14165 \"-LC:/Users/username/AppData/Roaming/.openmodelica/libraries/Buildings/Resources/Library\",
14166 ...}
14167 The function will check for strings that start with \"-L (or /LIBPATH:\" for the msvc
14168 target) and then trims it to get the corrseponding directory. Libraries are -lname
14169 (or name.lib for msvc).
14170
14171 If you want something more general write another function and generalize this.
14172 We can also fix the creation of MakefileParams to separately list out these directories
14173 (We do have MakefileParams.libDirs which seems to be empty).
14174 "
14175 input list<String> libsAndLinkDirs;
14176 output list<String> outLocations = {};
14177 output list<String> outLibs = {};
14178 algorithm
14179
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 82 times.
122 for str in libsAndLinkDirs loop
14180 /* fix issue https://github.com/OpenModelica/OpenModelica/issues/15714
14181 * strip exactly the first 2 characters (e.g) -lexternalfuncl to externalfuncl and "-LC:/FmuWithStaticLibEndsWithL" to C:/FmuWithStaticLibEndsWithL
14182 */
14183
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 24 times.
40 if StringUtil.startsWith(str, "\"-L") then
14184 16 outLocations := listAppend({substring(str, 4, stringLength(str)-1)}, outLocations);
14185 // The msvc target spells the same directories /LIBPATH:"dir", see SimCodeFunctionUtil.
14186 elseif StringUtil.startsWith(str, "/LIBPATH:\"") then
14187 ✗ outLocations := listAppend({substring(str, 11, stringLength(str)-1)}, outLocations);
14188 elseif StringUtil.startsWith(str, "-l") then
14189 8 outLibs := listAppend({substring(str, 3, stringLength(str))}, outLibs);
14190 // ... and a library name as name.lib; a path to a library file is passed as it is.
14191 elseif StringUtil.endsWith(str, ".lib") and System.stringFind(str, "/") < 0 and System.stringFind(str, "\\") < 0 then
14192 ✗ outLibs := listAppend({substring(str, 1, stringLength(str)-4)}, outLibs);
14193 end if;
14194 end for;
14195 82 outLocations := listReverse(outLocations);
14196 82 outLibs := listReverse(outLibs);
14197 end getDirectoriesForDLLsFromLinkLibs;
14198
14199 public function getCmakeCrossPlatformSuffixes
14200 "Generate CMAKE_FIND_LIBRARY suffix for different platform"
14201 output String cmakeCode;
14202 algorithm
14203 cmakeCode := "\n# Cross-Platform CMAKE_FIND_LIBRARY_SUFFIXES\n"
14204 + "if(WIN32)\n"
14205 + " set(CMAKE_FIND_LIBRARY_SUFFIXES \".lib\" \".dll\" \".a\")\n"
14206 + "elseif(APPLE)\n"
14207 + " set(CMAKE_FIND_LIBRARY_SUFFIXES \".dylib\" \".a\")\n"
14208 + "else()\n"
14209 + " set(CMAKE_FIND_LIBRARY_SUFFIXES \".so\" \".a\")\n"
14210 + "endif()\n";
14211 end getCmakeCrossPlatformSuffixes;
14212
14213 public function getCmakeLinkLibrariesCode
14214 "Generate CMake code to find and link all input libraries."
14215 input list<String> libs;
14216 output String needModelicaExternalC = "OFF";
14217 output String cmakeCode = "";
14218 protected
14219 list<String> locations;
14220 list<String> libraries;
14221 function addDockerVol
14222 input String istring;
14223 output String ostring = "\"${DOCKER_VOL_DIR}"+istring+"\"";
14224 end addDockerVol;
14225 algorithm
14226 // HDF5 is there for ModelicaMatIO, which the FMU compiles from source without it.
14227 82 (locations, libraries) := getDirectoriesForDLLsFromLinkLibs(
14228 List.removeOnTrue(Autoconf.hdf5Libs, stringEqual, libs));
14229 82 locations := listAppend({Settings.getInstallationDirectoryPath() + "/lib/${CMAKE_LIBRARY_ARCHITECTURE}/omc"}, locations); // zlib
14230 82 locations := listAppend({Settings.getInstallationDirectoryPath() + "/bin"}, locations); // pthread located in OpenModelica/bin/ on Windows
14231 82 locations := List.map(locations, addDockerVol);
14232 // Use target_link_directories when CMake 3.13 is available and skip the find_library part
14233 82 cmakeCode := cmakeCode + "set(EXTERNAL_LIBDIRECTORIES " + stringDelimitList(locations, "\n ") + ")\n";
14234 /* The directories above were resolved for the platform omc is running on. When
14235 * cross compiling add the Resources/Library sub directories of the target platform.
14236 */
14237 82 cmakeCode := cmakeCode + "om_add_target_library_directories(EXTERNAL_LIBDIRECTORIES)\n";
14238 /* fix issue https://github.com/OpenModelica/OpenModelica/issues/12640
14239 * in windows cmake does not find .dll suffixes using find_library(), the default is ".lib" & ".a" we need to explicitly
14240 * specify to look for ".dll" suffix
14241 */
14242 82 cmakeCode := cmakeCode + getCmakeCrossPlatformSuffixes() + "\n";
14243
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 82 times.
90 for lib in libraries loop
14244 // Special handling for ModelicaExternalC, we always copy the sources into the FMU
14245
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
8 if List.contains({"ModelicaStandardTables", "ModelicaIO", "ModelicaMatIO"}, lib, stringEqual) then
14246 needModelicaExternalC := "ON";
14247 // zlib is referred to from MSL Tables, but by default not used by ModelicaMatIO
14248 elseif lib == "zlib" then
14249 2 cmakeCode := cmakeCode + "find_library(" + lib + "\n" +
14250 " NAMES " + lib + "\n" +
14251 " PATHS ${EXTERNAL_LIBDIRECTORIES} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)\n" +
14252 "if(NOT " + lib + ")\n" +
14253 " message(WARNING \"Could not find library zlib\")" + "\n" +
14254 " message(STATUS \"zlib is referred by ModelicaMatIO, but not used by default. Try compiling without linking.\")" + "\n" +
14255 "else()\n" +
14256 " message(STATUS \"Linking ${" + lib + "}\")" + "\n" +
14257 " target_link_libraries(${FMU_NAME_HASH} PRIVATE ${" + lib + "})" + "\n" +
14258 " list(APPEND RUNTIME_DEPENDS ${" + lib + "})" + "\n" +
14259 "endif()\n";
14260 else
14261 1 cmakeCode := cmakeCode + "find_library(" + lib + "\n" +
14262 " NAMES " + lib + "\n" +
14263 " PATHS ${EXTERNAL_LIBDIRECTORIES} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)\n" +
14264 "if(NOT " + lib + ")\n" +
14265 " message(FATAL_ERROR \"Could not find library " + lib + "\")\n" +
14266 "endif()\n" +
14267 "message(STATUS \"Linking ${" + lib + "}\")\n" +
14268 "target_link_libraries(${FMU_NAME_HASH} PRIVATE ${" + lib + "})\n" +
14269 "list(APPEND RUNTIME_DEPENDS ${" + lib + "})\n";
14270 end if;
14271 end for;
14272 end getCmakeLinkLibrariesCode;
14273
14274 public function getCmakeSundialsLinkCode
14275 "Code for FMU CMakeLists.txt to specify if CVODE is needed."
14276 input Option<SimCode.FmiSimulationFlags> fmiSimulationFlags;
14277 output String needCvode = "OFF";
14278 output String cvodeDirectory = "\"\"";
14279 algorithm
14280 ✗ if cvodeFmiFlagIsSet(fmiSimulationFlags) then
14281 needCvode := "ON";
14282 // ${DOCKER_VOL_DIR} so the path also resolves inside the container when cross compiling,
14283 // see getCmakeLinkLibrariesCode. It is empty for a normal build.
14284 ✗ cvodeDirectory := "\"${DOCKER_VOL_DIR}" + Settings.getInstallationDirectoryPath() + "/lib/${CMAKE_LIBRARY_ARCHITECTURE}/omc\"";
14285 end if;
14286 end getCmakeSundialsLinkCode;
14287
14288 public function cvodeFmiFlagIsSet
14289 "Checks if s:cvode is part of FMI_FLAGS.
14290 If a *.json exists we don't check and assume cvode will be needed at some point."
14291 input Option<SimCode.FmiSimulationFlags> fmiSimulationFlags;
14292 output Boolean needsCvode = false;
14293 algorithm
14294 () := match fmiSimulationFlags
14295 local
14296 list<tuple<String,String>> nameValueTuples;
14297 String setting, value;
14298 String configFile;
14299 String fileContent;
14300 case SOME(SimCode.FMI_SIMULATION_FLAGS(nameValueTuples))
14301 algorithm
14302
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if not listEmpty(nameValueTuples) then
14303
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 for tpl in nameValueTuples loop
14304 6 (setting, value) := tpl;
14305
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
6 if stringEqual(setting, "s") and stringEqual(value, "cvode") then
14306 needsCvode := true;
14307 break;
14308 end if;
14309 end for;
14310 end if;
14311 then();
14312 case SOME(SimCode.FMI_SIMULATION_FLAGS_FILE(configFile))
14313 algorithm
14314 ✗ fileContent := System.readFile(configFile);
14315 ✗ if not -1 == System.stringFind(fileContent, "\"cvode\"") then
14316 needsCvode := true;
14317 end if;
14318 then();
14319 else then();
14320 end match;
14321 end cvodeFmiFlagIsSet;
14322
14323 public function stripIncludeFlag
14324 "Directory of a makefileParams include entry, which is of the form \"-I<directory>\",
14325 quotes included. Strips exactly the first 3 characters and the trailing quote, e.g.
14326 \"-IC:/FmuWithStaticLibEndsWithI\" to C:/FmuWithStaticLibEndsWithI."
14327 input String include;
14328 output String directory = substring(include, 4, stringLength(include)-1);
14329 end stripIncludeFlag;
14330
14331 public function make2CMakeInclude
14332 "Convert makefile include directories to CMake include directories"
14333 input list<String> includes;
14334 output String cmakeCode = "";
14335 algorithm
14336
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 82 times.
83 for include in includes loop
14337 1 cmakeCode := cmakeCode + "\n " +
14338 "\"${DOCKER_VOL_DIR}" + stripIncludeFlag(include) + "\"";
14339 end for;
14340 end make2CMakeInclude;
14341
14342 public function msvcEnvironment
14343 "The cmd prefix that enters the Visual Studio environment for the msvc
14344 target, where the build tools and its cmake are not on the PATH. Empty for
14345 other targets."
14346 output String prefix = "";
14347 algorithm
14348 if Autoconf.os == "Windows_NT" and StringUtil.startsWith(Config.simulationCodeTarget(), "msvc") then
14349 prefix := "call \"" + System.stringReplace(Settings.getInstallationDirectoryPath() + "/share/omc/scripts/msvc_env.bat", "/", "\\") + "\" && ";
14350 end if;
14351 end msvcEnvironment;
14352
14353 public function getCMakeVersion
14354 "Get CMake version"
14355 input String pathToCMake = Autoconf.cmake;
14356 output SemanticVersion.Version cmakeVersion;
14357 protected
14358 Integer retVal;
14359 String cmakeVersionLogFile = "systemCall_cmakeVersion.log";
14360 list<String> regexOut;
14361 Integer numMatches;
14362 String cmakeVersionString;
14363 algorithm
14364 82 retVal := System.systemCallRestrictedEnv(msvcEnvironment() + pathToCMake + " --version", cmakeVersionLogFile);
14365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if 0 <> retVal then
14366 ✗ Error.addInternalError("Failed to get version from " + pathToCMake + ": " + System.readFile(cmakeVersionLogFile), sourceInfo());
14367 ✗ System.removeFile(cmakeVersionLogFile);
14368 ✗ fail();
14369 end if;
14370 // Regex magic to read major.minor.patch version from cmake --version
14371 // regex \d doesn't work on Linux, using [0-9] instead
14372 82 (numMatches, regexOut) := System.regex(
14373 System.trimWhitespace(System.readFile(cmakeVersionLogFile)),
14374 "[0-9]+\\.[0-9]+\\.[0-9]+",
14375 maxMatches=1,
14376 extended=true
14377 );
14378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if numMatches == 0 then
14379 ✗ System.removeFile(cmakeVersionLogFile);
14380 ✗ Error.addInternalError("Failed to read semantic version from " + pathToCMake, sourceInfo());
14381 ✗ fail();
14382 end if;
14383 82 cmakeVersionString := listHead(regexOut);
14384 82 cmakeVersion := SemanticVersion.parse(cmakeVersionString);
14385 82 System.removeFile(cmakeVersionLogFile);
14386 end getCMakeVersion;
14387
14388 annotation(__OpenModelica_Interface="backend");
14389 end SimCodeUtil;
14390