Usage

User guide

Installation

Simulate.jl runs on Julia versions ≥ v"1.0" [1]. The current stable, registered version is installed with

pkg> add Simulate

The development version is installed with:

pkg> add("https://github.com/pbayer/Simulate.jl")

The package is then loaded with

julia> using Simulate

The clock

Simulate.ClockType.
Clock(Δt::Number=0; t0::Number=0, unit::FreeUnits=NoUnits)

Create a new simulation clock.

Arguments

  • Δt::Number=0: time increment. If no Δt is given, the simulation doesn't tick, but jumps from event to event. Δt can be set later with sample_time!.
  • t0::Number=0: start time for simulation
  • unit::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.

Fields

  • state::SState: clock state
  • time::Float64: clock time
  • unit::FreeUnits: time unit
  • events::PriorityQueue{SimEvent,Float64}: scheduled events
  • cevents::Array{SimCond,1}: conditional events
  • processes::Dict{Any, SimProcess}: registered processes
  • end_time::Float64: end time for simulation
  • evcount::Int64: event counter
  • scount::Int64: sample count
  • tev::Float64: next event time
  • Δt::Float64: sampling time, timestep between ticks
  • sexpr::Array{Sample,1}: sampling expressions to evaluate at each tick
  • tsa::Float64: next sample time

Examples

julia> using Simulate, Unitful

julia> import Unitful: s, minute, hr

julia> c = Clock()                 # create a unitless clock (standard)
Clock: state=Simulate.Undefined(), time=0.0, unit=, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=0.0

julia> init!(c)                    # initialize it explicitly (normally done implicitly)
Simulate.Idle()

julia> c = Clock(1s, unit=minute)  # create a clock with units, does conversions automatically
Clock: state=Simulate.Undefined(), time=0.0, unit=minute, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=0.016666666666666666

julia> c = Clock(1s)               # create a clock with implicit unit setting
Clock: state=Simulate.Undefined(), time=0.0, unit=s, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=1.0

julia> c = Clock(t0=60s)           # another example of implicit unit setting
Clock: state=Simulate.Undefined(), time=60.0, unit=s, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=0.0

julia> c = Clock(1s, t0=1hr)       # if given times with different units, Δt takes precedence
Clock: state=Simulate.Undefined(), time=3600.0, unit=s, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=1.0
source

The central clock is 𝐶. You can set time units and query the current simulation time.

Simulate.𝐶Constant.
𝐶
Clk

𝐶 (𝐶 = \itC+tab) or Clk is the central simulation clock. If you do one simulation at a time, you can use 𝐶 or Clk for time keeping.

Examples

julia> using Simulate

julia> reset!(𝐶)
"clock reset to t₀=0.0, sampling rate Δt=0.0."

julia> 𝐶  # central clock
Clock: state=Simulate.Idle(), time=0.0, unit=, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=0.0

julia> 𝐶 === Clk
true
source
Simulate.setUnit!Function.
setUnit!(sim::Clock, new::FreeUnits)

set a clock to a new time unit in Unitful. If necessary convert current clock times to the new unit.

Arguments

  • sim::Clock
  • new::FreeUnits: new is one of ms, s, minute or hr or another Unitful Time unit.

Examples

julia> using Simulate, Unitful

julia> import Unitful: Time, s, minute, hr

julia> c = Clock(t0=60)     # setup a new clock with t0=60
Clock: state=Simulate.Undefined(), time=60.0, unit=, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=0.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> typeof(tau(c))       # tau(c) now returns a time Quantity ...
Quantity{Float64,𝐓,Unitful.FreeUnits{(minute,),𝐓,nothing}}

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
source
Simulate.tauMethod.
tau(sim::Clock=𝐶)
τ(sim::Clock=𝐶)

Return the current simulation time (τ = \tau+tab).

Examples

julia> using Simulate

julia> reset!(𝐶)
"clock reset to t₀=0.0, sampling rate Δt=0.0."
julia> tau() # gives the central time
0.0
julia> τ() # alias, gives the central time
0.0
source
Simulate.@tauMacro.
@tau(sim::Clock)
@tau sim
@tau()
@tau

return the current simulation time.

Arguments

  • sim::Clock: if no clock argument is given, it returns 𝐶's time.
source

Events

Events are scheduled on the clock's timeline and are triggered at a given simulation time or under conditions which may become true during simulation.

Expressions and functions as events and conditions

Julia expressions and functions can be scheduled as events.

Simulate.TimingType.
Timing

Enumeration type for scheduling events and timed conditions:

  • at: schedule an event at a given time,
  • after: schedule an event a given time after current time,
  • every: schedule an event every given time from now on,
  • before: a timed condition is true before a given time,
  • until: delay until t.
source
SimFunction(func::Function, arg...; kw...)
SF(func::Function, arg...; kw...)

Prepare a function for being called as an event in a simulation.

Arguments, fields

  • func::Function: function to be executed at a later simulation time
  • arg...: arguments to the function
  • kw...: keyword arguments
Note

If the variables stored in a SimFunction are composite types, they can change until they are evaluated later by func.

Example

julia> using Simulate

julia> f(a,b,c; d=4, e=5) = a+b+c+d+e       # if you define a function and ...
f (generic function with 1 method)

julia> sf = SF(f, 10, 20, 30, d=14, e=15);  # store it as SimFunction

julia> sf.func(sf.arg...; sf.kw...)         # it can be executed later
89

julia> d = Dict(:a => 1, :b => 2);          # we set up a dictionary

julia> g(t) = t[:a] + t[:b]                 # and a function adding :a and :b
g (generic function with 1 method)

julia> g(d)                                 # our add function gives 3
3

julia> ff = SimFunction(g, d);              # we set up a SimFunction

julia> d[:a] = 10;                          # later somehow we change d

julia> ff.func(ff.arg...)                   # calling ff then gives a different result
12
source
Simulate.@SFMacro.
@SF(f::Symbol, arg...)
@SF f arg...

create a SimFunction from arguments f, arg...

Arguments

  • f::Symbol: a function given as a symbol, e.g. :f if f() is your function,
  • arg...: further arguments to your function
Note
  1. keyword arguments don't work with this macro, use SF instead.
  2. if you give @SF as argument(s) to a function, you must enclose it/them in parentheses ( @SF ... ) or ( (@SF ...), (@SF ...) )

Examples

julia> using Simulate

julia> a = 1
1
julia> incra() = global a += 1             # create a simple increment function
incra (generic function with 1 method)

julia> event!((@SF incra), after, 3);      # schedule an increment after 3 time units

julia> a                                   # nothing happened to a
1

julia> run!(𝐶, 5)                          # run the simulation
"run! finished with 1 clock events, 0 sample steps, simulation time: 5.0"

julia> a                                   # now it should have been incremented
2

julia> event!((@SF incra), (@tau :>= 8));  # schedule a conditional event

julia> run!(𝐶, 5)
"run! finished with 0 clock events, 301 sample steps, simulation time: 10.0"

julia> a                                   # the conditional event was triggered
3

julia> event!(((@SF incra), (@SF incra)),  # two increments
        ((@tau :>= 12), (@val :a :<= 3))); # on two conditions

julia> run!(𝐶, 5)
"run! finished with 0 clock events, 201 sample steps, simulation time: 15.0"

julia> a                                   # two increments happened
5
source
Simulate.SimExprConstant.
SimExpr = Union{Expr, SimFunction}

A type which is either a SimFunction or Julia expression, Expr-type.

source

SimFunctions and expressions can be given to events on their own or in arrays or tuples, even mixed:

function events()
    event!(:(i += 1), after, 10)  # one expression
    event!(SF(f, 1, 2, 3, diff=pi), every, 1)  # one SimFunction
    event!((:(i += 1), SF(g, j)), [:(tau() ≥ 50), SF(isready, input), :(a ≤ 10)]) # two SimExpr under three conditions
end

All given expressions or functions are then evaluated at a given simulation time or when during simulation the given conditions become true.

Timed events

SimFunctions and expressions can be scheduled for execution at given clock times.

Simulate.event!Method.
event!(sim::Clock, ex::Union{SimExpr, Array, Tuple}, t::Number; scope::Module=Main, cycle::Number=0.0)::Float64
event!(ex::Union{SimExpr, Array, Tuple}, t::Number; scope::Module=Main, cycle::Number=0.0)

Schedule an event for a given simulation time.

Arguments

  • sim::Clock: simulation clock, if no clock is given, the event goes to 𝐶,
  • ex::{SimExpr, Array, Tuple}: an expression or SimFunction or an array or tuple of them,
  • t::Real or t::Time: simulation time, if t < sim.time set t = sim.time,
  • scope::Module=Main: scope for expressions to be evaluated in,
  • cycle::Float64=0.0: repeat cycle time for an event.

returns

Scheduled internal simulation time (unitless) for that event. May return a time > t from repeated applications of nextfloat(t) if there are events scheduled for t.

Examples

julia> using Simulate, Unitful

julia> import Unitful: s, minute, hr

julia> myfunc(a, b) = a+b
myfunc (generic function with 1 method)

julia> event!(𝐶, SimFunction(myfunc, 1, 2), 1) # a 1st event to 1
1.0
julia> event!(𝐶, SimFunction(myfunc, 2, 3), 1) #  a 2nd event to the same time
1.0000000000000002

julia> event!(𝐶, SimFunction(myfunc, 3, 4), 1s)
Warning: clock has no time unit, ignoring units
1.0000000000000004

julia> setUnit!(𝐶, s)
0.0 s

julia> event!(𝐶, SimFunction(myfunc, 4, 5), 1minute)
60.0
source

As a convenience the Timing can be also choosen using at, after or every t.

Simulate.event!Method.
event!(sim::Clock, ex::Union{SimExpr, Array, Tuple}, T::Timing, t::Number; scope::Module=Main)::Float64
event!(ex::Union{SimExpr, Array, Tuple}, T::Timing, t::Number; scope::Module=Main)

Schedule a timed event, that is an event with a timing.

Arguments

  • sim::Clock: simulation clock, if no clock is given, the event goes to 𝐶,
  • ex::{SimExpr, Array, Tuple}: an expression or SimFunction or an array or tuple of them,
  • T::Timing: a timing, at, after or every (before behaves like at),
  • t::Float64 or t::Time: simulation time,
  • scope::Module=Main: scope for the expressions to be evaluated

returns

Scheduled internal simulation time (unitless) for that event.

Examples

julia> using Simulate, Unitful

julia> import Unitful: s, minute, hr

julia> setUnit!(𝐶, s)
0.0 s

julia> myfunc(a, b) = a+b
myfunc (generic function with 1 method)

julia> event!(𝐶, SimFunction(myfunc, 5, 6), after, 1hr)
3600.0
source

Conditional events

They are evaluated at each clock tick (like sampling functions) and are fired when all conditions are met.

Simulate.event!Method.
event!(sim::Clock, ex::Union{SimExpr, Array, Tuple}, cond::Union{SimExpr, Array, Tuple}; scope::Module=Main):
event!(ex::Union{SimExpr, Array, Tuple}, cond::Union{SimExpr, Array, Tuple}; scope::Module=Main)

Schedule a conditional event.

It is executed immediately if the conditions are met, else the condition is checked at each clock tick Δt. A conditional event is triggered only once. After that it is removed from the clock. If no sampling rate Δt is setup, a default sampling rate is setup depending on the scale of the remaining simulation time $Δt = scale(t_r)/100$ or $0.01$ if $t_r = 0$.

Arguments

  • sim::Clock: simulation clock, if no clock is given, the event goes to 𝐶,
  • ex::{SimExpr, Array, Tuple}: an expression or SimFunction or an array or tuple of them,
  • cond::{SimExpr, Array, Tuple}: a condition is an expression or SimFunction or an array or tuple of them. It is true only if all expressions or SimFunctions therein return true,
  • scope::Module=Main: scope for the expressions to be evaluated

returns

current simulation time tau(sim).

Examples

julia> using Simulate

julia> c = Clock()   # create a new clock
Clock: state=Simulate.Undefined(), time=0.0, unit=, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=0.0

julia> event!(c, SF((x)->println(tau(x), ": now I'm triggered"), c), (@tau c :>= 5))
0.0

julia> c             # a conditional event turns sampling on
Clock: state=Simulate.Undefined(), time=0.0, unit=, events: 0, cevents: 1, processes: 0, sampling: 0, sample rate Δt=0.01

julia> run!(c, 10)   # sampling is not exact, so it takes 501 sample steps to fire the event
5.009999999999938: now I'm triggered
"run! finished with 0 clock events, 501 sample steps, simulation time: 10.0"

After the event is triggered, sampling is again switched off.

source
Note

Since conditions often are not met exactly you should prefer inequalities like <, ≤, ≥, > to equality == in order to get sure that a fulfilled condition can be detected, e.g. $:(tau() ≥ 100)$ is preferable to $:(tau() == 100)$.

There are some helper functions and macros for defining conditions. It is usually more convenient to use the macros since the generate the necessary SimFunctions directly:

Simulate.tauMethod.
tau(sim::Clock, check::Function, x::Union{Number,Symbol}; m::Module=Main)
tau(check::Function, x::Union{Number,Symbol}; m::Module=Main)

Compare the current simulation time against a number or a variable.

Arguments

  • sim::Clock: clock variable, if not given, it is 𝐶.
  • check::Function: a comparison operator like ≥, >, ==, <, ≤,
  • x::Union{Number,Symbol}: a number or a symbolic variable like :a, a symbolic variable can be evaluated later at event time,
  • m::Module=Main: the evaluation scope, if a symbolic variable is given.

Examples

julia> using Simulate

julia> tau(>=, 1)
false

julia> tau(<, 1)
true

julia> a = 1
1

julia> tau(<=, :a, @__MODULE__)
true
source
Simulate.@tauMacro.
@tau(sim::Clock, check::Symbol, val)
@tau sim check val
@tau(check::Symbol, val)
@tau check val

create a SimFunction comparing current simulation time with a given value or variable.

Arguments

  • sim::Clock: if no clock is given, it compares with 𝐶's time,
  • check::Symbol: the check operator must be given as a symbol e.g. :<,
  • val::Union{Number, QuoteNode}: a value or a symbolic variable,
Note

If you give @tau as argument(s) to a function, you must enclose it/them in parentheses ( @tau ... ) or ( (@tau ...), (@tau ...) )!

Examples

julia> using Simulate

julia> reset!(𝐶)
"clock reset to t₀=0.0, sampling rate Δt=0.0."
julia> sf = @tau :≥ 100;

julia> Simulate.simExec(sf)
false

julia> Simulate.simExec(@tau < 100)                ### wrong !!
ERROR: syntax: "<" is not a unary operator

julia> Simulate.simExec(@tau :< 100)               ### correct
true

julia> a = 1
1

julia> Simulate.simExec(@tau :< :a)
true

julia> event!(SF(()->global a+=1), (@tau :>= 3))   ### create a conditional event
0.0

julia> a
1

julia> run!(𝐶, 5)                                  ### run
"run! finished with 0 clock events, 301 sample steps, simulation time: 5.0"

julia> a
2
source
Simulate.valFunction.
val(a::Union{Number, Symbol}, check::Function, x::Union{Number, Symbol}, m::Module=Main)

Compare two variables or numbers.

Arguments

  • a, xUnion{Number, Symbol}: a number or a symbolic variable like :a, a symbolic variable can be evaluated later at event time,
  • check::Function: a comparison operator like ≥, >, ==, <, ≤,
  • m::Module=Main: the evaluation scope, if a symbolic variable is given.

Examples

julia> using Simulate

julia> val(1, <=, 2)
true

julia> a = 1
1

julia> val(:a, <=, 2, @__MODULE__)
true
source
Simulate.@valMacro.
@val(a, check::QuoteNode, b)
@val a check b

Create a Simfunction comparing two values a and b or two symbolic variables :a and :b. The comparison operator must be given symbolically, e.g. :≤.

Arguments

  • a, b:: a number, expression or symbol
  • check::QuoteNode: a comparison operator as a symbol like :> or :≤
Note

If you give @val as argument(s) to a function, you must enclose it/them in parentheses ( @val ... ) or e.g. ( (@tau ...), (@val ...) )!

Examples

julia> using Simulate

julia> reset!(𝐶)
"clock reset to t₀=0.0, sampling rate Δt=0.0."

julia> Simulate.simExec(@val 1 :≤ 2)
true

julia> a = 1
1

julia> Simulate.simExec(@val :a :≤ 2)
true

julia> event!(SF(()->global a+=1), ((@tau :>= 3), (@val :a :<= 3))); # a conditional event

julia> run!(𝐶, 5)
"run! finished with 0 clock events, 301 sample steps, simulation time: 5.0"

julia> a
2
source

Processes

Julia functions can be registered and run as processes if they have an input and an output channel as their first two arguments. They follow another (the process-oriented) scheme and can be suspended and reactivated by the scheduler if they wait for something or delay. They must not (but are free to) handle and create events explicitly.

SimProcess( id, func::Function, arg...; kw...)
SP(id, func::Function, arg...; kw...)

Prepare a function to run as a process in a simulation.

Arguments, fields

  • id: some unique identification, it should get registered with
  • func::Function: a function f(arg...; kw...)
  • arg...: further arguments to f
  • kw...: keyword arguments to f
Note

A function as a SimProcess most often runs in a loop. It has to give back control by e.g. doing a take!(input) or by calling delay! etc., which will yield it. Otherwise it will starve everything else!

Examples

julia> using Simulate
source
Simulate.@SPMacro.
@SP(id, f::Symbol, arg...)
@SP id f arg...

create a SimProcess from arguments f, arg...

Note

keyword arguments don't work with this macro, use SP instead.

source
SimException(ev::SEvent, value=nothing)

Define a SimException, which can be thrown to processes.

Arguments, fields

  • ev::SEvent: delivers an event to the interrupted task
  • value=nothing: deliver some other value
source
Simulate.process!Function.
process!(sim::Clock, p::SimProcess, cycles=Inf)
process!(p::SimProcess, cycles=Inf)

Register a SimProcess to a clock, start it as an asynchronous process and return the id it was registered with. It can then be found under sim.processes[id].

Arguments

  • sim::Clock: clock, if no clock is given, it runs under 𝐶,
  • p::SimProcess
  • cycles::Number=Inf: number of cycles the process should run.
source
Simulate.interrupt!Function.
interrupt!(p::SimProcess, ev::SEvent, value=nothing)

Interrupt a SimProcess by throwing a SimException to it.

source
Simulate.stop!Method.

Stop a SimProcess

source

Delay and wait …

Processes must not handle their events explicitly, but can call delay! or wait! or take! and put! … on their channels. This usually comes in handy. They are then suspended until certain conditions are met or requested resources are available.

Simulate.delay!Function.
delay!(sim::Clock, t::Number)
delay!(t::Number)

Delay a process for a time interval t on the clock sim. Suspend the calling process until being reactivated by the clock at the appropriate time.

Arguments

  • sim::Clock: clock, if no clock is given, the delay goes to 𝐶.
  • t::Number: the time interval for the delay.
source
delay!(sim::Clock, T::Timing, t::Number)
delay!(T::Timing, t::Number)

Used for delaying a process until a given time t.

Arguments

  • sim::Clock: if no clock is given, the delay goes to 𝐶,
  • T::Timing: only until is accepted,
  • t::Number: delay until time t if t > sim.time, else give a warning.
source
Simulate.wait!Function.
wait!(sim::Clock, cond::Union{SimExpr, Array, Tuple}; scope::Module=Main)
wait!(cond::Union{SimExpr, Array, Tuple}; scope::Module=Main)

Wait on a clock for a condition to become true. Suspend the calling process until the given condition is true.

Arguments

  • sim::Clock: clock, if no clock is given, the delay goes to 𝐶.
  • cond::Union{SimExpr, Array, Tuple}: a condition is an expression or SimFunction or an array or tuple of them. It is true only if all expressions or SimFunctions therein return true.
  • scope::Module=Main: evaluation scope for given expressions
source

Now

If processes want IO-operations to finish before letting the clock proceed, they can enclose those operations in a now! call.

Simulate.now!Function.
now!(sim::Clock, op::Union{SimExpr, Array, Tuple})
now!(op::Union{SimExpr, Array, Tuple})

Let the given operation be executed now! by the clock. Thus the clock cannot proceed before the op is finished.

Arguments

  • sim::Clock:
  • op::Union{SimExpr, Array, Tuple}:
source

Continuous sampling

Functions or expressions can register for sampling and are then executed "continuously" at each clock increment Δt.

Simulate.sample_time!Function.
sample_time!(sim::Clock, Δt::Number)
sample_time!(Δt::Number)

set the clock's sample rate starting from now (tau(sim)).

Arguments

  • sim::Clock: if no clock is given, set the sample rate on 𝐶,
  • Δt::Number: sample rate, time interval for sampling
source
Simulate.sample!Function.
sample!(sim::Clock, ex::Union{Expr, SimFunction}, Δt::Number=sim.Δt; scope::Module=Main)
sample!(ex::Union{Expr, SimFunction}, Δt::Number=sim.Δt; scope::Module=Main)

enqueue an expression for sampling.

Arguments

  • sim::Clock: if no clock is given, it samples on 𝐶,
  • ex::Union{Expr, SimFunction}: an expression or function,
  • Δt::Number=sim.Δt: set the clock's sampling rate, if no Δt is given, it takes the current sampling rate, if that is 0, it calculates one,
  • scope::Module=Main: optional, an evaluation scope for a given expression.
source

Running simulations

If we run the clock, events are triggered, conditions are evaluated, sampling is done and delays are executed … Thus we run a simulation. We can also step through a simulation or stop and resume a clock, reset ist and so on.

Simulate.reset!Function.
reset!(sim::Clock, Δt::Number=0; t0::Number=0, hard::Bool=true, unit=NoUnits)

reset a clock

Arguments

  • sim::Clock
  • Δt::Number=0: time increment
  • t0::Float64=0 or t0::Time: start time
  • hard::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 Simulate, Unitful

julia> import Unitful: s

julia> c = Clock(1s, t0=60s)
Clock: state=Simulate.Undefined(), time=60.0, unit=s, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=1.0

julia> reset!(c)
"clock reset to t₀=0.0, sampling rate Δt=0.0."

julia> c
Clock: state=Simulate.Idle(), time=0.0, unit=, events: 0, cevents: 0, processes: 0, sampling: 0, sample rate Δt=0.0
source
Simulate.incr!Function.
incr!(sim::Clock)

Take one simulation step, execute the next tick or event.

source
Simulate.run!Function.
run!(sim::Clock, duration::Number)

Run a simulation for a given duration. Call scheduled events and evaluate sampling expressions at each tick in that timeframe.

source
Simulate.stop!Method.
stop!(sim::Clock)

Stop a running simulation.

source
Simulate.resume!Function.
resume!(sim::Clock)

Resume a halted simulation.

source
Simulate.sync!Function.
sync!(sim::Clock, to::Clock=𝐶)

Force a synchronization of two clocks. Change all registered times of sim accordingly. Convert or force sim.unit to to.unit.

source

Logging

A Logger allows to register variables and to record their states on demand. The last record is stored in the logging variable. According to the Logger's state it can be printed or stored in a table.

Example

julia> sim = Clock(); # create a clock

julia> l = Logger(); # create a logging variable

julia> init!(l, sim); # initialize the logger

julia> (a, b, c) = 1, 1, 1 # create some variables
(1, 1, 1)

julia> setup!(l, [:a, :b, :c], scope = m); # register them for logging
ERROR: UndefVarError: m not defined

julia> record!(l) # record the variables with the current clock time
Warning: undefined transition Logger, ::Simulate.Empty, ::Simulate.Log)

julia> l.last # show the last record
NamedTuple()

julia> function f()  # a function for increasing and recording the variables
         global a += 1
         global b = a^2
         global c = a^3
         record!(l)
       end
f (generic function with 1 method)

julia> switch!(l, 1); # switch logger to printing
Warning: undefined transition Logger, ::Simulate.Empty, ::Simulate.Switch)

julia> f() # increase and record the variables
Warning: undefined transition Logger, ::Simulate.Empty, ::Simulate.Log)

julia> switch!(l, 2); # switch logger to storing in data table
Warning: undefined transition Logger, ::Simulate.Empty, ::Simulate.Switch)

julia> for i in 1:10 # create some events
           event!(sim, :(f()), i, scope = m)
       end
ERROR: UndefVarError: m not defined

julia> run!(sim, 10) # run a simulation
"run! finished with 0 clock events, 0 sample steps, simulation time: 10.0"

julia> l.df # view the recorded values
0×0 DataFrames.DataFrame

Types

Simulate.LoggerType.
Logger()

Setup and return a logging variable.

source

Functions

Simulate.init!Function.
init!(sim::Clock)

initialize a clock.

source
init!(L::Logger, sim::Clock)

Initialize a Logger.

source
Simulate.setup!Function.
setup!(L::Logger, vars::Array{Symbol})

Setup a logger with logging variables.

Arguments

  • L::Logger
  • vars::Array{Symbol}: An array of symbols, e.g. of global variables
  • scope::Module = Main: Scope in which to evaluate the variables
source
Simulate.switch!Function.
switch!(L::Logger, to::Number=0)

Switch the operating mode of a logger.

to = 0: no output, to = 1: print, `to = 2: store in log table"

source
Simulate.record!Function.
record!(L::Logger)

record the logging variables with the current operating mode.

source
Simulate.clear!Function.
clear!(L::Logger)

clear the loggers last record and data table.

source
[1]

currently builds fail on x86 machines with Julia 1.0, Appveyor is set to allow this. There is an issue in the repo, maybe someone can look into it or fix it.