Skip to content

Commit

Permalink
[BE] improve inverse algorithm handling
Browse files Browse the repository at this point in the history
 - attempt to fix ticket:4855

Belonging to [master]:
  - OpenModelica/OMCompiler#2336
  - OpenModelica/OpenModelica-testsuite#913
  • Loading branch information
Willi Braun authored and OpenModelica-Hudson committed Apr 5, 2018
1 parent 73e3f9c commit 180e008
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Compiler/BackEnd/BackendDAEOptimize.mo
Expand Up @@ -3700,7 +3700,7 @@ algorithm
end match;
end eaddInitialStmtsToAlgorithms1Helper;

protected function expandAlgorithmStmts "Helper function to eaddInitialStmtsToAlgorithms1Helper."
public function expandAlgorithmStmts "Helper function to eaddInitialStmtsToAlgorithms1Helper."
input list<DAE.Statement> inAlg;
input list<DAE.Exp> inOutputs;
input BackendDAE.Variables inVars;
Expand Down
2 changes: 1 addition & 1 deletion Compiler/SimCode/SimCode.mo
Expand Up @@ -340,10 +340,10 @@ uniontype SimEqSystem
end SES_ALGORITHM;

record SES_INVERSE_ALGORITHM
"this should only occur inside SES_NONLINEAR"
Integer index;
list<DAE.Statement> statements;
list<DAE.ComponentRef> knownOutputCrefs "this is a subset of output crefs of the original algorithm, which are already known";
Boolean insideNonLinearSystem;
BackendDAE.EquationAttributes eqAttr;
end SES_INVERSE_ALGORITHM;

Expand Down
31 changes: 25 additions & 6 deletions Compiler/SimCode/SimCodeUtil.mo
Expand Up @@ -5546,6 +5546,8 @@ algorithm
DAE.ElementSource source;
DAE.Expand crefExpand;
BackendDAE.EquationAttributes eqAttr;
list<SimCode.SimEqSystem> result;
list<DAE.Exp> discreteVarsExp;
constant Boolean debug = false;

// normal call
Expand Down Expand Up @@ -5580,6 +5582,7 @@ algorithm
// get and expand the searched variables
solvedVars = List.map(vars, BackendVariable.varCref);
solvedVars = List.unionList(List.map1(solvedVars, ComponentReference.expandCref, true));
if debug then BackendDump.debugStrCrefLstStr("solvedVars : ", solvedVars, ", ", "\n"); end if;

// get and expand all other variables
algOutVars = CheckModel.checkAndGetAlgorithmOutputs(alg, source, crefExpand);
Expand All @@ -5588,10 +5591,14 @@ algorithm
// the remaining quantity of all out vars to the solved vars
knownOutputCrefs = List.setDifference(algOutVars, solvedVars);

//Why do we need to filter the discrete variables?
//List.filterOnTrue(BackendVariable.varList(knVars),BackendVariable.isRecordVar);
// filter since are not solvable with non-linear solver
solvedVars = List.map(List.filterOnTrue(vars, BackendVariable.isVarNonDiscrete), BackendVariable.varCref);

// discrete vars are added with there start value and by
// event iteration we ensure that all variable are consistent
discreteVarsExp = list(Expression.crefToExp(BackendVariable.varCref(v)) for v in List.filterOnTrue(vars, BackendVariable.isVarDiscrete));
algStatements = BackendDAEOptimize.expandAlgorithmStmts(algStatements, discreteVarsExp, BackendVariable.listVar(vars), true);

if debug then
BackendDump.debugStrCrefLstStr("algOutVars : ", algOutVars, ", ", "\n");
BackendDump.debugStrCrefLstStr("filtered solvedVars: ", solvedVars, ", ", "\n");
Expand All @@ -5601,8 +5608,20 @@ algorithm
//Why should we have the same amount of solved vars and know vars?
//true = intEq(listLength(solvedVars), listLength(knownOutputCrefs));

alg = DAE.ALGORITHM_STMTS(algStatements);
DAE.ALGORITHM_STMTS(algStatements) = BackendDAEUtil.collateAlgorithm(alg, NONE());
then ({SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(iuniqueEqIndex+1, {SimCode.SES_INVERSE_ALGORITHM(iuniqueEqIndex, algStatements, knownOutputCrefs, eqAttr)}, solvedVars, 0, listLength(vars), NONE(), false, false, false), NONE(), eqAttr)}, iuniqueEqIndex+2);

if not listEmpty(solvedVars) then
result = {SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(iuniqueEqIndex+1,
{SimCode.SES_INVERSE_ALGORITHM(iuniqueEqIndex, algStatements, knownOutputCrefs, true, eqAttr)},
solvedVars, 0, listLength(vars), NONE(), false, false, false), NONE(), eqAttr)};
ouniqueEqIndex = iuniqueEqIndex+2;
else
result = {SimCode.SES_INVERSE_ALGORITHM(iuniqueEqIndex, algStatements, knownOutputCrefs, false, eqAttr)};
ouniqueEqIndex = iuniqueEqIndex+1;
end if;

then (result, ouniqueEqIndex);

// Error message, inverse algorithms cannot be solved for discrete variables
case (BackendDAE.ALGORITHM(alg=alg, source=source, expand=crefExpand, attr=eqAttr)::_, _) equation
Expand Down Expand Up @@ -11752,7 +11771,7 @@ author:Waurich TUD 2014-05"
algorithm
simEqSysOut := match(simEqSysIn,idx)
local
Boolean pom,changed,ic;
Boolean pom,changed,ic, inls;
Integer idxLS,idxNLS,idxMX,nUnknowns;
list<Boolean> bLst;
DAE.ComponentRef cref;
Expand Down Expand Up @@ -11797,8 +11816,8 @@ algorithm
case(SimCode.SES_ALGORITHM(statements=stmts,eqAttr=eqAttr), _) equation
simEqSys = SimCode.SES_ALGORITHM(idx,stmts, eqAttr);
then simEqSys;
case(SimCode.SES_INVERSE_ALGORITHM(statements=stmts, knownOutputCrefs=crefs,eqAttr=eqAttr), _) equation
simEqSys = SimCode.SES_INVERSE_ALGORITHM(idx, stmts, crefs, eqAttr);
case(SimCode.SES_INVERSE_ALGORITHM(statements=stmts, knownOutputCrefs=crefs,insideNonLinearSystem=inls,eqAttr=eqAttr), _) equation
simEqSys = SimCode.SES_INVERSE_ALGORITHM(idx, stmts, crefs, inls, eqAttr);
then simEqSys;
case(SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(partOfMixed=pom,tornSystem=tornSystem,vars=simVars,beqs=expLst,sources=sources,simJac=simJac,residual=simEqSysLst,jacobianMatrix=jac,indexLinearSystem=idxLS,nUnknowns=nUnknowns),eqAttr=eqAttr),_)
equation
Expand Down
29 changes: 24 additions & 5 deletions Compiler/Template/CodegenC.tpl
Expand Up @@ -4855,7 +4855,6 @@ template equation_arrayFormat(SimEqSystem eq, String name, Context context, Inte
case e as SES_IFEQUATION(__)
then equationIfEquationAssign(e, context, &varD, &tempeqns, modelNamePrefix)
case e as SES_ALGORITHM(__)
then equationAlgorithm(e, context, &varD, &tempeqns)
case e as SES_INVERSE_ALGORITHM(__)
then equationAlgorithm(e, context, &varD, &tempeqns)
case e as SES_LINEAR(__)
Expand Down Expand Up @@ -4956,9 +4955,8 @@ template equation_impl2(Integer clockIndex, SimEqSystem eq, Context context, Str
then equationArrayCallAssign(e, context, &varD, &tempeqns)
case e as SES_IFEQUATION(__)
then equationIfEquationAssign(e, context, &varD, &tempeqns, modelNamePrefix)
case e as SES_ALGORITHM(__)
then equationAlgorithm(e, context, &varD, &tempeqns)
case e as SES_INVERSE_ALGORITHM(__)
case e as SES_ALGORITHM(__)
then equationAlgorithm(e, context, &varD, &tempeqns)
case e as SES_LINEAR(__)
then equationLinear(e, context, &varD)
Expand Down Expand Up @@ -5211,11 +5209,32 @@ template equationAlgorithm(SimEqSystem eq, Context context, Text &varDecls, Text
"Generates an equation that is an algorithm."
::=
match eq
case SES_ALGORITHM(__)
case SES_INVERSE_ALGORITHM(__) then
/* SES_INVERSE_ALGORITHM which is used by the non-linear solver */
case alg as SES_INVERSE_ALGORITHM(insideNonLinearSystem=true)
case SES_ALGORITHM(__) then
(statements |> stmt =>
algStatement(stmt, context, &varDecls, &auxFunction)
;separator="\n")
/* Generates an equation that is an inverse algorithm
without continuous variables, discrete variables are
handled by the event iteration */
case alg as SES_INVERSE_ALGORITHM(__) then
let backupKnown = (alg.knownOutputCrefs |> cr hasindex i0 =>
let &varDecls += '<%crefType(cr)%> OLD_<%i0%>;<%\n%>'
'OLD_<%i0%> = <%cref(cr)%>;'
;separator="\n")
let stmts = (statements |> stmt =>
algStatement(stmt, context, &varDecls, &auxFunction)
;separator="\n")
let restoreKnownVars = (alg.knownOutputCrefs |> cr hasindex i0 => '<%cref(cr)%> = OLD_<%i0%>;' ;separator="\n")
<<
/* backup outputs of the algorithm */
<%backupKnown%>
/* algrithm it self */
<%stmts%>
/* restore outputs of the algorithm */
<%restoreKnownVars%>
>>
end equationAlgorithm;

template equationLinear(SimEqSystem eq, Context context, Text &varDecls)
Expand Down
2 changes: 1 addition & 1 deletion Compiler/Template/SimCodeTV.mo
Expand Up @@ -464,10 +464,10 @@ package SimCode
end SES_ALGORITHM;

record SES_INVERSE_ALGORITHM
"this should only occur inside SES_NONLINEAR"
Integer index;
list<DAE.Statement> statements;
list<DAE.ComponentRef> knownOutputCrefs "this is a subset of output crefs of the original algorithm, which are already known";
Boolean insideNonLinearSystem;
BackendDAE.EquationAttributes eqAttr;
end SES_INVERSE_ALGORITHM;

Expand Down

0 comments on commit 180e008

Please sign in to comment.