/
types.jl
107 lines (80 loc) · 3.44 KB
/
types.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"""
SimulationLog(; value_dict::Dict{Symbol,Vector}=Dict{Symbol,Vector}(), is_active::Bool=false)
A log of saved variables from a simulation. Variables can be accessed with dot notation or the `getproperty`
function.
"""
Base.@kwdef mutable struct SimulationLog
value_dict::Dict{Symbol, Array} = Dict{Symbol, Array}()
is_active::Bool = false
end
function Base.show(io::IO, log::SimulationLog)
println(io, "SimulationLog with signals:")
for (name, val) in value_dict(log)
println(io, " $name :: $(typeof(val))")
end
end
# Field access
"""
value_dict(log::SimulationLog)
Get the value dictionary of a `SimulationLog`.
"""
value_dict(log::SimulationLog) = getfield(log, :value_dict)
"""
is_active(log::SimulationLog)
See if simulation is currently active (able to be logged to).
"""
is_active(log::SimulationLog) = getfield(log, :is_active)
# Setting fields
"""
activate!(log::SimulationLog=GLOBAL_LOG)
Activate a `SimulationLog`. If no log is given, activate the `GLOBAL_LOG`.
"""
activate!(log::SimulationLog=GLOBAL_LOG) = setfield!(log, :is_active, true)
"""
deactivate!(log::SimulationLog=GLOBAL_LOG)
Deactivate a `SimulationLog`. If no log is given, deactivate the `GLOBAL_LOG`.
"""
deactivate!(log::SimulationLog=GLOBAL_LOG) = setfield!(log, :is_active, false)
"""
reset!(log::SimulationLog=GLOBAL_LOG)
Reset the value dictionary of a `SimulationLog`. If no log is given, the `GLOBAL_LOG` will
be reset
"""
reset!(log::SimulationLog=GLOBAL_LOG) = setfield!(log, :value_dict, Dict{Symbol, Array}())
# Value access
Base.keys(log::SimulationLog) = keys(value_dict(log))
Base.propertynames(log::SimulationLog) = Tuple(keys(value_dict(log)))
Base.getproperty(log::SimulationLog, s::Symbol) = value_dict(log)[s]
function Base.setproperty!(log::SimulationLog, s::Symbol, val)
val_dict = value_dict(log)
val_dict[s] = val
end
Base.getindex(log::SimulationLog, s::Symbol) = getproperty(log, s)
Base.setindex!(log::SimulationLog, val, s::Symbol) = setproperty!(log, s, val)
"""
struct Logged{T,N,A,S<:AbstractTimeseriesSolution{T,N,A}} <: AbstractTimeseriesSolution{T,N,A}
Logged(sol::AbstractTimeseriesSolution, log::SimulationLog)
Logged differential equation solution. All properties of the underlying solution
can be accessed with the `getproperty` or 'dot' accessing. The inner `SimulationLog` can
be accessed with `.log`. A `Logged` solution can be used the same way as its underlying
solution (i.e. indexed with `sol[i]` and interpolated with `sol(t)`)
"""
struct Logged{T,N,A,S<:AbstractTimeseriesSolution{T,N,A}} <: AbstractTimeseriesSolution{T,N,A}
sol::S
log::SimulationLog
end
function Base.show(io::IO, mime::MIME"text/plain", sol::Logged)
show(io, mime, sol.sol)
println(io, "\nWith logged values:")
for (name, val) in value_dict(sol.log)
println(io, " $name: $(join(string.(size(val)), "×"))-element $(typeof(val))")
end
end
(sol::Logged)(args...; kwargs...) = sol.sol(args...; kwargs...)
Base.getindex(sol::Logged, i::Int) = getindex(sol.sol, i)
Base.getindex(sol::Logged, i::Colon) = getindex(sol.sol, i)
@inline Base.getproperty(sol::Logged, s::Symbol) = getproperty(sol, Val(s))
@inline Base.getproperty(sol::Logged, ::Val{:log}) = getfield(sol, :log)
@inline Base.getproperty(sol::Logged, ::Val{:sol}) = getfield(sol, :sol)
@inline Base.getproperty(sol::Logged, ::Val{s}) where {s} = getproperty(sol.sol, s)
Base.propertynames(sol::Logged) = (:log, propertynames(sol.sol)...)