ITime

ITime, or integer time, is a time type used by CliMA simulations to keep track of simulation time. For more information, refer to the TimeManager section in ClimaUtilities and the ITime section in ClimaAtmos.

How do I use ITime?

There are three fields to an ITime which are counter, period, and epoch. An ITime represents the amount of time, computed as counter * period, that has passed since the epoch. See the example below of constructing an ITime.

julia> using ClimaUtilities.TimeManager, Dates # ITime is from ClimaUtilities
julia> t = ITime(3, period = Minute(1), epoch = DateTime(2008))3.0 minutes (2008-01-01T00:03:00) [counter = 3, period = 1 minute, epoch = 2008-01-01T00:00:00]
julia> counter(t)3
julia> period(t)1 minute
julia> epoch(t)2008-01-01T00:00:00

The ITime t represents that three minutes have elapsed since 2008. The epoch is chosen to be the start date of the simulation. Note that the counter must be an integer. This means no floating point error can occur!

However, what are the differences between the following constructions of ITime?

julia> dt1 = ITime(60000, period = Millisecond(1), epoch = DateTime(2010))60000.0 milliseconds (2010-01-01T00:01:00) [counter = 60000, period = 1 millisecond, epoch = 2010-01-01T00:00:00]
julia> dt2 = ITime(60, period = Second(1), epoch = DateTime(2010))60.0 seconds (2010-01-01T00:01:00) [counter = 60, period = 1 second, epoch = 2010-01-01T00:00:00]
julia> dt3 = ITime(1, period = Minute(1), epoch = DateTime(2010))1.0 minute (2010-01-01T00:01:00) [counter = 1, period = 1 minute, epoch = 2010-01-01T00:00:00]

The ITimes dt1, dt2, and dt3 represent the same quantity which is 1 minute since 2010. However, the periods are different between the ITimes. As a result, t1, t2, and t3 can only represent times in terms of milliseconds, seconds, and minutes respectively.

Furthermore, dt1, dt2, and dt3 are all different types.

julia> typeof(dt1)ClimaUtilities.TimeManager.ITime{Int64, Dates.Millisecond, Dates.DateTime}
julia> typeof(dt2)ClimaUtilities.TimeManager.ITime{Int64, Dates.Second, Dates.DateTime}
julia> typeof(dt3)ClimaUtilities.TimeManager.ITime{Int64, Dates.Minute, Dates.DateTime}

This raises two concerns to keep in mind when working with ITimes. The period in ITime represents how accurate time is kept tracked of. In the example above, dt3 can only keep track of time that is accurate up to a minute. This can result in a loss of precision in a simulation if time needs to be resolved with a higher precision than a minute. For example, in the time stepping stages, the result of t + α * dt may be rounded. However, one cannot use nanoseconds for the period because the counter will be large. This runs the risk of integer overflow in the counter. As such, one needs to be careful about what period is chosen for the ITime.

Maximum representable date

With a period of Dates.Second(1), an epoch of 2008, and a counter of type Int32, the maximum representable date is 2076-01-19T03:14:07. With Int64 instead for the type of the counter, the maximum representable date is 292277025-08-17T07:12:55.807.

With a period of Dates.Millisecond(1), an epoch of 2008, and a counter of type Int32, the maximum representable date is 2008-01-25T20:31:23.647. With Int64 instead for the type of the counter, the maximum representable date is 292277025-08-17T07:12:55.807.

No period provided

If no period is provided, then the constructor for ITime will assume the provided value is in seconds and choose a reasonable value for the period. See TimeManager section in ClimaUtilities for more information.

Next, the different types of dt1, dt2, and dt3 can lead to problems as most functions and structs expect a single type for time. This can be solved by using promote which makes all the ITimes have the same type. See the example below.

julia> dt1, dt2, dt3 = promote(dt1, dt2, dt3)(60000.0 milliseconds (2010-01-01T00:01:00) [counter = 60000, period = 1 millisecond, epoch = 2010-01-01T00:00:00], 60000.0 milliseconds (2010-01-01T00:01:00) [counter = 60000, period = 1 millisecond, epoch = 2010-01-01T00:00:00], 60000.0 milliseconds (2010-01-01T00:01:00) [counter = 60000, period = 1 millisecond, epoch = 2010-01-01T00:00:00])
julia> typeof(dt1) == typeof(dt2)true
julia> typeof(dt2) == typeof(dt3)true

Finally, other useful functions to know about ITime are date and float. The function date returns the date of t and the function float convert t into a floating point number. See the examples below.

julia> t = ITime(60, period = Second(1), epoch = DateTime(2008))60.0 seconds (2008-01-01T00:01:00) [counter = 60, period = 1 second, epoch = 2008-01-01T00:00:00]
julia> date(t)2008-01-01T00:01:00
julia> float(t)60.0