-
Notifications
You must be signed in to change notification settings - Fork 191
/
clock.jl
79 lines (59 loc) · 2.7 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
67
68
69
70
71
72
73
74
75
76
77
78
79
using Adapt
using Dates: AbstractTime, DateTime, Nanosecond, Millisecond
using Oceananigans.Utils: prettytime
import Base: show
import Oceananigans.Units: Time
"""
mutable struct Clock{T, FT}
Keeps track of the current `time`, `last_Δt`, `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{TT, DT}
time :: TT
last_Δt :: DT
iteration :: Int
stage :: Int
end
"""
Clock(; time, last_Δt = Inf, iteration=0, stage=1)
Returns a `Clock` object. By default, `Clock` is initialized to the zeroth `iteration`
and first time step `stage` with `last_Δt`.
"""
Clock(; time::TT, last_Δt::DT=Inf, iteration=0, stage=1) where {TT, DT} = Clock{TT, DT}(time, last_Δt, iteration, stage)
# TODO: when supporting DateTime, this function will have to be extended
time_step_type(TT) = TT
function Clock{TT}(; time, last_Δt=Inf, iteration=0, stage=1) where TT
DT = time_step_type(TT)
last_Δt = convert(DT, last_Δt)
return Clock{TT, DT}(time, last_Δt, iteration, stage)
end
Base.summary(clock::Clock) = string("Clock(time=$(prettytime(clock.time)), iteration=$(clock.iteration), last_Δt=$(prettytime(clock.last_Δt)))")
Base.show(io::IO, c::Clock{TT, DT}) where {TT, DT} =
println(io, "Clock{$TT, $DT}: time = $(prettytime(c.time)), last_Δt = $(prettytime(c.last_Δt)), 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)
clock.last_Δt = Δ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, last_Δt=clock.last_Δt, iteration=clock.iteration, stage=clock.stage)