Opened 10 years ago

Last modified 6 years ago

#3186 assigned defect

Partial binding of record sub-components in functions are lost

Reported by: Rüdiger Franke Owned by: Per Östlund
Priority: critical Milestone: 2.0.0
Component: New Instantiation Version: trunk
Keywords: Cc: Per Östlund

Description (last modified by Adrian Pop)

The modifiers on record S, variable s in function precalculation are lost during flattening. See the model below.

Today's test show an increase from 74 to 89 built models for the PowerSystems library, see

https://test.openmodelica.org/libraries/history/PowerSystems-trend.svg

This is due to the introduction of the workaround M3 of #3183, see

https://github.com/modelica/PowerSystems/commit/bb0593fd7db98de8af4ead2c2047a280267955ef

Interestingly no compilation error occurs. The simulations fail with divisions by zero, because the record constructor functions are not called.

See the following example:

package MissingPrecalculation
  record R
    parameter Integer nr;
    Real[nr] vr;
  end R;

  record S
    parameter Integer ns;
    Real[ns] vs;
  end S;

  function precalculation
    input R r;
    output S s(ns = r.nr);
  algorithm
    s.vs := 2*r.vr;
  end precalculation;

  model M3
    parameter R r(nr = 2, vr = {1, 2});
    record S2 = S(ns = r.nr);
    parameter S2 s = precalculation(r);
  end M3;
end MissingPrecalculation;

Flattening results in:

function MissingPrecalculation.precalculation
  input MissingPrecalculation.R r;
  output MissingPrecalculation.S s;
algorithm
  s.vs := r.vr * 2.0;
end MissingPrecalculation.precalculation;

class MissingPrecalculation.M3
  parameter Integer r.nr = 2;
  parameter Real r.vr[1] = 1.0;
  parameter Real r.vr[2] = 2.0;
  parameter Integer s.ns = s.r.nr;
  parameter Real s.vs[1];
  parameter Real s.vs[2];
end MissingPrecalculation.M3;

Couldn't the the modifier for ns be kept in the precalculation function and the function call be placed in initial equations:

function MissingPrecalculation.precalculation
  input MissingPrecalculation.R r;
  output MissingPrecalculation.S s(ns = r.nr);
algorithm
  s.vs := r.vr * 2.0;
end MissingPrecalculation.precalculation;

class MissingPrecalculation.M3
  parameter Integer r.nr = 2;
  parameter Real r.vr[1] = 1.0;
  parameter Real r.vr[2] = 2.0;
  parameter Integer s.ns(fixed = false);
  parameter Real s.vs[1](fixed = false);
  parameter Real s.vs[2](fixed = false);
initial equation
  s = /*.MissingPrecalculation.S*/(MissingPrecalculation.precalculation(/*.MissingPrecalculation.R*/(r)));
end MissingPrecalculation.M3;

Any other idea?

Change History (25)

comment:1 by Rüdiger Franke, 10 years ago

Description: modified (diff)

comment:2 by Rüdiger Franke, 10 years ago

Description: modified (diff)

comment:3 by Rüdiger Franke, 10 years ago

Here is a version of the test model that compiles and simulates with uninitialised parameters (see also all the PowerSystems.Examples.Spot.*AC3ph.* that compile and fail during simulation, like DrivesAC3ph.SM_ctrlAv or GenerationAC3ph.TurbineGenerator):

package MissingPrecalculation
  record R
    parameter Integer nr;
    Real[nr] vr;
  end R;

  record S
    parameter Integer ns;
    Real[ns] vs;
  end S;

  function precalculation
    input R r;
    output S s(ns = r.nr);
  algorithm
    s.vs := 2*r.vr;
  end precalculation;

  model M4
    parameter R r(nr = 2, vr = {1, 2});
    final parameter Integer ns = r.nr;
    record S2 = S(ns = ns);
    parameter S2 s = precalculation(r);
    Real t = 1/s.vs[2];
  end M4;
end MissingPrecalculation;

Flattening gives:

class MissingPrecalculation.M4
  parameter Integer r.nr = 2;
  parameter Real r.vr[1] = 1.0;
  parameter Real r.vr[2] = 2.0;
  final parameter Integer ns = r.nr;
  parameter Integer s.ns = s.ns;
  parameter Real s.vs[1];
  parameter Real s.vs[2];
  Real t = 1.0 / s.vs[2];
end MissingPrecalculation.M4;

Lacking the call to MissingPrecalculation.precalculation and resolving s.ns only by chance, the translation warns:

[1] Translation Warning
[MissingPrecalculation.mo: 9:5-9:16]: Parameter s.vs[2] has no value, and is fixed during initialization (fixed=true), using available start value (start=0.0) as default value.

[2] Translation Warning
[MissingPrecalculation.mo: 9:5-9:16]: Parameter s.vs[1] has no value, and is fixed during initialization (fixed=true), using available start value (start=0.0) as default value.

The simulation runs and fails with division by zero.

comment:4 by Adrian Pop, 10 years ago

It seems we handle modifiers for record components inside functions badly.
It would work if you say:

  function precalculation
    input R r;
    output S s = S(ns = r.nr, vs = 2*r.vr);
  end precalculation;

Is not very clear for me how to handle such modifiers inside functions, I will need to think about it.

comment:5 by Adrian Pop, 10 years ago

And, btw the record constructor function is not lost during flattening.
We evaluate the function call and replace it with the result because we need to know the array sizes inside the record components.

comment:6 by Rüdiger Franke, 10 years ago

The structural part of the precalculation function finds in its signature -- output S s(ns = r.nr). This is needed because S.ns is a parameter that cannot be changed in the algorithm section anymore. The other members of S should be treated as regular model parameters that are calculated at runtime from the free parameters R r.

Couldn't only the function signature be evaluated during flattening, while the function as such is evaluated at runtime?
See also #3182.

comment:7 by Adrian Pop, 10 years ago

Unfortunately the current front-end design evaluates a lot of things during compile time (should only evaluate structural parameters) and it will take some time to change.

I think that the modification part of output S s(ns = r.nr); should become an assignment s.ns = r.nr; used to set the output structure after its declaration.

We should keep the binding and use it to set the output structure member after its declaration.

comment:8 by Adrian Pop, 10 years ago

Owner: changed from somebody to Adrian Pop
Status: newaccepted

There are 2 issues here:

  1. record S2 = S(ns = ns); generates a record constructor with input Integer ns = ns; which has wrong scoping
  2. the binding for output S s(ns = r.nr); is saved inside the type of s and not as a binding for s as that is not currently possible (we can only have default bindings for the entire record variable, not for sub-components).

comment:9 by Rüdiger Franke, 10 years ago

Regarding issue 1: record S2 is just a workaround anyway -- but I wonder how Fluid works then, because it modifies types of flow and heat transfer models a lot. Issue 2 might be treated by explicitly calling a record constructor for the output precalculation.s as you propose in comment:4.

This requires the treatment of two new things:

  1. each record member must get a value from the constructor (but please not more than a default value that is changed in the algorithm section afterwards, because the algorithm is generally not trivial)
  2. it results in the translation error: Looking for a function S but found a record

It appears that both issues can be treated with an operator record:

package MissingPrecalculation
  record R
    parameter Integer nr;
    Real[nr] vr;
  end R;

  operator record S
    parameter Integer ns;
    Real[ns] vs;
    encapsulated operator 'constructor'
      import MissingPrecalculation.S;
      function fromSize
        input Integer ns;
        output S s(ns = ns, vs = zeros(ns));
      end fromSize;
    end 'constructor';
  end S;

  function precalculation
    input R r;
    output S s = S(ns = r.nr);
  algorithm
    s.vs := 2*r.vr;
  end precalculation;

  model M5
    parameter R r(nr = 2, vr = {1, 2});
    parameter S s = precalculation(r);
    Real t = 1/s.vs[2];
  end M5;
end MissingPrecalculation;


comment:10 by Rüdiger Franke, 10 years ago

Live could be so easy, but Modelica libs aren't. While M5 given in above is working, the real AC3ph machine models additionally replace the input parameter record. This produces again the translation error "Could not evaluate structural parameter (or constant) ns which gives dimensions of array: vs[ns]". See M6 below:

package MissingPrecalculation
  record R
    parameter Integer nr;
    Real[nr] vr;
  end R;

  record R1
    extends R(nr = 2, vr = {1, 2});
  end R1;

  operator record S
    parameter Integer ns;
    Real[ns] vs;
    encapsulated operator 'constructor'
      import MissingPrecalculation.S;
      function fromSize
        input Integer ns;
        output S s(ns = ns, vs = zeros(ns));
      algorithm
      end fromSize;
    end 'constructor';
  end S;

  function precalculation
    input R r;
    output S s = S(ns = r.nr);
  algorithm
    s.vs := 2*r.vr;
  end precalculation;

  model M5
    replaceable parameter R r;
    parameter S s = precalculation(r);
    Real t = 1/s.vs[2];
  end M5;

  model M6
    extends M5(redeclare replaceable parameter R1 r);
  end M6;
end MissingPrecalculation;

comment:11 by Adrian Pop, 10 years ago

Description: modified (diff)
Summary: Record constructor function lost during flatteningPartial binding of record sub-components in functions are lost

comment:12 by Rüdiger Franke, 10 years ago

The commit
https://github.com/modelica/PowerSystems/commit/592eaed2e3d1c48ac35da597a4d5860675796e20
brings the lib back to its original status (see #3183). This is because the ultimate solution might require other changes anyway -- or no changes at all.

The nightly tests should now report frontend failures for the AC3ph machine models again, as opposed to simulation failures that result from the lost partial bindings.

comment:13 by Martin Sjölund, 10 years ago

Milestone: 1.9.21.9.3

Milestone changed to 1.9.3 since 1.9.2 was released.

comment:14 by Martin Sjölund, 9 years ago

Milestone: 1.9.31.9.4

Moved to new milestone 1.9.4

comment:15 by Martin Sjölund, 9 years ago

Milestone: 1.9.41.9.5

Milestone pushed to 1.9.5

comment:16 by Martin Sjölund, 9 years ago

Milestone: 1.9.51.10.0

Milestone renamed

comment:17 by Martin Sjölund, 8 years ago

Milestone: 1.10.01.11.0

Ticket retargeted after milestone closed

comment:18 by Martin Sjölund, 8 years ago

Milestone: 1.11.01.12.0

Milestone moved to 1.12.0 due to 1.11.0 already being released.

comment:19 by Francesco Casella, 7 years ago

Milestone: 1.12.0Future

The milestone of this ticket has been reassigned to "Future".

If you think the issue is still valid and relevant for you, please select milestone 1.13.0 for back-end, code generation and run-time issues, or 2.0.0 for front-end issues.

If you are aware that the problem is no longer present, please select the milestone corresponding to the version of OMC you used to check that, and set the status to "worksforme".

In both cases, a short informative comment would be welcome.

comment:20 by Francesco Casella, 6 years ago

Milestone: Future2.0.0

comment:21 by Francesco Casella, 6 years ago

See #5204

comment:22 by Rüdiger Franke, 6 years ago

Cc: Per Östlund added

@perost as you appear to work on records, could you have a look at this old ticket, in particular at M3, M5 and M6?

It relates to many failed PowerSystems models. See also #3302, #3882, #5204.

in reply to:  22 comment:23 by Per Östlund, 6 years ago

Replying to rfranke:

@perost as you appear to work on records, could you have a look at this old ticket, in particular at M3, M5 and M6?

M3 and M4 now works with the changes in 66dc536e, but it seems like M5 and M6 require further fixes.

comment:24 by Francesco Casella, 6 years ago

Owner: changed from Adrian Pop to Per Östlund
Status: acceptedassigned

comment:25 by Francesco Casella, 6 years ago

Component: FrontendNew Instantiation
Note: See TracTickets for help on using tickets.