Closed aidanheerdegen closed 4 years ago
Confirmed this is an error in the integer division here:
https://github.com/payu-org/payu/blob/master/payu/models/mitgcm.py#L141
Another example with t_start = 30.0
and dt=0.001
:
(Pdb) p t_start
30.0
(Pdb) p dt
0.001
(Pdb) t_start // dt
29999.0
(Pdb) 30.0 // 0.001
29999.0
(Pdb) 30.0 / 0.001
30000.0
In the above case it erroneously claims the timestep is not a divisor of the runtime, when the timestep has not changed!
Presumably this is because 0.001 is not exactly representable as a float (I expect 0.001 has a recurring binary mantissa that gets rounded in the float representation) so it is actually slightly bigger than 0.001, so //
rounds down to 29999...?
Sounds plausible
Python 3.6.8 tells me
>>> 1//0.001
999.0
>>> 1/0.001
1000.0
>>> 1/1024
0.0009765625
>>> 1//0.0009765625
1024.0
ie the representation of 0.001 is slightly big, messing up the floor division //
, whereas 1/1024
is exact and the division works as expected. So it will depend on whether you get unlucky with the representability of dt.
It might be best to avoid testing for (in)equality with floats for this reason... it's a can of worms, e.g. https://dl.acm.org/doi/10.1145/103162.103163
A proper solution to this would be to use the python decimal library. This is not straightforward as the library used to parse the namelist data does not currently allow for this to be easily used, as values are returned as native python numeric types.
This sort of confusion is why I was surprised to hear that MITgcm supports a fractional timestep. In MOM5 it's an integer.
Report from user: