Clocks
Clocks schedule and execute actions, computations that happen as events at specified times (or under specified conditions).
Virtual Clocks
A Clock
is not bound to physical time and executes an event sequence as fast as possible by jumping from event to event.
DiscreteEvents.Clock
— TypeClock{AC} <: AbstractClock
A virtual clock structure, used for global and thread local clocks.
Fields
id::Int
: clock ident number 1: master clock, > 1: parallel clock,ac::AC
: if id == 1: aVector{ClockChannel}
else:Ref{ActiveClock}
,state::ClockState
: clock state,time::Float64
: clock time,unit::FreeUnits
: time unit,end_time::Float64
: end time for simulation,Δt::Float64
: sampling time, timestep between ticks,sc::Schedule
: the clockSchedule
(events, cond events and sampling),processes::Dict{Any, Prc}
: registeredPrc
es,channels::Vector{Channel}
: registered (Actor) channels,tn::Float64
: next timestep,tev::Float64
: next event time,evcount::Int
: event counter,scount::Int
: sample counter
DiscreteEvents.Clock
— MethodClock(Δt::T=0.01; t0::U=0, unit::FreeUnits=NoUnits) where {T<:Number,U<:Number}
Create a new virtual clock.
Arguments
Δt::T=0.01
: time increment for sampling. Δt can be set later withsample_time!
.t0::U=0
: start time for simulationunit::FreeUnits=NoUnits
: clock time unit. Units can be set explicitely by setting e.g.unit=minute
or implicitly by giving Δt as a time or else setting t0 to a time, e.g.t0=60s
.
The created clock has id==1 (master).
You can create clocks easily:
julia> using DiscreteEvents, Unitful, .Threads
julia> import Unitful: s, minute, hr
julia> c = Clock() # create a unitless clock (standard)
Clock 1: state=:idle, t=0.0, Δt=0.01, prc:0
scheduled ev:0, cev:0, sampl:0
julia> c1 = Clock(1s, unit=minute) # create a clock with unit [minute]
Clock 1: state=:idle, t=0.0minute, Δt=0.01667minute, prc:0
scheduled ev:0, cev:0, sampl:0
julia> c2 = Clock(1s) # create a clock with implicit unit [s]
Clock 1: state=:idle, t=0.0s, Δt=1.0s, prc:0
scheduled ev:0, cev:0, sampl:0
julia> c3 = Clock(t0=60s) # another clock with implicit unit [s]
Clock 1: state=:idle, t=60.0s, Δt=0.01s, prc:0
scheduled ev:0, cev:0, sampl:0
julia> c4 = Clock(1s, t0=1hr) # here Δt's unit [s] takes precedence
Clock 1: state=:idle, t=3600.0s, Δt=1.0s, prc:0
scheduled ev:0, cev:0, sampl:0
There is a default clock 𝐶
for experimental work:
DiscreteEvents.𝐶
— Constant𝐶
𝐶
(𝐶 = \itC+tab
) is a default clock, ready to use.
Examples
julia> using DiscreteEvents
julia> resetClock!(𝐶)
"clock reset to t₀=0.0, sampling rate Δt=0.01."
julia> 𝐶 # default clock
Clock 1: state=:idle, t=0.0, Δt=0.01, prc:0
scheduled ev:0, cev:0, sampl:0
You can query the current clock time:
DiscreteEvents.tau
— Functiontau(clk::Clock=𝐶)
Return the current simulation time.
Examples
julia> using DiscreteEvents
julia> resetClock!(𝐶) # reset the default clock
"clock reset to t₀=0.0, sampling rate Δt=0.01."
julia> tau() # gives the default clock's time
0.0
Real Time Clocks (Experimental)
Real time clocks are a new feature in v0.3 and thus cannot yet be considered as stable. Please try and report problems.
RTClock
s schedule and execute actions on a real (system) time line.
DiscreteEvents.RTClock
— TypeRTClock{E <: ClockEvent} <: AbstractClock
A real time clock checks every given period for scheduled events and executes them. It has a time in seconds since its start or last reset and uses system time for updating.
Real time clocks are controlled over channels. Multiple real time clocks can be setup with arbitrary periods (≥ 1 ms). Real time clocks should not be created directly but rather with CreateRTClock
.
Fields
Timer::Timer
: clock period in seconds, minimum is 0.001 (1 ms)clock::Clock
: clock workcmd::Channel{T}
: command channel to asynchronous clockback::Channel{T}
: back channel from async clockid::Int
: arbitrary id numberthread::Int
: thread the async clock is living intime::Float64
: clock time since start in secondst0::Float64
: system time at clock start in secondsT::Float64
: clock period in seconds
DiscreteEvents.createRTClock
— FunctioncreateRTClock(T::Float64, id::Int, thrd::Int=nthreads(); ch_size::Int=256)
Create, start and return a real time Clock.
The clock takes the current system time and starts to count in seconds with the given period T
. Events or sampling functions can then be scheduled to it.
Arguments
T::Float64
: period (clock resolution) in seconds, T ≥ 0.001id::Int
: clock identification number other than 0:nthreads()thrd::Int=nthreads()
: thread, the clock task should run inch_size::Int=256
: clock communication channel size
DiscreteEvents.stopRTClock
— FunctionstopRTClock(rtc::RTClock)
Stop a real time clock.
You can work with real time clocks easily:
julia> rtc = createRTClock(0.01, 99) # create a real time clock
RTClock 99 on thread 1: state=:idle, t=0.1714 s, T=0.01 s, prc:0
scheduled ev:0, cev:0, sampl:0
julia> sleep(1)
julia> tau(rtc) # query its time after a sleep
1.2157041950000007
julia> a = [1] # create a mutable variable
1-element Vector{Int64}:
1
julia> f(x) = x[1] += 1 # an incrementing function
f (generic function with 1 method)
julia> event!(rtc, fun(f, a), every, 1) # increment now and then every second
DiscreteEvents.Register{DiscreteEvents.DiscreteEvent{DiscreteEvents.var"#9#10"{Nothing, typeof(Main.ex-clocks.f), Tuple{Vector{Int64}}}, Float64}}(DiscreteEvents.DiscreteEvent{DiscreteEvents.var"#9#10"{Nothing, typeof(Main.ex-clocks.f), Tuple{Vector{Int64}}}, Float64}(DiscreteEvents.var"#9#10"{Nothing, typeof(Main.ex-clocks.f), Tuple{Vector{Int64}}}(nothing, Main.ex-clocks.f, ([1],)), 1.225829798999996, 1.0, 9223372036854775807))
julia> sleep(3) # sleep 3 seconds
julia> a[1] # query a
1
julia> stopRTClock(rtc) # stop the clock
DiscreteEvents.Stop()
Clock Operation
Virtual clocks can be run, stopped or stepped through and thereby used to simulate chains of events.
DiscreteEvents.run!
— Functionrun!(clk::Clock, duration::N) where {N<:Number}
Run a simulation for a given duration.
DiscreteEvents.@run!
— Macro@run! clk t
Run a clock clk
for a duration t
.
DiscreteEvents.incr!
— Functionincr!(clk::Clock)
Take one simulation step, execute the next tick or event.
DiscreteEvents.resetClock!
— FunctionresetClock!(clk::Clock, Δt::T=0.01; t0::U=0; <keyword arguments>) where {T<:Number, U<:Number}
Reset a clock.
Arguments
clk::Clock
Δt::T=0.01
: sample ratet0::Float64=0
ort0::Time
: start timehard::Bool=true
: time is reset, all scheduled events and sampling are deleted. If hard=false, then only time is reset, event and sampling times are adjusted accordingly.unit=NoUnits
: the Time unit for the clock after reset. If aΔt::Time
is given, its Time unit goes into the clock Time unit. If only t0::Time is given, its Time unit goes into the clock time unit.
Examples
julia> using DiscreteEvents, Unitful
julia> import Unitful: s
julia> c = Clock(1s, t0=60s)
Clock 1: state=:idle, t=60.0s, Δt=1.0s, prc:0
scheduled ev:0, cev:0, sampl:0
julia> resetClock!(c)
"clock reset to t₀=0.0, sampling rate Δt=0.01."
julia> c
Clock 1: state=:idle, t=0.0, Δt=0.01, prc:0
scheduled ev:0, cev:0, sampl:0
resetClock!(rtc::RTClock)
Reset a real time clock. Set its time to zero and delete all scheduled and sampling events.
DiscreteEvents.stop!
— Functionstop!(clk::Clock)
Stop a running simulation.
Stop a Prc
DiscreteEvents.resume!
— Functionresume!(clk::Clock)
Resume a halted simulation.
DiscreteEvents.sync!
— Functionsync!(clk::Clock, to::Clock=𝐶)
Force a synchronization of two clocks. Change all registered times of clk
accordingly. Convert or force clk.unit to to.unit.
Time Units
You can set time units of a virtual clock:
DiscreteEvents.setUnit!
— FunctionsetUnit!(clk::Clock, new::FreeUnits)
set a clock to a new time unit in Unitful
. If necessary convert current clock times to the new unit.
Arguments
clk::Clock
new::FreeUnits
: new is one ofms
,s
,minute
orhr
or another UnitfulTime
unit.
Examples
julia> using DiscreteEvents, Unitful
julia> import Unitful: Time, s, minute, hr
julia> c = Clock(t0=60) # setup a new clock with t0=60
Clock 1: state=:idle, t=60.0, Δt=0.01, prc:0
scheduled ev:0, cev:0, sampl:0
julia> tau(c) # current time is 60.0 NoUnits
60.0
julia> setUnit!(c, s) # set clock unit to Unitful.s
60.0 s
julia> tau(c) # current time is now 60.0 s
60.0 s
julia> setUnit!(c, minute) # set clock unit to Unitful.minute
1.0 minute
julia> tau(c) # current time is now 1.0 minute
1.0 minute
julia> isa(tau(c), Time)
true
julia> uconvert(s, tau(c)) # ... which can be converted to other time units
60.0 s
julia> tau(c).val # it has a value of 1.0
1.0
julia> c.time # internal clock time is set to 1.0 (a Float64)
1.0
julia> c.unit # internal clock unit is set to Unitful.minute
minute
This is not yet implemented for parallel clocks!