Skip to content
This repository has been archived by the owner on May 18, 2019. It is now read-only.

Commit

Permalink
Make inline integration for synchronous models work with arrays
Browse files Browse the repository at this point in the history
- synchronousFeatures generates for-equation with integration formula
- SimCodeUtil.createEquation solves for-equations for states
- (CodegenUtilSimulation.dumpEqs uses Modelica instead of C syntax)

Belonging to [master]:
  - #2698
  - OpenModelica/OpenModelica-testsuite#1045
  • Loading branch information
rfranke authored and OpenModelica-Hudson committed Oct 6, 2018
1 parent eda1ea2 commit ec7f741
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 20 deletions.
56 changes: 45 additions & 11 deletions Compiler/BackEnd/SynchronousFeatures.mo
Expand Up @@ -213,6 +213,7 @@ algorithm
list<DAE.ComponentRef> derVars = {};
BackendDAE.Var var;
DAE.Exp exp, exp2;
DAE.Type ty;
case syst as BackendDAE.EQSYSTEM(orderedEqs = eqs)
algorithm
BackendDAE.CLOCKED_PARTITION(idx) := syst.partitionKind;
Expand All @@ -232,7 +233,7 @@ algorithm
// replace der(x) with $DER.x and collect derVars x
for i in 1:BackendEquation.getNumberOfEquations(eqs) loop
eq := BackendEquation.get(eqs, i);
(eq, derVars) := BackendEquation.traverseExpsOfEquation(eq, getDerVars1, derVars);
(eq, (derVars, _)) := BackendEquation.traverseExpsOfEquation(eq, getDerVars1, (derVars, BackendEquation.getForEquationIterIdent(eq)));
lstEqs := eq :: lstEqs;
end for;
// add all $DER.x as additional variables
Expand All @@ -244,9 +245,16 @@ algorithm
// add defining equations for $DER.x, depending on solverMethod
for derVar in derVars loop
var := listGet(BackendVariable.getVar(derVar, syst.orderedVars), 1);
exp := DAE.CALL(Absyn.IDENT(name = "der"), {DAE.CREF(derVar, var.varType)}, DAE.callAttrBuiltinImpureReal);
ty := var.varType;
// add forIter subscript and use element type if var is array
derVar := match var.varType
case DAE.T_ARRAY(ty = ty)
then ComponentReference.crefSetLastSubs(derVar, {DAE.INDEX(DAE.CREF(DAE.CREF_IDENT("i", DAE.T_INTEGER_DEFAULT, {}), DAE.T_INTEGER_DEFAULT))});
else derVar;
end match;
exp := DAE.CALL(Absyn.IDENT(name = "der"), {DAE.CREF(derVar, ty)}, DAE.callAttrBuiltinImpureReal);
exp := substituteFiniteDifference(exp);
exp2 := DAE.CREF(ComponentReference.crefPrefixDer(derVar), var.varType);
exp2 := DAE.CREF(ComponentReference.crefPrefixDer(derVar), ty);
if solverMethod == "ExplicitEuler" then
// introduce states to delay derivatives; see MLS 3.3, section 16.8.2 Solver Methods
exp2 := DAE.CALL(Absyn.IDENT(name = "previous"), {exp2}, DAE.callAttrBuiltinImpureReal);
Expand All @@ -259,7 +267,17 @@ algorithm
// clocked continuous states are fixed at first tick
exp2 := DAE.IFEXP(DAE.CALL(Absyn.IDENT(name = "firstTick"), {}, DAE.callAttrBuiltinImpureBool),
DAE.RCONST(0), exp2);
eq := BackendDAE.EQUATION(exp, exp2, var.source, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC);
// create for-equation or regular equation
eq := match var.varType
local
DAE.Dimension dim;
case DAE.T_ARRAY(dims = {dim})
then BackendDAE.FOR_EQUATION(
DAE.CREF(DAE.CREF_IDENT("i", DAE.T_INTEGER_DEFAULT, {}), DAE.T_INTEGER_DEFAULT),
DAE.ICONST(1), DAEUtil.dimExp(dim),
exp, exp2, var.source, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC);
else BackendDAE.EQUATION(exp, exp2, var.source, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC);
end match;
lstEqs := eq :: lstEqs;
end for;
syst.orderedEqs := BackendEquation.listEquation(listReverse(lstEqs));
Expand All @@ -281,9 +299,9 @@ end treatClockedStates;

protected function getDerVars1 "helper to getDerVars"
input DAE.Exp inExp;
input list<DAE.ComponentRef> inDerVars;
input tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> inDerVars;
output DAE.Exp outExp;
output list<DAE.ComponentRef> outDerVars;
output tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> outDerVars;
algorithm
(outExp, outDerVars) := Expression.traverseExpBottomUp(inExp, getDerVars, inDerVars);
end getDerVars1;
Expand All @@ -292,21 +310,37 @@ protected function getDerVars
"Get all crefs that appear in a der() operator and replace der(x) with $DER.x.
author: rfranke"
input DAE.Exp inExp;
input list<DAE.ComponentRef> inDerVars;
input tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> inDerVars;
output DAE.Exp outExp;
output list<DAE.ComponentRef> outDerVars = inDerVars;
output tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> outDerVars = inDerVars;
algorithm
outExp := match inExp
local
list<DAE.ComponentRef> derVars;
Option<DAE.Ident> optForIter;
DAE.Ident forIter;
DAE.ComponentRef x;
DAE.Type ty;
DAE.Exp der_x;
case DAE.CALL(path = Absyn.IDENT(name = "der"),
expLst = {DAE.CREF(componentRef = x, ty = ty)})
algorithm
if not ComponentReference.crefInLst(x, outDerVars) then
outDerVars := x :: outDerVars;
// build $DER.x
der_x := DAE.CREF(ComponentReference.crefPrefixDer(x), ty);
// strip optional forIter and append x to derVars
(derVars, optForIter) := inDerVars;
_ := match optForIter
case SOME(forIter)
algorithm
x := ComponentReference.crefStripIterSub(x, forIter);
then ();
else ();
end match;
if not ComponentReference.crefInLst(x, derVars) then
derVars := x :: derVars;
end if;
then DAE.CREF(ComponentReference.crefPrefixDer(x), ty);
outDerVars := (derVars, optForIter);
then der_x;
else inExp;
end match;
end getDerVars;
Expand Down
18 changes: 18 additions & 0 deletions Compiler/FrontEnd/DAEUtil.mo
Expand Up @@ -235,6 +235,24 @@ algorithm
end match;
end expTypeArrayDimensions;

public function dimExp
"Converts a dimension to an expression, covering constants and paramters."
input DAE.Dimension dim;
output DAE.Exp exp;
algorithm
exp := match dim
local
Integer iconst;
case DAE.DIM_INTEGER(iconst) then
DAE.ICONST(iconst);
case DAE.DIM_EXP(exp) then
exp;
else algorithm
Error.addMessage(Error.DIMENSION_NOT_KNOWN, {anyString(dim)});
then fail();
end match;
end dimExp;

public function derivativeOrder "
Function to sort derivatives.
Used for Util.sort"
Expand Down
14 changes: 10 additions & 4 deletions Compiler/SimCode/SimCodeUtil.mo
Expand Up @@ -2084,7 +2084,8 @@ algorithm
list<DAE.ComponentRef> conditions, solveCr;
list<SimCode.SimEqSystem> resEqs;
DAE.ComponentRef left, varOutput;
DAE.Exp e1, e2, varexp, exp_, right, cond, prevarexp;
DAE.Exp e1, e2, varexp, exp_, start, cond, prevarexp;
DAE.Ident iter;
BackendDAE.WhenEquation whenEquation, elseWhen;
Option<BackendDAE.WhenEquation> oelseWhen;
String algStr, message, eqStr;
Expand All @@ -2109,10 +2110,15 @@ algorithm
then
({SimCode.SES_SIMPLE_ASSIGN(iuniqueEqIndex, cr, e2, source, eqAttr)}, iuniqueEqIndex + 1, itempvars);

// for equation that may result from -d=-nfScalarize and is assumed solved
case BackendDAE.FOR_EQUATION(iter = varexp, start = e1, stop = e2, left = DAE.CREF(componentRef = cr), right = right, source = source, attr = eqAttr)
// for equation that may result from -d=-nfScalarize
case BackendDAE.FOR_EQUATION(iter = varexp, start = start, stop = cond, left = e1, right = e2, source = source, attr = eqAttr)
algorithm
DAE.CREF(componentRef = DAE.CREF_IDENT(ident = iter)) := varexp;
cr := ComponentReference.crefSetLastSubs(v.varName, {DAE.INDEX(DAE.CREF(DAE.CREF_IDENT(iter, DAE.T_INTEGER_DEFAULT, {}), DAE.T_INTEGER_DEFAULT))});
BackendDAE.SHARED(functionTree = funcs) := shared;
(exp_, asserts, solveEqns, solveCr) := ExpressionSolve.solve2(e1, e2, Expression.crefExp(cr), SOME(funcs), SOME(iuniqueEqIndex), true, BackendDAEUtil.isSimulationDAE(shared));
then
({SimCode.SES_FOR_LOOP(iuniqueEqIndex, varexp, e1, e2, cr, right, source, eqAttr)}, iuniqueEqIndex + 1, itempvars);
({SimCode.SES_FOR_LOOP(iuniqueEqIndex, varexp, start, cond, cr, exp_, source, eqAttr)}, iuniqueEqIndex + 1, itempvars);

// solved equation
case BackendDAE.SOLVED_EQUATION(exp=e2, source=source, attr=eqAttr)
Expand Down
9 changes: 4 additions & 5 deletions Compiler/Template/CodegenUtilSimulation.tpl
Expand Up @@ -215,11 +215,10 @@ template dumpEqs(list<SimEqSystem> eqs)
>>
case e as SES_FOR_LOOP(__) then
let &forstatement = buffer ""
let &forstatement += 'for(size_t ' + escapeCComments(dumpExp(e.iter,"\"")) + ' = ' + escapeCComments(dumpExp(e.startIt,"\"")) + '; '
let &forstatement += escapeCComments(dumpExp(e.iter,"\"")) + ' != ' + escapeCComments(dumpExp(e.endIt,"\"")) + '+1; '
let &forstatement += escapeCComments(dumpExp(e.iter,"\"")) + '++) {<%\n%>'
let &forstatement += ' <%crefStr(e.cref)%> = <%escapeCComments(dumpExp(e.exp,"\""))%><%\n%>'
let &forstatement += '}'
let &forstatement += 'for ' + escapeCComments(dumpExp(e.iter,"\"")) + ' in ' + escapeCComments(dumpExp(e.startIt,"\""))
let &forstatement += ' : ' + escapeCComments(dumpExp(e.endIt,"\"")) + ' loop<%\n%>'
let &forstatement += ' <%crefStr(e.cref)%> = <%escapeCComments(dumpExp(e.exp,"\""))%>; '
let &forstatement += 'end for'
<<
equation index: <%equationIndex(e)%>
type: FOR_LOOP
Expand Down

0 comments on commit ec7f741

Please sign in to comment.