ModelicaSpecification icon indicating copy to clipboard operation
ModelicaSpecification copied to clipboard

Unit of constants

Open HansOlsson opened this issue 3 years ago • 6 comments

Added together with other unit-changes: The units of parameters and constants may only be inferred from their binding equations.

Background: Normally in unit-checking it makes sense to derive the unit for all variables without a specified unit. However, for parameters and constants it does not make sense to derive them (except from their binding equations).

As a stupid example consider (yes, there's a bug):

model M1
  Real radius(unit="m")=1;
  Real area(unit="m2")=Modelica.Constants.pi*radius;
end M1;

model M2
   Real radius(unit="m")=1;
   Real area=Modelica.Constants.pi*radius^2;
end M2;

model M
  M1 m1;
  M2 m2;
end M;

If we do unit-checking mindlessly we get that Modelica.Constants.pi has unit="m" and thus m2.area has unit="m3".

Alternatives for improving:

  • As a minimum we should not allow the unit of parameters and constants to be derived from anything but their binding equations.
  • State that parameters and constants have unit="1", unless specified or derived from binding equations. (Can be seen as an optional addition.)
  • (Explicitly adding unit="1" for pi seems counterintuitive and it will be missed for some constant. Additionally in many cases it should be unit="rad", but not in other cases.)

I believe it makes sense for all parameters and constants, but it is at least 100% clear for package constants - since they might be used in different models - giving quite unexpected results as above.

The example may seem contrived - but I saw something similar in Modelica.Mechanics.MultiBody.Visualizers.PipeWithScalarField.

HansOlsson avatar Oct 06 '22 12:10 HansOlsson

Pi is a non-dimensional quantity, defined since the times of Archimedes of Syracuse as the ratio of the length of the circumference to the length of the diameter of a circle. Therefore, in Modelica its unit should be "m/m" = "1".

Doing so would allow to find out that M1 is wrong without the need of the proposed rule.

Furthermore, it would allow to catch the buggy equation in this model

  Real A(unit="m2");
  Real R(unit="m");
  constant Real pi(unit="1") = 3.1415927;
equation
  A = pi*R^3

which has "m2" on the LHS and "m3" on the RHS. Following the original proposal of this ticket, one should write

  Real A(unit="m2");
  Real R(unit="m");
  constant Real pi= 3.1415927;
equation
  A = pi*R^3

and avoid unit inference on pi. Hence, the error won't be caught, because the RHS would contain a Real unit-less constant, which prevents performing dimensional checking.

Regarding the ambiguity between "1" or "rad" for the unit of pi, this is a non-issue. Consider this MWE

  constant Real pi(unit="1");
  Real theta(unit="rad");
equation
  theta = pi;

where the equation has unit "rad" on the LHS and "1" on the RHS. Is this a problem? My argument is that it isn't.

When we talk about "unit checking" we are actually checking for dimensional consistency, not unit consistency. We should more properly refer to "dimensional checking". Dimensional checking can be easily automated, unit checking requires human judgement and expertise. To convince you of that, consider this MWE:

  Real theta(unit="rad");
  Real w(unit="rad/s");
  Real f(unit="Hz");
  Real L(unit="m");
  parameter Real R(unit="m");
equation
  der(theta) = w;
  der(theta) = f;
  L = theta*R;

The first equation is dimensionally consistent and has units rad/s on both sides. So far so good.

The second equation is dimensionally consistent (the dimensions are time^-1 on both sides) but unit-inconsistent, because it has rad only on the LHS. Should we reject such equations? The answer is no, otherwise we should also reject the third one, which has "m" on the LHS and "rad*m" on the LHS, but is perfectly legitimate. Only a human with knowledge of basic physics can figure out that the second equation is wrong, while the third is fine. Not a machine.

Bottom line:

  • for the sake of unit-checking (actually dimensional checking), "rad" and "1", as well as "Hz" and "rad/s", should be considered as (dimensionally) equivalent, lest we reject perfectly legitimate equations
  • for the sake of displaying the proper units, I would suggest to follow Archimedes' footsteps and declare the unit of pi to be "1"
  • doing so also allows to catch dimensionally inconsistent equations containing pi, that would otherwise not be detected as such

casella avatar Oct 06 '22 23:10 casella

Pi is a non-dimensional quantity, defined since the times of Archimedes of Syracuse as the ratio of the length of the circumference to the length of the diameter of a circle. Therefore, in Modelica its unit should be "m/m" = "1".

Doing so would allow to find out that M1 is wrong without the need of the proposed rule.

The proposal would allow that.

And additionally one alternative was that constants and parameters where the unit couldn't be inferred from the binding equation, and no unit was specified they would automatically get unit="1" - so that the existing pi-definition would be seen as having unit="1" and the error would be detected immediately.

However, the main idea was to avoid this weird inferenced of unit of constants in general.

Note that even if "rad" and "1" are dimensionally equivalent there's also the issue of displaying the inferred unit and using displayUnit, and there unit "1" and "rad" behave differently. If unit is "rad" I can change to displayUnit="deg" and enter it in degrees - that doesn't make sense if the unit is "1" - even though the two units are dimensionally equivalent. (Similarly for "N.m" and "J").

HansOlsson avatar Oct 07 '22 08:10 HansOlsson

Pi is a non-dimensional quantity, defined since the times of Archimedes of Syracuse as the ratio of the length of the circumference to the length of the diameter of a circle. Therefore, in Modelica its unit should be "m/m" = "1". Doing so would allow to find out that M1 is wrong without the need of the proposed rule.

The proposal would allow that.

True. But won't it made it unnecessary?

Note that even if "rad" and "1" are dimensionally equivalent there's also the issue of displaying the inferred unit and using displayUnit, and there unit "1" and "rad" behave differently. If unit is "rad" I can change to displayUnit="deg" and enter it in degrees - that doesn't make sense if the unit is "1" - even though the two units are dimensionally equivalent. (Similarly for "N.m" and "J").

See my comment in #2127

casella avatar Oct 07 '22 15:10 casella

What this issue suggests is achieved by #3257, see the quite conservative list presented with In some cases the empty unit can be implicitly cast to an inferred unit:. (Personally, I was against the inference in function calls, but it is now part of the proposal due to popular demand.)

This rule is also part of the solution: Expressions defined to not propagate the empty unit, thereby forcing inference of unit "1". In this rule, parameters and constants have no special role, but unit inference is equally restrictive for all component variabilities (not counting variables inside functions).

henrikt-ma avatar Oct 10 '22 20:10 henrikt-ma

What this issue suggests is achieved by #3257, see the quite conservative list presented with _ In some cases the empty unit can be implicitly cast to an inferred unit:_.

I cannot see that it treats constants specially. And not inferring the unit for a normal variable in the same situation would be a serious defect.

HansOlsson avatar Oct 10 '22 20:10 HansOlsson

What this issue suggests is achieved by #3257, see the quite conservative list presented with _ In some cases the empty unit can be implicitly cast to an inferred unit:_.

I cannot see that it treats constants specially.

Correct.

And not inferring the unit for a normal variable in the same situation would be a serious defect.

This is not clear to me. Is it about the units of the general-purpose blocks in Modelica.Blocks.Math?

henrikt-ma avatar Oct 10 '22 21:10 henrikt-ma