OMCompiler/Compiler/NBackEnd/Modules/1_Main/NBCausalize.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 NBCausalize | ||
| 37 | "file: NBCausalize.mo | ||
| 38 | package: NBCausalize | ||
| 39 | description: This file contains the functions which perform the causalization process; | ||
| 40 | " | ||
| 41 | |||
| 42 | public | ||
| 43 | import Module = NBModule; | ||
| 44 | |||
| 45 | protected | ||
| 46 | // OF imports | ||
| 47 | import Absyn.Path; | ||
| 48 | |||
| 49 | // NF imports | ||
| 50 | import ComponentRef = NFComponentRef; | ||
| 51 | import Dimension = NFDimension; | ||
| 52 | import Expression = NFExpression; | ||
| 53 | import NFFunction.Function; | ||
| 54 | import InstNode = NFInstNode.InstNode; | ||
| 55 | import Prefixes = NFPrefixes; | ||
| 56 | import Subscript = NFSubscript; | ||
| 57 | import Type = NFType; | ||
| 58 | import TypeCheck = NFTypeCheck; | ||
| 59 | import Variable = NFVariable; | ||
| 60 | import NFArrayConnections.NameVertexTable; | ||
| 61 | |||
| 62 | // Backend imports | ||
| 63 | import Adjacency = NBAdjacency; | ||
| 64 | import ASSC = NBASSC; | ||
| 65 | import BackendDAE = NBackendDAE; | ||
| 66 | import BEquation = NBEquation; | ||
| 67 | import Differentiate = NBDifferentiate; | ||
| 68 | import NBEquation.{Equation, EquationPointers, EqData, EquationAttributes, Iterator}; | ||
| 69 | import Matching = NBMatching; | ||
| 70 | import Sorting = NBSorting; | ||
| 71 | import StrongComponent = NBStrongComponent; | ||
| 72 | import BPartition = NBPartition; | ||
| 73 | import NBPartition.Partition; | ||
| 74 | import BVariable = NBVariable; | ||
| 75 | import NBVariable.{VariablePointers, VarData}; | ||
| 76 | |||
| 77 | // util imports | ||
| 78 | import BackendUtil = NBBackendUtil; | ||
| 79 | import Error; | ||
| 80 | import ErrorExt; | ||
| 81 | import List; | ||
| 82 | import StringUtil; | ||
| 83 | |||
| 84 | // ############################################################ | ||
| 85 | // Main Functions | ||
| 86 | // ############################################################ | ||
| 87 | |||
| 88 | public | ||
| 89 | function main extends Module.wrapper; | ||
| 90 | input BPartition.Kind kind; | ||
| 91 | protected | ||
| 92 | Module.causalizeInterface func = getModule(); | ||
| 93 | algorithm | ||
| 94 | bdae := match (kind, bdae) | ||
| 95 | local | ||
| 96 | list<Partition> partitions, clocked, twins; | ||
| 97 | VarData varData; | ||
| 98 | EqData eqData; | ||
| 99 | |||
| 100 | case (NBPartition.Kind.ODE, BackendDAE.MAIN(ode = partitions, clocked = clocked, varData = varData, eqData = eqData)) | ||
| 101 | algorithm | ||
| 102 | 190 | (partitions, varData, eqData) := applyModule(partitions, kind, varData, eqData, bdae.funcMap, func); | |
| 103 | 188 | (clocked, varData, eqData) := applyModule(clocked, kind, varData, eqData, bdae.funcMap, func); | |
| 104 | 188 | bdae.ode := partitions; | |
| 105 | 188 | bdae.clocked := clocked; | |
| 106 | 188 | bdae.varData := varData; | |
| 107 | 188 | bdae.eqData := eqData; | |
| 108 | then bdae; | ||
| 109 | |||
| 110 | case (_, BackendDAE.MAIN(init = partitions, varData = varData, eqData = eqData)) guard(Partition.kindIsInitial(kind)) | ||
| 111 | algorithm | ||
| 112 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
|
188 | if Flags.isSet(Flags.INITIALIZATION) then |
| 113 | ✗ | print(StringUtil.headline_1("Balance Initialization") + "\n"); | |
| 114 | end if; | ||
| 115 | // init_0 is init with the homotopy calls replaced by their simplified branch | ||
| 116 | 188 | (partitions, varData, eqData, twins) := applyModule(partitions, kind, varData, eqData, bdae.funcMap, func, Util.getOptionOrDefault(bdae.init_0, {})); | |
| 117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
|
188 | bdae.init := partitions; |
| 118 |
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 |
| 119 | 6 | bdae.init_0 := SOME(twins); | |
| 120 | end if; | ||
| 121 | 188 | bdae.varData := varData; | |
| 122 | 188 | bdae.eqData := eqData; | |
| 123 | then bdae; | ||
| 124 | |||
| 125 | case (NBPartition.Kind.DAE, BackendDAE.MAIN(dae = SOME(partitions), varData = varData, eqData = eqData)) | ||
| 126 | algorithm | ||
| 127 | 1 | (partitions, varData, eqData) := applyModule(partitions, kind, varData, eqData, bdae.funcMap, causalizeDAEMode); | |
| 128 | 1 | bdae.dae := SOME(partitions); | |
| 129 | 1 | bdae.varData := varData; | |
| 130 | 1 | bdae.eqData := eqData; | |
| 131 | then bdae; | ||
| 132 | |||
| 133 | else algorithm | ||
| 134 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed with partition type " + Partition.Partition.kindToString(kind) + "!"}); | |
| 135 | ✗ | then fail(); | |
| 136 | end match; | ||
| 137 | end main; | ||
| 138 | |||
| 139 | function applyModule | ||
| 140 | input list<Partition> partitions; | ||
| 141 | input BPartition.Kind kind; | ||
| 142 | output list<Partition> new_partitions = {}; | ||
| 143 | input output VarData varData; | ||
| 144 | input output EqData eqData; | ||
| 145 | input UnorderedMap<Path, Function> funcMap; | ||
| 146 | input Module.causalizeInterface func; | ||
| 147 | input list<Partition> twins = {} "partitions of nearly the same systems, paired by index"; | ||
| 148 | output list<Partition> new_twins = {}; | ||
| 149 | protected | ||
| 150 | Partition new_partition; | ||
| 151 | list<Partition> paired, unpaired = twins; | ||
| 152 | Boolean violated = false "true if any partition violated variability consistency"; | ||
| 153 | algorithm | ||
| 154 |
2/2✓ Branch 0 taken 505 times.
✓ Branch 1 taken 566 times.
|
1071 | for partition in partitions loop |
| 155 | 505 | (paired, unpaired) := List.splitOnTrue(unpaired, function Partition.hasIndex(index = partition.index)); | |
| 156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
505 | (new_partition, varData, eqData, paired) := func(partition, varData, eqData, funcMap, paired); |
| 157 |
2/2✓ Branch 1 taken 503 times.
✓ Branch 2 taken 1 time.
|
504 | new_partitions := if Partition.isEmpty(new_partition) then new_partitions else new_partition :: new_partitions; |
| 158 |
5/6✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 504 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 504 times.
|
510 | new_twins := List.append_reverse(list(twin for twin guard(not Partition.isEmpty(twin)) in paired), new_twins); |
| 159 | end for; | ||
| 160 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 566 times.
|
566 | for twin in unpaired loop |
| 161 | ✗ | (new_partition, varData, eqData) := func(twin, varData, eqData, funcMap, {}); | |
| 162 | ✗ | new_twins := if Partition.isEmpty(new_partition) then new_twins else new_partition :: new_twins; | |
| 163 | end for; | ||
| 164 | 566 | new_partitions := listReverse(new_partitions); | |
| 165 | 566 | new_twins := listReverse(new_twins); | |
| 166 | |||
| 167 |
2/2✓ Branch 1 taken 378 times.
✓ Branch 2 taken 188 times.
|
566 | if not Partition.kindIsInitial(kind) then |
| 168 |
2/2✓ Branch 0 taken 329 times.
✓ Branch 1 taken 378 times.
|
707 | for partition in new_partitions loop |
| 169 |
3/4✓ Branch 1 taken 328 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 328 times.
✗ Branch 4 not taken.
|
329 | violated := checkSystemVariabilities(partition) or violated; |
| 170 | end for; | ||
| 171 |
2/2✓ Branch 0 taken 377 times.
✓ Branch 1 taken 1 time.
|
378 | if violated then fail(); end if; |
| 172 | end if; | ||
| 173 | end applyModule; | ||
| 174 | |||
| 175 | function checkSystemVariabilities | ||
| 176 | "checks whether variability is valid. Prevents things like `Integer i = time;`" | ||
| 177 | input Partition partition; | ||
| 178 | output Boolean violated = false; | ||
| 179 | protected | ||
| 180 | String err; | ||
| 181 | algorithm | ||
| 182 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
✓ Branch 2 taken 329 times.
✗ Branch 3 not taken.
|
329 | if isSome(partition.strongComponents) then |
| 183 |
2/2✓ Branch 2 taken 2432 times.
✓ Branch 3 taken 329 times.
|
3090 | for scc in Util.getOption(partition.strongComponents) loop |
| 184 | () := match scc | ||
| 185 | local | ||
| 186 | Type ty1, ty2; | ||
| 187 | TypeCheck.MatchKind kind; | ||
| 188 | |||
| 189 | case StrongComponent.SINGLE_COMPONENT() algorithm | ||
| 190 | 1372 | ty1 := Type.removeSizeOneArraysAndRecords(Variable.typeOf(Pointer.access(scc.var))); | |
| 191 | 1372 | ty2 := Type.removeSizeOneArraysAndRecords(Equation.getType(Pointer.access(scc.eqn))); | |
| 192 | 1372 | (_, _, kind) := TypeCheck.matchTypes(ty1, ty2, Expression.fromCref(BVariable.getVarName(scc.var))); | |
| 193 | |||
| 194 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1371 times.
|
1372 | if kind <> NFTypeCheck.MatchKind.EXACT then |
| 195 | // The variability of the equation must be greater or equal to that of the variable it solves. | ||
| 196 | // See MLS section 3.8 Variability of Expressions | ||
| 197 | 1 | err := getInstanceName() + " failed. The following strong component has conflicting types: " | |
| 198 | + Type.toString(ty1) + " != " + Type.toString(ty2) + "\n" + StrongComponent.toString(scc); | ||
| 199 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if Flags.isSet(Flags.BLT_DUMP) then |
| 200 | ✗ | err := err + "\n" + Partition.toString(partition); | |
| 201 | end if; | ||
| 202 | 1 | Error.addMessage(Error.COMPILER_ERROR, {err}); | |
| 203 | violated := true; | ||
| 204 | end if; | ||
| 205 | then (); | ||
| 206 | /* TODO case StrongComponent.MULTI_COMPONENT() */ | ||
| 207 | else (); | ||
| 208 | end match; | ||
| 209 | end for; | ||
| 210 | end if; | ||
| 211 | end checkSystemVariabilities; | ||
| 212 | |||
| 213 | function simple | ||
| 214 | input VariablePointers vars; | ||
| 215 | input EquationPointers eqns; | ||
| 216 | input BPartition.Kind kind; | ||
| 217 | input Adjacency.MatrixStrictness st = NBAdjacency.MatrixStrictness.MATCHING; | ||
| 218 | input Iterator iter = Iterator.EMPTY(); | ||
| 219 | output Matching matching; | ||
| 220 | output list<StrongComponent> comps; | ||
| 221 | protected | ||
| 222 | Adjacency.Matrix full, adj; | ||
| 223 | algorithm | ||
| 224 | // create full matrix | ||
| 225 | 1112 | full := Adjacency.Matrix.createFull(vars, eqns, kind); | |
| 226 | |||
| 227 | // create solvable adjacency matrix for matching | ||
| 228 | 1112 | adj := Adjacency.Matrix.fullToFinal(full, vars.map, eqns.map, eqns, st, iter); | |
| 229 | 1112 | matching := Matching.regular(NBMatching.EMPTY_MATCHING, adj); | |
| 230 | |||
| 231 | // create all occurence adjacency matrix for sorting, upgrading the matching matrix | ||
| 232 | 1112 | adj := Adjacency.Matrix.upgrade(adj, full, vars.map, eqns.map, eqns, NBAdjacency.MatrixStrictness.SORTING); | |
| 233 | 1112 | comps := Sorting.tarjan(adj, matching, vars, eqns); | |
| 234 | end simple; | ||
| 235 | |||
| 236 | function getModule | ||
| 237 | "Returns the module function that was chosen by the user." | ||
| 238 | output Module.causalizeInterface func; | ||
| 239 | protected | ||
| 240 | String flag = Flags.getConfigString(Flags.MATCHING_ALGORITHM); | ||
| 241 | algorithm | ||
| 242 | func := match flag | ||
| 243 | case "PFPlusExt" then causalizePseudoArray; | ||
| 244 | case "pseudo" then causalizePseudoArray; | ||
| 245 | /* ... New causalize modules have to be added here */ | ||
| 246 | else algorithm | ||
| 247 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for unknown option: " + flag}); | |
| 248 | ✗ | then fail(); | |
| 249 | end match; | ||
| 250 | end getModule; | ||
| 251 | |||
| 252 | // ############################################################ | ||
| 253 | // Protected Functions and Types | ||
| 254 | // ############################################################ | ||
| 255 | |||
| 256 | protected | ||
| 257 | function causalizePseudoArray extends Module.causalizeInterface; | ||
| 258 | protected | ||
| 259 | BPartition.Kind kind = Partition.getKind(partition); | ||
| 260 | VariablePointers variables; | ||
| 261 | EquationPointers equations; | ||
| 262 | Adjacency.Matrix full, adj_matching, adj_sorting; | ||
| 263 | Matching matching; | ||
| 264 | list<StrongComponent> comps; | ||
| 265 | list<Partition> new_twins = {}; | ||
| 266 | algorithm | ||
| 267 | (variables, equations, full, matching, comps) := match kind | ||
| 268 | local | ||
| 269 | list<Pointer<Variable>> fixable, unfixable; | ||
| 270 | list<Pointer<Equation>> initials, simulation; | ||
| 271 | UnorderedMap<ComponentRef, Integer> vo, vn, eo, en; | ||
| 272 | |||
| 273 | case kind guard(Partition.kindIsInitial(kind)) algorithm | ||
| 274 | // compress the arrays to remove gaps | ||
| 275 | 175 | partition.unknowns := VariablePointers.compress(partition.unknowns); | |
| 276 | 175 | partition.equations := EquationPointers.compress(partition.equations); | |
| 277 | |||
| 278 | // split the variables and equations | ||
| 279 | 175 | (fixable, unfixable) := List.splitOnTrue(VariablePointers.toList(partition.unknowns), BVariable.isFixable); | |
| 280 | 175 | (initials, simulation) := List.splitOnTrue(EquationPointers.toList(partition.equations), Equation.isInitial); | |
| 281 | |||
| 282 | // create full matrix | ||
| 283 | 175 | full := Adjacency.Matrix.createFull(partition.unknowns, partition.equations, kind); | |
| 284 | |||
| 285 | // do not resolve potential singular partitions in Phase I or II! -> regular matching | ||
| 286 | // ################################################# | ||
| 287 | // Phase I: match initial equations <-> unfixable vars | ||
| 288 | // ################################################# | ||
| 289 |
4/4✓ Branch 0 taken 2805 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 2805 times.
✓ Branch 3 taken 175 times.
|
2980 | vn := UnorderedMap.subMap(partition.unknowns.map, list(BVariable.getVarName(var) for var in unfixable)); |
| 290 |
4/4✓ Branch 0 taken 723 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 723 times.
✓ Branch 3 taken 175 times.
|
898 | en := UnorderedMap.subMap(partition.equations.map, list(Equation.getEqnName(eqn) for eqn in initials)); |
| 291 | 175 | adj_matching := Adjacency.Matrix.fullToFinal(full, vn, en, partition.equations, NBAdjacency.MatrixStrictness.MATCHING); | |
| 292 | 175 | matching := Matching.regular(NBMatching.EMPTY_MATCHING, adj_matching, true, true); | |
| 293 | |||
| 294 | // ################################################# | ||
| 295 | // Phase II: match all equations <-> unfixables | ||
| 296 | // ################################################# | ||
| 297 | vo := vn; | ||
| 298 | eo := en; | ||
| 299 | 175 | vn := UnorderedMap.new<Integer>(ComponentRef.hash, ComponentRef.isEqual); | |
| 300 |
4/4✓ Branch 0 taken 3335 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 3335 times.
✓ Branch 3 taken 175 times.
|
3510 | en := UnorderedMap.subMap(partition.equations.map, list(Equation.getEqnName(eqn) for eqn in simulation)); |
| 301 | 175 | (adj_matching, full) := Adjacency.Matrix.expand(adj_matching, full, vo, vn, eo, en, partition.unknowns, partition.equations, Partition.getKind(partition)); | |
| 302 | 175 | matching := Matching.regular(matching, adj_matching, true, true); | |
| 303 | |||
| 304 | // ################################################# | ||
| 305 | // Phase III: match all equations <-> all vars | ||
| 306 | // ################################################# | ||
| 307 | 175 | vo := UnorderedMap.merge(vo, vn, sourceInfo()); | |
| 308 | 175 | eo := UnorderedMap.merge(eo, en, sourceInfo()); | |
| 309 |
4/4✓ Branch 0 taken 380 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 380 times.
✓ Branch 3 taken 175 times.
|
555 | vn := UnorderedMap.subMap(partition.unknowns.map, list(BVariable.getVarName(var) for var in fixable)); |
| 310 | 175 | en := UnorderedMap.new<Integer>(ComponentRef.hash, ComponentRef.isEqual); | |
| 311 | 175 | (adj_matching, full) := Adjacency.Matrix.expand(adj_matching, full, vo, vn, eo, en, partition.unknowns, partition.equations, Partition.getKind(partition)); | |
| 312 | 175 | (matching, adj_matching, full, variables, equations, varData, eqData) := Matching.singular(matching, adj_matching, full, partition.unknowns, partition.equations, funcMap, varData, eqData, kind, false, false); | |
| 313 | |||
| 314 | // create all occurence adjacency matrix for sorting, upgrading the matching matrix | ||
| 315 | 175 | adj_sorting := Adjacency.Matrix.upgrade(adj_matching, full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.SORTING); | |
| 316 | 175 | comps := Sorting.tarjan(adj_sorting, matching, variables, equations); | |
| 317 | 175 | then (variables, equations, full, matching, comps); | |
| 318 | |||
| 319 | else algorithm | ||
| 320 | // compress the arrays to remove gaps | ||
| 321 | 329 | variables := VariablePointers.compress(partition.unknowns); | |
| 322 | 329 | equations := EquationPointers.compress(partition.equations); | |
| 323 | |||
| 324 | // perform ASSC on the system | ||
| 325 | //ASSC.main(equations, variables); | ||
| 326 | |||
| 327 | // create full matrix | ||
| 328 | 329 | full := Adjacency.Matrix.createFull(variables, equations, kind); | |
| 329 | |||
| 330 | // create solvable adjacency matrix for matching | ||
| 331 | 329 | adj_matching := Adjacency.Matrix.fullToFinal(full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.MATCHING); | |
| 332 | |||
| 333 | // perform matching | ||
| 334 | 329 | (matching, adj_matching, full, variables, equations, varData, eqData) := Matching.singular(NBMatching.EMPTY_MATCHING, adj_matching, full, variables, equations, funcMap, varData, eqData, kind, false); | |
| 335 | |||
| 336 | // create all occurence adjacency matrix for sorting, upgrading the matching matrix | ||
| 337 | 328 | adj_sorting := Adjacency.Matrix.upgrade(adj_matching, full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.SORTING); | |
| 338 | 328 | comps := Sorting.tarjan(adj_sorting, matching, variables, equations); | |
| 339 | 328 | then (variables, equations, full, matching, comps); | |
| 340 | end match; | ||
| 341 | |||
| 342 | 1006 | partition.unknowns := variables; | |
| 343 | partition.equations := equations; | ||
| 344 | partition.adjacencyMatrix := SOME(full); | ||
| 345 | partition.matching := SOME(matching); | ||
| 346 | partition.strongComponents := SOME(listArray(comps)); | ||
| 347 | |||
| 348 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 503 times.
|
509 | for twin in twins loop |
| 349 | 6 | (twin, varData, eqData) := causalizeTwin(twin, partition, adj_matching, adj_sorting, funcMap, varData, eqData); | |
| 350 | new_twins := twin :: new_twins; | ||
| 351 | end for; | ||
| 352 | 503 | twins := listReverse(new_twins); | |
| 353 | end causalizePseudoArray; | ||
| 354 | |||
| 355 | function causalizeTwin | ||
| 356 | "causalizes the twin from the seed and falls back to causalizing it from | ||
| 357 | scratch if that fails. The seed's matching was not built by the three | ||
| 358 | matching phases and can leave a variable that is not fixable unmatched | ||
| 359 | in the balancing of the initialization." | ||
| 360 | input output Partition twin; | ||
| 361 | input Partition seed; | ||
| 362 | input Adjacency.Matrix seed_matching; | ||
| 363 | input Adjacency.Matrix seed_sorting; | ||
| 364 | input UnorderedMap<Path, Function> funcMap; | ||
| 365 | input output VarData varData; | ||
| 366 | input output EqData eqData; | ||
| 367 | protected | ||
| 368 | list<Partition> no_twins; | ||
| 369 | algorithm | ||
| 370 | 6 | ErrorExt.setCheckpoint("NBCausalize.causalizeTwin"); | |
| 371 | try | ||
| 372 | 6 | (twin, varData, eqData) := causalizeTwinSeeded(twin, seed, seed_matching, seed_sorting, funcMap, varData, eqData); | |
| 373 | 6 | ErrorExt.delCheckpoint("NBCausalize.causalizeTwin"); | |
| 374 | else | ||
| 375 | ✗ | ErrorExt.rollBack("NBCausalize.causalizeTwin"); | |
| 376 | ✗ | (twin, varData, eqData, no_twins) := causalizePseudoArray(twin, varData, eqData, funcMap, {}); | |
| 377 | end try; | ||
| 378 | end causalizeTwin; | ||
| 379 | |||
| 380 | function causalizeTwinSeeded | ||
| 381 | "causalizes a partition over the same variables as the causalized seed and | ||
| 382 | nearly the same equations: the rows of equal equations are taken from the | ||
| 383 | seed's matrices and its matching is the starting point" | ||
| 384 | input output Partition twin; | ||
| 385 | input Partition seed; | ||
| 386 | input Adjacency.Matrix seed_matching; | ||
| 387 | input Adjacency.Matrix seed_sorting; | ||
| 388 | input UnorderedMap<Path, Function> funcMap; | ||
| 389 | input output VarData varData; | ||
| 390 | input output EqData eqData; | ||
| 391 | protected | ||
| 392 | BPartition.Kind kind = Partition.getKind(twin); | ||
| 393 | VariablePointers variables; | ||
| 394 | EquationPointers equations; | ||
| 395 | Adjacency.Matrix full, balanced, adj_matching, adj_sorting; | ||
| 396 | Matching matching; | ||
| 397 | array<Integer> seed_index; | ||
| 398 | list<StrongComponent> comps; | ||
| 399 | algorithm | ||
| 400 | 6 | twin.unknowns := VariablePointers.compress(twin.unknowns); | |
| 401 | twin.equations := EquationPointers.compress(twin.equations); | ||
| 402 | 6 | full := Adjacency.Matrix.createFull(twin.unknowns, twin.equations, kind); | |
| 403 | 6 | seed_index := Adjacency.Matrix.equalRows(seed.equations, seed.unknowns, twin.equations, twin.unknowns); | |
| 404 | 6 | adj_matching := Adjacency.Matrix.upgradeFrom(NBAdjacency.Matrix.EMPTY(NBAdjacency.MatrixStrictness.FULL), full, twin.unknowns.map, twin.equations.map, twin.equations, NBAdjacency.MatrixStrictness.MATCHING, seed_matching, seed_index); | |
| 405 | 6 | matching := Matching.fromSeed(seed, adj_matching, twin.unknowns, twin.equations); | |
| 406 | 6 | (matching, adj_matching, balanced, variables, equations, varData, eqData) := Matching.singular(matching, adj_matching, full, twin.unknowns, twin.equations, funcMap, varData, eqData, kind, false, false); | |
| 407 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if referenceEq(balanced, full) then |
| 408 | 6 | adj_sorting := Adjacency.Matrix.upgradeFrom(adj_matching, full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.SORTING, seed_sorting, seed_index); | |
| 409 | else | ||
| 410 | full := balanced; | ||
| 411 | ✗ | adj_sorting := Adjacency.Matrix.upgrade(adj_matching, full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.SORTING); | |
| 412 | end if; | ||
| 413 | 6 | comps := Sorting.tarjan(adj_sorting, matching, variables, equations); | |
| 414 | |||
| 415 | 18 | twin.unknowns := variables; | |
| 416 | twin.equations := equations; | ||
| 417 | twin.adjacencyMatrix := SOME(full); | ||
| 418 | twin.matching := SOME(matching); | ||
| 419 | twin.strongComponents := SOME(listArray(comps)); | ||
| 420 | end causalizeTwinSeeded; | ||
| 421 | |||
| 422 | function causalizeDAEMode extends Module.causalizeInterface; | ||
| 423 | algorithm | ||
| 424 | // nothing to do? | ||
| 425 | end causalizeDAEMode; | ||
| 426 | |||
| 427 | annotation(__OpenModelica_Interface="nbackend"); | ||
| 428 | end NBCausalize; | ||
| 429 |