Skip to content

Commit

Permalink
[NF] Evaluate actualStream.
Browse files Browse the repository at this point in the history
- Add missing evaluation of actualStream to ConnectEquations.
- Remove the associated flow cref stored in stream connectors,
  since it doesn't work for actualStream and we can just look it up
  in the type of the connector instead.

Belonging to [master]:
  - OpenModelica/OMCompiler#2642
  - OpenModelica/OpenModelica-testsuite#1029
  • Loading branch information
perost authored and OpenModelica-Hudson committed Sep 11, 2018
1 parent 661b595 commit 2fa8c5e
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 175 deletions.
5 changes: 5 additions & 0 deletions Compiler/NFFrontEnd/NFBuiltinFuncs.mo
Expand Up @@ -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;
7 changes: 7 additions & 0 deletions Compiler/NFFrontEnd/NFComponentRef.mo
Expand Up @@ -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;
Expand Down
251 changes: 103 additions & 148 deletions Compiler/NFFrontEnd/NFConnectEquations.mo
Expand Up @@ -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");
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand Down Expand Up @@ -528,7 +529,7 @@ protected
Option<Expression> 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
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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<list<Connector>> 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<DAE.Var> attr;
// Option<Values.Value> 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<DAE.Element> daeElements;
//protected
// list<DAE.Element> 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<DAE.Exp> conditions;
// input list<list<DAE.Element>> branches;
// input list<DAE.Element> elseBranch;
// output list<DAE.Element> elements;
//protected
// Boolean cond_value;
// list<list<DAE.Element>> 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<list<Connector>> 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<Expression> 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;
Expand All @@ -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;

0 comments on commit 2fa8c5e

Please sign in to comment.