OMCompiler/Compiler/NBackEnd/Modules/2_Pre/NBDetectStates.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 NBDetectStates | ||
| 37 | " file: NBDetectStates.mo | ||
| 38 | package: NBDetectStates | ||
| 39 | description: This file contains all functions for the detection of continuous | ||
| 40 | and discrete state variables. | ||
| 41 | " | ||
| 42 | |||
| 43 | public | ||
| 44 | import Module = NBModule; | ||
| 45 | |||
| 46 | protected | ||
| 47 | // Old Frontend Imports | ||
| 48 | import Absyn; | ||
| 49 | |||
| 50 | // New Frontend Imports | ||
| 51 | import Call = NFCall; | ||
| 52 | import ComponentRef = NFComponentRef; | ||
| 53 | import Expression = NFExpression; | ||
| 54 | import Function = NFFunction; | ||
| 55 | import InstNode = NFInstNode.InstNode; | ||
| 56 | import SimplifyExp = NFSimplifyExp; | ||
| 57 | import Type = NFType; | ||
| 58 | import Operator = NFOperator; | ||
| 59 | import Variable = NFVariable; | ||
| 60 | import NFBackendExtension.{StateSelect, VariableKind}; | ||
| 61 | |||
| 62 | // Backend imports | ||
| 63 | import BackendDAE = NBackendDAE; | ||
| 64 | import BEquation = NBEquation; | ||
| 65 | import BVariable = NBVariable; | ||
| 66 | import Differentiate = NBDifferentiate; | ||
| 67 | import NBEquation.{Equation, EquationPointers, EqData, EquationAttributes, EquationKind, Iterator, WhenEquationBody, WhenStatement, IfEquationBody}; | ||
| 68 | import FunctionAlias = NBFunctionAlias; | ||
| 69 | import BPartition = NBPartition; | ||
| 70 | import NBVariable.{VariablePointers, VarData}; | ||
| 71 | |||
| 72 | // Util | ||
| 73 | import StringUtil; | ||
| 74 | |||
| 75 | // ========================================================================= | ||
| 76 | // MAIN ROUTINE, PLEASE DO NOT CHANGE | ||
| 77 | // ========================================================================= | ||
| 78 | public | ||
| 79 | function main | ||
| 80 | "Wrapper function for any detect states function. This will be | ||
| 81 | called during simulation and gets the corresponding subfunction from | ||
| 82 | Config." | ||
| 83 | extends Module.wrapper; | ||
| 84 | protected | ||
| 85 | Module.detectStatesInterface mainFunc; | ||
| 86 | Module.detectContinuousStatesInterface contFunc; | ||
| 87 | Module.detectDiscreteStatesInterface discFunc; | ||
| 88 | algorithm | ||
| 89 | 190 | (mainFunc, contFunc, discFunc) := getModule(); | |
| 90 | |||
| 91 | bdae := match bdae | ||
| 92 | local | ||
| 93 | VarData varData "Data containing variable pointers"; | ||
| 94 | EqData eqData "Data containing equation pointers"; | ||
| 95 | case BackendDAE.MAIN(varData = varData, eqData = eqData) | ||
| 96 | algorithm | ||
| 97 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
|
190 | (varData, eqData) := mainFunc(varData, eqData, contFunc, discFunc); |
| 98 | 190 | bdae.varData := varData; | |
| 99 | 190 | bdae.eqData := eqData; | |
| 100 | then bdae; | ||
| 101 | |||
| 102 | else algorithm | ||
| 103 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."}); | |
| 104 | ✗ | then fail(); | |
| 105 | end match; | ||
| 106 | end main; | ||
| 107 | |||
| 108 | function getModule | ||
| 109 | "Returns the module function that was chosen by the user." | ||
| 110 | output Module.detectStatesInterface mainFunc; | ||
| 111 | output Module.detectContinuousStatesInterface contFunc; | ||
| 112 | output Module.detectDiscreteStatesInterface discFunc; | ||
| 113 | protected | ||
| 114 | String flag = "default"; //Flags.getConfigString(Flags.DETECT_STATES) | ||
| 115 | algorithm | ||
| 116 | (mainFunc, contFunc, discFunc) := match flag | ||
| 117 | case "default" then (detectStatesDefault, detectContinuousStatesDefault, detectDiscreteStatesDefault); | ||
| 118 | /* ... New detect states modules have to be added here */ | ||
| 119 | else fail(); | ||
| 120 | end match; | ||
| 121 | end getModule; | ||
| 122 | |||
| 123 | /* ========================================================================= | ||
| 124 | SUB ROUTINES | ||
| 125 | ========================================================================= */ | ||
| 126 | protected | ||
| 127 | function detectStatesDefault extends Module.detectStatesInterface; | ||
| 128 | protected | ||
| 129 | VariablePointers variables "All variables"; | ||
| 130 | EquationPointers equations "System equations"; | ||
| 131 | EquationPointers disc_eqns "Discrete equations"; | ||
| 132 | EquationPointers init_eqns "Initial equations"; | ||
| 133 | EquationPointers removed_eqns "Removed equations"; | ||
| 134 | VariablePointers unknowns "Unknowns"; | ||
| 135 | VariablePointers knowns "Knowns"; | ||
| 136 | VariablePointers initials "Initial unknowns"; | ||
| 137 | VariablePointers states "States"; | ||
| 138 | VariablePointers derivatives "State derivatives (der(x) -> $DER.x)"; | ||
| 139 | VariablePointers algebraics "Algebraic variables"; | ||
| 140 | VariablePointers discretes "Discrete variables"; | ||
| 141 | VariablePointers discrete_states"Discrete state variables"; | ||
| 142 | VariablePointers clocked_states "Clocked state variables"; | ||
| 143 | VariablePointers previous "Previous discrete variables (pre(d) -> $PRE.d)"; | ||
| 144 | list<Pointer<Equation>> aux_eqns; | ||
| 145 | EqData newEqData; | ||
| 146 | algorithm | ||
| 147 | // introduce sliced state alias before resolving the der() calls | ||
| 148 | 190 | (varData, eqData) := FunctionAlias.introduceSlicedStateAlias(varData, eqData, NBPartition.Kind.ODE); | |
| 149 | |||
| 150 | (varData, eqData) := match (varData, eqData) | ||
| 151 | case (BVariable.VAR_DATA_SIM(), BEquation.EQ_DATA_SIM()) algorithm | ||
| 152 | |||
| 153 | // collect continuous states from all equations | ||
| 154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
|
190 | (variables, unknowns, knowns, initials, states, derivatives, algebraics, aux_eqns) |
| 155 | := continuousFunc(varData.variables, varData.unknowns, varData.knowns, varData.initials, varData.states, varData.derivatives, varData.algebraics, eqData.equations); | ||
| 156 | |||
| 157 | // collect discrete states from discrete equations | ||
| 158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
|
190 | (variables, disc_eqns, knowns, initials, discretes, discrete_states, clocked_states, previous) |
| 159 | := discreteFunc(varData.variables, eqData.discretes, varData.knowns, varData.initials, varData.discretes, varData.discrete_states, varData.clocked_states, varData.previous, "discrete equations"); | ||
| 160 | |||
| 161 | // collect clocked states from clocked equations | ||
| 162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
|
190 | (variables, disc_eqns, knowns, initials, discretes, discrete_states, clocked_states, previous) |
| 163 | := discreteFunc(variables, eqData.clocked, knowns, initials, discretes, discrete_states, clocked_states, previous, "clocked equations"); | ||
| 164 | |||
| 165 | // collect clocked states from continuous equations | ||
| 166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
|
190 | (variables, disc_eqns, knowns, initials, discretes, discrete_states, clocked_states, previous) |
| 167 | := discreteFunc(variables, eqData.continuous, knowns, initials, discretes, discrete_states, clocked_states, previous, "continuous equations"); | ||
| 168 | |||
| 169 | // collect discrete states from initial equations | ||
| 170 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
|
190 | (variables, init_eqns, knowns, initials, discretes, discrete_states, clocked_states, previous) |
| 171 | := discreteFunc(variables, eqData.initials, knowns, initials, discretes, discrete_states, clocked_states, previous, "initial equations"); | ||
| 172 | |||
| 173 | // collect pre, edge and change from the removed equations, e.g. when equations that only have reinit | ||
| 174 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
|
190 | (variables, removed_eqns, knowns, initials, discretes, discrete_states, clocked_states, previous) |
| 175 | := discreteFunc(variables, eqData.removed, knowns, initials, discretes, discrete_states, clocked_states, previous, "removed equations"); | ||
| 176 | |||
| 177 | // update variable arrays | ||
| 178 | 190 | varData.variables := variables; | |
| 179 | 190 | varData.unknowns := unknowns; | |
| 180 | 190 | varData.knowns := knowns; | |
| 181 | 190 | varData.initials := initials; | |
| 182 | 190 | varData.derivatives := derivatives; | |
| 183 | 190 | varData.algebraics := algebraics; | |
| 184 | 190 | varData.discretes := discretes; | |
| 185 | 190 | varData.discrete_states := discrete_states; | |
| 186 | 190 | varData.clocked_states := clocked_states; | |
| 187 | 190 | varData.previous := previous; | |
| 188 | 190 | varData.states := states; | |
| 189 | |||
| 190 | // update equation arrays | ||
| 191 | 190 | newEqData := EqData.addTypedList(eqData, aux_eqns, EqData.EqType.CONTINUOUS, false); | |
| 192 | |||
| 193 | // detect state order | ||
| 194 | 190 | EquationPointers.map(EqData.getEquations(newEqData), function stateOrder(state_order = varData.state_order)); | |
| 195 |
4/4✓ Branch 1 taken 5 times.
✓ Branch 2 taken 185 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
|
190 | if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) and not UnorderedMap.isEmpty(varData.state_order) then |
| 196 | 3 | print(StringUtil.headline_4("[stateselection] State Order:")); | |
| 197 | 3 | print("\t" + UnorderedMap.toString(varData.state_order, ComponentRef.toString, ComponentRef.toString, "\n\t", " --d/dt--> ") + "\n\n"); | |
| 198 | end if; | ||
| 199 | then (varData, newEqData); | ||
| 200 | else (varData, eqData); | ||
| 201 | end match; | ||
| 202 | end detectStatesDefault; | ||
| 203 | |||
| 204 | function detectContinuousStatesDefault extends Module.detectContinuousStatesInterface; | ||
| 205 | protected | ||
| 206 | Pointer<list<Pointer<Variable>>> acc_states = Pointer.create({}); | ||
| 207 | Pointer<list<Pointer<Variable>>> acc_derivatives = Pointer.create({}); | ||
| 208 | Pointer<list<Pointer<Equation>>> acc_aux_equations = Pointer.create({}); | ||
| 209 | Pointer<Integer> uniqueIndex = Pointer.create(0); | ||
| 210 | Differentiate.DifferentiationArguments diffArgs = Differentiate.DifferentiationArguments.default(); | ||
| 211 | algorithm | ||
| 212 | // collect all 'natural' states der(x) | ||
| 213 | 190 | EquationPointers.mapExp(equations, function collectStatesAndDerivatives(acc_states = acc_states, acc_derivatives = acc_derivatives, scalarized = variables.scalarized)); | |
| 214 | // resolve all general der(exp) expressions | ||
| 215 | 190 | EquationPointers.mapExp(equations, function resolveGeneralDer(acc_states = acc_states, acc_derivatives = acc_derivatives, acc_aux_equations = acc_aux_equations, uniqueIndex = uniqueIndex, diffArgs = diffArgs)); | |
| 216 | // move stuff to their correct arrays | ||
| 217 | 190 | (variables, unknowns, knowns, initials, states, derivatives, algebraics) := updateStatesAndDerivatives(variables, unknowns, knowns, initials, states, derivatives, algebraics, Pointer.access(acc_states), Pointer.access(acc_derivatives)); | |
| 218 | |||
| 219 | // promote StateSelect.prefer variables if their derivative already exists | ||
| 220 | 190 | (variables, unknowns, knowns, initials, states, derivatives, algebraics) := promotePreferStates(variables, unknowns, knowns, initials, states, derivatives, algebraics); | |
| 221 | |||
| 222 | 190 | aux_eqns := Pointer.access(acc_aux_equations); | |
| 223 |
4/4✓ Branch 1 taken 185 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 time.
|
190 | if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) and not listEmpty(aux_eqns) then |
| 224 | 1 | print(StringUtil.headline_4("[stateselection] (" + intString(listLength(aux_eqns)) + ") Created auxiliary equations:")); | |
| 225 | 1 | print(List.toString(aux_eqns, function Equation.pointerToString(str=""), List.Style.NEWLINE_TAB) + "\n\n"); | |
| 226 | end if; | ||
| 227 | end detectContinuousStatesDefault; | ||
| 228 | |||
| 229 | function detectDiscreteStatesDefault extends Module.detectDiscreteStatesInterface; | ||
| 230 | protected | ||
| 231 | Pointer<list<Pointer<Variable>>> acc_discrete_states = Pointer.create({}); | ||
| 232 | Pointer<list<Pointer<Variable>>> acc_clocked_states = Pointer.create({}); | ||
| 233 | Pointer<list<Pointer<Variable>>> acc_previous = Pointer.create({}); | ||
| 234 | algorithm | ||
| 235 | // collect all states on the lhs of a when | ||
| 236 | 950 | EquationPointers.map(equations, function collectDiscreteStatesFromWhen(acc_discrete_states = acc_discrete_states, acc_previous = acc_previous, scalarized = variables.scalarized)); | |
| 237 | // collect all pre(d) | ||
| 238 | 950 | EquationPointers.mapExp(equations, function collectPreAndPrevious(acc_previous = acc_previous, acc_clocked_states = acc_clocked_states, scalarized = variables.scalarized)); | |
| 239 | // move stuff to their correct arrays | ||
| 240 | 950 | (variables, knowns, initials, discretes, discrete_states, clocked_states, previous) := updateDiscreteStatesAndPrevious(variables, knowns, initials, discretes, discrete_states, clocked_states, previous, Pointer.access(acc_discrete_states), Pointer.access(acc_clocked_states), Pointer.access(acc_previous), context); | |
| 241 | end detectDiscreteStatesDefault; | ||
| 242 | |||
| 243 | function collectStatesAndDerivatives | ||
| 244 | "Collects all states and creates a derivative variable for each." | ||
| 245 | input output Expression exp; | ||
| 246 | input Pointer<list<Pointer<Variable>>> acc_states; | ||
| 247 | input Pointer<list<Pointer<Variable>>> acc_derivatives; | ||
| 248 | input Boolean scalarized; | ||
| 249 | algorithm | ||
| 250 | exp := match exp | ||
| 251 | local | ||
| 252 | Expression res; | ||
| 253 | ComponentRef state_cref, der_cref; | ||
| 254 | Pointer<Variable> state_var, der_var; | ||
| 255 | |||
| 256 | // parse all der(x) calls where x is not a state derivative. those need to be handled by resolveGeneralDer() | ||
| 257 | case Expression.CALL(call = Call.TYPED_CALL(fn = Function.FUNCTION(path = Absyn.IDENT(name = "der")), | ||
| 258 | arguments = {Expression.CREF(cref = state_cref)})) guard(not BVariable.checkCref(state_cref, BVariable.isStateDerivative, sourceInfo())) | ||
| 259 | algorithm | ||
| 260 | 185 | state_var := BVariable.getVarPointer(state_cref, sourceInfo()); | |
| 261 | |||
| 262 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 180 times.
|
185 | if not BVariable.isContinuous(state_var, false) then |
| 263 | // if the variable is not continuous, its derivative is zero | ||
| 264 | 5 | res := Expression.makeZero(ComponentRef.getSubscriptedType(state_cref)); | |
| 265 | else | ||
| 266 |
2/2✓ Branch 1 taken 40 times.
✓ Branch 2 taken 140 times.
|
180 | if BVariable.hasDerVar(state_var) then |
| 267 | // this derivative was already created -> the variable should already have a pointer to its derivative | ||
| 268 | 40 | der_cref := BVariable.getPartnerCref(state_cref, BVariable.getVarDer, scalarized); | |
| 269 | else | ||
| 270 | // create new derivative variable | ||
| 271 | 140 | (der_cref, der_var) := BVariable.makeDerVar(state_cref, scalarized); | |
| 272 | 140 | state_var := BVariable.getVarPointer(state_cref, sourceInfo()); | |
| 273 | 140 | BVariable.setStateDerivativeVar(state_var, der_var); | |
| 274 | 280 | Pointer.update(acc_states, state_var :: Pointer.access(acc_states)); | |
| 275 | 140 | Pointer.update(acc_derivatives, der_var :: Pointer.access(acc_derivatives)); | |
| 276 | end if; | ||
| 277 | 180 | res := Expression.fromCref(der_cref); | |
| 278 | end if; | ||
| 279 | then res; | ||
| 280 | |||
| 281 | else exp; | ||
| 282 | end match; | ||
| 283 | end collectStatesAndDerivatives; | ||
| 284 | |||
| 285 | function resolveGeneralDer | ||
| 286 | "Collects all states and creates a derivative variable for each." | ||
| 287 | input output Expression exp; | ||
| 288 | input Pointer<list<Pointer<Variable>>> acc_states; | ||
| 289 | input Pointer<list<Pointer<Variable>>> acc_derivatives; | ||
| 290 | input Pointer<list<Pointer<Equation>>> acc_aux_equations; | ||
| 291 | input Pointer<Integer> uniqueIndex; | ||
| 292 | input Differentiate.DifferentiationArguments diffArgs; | ||
| 293 | algorithm | ||
| 294 | exp := match exp | ||
| 295 | local | ||
| 296 | ComponentRef state_cref, der_cref; | ||
| 297 | Pointer<Variable> state_var, der_var; | ||
| 298 | Expression arg, returnExp; | ||
| 299 | Pointer<Equation> aux_equation; | ||
| 300 | Differentiate.DifferentiationArguments oDiffArgs; | ||
| 301 | |||
| 302 | case Expression.CALL(call = Call.TYPED_CALL(fn = Function.FUNCTION(path = Absyn.IDENT(name = "der")), arguments = {arg})) | ||
| 303 | algorithm | ||
| 304 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
|
6 | if Expression.fold(arg, checkAlgebraic, 0) > 1 then |
| 305 | // more than one algebraic variable > create auxiliary state | ||
| 306 | 3 | (state_var, state_cref, der_var, der_cref) := BVariable.makeAuxStateVar(Pointer.access(uniqueIndex), SOME(arg)); | |
| 307 | 3 | aux_equation := Equation.makeAssignment(Expression.fromCref(state_cref), arg, uniqueIndex, NBVariable.AUXILIARY_STR, Iterator.EMPTY(), EquationAttributes.default(EquationKind.CONTINUOUS, false)); | |
| 308 | 3 | returnExp := Expression.fromCref(der_cref); | |
| 309 | |||
| 310 | 6 | Pointer.update(acc_states, state_var :: Pointer.access(acc_states)); | |
| 311 | 3 | Pointer.update(acc_derivatives, der_var :: Pointer.access(acc_derivatives)); | |
| 312 | 6 | Pointer.update(acc_aux_equations, aux_equation :: Pointer.access(acc_aux_equations)); | |
| 313 | else | ||
| 314 | // one or less algebraic variables > differentiate the expression | ||
| 315 | 3 | (returnExp, oDiffArgs) := Differentiate.differentiateExpression(arg, diffArgs); | |
| 316 | 3 | returnExp := SimplifyExp.simplifyDump(returnExp, true, getInstanceName()); | |
| 317 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
|
3 | if List.hasOneElement(oDiffArgs.new_vars) then |
| 318 | 2 | der_var := listHead(oDiffArgs.new_vars); | |
| 319 | 2 | Pointer.update(acc_derivatives, der_var :: Pointer.access(acc_derivatives)); | |
| 320 | 4 | Pointer.update(acc_states, Util.getOption(BVariable.getVarState(der_var)) :: Pointer.access(acc_states)); | |
| 321 | elseif List.hasSeveralElements(oDiffArgs.new_vars) then | ||
| 322 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because the number of algebraic variables were miscounted! " + | |
| 323 | "Expected: 0 or 1, got: " + intString(listLength(oDiffArgs.new_vars))}); | ||
| 324 | ✗ | fail(); | |
| 325 | end if; | ||
| 326 | end if; | ||
| 327 | then returnExp; | ||
| 328 | |||
| 329 | else exp; | ||
| 330 | end match; | ||
| 331 | end resolveGeneralDer; | ||
| 332 | |||
| 333 | function checkAlgebraic | ||
| 334 | "Needs to be mapped with Expression.fold() | ||
| 335 | counts the number of algebraic variables in an expression. | ||
| 336 | Count state derivatives double to ensure that they get an auxiliary." | ||
| 337 | input Expression exp; | ||
| 338 | input output Integer i; | ||
| 339 | algorithm | ||
| 340 | i := match exp | ||
| 341 | 2 | case Expression.CREF() guard(BVariable.isStateDerivative(BVariable.getVarPointer(exp.cref, sourceInfo()))) then i + 2; | |
| 342 | 4 | case Expression.CREF() guard(BVariable.isAlgebraic(BVariable.getVarPointer(exp.cref, sourceInfo()))) then i + 1; | |
| 343 | else i; | ||
| 344 | end match; | ||
| 345 | end checkAlgebraic; | ||
| 346 | |||
| 347 | function updateStatesAndDerivatives | ||
| 348 | "Updates the variable pointer arrays with the new information about states and derivatives." | ||
| 349 | input output VariablePointers variables "All variables"; | ||
| 350 | input output VariablePointers unknowns "Unknowns"; | ||
| 351 | input output VariablePointers knowns "Knowns"; | ||
| 352 | input output VariablePointers initials "Initial unknowns"; | ||
| 353 | input output VariablePointers states "States"; | ||
| 354 | input output VariablePointers derivatives "State derivatives (der(x) -> $DER.x)"; | ||
| 355 | input output VariablePointers algebraics "Algebraic variables"; | ||
| 356 | input list<Pointer<Variable>> acc_states; | ||
| 357 | input list<Pointer<Variable>> acc_derivatives; | ||
| 358 | algorithm | ||
| 359 | // Add the new derivatives to variables, unknowns and derivative pointer arrays | ||
| 360 | 190 | variables := VariablePointers.addList(acc_derivatives, variables); | |
| 361 | 190 | unknowns := VariablePointers.addList(acc_derivatives, unknowns); | |
| 362 | 190 | initials := VariablePointers.addList(acc_derivatives, initials); | |
| 363 | 190 | derivatives := VariablePointers.addList(acc_derivatives, derivatives); | |
| 364 | |||
| 365 | // add states to variables and state pointer array | ||
| 366 | 190 | variables := VariablePointers.addList(acc_states, variables); | |
| 367 | 190 | states := VariablePointers.addList(acc_states, states); | |
| 368 | |||
| 369 | // remove states from unknowns and algebraics | ||
| 370 | 190 | unknowns := VariablePointers.removeList(acc_states, unknowns); | |
| 371 | 190 | algebraics := VariablePointers.removeList(acc_states, algebraics); | |
| 372 | |||
| 373 |
2/2✓ Branch 1 taken 185 times.
✓ Branch 2 taken 5 times.
|
190 | if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) then |
| 374 | 5 | print(StringUtil.headline_4("[stateselection] (" + intString(listLength(acc_states)) + ") Natural states before index reduction:")); | |
| 375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if listEmpty(acc_states) then |
| 376 | ✗ | print("\t<no states>\n\n"); | |
| 377 | else | ||
| 378 | 5 | print(List.toString(acc_states, BVariable.pointerToString, List.Style.NEWLINE_TAB) + "\n\n"); | |
| 379 | end if; | ||
| 380 | end if; | ||
| 381 | end updateStatesAndDerivatives; | ||
| 382 | |||
| 383 | function collectPreAndPrevious | ||
| 384 | "Collects all pre and previous variables. Only to be used on discrete equations!" | ||
| 385 | input output Expression exp; | ||
| 386 | input Pointer<list<Pointer<Variable>>> acc_previous; | ||
| 387 | input Pointer<list<Pointer<Variable>>> acc_clocked_states; | ||
| 388 | input Boolean scalarized; | ||
| 389 | algorithm | ||
| 390 | exp := match exp | ||
| 391 | local | ||
| 392 | Function.Function fn; | ||
| 393 | Boolean b; | ||
| 394 | list<Expression> args; | ||
| 395 | Expression new_exp, old_exp; | ||
| 396 | |||
| 397 | // the call has an input that is only a boolean. for pre() return the boolean, for edge() and change() always false | ||
| 398 | case Expression.CALL(call = Call.TYPED_CALL(fn = fn, arguments = {Expression.BOOLEAN(b)})) | ||
| 399 | algorithm | ||
| 400 | new_exp := match fn | ||
| 401 | ✗ | case Function.FUNCTION(path = Absyn.IDENT(name = "previous")) then Expression.BOOLEAN(b); | |
| 402 | ✗ | case Function.FUNCTION(path = Absyn.IDENT(name = "pre")) then Expression.BOOLEAN(b); | |
| 403 | case Function.FUNCTION(path = Absyn.IDENT(name = "edge")) then Expression.BOOLEAN(false); | ||
| 404 | case Function.FUNCTION(path = Absyn.IDENT(name = "change")) then Expression.BOOLEAN(false); | ||
| 405 | else exp; | ||
| 406 | end match; | ||
| 407 | then new_exp; | ||
| 408 | |||
| 409 | // the expression is previous(d) -> $PRE.d or previous(not d) -> not $PRE.d | ||
| 410 | // also store the clocked state | ||
| 411 | case Expression.CALL(call = Call.TYPED_CALL(fn = Function.FUNCTION(path = Absyn.IDENT(name = "previous")), arguments = args)) | ||
| 412 | algorithm | ||
| 413 | 6 | (new_exp, old_exp) := preFromArgs(args, acc_previous, scalarized, "previous"); | |
| 414 | () := match old_exp | ||
| 415 | case Expression.CREF() algorithm | ||
| 416 | 12 | Pointer.update(acc_clocked_states, BVariable.getVarPointer(old_exp.cref, sourceInfo()) :: Pointer.access(acc_clocked_states)); | |
| 417 | then (); | ||
| 418 | |||
| 419 | else algorithm | ||
| 420 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because previous() can only contain component references, but contained: " | |
| 421 | + Expression.toString(old_exp)}); | ||
| 422 | ✗ | then fail(); | |
| 423 | end match; | ||
| 424 | then new_exp; | ||
| 425 | |||
| 426 | // the expression is pre(d) -> $PRE.d or pre(not d) -> not $PRE.d | ||
| 427 | case Expression.CALL(call = Call.TYPED_CALL(fn = Function.FUNCTION(path = Absyn.IDENT(name = "pre")), arguments = args)) | ||
| 428 | algorithm | ||
| 429 | 100 | (new_exp, _) := preFromArgs(args, acc_previous, scalarized, "pre"); | |
| 430 | then new_exp; | ||
| 431 | |||
| 432 | // the expression is edge(d) -> d and not $PRE.d or edge(not d) not d and $PRE.d | ||
| 433 | case Expression.CALL(call = Call.TYPED_CALL(fn = Function.FUNCTION(path = Absyn.IDENT(name = "edge")), arguments = args)) | ||
| 434 | algorithm | ||
| 435 | ✗ | (new_exp, old_exp) := preFromArgs(args, acc_previous, scalarized, "edge"); | |
| 436 | ✗ | then Expression.LBINARY(old_exp, Operator.makeAnd(Expression.typeOf(old_exp)), Expression.logicNegate(new_exp)); | |
| 437 | |||
| 438 | // the expression is change(d) -> d <> $PRE.d or change(not d) not d <> not $PRE.d | ||
| 439 | // (not necessary to have the "not" but works and is most consistent with other cases) | ||
| 440 | case Expression.CALL(call = Call.TYPED_CALL(fn = Function.FUNCTION(path = Absyn.IDENT(name = "change")), arguments = args)) | ||
| 441 | algorithm | ||
| 442 | ✗ | (new_exp, old_exp) := preFromArgs(args, acc_previous, scalarized, "change"); | |
| 443 | ✗ | then Expression.RELATION(old_exp, Operator.makeNotEqual(Expression.typeOf(old_exp)), new_exp, -1); | |
| 444 | |||
| 445 | else exp; | ||
| 446 | end match; | ||
| 447 | end collectPreAndPrevious; | ||
| 448 | |||
| 449 | function preFromArgs | ||
| 450 | "takes a list of arguments (expected to be only one cref) and creates the pre variable from it. | ||
| 451 | used for pre(), edge(), change()" | ||
| 452 | input list<Expression> args; | ||
| 453 | input Pointer<list<Pointer<Variable>>> acc_previous; | ||
| 454 | input Boolean scalarized; | ||
| 455 | input String context; | ||
| 456 | output Expression new_exp; | ||
| 457 | output Expression old_exp; | ||
| 458 | protected | ||
| 459 | ComponentRef state_cref, pre_cref; | ||
| 460 | Pointer<Variable> state_var; | ||
| 461 | Boolean negated; | ||
| 462 | algorithm | ||
| 463 | (state_var, old_exp, negated) := match args | ||
| 464 | 106 | case {old_exp as Expression.CREF(cref = state_cref)} then (BVariable.getVarPointer(state_cref, sourceInfo()), old_exp, false); | |
| 465 | ✗ | case {old_exp as Expression.LUNARY(exp = Expression.CREF(cref = state_cref))} then (BVariable.getVarPointer(state_cref, sourceInfo()), old_exp, true); | |
| 466 | else algorithm | ||
| 467 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unexpected expression " + context + "(" | |
| 468 | + List.toString(args, Expression.toString, List.Style.FLAT) + ")."}); | ||
| 469 | ✗ | then fail(); | |
| 470 | end match; | ||
| 471 | 106 | pre_cref := getPreVar(state_cref, state_var, acc_previous, scalarized); | |
| 472 | |||
| 473 | 106 | new_exp := Expression.fromCref(pre_cref); | |
| 474 |
1/2✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
|
106 | if negated then |
| 475 | ✗ | new_exp := Expression.logicNegate(new_exp); | |
| 476 | end if; | ||
| 477 | end preFromArgs; | ||
| 478 | |||
| 479 | function updateDiscreteStatesAndPrevious | ||
| 480 | "Updates the variable pointer arrays with the new information about states and derivatives." | ||
| 481 | input output VariablePointers variables "All variables"; | ||
| 482 | input output VariablePointers knowns "Knowns"; | ||
| 483 | input output VariablePointers initials "initial unknowns"; | ||
| 484 | input output VariablePointers discretes "Discrete variables"; | ||
| 485 | input output VariablePointers discrete_states "Discrete state variables"; | ||
| 486 | input output VariablePointers clocked_states "Clocked state variables"; | ||
| 487 | input output VariablePointers previous "Previous (left limit) variables"; | ||
| 488 | input list<Pointer<Variable>> acc_discrete_states; | ||
| 489 | input list<Pointer<Variable>> acc_clocked_states; | ||
| 490 | input list<Pointer<Variable>> acc_previous; | ||
| 491 | input String context "only for debugging"; | ||
| 492 | algorithm | ||
| 493 | // Add the new derivatives to variables, unknowns and derivative pointer arrays | ||
| 494 | 950 | variables := VariablePointers.addList(acc_previous, variables); | |
| 495 | 950 | knowns := VariablePointers.addList(acc_previous, knowns); | |
| 496 | 950 | initials := VariablePointers.addList(acc_previous, initials); | |
| 497 | 950 | previous := VariablePointers.addList(acc_previous, previous); | |
| 498 | 950 | discrete_states := VariablePointers.addList(acc_discrete_states, discrete_states); | |
| 499 | 950 | clocked_states := VariablePointers.addList(acc_clocked_states, clocked_states); | |
| 500 | // remove discrete states from discretes and remove clocked states from both discretes and discrete states | ||
| 501 | 950 | discretes := VariablePointers.removeList(acc_discrete_states, discretes); | |
| 502 | 950 | discretes := VariablePointers.removeList(acc_clocked_states, discretes); | |
| 503 | 950 | discrete_states := VariablePointers.removeList(acc_clocked_states, discrete_states); | |
| 504 | |||
| 505 |
2/2✓ Branch 1 taken 25 times.
✓ Branch 2 taken 925 times.
|
950 | if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) then |
| 506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if not listEmpty(acc_discrete_states) then |
| 507 | ✗ | print(StringUtil.headline_4("[stateselection] Natural discrete states from " + context + ":")); | |
| 508 | ✗ | print(List.toString(acc_discrete_states, BVariable.pointerToString, List.Style.NEWLINE_TAB) + "\n\n"); | |
| 509 | end if; | ||
| 510 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if not listEmpty(acc_clocked_states) then |
| 511 | ✗ | print(StringUtil.headline_4("[stateselection] Natural clocked states from " + context + ":")); | |
| 512 | ✗ | print(List.toString(acc_clocked_states, BVariable.pointerToString, List.Style.NEWLINE_TAB) + "\n\n"); | |
| 513 | end if; | ||
| 514 | end if; | ||
| 515 | |||
| 516 |
1/2✓ Branch 1 taken 950 times.
✗ Branch 2 not taken.
|
950 | if Flags.isSet(Flags.DUMP_DISCRETEVARS_INFO) then |
| 517 | ✗ | if not listEmpty(acc_previous) then | |
| 518 | ✗ | print(StringUtil.headline_4("[discreteinfo] pre() and previous() variables from " + context + ":")); | |
| 519 | ✗ | print(List.toString(acc_previous, BVariable.pointerToString, List.Style.NEWLINE_TAB) + "\n\n"); | |
| 520 | end if; | ||
| 521 | end if; | ||
| 522 | |||
| 523 | end updateDiscreteStatesAndPrevious; | ||
| 524 | |||
| 525 | function collectDiscreteStatesFromWhen | ||
| 526 | "All variables on the LHS in a when equation are considered discrete." | ||
| 527 | input output Equation eqn "outputs equation just to fit the map() interface. does not change."; | ||
| 528 | input Pointer<list<Pointer<Variable>>> acc_discrete_states; | ||
| 529 | input Pointer<list<Pointer<Variable>>> acc_previous; | ||
| 530 | input Boolean scalarized; | ||
| 531 | algorithm | ||
| 532 | () := match eqn | ||
| 533 | case Equation.WHEN_EQUATION() algorithm | ||
| 534 | 74 | collectDiscreteStatesFromWhenBody(eqn.body, acc_discrete_states, acc_previous, scalarized); | |
| 535 | then (); | ||
| 536 | case Equation.FOR_EQUATION() algorithm | ||
| 537 |
2/2✓ Branch 0 taken 304 times.
✓ Branch 1 taken 304 times.
|
608 | for b_eqn in eqn.body loop |
| 538 | 304 | collectDiscreteStatesFromWhen(b_eqn, acc_discrete_states, acc_previous, scalarized); | |
| 539 | end for; | ||
| 540 | then (); | ||
| 541 | case Equation.IF_EQUATION() algorithm | ||
| 542 | 5 | collectDiscreteStatesFromWhenInIf(eqn.body, acc_discrete_states, acc_previous, scalarized); | |
| 543 | then (); | ||
| 544 | else (); | ||
| 545 | end match; | ||
| 546 | end collectDiscreteStatesFromWhen; | ||
| 547 | |||
| 548 | function collectDiscreteStatesFromWhenBody | ||
| 549 | "All variables on the LHS in a when equation are considered discrete." | ||
| 550 | input WhenEquationBody body; | ||
| 551 | input Pointer<list<Pointer<Variable>>> acc_discrete_states; | ||
| 552 | input Pointer<list<Pointer<Variable>>> acc_previous; | ||
| 553 | input Boolean scalarized; | ||
| 554 | algorithm | ||
| 555 |
2/2✓ Branch 0 taken 74 times.
✓ Branch 1 taken 74 times.
|
148 | for body_stmt in body.when_stmts loop |
| 556 | () := match body_stmt | ||
| 557 | local | ||
| 558 | ComponentRef state_cref; | ||
| 559 | Pointer<Variable> state_var; | ||
| 560 | |||
| 561 | case WhenStatement.ASSIGN(lhs = Expression.CREF(cref = state_cref)) algorithm | ||
| 562 | // the function getPreVar() does all necessary collecting of information | ||
| 563 | // but we don't need the actual pre cref it returns | ||
| 564 | 68 | state_var := BVariable.getVarPointer(state_cref, sourceInfo()); | |
| 565 | 68 | BVariable.makeDiscreteStateVar(state_var); | |
| 566 | 68 | getPreVar(state_cref, state_var, acc_previous, scalarized); | |
| 567 | 136 | Pointer.update(acc_discrete_states, state_var :: Pointer.access(acc_discrete_states)); | |
| 568 | then (); | ||
| 569 | |||
| 570 | else (); | ||
| 571 | end match; | ||
| 572 | end for; | ||
| 573 | end collectDiscreteStatesFromWhenBody; | ||
| 574 | |||
| 575 | function collectDiscreteStatesFromWhenInIf | ||
| 576 | input IfEquationBody body; | ||
| 577 | input Pointer<list<Pointer<Variable>>> acc_discrete_states; | ||
| 578 | input Pointer<list<Pointer<Variable>>> acc_previous; | ||
| 579 | input Boolean scalarized; | ||
| 580 | algorithm | ||
| 581 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
20 | for eqn in body.then_eqns loop |
| 582 | 10 | collectDiscreteStatesFromWhen(Pointer.access(eqn), acc_discrete_states, acc_previous, scalarized); | |
| 583 | end for; | ||
| 584 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
|
10 | if isSome(body.else_if) then |
| 585 | 5 | collectDiscreteStatesFromWhenInIf(Util.getOption(body.else_if), acc_discrete_states, acc_previous, scalarized); | |
| 586 | end if; | ||
| 587 | end collectDiscreteStatesFromWhenInIf; | ||
| 588 | |||
| 589 | function getPreVar | ||
| 590 | input ComponentRef var_cref; | ||
| 591 | input Pointer<Variable> var_ptr; | ||
| 592 | input Pointer<list<Pointer<Variable>>> acc_previous; | ||
| 593 | input Boolean scalarized; | ||
| 594 | output ComponentRef pre_cref; | ||
| 595 | protected | ||
| 596 | Option<Pointer<Variable>> pre = BVariable.getVarPre(var_ptr); | ||
| 597 | Pointer<Variable> pre_var; | ||
| 598 | algorithm | ||
| 599 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 93 times.
|
174 | if isSome(pre) then |
| 600 | 93 | SOME(pre_var) := pre; | |
| 601 | 93 | pre_cref := BVariable.getVarName(pre_var); | |
| 602 | 93 | pre_cref := ComponentRef.copySubscripts(var_cref, pre_cref); | |
| 603 | else | ||
| 604 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | if not scalarized then |
| 605 | // prevent the created pre variable from having the subscripts, but add it to the pre_cref | ||
| 606 | 81 | (pre_cref, pre_var) := BVariable.makePreVar(ComponentRef.stripSubscriptsAll(var_cref)); | |
| 607 | 81 | pre_cref := ComponentRef.copySubscripts(var_cref, pre_cref); | |
| 608 | else | ||
| 609 | ✗ | (pre_cref, pre_var) := BVariable.makePreVar(var_cref); | |
| 610 | end if; | ||
| 611 | 81 | Pointer.update(acc_previous, pre_var :: Pointer.access(acc_previous)); | |
| 612 | end if; | ||
| 613 | end getPreVar; | ||
| 614 | |||
| 615 | public function findDiscreteStatesFromWhenBody | ||
| 616 | "All variables on the LHS in a when equation are considered discrete, add these to acc lists" | ||
| 617 | input WhenEquationBody body; | ||
| 618 | input Pointer<list<Pointer<Variable>>> acc_discrete_states; | ||
| 619 | input Pointer<list<Pointer<Variable>>> acc_previous; | ||
| 620 | algorithm | ||
| 621 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
2 | for body_stmt in body.when_stmts loop |
| 622 | () := match body_stmt | ||
| 623 | local | ||
| 624 | ComponentRef state_cref; | ||
| 625 | Pointer<Variable> state_var, pre_var; | ||
| 626 | |||
| 627 | case WhenStatement.ASSIGN(lhs = Expression.CREF(cref = state_cref)) algorithm | ||
| 628 | 1 | state_var := BVariable.getVarPointer(state_cref, sourceInfo()); | |
| 629 | () := match BVariable.getVarPre(state_var) | ||
| 630 | case SOME(pre_var) algorithm | ||
| 631 | 2 | Pointer.update(acc_previous, pre_var :: Pointer.access(acc_previous)); | |
| 632 | then (); | ||
| 633 | else (); | ||
| 634 | end match; | ||
| 635 | 2 | Pointer.update(acc_discrete_states, state_var :: Pointer.access(acc_discrete_states)); | |
| 636 | then (); | ||
| 637 | else (); | ||
| 638 | end match; | ||
| 639 | end for; | ||
| 640 | end findDiscreteStatesFromWhenBody; | ||
| 641 | |||
| 642 | function stateOrder | ||
| 643 | input output Equation eqn; | ||
| 644 | input UnorderedMap<ComponentRef, ComponentRef> state_order; | ||
| 645 | protected | ||
| 646 | Expression lhs, rhs; | ||
| 647 | algorithm | ||
| 648 | () := match eqn | ||
| 649 | case Equation.SCALAR_EQUATION(lhs = lhs as Expression.CREF(), rhs = rhs as Expression.CREF()) algorithm | ||
| 650 | 680 | updateStateOrder(lhs.cref, rhs.cref, state_order); | |
| 651 | then (); | ||
| 652 | |||
| 653 | // ToDo: sliced array/for-loops | ||
| 654 | case Equation.ARRAY_EQUATION(lhs = lhs as Expression.CREF(), rhs = rhs as Expression.CREF()) algorithm | ||
| 655 | 219 | updateStateOrder(lhs.cref, rhs.cref, state_order); | |
| 656 | then (); | ||
| 657 | |||
| 658 | case Equation.FOR_EQUATION() algorithm | ||
| 659 |
2/2✓ Branch 0 taken 304 times.
✓ Branch 1 taken 304 times.
|
608 | for b in eqn.body loop |
| 660 | 304 | stateOrder(b, state_order); | |
| 661 | end for; | ||
| 662 | then (); | ||
| 663 | |||
| 664 | else (); | ||
| 665 | end match; | ||
| 666 | end stateOrder; | ||
| 667 | |||
| 668 | function promotePreferStates | ||
| 669 | "Promotes StateSelect.prefer variables to states if the model has ANY der() calls. | ||
| 670 | Only relevant for variables that have StateSelect.prefer but do NOT occur inside der() | ||
| 671 | calls — those that do occur are already promoted by natural state collection and removed | ||
| 672 | from algebraics before this function runs." | ||
| 673 | input output VariablePointers variables; | ||
| 674 | input output VariablePointers unknowns; | ||
| 675 | input output VariablePointers knowns; | ||
| 676 | input output VariablePointers initials; | ||
| 677 | input output VariablePointers states; | ||
| 678 | input output VariablePointers derivatives; | ||
| 679 | input output VariablePointers algebraics; | ||
| 680 | protected | ||
| 681 | list<Pointer<Variable>> acc_prefer_states = {}; | ||
| 682 | list<Pointer<Variable>> acc_prefer_ders = {}; | ||
| 683 | ComponentRef der_cref; | ||
| 684 | Pointer<Variable> der_var; | ||
| 685 | algorithm | ||
| 686 | // only promote if the model is dynamic (has at least one der() call) | ||
| 687 |
2/2✓ Branch 1 taken 106 times.
✓ Branch 2 taken 84 times.
|
190 | if VariablePointers.size(states) > 0 then |
| 688 |
2/2✓ Branch 1 taken 522 times.
✓ Branch 2 taken 84 times.
|
606 | for alg_ptr in VariablePointers.toList(algebraics) loop |
| 689 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 519 times.
|
522 | if BVariable.isStateSelect(alg_ptr, StateSelect.PREFER) then |
| 690 | // this variable has StateSelect.prefer but is not inside any der() call; | ||
| 691 | // create its derivative and promote it to a state | ||
| 692 | 3 | (der_cref, der_var) := BVariable.makeDerVar(BVariable.getVarName(alg_ptr), variables.scalarized); | |
| 693 | 6 | BVariable.setVarKind(alg_ptr, VariableKind.STATE(1, SOME(PointerWeak.downgrade(der_var)), false)); | |
| 694 | acc_prefer_states := alg_ptr :: acc_prefer_states; | ||
| 695 | 3 | acc_prefer_ders := der_var :: acc_prefer_ders; | |
| 696 | end if; | ||
| 697 | end for; | ||
| 698 | |||
| 699 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1 time.
|
84 | if not listEmpty(acc_prefer_states) then |
| 700 | // update state variable arrays | ||
| 701 | 1 | states := VariablePointers.addList(acc_prefer_states, states); | |
| 702 | 1 | unknowns := VariablePointers.removeList(acc_prefer_states, unknowns); | |
| 703 | 1 | algebraics := VariablePointers.removeList(acc_prefer_states, algebraics); | |
| 704 | |||
| 705 | // update derivative variable arrays (newly created — not yet in any array) | ||
| 706 | 1 | variables := VariablePointers.addList(acc_prefer_ders, variables); | |
| 707 | 1 | unknowns := VariablePointers.addList(acc_prefer_ders, unknowns); | |
| 708 | 1 | initials := VariablePointers.addList(acc_prefer_ders, initials); | |
| 709 | 1 | derivatives := VariablePointers.addList(acc_prefer_ders, derivatives); | |
| 710 | |||
| 711 |
1/2✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
|
1 | if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) then |
| 712 | ✗ | print(StringUtil.headline_4("[stateselection] (" + intString(listLength(acc_prefer_states)) + ") Forced states by StateSelect.PREFER:")); | |
| 713 | ✗ | print(List.toString(acc_prefer_states, BVariable.pointerToString, List.Style.NEWLINE_TAB) + "\n\n"); | |
| 714 | end if; | ||
| 715 | end if; | ||
| 716 | end if; | ||
| 717 | end promotePreferStates; | ||
| 718 | |||
| 719 | function updateStateOrder | ||
| 720 | input ComponentRef lhs; | ||
| 721 | input ComponentRef rhs; | ||
| 722 | input UnorderedMap<ComponentRef, ComponentRef> state_order; | ||
| 723 | protected | ||
| 724 | PointerWeak<Variable> state; | ||
| 725 | algorithm | ||
| 726 | () := match (BVariable.getVarKind(BVariable.getVarPointer(lhs, sourceInfo())), BVariable.getVarKind(BVariable.getVarPointer(rhs, sourceInfo()))) | ||
| 727 | // a = der(b) | ||
| 728 | case (_, VariableKind.STATE_DER(state = state)) algorithm | ||
| 729 | 28 | UnorderedMap.add(BVariable.getVarName(PointerWeak.upgrade(state)), ComponentRef.stripSubscriptsAll(lhs), state_order); | |
| 730 | then (); | ||
| 731 | // der(b) = a | ||
| 732 | case (VariableKind.STATE_DER(state = state), _) algorithm | ||
| 733 | 34 | UnorderedMap.add(BVariable.getVarName(PointerWeak.upgrade(state)), ComponentRef.stripSubscriptsAll(rhs), state_order); | |
| 734 | then (); | ||
| 735 | else (); | ||
| 736 | end match; | ||
| 737 | end updateStateOrder; | ||
| 738 | |||
| 739 | annotation(__OpenModelica_Interface="nbackend"); | ||
| 740 | end NBDetectStates; | ||
| 741 | |||
| 742 | |||
| 743 |