-
Notifications
You must be signed in to change notification settings - Fork 298
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
displayUnit conversion results in many trailing zeros #8860
Comments
Probably a duplicate of #7491. The root issue was extensively discussed in #7465 in a slightly different context (flat Modelica output), though the discussion turned out a bit academic at a certain point. One solution is to use the routines from the Ryu library, which should address all such issues nicely. It seems that there was consensus on that, but then we didn't take action. @sjoelund, @perost, @mahge, @adeas31 what would be the best way to incorporate this utility function in OMC, and then use it consistently for rendering of OMEdit unit-converted parameters and for (flat) Modelica output from the frontend? |
Oops, yeah, this indeed looks like a dupe, sorry about that! |
In fact, good that you raised this issue, that was left stranded as many others. I opened #8865 on this topic. |
Hi, The reverse also seems to be true: the text model has a neat rounded value whereas the graphical view shows superfluous digits. Best regards, |
It's already mentioned there, thanks! |
…11168) * use libryu.a library in MetaModelica to convert doubles to strings - see tickets #8865, #8860, #7465 * fix the include path to ryu.h * remove the bad * * add using ryu in the cmake build * use the functions from om_format.c moved inside libryu.a * update 3rdParty to get the libryu.a changes * fix the call to ryu OM routines - use the new om_format.h header - add the call to ryu to get the buffer - declare the needed ryu functions as extern - add the underscore back, it needs to be there - update 3rdParty * update and disable tests due to double printing format changes - disabled tests (CHECK THESE PROPERLY!): testsuite/openmodelica/cppruntime/clockedEventRotationalTest.mos testsuite/simulation/libraries/msl32/Modelica.Electrical.Analog.Examples.AmplifierWithOpAmpDetailed.mos testsuite/simulation/modelica/others/EngineV6_output.mos testsuite/simulation/libraries/msl32/Modelica.Mechanics.MultiBody.Examples.Loops.EngineV6.mos
OK, current status with the original issue reported by @bilderbuchi and the current 1.23.0 nightly build:
The root cause is #11397. This should be fixed automatically once we switch to the new MSYS2 UCRT64 runtime, see #10939. |
@bilderbuchi this should be now fixed with the 1.23.0-dev nightly build. Please check. |
Yes, in most of the cases it is working. However, I found a corner case. package Test
model M
parameter Modelica.Units.SI.Density d[1];
annotation(
Icon(graphics = {Rectangle(origin = {-1, 0}, extent = {{-99, 100}, {101, -100}}), Text(origin = {4, 11}, extent = {{-66, 53}, {66, -53}}, textString = "M")}));
end M;
model S
M m(d (each displayUnit = "kg/m3")= {950}) annotation(
Placement(visible = true, transformation(origin = {0, -2}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
end S;
annotation(uses(Modelica(version="4.0.0")));
end Test;
OMEdit shows |
This is weird. There is actually no conversion involved in this case: 950 has an exact representation in IEEE 754 double precision, so multiplying or dividing it by 1.0, which also has an exact representation, should still return an exact integer value. Why should it be rendered differently? @adeas31, @perost could you please track all the steps from the 950 in the source code to the displayed 949.9999999999999, so we understand exactly where it goes wrong? |
From the OMEdit log I'm getting:
I'm not sure about the purpose of those |
The actual displayUnit of But in general this shouldn't be a problem. Multiple conversions should work fine. The same behavior can be achieved by just changing displayUnits multiple times from the dropdown. |
I agree that we should have a system in place that can handle the rounding of multiple conversions nicely, though I find it sub-optimal that in case there is a local displayUnit we don't go for that directly. But that's another story. So, apparently this pseudo code prints 949.9999999999999?
Could you please check that? |
@adeas31 I think I know what is going on here. The problem is that you are carrying out two conversions in a row, which both introduce rounding errors. The first time you are computing Bottom line: please avoid the double conversion and do the conversion from unit to displayUnit only once, so we have a chance that Ryu can recover the round figure. In this specific case, there won't be any conversion, so it will work for sure.
AFAIU this is not exactly the case. When you do this, each time the result of the operation is passed through Ryu, which tries to approximate it "on the right side", i.e. the one with less digits. This doesn't happen in the case at hand, where two conversions are applied in a row without any Ryu re-adjustment in-between. |
I can confirm that the originally reported model shows fixed behaviour now. |
This produces
So i don't think the double conversion is an issue here. |
I guess the problem is that OMEdit does the unit conversions with factors that don't have an exact representation as IEEE 754 double precision numbers, such as 0.001 or 1e-6 etc. As in the above example, this introduces two approximations: one when representing the user input, e.g. 0.95, and one representing the conversion factor, e.g. 0.001. I think we should make the unit conversion smarter, by trying to always have a conversion factor that has an exact representation. For example, if you now want to convert g/cm3 to kg/m3, you divide by 0.001, but you could actually multiply by 1000 instead. I think that
would return I think this should fix it. In any case I would try to avoid the double conversion, it is just an unnecessary numerical hazard. |
We could also improve print_ryu(d) as follows
However, this is somehow based on heuristics. I believe the right approach is to do the conversions by multiplying and dividing by the same factor, preferably (when possible) with an exact representation (e.g. an integer value), rather than dividing by a factor and then dividing by it inverse. |
Works as expected after #12052 |
Confirmed |
Description
Using displayUnit on component parameters sometimes results in values with a large number of trailing zeros and a 1 in the last digit.
This reduces readability of the code, and maybe just stems from a string formatting problem
Steps to Reproduce
rod.L
:rod
30
(mm) forL
(i.e.1e-3
in base units)Could not preserve the formatting of the model instead internal pretty-printing algorithm is used." - I don't know if this is supposed to happen, may be related to Pretty-Printing algorithm being called after deleting components in OMEdit v1.18.1 #8635
rod(L(displayUnit = "mm") = 0.03000000000000001)
Expected Behavior
After entering a length of
30
mm in the dialog, the entry in source should be0.03
,30e-3
,3e-2
or similar.AFAICT, the suggested additional precision was not there in the first place.
Note how Python behaves similarly when printing floats.
Version and OS
The text was updated successfully, but these errors were encountered: