forked from SciML/ModelingToolkit.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclock.jl
120 lines (94 loc) · 3.1 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
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
108
109
110
111
112
113
114
115
116
117
118
119
120
module InferredClock
export InferredTimeDomain
using Expronicon.ADT: @adt, @match
using SciMLBase: TimeDomain
@adt InferredTimeDomain begin
Inferred
InferredDiscrete
end
Base.Broadcast.broadcastable(x::InferredTimeDomain) = Ref(x)
end
using .InferredClock
struct VariableTimeDomain end
Symbolics.option_to_metadata_type(::Val{:timedomain}) = VariableTimeDomain
is_concrete_time_domain(::TimeDomain) = true
is_concrete_time_domain(_) = false
"""
is_continuous_domain(x)
true if `x` contains only continuous-domain signals.
See also [`has_continuous_domain`](@ref)
"""
function is_continuous_domain(x)
issym(x) && return getmetadata(x, VariableTimeDomain, false) == Continuous
!has_discrete_domain(x) && has_continuous_domain(x)
end
get_time_domain(_, x) = get_time_domain(x)
function get_time_domain(x)
if iscall(x) && operation(x) isa Operator
output_timedomain(x)
else
getmetadata(x, VariableTimeDomain, nothing)
end
end
get_time_domain(x::Num) = get_time_domain(value(x))
has_time_domain(_, x) = has_time_domain(x)
"""
has_time_domain(x)
Determine if variable `x` has a time-domain attributed to it.
"""
function has_time_domain(x::Symbolic)
# getmetadata(x, Continuous, nothing) !== nothing ||
# getmetadata(x, Discrete, nothing) !== nothing
getmetadata(x, VariableTimeDomain, nothing) !== nothing
end
has_time_domain(x::Num) = has_time_domain(value(x))
has_time_domain(x) = false
for op in [Differential]
@eval input_timedomain(::$op, arg = nothing) = Continuous
@eval output_timedomain(::$op, arg = nothing) = Continuous
end
"""
has_discrete_domain(x)
true if `x` contains discrete signals (`x` may or may not contain continuous-domain signals). `x` may be an expression or equation.
See also [`is_discrete_domain`](@ref)
"""
function has_discrete_domain(x)
issym(x) && return is_discrete_domain(x)
hasshift(x) || hassample(x) || hashold(x)
end
"""
has_continuous_domain(x)
true if `x` contains continuous signals (`x` may or may not contain discrete-domain signals). `x` may be an expression or equation.
See also [`is_continuous_domain`](@ref)
"""
function has_continuous_domain(x)
issym(x) && return is_continuous_domain(x)
hasderiv(x) || hasdiff(x) || hassample(x) || hashold(x)
end
"""
is_hybrid_domain(x)
true if `x` contains both discrete and continuous-domain signals. `x` may be an expression or equation.
"""
is_hybrid_domain(x) = has_discrete_domain(x) && has_continuous_domain(x)
"""
is_discrete_domain(x)
true if `x` contains only discrete-domain signals.
See also [`has_discrete_domain`](@ref)
"""
function is_discrete_domain(x)
if hasmetadata(x, VariableTimeDomain) || issym(x)
return is_discrete_time_domain(getmetadata(x, VariableTimeDomain, false))
end
!has_discrete_domain(x) && has_continuous_domain(x)
end
sampletime(c) = @match c begin
PeriodicClock(dt, _...) => dt
_ => nothing
end
struct ClockInferenceException <: Exception
msg::Any
end
function Base.showerror(io::IO, cie::ClockInferenceException)
print(io, "ClockInferenceException: ", cie.msg)
end
struct IntegerSequence end