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