diff --git a/Compiler/BackEnd/BackendVarTransform.mo b/Compiler/BackEnd/BackendVarTransform.mo index 0df392d9655..f8b9326b822 100644 --- a/Compiler/BackEnd/BackendVarTransform.mo +++ b/Compiler/BackEnd/BackendVarTransform.mo @@ -54,6 +54,7 @@ protected import ClassInf; protected import ComponentReference; protected import DAEUtil; protected import Debug; +protected import EvaluateFunctions; protected import Expression; protected import ExpressionDump; protected import ExpressionSimplify; @@ -879,6 +880,30 @@ algorithm end matchcontinue; end hasNoReplacementCrefFirst; +public function varHasNoReplacement " + Outputs true if the replacements contains no rule for the var +" + input BackendDAE.Var var; + input VariableReplacements inVariableReplacements; + output Boolean bOut; +algorithm + bOut:= + matchcontinue (var,inVariableReplacements) + local + DAE.ComponentRef src; + DAE.Exp dst; + HashTable2.HashTable ht; + case (BackendDAE.VAR(varName=src),REPLACEMENTS(hashTable=ht)) + equation + _ = BaseHashTable.get(src,ht); + then + false; + else + equation + then true; + end matchcontinue; +end varHasNoReplacement; + public function getReplacementVarArraySize input VariableReplacements inVariableReplacements; output Integer size; @@ -2973,5 +2998,32 @@ algorithm print("derConst: " + intString(BaseHashTable.hashTableCurrentSize(extht)) + "\n"); end dumpStatistics; +public function simplifyReplacements"applies ExpressionSimplify.simplify on all replacement expressions" + input VariableReplacements replIn; + input DAE.FunctionTree functions; + output VariableReplacements replOut; +protected + list crefs; + list exps; +algorithm + (crefs,exps) := getAllReplacements(replIn); + (exps,_) := List.map_2(exps,ExpressionSimplify.simplify); + exps := List.map1(exps, EvaluateFunctions.evaluateConstantFunctionCallExp,functions); + replOut := addReplacements(replIn,crefs,exps,NONE()); +end simplifyReplacements; + +public function getConstantReplacements"gets a clean replacement set containing only constant replacement rules" + input VariableReplacements replIn; + output VariableReplacements replOut; +protected + list crefs; + list exps; +algorithm + (crefs,exps) := getAllReplacements(replIn); + (exps,crefs):= List.filterOnTrueSync(exps,Expression.isEvaluatedConst,crefs); + replOut := emptyReplacements(); + replOut := addReplacements(replOut,crefs,exps,NONE()); +end getConstantReplacements; + annotation(__OpenModelica_Interface="backend"); end BackendVarTransform; diff --git a/Compiler/BackEnd/EvaluateParameter.mo b/Compiler/BackEnd/EvaluateParameter.mo index d4bd0a4080b..d73f989a910 100644 --- a/Compiler/BackEnd/EvaluateParameter.mo +++ b/Compiler/BackEnd/EvaluateParameter.mo @@ -104,110 +104,6 @@ end selectParameterFunc; * */ -public function evaluateAllParameters -"author Waurich TUD - evaluates and replaces all parameters" - input BackendDAE.BackendDAE inDAE; - output BackendDAE.BackendDAE outDAE; -protected - BackendDAE.Variables knvars, vars, extVars, aliasVars; - BackendDAE.EquationArray eqArr,initEqs,remEqs, remEqsSys; - BackendDAE.EqSystem sys; - BackendDAE.EqSystems systs, systs2; - BackendDAE.Shared shared; - BackendDAE.EventInfo eventInfo; - DAE.FunctionTree functionTree; - list knVarsLst, varLst; - BackendVarTransform.VariableReplacements repl; - array ass1, ass2; - list order; - list> comps; -algorithm - if Flags.isSet(Flags.EVAL_ALL_PARAMS) then - BackendDAE.DAE (systs, shared as BackendDAE.SHARED(knownVars=knvars, functionTree=functionTree)) := inDAE; - knVarsLst := BackendVariable.varList(knvars); - // bring all params in the correct order - (comps,ass1,ass2) := BackendDAEUtil.causalizeVarBindSystem(knVarsLst); - order := List.map1(List.flatten(comps), Array.getIndexFirst,ass1); - knVarsLst := List.map1(order,BackendVariable.getVarAtIndexFirst,knvars); - repl := BackendVarTransform.emptyReplacements(); - (repl,knVarsLst) := List.fold1(knVarsLst,evaluateAllParameters0,functionTree,(repl,{})); - systs2 := {}; - // replace all equations and all bindExps of the vars - for sys in systs loop - vars := sys.orderedVars; - varLst := BackendVariable.varList(vars); - varLst := List.map1(varLst,BackendVarTransform.replaceBindingExp,repl); - varLst := List.map1(varLst,BackendVarTransform.replaceVariableAttributesInVar,repl); - sys.orderedVars := BackendVariable.listVar1(varLst); - eqArr := sys.orderedEqs; - remEqsSys := sys.removedEqs; - (eqArr,_) := BackendVarTransform.replaceEquationsArr(eqArr,repl,NONE()); - (remEqsSys,_) := BackendVarTransform.replaceEquationsArr(remEqsSys,repl,NONE()); - sys.orderedEqs := eqArr; - sys.removedEqs := remEqsSys; - systs2 := sys::systs2; - end for; - systs2 := listReverse(systs2); - - // replace all init eqs, removed eqs, external var-bindings and alias var bindings, event-infos - initEqs := shared.initialEqs; - remEqs := shared.removedEqs; - extVars := shared.externalObjects; - aliasVars := shared.aliasVars; - eventInfo := shared.eventInfo; - (initEqs,_) := BackendVarTransform.replaceEquationsArr(initEqs,repl,NONE()); - (remEqs,_) := BackendVarTransform.replaceEquationsArr(remEqs,repl,NONE()); - extVars := BackendVariable.listVar1(List.map1(BackendVariable.varList(extVars),BackendVarTransform.replaceBindingExp,repl)); - aliasVars := BackendVariable.listVar1(List.map1(BackendVariable.varList(aliasVars),BackendVarTransform.replaceBindingExp,repl)); - eventInfo := BackendVarTransform.replaceEventInfo(eventInfo,repl,NONE()); - shared.initialEqs := initEqs; - shared.removedEqs := remEqs; - shared.externalObjects := extVars; - shared.aliasVars := aliasVars; - shared.eventInfo := eventInfo; - // set remaining, not evaluated params - shared.knownVars := BackendVariable.listVar(knVarsLst); - outDAE := BackendDAE.DAE(systs2,shared); - else - outDAE := inDAE; - end if; -end evaluateAllParameters; - - -protected function evaluateAllParameters0"evaluates a single parameter to constant or puts it in the knownVarsFold. The first array elements have to remain." - input BackendDAE.Var var; - input DAE.FunctionTree funcsIn; - input tuple> tplIn; - output tuple> tplOut; -algorithm - tplOut := matchcontinue(var,funcsIn,tplIn) - local - BackendVarTransform.VariableReplacements repl; - DAE.Exp bindExp; - DAE.ComponentRef cref; - list knVarsFold; - case(BackendDAE.VAR(varName = cref, bindExp = SOME(bindExp)),_,(repl,knVarsFold)) - algorithm - (bindExp,_) := BackendVarTransform.replaceExp(bindExp,repl,NONE()); - bindExp := ExpressionSimplify.simplify(bindExp); - bindExp := EvaluateFunctions.evaluateConstantFunctionCallExp(bindExp,funcsIn); - if ComponentReference.crefHaveSubs(BackendVariable.varCref(var)) and Expression.isConst(bindExp) then - // since we need the arrays to iterate over them, otherwise we would have to expand loops - repl := BackendVarTransform.addReplacement(repl,cref,bindExp,NONE()); - var.bindExp := SOME(bindExp); - knVarsFold := var::knVarsFold; - elseif Expression.isConst(bindExp) then - repl := BackendVarTransform.addReplacement(repl,cref,bindExp,NONE()); - else - knVarsFold := var::knVarsFold; - end if; - then (repl,knVarsFold); - else - tplIn; - end matchcontinue; -end evaluateAllParameters0; - public function evaluateFinalParameters "author Frenkel TUD @@ -1225,5 +1121,174 @@ algorithm end replaceEvaluatedParametersSystemEqns; + +//------------------------------------------ +// evaluate all parameters +//------------------------------------------ + +public function evaluateAllParameters +"author Waurich TUD + evaluates and replaces all parameters" + input BackendDAE.BackendDAE inDAE; + output BackendDAE.BackendDAE outDAE; +protected + Boolean evaluatedSomething; + Integer nVars,nEqs; + BackendDAE.Variables knvars, vars, extVars, aliasVars; + BackendDAE.EquationArray eqArr,initEqs,remEqs, remEqsSys; + BackendDAE.EqSystem sys; + BackendDAE.EqSystems systs, systs2; + BackendDAE.IncidenceMatrix m,mT; + BackendDAE.Shared shared; + BackendDAE.EventInfo eventInfo; + DAE.FunctionTree functionTree; + list bindExps; + list eqs, initEqLst, initEqLst2; + list knVarsLst, unknownVars, varLst; + BackendVarTransform.VariableReplacements repl; + array ass1, ass2; + list order; + list> comps; +algorithm + if Flags.isSet(Flags.EVAL_ALL_PARAMS) then + BackendDAE.DAE (systs, shared as BackendDAE.SHARED(knownVars=knvars, initialEqs=initEqs, functionTree=functionTree)) := inDAE; + knVarsLst := BackendVariable.varList(knvars); + //BackendDump.dumpVarList(knVarsLst,"knVarsLst"); + initEqLst := BackendEquation.equationList(initEqs); + initEqLst := List.filter1OnTrue(initEqLst, isParameterEquation, knvars); + repl := BackendVarTransform.emptyReplacements(); + (repl,unknownVars, evaluatedSomething) := getParameterBindingReplacements(knVarsLst, functionTree, repl); + + while evaluatedSomething and not listEmpty(unknownVars) loop + //use the evaluated parameters to evaluate more + (repl,unknownVars, evaluatedSomething) := getParameterBindingReplacements(unknownVars, functionTree, repl); + //BackendDump.dumpVarList(unknownVars,"UNKNOWNS2"); + end while; + + //Continue work from here... + repl := BackendVarTransform.getConstantReplacements(repl); + (initEqLst,_) := BackendVarTransform.replaceEquations(initEqLst,repl,NONE()); + unknownVars := List.filter1OnTrue(knVarsLst,BackendVarTransform.varHasNoReplacement,repl); + unknownVars := List.map1(unknownVars,BackendVarTransform.replaceBindingExp,repl); + //BackendDump.dumpEquationList(initEqLst,"initEqLst"); + if not listEmpty(unknownVars) then BackendDump.dumpVarList(unknownVars,"Could not evaluate following parameters. Ask a Developer for further support."); end if; + //BackendVarTransform.dumpReplacements(repl); + //...to here and extend the function evaluation (in simplifyReplacements) and evaluation of parameters (e.g. Modelica.Blocks.Examples.Filter.mo) + + systs2 := {}; + // replace all equations and all bindExps of the vars + for sys in systs loop + vars := sys.orderedVars; + varLst := BackendVariable.varList(vars); + varLst := List.map1(varLst,BackendVarTransform.replaceBindingExp,repl); + varLst := List.map1(varLst,BackendVarTransform.replaceVariableAttributesInVar,repl); + sys.orderedVars := BackendVariable.listVar1(varLst); + eqArr := sys.orderedEqs; + remEqsSys := sys.removedEqs; + (eqArr,_) := BackendVarTransform.replaceEquationsArr(eqArr,repl,NONE()); + (remEqsSys,_) := BackendVarTransform.replaceEquationsArr(remEqsSys,repl,NONE()); + sys.orderedEqs := eqArr; + sys.removedEqs := remEqsSys; + systs2 := sys::systs2; + end for; + systs2 := listReverse(systs2); + + // replace all init eqs, removed eqs, external var-bindings and alias var bindings, event-infos + initEqs := shared.initialEqs; + remEqs := shared.removedEqs; + extVars := shared.externalObjects; + aliasVars := shared.aliasVars; + eventInfo := shared.eventInfo; + (initEqs,_) := BackendVarTransform.replaceEquationsArr(initEqs,repl,NONE()); + (remEqs,_) := BackendVarTransform.replaceEquationsArr(remEqs,repl,NONE()); + extVars := BackendVariable.listVar1(List.map1(BackendVariable.varList(extVars),BackendVarTransform.replaceBindingExp,repl)); + aliasVars := BackendVariable.listVar1(List.map1(BackendVariable.varList(aliasVars),BackendVarTransform.replaceBindingExp,repl)); + eventInfo := BackendVarTransform.replaceEventInfo(eventInfo,repl,NONE()); + shared.initialEqs := initEqs; + shared.removedEqs := remEqs; + shared.externalObjects := extVars; + shared.aliasVars := aliasVars; + shared.eventInfo := eventInfo; + // set remaining, not evaluated params + shared.knownVars := BackendVariable.listVar(unknownVars); + outDAE := BackendDAE.DAE(systs2,shared); + else + outDAE := inDAE; + end if; +end evaluateAllParameters; + + +protected function getParameterBindingReplacements "gathers replacements for the vars with binding" + input list varsIn; + input DAE.FunctionTree functionTree; + input BackendVarTransform.VariableReplacements replIn; + output BackendVarTransform.VariableReplacements replOut; + output list unKnowns = {}; + output Boolean evaluatedSomething = false; +protected + BackendVarTransform.VariableReplacements repl; + DAE.ComponentRef cref; + BackendDAE.Var var; + DAE.Exp bindExp; +algorithm + repl := replIn; + for var in varsIn loop + if BackendVariable.varHasBindExp(var) then + bindExp := BackendVariable.varBindExp(var); + (bindExp,_) := BackendVarTransform.replaceExp(bindExp,repl,NONE()); + bindExp := EvaluateFunctions.evaluateConstantFunctionCallExp(bindExp,functionTree); + bindExp := ExpressionSimplify.simplify(bindExp); + if Expression.isEvaluatedConst(bindExp) then + //print("BIND "+ExpressionDump.printExpStr(bindExp)+"\n"); + //print("BIND "+ExpressionDump.dumpExpStr(bindExp,1)+"\n"); + cref := BackendVariable.varCref(var); + repl := BackendVarTransform.addReplacement(repl,cref,bindExp,NONE()); + evaluatedSomething := true; + else + unKnowns := var::unKnowns; + end if; + else + unKnowns := var::unKnowns; + end if; + end for; + replOut := BackendVarTransform.simplifyReplacements(repl,functionTree); +end getParameterBindingReplacements; + +protected function getParameterBindingEquations "gathers equations for the vars with binding" + input list varsIn; + input DAE.FunctionTree functionTree; + output list eqs; + output list unKnowns = {}; +protected + DAE.ComponentRef cref; + BackendDAE.Var var; + DAE.Exp bindExp; +algorithm + eqs := {}; + for var in varsIn loop + if BackendVariable.varHasBindExp(var) then + bindExp := BackendVariable.varBindExp(var); + bindExp := EvaluateFunctions.evaluateConstantFunctionCallExp(bindExp,functionTree); + bindExp := ExpressionSimplify.simplify(bindExp); + //print("BIND "+ExpressionDump.dumpExpStr(bindExp,1)+"\n"); + cref := BackendVariable.varCref(var); + eqs := BackendEquation.generateEquation(Expression.crefExp(cref), bindExp, DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC)::eqs; + else + unKnowns := var::unKnowns; + end if; + end for; +end getParameterBindingEquations; + +protected function isParameterEquation"outputs true if the equation is only dependent on parameters" + input BackendDAE.Equation eq; + input BackendDAE.Variables knownVars; + output Boolean b; +protected + list crefs; +algorithm + crefs := BackendEquation.equationCrefs(eq); + b := List.fold(List.map2(crefs,BackendVariable.existsVar,knownVars,false),boolAnd,true); +end isParameterEquation; + annotation(__OpenModelica_Interface="backend"); end EvaluateParameter; diff --git a/Compiler/FrontEnd/Expression.mo b/Compiler/FrontEnd/Expression.mo index a6da1e743cd..50824f183f7 100644 --- a/Compiler/FrontEnd/Expression.mo +++ b/Compiler/FrontEnd/Expression.mo @@ -7346,6 +7346,33 @@ algorithm outBoolean := isConstWork(inExp,true); end isConst; +public function isEvaluatedConst +"Returns true if an expression is really a constant scalar value. no calls, casts, or something" + input DAE.Exp inExp; + output Boolean outBoolean; +algorithm + outBoolean := isEvaluatedConstWork(inExp,true); +end isEvaluatedConst; + +protected function isEvaluatedConstWork +"Returns true if an expression is really constant" + input DAE.Exp inExp; + input Boolean inRes; + output Boolean outBoolean; +algorithm + outBoolean := match (inExp,inRes) + local + DAE.Exp e; + case (_,false) then false; + case (DAE.ICONST(),_) then true; + case (DAE.RCONST(),_) then true; + case (DAE.BCONST(),_) then true; + case (DAE.SCONST(),_) then true; + case (DAE.ENUM_LITERAL(),_) then true; + else false; + end match; +end isEvaluatedConstWork; + protected function isConstWork "Returns true if an expression is constant" input DAE.Exp inExp; diff --git a/Compiler/FrontEnd/ExpressionSimplify.mo b/Compiler/FrontEnd/ExpressionSimplify.mo index bddc3a5e16c..2bf41cf4d46 100644 --- a/Compiler/FrontEnd/ExpressionSimplify.mo +++ b/Compiler/FrontEnd/ExpressionSimplify.mo @@ -320,7 +320,7 @@ algorithm Boolean b2; Real r1,r2; String idn; - Integer n; + Integer n,i1,i2; // homotopy(e, e) => e case DAE.CALL(path=Absyn.IDENT("homotopy"),expLst={e1,e2}) @@ -424,6 +424,18 @@ algorithm then e; case (DAE.CALL(path=Absyn.IDENT("atan"),expLst={DAE.CALL(path=Absyn.IDENT("tan"),expLst={e})})) then e; + // modulo for real values + case (DAE.CALL(path=Absyn.IDENT("mod"),expLst={DAE.RCONST(r1),DAE.RCONST(r2)})) + equation + then DAE.RCONST(r1-floor(r1/r2)*r2); + // modulo for integer values + case (DAE.CALL(path=Absyn.IDENT("mod"),expLst={DAE.ICONST(i1),DAE.ICONST(i2)})) + equation + then DAE.ICONST(realInt(intReal(i1)-floor(intReal(i1)/intReal(i2))*intReal(i2))); + // integer call + case (DAE.CALL(path=Absyn.IDENT("integer"),expLst={DAE.RCONST(r1)})) + equation + then DAE.ICONST(realInt(r1)); // sin(acos(e)) = sqrt(1-e^2) case (DAE.CALL(path=Absyn.IDENT("sin"),expLst={DAE.CALL(path=Absyn.IDENT("acos"),expLst={e})})) then Expression.makePureBuiltinCall("sqrt",{DAE.BINARY(DAE.RCONST(1),DAE.SUB(DAE.T_REAL_DEFAULT),DAE.BINARY(e,DAE.MUL(DAE.T_REAL_DEFAULT),e))},DAE.T_REAL_DEFAULT);