-
Notifications
You must be signed in to change notification settings - Fork 191
/
clock.jl
66 lines (49 loc) · 2.14 KB
/
clock.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using Adapt
using Dates: AbstractTime, DateTime, Nanosecond, Millisecond
using Oceananigans.Utils: prettytime
import Base: show
import Oceananigans.Units: Time
"""
mutable struct Clock{T<:Number}
Keeps track of the current `time`, `iteration` number, and time-stepping `stage`.
The `stage` is updated only for multi-stage time-stepping methods. The `time::T` is
either a number or a `DateTime` object.
"""
mutable struct Clock{T}
time :: T
iteration :: Int
stage :: Int
end
"""
Clock(; time, iteration=0, stage=1)
Returns a `Clock` object. By default, `Clock` is initialized to the zeroth `iteration`
and first time step `stage`.
"""
Clock(; time::T, iteration=0, stage=1) where T = Clock{T}(time, iteration, stage)
Base.summary(clock::Clock) = string("Clock(time=$(prettytime(clock.time)), iteration=$(clock.iteration))")
Base.show(io::IO, c::Clock{T}) where T =
println(io, "Clock{$T}: time = $(prettytime(c.time)), iteration = $(c.iteration), stage = $(c.stage)")
next_time(clock, Δt) = clock.time + Δt
next_time(clock::Clock{<:AbstractTime}, Δt) = clock.time + Nanosecond(round(Int, 1e9 * Δt))
tick_time!(clock, Δt) = clock.time += Δt
tick_time!(clock::Clock{<:AbstractTime}, Δt) = clock.time += Nanosecond(round(Int, 1e9 * Δt))
Time(clock::Clock) = Time(clock.time)
# Convert the time to units of clock.time (assumed to be seconds if using DateTime or TimeDate).
unit_time(t) = t
unit_time(t::Millisecond) = t.value / 1_000
unit_time(t::Nanosecond) = t.value / 1_000_000_000
# Convert to a base Julia type (a float or DateTime). Mainly used by NetCDFOutputWriter.
float_or_date_time(t) = t
float_or_date_time(t::AbstractTime) = DateTime(t)
function tick!(clock, Δt; stage=false)
tick_time!(clock, Δt)
if stage # tick a stage update
clock.stage += 1
else # tick an iteration and reset stage
clock.iteration += 1
clock.stage = 1
end
return nothing
end
"Adapt `Clock` to work on the GPU via CUDAnative and CUDAdrv."
Adapt.adapt_structure(to, clock::Clock) = (time=clock.time, iteration=clock.iteration, stage=clock.stage)