Skip to content

Conversation

@henrikt-ma
Copy link
Contributor

I think the community is aware that we at Wolfram are currently making a push in the handling and checking of units. This PR is on the advanced topic of absoluteValue-correctness, and I know it will take some discussion to get everyone onboard this time.

Background

Before getting to any technical detail of the proposed changes, let me divide unit errors into the following three categories:

  1. Mismatched powers of base unit symbols, such as assigning an expression in "m" to a variable with unit "s".
  2. Mismatched prefix scaling, such as assigning an expression in "ms" to a variable with unit "s".
  3. Mismatched delta-character, such as assigning a TemperatureDifference expression to a Temperature variable.

Here, (1) is probably the category that first comes to mind. It is harmless in the sense that it won't affect the numerical values used to set parameters or start-attributes, or the axis reading of a plotted result. The only problem is that the values are presented with a bad unit.

I am aware that many consider it poor modeling style to even risk ending up in (2), but if one does, these unit errors are dangerous compared to (1). The reason is that it will impact values used to set parameters or start-values, or axis readings in a plot. For example, if the user prefers to edit values and plot results in the unit "s", but a variable has been incorrectly given the unit "ms" instead of "s", parameter values given in "s" will be multiplied by 1000 when turned into the value of a parameter modification, and simulation results will be divided by 1000 when shown in a plot with "s" on the axis. Fortunately, detecting errors of this kind comes naturally with a system able to detect (1).

If (2) is considered a sign of bad modeling style (existence of unit with prefix), the same can't be said about the more subtle (3) as both Temperature and TemperatureDifference have roles to play in correct modeling with temperatures. Further, ability to detect (3) is not a problem with an of-the-shelf solution that most people have an intuitive understanding of. Even worse, the consequences of (3) are worse than (2) due to the subtle difference between applying and not applying a unit's offset when performing unit conversions. From here on, an error in category (3) is called just a delta error.

Inspired by other unit handling systems' ability to model and check the delta-aspect of a quantity, we have developed a solution around absoluteValue in System Modeler. Similar to any other aspect of unit correctness, we have done this without any support in the specification, driven by the necessity to avoid ending up with the subtle delta errors – especially in a context where variables are automatically inferred to have temperature units.

Rationale

Similar to how we have recently fixed many other unit errors in the MSL without any support in the specification, I suggest that this PR is also considered in view of the same lack of formal specification. Instead, I'll give a couple of examples to motivate the pattern behind the proposed changes.

Absolute plus difference is absolute

Suppose that the delta error is not detected here:

model DeltaError1
  parameter Modelica.SIunits.TemperatureDifference p = 1000;
  Modelica.SIunits.Temperature x = p; /* Delta error */
end DeltaError1;

When plotting the result of x in the default display unit "degC", the offset will be taken into consideration, causing x to appear as having value 726.85 °C. Had the error in the model been fixed by changing the type of x,

  Modelica.SIunits.TemperatureDifference x = p; /* OK */

the value would display correctly as a temperature difference of 1000 °C.

Another way of fixing the model would be to turn the temperature difference into an absolute temperature, by adding it to an absolute temperature:

  constant Modelica.SIunits.Temperature T_zero_K = 0;
  Modelica.SIunits.Temperature x = T_zero_K + p; /* OK */

In this case, it would be correct to display the value of x as an absolute temperature of 726.85 °C.

Multiplicative operations give relative results

In short, what this PR does, is to convert relative temperature expressions into absolute temperature by adding an absolute temperature offset of 0 K. Adding 0 will not affect computed numerical values, but only addresses the delta errors.

The long story needs to explain why the converted expressions are considered relative temperatures, and here the central insight is that multiplicative operations are problematic for absolute temperatures. For example, consider this erroneous model:

model DeltaError2
  parameter Modelica.SIunits.Temperature tYesterday = 293.15;
  Modelica.SIunits.Temperature tToday = 1.2 * tYesterday; /* "20% warmer today than yesterday." */
end DeltaError2;

The user has entered that the temperature yesterday was 20 °C, and has tried to express that today's temperature of 24 °C is 20% warmer. As this model shows, this way of calculating with absolute temperatures doesn't make sense, as the resulting tToday would have been 58.63 °C. A sound system for unit checking needs to detect that 1.2 * tYesterday is not compatible with tToday, and the user can fix the problem by performing the multiplication on a temperature difference instead:

model DeltaError2_correct
  parameter Modelica.SIunits.Temperature tYesterday = 293.15;
  constant Modelica.SIunits.Temperature t0 = 273.15 "Reference temperature";
  Modelica.SIunits.TemperatureDifference dT = tYesterday - t0; /* Intermediate variable just for extra clarity. */
  Modelica.SIunits.Temperature tToday = t0 + 1.2 * dT; /* 20% warmer today than yesterday, relative to reference temperature. */
end DeltaError2_correct;

Allowing 1.2 * tYesterday even though tYesterday is an absolute temperature is a problem in itself, but outside the scope of this PR. If reviewers find the PR incomplete with this limitation of scope, they are encouraged to speak up.

Another example of a multiplicative relation that does not make sense for absolute temperatures is the heat capacity relation. As temperature is the only quantity where we have units with offset, we can treat all other quantities as being differences by default without risk of incorrect unit conversions, here applied to thermal energy and heat capacity. A correct model could thus look like this:

partial model HeatCapacityEquation
  parameter Modelica.SIunits.Temperature t0 = 293.15;
  parameter Modelica.SIunits.HeatCapacity C = 100 "Heat capacity at temperature t0";
  Modelica.SIunits.Energy delta_Q;
  Modelica.SIunits.TemperatureDifference delta_T = delta_Q / C;
end HeatCapacityEquation;

Similar to DeltaError2 above, it would have been problematic to assign delta_Q / C to an absolute temperature variable, but such a problem can be addressed by adding a zero absolute temperature offset:

  Modelica.SIunits.Temperature t = T_zero_K + delta_Q / C;

Of course, there could also be other ways of addressing the "delta error" that make more sense from a modeling perspective – this is just a minimal fix without any effect on calculated values.

@henrikt-ma
Copy link
Contributor Author

I am leaving this PR in Draft state while reconsidering the limitation of scope discussed above.

@HansOlsson
Copy link
Contributor

Multiplicative operations give relative results

In short, what this PR does, is to convert relative temperature expressions into absolute temperature by adding an absolute temperature offset of 0 K. Adding 0 will not affect computed numerical values, but only addresses the delta errors.

The long story needs to explain why the converted expressions are considered relative temperatures, and here the central insight is that multiplicative operations are problematic for absolute temperatures. For example, consider this erroneous model:

model DeltaError2
  parameter Modelica.SIunits.Temperature tYesterday = 293.15;
  Modelica.SIunits.Temperature tToday = 1.2 * tYesterday; /* "20% warmer today than yesterday." */
end DeltaError2;

This motivation for forbidding multiplication of absolute temperatures doesn't make sense to me from a physics perspective. I agree that 20% warmer today is a bit odd and shouldn't be expressed that way, but I don't normally hear people say that so I don't see a real problem. If I see such a factor in a test-example I just assume someone is being sloppy.

However, I am aware of e.g., frequency-peak for black-body radiation being some constant times absolute temperature, and Stefan-Boltzmann laws where energy is some other constant times T^4. The fact that those formulas just work is one reason we use the absolute temperature scale and not some other temperature scale.

Thus an absolute requirement is that absolute temperature multiplied by something is not seen as problematic.

Copy link
Contributor

@HansOlsson HansOlsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of the proposed changes make sense to me.

Weighted average of temperatures is well-defined, and since the media has h=cp*T it doesn't make sense to modify some of the formulas with T=h/cp.

Added: With weighted average I mean: T_final_K = (mass1.T*mass1.C + mass2.T*mass2.C)/(mass1.C + mass2.C); (which actually works regardless of the reference temperature).

If someone were to modify h=cp*T I would find it more likely that the change would be h=cp*T+h_offset, or possibly offset for both.

However, I can understand some need for making it clearer whether a temperature is a difference or not - but that would need careful analysis, and possibly some other change.

@henrikt-ma
Copy link
Contributor Author

However, I am aware of e.g., frequency-peak for black-body radiation being some constant times absolute temperature, and Stefan-Boltzmann laws where energy is some other constant times T^4. The fact that those formulas just work is one reason we use the absolute temperature scale and not some other temperature scale.

Thus an absolute requirement is that absolute temperature multiplied by something is not seen as problematic.

There is a price to pay for having the current system with overloaded meanings of temperature units with offset. In a world without the risk of getting the wrong display unit conversion to °C and °F, one wouldn't need to worry about what sort of temperature to use in physical relations such as the Stefan–Boltzmann law. Unfortunately, our situation isn't that simple, but as this PR shows, we can have checks that allow detecting delta errors, and it is trivial to adapt relations so that they comply with the checks by adding or subtracting the T_zero_K absolute offset.

I am all ears if you have a better way of detecting the delta errors.

@HansOlsson
Copy link
Contributor

However, I am aware of e.g., frequency-peak for black-body radiation being some constant times absolute temperature, and Stefan-Boltzmann laws where energy is some other constant times T^4. The fact that those formulas just work is one reason we use the absolute temperature scale and not some other temperature scale.
Thus an absolute requirement is that absolute temperature multiplied by something is not seen as problematic.

There is a price to pay for having the current system with overloaded meanings of temperature units with offset. In a world without the risk of getting the wrong display unit conversion to °C and °F, one wouldn't need to worry about what sort of temperature to use in physical relations such as the Stefan–Boltzmann law. Unfortunately, our situation isn't that simple, but as this PR shows, we can have checks that allow detecting delta errors, and it is trivial to adapt relations so that they comply with the checks by adding or subtracting the T_zero_K absolute offset.

I don't see that this PR shows any such improvements or that any actual problems were caught, and to me it introduces a number of problems:

  • The value of T_zero_K is wrong, it should be 0 and adding such a zero is just confusing.
  • It makes the formula for the weighted average of temperatures more complicated.
  • The handling of h=cp*T is inconsistent; as shown by the proposed:
 T_b=Modelica.Constants.T_zero_K + flowPort_b.h/medium.cp;
  dT=if noEvent(V_flow>=0) then T-T_a else T_b-T;
  h = medium.cp*T;

Here we have h=cp*T twice, once with offset, once without.

@HansOlsson
Copy link
Contributor

If we want to find such potential errors, e.g., #4032 we first should recognize that there are about 15 uses of TemperatureDifference (dT) and 500+ uses of Temperature (T) indicating that TemperatureDifference is the rare one.

The obvious cases that we might want to find are:

  • Temperature equal to a temperature difference
  • The difference between two temperatures not declared as a difference

Checking for either of them doesn't need this PR, and the likely correction for both is to change the declarations, whereas adding a general base-line does not make sense. More advanced equations cannot easily be checked in this way.

FixedMassFlowRate fixedMassFlowRate(
redeclare package Medium = Medium,
T_ambient=1.2*T_start,
T_ambient=Modelica.Constants.T_zero_K + 1.2*T_start,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change clearly makes things worse; computing a temperature as 1.2 times another is a bit odd (but is ok for a test).

But in the new equation we T_ambient=Modelica.Constants.T_zero_K + 1.2*T_start, which is a form where one would normally expect T_start to be a temperature difference, which it isn't. (We have other equations that use T_a=T_start+0.5*dT so using a literal times a difference is fairly normal).

Copy link
Contributor Author

@henrikt-ma henrikt-ma May 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. This is the reason behind keeping this PR in Draft state. A proper way to write the modification would be:

import Modelica.Constants.T_zero_K;

Suggested change
T_ambient=Modelica.Constants.T_zero_K + 1.2*T_start,
T_ambient=T_zero_K + 1.2*(T_start - T_zero_K),

Co-authored-by: Hans Olsson <[email protected]>
@henrikt-ma
Copy link
Contributor Author

henrikt-ma commented May 24, 2023

If we want to find such potential errors, e.g., #4032 we first should recognize that there are about 15 uses of TemperatureDifference (dT) and 500+ uses of Temperature (T) indicating that TemperatureDifference is the rare one.

The system we have would detect #4032, but I don't know why it is important that TemperatureDifference is the rare one.

The obvious cases that we might want to find are:

  • Temperature equal to a temperature difference

If you mean Temperature vs TemperatureDifference, this is trivial indeed. It doesn't get interesting until we deduce units of expressions and inferring units of variables.

  • The difference between two temperatures not declared as a difference

Right, the underlying subtraction rule here is one out of a handful rules needed for deduction of the delta-aspect of a temperature quantity.

Checking for either of them doesn't need this PR, and the likely correction for both is to change the declarations, whereas adding a general base-line does not make sense. More advanced equations cannot easily be checked in this way.

This PR should serve as a starting point for bringing attention to the problem with delta-errors, and that there is a way to reason which allows typical errors to be detected. Again, the reason for keeping the PR in Draft state is that it does not fix all things that need to be rejected in order to get a really useful error detection. Locally, I have a branch where also things like 1.2*T_start have been fixed, but I find it better to start this discussion around a smaller set of changes.

Let me try to summarize the rules we are applying for detection of delta-errors:

  • A temperature variable with explicit unit is relative when absoluteValue = false.
  • A relative temperature, dT, can be used in expressions similar to non-temperature quantities.
    • For example, all of 0.2 * dT, dT1 - dT2, dT ^ 2 are valid.
  • An absolute temperature, T, works differently:
    • An absolute temperature cannot be used with multiplicative or power-like operators/functions.
      • In particular (-1) * T is an error, and unary negation is considered equivalent.
    • The difference T1 - T2 is a relative temperature.
    • All of T + dT, dT + T, and T - dT are absolute temperatures.
    • dT - T is an error (similar to dT + ((-1) * T)).
  • When a temperature is the result of a multiplicative or power-like operation/call, it is a relative temperature.

The last rule is a natural in view of the other rules. For example, note that the equation:

x = dQ / C

couldn't be rewritten as the following unless x is a relative temperature:

C * x = dQ

Similarly, one couldn't rewrite x = derT * dT as derT = x / dT unless x is a relative temperature.

@henrikt-ma
Copy link
Contributor Author

  • It makes the formula for the weighted average of temperatures more complicated.

The ability to detect delta-errors pretty much boils down to modeling absolute temperature as an affine space, and temperature difference as the corresponding vector space.

A weighted average is an affine combination, and a great thing about affine combinations is that they are defined for affine spaces. It would be very easy to define Modelica.Math.Vectors.weightedMean in such a way that it is delta-correct for both absolute and relative quantities (simply use the first element as the arbitrary point of reference).

@HansOlsson
Copy link
Contributor

HansOlsson commented May 25, 2023

  • An absolute temperature cannot be used with multiplicative or power-like operators/functions.
  • When a temperature is the result of a multiplicative or power-like operation/call, it is a relative temperature.

Those two rules do not make sense, since there are a number of well-known physical laws that violate that.

That's not up for discussion.

This is in contrast to other domains, e.g., mechanical and electrical where we lack absolute coordinates and every physical system should work the same if translated/rotated and/or if the electrical potential was shifted (there might be some modeling issues regarding that in MSL).

Absolute temperature is different, that's why we have the ideal gas-law pV=nR*T etc.

The ability to detect delta-errors pretty much boils down to modeling absolute temperature as an affine space, and temperature difference as the corresponding vector space.

That is the underlying error in this PR. Absolute temperature is not an affine space.

But, electrical potentials form an affine space with voltages as the corresponding vector space. (Similarly for mechanical systems, where absolute space and time have a more interesting philosophical history.)

But if it had been an affine space the original weighted mean would be an affine combination (https://en.wikipedia.org/wiki/Affine_combination ), and thus correct without any changes.

@HansOlsson HansOlsson added the invalid Invalid issue label Jun 20, 2023
@HansOlsson HansOlsson closed this Jun 20, 2023
@HansOlsson HansOlsson added this to the never milestone Jun 20, 2023
@henrikt-ma
Copy link
Contributor Author

  • An absolute temperature cannot be used with multiplicative or power-like operators/functions.
  • When a temperature is the result of a multiplicative or power-like operation/call, it is a relative temperature.

Those two rules do not make sense, since there are a number of well-known physical laws that violate that.

The problem is that the physical laws didn't ask for the existence of temperature units with offset, the absoluteValue-annotation, and the possibility to automatically infer units of variables. We (humans) added that complexity and need to deal with it.

I find this similar to the way that other physical equations need to be reformulated depending on whether the radian is a base unit, whether one uses π or τ (= 2π), etc. The essence of the equation doesn't change, it just looks a bit different depending on design choices that have nothing to do with the physics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid Invalid issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants