Skip to content

Commit

Permalink
[BE] update algorithms discrete output variables
Browse files Browse the repository at this point in the history
- add all discrete output variables to the adjacency matrix
- update small spelling errors
- ticket #5659
- remove bug_2452_2 since it is not valid due to the specification,
  see discussion under ticket #5659 for further information
  • Loading branch information
kabdelhak authored and adrpo committed Oct 19, 2019
1 parent 023bac1 commit ac9e8ec
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 66 deletions.
1 change: 0 additions & 1 deletion .CI/compliance.failures
@@ -1,4 +1,3 @@
ModelicaCompliance.Algorithms.For.EnumRange
ModelicaCompliance.Algorithms.For.RealRange
ModelicaCompliance.Algorithms.For.ShadowedIterator
ModelicaCompliance.Algorithms.For.StringRange
Expand Down
53 changes: 39 additions & 14 deletions OMCompiler/Compiler/BackEnd/BackendDAETransform.mo
Expand Up @@ -150,12 +150,12 @@ protected function analyseStrongComponentsScalar "author: Frenkel TUD 2011-05
input array<Integer> markarray;
output BackendDAE.StrongComponents outComps = {};
protected
BackendDAE.StrongComponent acomp;
list<BackendDAE.StrongComponent> acomp;
Integer mark = imark;
algorithm
for comp in inComps loop
(acomp, mark) := analyseStrongComponentScalar(comp, syst, shared, inAss1, inAss2, mapEqnIncRow, mapIncRowEqn, mark, markarray);
outComps := acomp :: outComps;
outComps := listAppend(acomp,outComps);
end for;

outComps := Dangerous.listReverseInPlace(outComps);
Expand All @@ -171,7 +171,7 @@ protected function analyseStrongComponentScalar "author: Frenkel TUD 2011-05"
input array<Integer> mapIncRowEqn;
input Integer imark;
input array<Integer> markarray;
output BackendDAE.StrongComponent outComp;
output list<BackendDAE.StrongComponent> outComp;
output Integer omark = imark + 1;
protected
list<Integer> comp, vlst;
Expand All @@ -191,7 +191,7 @@ algorithm
comp := List.fold2(comp, uniqueComp, imark, markarray, {});
//comp = List.unique(comp);
eqn_lst := List.map1r(comp, BackendEquation.get, eqns);
outComp := analyseStrongComponentBlock(comp, eqn_lst, varlst, vlst, syst, shared);
outComp := analyseStrongComponentBlock(comp, eqn_lst, varlst, vlst, syst, shared, mapEqnIncRow);
else
Error.addInternalError("function analyseStrongComponentScalar failed", sourceInfo());
fail();
Expand All @@ -218,7 +218,8 @@ protected function analyseStrongComponentBlock "author: Frenkel TUD 2011-05"
input list<Integer> inVarindxLst;
input BackendDAE.EqSystem isyst;
input BackendDAE.Shared ishared;
output BackendDAE.StrongComponent outComp;
input array<list<Integer>> mapEqnIncRow;
output list<BackendDAE.StrongComponent> outComp;
algorithm
outComp := matchcontinue (inComp, inEqnLst, inVarLst, inVarindxLst)
local
Expand All @@ -242,9 +243,10 @@ algorithm
list<DAE.Exp> expLst;
list<String> slst;
Boolean jacConstant, mixedSystem, b1;
list<BackendDAE.StrongComponent> algorithmComp;

case (compelem::{}, BackendDAE.ALGORITHM()::{}, _, varindxs)
then BackendDAE.SINGLEALGORITHM(compelem, varindxs);
then {BackendDAE.SINGLEALGORITHM(compelem, varindxs)};

case (compelem::{}, BackendDAE.ARRAY_EQUATION()::{}, var_lst, varindxs) equation
crlst = List.map(var_lst,BackendVariable.varCref);
Expand All @@ -254,19 +256,19 @@ algorithm
expLst = List.map(crlst, Expression.crefExp);
true = List.exist1(inEqnLst,crefsAreArray,expLst);
end if;
then BackendDAE.SINGLEARRAY(compelem, varindxs);
then {BackendDAE.SINGLEARRAY(compelem, varindxs)};

case (compelem::{}, BackendDAE.IF_EQUATION()::{}, _, varindxs)
then BackendDAE.SINGLEIFEQUATION(compelem, varindxs);
then {BackendDAE.SINGLEIFEQUATION(compelem, varindxs)};

case (compelem::{}, BackendDAE.COMPLEX_EQUATION()::{}, _, varindxs)
then BackendDAE.SINGLECOMPLEXEQUATION(compelem, varindxs);
then {BackendDAE.SINGLECOMPLEXEQUATION(compelem, varindxs)};

case (compelem::{}, BackendDAE.WHEN_EQUATION()::{}, _, varindxs)
then BackendDAE.SINGLEWHENEQUATION(compelem, varindxs);
then {BackendDAE.SINGLEWHENEQUATION(compelem, varindxs)};

case (compelem::{}, _, _, v::{})
then BackendDAE.SINGLEEQUATION(compelem, v);
then {BackendDAE.SINGLEEQUATION(compelem, v)};

case (comp, eqn_lst, var_lst, varindxs) equation
//false = BackendVariable.hasDiscreteVar(var_lst); //lochel: mixed systems and non-linear systems are treated the same
Expand All @@ -293,12 +295,35 @@ algorithm
jac = NONE();
jac_tp = BackendDAE.JAC_NO_ANALYTIC();
end if;
then BackendDAE.EQUATIONSYSTEM(comp, varindxs, BackendDAE.FULL_JACOBIAN(jac), jac_tp, mixedSystem);

then {BackendDAE.EQUATIONSYSTEM(comp, varindxs, BackendDAE.FULL_JACOBIAN(jac), jac_tp, mixedSystem)};

/*
All algorithms - assume each can be solved for its matched variables.
Purely discrete algebraic loops are not solvable otherwise.
Related to ticket #5659
*/
case (comp, eqn_lst, var_lst, varindxs)
guard(BackendEquation.allAlgorithmsLst(eqn_lst))
algorithm
true := BackendVariable.hasDiscreteVar(var_lst);
false := BackendVariable.hasContinuousVar(var_lst);
BackendDAE.MATCHING(ass1, ass2, _) := isyst.matching;
algorithmComp := {};
for c in comp loop
indxdisc_var := {};
// get matched variables for each aglorithm
for j in mapEqnIncRow[c] loop
indxdisc_var := ass2[j] :: indxdisc_var;
end for;
algorithmComp := BackendDAE.SINGLEALGORITHM(c, indxdisc_var) :: algorithmComp;
end for;
then algorithmComp;

/* Purely discrete algebraic loops are not solvable. */
case (_, eqn_lst, var_lst, _) equation
true = BackendVariable.hasDiscreteVar(var_lst);
false = BackendVariable.hasContinuousVar(var_lst);
msg = getInstanceName() + " failed (Sorry - Support for Discrete Equation Systems is not yet implemented)\n";
msg = getInstanceName() + " failed (Purely discrete algebraic loops cannot be solved by iterative processes. Try to break them open using the delay() operator.)\n";
crlst = List.map(var_lst, BackendVariable.varCref);
slst = List.map(crlst, ComponentReference.printComponentRefStr);
msg = msg + stringDelimitList(slst, "\n");
Expand Down
63 changes: 56 additions & 7 deletions OMCompiler/Compiler/BackEnd/BackendDAEUtil.mo
Expand Up @@ -2568,6 +2568,9 @@ algorithm
list<BackendDAE.Equation> eqns;
BackendDAE.Equation eqn;
list<BackendDAE.WhenOperator> whenStmtLst;
list<DAE.ComponentRef> crefLst;
list<BackendDAE.Var> varslst;
list<Integer> p;

// EQUATION
case BackendDAE.EQUATION(exp = e1,scalar = e2)
Expand Down Expand Up @@ -2625,15 +2628,27 @@ algorithm
then
(res,size);

// ALGORITHM For now assume that algorithm will be solvable for
// correct variables. I.e. find all variables in algorithm and add to lst.
// If algorithm later on needs to be inverted, i.e. solved for
// different variables than calculated, a non linear solver or
// analysis of algorithm itself needs to be implemented.
// ALGORITHM
case BackendDAE.ALGORITHM(size=size,alg=DAE.ALGORITHM_STMTS(statementLst = statementLst))
equation
res = traverseStmts(statementLst, function incidenceRowAlgorithm(inVariables = vars,
algorithm
res := traverseStmts(statementLst, function incidenceRowAlgorithm(inVariables = vars,
functionTree = functionTree, inIndexType = inIndexType), iRow);
/*
If looking for solvability add all discrete output variables, even if they don't occur in the algorithm.
Discrete output variables that do not occur get computed by pre().
Ticket #5659
*/
if indexTypeSovable(inIndexType) then
try
crefLst := CheckModel.algorithmStatementListOutputs(statementLst, DAE.EXPAND()); // expand as we're in an algorithm
for cr in crefLst loop
(varslst, p) := BackendVariable.getVar(cr, vars);
res := incidenceRowExp1Discrete(varslst,p,res,0);
end for;
else
/* ... */
end try;
end if;
then
(res,size);

Expand Down Expand Up @@ -3203,6 +3218,7 @@ algorithm
end traversingincidenceRowExpFinder;

protected function incidenceRowExp1
"Adds an incidence matrix entry for all variables in the inVarLst."
input list<BackendDAE.Var> inVarLst;
input list<Integer> inIntegerLst;
input AvlSetInt.Tree inVarIndxLst;
Expand Down Expand Up @@ -3237,6 +3253,29 @@ algorithm
end match;
end incidenceRowExp1;

protected function incidenceRowExp1Discrete
"Adds an incidence matrix entry for all variables in the inVarLst, if they are discrete."
input list<BackendDAE.Var> inVarLst;
input list<Integer> inIntegerLst;
input AvlSetInt.Tree inVarIndxLst;
input Integer diffindex;
output AvlSetInt.Tree outVarIndxLst;
algorithm
outVarIndxLst := match (inVarLst,inIntegerLst,inVarIndxLst,diffindex)
local
list<BackendDAE.Var> rest;
list<Integer> irest;
AvlSetInt.Tree vars;
Integer i,i1,diffidx;
Boolean b;
case ({},{},vars,_) then vars;
case (BackendDAE.VAR(varKind = BackendDAE.DISCRETE())::rest,i::irest,_,_)
equation
vars = AvlSetInt.add(inVarIndxLst, i);
then incidenceRowExp1Discrete(rest,irest,vars,diffindex);
end match;
end incidenceRowExp1Discrete;

public function traversingincidenceRowExpFinderwithInput "Helper for statesAndVarsExp"
input DAE.Exp inExp;
input tuple<BackendDAE.Variables,AvlSetInt.Tree> inTpl;
Expand Down Expand Up @@ -9919,5 +9958,15 @@ algorithm
end match;
end containsHomotopyCall2;

protected function indexTypeSovable
input BackendDAE.IndexType indexType;
output Boolean b;
algorithm
b := match indexType
case BackendDAE.SOLVABLE() then true;
else false;
end match;
end indexTypeSovable;

annotation(__OpenModelica_Interface="backend");
end BackendDAEUtil;
15 changes: 15 additions & 0 deletions OMCompiler/Compiler/BackEnd/BackendEquation.mo
Expand Up @@ -3196,5 +3196,20 @@ algorithm
end match;
end scalarComplexEquations;

public function allAlgorithmsLst
input list<BackendDAE.Equation> eqn_lst;
output Boolean b;
algorithm
b := match eqn_lst
local
list<BackendDAE.Equation> rest;
case {} then true;
case BackendDAE.ALGORITHM()::{} then true;
case BackendDAE.ALGORITHM()::rest then allAlgorithmsLst(rest);
else false;
end match;
end allAlgorithmsLst;


annotation(__OpenModelica_Interface="backend");
end BackendEquation;
10 changes: 5 additions & 5 deletions OMCompiler/Compiler/BackEnd/IndexReduction.mo
Expand Up @@ -432,7 +432,7 @@ algorithm
// Failure
case (_, {}, (_, _, _, mapIncRowEqn, _)) equation
if Flags.isSet(Flags.BLT_DUMP) then
print("Reduce Index failed! Found empty set of continues equations.\nmarked equations:\n");
print("Reduce Index failed! Found empty set of continuous equations.\nmarked equations:\n");
end if;
// get from scalar eqns indexes the indexes in the equation array
eqns1 = List.map1r(eqns, arrayGet, mapIncRowEqn);
Expand All @@ -444,12 +444,12 @@ algorithm
if Flags.isSet(Flags.BLT_DUMP) then
BackendDump.printBackendDAE(BackendDAE.DAE({syst}, inShared));
end if;
Error.addMessage(Error.INTERNAL_ERROR, {"IndexReduction.pantelidesIndexReduction failed! Found empty set of continues equations. Use -d=bltdump to get more information."});
Error.addMessage(Error.INTERNAL_ERROR, {"IndexReduction.pantelidesIndexReduction failed! Found empty set of continuous equations. Use -d=bltdump to get more information."});
then fail();

case (false, _::_, (_, _, _, mapIncRowEqn, _)) equation
if Flags.isSet(Flags.BLT_DUMP) then
print("Reduce Index failed! System is structurally singulare and cannot handled because number of unassigned continues equations is larger than number of states.\nmarked equations:\n");
print("Reduce Index failed! System is structurally singulare and cannot handled because number of unassigned continuous equations is larger than number of states.\nmarked equations:\n");
// get from scalar eqns indexes the indexes in the equation array
BackendDump.debuglst(eqns, intString, " ", "\n");
end if;
Expand Down Expand Up @@ -506,7 +506,7 @@ algorithm
varlst = m[eindx];
varlst = List.map(varlst,intAbs);
vlst = List.map1r(varlst,BackendVariable.getVarAt,vars);
// if there is a continues variable then b is false
// if there is a continuous variable then b is false
b = List.mapBoolAnd(vlst,BackendVariable.isVarDiscrete);
eqnsLst = List.consOnTrue(not b, eindx, eqnsLst);
unassignedEqns = List.consOnTrue(ba and not b, eindx, unassignedEqns);
Expand Down Expand Up @@ -2203,7 +2203,7 @@ algorithm
BackendDump.dumpEquationList(eqnslst, "Constraint equations:");
end if;
// no chance, to much equations
msg = "It is not possible to select continues time states because Number of Equations " + intString(neqns) + " greater than number of States " + intString(nfreeStates) + " to select from.";
msg = "It is not possible to select continuous time states because Number of Equations " + intString(neqns) + " greater than number of States " + intString(nfreeStates) + " to select from.";
Error.addMessage(Error.INTERNAL_ERROR, {msg});
then
fail();
Expand Down
5 changes: 3 additions & 2 deletions OMCompiler/Compiler/FrontEnd/CheckModel.mo
Expand Up @@ -574,11 +574,12 @@ algorithm
Modelica spec 3.3 rev 11.1.2
"If at least one element of an array appears on the left hand side of the assignment operator, then the
complete array is initialized in this algorithm section"
So we strip the subs and send the whole array to expansion. i.e. we consider the whole array as modified.
So we strip the last sub and all iterator subs and send the whole array to expansion. i.e. we consider the whole array as modified.
*/
case (e as DAE.CREF(componentRef=cr), (expand,ht))
equation
cr = ComponentReference.crefStripSubs(cr);
cr = ComponentReference.crefStripLastSubs(cr);
cr = ComponentReference.crefStripIterSub(cr);
crlst = ComponentReference.expandCref(cr, true);
ht = List.fold(crlst, BaseHashSet.add, ht);
then (e, false, (expand,ht));
Expand Down
7 changes: 4 additions & 3 deletions OMCompiler/Compiler/FrontEnd/ComponentReference.mo
Expand Up @@ -2820,9 +2820,10 @@ end crefStripLastSubs;
public function crefStripIterSub
"Recursively looks up subscripts and strips the given iter sub.
This gives an array variable that is defined in a for loop (no NF_SCALARIZE).
Removes all iteration subscripts if an empty or no iter input was given.
author: rfranke"
input DAE.ComponentRef inComponentRef;
input DAE.Ident iter;
input DAE.Ident iter = "";
output DAE.ComponentRef outComponentRef;
protected
DAE.Ident ident, index;
Expand All @@ -2834,11 +2835,11 @@ algorithm
case DAE.CREF_IDENT(ident = ident, identType = ty,
subscriptLst = subs as {DAE.INDEX(exp = DAE.CREF(componentRef = DAE.CREF_IDENT(ident = index)))})
then
makeCrefIdent(ident, ty, if index == iter then {} else subs);
makeCrefIdent(ident, ty, if ("" == iter) or (index == iter) then {} else subs);
case DAE.CREF_QUAL(ident = ident, identType = ty, componentRef = cref,
subscriptLst = subs as {DAE.INDEX(exp = DAE.CREF(componentRef = DAE.CREF_IDENT(ident = index)))})
algorithm
if index == iter then
if ("" == iter) or (index == iter) then
subs := {};
else
cref := crefStripIterSub(cref, iter);
Expand Down
38 changes: 4 additions & 34 deletions testsuite/simulation/modelica/algorithms_functions/bug_2452.mos
Expand Up @@ -34,40 +34,17 @@ algorithm
end for;
end bug_2452;



/* The algorithm section is considered to have 2 equations here.
Array is expanded and considered whole*/
model bug_2452_2
record R
Integer d;
end R;
R r[2];
algorithm
r[1].d := 0;
end bug_2452_2;



/* We need to make sure that we have proper counting when algorithm
secions come from component arrays. This will end up as

algorithm
r[1].d := 0;
algorithm
r[2].d := 0;

However unlike the mdoel above this time each algorithm section
is considered to have only 1 equation.
/*
These algorithms are considered to have only 1 equation.
*/
model bug_2452_3
model bug_2452_2
model R
Integer d;
algorithm
d := 0;
end R;
R r[2];
end bug_2452_3;
end bug_2452_2;

"); getErrorString();

Expand All @@ -77,9 +54,6 @@ checkModel(bug_2452); getErrorString();
// bug_2452_2 has 2 equation(s) and 2 variable(s)
checkModel(bug_2452_2); getErrorString();

// bug_2452_3 has 2 equation(s) and 2 variable(s)
checkModel(bug_2452_3); getErrorString();

// Result:
// true
// ""
Expand All @@ -91,8 +65,4 @@ checkModel(bug_2452_3); getErrorString();
// Class bug_2452_2 has 2 equation(s) and 2 variable(s).
// 0 of these are trivial equation(s)."
// ""
// "Check of bug_2452_3 completed successfully.
// Class bug_2452_3 has 2 equation(s) and 2 variable(s).
// 0 of these are trivial equation(s)."
// ""
// endResult

0 comments on commit ac9e8ec

Please sign in to comment.