Skip to content

Commit

Permalink
Improve handling of if/for containing connections (#11694)
Browse files Browse the repository at this point in the history
- Mark if-conditions/for-ranges as structural if they are parameter
  expressions and the if/for contains connections.

Fixes #11606
  • Loading branch information
perost committed Dec 7, 2023
1 parent b4056e3 commit 901e52a
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 21 deletions.
18 changes: 18 additions & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFComponent.mo
Expand Up @@ -357,6 +357,24 @@ public
end if;
end getImplicitBinding;

function getTypeAttributeBinding
input Component component;
input String attrName;
output Binding binding;
protected
InstNode start_node;
Component start_comp;
algorithm
try
start_node := Class.lookupElement(attrName, InstNode.getClass(classInstance(component)));
start_comp := InstNode.component(start_node);
true := Component.isTypeAttribute(start_comp);
binding := Component.getBinding(start_comp);
else
binding := NFBinding.EMPTY_BINDING;
end try;
end getTypeAttributeBinding;

function setBinding
input Binding binding;
input output Component component;
Expand Down
17 changes: 17 additions & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFEquation.mo
Expand Up @@ -45,6 +45,7 @@ protected
import FlatModelicaUtil = NFFlatModelicaUtil;
import IOStream;
import Util;
import Call = NFCall;

public
uniontype Branch
Expand Down Expand Up @@ -1180,6 +1181,7 @@ public
end replaceIteratorList;

function isConnect
"Checks if an equation is a connect equation."
input Equation eq;
output Boolean isConnect;
algorithm
Expand All @@ -1189,6 +1191,21 @@ public
end match;
end isConnect;

function isConnection
"Checks if an equation is a connect equation or a Connections.* call."
input Equation eq;
output Boolean res;
protected
Call call;
algorithm
res := match eq
case Equation.CONNECT() then true;
case Equation.NORETCALL(exp = Expression.CALL(call = call))
then Call.functionNameFirst(call) == "Connections";
else false;
end match;
end isConnection;

function sizeOfList
input list<Equation> eqs;
output Integer size = 0;
Expand Down
17 changes: 1 addition & 16 deletions OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -1708,7 +1708,7 @@ protected
InstNode scope;
algorithm
Equation.IF(branches = branches, scope = scope, source = src) := eq;
has_connect := Equation.contains(eq, isConnectEq);
has_connect := Equation.contains(eq, Equation.isConnection);

// Print errors for unbound constants/parameters if the if-equation contains
// connects, since we must select a branch in that case.
Expand Down Expand Up @@ -1792,21 +1792,6 @@ algorithm
end if;
end flattenIfEquation;

function isConnectEq
input Equation eq;
output Boolean isConnect;
algorithm
isConnect := match eq
local
Function fn;

case Equation.CONNECT() then true;
case Equation.NORETCALL(exp = Expression.CALL(call = Call.TYPED_CALL(fn = fn)))
then AbsynUtil.pathFirstIdent(Function.name(fn)) == "Connections";
else false;
end match;
end isConnectEq;

function flattenEqBranch
input output Equation.Branch branch;
input Prefix prefix;
Expand Down
13 changes: 9 additions & 4 deletions OMCompiler/Compiler/NFFrontEnd/NFStructural.mo
Expand Up @@ -58,11 +58,15 @@ public
output Boolean isStructural;
protected
Boolean is_fixed;
Binding binding;
algorithm
if compAttrs.variability <> Variability.PARAMETER then
// Only parameters can be structural.
isStructural := false;
elseif compEval or parentEval then
binding := if Binding.isBound(compBinding) then
compBinding else Component.getTypeAttributeBinding(component, "start");

// If the component or any of its parents has an Evaluate=true annotation
// we should probably evaluate the parameter, which we do by marking it as
// structural.
Expand All @@ -72,7 +76,7 @@ public
elseif Component.isExternalObject(component) then
// Except external objects.
isStructural := false;
elseif not InstNode.hasBinding(compNode) then
elseif not (Binding.isBound(binding) or InstNode.hasBinding(compNode)) then
// Except parameters with no bindings.
if not parentEval and not Flags.getConfigBool(Flags.CHECK_MODEL) then
// Print a warning if a parameter has an Evaluate=true annotation but no binding.
Expand All @@ -81,7 +85,7 @@ public
end if;

isStructural := false;
elseif isBindingNotFixed(compBinding, requireFinal = false) then
elseif isBindingNotFixed(binding, requireFinal = false) then
// Except parameters that depend on non-fixed parameters.
isStructural := false;
else
Expand All @@ -92,7 +96,7 @@ public
// // If a parameter is fixed and final we might also want to evaluate it,
// // since its binding can't be modified. But only if all parameters it
// // depends on are also fixed and final.
// if Binding.isUnbound(compBinding) or isBindingNotFixed(compBinding, requireFinal = true) then
// if Binding.isUnbound(binding) or isBindingNotFixed(binding, requireFinal = true) then
// isStructural := false;
// else
// isStructural := true;
Expand Down Expand Up @@ -143,7 +147,8 @@ public
if InstNode.isComponent(parent) and InstNode.isRecord(parent) then
isNotFixed := isComponentBindingNotFixed(InstNode.component(parent), parent, requireFinal, maxDepth, true);
else
isNotFixed := true;
binding := Component.getTypeAttributeBinding(component, "start");
isNotFixed := isBindingNotFixed(binding, requireFinal, maxDepth);
end if;
end if;
else
Expand Down
7 changes: 6 additions & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFTyping.mo
Expand Up @@ -2988,6 +2988,10 @@ algorithm
e1 := typeIterator(eq.iterator, e1, context, structural = true);
next_context := InstContext.set(context, NFInstContext.FOR);
body := list(typeEquation(e, next_context) for e in eq.body);

if Equation.containsList(body, Equation.isConnection) then
Structural.markExp(e1);
end if;
then
Equation.FOR(eq.iterator, SOME(e1), body, eq.scope, eq.source);

Expand Down Expand Up @@ -3497,7 +3501,8 @@ algorithm
// connections in the branch, mark the context so we can check that when
// typing the body of the branch.
next_context := InstContext.set(next_context, NFInstContext.NONEXPANDABLE);
elseif var == Variability.PARAMETER and accum_var <= Variability.PARAMETER then
elseif var == Variability.PARAMETER and
(accum_var <= Variability.PARAMETER or Equation.containsList(eql, Equation.isConnection)) then
// If all conditions up to and including this one are parameter
// expressions, consider the condition to be structural.
var := Variability.STRUCTURAL_PARAMETER;
Expand Down
51 changes: 51 additions & 0 deletions testsuite/flattening/modelica/scodeinst/ForConnect2.mo
@@ -0,0 +1,51 @@
// name: ForConnect2
// keywords:
// status: correct
// cflags: -d=newInst
//
//

connector C
Real e;
flow Real f;
end C;

model ForConnect2
C c1[3], c2[3];
parameter Integer n(start = 3);
equation
for i in 1:n loop
connect(c1[i], c2[i]);
end for;
end ForConnect2;

// Result:
// class ForConnect2
// Real c1[1].e;
// Real c1[1].f;
// Real c1[2].e;
// Real c1[2].f;
// Real c1[3].e;
// Real c1[3].f;
// Real c2[1].e;
// Real c2[1].f;
// Real c2[2].e;
// Real c2[2].f;
// Real c2[3].e;
// Real c2[3].f;
// final parameter Integer n(start = 3);
// equation
// c1[1].e = c2[1].e;
// (-c1[1].f) - c2[1].f = 0.0;
// c1[2].e = c2[2].e;
// (-c1[2].f) - c2[2].f = 0.0;
// c1[3].e = c2[3].e;
// (-c1[3].f) - c2[3].f = 0.0;
// c1[1].f = 0.0;
// c1[2].f = 0.0;
// c1[3].f = 0.0;
// c2[1].f = 0.0;
// c2[2].f = 0.0;
// c2[3].f = 0.0;
// end ForConnect2;
// endResult
35 changes: 35 additions & 0 deletions testsuite/flattening/modelica/scodeinst/IfConnect4.mo
@@ -0,0 +1,35 @@
// name: IfConnect4
// keywords:
// status: correct
// cflags: -d=newInst
//
//

connector C
Real e;
flow Real f;
end C;

model IfConnect4
parameter Boolean b(start = true);
C c1, c2;
equation
if b then
connect(c1, c2);
end if;
end IfConnect4;

// Result:
// class IfConnect4
// final parameter Boolean b(start = true);
// Real c1.e;
// Real c1.f;
// Real c2.e;
// Real c2.f;
// equation
// c1.e = c2.e;
// (-c1.f) - c2.f = 0.0;
// c1.f = 0.0;
// c2.f = 0.0;
// end IfConnect4;
// endResult
2 changes: 2 additions & 0 deletions testsuite/flattening/modelica/scodeinst/Makefile
Expand Up @@ -514,6 +514,7 @@ Final5.mo \
Final6.mo \
Final7.mo \
ForConnect1.mo \
ForConnect2.mo \
ForEquation1.mo \
ForEquation2.mo \
ForEquation3.mo \
Expand Down Expand Up @@ -705,6 +706,7 @@ FunctionUnitialized4.mo \
IfConnect1.mo \
IfConnect2.mo \
IfConnect3.mo \
IfConnect4.mo \
IfEquation1.mo \
IfEquation2.mo \
IfEquation3.mo \
Expand Down

0 comments on commit 901e52a

Please sign in to comment.