Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#5834 closed discussion (invalid)

Automatic sum using inner outer keywords behaves diferently in new frontend

Reported by: libor.kudela@… 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)

global_sum_test.mo (912 bytes ) - added by libor.kudela@… 5 years ago.
MWE package

Download all attachments as: .zip

Change History (4)

by libor.kudela@…, 5 years ago

Attachment: global_sum_test.mo added

MWE package

comment:1 by Francesco Casella, 5 years ago

Owner: changed from LiborKudela to Francesco Casella
Status: newaccepted

@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 Francesco Casella, 5 years ago

Resolution: invalid
Status: acceptedclosed

comment:3 by libor.kudela@…, 5 years ago

Ok, I totally see it now.

Thank you very much for your great explanation.

Note: See TracTickets for help on using tickets.