modelica / ModelicaSpecification

Specification of the Modelica Language
https://specification.modelica.org
Creative Commons Attribution Share Alike 4.0 International
103 stars 41 forks source link

Assignments and variability of record constructor expressions #3139

Open henrikt-ma opened 2 years ago

henrikt-ma commented 2 years ago

I'd like to get confirmation that both assignments in the following model have variability violations:

model RecordAssignmentVariability
  record R
    Real x;
    Integer k;
  end R;

  function makeR "Wrapper around record constructor for R"
    input Real x;
    input Integer k;
    output R r(x = x, k = k);
  end makeR;

  R r1, r2;
algorithm
  r1 := makeR(x = time, k = integer(time)); /* Error: RHS function call has continuous-time variability. */
  r2 := R(x = time, k = integer(time)); /* Error: Explicit use of record constructor doesn't help. */
end RecordAssignmentVariability;

In other words, statements don't have anything corresponding to the discrete-valued equation variability rule that allows an equation to be treated member by member for records.

Maybe this is something we could clarify as part of #3135?

Note that the specification is at least rather clearly stating that the component variability of the record components is discrete-time: https://specification.modelica.org/master/class-predefined-types-and-declarations.html#variability-of-structured-entities

eshmoylova commented 2 years ago

I thought that the variability check would be first performed on records (r1 is continuous and so is RHS) and then based on the rule in 6.7, it would just be performed based on the named elements.

It is interesting that in 8.3.1 Simple Equality Equations, there is a requirement of type compatibility (and, hence, the explanation of how to perform it on records):

The types of the left-hand-side and the right-hand-side of an equation need to be compatible in the same way as two arguments of binary operators (section 6.7).

But there is no mention of type compatibility in 11.2.1 Simple Assignment Statements, so, in a way, nothing about assignments on records is specified.

eshmoylova commented 2 years ago

Note that the specification is at least rather clearly stating that the component variability of the record components is discrete-time: https://specification.modelica.org/master/class-predefined-types-and-declarations.html#variability-of-structured-entities

My interpretation of that rule (backed up by the examples under) is that r1.x is a continuous-time variable and r1.k is a discrete-time variable.

henrikt-ma commented 2 years ago

My interpretation of that rule (backed up by the examples under) is that r1.x is a continuous-time variable and r1.k is a discrete-time variable.

Looks like there is some room for clarification here. :)

My careless interpretation of the examples ignored the use of the out-of-place term variable. As I'm not sure we consider, for instance, a.pi a component, my reading of the examples was actually about the component reference expressions:

parameter A a;
  // a.pi has constant variability
  // a.y and a.i have parameter variability
A b;
  // b.pi has constant variability
  // b.y has continuous-time variability
  // b.i has discrete-time variability
henrikt-ma commented 2 years ago

I thought that the variability check would be first performed on records (r1 is continuous and so is RHS) and then based on the rule in 6.7, it would just be performed based on the named elements.

The treatment of r1 as continuous-time in the LHS is exactly the thing we need to address. It would be (currently is) a failure of the variability rules that we cannot directly reject the assignment of a continuous-time expression to r1, as r1 contains parts that can only be allowed to change at events.

Of course, this variability rule is just a convenience that allows tools to report potential model problems as errors with clear support in the specification, but to me treating r1 as continuous-time on the LHS of an assignment would be equivalent to allowing this model:

model M
  Real x;
  discrete Real k(start = 0.0, fixed = true);
equation
  when time > 0.5 then
    k = 1.0;
  end when;
algorithm
  k := x; /* Variability violation. */
end M;

Note that the model above wouldn't be a problem for a tool to handle, but that the variability rule enforces assignments to agree with "common intuition" about variability, making them somewhat easier to reason about.

henrikt-ma commented 2 years ago

To further illustrate this problem, I invite representatives of all tools to provide current behavior for this model, including the quality of the simulation result for r.k, if any:

model RecordAssignmentVariability
  record R
    Real x;
    Integer k;
  end R;

  function f
    input Real t;
    output R y(x = t, k = if t ^ 2 < 2 then 1 else 2);
  end f;

  R r;
algorithm
  r := f(time);
  annotation(experiment(StopTime = 5.0, Interval = 0.5));
end RecordAssignmentVariability;
qlambert-pro commented 2 years ago

I am also surprised how anyone expects the description of how RecordConstructor are automatically generated to pass variability checking.

record R
   constant Real x ;
end R;

is supposed to be turned into

function R
  input Real x;
  output R $special_not_used(x = x);
end R;

except $special_not_used.x is constant and x has discrete variability in the best interpretation possible.

qlambert-pro commented 2 years ago

There is also the question of the validity of the following model:

model RecordFieldVariabilityInFunctions
  record R
    constant Integer n = 3;
    parameter Real a[n] = fill(1, n);
    parameter Real b[n] = a[1:end];
  end R;

  function f
    input R r;
    output Real o = 2;
  end f;

  parameter R r;
  Real x = f(r);
end RecordFieldVariabilityInFunctions;

I am not sure what to think of the definition of a constant as input to a function when it is the field of a record.

HansOlsson commented 2 years ago

Seems we need to return to this.