-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stricter definition of numerics #3591
Comments
(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. For scaling it is both important and normally a non-issue. 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. |
The problem is when you are handling some quantities together with infinity, e.g. for comparisons. If the quantity at hand is very small (e.g. nominal = 1e-12, as it can happen with time scales in microelectronics), scaling requires to multiply by a 1e12 factor. This gets the quantity to be better scaled, but if infinities are also involved, they also get multiplied by 1e12, which can cause them to overflow if you don't have healthy built-in margins. |
This is never going to happen in practice. Ever. |
Except that the scaling isn't purely with nominal but a mixed absolute-relative, i.e.., abs(x)+nominal(x). If the value is 1e300 and the nominal is 1e-12 then the scaling should therefore be about 1e300 - not 1e-12; and thus the scaling does not cause overflow. |
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).
The text was updated successfully, but these errors were encountered: