Skip to content

Commit

Permalink
revise isDiscretExp function for zero-crossings
Browse files Browse the repository at this point in the history
 - moved and merged isVarDiscrete
 - removed isDiscreteEquation, since it's not used and it's wrong.
  • Loading branch information
Willi Braun committed Aug 17, 2015
1 parent 45e4f50 commit 32ed7bf
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 217 deletions.
4 changes: 2 additions & 2 deletions Compiler/BackEnd/BackendDAETransform.mo
Expand Up @@ -285,7 +285,7 @@ algorithm
case (comp, eqn_lst, var_varindx_lst) equation
var_lst = List.map(var_varindx_lst, Util.tuple21);
//false = BackendVariable.hasDiscreteVar(var_lst); //lochel: mixed systems and non-linear systems are treated the same
true = BackendVariable.hasContinousVar(var_lst); //lochel: pure discrete equation systems are not supported
true = BackendVariable.hasContinuousVar(var_lst); //lochel: pure discrete equation systems are not supported
varindxs = List.map(var_varindx_lst, Util.tuple22);
eqn_lst1 = BackendEquation.replaceDerOpInEquationList(eqn_lst);
// States are solved for der(x) not x.
Expand All @@ -309,7 +309,7 @@ algorithm
case (_, eqn_lst, var_varindx_lst) equation
var_lst = List.map(var_varindx_lst, Util.tuple21);
true = BackendVariable.hasDiscreteVar(var_lst);
false = BackendVariable.hasContinousVar(var_lst);
false = BackendVariable.hasContinuousVar(var_lst);
msg = getInstanceName() + " failed (Sorry - Support for Discrete Equation Systems is not yet implemented)\n";
crlst = List.map(var_lst, BackendVariable.varCref);
slst = List.map(crlst, ComponentReference.printComponentRefStr);
Expand Down
224 changes: 26 additions & 198 deletions Compiler/BackEnd/BackendDAEUtil.mo
Expand Up @@ -749,82 +749,19 @@ algorithm
outType := inType;
end makeExpType;

public function isDiscreteEquation
input BackendDAE.Equation eqn;
input BackendDAE.Variables vars;
input BackendDAE.Variables knvars;
output Boolean b;
algorithm
b := matchcontinue(eqn)
local
DAE.Exp e1, e2;
DAE.ComponentRef cr;
list<DAE.Exp> expl;
list<DAE.Statement> stmts;

case BackendDAE.EQUATION(exp=e1, scalar=e2) equation
b = isDiscreteExp(e1, vars, knvars) and isDiscreteExp(e2, vars, knvars);
then b;

case BackendDAE.COMPLEX_EQUATION(left=e1, right=e2) equation
b = isDiscreteExp(e1, vars, knvars) and isDiscreteExp(e2, vars, knvars);
then b;

case BackendDAE.ARRAY_EQUATION(left=e1, right=e2) equation
b = isDiscreteExp(e1, vars, knvars) and isDiscreteExp(e2, vars, knvars);
then b;

case BackendDAE.SOLVED_EQUATION(componentRef=cr, exp=e2) equation
e1 = Expression.crefExp(cr);
b = isDiscreteExp(e1, vars, knvars) and isDiscreteExp(e2, vars, knvars);
then b;

case BackendDAE.RESIDUAL_EQUATION(exp=e1) equation
b = isDiscreteExp(e1, vars, knvars);
then b;

case BackendDAE.ALGORITHM(alg=DAE.ALGORITHM_STMTS(stmts)) equation
(_, (_, _, true)) = DAEUtil.traverseDAEEquationsStmts(stmts, isDiscreteExp1, (vars, knvars, false));
then true;

case BackendDAE.WHEN_EQUATION()
then true;

else false;
end matchcontinue;
end isDiscreteEquation;

public function isDiscreteExp "Returns true if expression is a discrete expression."
public function hasExpContinuousParts
"Returns true if expression has contiuous parts,
and false if the expression is completely discrete.
Used to detect if an expression is a ZeroCrossing."
input DAE.Exp inExp;
input BackendDAE.Variables inVariables;
input BackendDAE.Variables inKnvars;
output Boolean outBoolean;
protected
Option<Boolean> obool;
algorithm
(_,(_, _, obool)) := Expression.traverseExpTopDown(inExp, traversingisDiscreteExpFinder, (inVariables, inKnvars, NONE()));
outBoolean := Util.getOptionOrDefault(obool, false);
end isDiscreteExp;
(_,(_, _, SOME(outBoolean))) := Expression.traverseExpTopDown(inExp, traversingContinuousExpFinder, (inVariables, inKnvars, SOME(false)));
end hasExpContinuousParts;

// Why is this so similar to isDiscreteExp? What is the difference?
protected function isDiscreteExp1 "Returns true if expression is a discrete expression."
input DAE.Exp inExp;
input tuple<BackendDAE.Variables, BackendDAE.Variables, Boolean> inTpl;
output DAE.Exp outExp;
output tuple<BackendDAE.Variables, BackendDAE.Variables, Boolean> outTpl;
protected
Option<Boolean> obool;
Boolean b, b1;
BackendDAE.Variables v, kv;
algorithm
(v, kv, b) := inTpl;
(_,(_, _, obool)) := Expression.traverseExpTopDown(inExp, traversingisDiscreteExpFinder, (v, kv, NONE()));
b1 := Util.getOptionOrDefault(obool, b);
outExp := inExp;
outTpl := (v, kv, b or b1);
end isDiscreteExp1;

protected function traversingisDiscreteExpFinder "Helper for isDiscreteExp"
protected function traversingContinuousExpFinder "Helper for isDiscreteExp"
input DAE.Exp inExp;
input tuple<BackendDAE.Variables,BackendDAE.Variables,Option<Boolean>> inTpl;
output DAE.Exp outExp;
Expand All @@ -841,149 +778,40 @@ algorithm
Boolean b, b1, b2;
Boolean res;
Var backendVar;

case (e as DAE.ICONST(), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.RCONST(), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.SCONST(), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.BCONST(), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.ENUM_LITERAL(), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));
Absyn.Ident name;

case (e as DAE.CREF(componentRef=cr), (vars, knvars, blst)) equation
((BackendDAE.VAR(varKind=kind)::_), _) = BackendVariable.getVar(cr, vars);
res = isKindDiscrete(kind);
b = Util.getOptionOrDefault(blst, res);
b = b and res;
then (e, false, (vars, knvars, SOME(b)));
((backendVar::_), _) = BackendVariable.getVar(cr, vars);
false = BackendVariable.isVarDiscrete(backendVar);
then (e, false, (vars, knvars, SOME(true)));

// builtin variable time is not discrete
case (e as DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time")), (vars, knvars, _))
then (e, false, (vars, knvars, SOME(false)));
then (e, false, (vars, knvars, SOME(true)));

// Known variables that are input are continuous
case (e as DAE.CREF(componentRef=cr), (vars, knvars, _)) equation
(backendVar::_, _) = BackendVariable.getVar(cr, knvars);
true = BackendVariable.isInput(backendVar);
then (e, false, (vars, knvars, SOME(false)));

// parameters & constants are always discrete
case (e as DAE.CREF(componentRef=cr), (vars, knvars, blst)) equation
((BackendDAE.VAR()::_), _) = BackendVariable.getVar(cr, knvars);
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.RELATION(exp1=e1, exp2=e2), (vars, knvars, _)) equation
b1 = isDiscreteExp(e1, vars, knvars);
b2 = isDiscreteExp(e2, vars, knvars);
b = b1 and b2;
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="pre")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="edge")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="change")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="ceil")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="floor")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="div")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="mod")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="rem")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));

case (e as DAE.CALL(path=Absyn.IDENT(name="initial")), (vars, knvars, blst)) equation
b = Util.getOptionOrDefault(blst, true);
then (e, false, (vars, knvars, SOME(b)));
/*
This cases are wrong because of Modelica Specification:
3.8.3
Unless inside noEvent: Ordered relations (>,<,>=,<=) and the functions ceil, floor, div, mod,
rem, abs, sign. These will generate events if at least one subexpression is not a
discrete-time expression. [In other words, relations inside noEvent(), such as noEvent(x>1),
are not discrete-time expressions].
and
3.7.1
then (e, false, (vars, knvars, SOME(true)));

case (e as DAE.CALL(path=Absyn.IDENT(name=name)), (vars, knvars, blst))
guard stringEq("pre", name) or
stringEq("change", name) or
stringEq("ceil", name) or
stringEq("floor", name) or
stringEq("div", name) or
stringEq("mod", name) or
stringEq("rem", name)
then (e, false, (vars, knvars, blst));

abs(v): Is expanded into
noEvent(if v >= 0 then v else -v)
Argument v needs to be an Integer or Real expression.
sign(v): Is expanded into
noEvent(if v>0 then 1 else if v<0 then -1 else 0)
Argument v needs to be an Integer or Real expression.
case (((e as DAE.CALL(path=Absyn.IDENT(name="abs")),(vars,knvars,blst))))
equation
b = Util.getOptionOrDefault(blst,true);
then ((e,false,(vars,knvars,SOME(b))));
case (((e as DAE.CALL(path=Absyn.IDENT(name="sign")),(vars,knvars,blst))))
equation
b = Util.getOptionOrDefault(blst,true);
then ((e,false,(vars,knvars,SOME(b))));
*/
case (e as DAE.CALL(path=Absyn.IDENT(name="noEvent")), (vars, knvars, _))
then (e, false, (vars, knvars, SOME(false)));

case (e, (vars, knvars, NONE()))
then (e, true, (vars, knvars, NONE()));

case (e, (vars, knvars, SOME(b)))
then (e, b, (vars, knvars, SOME(b)));
case (e, (vars, knvars, blst))
then (e, true, (vars, knvars, blst));
end matchcontinue;
end traversingisDiscreteExpFinder;


public function isVarDiscrete "returns true if variable is discrete"
input BackendDAE.Var inVar;
output Boolean res = isKindDiscrete(inVar.varKind);
end isVarDiscrete;

protected function isKindDiscrete "Returns true if VarKind is discrete."
input VarKind inVarKind;
output Boolean outBoolean;
algorithm
outBoolean := match inVarKind
case (BackendDAE.DISCRETE()) then true;
case (BackendDAE.PARAM()) then true;
case (BackendDAE.CONST()) then true;
else false;
end match;
end isKindDiscrete;
end traversingContinuousExpFinder;

public function statesAndVarsExp
"This function investigates an expression and returns as subexpressions
Expand Down
12 changes: 7 additions & 5 deletions Compiler/BackEnd/BackendVariable.mo
Expand Up @@ -736,6 +736,8 @@ public function isVarDiscrete
algorithm
outBoolean := match (inVar)
case (BackendDAE.VAR(varKind = BackendDAE.DISCRETE())) then true;
case (BackendDAE.VAR(varKind = BackendDAE.PARAM())) then true;
case (BackendDAE.VAR(varKind = BackendDAE.CONST())) then true;
case (BackendDAE.VAR(varType = DAE.T_INTEGER())) then true;
case (BackendDAE.VAR(varType = DAE.T_BOOL())) then true;
case (BackendDAE.VAR(varType = DAE.T_ENUMERATION())) then true;
Expand Down Expand Up @@ -777,8 +779,8 @@ algorithm

end hasDiscreteVar;

public function hasContinousVar
"Returns true if var list contains a continous time variable."
public function hasContinuousVar
"Returns true if var list contains a continuous time variable."
input list<BackendDAE.Var> inBackendDAEVarLst;
output Boolean outBoolean;
algorithm
Expand All @@ -800,10 +802,10 @@ algorithm
case ((BackendDAE.VAR(varKind=BackendDAE.OPT_TGRID()) :: _)) then true;
case ((BackendDAE.VAR(varKind=BackendDAE.OPT_LOOP_INPUT()) :: _)) then true;
case ((BackendDAE.VAR(varKind=BackendDAE.ALG_STATE()) :: _)) then true;
case ((_ :: vs)) then hasContinousVar(vs);
case ((_ :: vs)) then hasContinuousVar(vs);
case ({}) then false;
end match;
end hasContinousVar;
end hasContinuousVar;

public function isVarNonDiscreteAlg
input BackendDAE.Var var;
Expand Down Expand Up @@ -3135,7 +3137,7 @@ protected function traversingisisVarDiscreteFinder
output list<BackendDAE.Var> v_lst;
algorithm
v := inVar;
v_lst := List.consOnTrue(BackendDAEUtil.isVarDiscrete(v),v,inVars);
v_lst := List.consOnTrue(isVarDiscrete(v),v,inVars);
end traversingisisVarDiscreteFinder;

public function getAllStateVarFromVariables
Expand Down
2 changes: 1 addition & 1 deletion Compiler/BackEnd/CommonSubExpression.mo
Expand Up @@ -895,7 +895,7 @@ algorithm

var1 = BackendVariable.getVarAt(vars, varIdxAlias);
var2 = BackendVariable.getVarAt(vars, varIdxRepl);
false = BackendVariable.isStateVar(var1) or BackendDAEUtil.isVarDiscrete(var1);
false = BackendVariable.isStateVar(var1) or BackendVariable.isVarDiscrete(var1);

cref = BackendVariable.varCref(var2);
varExp = BackendVariable.varExp(var1);
Expand Down
20 changes: 10 additions & 10 deletions Compiler/BackEnd/FindZeroCrossings.mo
Expand Up @@ -875,16 +875,16 @@ algorithm

// function with discrete expressions generate no zerocrossing
case (DAE.LUNARY(exp=e1), ((zeroCrossings, relations, samples, numRelations, numMathFunctions), (eq_count, vars, knvars))) equation
true = BackendDAEUtil.isDiscreteExp(e1, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e1, vars, knvars);
if Flags.isSet(Flags.RELIDX) then
print("discrete LUNARY: " + intString(numRelations) + "\n");
end if;
//fcall(Flags.RELIDX, BackendDump.debugExpStr, (inExp, "\n"));
then (inExp, true, ((zeroCrossings, relations, samples, numRelations, numMathFunctions), (eq_count, vars, knvars)));

case (DAE.LBINARY(exp1=e1, exp2=e2), ((zeroCrossings, relations, samples, numRelations, numMathFunctions), (eq_count, vars, knvars))) equation
true = BackendDAEUtil.isDiscreteExp(e1, vars, knvars);
true = BackendDAEUtil.isDiscreteExp(e2, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e1, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e2, vars, knvars);
if Flags.isSet(Flags.RELIDX) then
print("discrete LBINARY: " + intString(numRelations) + "\n");
end if;
Expand Down Expand Up @@ -925,8 +925,8 @@ algorithm

// function with discrete expressions generate no zerocrossing
case (DAE.RELATION(exp1=e1, exp2=e2), ((zeroCrossings, relations, samples, numRelations, numMathFunctions), (eq_count, vars, knvars))) equation
true = BackendDAEUtil.isDiscreteExp(e1, vars, knvars);
true = BackendDAEUtil.isDiscreteExp(e2, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e1, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e2, vars, knvars);
if Flags.isSet(Flags.RELIDX) then
print("discrete RELATION: " + intString(numRelations) + "\n");
end if;
Expand Down Expand Up @@ -1097,7 +1097,7 @@ algorithm
then (inExp, true, (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars)));

case (DAE.LUNARY(exp=e1), (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars))) equation
true = BackendDAEUtil.isDiscreteExp(e1, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e1, vars, knvars);
//fcall(Flags.RELIDX, print, "discrete LUNARY: " + intString(indx) + "\n");
//fcall(Flags.RELIDX, BackendDump.debugExpStr, (inExp, "\n"));
then (inExp, true, (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars)));
Expand Down Expand Up @@ -1140,8 +1140,8 @@ algorithm
then (e_1, false, (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars)));

case (DAE.LBINARY(exp1=e1, exp2=e2), (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars))) equation
true = BackendDAEUtil.isDiscreteExp(e1, vars, knvars);
true = BackendDAEUtil.isDiscreteExp(e2, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e1, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e2, vars, knvars);
//fcall(Flags.RELIDX, print, "discrete LBINARY: " + intString(numRelations) + "\n");
//fcall(Flags.RELIDX, BackendDump.debugExpStr, (inExp, "\n"));
then (inExp, true, (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars)));
Expand Down Expand Up @@ -1189,8 +1189,8 @@ algorithm

// function with discrete expressions generate no zerocrossing.
case (DAE.RELATION(exp1=e1, exp2=e2), (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars))) equation
true = BackendDAEUtil.isDiscreteExp(e1, vars, knvars);
true = BackendDAEUtil.isDiscreteExp(e2, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e1, vars, knvars);
false = BackendDAEUtil.hasExpContinuousParts(e2, vars, knvars);
then (inExp, true, (iterator, inExpLst, range, (zeroCrossings, relations, samples, numRelations, numMathFunctions), (alg_indx, vars, knvars)));

// All other functions generate zerocrossing.
Expand Down
2 changes: 1 addition & 1 deletion Compiler/SimCode/SimCodeUtil.mo
Expand Up @@ -4331,7 +4331,7 @@ algorithm
DAE.ComponentRef cr;
case (v, cr_lst)
equation
true = BackendDAEUtil.isVarDiscrete(v);
true = BackendVariable.isVarDiscrete(v);
cr = BackendVariable.varCref(v);
then (v, cr::cr_lst);
else (inVar,inTpl);
Expand Down

0 comments on commit 32ed7bf

Please sign in to comment.