#5834 closed discussion (invalid)
Automatic sum using inner outer keywords behaves diferently in new frontend
Reported by: | Owned by: | Francesco Casella | |
---|---|---|---|
Priority: | normal | Milestone: | 1.14.1 |
Component: | Frontend | Version: | v1.14.1 |
Keywords: | inner outer flow connect | Cc: |
Description
I developed a method for summing(collecting) set of Real values from across instances into one global instance.
Please consider this Modelica code as MWE:
Example package:
package global_sum_test connector Sum_port flow Real a; flow Real b; end Sum_port; model Global Sum_port sum; annotation(defaultComponentName = "global"); end Global; model Sum_adder outer Global global; outer Sum_port sum; //consider having or not having the outer keyword in front of this declaration Real a; Real b; equation sum.a = a; sum.b = b; connect(sum, global.sum); end Sum_adder; model Local parameter Real a = 0.5; parameter Real b = 1.0; Sum_adder sum_adder(a=a,b=b); end Local; model Local_nested parameter Real a = 0.5; parameter Real b = 1.0; Sum_adder sum_adder(a=a,b=b); Local local; end Local_nested; model test_model inner global_sum_test.Global global; Local local; Local_nested local_nested; end test_model; end global_sum_test;
Old frontend Instantiating global_sum_test.test_model:
"outer" keyword not present:
class global_sum_test.test_model Real global.sum.a; Real global.sum.b; parameter Real local.a = 0.5; parameter Real local.b = 1.0; Real local.sum_adder.sum.a; Real local.sum_adder.sum.b; Real local.sum_adder.a = local.a; Real local.sum_adder.b = local.b; parameter Real local_nested.a = 0.5; parameter Real local_nested.b = 1.0; Real local_nested.sum_adder.sum.a; Real local_nested.sum_adder.sum.b; Real local_nested.sum_adder.a = local_nested.a; Real local_nested.sum_adder.b = local_nested.b; parameter Real local_nested.local.a = 0.5; parameter Real local_nested.local.b = 1.0; Real local_nested.local.sum_adder.sum.a; Real local_nested.local.sum_adder.sum.b; Real local_nested.local.sum_adder.a = local_nested.local.a; Real local_nested.local.sum_adder.b = local_nested.local.b; equation local.sum_adder.sum.a = local.sum_adder.a; local.sum_adder.sum.b = local.sum_adder.b; local_nested.sum_adder.sum.a = local_nested.sum_adder.a; local_nested.sum_adder.sum.b = local_nested.sum_adder.b; local_nested.local.sum_adder.sum.a = local_nested.local.sum_adder.a; local_nested.local.sum_adder.sum.b = local_nested.local.sum_adder.b; global.sum.b + (-local.sum_adder.sum.b) + (-local_nested.local.sum_adder.sum.b) + (-local_nested.sum_adder.sum.b) = 0.0; global.sum.a + (-local.sum_adder.sum.a) + (-local_nested.local.sum_adder.sum.a) + (-local_nested.sum_adder.sum.a) = 0.0; local.sum_adder.sum.b = 0.0; local.sum_adder.sum.a = 0.0; local_nested.local.sum_adder.sum.b = 0.0; local_nested.local.sum_adder.sum.a = 0.0; local_nested.sum_adder.sum.b = 0.0; local_nested.sum_adder.sum.a = 0.0; end global_sum_test.test_model;
which obviously does not work since the system is overdetermined by additional 6 equations generated at the end.
So I added the "outer" keyword in front of the commented declaration. It complains but compiles and everything is working.
[5] 22:02:03 Translation Error [global_sum_test: 21:5-21:29]: The language feature Connections where both connectors are outer references is not supported. Suggested workaround: No suggestion
"outer" keyword is present:
class global_sum_test.test_model Real global.sum.a; Real global.sum.b; parameter Real local.a = 0.5; parameter Real local.b = 1.0; Real local.sum_adder.sum.a; Real local.sum_adder.sum.b; Real local.sum_adder.a = local.a; Real local.sum_adder.b = local.b; parameter Real local_nested.a = 0.5; parameter Real local_nested.b = 1.0; Real local_nested.sum_adder.sum.a; Real local_nested.sum_adder.sum.b; Real local_nested.sum_adder.a = local_nested.a; Real local_nested.sum_adder.b = local_nested.b; parameter Real local_nested.local.a = 0.5; parameter Real local_nested.local.b = 1.0; Real local_nested.local.sum_adder.sum.a; Real local_nested.local.sum_adder.sum.b; Real local_nested.local.sum_adder.a = local_nested.local.a; Real local_nested.local.sum_adder.b = local_nested.local.b; equation local.sum_adder.sum.a = local.sum_adder.a; local.sum_adder.sum.b = local.sum_adder.b; local_nested.sum_adder.sum.a = local_nested.sum_adder.a; local_nested.sum_adder.sum.b = local_nested.sum_adder.b; local_nested.local.sum_adder.sum.a = local_nested.local.sum_adder.a; local_nested.local.sum_adder.sum.b = local_nested.local.sum_adder.b; global.sum.b + (-local.sum_adder.sum.b) + (-local_nested.local.sum_adder.sum.b) + (-local_nested.sum_adder.sum.b) = 0.0; global.sum.a + (-local.sum_adder.sum.a) + (-local_nested.local.sum_adder.sum.a) + (-local_nested.sum_adder.sum.a) = 0.0; end global_sum_test.test_model;
which removes the 6 additional equations and makes the method work excellently.
I am not sure what the specification of Modelica says here, but I guess it works because it cannot find the inner declaration of the Sum_port and therefore somehow does not generate the 6 equations which would break it.
New frontend Instantiating global_sum_test.test_model:
The new frontend does behave the same in the first case (except it reorders the generated equations).
"outer" keyword not present:
class global_sum_test.test_model Real global.sum.a; Real global.sum.b; parameter Real local.a = 0.5; parameter Real local.b = 1.0; Real local.sum_adder.sum.a; Real local.sum_adder.sum.b; Real local.sum_adder.a = local.a; Real local.sum_adder.b = local.b; parameter Real local_nested.a = 0.5; parameter Real local_nested.b = 1.0; Real local_nested.sum_adder.sum.a; Real local_nested.sum_adder.sum.b; Real local_nested.sum_adder.a = local_nested.a; Real local_nested.sum_adder.b = local_nested.b; parameter Real local_nested.local.a = 0.5; parameter Real local_nested.local.b = 1.0; Real local_nested.local.sum_adder.sum.a; Real local_nested.local.sum_adder.sum.b; Real local_nested.local.sum_adder.a = local_nested.local.a; Real local_nested.local.sum_adder.b = local_nested.local.b; equation global.sum.a + (-local_nested.local.sum_adder.sum.a) + (-local_nested.sum_adder.sum.a) + (-local.sum_adder.sum.a) = 0.0; global.sum.b + (-local_nested.local.sum_adder.sum.b) + (-local_nested.sum_adder.sum.b) + (-local.sum_adder.sum.b) = 0.0; local.sum_adder.sum.a = 0.0; local.sum_adder.sum.b = 0.0; local_nested.sum_adder.sum.a = 0.0; local_nested.sum_adder.sum.b = 0.0; local_nested.local.sum_adder.sum.a = 0.0; local_nested.local.sum_adder.sum.b = 0.0; local.sum_adder.sum.a = local.sum_adder.a; local.sum_adder.sum.b = local.sum_adder.b; local_nested.sum_adder.sum.a = local_nested.sum_adder.a; local_nested.sum_adder.sum.b = local_nested.sum_adder.b; local_nested.local.sum_adder.sum.a = local_nested.local.sum_adder.a; local_nested.local.sum_adder.sum.b = local_nested.local.sum_adder.b; end global_sum_test.test_model;
But when I want to use the same trick by adding the "outer" keyword the new frontend generates an inner declaration automatically so the trick does not work. During translation it warns:
[1] 21:56:43 Translation Warning [global_sum_test: 15:5-15:23]: An inner declaration for outer component sum could not be found and was automatically generated.
"outer" keyword is present:
class global_sum_test.test_model Real global.sum.a; Real global.sum.b; parameter Real local.a = 0.5; parameter Real local.b = 1.0; Real local.sum_adder.a = local.a; Real local.sum_adder.b = local.b; parameter Real local_nested.a = 0.5; parameter Real local_nested.b = 1.0; Real local_nested.sum_adder.a = local_nested.a; Real local_nested.sum_adder.b = local_nested.b; parameter Real local_nested.local.a = 0.5; parameter Real local_nested.local.b = 1.0; Real local_nested.local.sum_adder.a = local_nested.local.a; Real local_nested.local.sum_adder.b = local_nested.local.b; Real sum.a; Real sum.b; equation global.sum.a + (-sum.a) = 0.0; global.sum.b + (-sum.b) = 0.0; sum.a = 0.0; sum.b = 0.0; sum.a = local.sum_adder.a; sum.b = local.sum_adder.b; sum.a = local_nested.sum_adder.a; sum.b = local_nested.sum_adder.b; sum.a = local_nested.local.sum_adder.a; sum.b = local_nested.local.sum_adder.b; end global_sum_test.test_model;
which obviously does not work.
I do like the possibility of using the method as it worked in the old frontend when the "outer" keyword was present. It is very very useful in cases where the model is relatively nested, so one does not have to code the sum manually which is tedious, but I think it actually works because of some bug (at least the translation error suggests that). What do you think about this? Should the new frontend also automatically generate the inner declarations. Or is there some other way to do these sums so seamlessly? I am confused...
Attachments (1)
Change History (4)
by , 5 years ago
Attachment: | global_sum_test.mo added |
---|
comment:1 by , 5 years ago
Owner: | changed from | to
---|---|
Status: | new → accepted |
@LiborKudela, your models are not balanced, see Modelica Specification Section 4.7.
First of all, the connectors are not balanced, you should have one effort variable for each flow variable in the connector. To resolve this issue, add two (dummy) effort variables to the connecotor, and set them to zero in the system object. This doesn't solve your problem, but is a step forward to guarantee better diagnostics in case of too many or too few equations.
Second, the Sum_adder model is not balanced, because it has no equations to give values to a
and b
. You can add binding equations a = 0
and b = 0
, which are then overridden by the modifiers when you instantiate the model.
Most importantly, the connect statement in Sum_adder
connects one outside connector sum
(see Modelica Specification Section 9.1.2) to an inside connector global.sum
. Because of the outer declaration, global.sum
is actually an alias for an object declared elsewhere, but this is irrelevant here.
Now, this connection is part of the implementation of the object. However, when you instantiate Sum_adder
, its sum
connector is not connected to anything from the outside; hence, it is part of a connection set with only one element (itself), which means that an equation for each flow variables stating that it is zero is generated. That's why you get the extra equations.
As an analogy, you could build an electrical device model with an outside pin connector. Inside, you connect it to lots of components. But then, when you instantiate it, the pin is unconnected, hence an equation pin.i = 0
will be generated, because the component is electrically insulated.
If you want to get the thing to work without resorting to hacks, the connection to the global.sum
connector must involve two inside connectors, while no outside connector should be declared in Sum_adder
.
Here is a correct MWE implementation
package global_sum_test connector Sum_port flow Real a; flow Real b; Real c; Real d; end Sum_port; model Global Sum_port sum; equation sum.c = 0; sum.d = 0; annotation(defaultComponentName = "global"); end Global; model Term_generator Sum_port sum; Real a = 0; Real b = 0; equation sum.a = -a; sum.b = -b; end Term_generator; model Sum_adder outer Global global; Term_generator gen(a = a, b = b); Real a = 2; Real b = 3; equation connect(gen.sum, global.sum); end Sum_adder; model Local parameter Real a = 0.5; parameter Real b = 1.0; Sum_adder sum_adder(a=a,b=b); end Local; model Local_nested parameter Real a = 0.5; parameter Real b = 1.0; Sum_adder sum_adder(a=a,b=b); Local local; end Local_nested; model test_model inner global_sum_test.Global global; Local local; Local_nested local_nested; end test_model; end global_sum_test;
comment:2 by , 5 years ago
Resolution: | → invalid |
---|---|
Status: | accepted → closed |
comment:3 by , 5 years ago
Ok, I totally see it now.
Thank you very much for your great explanation.
MWE package