Open HansOlsson opened 1 week ago
(Reporting and adapting my argument from #4479, since it is relevant for this discussion.)
Note that expressions in the Modelica code are not always interpreted literally.
A Modelica tool is free to apply transformations to expressions and equations that are equivalent from a mathematical point of view, but not from a numerical point of view. For example, it can
Adding NaN, Inf and the associated semantics to Modelica means that every time a tool applies any such transformation, it will need to take care of that as well.
As Aesop wrote in his fables, be careful what you wish for, lest it comes true! 😃
Numerical routines should be written to avoid overflow.
If you look at something simple like the 2-norm in the BLAS-routine dnrm2
you can see that this is something that people actually do.
For scaling it is both important and normally a non-issue. The reason is that scaling is intended to get values closer to 1 and if scaling introduces an overflow it indicates that not only is the scaling not doing what it is supposed to do, but actually making the problem worse.
If you look at the scaling defined in the Modelica specification it uses |x.nominal|+|x| as scale factor for x. You don't have to divide by it, but if you do - dividing x by this scale factor is by definition guaranteed to produce a value <=1 in absolute terms, and thus not overflow (it may underflow if x was close to the smallest number and the nominal value larger than 1, but underflow is less of an issue - especially as this case indicates that the modeler don't care about such a small value).
The only issue is if |x.nominal| is close to the maximum floating point number (DBL_MAX), and the variable also has a value of similar magnitude. Adding a restriction that |nominal| should be less than something like DBL_MAX*DBL_EPSILON avoids that case, and I don't see any existing models violating that. Alternatively we could recommend max(|x.nominal|, |x|) instead, - which avoids the issue without any restriction, or some other alternative.
There has been a background discussion regarding floating point semantics, especially for the weird cases and I thought it would be best to get some agreement.
For the weird cases I mean:
My thinking is that we use IEEE-754 (alternatively any similar floating point numbers system) with the following extras:
NaN
(Not a Number) can propagate in the normal way (so thatsqrt(-1)
just generatesNaN
and e.g.,56.6*NaN
isNaN
), provided that an accepted model evaluation does not contain:NaN
NaN
as an operandNaN
as an operandNaN
spreads to everything we just have to check the result, not all individual expressions. I don't know if this will gain anything, but I don't see a problem with allowing it.NaN
according to previous, another is to fail; both should generate the same result (at end). Unless the intermediateNaN
does not impact the result. That is a modeling issue that tools are not required to detect (at the end)NaN
for +/-infinity, but another alternative is given belowTo me it would be good to have this now, and the possible extension for infinity is to allow:
At least for evaluable parameters allow:
1/0
should be allowed is a point worth discussingp*0*x
simplifying to0
(see below), instead of gettingNaN
and failure.And possibly even for other parameters, and even discrete variables.
Background - the critical points for not "just using IEEE-754" are:
a=p*0;
givinga=0
anda+p=b+p;
givinga=b;
) and similarly we don't want to allow non-finite solutions.Specifically it could be that the simplification
p*0*x
is sufficiently rare for evaluable parameters that we can delay it until evaluating the evaluable parameters, and in case it is actually infinity view this expression as an error (should be rare, right?).However, even if this might make perfect sense and have very little impact for models in practice, it could still be complicated to implement in tools. That's one reason I think we should do this later.
Note that for
NaN
a special case would be something like:To me this model has an error when y<0, but a tool does not necessarily have to detect it (if using
NaN
for negative sqrt it will be overwritten); and even with our current rules, https://specification.modelica.org/master/operators-and-expressions.html#evaluation-order , a tool could simplify this to:(avoiding the issue).