Skip to content

Commit 23ecc5d

Browse files
authored
[NB] update DAE mode jacobians (#14137)
* [NB] update DAE mode jacobians - update pipeline to only do required DAE mode jacobians and not ODE jacobians - update pipeline to do modules in DAE mode and remove them from the main DAE module - remove empty partitions from DAE mode (full discrete) - when differentiating algebraic loops for jacobians they are known to be linear - [SimCode] use correct DAE mode jacobian instead of ODE jacobian - [NB] add missing DAEMode residual variable checks - works towards #13980
1 parent 289a404 commit 23ecc5d

File tree

9 files changed

+58
-28
lines changed

9 files changed

+58
-28
lines changed

OMCompiler/Compiler/NBackEnd/Classes/NBackendDAE.mo

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ public
267267
list<String> followEquations = Flags.getConfigStringList(Flags.DEBUG_FOLLOW_EQUATIONS);
268268
Option<UnorderedSet<String>> eq_filter_opt;
269269
list<DAE.InlineType> inline_types = {DAE.NORM_INLINE(), DAE.BUILTIN_EARLY_INLINE(), DAE.EARLY_INLINE(), DAE.DEFAULT_INLINE()};
270+
NBPartition.Kind kind;
270271
algorithm
271272
// if we filter dump for equations
272273
if listEmpty(followEquations) then
@@ -292,10 +293,13 @@ public
292293

293294
if Flags.getConfigBool(Flags.DAE_MODE) then
294295
mainModules := {(DAEMode.main, "DAE-Mode")};
296+
kind := NBPartition.Kind.DAE;
295297
else
296298
mainModules := {};
299+
kind := NBPartition.Kind.ODE;
297300
end if;
298301

302+
// all main modules are always done in ODE mode
299303
mainModules := listAppend({
300304
(function Partitioning.main(kind = NBPartition.Kind.ODE), "Partitioning"),
301305
(function Causalize.main(kind = NBPartition.Kind.ODE), "Causalize"),
@@ -307,10 +311,10 @@ public
307311
// (do not change order SOLVE -> JACOBIAN)
308312
postOptModules := {
309313
(Evaluation.removeDummies, "Remove Dummies"),
310-
(function Tearing.main(kind = NBPartition.Kind.ODE), "Tearing"),
311-
(Partitioning.categorize, "Categorize"),
312-
(Solve.main, "Solve"),
313-
(function Jacobian.main(kind = NBPartition.Kind.ODE), "Jacobian")
314+
(function Tearing.main(kind = kind), "Tearing"),
315+
(Partitioning.categorize, "Categorize"),
316+
(Solve.main, "Solve"),
317+
(function Jacobian.main(kind = kind), "Jacobian")
314318
};
315319

316320
(bdae, preOptClocks) := applyModules(bdae, preOptModules, eq_filter_opt, ClockIndexes.RT_CLOCK_NEW_BACKEND_MODULE);

OMCompiler/Compiler/NBackEnd/Modules/1_Main/NBDAEMode.mo

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,8 @@ public
7575
then fail();
7676
end match;
7777

78-
// Modules
78+
// fake causalize system to fulfill pipeline requirements
7979
bdae := Causalize.main(bdae, NBPartition.Kind.DAE);
80-
bdae := Tearing.main(bdae, NBPartition.Kind.DAE);
81-
bdae := Jacobian.main(bdae, NBPartition.Kind.DAE);
8280
else
8381
Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
8482
end try;
@@ -130,7 +128,7 @@ protected
130128
// remove strong components
131129
part.strongComponents := NONE();
132130
// accumulate new partitions
133-
then part :: new_partitions;
131+
then if Partition.Partition.isEmpty(part) then new_partitions else part :: new_partitions;
134132
else new_partitions;
135133
end match;
136134
end for;

OMCompiler/Compiler/NBackEnd/Modules/3_Post/NBJacobian.mo

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public
137137
() := match kind
138138
case NBPartition.Kind.ODE algorithm bdae.ode := newPartitions; then ();
139139
case NBPartition.Kind.DAE algorithm bdae.dae := SOME(newPartitions); then ();
140+
else ();
140141
end match;
141142
bdae.ode_event := newEvents;
142143
bdae.funcTree := funcTree;
@@ -421,7 +422,7 @@ public
421422
// create row-wise sparsity pattern
422423
for cref in listReverse(partial_vars) loop
423424
// only create rows for derivatives
424-
if jacType == JacobianType.NLS or BVariable.checkCref(cref, BVariable.isStateDerivative) then
425+
if jacType == JacobianType.NLS or BVariable.checkCref(cref, BVariable.isStateDerivative) or BVariable.checkCref(cref, BVariable.isResidual) then
425426
if UnorderedMap.contains(cref, map) then
426427
tmp := UnorderedSet.unique_list(UnorderedMap.getOrFail(cref, map), ComponentRef.hash, ComponentRef.isEqual);
427428
rows := (cref, tmp) :: rows;
@@ -539,7 +540,8 @@ public
539540
if jacType == JacobianType.NLS then
540541
partials := listArray(sparsityPattern.partial_vars);
541542
else
542-
partials := listArray(list(cref for cref guard(BVariable.checkCref(cref, BVariable.isStateDerivative)) in sparsityPattern.partial_vars));
543+
partials := listArray(list(cref for cref guard(BVariable.checkCref(cref, BVariable.isStateDerivative) or
544+
BVariable.checkCref(cref, BVariable.isResidual)) in sparsityPattern.partial_vars));
543545
end if;
544546

545547
// create cref -> index maps
@@ -674,17 +676,23 @@ protected
674676
input String name "Context name for jacobian";
675677
input Module.jacobianInterface func;
676678
protected
679+
JacobianType jacType;
680+
VariablePointers unknowns;
677681
list<Pointer<Variable>> derivative_vars, state_vars;
678682
VariablePointers seedCandidates, partialCandidates;
679683
Option<Jacobian> jacobian "Resulting jacobian";
680684
Partition.Kind kind = Partition.Partition.getKind(part);
681685
algorithm
682686
partialCandidates := part.unknowns;
683-
derivative_vars := list(var for var guard(BVariable.isStateDerivative(var)) in VariablePointers.toList(part.unknowns));
687+
unknowns := if Partition.Partition.getKind(part) == NBPartition.Kind.DAE then Util.getOption(part.daeUnknowns) else part.unknowns;
688+
jacType := if Partition.Partition.getKind(part) == NBPartition.Kind.DAE then JacobianType.DAE else JacobianType.ODE;
689+
690+
derivative_vars := list(var for var guard(BVariable.isStateDerivative(var)) in VariablePointers.toList(unknowns));
684691
state_vars := list(Util.getOption(BVariable.getVarState(var)) for var in derivative_vars);
685692
seedCandidates := VariablePointers.fromList(state_vars, partialCandidates.scalarized);
686693

687-
(jacobian, funcTree) := func(name, JacobianType.ODE, seedCandidates, partialCandidates, part.equations, knowns, part.strongComponents, funcTree, kind == NBPartition.Kind.INI);
694+
(jacobian, funcTree) := func(name, jacType, seedCandidates, partialCandidates, part.equations, knowns, part.strongComponents, funcTree, kind == NBPartition.Kind.INI);
695+
688696
part.association := Partition.Association.CONTINUOUS(kind, jacobian);
689697
if Flags.isSet(Flags.JAC_DUMP) then
690698
print(Partition.Partition.toString(part, 2));
@@ -821,14 +829,14 @@ protected
821829
end jacobianNone;
822830

823831
function getTmpFilterFunction
824-
" - ODE/DAE filter by state derivative / algebraic
825-
- LS/NLS filter by residual / inner"
832+
" - ODE filter by state derivative / algebraic
833+
- LS/NLS/DAE filter by residual / inner"
826834
input JacobianType jacType;
827835
output BVariable.checkVar func;
828836
algorithm
829837
func := match jacType
830838
case JacobianType.ODE then BVariable.isStateDerivative;
831-
case JacobianType.DAE then BVariable.isStateDerivative;
839+
case JacobianType.DAE then BVariable.isResidual;
832840
case JacobianType.LS then BVariable.isResidual;
833841
case JacobianType.NLS then BVariable.isResidual;
834842
else algorithm

OMCompiler/Compiler/NBackEnd/Modules/3_Post/NBTearing.mo

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,9 @@ public
149149
(partitions, funcTree) := tearingTraverser(partitions, funcs, funcTree, eq_index, kind);
150150
bdae.dae := SOME(partitions);
151151
bdae.funcTree := funcTree;
152-
then bdae;
152+
// recursively call this function to also apply to the ODE section (used for events)
153+
// ToDo: only create event partitions, disregard rest
154+
then main(bdae, NBPartition.Kind.ODE);
153155

154156
// ToDo: all the other cases: e.g. Jacobian, Hessian
155157
end match;

OMCompiler/Compiler/NBackEnd/Modules/NBModule.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ public
272272
[!] This function can not only be used as an optimization module but also for
273273
nonlinear partitions, state sets, linearization and dynamic optimization."
274274
input String name "Name of jacobian";
275-
input JacobianType jacType "Type of jacobian (sim/nonlin)";
275+
input JacobianType jacType "Type of jacobian (ode/dae/lin/nonlin)";
276276
input VariablePointers seedCandidates "differentiate by these";
277277
input VariablePointers partialCandidates "solve the equations for these";
278278
input EquationPointers equations "Equations array";

OMCompiler/Compiler/NBackEnd/Util/NBDifferentiate.mo

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ public
182182
DifferentiationArguments diffArguments;
183183
Tearing strict;
184184
Option<Tearing> casual;
185+
Boolean linear;
185186

186187
case StrongComponent.SINGLE_COMPONENT() algorithm
187188
new_var := differentiateVariablePointer(comp.var, diffArguments_ptr);
@@ -221,7 +222,9 @@ public
221222
case StrongComponent.ALGEBRAIC_LOOP() algorithm
222223
strict := differentiateTearing(comp.strict, diffArguments_ptr, idx, context, name);
223224
casual := Util.applyOption(comp.casual, function differentiateTearing(diffArguments_ptr=diffArguments_ptr, idx=idx, context=context, name=name));
224-
then StrongComponent.ALGEBRAIC_LOOP(-1, strict, casual, comp.linear, false, comp.homotopy, comp.status);
225+
// if we differentiate for jacobian, the algebraic loops will always be linear
226+
linear := match Pointer.access(diffArguments_ptr) case DIFFERENTIATION_ARGUMENTS(diffType = NBDifferentiate.DifferentiationType.JACOBIAN) then true; else comp.linear; end match;
227+
then StrongComponent.ALGEBRAIC_LOOP(-1, strict, casual, linear, false, comp.homotopy, comp.status);
225228

226229
case StrongComponent.ENTWINED_COMPONENT() algorithm
227230
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " not implemented for entwined equation:\n" + StrongComponent.toString(comp)});

OMCompiler/Compiler/NSimCode/NSimCode.mo

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -406,15 +406,11 @@ public
406406

407407
(linearLoops, nonlinearLoops, jacobians, simCodeIndices) := collectAlgebraicLoops(init, init_0, ode, algebraic, daeModeData, simCodeIndices, simcode_map);
408408

409-
for jac in jacobians loop
410-
if Util.isSome(jac.jac_map) then
411-
vars := SimVars.addSeedAndJacobianVars(vars, UnorderedMap.toList(Util.getOption(jac.jac_map)));
412-
end if;
413-
end for;
414-
415-
(jacA, simCodeIndices) := SimJacobian.createSimulationJacobian(bdae.ode, bdae.ode_event, simCodeIndices, simcode_map);
416409
if isSome(daeModeData) then
410+
(jacA, simCodeIndices) := SimJacobian.createSimulationJacobian(Util.getOption(bdae.dae), simCodeIndices, simcode_map);
417411
daeModeData := DaeModeData.addJacobian(daeModeData, jacA);
412+
else
413+
(jacA, simCodeIndices) := SimJacobian.createSimulationJacobian(listAppend(bdae.ode, bdae.ode_event), simCodeIndices, simcode_map);
418414
end if;
419415

420416
(jacB, simCodeIndices) := SimJacobian.empty("B", simCodeIndices);
@@ -424,6 +420,13 @@ public
424420
(jacH, simCodeIndices) := SimJacobian.empty("H", simCodeIndices);
425421
//jacobians := jacA :: jacB :: jacC :: jacD :: jacF :: jacobians;
426422
jacobians := listReverse(jacH :: jacF :: jacD :: jacC :: jacB :: jacA :: jacobians);
423+
424+
for jac in jacobians loop
425+
if Util.isSome(jac.jac_map) then
426+
vars := SimVars.addSeedAndJacobianVars(vars, UnorderedMap.toList(Util.getOption(jac.jac_map)));
427+
end if;
428+
end for;
429+
427430
// jacobian blocks only from simulation jacobians
428431
jac_blocks := SimJacobian.getJacobiansBlocks({jacA, jacB, jacC, jacD, jacF, jacH});
429432
(jac_blocks, simCodeIndices) := SimStrongComponent.Block.fixIndices(jac_blocks, {}, simCodeIndices);

OMCompiler/Compiler/NSimCode/NSimJacobian.mo

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,16 @@ public
276276
UnorderedMap.add(cref, var.index, idx_map);
277277
end if;
278278
end for;
279+
280+
// also add residuals if its DAE Mode
281+
if jacobian.jacType == NBJacobian.JacobianType.DAE then
282+
for var in resVars loop
283+
cref := SimVar.getName(var);
284+
UnorderedMap.add(cref, var.index, idx_map);
285+
//cref := BVariable.getPartnerCref(cref, BVariable.getVarPDer);
286+
//UnorderedMap.add(cref, var.index, idx_map);
287+
end for;
288+
end if;
279289
else
280290
for var in seedVars loop
281291
cref := SimVar.getName(var);
@@ -325,13 +335,11 @@ public
325335
end create;
326336

327337
function createSimulationJacobian
328-
input list<Partition.Partition> ode;
329-
input list<Partition.Partition> ode_event;
338+
input list<Partition.Partition> partitions;
330339
output SimJacobian simJac;
331340
input output SimCode.SimCodeIndices simCodeIndices;
332341
input UnorderedMap<ComponentRef, SimVar> simcode_map;
333342
protected
334-
list<Partition.Partition> partitions = listAppend(ode, ode_event);
335343
list<BackendDAE> jacobians = {};
336344
BackendDAE simJacobian;
337345
Option<SimJacobian> simJac_opt;

OMCompiler/Compiler/SimCode/SerializeModelInfo.mo

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,10 @@ algorithm
12671267
equation
12681268
File.write(file,"iteration variable for solving an algebraic loop");
12691269
then ();
1270+
case BackendDAE.DAE_RESIDUAL_VAR()
1271+
equation
1272+
File.write(file,"residual variable for dae mode");
1273+
then ();
12701274
else
12711275
equation
12721276
Error.addMessage(Error.INTERNAL_ERROR, {"serializeVarKind failed for " + SimCodeUtil.simVarString(var)});

0 commit comments

Comments
 (0)