diff --git a/Compiler/NFFrontEnd/NFBuiltinFuncs.mo b/Compiler/NFFrontEnd/NFBuiltinFuncs.mo index 17349e7bdd3..f7285f1c397 100644 --- a/Compiler/NFFrontEnd/NFBuiltinFuncs.mo +++ b/Compiler/NFFrontEnd/NFBuiltinFuncs.mo @@ -276,5 +276,10 @@ constant Function FILL_FUNC = Function.FUNCTION(Path.IDENT("fill"), Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {}, Pointer.createImmutable(true), Pointer.createImmutable(0)); +constant Function SMOOTH = Function.FUNCTION(Path.IDENT("smooth"), + InstNode.EMPTY_NODE(), {}, {}, {}, {}, + Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {}, + Pointer.createImmutable(true), Pointer.createImmutable(0)); + annotation(__OpenModelica_Interface="frontend"); end NFBuiltinFuncs; diff --git a/Compiler/NFFrontEnd/NFComponentRef.mo b/Compiler/NFFrontEnd/NFComponentRef.mo index c779c3a6cea..287d2f3b47b 100644 --- a/Compiler/NFFrontEnd/NFComponentRef.mo +++ b/Compiler/NFFrontEnd/NFComponentRef.mo @@ -175,6 +175,13 @@ public CREF(node = node) := cref; end node; + function nodeType + input ComponentRef cref; + output Type ty; + algorithm + CREF(ty = ty) := cref; + end nodeType; + function firstName input ComponentRef cref; output String name; diff --git a/Compiler/NFFrontEnd/NFConnectEquations.mo b/Compiler/NFFrontEnd/NFConnectEquations.mo index 3b81ba4ef13..bd188ba42c1 100644 --- a/Compiler/NFFrontEnd/NFConnectEquations.mo +++ b/Compiler/NFFrontEnd/NFConnectEquations.mo @@ -63,6 +63,7 @@ import NFBinding.Binding; import NFFunction.Function; import Global; import BuiltinCall = NFBuiltinCall; +import ComplexType = NFComplexType; constant Expression EQ_ASSERT_STR = Expression.STRING("Connected constants/parameters must be equal"); @@ -429,11 +430,11 @@ function streamFlowExp output Expression streamExp; output Expression flowExp; protected - ComponentRef flow_cr; + ComponentRef stream_cr; algorithm - Connector.CONNECTOR(associatedFlow = SOME(flow_cr)) := element; - streamExp := Expression.fromCref(element.name); - flowExp := Expression.fromCref(flow_cr); + stream_cr := Connector.name(element); + streamExp := Expression.fromCref(stream_cr); + flowExp := Expression.fromCref(associatedFlowCref(stream_cr)); end streamFlowExp; function flowExp @@ -443,7 +444,7 @@ function flowExp protected ComponentRef flow_cr; algorithm - Connector.CONNECTOR(associatedFlow = SOME(flow_cr)) := element; + flow_cr := associatedFlowCref(Connector.name(element)); flowExp := Expression.fromCref(flow_cr); end flowExp; @@ -528,7 +529,7 @@ protected Option nominal_oexp; Expression nominal_exp, flow_threshold; algorithm - flow_node := ComponentRef.node(Connector.flowCref(element)); + flow_node := ComponentRef.node(associatedFlowCref(Connector.name(element))); nominal_oexp := Class.lookupAttributeValue("nominal", InstNode.getClass(flow_node)); if isSome(nominal_oexp) then @@ -559,8 +560,8 @@ algorithm then match Function.name(call.fn) case Absyn.IDENT("inStream") then evaluateInStream(Expression.toCref(listHead(call.arguments)), sets, setsArray, ctable); - //case Absyn.IDENT("actualStream") - // then evaluateActualStream(Expression.toCref(listHead(call.arguments)), sets, setsArray); + case Absyn.IDENT("actualStream") + then evaluateActualStream(Expression.toCref(listHead(call.arguments)), sets, setsArray, ctable); case Absyn.IDENT("cardinality") then CardinalityTable.evaluateCardinality(listHead(call.arguments), ctable); else exp; @@ -583,7 +584,7 @@ protected Integer set; algorithm c := Connector.CONNECTOR(cref, Type.UNKNOWN(), Face.INSIDE, - ConnectorType.STREAM, NONE(), DAE.emptyElementSource); + ConnectorType.STREAM, DAE.emptyElementSource); try set := ConnectionSets.findSetArrayIndex(c, sets); @@ -691,145 +692,78 @@ algorithm end if; end isZeroFlow; -//protected function evaluateActualStream -// "This function evaluates the actualStream operator for a component reference, -// given the connection sets." -// input DAE.ComponentRef streamCref; -// input ConnectionSets.Sets sets; -// input array> setsArray; -// input Expression flowThreshold; -// output DAE.Exp exp; -//protected -// DAE.ComponentRef flow_cr; -// DAE.Exp e, flow_exp, stream_exp, instream_exp, rel_exp; -// DAE.Type ety; -// Integer flow_dir; -//algorithm -// //flow_cr := getStreamFlowAssociation(streamCref, sets); -// //ety := ComponentReference.crefLastType(flow_cr); -// //flow_dir := evaluateFlowDirection(ety); -// -// //// Select a branch if we know the flow direction, otherwise generate the whole -// //// if-equation. -// //if flow_dir == 1 then -// // rel_exp := evaluateInStream(streamCref, sets, setsArray, flowThreshold); -// //elseif flow_dir == -1 then -// // rel_exp := Expression.crefExp(streamCref); -// //else -// // flow_exp := Expression.crefExp(flow_cr); -// // stream_exp := Expression.crefExp(streamCref); -// // instream_exp := evaluateInStream(streamCref, sets, setsArray, flowThreshold); -// // rel_exp := DAE.IFEXP( -// // DAE.RELATION(flow_exp, DAE.GREATER(ety), DAE.RCONST(0.0), -1, NONE()), -// // instream_exp, stream_exp); -// //end if; -// -// //// actualStream(stream_var) = smooth(0, if flow_var > 0 then inStream(stream_var) -// //// else stream_var); -// //exp := DAE.CALL(Absyn.IDENT("smooth"), {DAE.ICONST(0), rel_exp}, -// // DAE.callAttrBuiltinReal); -// -// exp := DAE.ICONST(0); -//end evaluateActualStream; -// -//protected function evaluateFlowDirection -// "Checks the min/max attributes of a flow variables type to try and determine -// the flow direction. If the flow is positive 1 is returned, if it is negative -// -1, otherwise 0 if the direction can't be decided." -// input DAE.Type ty; -// output Integer direction = 0; -//protected -// list attr; -// Option min_oval, max_oval; -// Real min_val, max_val; -//algorithm -// attr := Types.getAttributes(ty); -// if listEmpty(attr) then return; end if; -// -// min_oval := Types.lookupAttributeValue(attr, "min"); -// max_oval := Types.lookupAttributeValue(attr, "max"); -// -// direction := match (min_oval, max_oval) -// // No attributes, flow direction can't be decided. -// case (NONE(), NONE()) then 0; -// // Flow is positive if min is positive. -// case (SOME(Values.REAL(min_val)), NONE()) -// then if min_val >= 0 then 1 else 0; -// // Flow is negative if max is negative. -// case (NONE(), SOME(Values.REAL(max_val))) -// then if max_val <= 0 then -1 else 0; -// // Flow is positive if both min and max are positive, negative if they are -// // both negative, otherwise undecideable. -// case (SOME(Values.REAL(min_val)), SOME(Values.REAL(max_val))) -// then -// if min_val >= 0 and max_val >= min_val then 1 -// elseif max_val <= 0 and min_val <= max_val then -1 -// else 0; -// else 0; -// end match; -//end evaluateFlowDirection; -// -//function evaluateCardinality -// input DAE.ComponentRef cref; -// input ConnectionSets.Sets sets; -// output DAE.Exp exp; -//algorithm -// // TODO: Implement this. -// //exp := DAE.ICONST(getConnectCount(cref, sets.sets)); -// exp := DAE.Exp.ICONST(0); -//end evaluateCardinality; -// -//function simplifyDAEElements -//"run this only if we have cardinality" -// input Boolean hasCardinality; -// input output list daeElements; -//protected -// list accum = {}; -//algorithm -// if not hasCardinality then -// return; -// end if; -// -// for e in daeElements loop -// accum := matchcontinue e -// case DAE.IF_EQUATION() -// then listAppend(simplifyDAEIfEquation(e.condition1, e.equations2, e.equations3), accum); -// case DAE.INITIAL_IF_EQUATION() -// then listAppend(simplifyDAEIfEquation(e.condition1, e.equations2, e.equations3), accum); -// case DAE.ASSERT(condition = DAE.BCONST(true)) then accum; -// else e :: accum; -// end matchcontinue; -// end for; -// -// daeElements := listReverse(accum); -//end simplifyDAEElements; -// -//protected function simplifyDAEIfEquation -// input list conditions; -// input list> branches; -// input list elseBranch; -// output list elements; -//protected -// Boolean cond_value; -// list> rest_branches = branches; -//algorithm -// for cond in conditions loop -// DAE.BCONST(cond_value) := cond; -// -// // Condition is true, substitute the if-equation with the branch contents. -// if cond_value == true then -// elements := listReverse(listHead(rest_branches)); -// return; -// end if; -// -// // Condition is false, discard the branch and continue with the other branches. -// rest_branches := listRest(rest_branches); -// end for; -// -// // All conditions were false, substitute if-equation with else-branch contents. -// elements := listReverse(elseBranch); -//end simplifyDAEIfEquation; -// +protected function evaluateActualStream + "This function evaluates the actualStream operator for a component reference, + given the connection sets." + input ComponentRef streamCref; + input ConnectionSets.Sets sets; + input array> setsArray; + input CardinalityTable.Table ctable; + output Expression exp; +protected + ComponentRef flow_cr; + Integer flow_dir; + Expression rel_exp, flow_exp, stream_exp, instream_exp; + Operator op; +algorithm + flow_cr := associatedFlowCref(streamCref); + flow_dir := evaluateFlowDirection(flow_cr); + + // Select a branch if we know the flow direction, otherwise generate the whole + // if-equation. + if flow_dir == 1 then + rel_exp := evaluateInStream(streamCref, sets, setsArray, ctable); + elseif flow_dir == -1 then + rel_exp := Expression.fromCref(streamCref); + else + flow_exp := Expression.fromCref(flow_cr); + stream_exp := Expression.fromCref(streamCref); + instream_exp := evaluateInStream(streamCref, sets, setsArray, ctable); + op := Operator.makeGreater(ComponentRef.nodeType(flow_cr)); + rel_exp := Expression.IF( + Expression.RELATION(flow_exp, op, Expression.REAL(0.0)), + instream_exp, stream_exp); + end if; + + // actualStream(stream_var) = smooth(0, if flow_var > 0 then inStream(stream_var) + // else stream_var); + exp := Expression.CALL(Call.makeTypedCall(NFBuiltinFuncs.SMOOTH, + {DAE.INTEGER(0), rel_exp}, Expression.variability(rel_exp))); +end evaluateActualStream; + +function evaluateFlowDirection + input ComponentRef flowCref; + output Integer direction = 0; +protected + Class flow_cls; + Option omin, omax; + Real min_val, max_val; +algorithm + flow_cls := InstNode.getClass(ComponentRef.node(flowCref)); + omin := Class.lookupAttributeValue("min", flow_cls); + omax := Class.lookupAttributeValue("max", flow_cls); + + direction := match (omin, omax) + // No attributes, flow direction can't be decided. + case (NONE(), NONE()) then 0; + // Flow is positive if min is positive. + case (SOME(Expression.REAL(min_val)), NONE()) + then if min_val >= 0 then 1 else 0; + // Flow is negative if max is negative. + case (NONE(), SOME(Expression.REAL(max_val))) + then if max_val <= 0 then -1 else 0; + // Flow is positive if both min and max are positive, negative if they are + // both negative, otherwise undecideable. + case (SOME(Expression.REAL(min_val)), SOME(Expression.REAL(max_val))) + then + if min_val >= 0 and max_val >= min_val then 1 + elseif max_val <= 0 and min_val <= max_val then -1 + else 0; + // Flow is undecideable if either attribute is not a constant Real value. + else 0; + end match; +end evaluateFlowDirection; + protected function removeStreamSetElement "This function removes the given cref from a connection set." input ComponentRef cref; @@ -848,5 +782,26 @@ algorithm matches := ComponentRef.isEqual(cref, element.name); end compareCrefStreamSet; +function associatedFlowCref + "Returns the flow cref that's declared in the same connector as the given + stream cref." + input ComponentRef streamCref; + output ComponentRef flowCref; +algorithm + flowCref := match streamCref + local + InstNode flow_node; + + // A connector with a single flow, append the flow node to the cref and return it. + case ComponentRef.CREF(ty = Type.COMPLEX(complexTy = ComplexType.CONNECTOR(flows = {flow_node}))) + then ComponentRef.prefixCref(flow_node, InstNode.getType(flow_node), {}, streamCref); + + // Otherwise, remove the first part of the cref and try again. + case ComponentRef.CREF() + then associatedFlowCref(streamCref.restCref); + + end match; +end associatedFlowCref; + annotation(__OpenModelica_Interface="frontend"); end NFConnectEquations; diff --git a/Compiler/NFFrontEnd/NFConnector.mo b/Compiler/NFFrontEnd/NFConnector.mo index 0eb526d29cb..7baeab7980b 100644 --- a/Compiler/NFFrontEnd/NFConnector.mo +++ b/Compiler/NFFrontEnd/NFConnector.mo @@ -57,7 +57,6 @@ public Type ty; Face face; ConnectorType cty; - Option associatedFlow; DAE.ElementSource source; end CONNECTOR; @@ -78,7 +77,7 @@ public InstNode node = ComponentRef.node(cref); algorithm conn := CONNECTOR(ComponentRef.simplifySubscripts(cref), ty, face, - Component.connectorType(InstNode.component(node)), NONE(), source); + Component.connectorType(InstNode.component(node)), source); end fromFacedCref; function fromExp @@ -182,13 +181,6 @@ public connl := splitImpl(conn.name, conn.ty, conn.face, conn.source, conn.cty); end split; - function flowCref - input Connector conn; - output ComponentRef cref; - algorithm - SOME(cref) := conn.associatedFlow; - end flowCref; - protected function crefFace "Determines whether a cref refers to an inside or outside connector, where @@ -212,25 +204,19 @@ protected input Face face; input DAE.ElementSource source; input ConnectorType cty; - input Option associatedFlow = NONE(); input output list conns = {}; algorithm conns := match ty local Type t; ComplexType ct; - Option aflow; ClassTree tree; case Type.COMPLEX(complexTy = ct as ComplexType.CONNECTOR()) algorithm - conns := splitImpl2(name, face, source, ct.potentials, NONE(), conns); - conns := splitImpl2(name, face, source, ct.flows, NONE(), conns); - - if not listEmpty(ct.streams) then - aflow := SOME(Connector.name(listHead(conns))); - conns := splitImpl2(name, face, source, ct.streams, aflow, conns); - end if; + conns := splitImpl2(name, face, source, ct.potentials, conns); + conns := splitImpl2(name, face, source, ct.flows, conns); + conns := splitImpl2(name, face, source, ct.streams, conns); then conns; @@ -238,7 +224,7 @@ protected algorithm tree := Class.classTree(InstNode.getClass(ty.cls)); conns := splitImpl2(name, face, source, - arrayList(ClassTree.getComponents(tree)), associatedFlow, conns); + arrayList(ClassTree.getComponents(tree)), conns); then conns; @@ -246,12 +232,12 @@ protected algorithm t := Type.arrayElementType(ty); for c in ComponentRef.scalarize(name) loop - conns := splitImpl(c, t, face, source, cty, associatedFlow, conns); + conns := splitImpl(c, t, face, source, cty, conns); end for; then conns; - else CONNECTOR(name, ty, face, cty, associatedFlow, source) :: conns; + else CONNECTOR(name, ty, face, cty, source) :: conns; end match; end splitImpl; @@ -260,7 +246,6 @@ protected input Face face; input DAE.ElementSource source; input list comps; - input Option associatedFlow; input output list conns; protected Component c; @@ -273,7 +258,7 @@ protected ty := Component.getType(c); cty := Component.connectorType(c); cref := ComponentRef.append(ComponentRef.fromNode(comp, ty), name); - conns := splitImpl(cref, ty, face, source, cty, associatedFlow, conns); + conns := splitImpl(cref, ty, face, source, cty, conns); end for; end splitImpl2; diff --git a/Compiler/Util/DisjointSets.mo b/Compiler/Util/DisjointSets.mo index 79e5422a89a..5992bf5021d 100644 --- a/Compiler/Util/DisjointSets.mo +++ b/Compiler/Util/DisjointSets.mo @@ -208,14 +208,13 @@ function find input output Sets sets; output Integer index; algorithm - // TODO: Replace with try once the bootstrapping has been updated. - _ := matchcontinue () case () algorithm + try // Check if a node already exists in the forest. index := BaseHashTable.get(entry, sets.elements); - then (); else algorithm + else // If a node doesn't already exist, create a new one. (sets, index) := add(entry, sets); - then (); end matchcontinue; + end try; end find; function findRoot