diff --git a/Compiler/BackEnd/BackendDAEOptimize.mo b/Compiler/BackEnd/BackendDAEOptimize.mo index 5458ec26c32..b9d1895ab09 100644 --- a/Compiler/BackEnd/BackendDAEOptimize.mo +++ b/Compiler/BackEnd/BackendDAEOptimize.mo @@ -110,6 +110,122 @@ algorithm outDAE.shared := shared; end simplifyAllExpressions; +// ============================================================================= +// simplifyInStream +// +// OM introduces $OMC$PosetiveMax which can simplified using min or max attribute +// see Modelica spec for inStream +// author: Vitalij Ruge +// see. #3885, 4441 +// ============================================================================= + +public function simplifyInStream + input output BackendDAE.BackendDAE dae; +protected + BackendDAE.Shared shared = dae.shared; + BackendDAE.EqSystems eqs = dae.eqs; + list vars = list(eq.orderedVars for eq in eqs); +algorithm + // from the description inputs are part of globalKnownVars and localKnownVars :( + vars := shared.globalKnownVars :: vars; // need inputs with min = 0 or max = 0 + vars := shared.localKnownVars :: vars; + _ := BackendDAEUtil.traverseBackendDAEExpsNoCopyWithUpdate(dae, simplifyInStreamWork, vars); +end simplifyInStream; + + +protected function simplifyInStreamWork + input DAE.Exp inExp; + input list inVars; + output DAE.Exp outExp; + output list outVars = inVars; +algorithm + outExp := Expression.traverseExpBottomUp(inExp, simplifyInStreamWork2, outVars); +end simplifyInStreamWork; + +protected function simplifyInStreamWork2 + input DAE.Exp inExp; + input list inVars; + output DAE.Exp outExp; + output list outVars = inVars; +algorithm + outExp := match(inExp) + local DAE.Type tp; + DAE.ComponentRef cr; + DAE.Exp e, expr; + Option eMin; + Option eMax; + Boolean isZero; + + + case DAE.CALL(path=Absyn.IDENT("$OMC$PositiveMax"),expLst={e as DAE.CREF(componentRef=cr), expr}) + algorithm + (eMin, eMax) := simplifyInStreamWorkExpresion(cr, outVars); + isZero := simplifyInStreamWorkSimplify(eMin, false); + tp := ComponentReference.crefTypeFull(cr); + then + if isZero then e else Expression.makePureBuiltinCall("max", {e, expr}, tp); + + case DAE.CALL(path=Absyn.IDENT("$OMC$PositiveMax"),expLst={e as DAE.UNARY(DAE.UMINUS(tp), DAE.CREF(componentRef=cr)), expr}) + algorithm + (eMin, eMax) := simplifyInStreamWorkExpresion(cr, outVars); + isZero := simplifyInStreamWorkSimplify(eMax, true); + then + if isZero then Expression.createZeroExpression(tp) else Expression.makePureBuiltinCall("max", {e, expr}, tp); + + case DAE.CALL(path=Absyn.IDENT("$OMC$PositiveMax"),expLst={e, expr}) + guard Expression.isZero(e) + then e; + + case DAE.CALL(path=Absyn.IDENT("$OMC$PositiveMax"),expLst={e, expr}) + //algorithm + //print("\nsimplifyInStreamWork: "); + //print(ExpressionDump.printExpStr(inExp)); + //print(" <-> "); + //print(ExpressionDump.printExpStr(e)); + + then Expression.makePureBuiltinCall("max", {e, expr}, Expression.typeof(e)); + + case _ + then inExp; + end match; + +end simplifyInStreamWork2; + +protected function simplifyInStreamWorkExpresion + input DAE.ComponentRef cr; + input list inVars; + output Option outMin = NONE(); + output Option outMax = NONE(); +protected + BackendDAE.Var v; +algorithm + for vars in inVars loop + try + (v, _) := BackendVariable.getVarSingle(cr, vars); + (outMin, outMax) := BackendVariable.getMinMaxAttribute(v); + break; + else + // search + end try; + end for; + +end simplifyInStreamWorkExpresion; + +protected function simplifyInStreamWorkSimplify + input Option bound; + input Boolean neg; + output Boolean isZero; +algorithm + isZero := match bound + local Real r; + case SOME(DAE.RCONST(r)) + then if neg then r<= 0.0 else r >= 0.0; + case _ + then false; + end match; +end simplifyInStreamWorkSimplify; + + // ============================================================================= // simplify time independent function calls // diff --git a/Compiler/BackEnd/BackendDAEUtil.mo b/Compiler/BackEnd/BackendDAEUtil.mo index c73a40b1fe7..c748195fc07 100644 --- a/Compiler/BackEnd/BackendDAEUtil.mo +++ b/Compiler/BackEnd/BackendDAEUtil.mo @@ -7495,6 +7495,7 @@ public function allPreOptimizationModules (BackendDAEOptimize.removeUnusedVariables, "removeUnusedVariables"), (BackendDAEOptimize.residualForm, "residualForm"), (BackendDAEOptimize.simplifyAllExpressions, "simplifyAllExpressions"), + (BackendDAEOptimize.simplifyInStream, "simplifyInStream"), (BackendDump.dumpDAE, "dumpDAE"), (XMLDump.dumpDAEXML, "dumpDAEXML"), // This should indeed be at the end @@ -7621,6 +7622,10 @@ algorithm preOptModules := getPreOptModulesString(); preOptModules := Util.getOptionOrDefault(inPreOptModules, preOptModules); + if isSome(getGlobalRoot(Global.isInStream)) then + enabledModules := "simplifyInStream"::enabledModules; + end if; + if Flags.getConfigBool(Flags.DEFAULT_OPT_MODULES_ORDERING) then // handle special flags, which enable modules diff --git a/Compiler/FrontEnd/ConnectUtil.mo b/Compiler/FrontEnd/ConnectUtil.mo index a0dca169098..c149b19172d 100644 --- a/Compiler/FrontEnd/ConnectUtil.mo +++ b/Compiler/FrontEnd/ConnectUtil.mo @@ -74,6 +74,7 @@ import PrefixUtil; import System; import Types; import Util; +import Global; // Import some types from Connect. import Connect.Face; @@ -1408,6 +1409,7 @@ protected Boolean has_stream, has_expandable, has_cardinality; ConnectionGraph.DaeEdges broken, connected; algorithm + setGlobalRoot(Global.isInStream, NONE()); if not topScope then return; end if; @@ -2321,7 +2323,7 @@ algorithm end if; positiveMaxCall := - DAE.CALL(Absyn.IDENT("max"), {flowExp, flow_threshold}, + DAE.CALL(Absyn.IDENT("$OMC$PositiveMax"), {flowExp, flow_threshold}, DAE.CALL_ATTR( ty, false, @@ -2330,6 +2332,8 @@ algorithm false, DAE.NO_INLINE(), DAE.NO_TAIL())); + + setGlobalRoot(Global.isInStream, SOME(true)); end makePositiveMaxCall; protected function evaluateConnectionOperators diff --git a/Compiler/Global/Global.mo b/Compiler/Global/Global.mo index b72dedf91a9..f19641bce81 100644 --- a/Compiler/Global/Global.mo +++ b/Compiler/Global/Global.mo @@ -64,6 +64,7 @@ constant Integer currentInstVar = 22; constant Integer operatorOverloadingCache = 23; constant Integer optionSimCode = 24; constant Integer interactiveCache = 25; +constant Integer isInStream = 26; // indexes in System.tick // ----------------------