Opened 9 years ago

Last modified 5 years ago

#3186 assigned defect

Partial binding of record sub-components in functions are lost

Reported by: rfranke Owned by: perost
Priority: critical Milestone: 2.0.0
Component: New Instantiation Version: trunk
Keywords: Cc: perost

Description (last modified by adrpo)

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 Changed 9 years ago by rfranke

  • Description modified (diff)

comment:2 Changed 9 years ago by rfranke

  • Description modified (diff)

comment:3 Changed 9 years ago by rfranke

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 Changed 9 years ago by adrpo

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 Changed 9 years ago by adrpo

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 Changed 9 years ago by rfranke

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 Changed 9 years ago by adrpo

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 Changed 9 years ago by adrpo

  • Owner changed from somebody to adrpo
  • Status changed from new to accepted

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 Changed 9 years ago by rfranke

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 Changed 9 years ago by rfranke

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 Changed 9 years ago by adrpo

  • Description modified (diff)
  • Summary changed from Record constructor function lost during flattening to Partial binding of record sub-components in functions are lost

comment:12 Changed 9 years ago by rfranke

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 Changed 9 years ago by sjoelund.se

  • Milestone changed from 1.9.2 to 1.9.3

Milestone changed to 1.9.3 since 1.9.2 was released.

comment:14 Changed 9 years ago by sjoelund.se

  • Milestone changed from 1.9.3 to 1.9.4

Moved to new milestone 1.9.4

comment:15 Changed 8 years ago by sjoelund.se

  • Milestone changed from 1.9.4 to 1.9.5

Milestone pushed to 1.9.5

comment:16 Changed 8 years ago by sjoelund.se

  • Milestone changed from 1.9.5 to 1.10.0

Milestone renamed

comment:17 Changed 7 years ago by sjoelund.se

  • Milestone changed from 1.10.0 to 1.11.0

Ticket retargeted after milestone closed

comment:18 Changed 7 years ago by sjoelund.se

  • Milestone changed from 1.11.0 to 1.12.0

Milestone moved to 1.12.0 due to 1.11.0 already being released.

comment:19 Changed 6 years ago by casella

  • Milestone changed from 1.12.0 to Future

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 Changed 5 years ago by casella

  • Milestone changed from Future to 2.0.0

comment:21 Changed 5 years ago by casella

See #5204

comment:22 follow-up: Changed 5 years ago by rfranke

  • Cc perost 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.

comment:23 in reply to: ↑ 22 Changed 5 years ago by perost

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 Changed 5 years ago by casella

  • Owner changed from adrpo to perost
  • Status changed from accepted to assigned

comment:25 Changed 5 years ago by casella

  • Component changed from Frontend to New Instantiation
Note: See TracTickets for help on using tickets.