Skip to content

Commit 5d74555

Browse files
authored
[NB] update for-when nesting (#10922)
* [NB] update for-when nesting - have size instead of type at for equation - correctly determine this size - correctly set empty attributes at size 0 when equations - add more debugging output for causalization failures * [NF] fix range size computation * [NF] even better range size computation * [NB] add missing boolean output
1 parent 654c4cf commit 5d74555

File tree

8 files changed

+123
-92
lines changed

8 files changed

+123
-92
lines changed

OMCompiler/Compiler/NBackEnd/Classes/NBEquation.mo

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ public
643643
end IF_EQUATION;
644644

645645
record FOR_EQUATION
646-
Type ty "equality type containing dimensions";
646+
Integer size "size of equation";
647647
Iterator iter "list of all: <iterator, range>";
648648
list<Equation> body "iterated equations (only multiples if entwined)";
649649
DAE.ElementSource source "origin of equation";
@@ -721,21 +721,23 @@ public
721721

722722
function size
723723
input Pointer<Equation> eqn_ptr;
724-
output Integer size;
724+
output Integer s;
725725
protected
726726
Equation eqn;
727727
algorithm
728728
eqn := Pointer.access(eqn_ptr);
729-
size := match eqn
730-
case SCALAR_EQUATION() then 1;
731-
case ARRAY_EQUATION() then Type.sizeOf(eqn.ty);
732-
case RECORD_EQUATION() then Type.sizeOf(eqn.ty);
733-
case ALGORITHM() then eqn.size;
734-
case IF_EQUATION() then eqn.size;
735-
case FOR_EQUATION() then Type.sizeOf(eqn.ty); //probably wrong
736-
case WHEN_EQUATION() then eqn.size;
737-
case AUX_EQUATION() then Variable.size(Pointer.access(eqn.auxiliary));
738-
case DUMMY_EQUATION() then 0;
729+
s := match eqn
730+
local
731+
Equation body;
732+
case SCALAR_EQUATION() then 1;
733+
case ARRAY_EQUATION() then Type.sizeOf(eqn.ty);
734+
case RECORD_EQUATION() then Type.sizeOf(eqn.ty);
735+
case ALGORITHM() then eqn.size;
736+
case IF_EQUATION() then eqn.size;
737+
case FOR_EQUATION(body = {body}) then eqn.size;
738+
case WHEN_EQUATION() then eqn.size;
739+
case AUX_EQUATION() then Variable.size(Pointer.access(eqn.auxiliary));
740+
case DUMMY_EQUATION() then 0;
739741
else algorithm
740742
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for:\n" + toString(eqn)});
741743
then fail();
@@ -846,7 +848,7 @@ public
846848
end if;
847849
else
848850
e := FOR_EQUATION(
849-
ty = ComponentRef.nodeType(lhs),
851+
size = ComponentRef.size(lhs),
850852
iter = Iterator.fromFrames(frames),
851853
body = {SCALAR_EQUATION(ty, Expression.fromCref(lhs), rhs, DAE.emptyElementSource, attr)}, // this can also be an array?
852854
source = DAE.emptyElementSource,
@@ -1475,7 +1477,6 @@ public
14751477
case SCALAR_EQUATION() then eq.ty;
14761478
case ARRAY_EQUATION() then eq.ty;
14771479
case RECORD_EQUATION() then eq.ty;
1478-
case FOR_EQUATION() then eq.ty;
14791480
else Type.REAL(); // TODO: WRONG there should not be an else case
14801481
end match;
14811482
end getType;
@@ -1698,7 +1699,7 @@ public
16981699
lhs := Expression.fromCref(ComponentRef.mergeSubscripts(subs, var.name, true, true));
16991700
eqn := Equation.fromLHSandRHS(lhs, rhs, idx, context, eqnAttr);
17001701
eqn := Pointer.create(Equation.FOR_EQUATION(
1701-
ty = ComponentRef.getSubscriptedType(var.name),
1702+
size = ComponentRef.size(var.name),
17021703
iter = iter,
17031704
body = {Pointer.access(eqn)},
17041705
source = DAE.emptyElementSource,
@@ -1719,7 +1720,7 @@ public
17191720
case FOR_EQUATION() algorithm
17201721
(body, acc) := mergeIterators(List.first(eq.body), false);
17211722
acc := eq.iter :: acc;
1722-
then (if top_level then Equation.FOR_EQUATION(eq.ty, Iterator.merge(acc), {body}, eq.source, eq.attr) else body, acc);
1723+
then (if top_level then Equation.FOR_EQUATION(eq.size, Iterator.merge(acc), {body}, eq.source, eq.attr) else body, acc);
17231724
else (eq, {});
17241725
end match;
17251726
end mergeIterators;
@@ -1737,7 +1738,7 @@ public
17371738
iterators := Iterator.split(eqn.iter);
17381739
body := List.first(eqn.body);
17391740
for iter in iterators loop
1740-
body := Equation.FOR_EQUATION(eqn.ty, iter, {body}, eqn.source, eqn.attr);
1741+
body := Equation.FOR_EQUATION(eqn.size, iter, {body}, eqn.source, eqn.attr);
17411742
end for;
17421743
then body;
17431744
else eqn;
@@ -1790,25 +1791,25 @@ public
17901791
(intersection, (rest1_left, rest1_right), (rest2_left, rest2_right)) := Iterator.intersect(eqn1.iter, eqn2.iter);
17911792
tmp := {};
17921793
if not Iterator.isEmpty(rest1_left) then
1793-
tmp := FOR_EQUATION(eqn1.ty, rest1_left, eqn1.body, eqn1.source, eqn1.attr) :: tmp;
1794+
tmp := FOR_EQUATION(eqn1.size, rest1_left, eqn1.body, eqn1.source, eqn1.attr) :: tmp;
17941795
end if;
17951796
if not Iterator.isEmpty(rest2_left) then
1796-
tmp := FOR_EQUATION(eqn2.ty, rest2_left, eqn2.body, eqn2.source, eqn2.attr) :: tmp;
1797+
tmp := FOR_EQUATION(eqn2.size, rest2_left, eqn2.body, eqn2.source, eqn2.attr) :: tmp;
17971798
end if;
17981799
if not Iterator.isEmpty(intersection) then
17991800
tmp := FOR_EQUATION(
1800-
ty = eqn1.ty,
1801+
size = eqn1.size,
18011802
iter = intersection,
18021803
body = entwine(listAppend(eqn1.body, eqn2.body), nesting_level + 1),
18031804
source = eqn1.source,
18041805
attr = eqn1.attr
18051806
) :: tmp;
18061807
end if;
18071808
if not Iterator.isEmpty(rest1_right) then
1808-
tmp := FOR_EQUATION(eqn1.ty, rest1_right, eqn1.body, eqn1.source, eqn1.attr) :: tmp;
1809+
tmp := FOR_EQUATION(eqn1.size, rest1_right, eqn1.body, eqn1.source, eqn1.attr) :: tmp;
18091810
end if;
18101811
if not Iterator.isEmpty(rest2_right) then
1811-
tmp := FOR_EQUATION(eqn2.ty, rest2_right, eqn2.body, eqn2.source, eqn2.attr) :: tmp;
1812+
tmp := FOR_EQUATION(eqn2.size, rest2_right, eqn2.body, eqn2.source, eqn2.attr) :: tmp;
18121813
end if;
18131814
// there has to be at least one equation
18141815
next :: tmp := tmp;
@@ -1858,7 +1859,8 @@ public
18581859
UnorderedMap<ComponentRef, Expression> replacements, removed_diagonals;
18591860
list<tuple<ComponentRef, Expression>> removed_diagonals_linear_maps;
18601861
Expression condition;
1861-
Type ty;
1862+
Integer size;
1863+
Iterator iter;
18621864

18631865
// empty index list indicates no slicing and no rearranging
18641866
case _ guard(listEmpty(indices)) then (Pointer.create(eqn), SlicingStatus.UNCHANGED, NBSolve.Status.EXPLICIT);
@@ -1904,7 +1906,7 @@ public
19041906

19051907
// solve the body equation for the cref if needed
19061908
// ToDo: act on solving status not equal to EXPLICIT ?
1907-
(body_lst, ty) := match cref_opt
1909+
body_lst := match cref_opt
19081910
local
19091911
ComponentRef cref;
19101912
case SOME(cref) algorithm
@@ -1932,18 +1934,16 @@ public
19321934
attr = eqn.attr
19331935
);
19341936
end if;
1935-
then ({body}, ComponentRef.getSubscriptedType(cref, true));
1937+
then {body};
19361938

1937-
// might be incorrect if the frames are not the last array dimensions
1938-
else (eqn.body, Type.unliftArrayN(listLength(frames), eqn.ty));
1939+
else eqn.body;
19391940
end match;
19401941

1941-
1942-
dims := list(Dimension.fromRange(Util.tuple22(frame)) for frame in frames);
1943-
ty := Type.liftArrayLeftList(ty, dims);
1942+
iter := Iterator.fromFrames(frames);
1943+
size := Iterator.size(iter) * sum(Equation.size(Pointer.create(eq)) for eq in body_lst);
19441944
sliced := FOR_EQUATION(
1945-
ty = ty,
1946-
iter = Iterator.fromFrames(frames),
1945+
size = size,
1946+
iter = iter,
19471947
body = body_lst,
19481948
source = eqn.source,
19491949
attr = eqn.attr

OMCompiler/Compiler/NBackEnd/Classes/NBackendDAE.mo

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ protected
753753
for body_elem_ptr in new_body loop
754754
body_elem := Pointer.access(body_elem_ptr);
755755
body_elem := BEquation.FOR_EQUATION(
756-
ty = Type.liftArrayLeftList(Equation.getType(body_elem), {Dimension.fromRange(range)}),
756+
size = Expression.rangeSize(range) * Equation.size(body_elem_ptr),
757757
iter = Iterator.SINGLE(iterator, range),
758758
body = {body_elem},
759759
source = frontend_equation.source,
@@ -935,10 +935,14 @@ protected
935935
case FEquation.WHEN(branches = branches, source = source)
936936
algorithm
937937
// When equation inside initial actually not allowed. Throw error?
938-
attr := EquationAttributes.default(EquationKind.DISCRETE, init);
939938
SOME(whenEqBody) := lowerWhenEquationBody(branches);
940939
bodies := BEquation.WhenEquationBody.split(whenEqBody);
941-
then list(Pointer.create(BEquation.WHEN_EQUATION(BEquation.WhenEquationBody.size(b), b, source, attr)) for b in bodies);
940+
then list(Pointer.create(BEquation.WHEN_EQUATION(
941+
size = BEquation.WhenEquationBody.size(b),
942+
body = b,
943+
source = source,
944+
attr = EquationAttributes.default(if BEquation.WhenEquationBody.size(b) > 0 then EquationKind.DISCRETE else EquationKind.EMPTY, init)
945+
)) for b in bodies);
942946

943947
case FEquation.ASSERT(condition = condition, message = message, level = level, source = source)
944948
algorithm

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,13 +405,20 @@ public
405405
output Matrix adj;
406406
input output Option<FunctionTree> funcTree = NONE() "only needed for LINEAR without existing derivatives";
407407
algorithm
408-
(adj, funcTree) := match ty
409-
case MatrixType.ARRAY then createArray(vars, eqns, st, funcTree);
410-
case MatrixType.PSEUDO then createPseudo(vars, eqns, st, funcTree);
411-
else algorithm
412-
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unknown adjacency matrix type."});
413-
then fail();
414-
end match;
408+
try
409+
(adj, funcTree) := match ty
410+
case MatrixType.ARRAY then createArray(vars, eqns, st, funcTree);
411+
case MatrixType.PSEUDO then createPseudo(vars, eqns, st, funcTree);
412+
else algorithm
413+
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unknown adjacency matrix type."});
414+
then fail();
415+
end match;
416+
else
417+
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed to create adjacency matrix for system:\n"
418+
+ VariablePointers.toString(vars, "system vars") + "\n"
419+
+ EquationPointers.toString(eqns, "system eqns")});
420+
fail();
421+
end try;
415422
end create;
416423

417424
function update

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,15 @@ public
135135
Boolean changed;
136136
algorithm
137137
// 1. match the system
138-
(matching, marked_eqns, mapping, matrixType, matrixStrictness) := continue_(matching, adj, transposed, clear);
138+
try
139+
(matching, marked_eqns, mapping, matrixType, matrixStrictness) := continue_(matching, adj, transposed, clear);
140+
else
141+
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed to match system:\n"
142+
+ VariablePointers.toString(vars, "system vars") + "\n"
143+
+ EquationPointers.toString(eqns, "system eqns") + "\n"
144+
+ Adjacency.Matrix.toString(adj)});
145+
fail();
146+
end try;
139147

140148
// 2. Resolve singular systems if necessary
141149
changed := match systemType

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -253,18 +253,27 @@ public
253253
extends Module.resolveSingularitiesInterface;
254254
input Matching matching;
255255
protected
256-
list<Slice<VariablePointer>> unmatched_vars;
257-
list<Slice<EquationPointer>> unmatched_eqns;
256+
list<Slice<VariablePointer>> unmatched_vars, matched_vars;
257+
list<Slice<EquationPointer>> unmatched_eqns, matched_eqns;
258+
String err_str;
258259
algorithm
259-
(_, unmatched_vars, _, unmatched_eqns) := Matching.getMatches(matching, mapping_opt, variables, equations);
260+
(matched_vars, unmatched_vars, matched_eqns, unmatched_eqns) := Matching.getMatches(matching, mapping_opt, variables, equations);
260261
if not listEmpty(unmatched_vars) then
261-
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName()
262-
+ " failed because following variables could not be solved:\n"
263-
+ List.toString(unmatched_vars, function Slice.toString(func=BVariable.pointerToString, maxLength=0), "", "\t", "\n\t", "\n", true)
264-
+ "\n Furthermore following equations are unmatched:\n"
265-
+ List.toString(unmatched_eqns, function Slice.toString(func=function Equation.pointerToString(str=""), maxLength=0), "", "\t", "\n\t", "\n", true)});
262+
err_str := getInstanceName()
263+
+ " failed.\n" + StringUtil.headline_4("(" + intString(listLength(unmatched_vars)) + ") Unmatched Variables")
264+
+ List.toString(unmatched_vars, function Slice.toString(func=BVariable.pointerToString, maxLength=10), "", "\t", "\n\t", "\n", true) + "\n"
265+
+ StringUtil.headline_4("(" + intString(listLength(unmatched_eqns)) + ") Unmatched Equations")
266+
+ List.toString(unmatched_eqns, function Slice.toString(func=function Equation.pointerToString(str=""), maxLength=10), "", "\t", "\n\t", "\n", true) + "\n";
267+
if Flags.isSet(Flags.BLT_DUMP) then
268+
err_str := err_str + " \n" + StringUtil.headline_4("(" + intString(listLength(matched_vars)) + ") Matched Variables")
269+
+ List.toString(matched_vars, function Slice.toString(func=BVariable.pointerToString, maxLength=10), "", "\t", "\n\t", "\n", true) + "\n"
270+
+ StringUtil.headline_4("(" + intString(listLength(matched_eqns)) + ") Matched Equations")
271+
+ List.toString(matched_eqns, function Slice.toString(func=function Equation.pointerToString(str=""), maxLength=10), "", "\t", "\n\t", "\n", true) + "\n";
272+
end if;
273+
Error.addMessage(Error.INTERNAL_ERROR,{err_str});
266274
fail();
267275
end if;
276+
changed := false;
268277
end noIndexReduction;
269278

270279
function balanceInitialization

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

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -209,40 +209,48 @@ public
209209
input EquationPointers eqns;
210210
output list<StrongComponent> comps = {};
211211
algorithm
212-
comps := match adj
213-
local
214-
list<list<Integer>> comps_indices, phase2_indices;
215-
PseudoBucket bucket;
216-
Option<StrongComponent> comp_opt;
217-
Adjacency.Matrix phase2_adj;
218-
Matching phase2_matching;
219-
array<SuperNode> super_nodes;
220-
221-
case Adjacency.Matrix.PSEUDO_ARRAY_ADJACENCY_MATRIX() algorithm
222-
bucket := PseudoBucket.create(matching.eqn_to_var, adj.mapping, adj.modes);
223-
comps_indices := tarjanScalar(adj.m, matching.var_to_eqn, matching.eqn_to_var);
224-
225-
// phase 2 tarjan
226-
(phase2_adj, phase2_matching, super_nodes) := SuperNode.create(adj, matching, comps_indices, bucket);
227-
228-
// kabdelhak: this match-statement is superfluous, SuperNode.create always returns these types.
229-
// it is just safer if something is changed in the future
230-
() := match phase2_adj
231-
case Adjacency.Matrix.PSEUDO_ARRAY_ADJACENCY_MATRIX() algorithm
232-
phase2_indices := tarjanScalar(phase2_adj.m, phase2_matching.var_to_eqn, phase2_matching.eqn_to_var);
233-
comps := list(SuperNode.collapse(comp, super_nodes, adj.m, adj.mapping, adj.modes, matching.var_to_eqn, matching.eqn_to_var, vars, eqns) for comp in phase2_indices);
234-
then ();
235-
236-
else algorithm
237-
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unknown adjacency matrix or matching type."});
238-
then fail();
239-
end match;
240-
then comps;
241-
242-
else algorithm
243-
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because adjacency matrix has unknown type."});
244-
then fail();
245-
end match;
212+
try
213+
comps := match adj
214+
local
215+
list<list<Integer>> comps_indices, phase2_indices;
216+
PseudoBucket bucket;
217+
Option<StrongComponent> comp_opt;
218+
Adjacency.Matrix phase2_adj;
219+
Matching phase2_matching;
220+
array<SuperNode> super_nodes;
221+
222+
case Adjacency.Matrix.PSEUDO_ARRAY_ADJACENCY_MATRIX() algorithm
223+
bucket := PseudoBucket.create(matching.eqn_to_var, adj.mapping, adj.modes);
224+
comps_indices := tarjanScalar(adj.m, matching.var_to_eqn, matching.eqn_to_var);
225+
226+
// phase 2 tarjan
227+
(phase2_adj, phase2_matching, super_nodes) := SuperNode.create(adj, matching, comps_indices, bucket);
228+
229+
// kabdelhak: this match-statement is superfluous, SuperNode.create always returns these types.
230+
// it is just safer if something is changed in the future
231+
() := match phase2_adj
232+
case Adjacency.Matrix.PSEUDO_ARRAY_ADJACENCY_MATRIX() algorithm
233+
phase2_indices := tarjanScalar(phase2_adj.m, phase2_matching.var_to_eqn, phase2_matching.eqn_to_var);
234+
comps := list(SuperNode.collapse(comp, super_nodes, adj.m, adj.mapping, adj.modes, matching.var_to_eqn, matching.eqn_to_var, vars, eqns) for comp in phase2_indices);
235+
then ();
236+
237+
else algorithm
238+
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because of unknown adjacency matrix or matching type."});
239+
then fail();
240+
end match;
241+
then comps;
242+
243+
else algorithm
244+
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because adjacency matrix has unknown type."});
245+
then fail();
246+
end match;
247+
else
248+
Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed to sort system:\n"
249+
+ VariablePointers.toString(vars, "system vars") + "\n"
250+
+ EquationPointers.toString(eqns, "system eqns") + "\n"
251+
+ Matching.toString(matching)});
252+
fail();
253+
end try;
246254
end tarjan;
247255

248256
function tarjanScalar

OMCompiler/Compiler/NBackEnd/Util/NBDifferentiate.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ public
287287
forBody := body_eqn :: forBody;
288288
end for;
289289
attr := differentiateEquationAttributes(eq.attr, diffArguments);
290-
then (Equation.FOR_EQUATION(eq.ty, eq.iter, listReverse(forBody), eq.source, attr), diffArguments);
290+
then (Equation.FOR_EQUATION(eq.size, eq.iter, listReverse(forBody), eq.source, attr), diffArguments);
291291

292292
case Equation.WHEN_EQUATION() algorithm
293293
(whenBody, diffArguments) := differentiateWhenEquationBody(eq.body, diffArguments);

OMCompiler/Compiler/NFFrontEnd/NFExpression.mo

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,12 +1120,7 @@ public
11201120

11211121
function rangeSize
11221122
input Expression range "has to be RANGE()!";
1123-
output Integer size;
1124-
protected
1125-
Integer start, step, stop;
1126-
algorithm
1127-
(start, step, stop) := getIntegerRange(range);
1128-
size := realInt((stop - start + 1) / step);
1123+
output Integer size = Dimension.size(Type.nthDimension(typeOf(range), 1));
11291124
end rangeSize;
11301125

11311126
function applySubscripts

0 commit comments

Comments
 (0)