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
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:
- record S2 = S(ns = ns); generates a record constructor with input Integer ns = ns; which has wrong scoping
- 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:
- 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)
- 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: ↓ 23 Changed 5 years ago by rfranke
- Cc perost added
comment:23 in reply to: ↑ 22 Changed 5 years ago by perost
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
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):
Flattening gives:
Lacking the call to MissingPrecalculation.precalculation and resolving s.ns only by chance, the translation warns:
The simulation runs and fails with division by zero.