Skip to content

Commit

Permalink
Improved performance of SimCode zero-crossings
Browse files Browse the repository at this point in the history
Changed the functions to not consume memory when not collecting
anything. When the are many independent equation systems, the
zero-crossings are traversed once per system, making the translation
slow (this is still true; it just uses less memory now).

In order to fix the problems, it needs to be possible to query which
equation system a zero-crossing belongs to in constant time (or vice
versa).
  • Loading branch information
sjoelund committed Jul 11, 2016
1 parent fde847b commit 52f0eb7
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 94 deletions.
58 changes: 33 additions & 25 deletions Compiler/BackEnd/BackendDAEUtil.mo
Expand Up @@ -55,6 +55,7 @@ public import Util;
protected
import Algorithm;
import Array;
import AvlSetInt;
import BackendDAEOptimize;
import BackendDAETransform;
import BackendDump;
Expand Down Expand Up @@ -1362,8 +1363,7 @@ algorithm
else
(_,statevarindx_lst) := BackendVariable.getAllStateVarIndexFromVariables(v);
end if;
eqns := List.map1r(statevarindx_lst,arrayGet,ass1);
eqns := List.select(eqns, Util.intPositive);
eqns := list(arrayGet(ass1,i) for i guard arrayGet(ass1,i)>0 in statevarindx_lst);
outIntegerArray := markStateEquationsWork(eqns,m,ass1,arr);
end markStateEquations;

Expand All @@ -1390,30 +1390,37 @@ protected
list<Integer> varindx_lst,eqns;
BackendDAE.IncidenceMatrix m;
BackendDAE.Variables v;
list<BackendDAE.Var> varlst;
AvlSetInt.Tree tree;
CheckEquationsVarsExpTopDownFunc func;
partial function CheckEquationsVarsExpTopDownFunc
input output DAE.Exp exp;
output Boolean cont;
input output AvlSetInt.Tree tree;
end CheckEquationsVarsExpTopDownFunc;
algorithm
BackendDAE.EQSYSTEM(orderedVars = v,m=SOME(m)) := syst;
(_, (_, varlst)) := traverseZeroCrossingExps(inZeroCross, varsCollector, (v,{}), {});
varindx_lst := BackendVariable.getVarIndexFromVars(varlst, v);
eqns := List.map1r(varindx_lst,arrayGet,ass1);
eqns := List.select(eqns, Util.intPositive);
tree := AvlSetInt.new();
func := function BackendEquation.checkEquationsVarsExpTopDown(vars=v);
for zc in inZeroCross loop
tree := varsCollector(zc.relation_, tree, func);
end for;
varindx_lst := AvlSetInt.listKeys(tree);
eqns := list(arrayGet(ass1,i) for i guard arrayGet(ass1,i)>0 in varindx_lst);
outIntegerArray := markStateEquationsWork(eqns,m,ass1,arr);
end markZeroCrossingEquations;

protected function varsCollector
input DAE.Exp inExp;
input tuple<BackendDAE.Variables, list<BackendDAE.Var>> inTpl;
output DAE.Exp exp;
output tuple<BackendDAE.Variables, list<BackendDAE.Var>> outTpl;
protected
BackendDAE.Variables vars;
list<BackendDAE.Var> varsLst, varLst2;
input DAE.Exp exp;
input output AvlSetInt.Tree tree;
input CheckEquationsVarsExpTopDownFunc func;

partial function CheckEquationsVarsExpTopDownFunc
input output DAE.Exp exp;
output Boolean cont;
input output AvlSetInt.Tree tree;
end CheckEquationsVarsExpTopDownFunc;
algorithm
(vars, varsLst) := inTpl;
varLst2 := BackendEquation.expressionVars(inExp, vars);
varsLst := listAppend(varLst2, varsLst);
exp := inExp;
outTpl := (vars, varsLst);
tree := BackendEquation.expressionVarsIndexes(exp, tree, func);
end varsCollector;

protected function markStateEquationsWork
Expand Down Expand Up @@ -6621,12 +6628,12 @@ algorithm
end match;
end traverseAlgorithmExpsWithUpdate;

public function traverseZeroCrossingExps
protected function traverseZeroCrossingExps
replaceable type Type_a subtypeof Any;
input list<BackendDAE.ZeroCrossing> iZeroCrossing;
input FuncExpType func;
input Type_a inTypeA;
input list<BackendDAE.ZeroCrossing> iAcc;
input list<BackendDAE.ZeroCrossing> iAcc={};
output list<BackendDAE.ZeroCrossing> oZeroCrossing;
output Type_a outTypeA;
partial function FuncExpType
Expand All @@ -6639,14 +6646,15 @@ algorithm
(oZeroCrossing,outTypeA) := match(iZeroCrossing,func,inTypeA,iAcc)
local
list<BackendDAE.ZeroCrossing> zeroCrossing;
DAE.Exp relation_;
DAE.Exp relation1, relation2;
list<Integer> occurEquLst;
Type_a arg;
BackendDAE.ZeroCrossing zc;
case({},_,_,_) then (listReverse(iAcc),inTypeA);
case(BackendDAE.ZERO_CROSSING(relation_,occurEquLst)::zeroCrossing,_,_,_)
case((zc as BackendDAE.ZERO_CROSSING(relation1,occurEquLst))::zeroCrossing,_,_,_)
equation
(relation_,arg) = Expression.traverseExpBottomUp(relation_,func,inTypeA);
(zeroCrossing,arg) = traverseZeroCrossingExps(zeroCrossing,func,arg,BackendDAE.ZERO_CROSSING(relation_,occurEquLst)::iAcc);
(relation2,arg) = Expression.traverseExpBottomUp(relation1,func,inTypeA);
(zeroCrossing,arg) = traverseZeroCrossingExps(zeroCrossing,func,arg,(if referenceEq(relation1,relation2) then zc else BackendDAE.ZERO_CROSSING(relation2,occurEquLst))::iAcc);
then
(zeroCrossing,arg);
end match;
Expand Down
120 changes: 57 additions & 63 deletions Compiler/BackEnd/BackendEquation.mo
Expand Up @@ -47,7 +47,7 @@ protected import BackendDAEUtil;
protected import BackendDump;
protected import BackendVariable;
protected import BaseHashTable;
protected import BinaryTreeInt;
protected import AvlSetInt;
protected import ClassInf;
protected import ComponentReference;
protected import DAEUtil;
Expand Down Expand Up @@ -185,12 +185,15 @@ public function equationsLstVars
input BackendDAE.Variables inVars;
output list<BackendDAE.Var> outVars;
protected
BinaryTreeInt.BinTree bt;
AvlSetInt.Tree indexes;
list<Integer> keys;
algorithm
bt := BinaryTreeInt.emptyBinTree;
(_, (_, bt)) := traverseExpsOfEquationList(inEquationLst, checkEquationsVarsExpTopDownTraverseHelper, (inVars, bt));
(keys, _) := BinaryTreeInt.bintreeToList(bt);
if listEmpty(inEquationLst) then
outVars := {};
return;
end if;
(_, indexes) := traverseExpsOfEquationList(inEquationLst, function checkEquationsVarsExpTopDownTraverseHelper(vars=inVars), AvlSetInt.new());
keys := AvlSetInt.listKeys(indexes);
outVars := List.map1r(keys, BackendVariable.getVarAt, inVars);
end equationsLstVars;

Expand All @@ -202,32 +205,14 @@ public function equationsVars
input BackendDAE.Variables inVars;
output list<BackendDAE.Var> outVars;
protected
BinaryTreeInt.BinTree bt;
AvlSetInt.Tree indexes;
list<Integer> keys;
algorithm
bt := BinaryTreeInt.emptyBinTree;
(_, bt) := BackendDAEUtil.traverseBackendDAEExpsEqns(inEquations, checkEquationsVarsExpTopDownTraverseHelper, (inVars, bt));
(keys, _) := BinaryTreeInt.bintreeToList(bt);
indexes := BackendDAEUtil.traverseBackendDAEExpsEqns(inEquations, function checkEquationsVarsExpTopDownTraverseHelper(vars=inVars), AvlSetInt.new());
keys := AvlSetInt.listKeys(indexes);
outVars := List.map1r(keys, BackendVariable.getVarAt, inVars);
end equationsVars;

public function equationsVars2
"author: Frenkel TUD 2011-05
From the equations and a variable array return all
occurring variables form the array."
input BackendDAE.EquationArray inEquations;
input BackendDAE.Variables inVars;
output list<BackendDAE.Var> outVars;
protected
BinaryTreeInt.BinTree bt;
list<Integer> keys;
algorithm
bt := BinaryTreeInt.emptyBinTree;
(_, bt) := BackendDAEUtil.traverseBackendDAEExpsEqns(inEquations, checkEquationsVarsExpTopDownTraverseHelper, (inVars, bt) );
(keys, _) := BinaryTreeInt.bintreeToList(bt);
outVars := List.map1r(keys, BackendVariable.getVarAt, inVars);
end equationsVars2;

public function equationVars
"author: Frenkel TUD 2012-03
From the equation and a variable array return all
Expand All @@ -236,12 +221,11 @@ public function equationVars
input BackendDAE.Variables inVars;
output list<BackendDAE.Var> outVars;
protected
BinaryTreeInt.BinTree bt;
AvlSetInt.Tree indexes;
list<Integer> keys;
algorithm
bt := BinaryTreeInt.emptyBinTree;
(_, (_, bt)) := traverseExpsOfEquation(inEquation, checkEquationsVarsExpTopDownTraverseHelper, (inVars, bt));
(keys, _) := BinaryTreeInt.bintreeToList(bt);
(_, indexes) := traverseExpsOfEquation(inEquation, function checkEquationsVarsExpTopDownTraverseHelper(vars=inVars), AvlSetInt.new());
keys := AvlSetInt.listKeys(indexes);
outVars := List.map1r(keys, BackendVariable.getVarAt, inVars);
end equationVars;

Expand All @@ -250,67 +234,77 @@ public function expressionVars
From the expression and a variable array return all
variables in the expression."
input DAE.Exp inExp;
input BackendDAE.Variables inVars;
input BackendDAE.Variables vars;
output list<BackendDAE.Var> outVars;
protected
BinaryTreeInt.BinTree bt;
AvlSetInt.Tree indexes;
list<Integer> keys;
algorithm
bt := BinaryTreeInt.emptyBinTree;
(_, (_, bt)) := Expression.traverseExpTopDown(inExp, checkEquationsVarsExpTopDown, (inVars, bt));
(keys, _) := BinaryTreeInt.bintreeToList(bt);
outVars := List.map1r(keys, BackendVariable.getVarAt, inVars);
(_, indexes) := Expression.traverseExpTopDown(inExp, function checkEquationsVarsExpTopDown(vars=vars), AvlSetInt.new());
keys := AvlSetInt.listKeys(indexes);
outVars := List.map1r(keys, BackendVariable.getVarAt, vars);
end expressionVars;

public function expressionVarsIndexes
"From the expression and a variable array return all variables in the expression."
input DAE.Exp exp;
input output AvlSetInt.Tree indexes;
input CheckEquationsVarsExpTopDownFunc func;

partial function CheckEquationsVarsExpTopDownFunc
input output DAE.Exp exp;
output Boolean cont;
input output AvlSetInt.Tree tree;
end CheckEquationsVarsExpTopDownFunc;
algorithm
(_, indexes) := Expression.traverseExpTopDown(exp, func, indexes);
end expressionVarsIndexes;

public function checkEquationsVarsExpTopDownTraverseHelper
"This function traverses expssions to-down to collect all
variables that are involed into the expression."
input DAE.Exp inExp;
input tuple<BackendDAE.Variables, BinaryTreeInt.BinTree> itpl;
output DAE.Exp outExp;
output tuple<BackendDAE.Variables, BinaryTreeInt.BinTree> otpl;
input output DAE.Exp exp;
input output AvlSetInt.Tree tree;
input BackendDAE.Variables vars;
algorithm
(outExp, otpl) := Expression.traverseExpTopDown(inExp,checkEquationsVarsExpTopDown,itpl);
(exp, tree) := Expression.traverseExpTopDown(exp,function checkEquationsVarsExpTopDown(vars=vars),tree);
end checkEquationsVarsExpTopDownTraverseHelper;

protected function checkEquationsVarsExpTopDown
input DAE.Exp inExp;
input tuple<BackendDAE.Variables, BinaryTreeInt.BinTree> inTuple;
output DAE.Exp outExp;
public function checkEquationsVarsExpTopDown
input output DAE.Exp exp;
output Boolean cont;
output tuple<BackendDAE.Variables, BinaryTreeInt.BinTree> outTuple;
input output AvlSetInt.Tree tree;
input BackendDAE.Variables vars;
algorithm
(outExp,cont,outTuple) := matchcontinue (inExp,inTuple)
(cont,tree) := matchcontinue exp
local
DAE.Exp e;
BackendDAE.Variables vars;
BinaryTreeInt.BinTree bt;
DAE.ComponentRef cr;
list<Integer> ilst;

// special case for time, it is never part of the equation system
case (e as DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time")), _)
then (e, true, inTuple);
case DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time"))
then (true, tree);

// case for function pointers
case (e as DAE.CREF(ty=DAE.T_FUNCTION_REFERENCE_FUNC()), _)
then (e, true, inTuple);
case DAE.CREF(ty=DAE.T_FUNCTION_REFERENCE_FUNC())
then (true, tree);

// case for pre vars
case (DAE.CALL(path = Absyn.IDENT(name = "pre")), _)
then (inExp, false, inTuple);
case DAE.CALL(path = Absyn.IDENT(name = "pre"))
then (false, tree);

// case for previous vars
case (DAE.CALL(path = Absyn.IDENT(name = "previous")), _)
then (inExp, false, inTuple);
case DAE.CALL(path = Absyn.IDENT(name = "previous"))
then (false, tree);

// add it
case (e as DAE.CREF(componentRef = cr), (vars, bt)) equation
(_, ilst) = BackendVariable.getVar(cr, vars);
bt = BinaryTreeInt.treeAddList(bt, ilst);
then (e, true, (vars, bt));
case DAE.CREF(componentRef = cr)
algorithm
(_, ilst) := BackendVariable.getVar(cr, vars);
tree := AvlSetInt.addList(tree, ilst);
then (true, tree);

else (inExp, true, inTuple);
else (true, tree);
end matchcontinue;
end checkEquationsVarsExpTopDown;

Expand Down
10 changes: 4 additions & 6 deletions Compiler/SimCode/SimCodeUtil.mo
Expand Up @@ -1228,7 +1228,6 @@ algorithm
oeqSccMapping, oeqBackendSimCodeMapping, obackendMapping, oSccOffset) := List.fold1(inSysts, createEquationsForSystems1, arg, foldArg);
oequationsForZeroCrossings := Dangerous.listReverseInPlace(oequationsForZeroCrossings);
((ouniqueEqIndex, olocalKnownVars)) := BackendVariable.traverseBackendDAEVars(shared.localKnownVars, traverseKnVarsToSimEqSystem, (ouniqueEqIndex, {}));

end createEquationsForSystems;

protected function createEquationsForSystems1
Expand Down Expand Up @@ -1268,8 +1267,8 @@ algorithm
(syst, _, _) = BackendDAEUtil.getIncidenceMatrixfromOption(inSyst, BackendDAE.ABSOLUTE(), SOME(funcs));

stateeqnsmark = arrayCreate(BackendDAEUtil.equationArraySizeDAE(syst), 0);
stateeqnsmark = BackendDAEUtil.markStateEquations(syst, stateeqnsmark, ass1);
zceqnsmarks = arrayCreate(BackendDAEUtil.equationArraySizeDAE(syst), 0);
stateeqnsmark = BackendDAEUtil.markStateEquations(syst, stateeqnsmark, ass1);
zceqnsmarks = BackendDAEUtil.markZeroCrossingEquations(syst, zeroCrossings, zceqnsmarks, ass1);

(odeEquations1, algebraicEquations1, allEquations1, equationsForZeroCrossings1, uniqueEqIndex,
Expand All @@ -1280,7 +1279,6 @@ algorithm
GC.free(stateeqnsmark);
GC.free(zceqnsmarks);


odeEquations = List.consOnTrue(not listEmpty(odeEquations1), odeEquations1, odeEquations);
algebraicEquations = List.consOnTrue(not listEmpty(algebraicEquations1), algebraicEquations1, algebraicEquations);
allEquations = List.append_reverse(allEquations1, allEquations);
Expand Down Expand Up @@ -1948,9 +1946,9 @@ algorithm

// try as is should fallback case is a hack for complex record equations
try
// make residual equations => 0 = f(x,xd,y)
eqnlst := List.flattenReverse(List.map(eqnlst, BackendEquation.equationToScalarResidualForm));
tmpEqns := {};
// make residual equations => 0 = f(x,xd,y)
eqnlst := List.flattenReverse(List.map(eqnlst, BackendEquation.equationToScalarResidualForm));
tmpEqns := {};
else
(eqnlst, tmpEqns, uniqueEqIndex, tempvars) := createDAEResidualComplexEquation(eqnlst, uniqueEqIndex, tempvars);
end try;
Expand Down
45 changes: 45 additions & 0 deletions Compiler/Util/AvlSetInt.mo
@@ -0,0 +1,45 @@
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
* ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/

encapsulated package AvlSetInt
import BaseAvlSet;
extends BaseAvlSet;
redeclare type Key = Integer;
redeclare function extends keyStr
algorithm
outString := String(inKey);
end keyStr;
redeclare function extends keyCompare
algorithm
outResult := sign(inKey2-inKey1);
end keyCompare;
annotation(__OpenModelica_Interface="backend");
end AvlSetInt;
1 change: 1 addition & 0 deletions Compiler/boot/LoadCompilerSources.mos
Expand Up @@ -326,6 +326,7 @@ if true then /* Suppress output */

"../Util/AvlTree.mo",
"../Util/AvlTreeString.mo",
"../Util/AvlSetInt.mo",

"../Util/DiffAlgorithm.mo",
"../Util/FMI.mo",
Expand Down

0 comments on commit 52f0eb7

Please sign in to comment.