Skip to content

Commit 17b0a95

Browse files
committed
Merge branch 'master' into constants2
2 parents af89d7b + 7a80a24 commit 17b0a95

13 files changed

+632
-19
lines changed

Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
name = "ModelingToolkit"
22
uuid = "961ee093-0014-501f-94e3-6117800e7a78"
33
authors = ["Yingbo Ma <[email protected]>", "Chris Rackauckas <[email protected]> and contributors"]
4-
version = "8.29.1"
4+
version = "8.30.0"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
88
ArrayInterfaceCore = "30b0a656-2188-435a-8636-2ec0e6a096e2"
99
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
10+
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
1011
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
1112
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
1213
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
@@ -48,6 +49,7 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
4849
AbstractTrees = "0.3, 0.4"
4950
ArrayInterfaceCore = "0.1.1"
5051
Combinatorics = "1"
52+
Compat = "3.42, 4"
5153
ConstructionBase = "1"
5254
DataStructures = "0.17, 0.18"
5355
DiffEqBase = "6.103.0"
@@ -70,7 +72,7 @@ NonlinearSolve = "0.3.8"
7072
RecursiveArrayTools = "2.3"
7173
Reexport = "0.2, 1"
7274
RuntimeGeneratedFunctions = "0.4.3, 0.5"
73-
SciMLBase = "1.58.0"
75+
SciMLBase = "1.60.0"
7476
Setfield = "0.7, 0.8, 1"
7577
SpecialFunctions = "0.7, 0.8, 0.9, 0.10, 1.0, 2"
7678
StaticArrays = "0.10, 0.11, 0.12, 1.0"

docs/make.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
using Documenter, ModelingToolkit
22

3+
# Make sure that plots don't throw a bunch of warnings / errors!
4+
ENV["GKSwstype"] = "100"
5+
using Plots
6+
37
include("pages.jl")
48

59
mathengine = MathJax3(Dict(:loader => Dict("load" => ["[tex]/require", "[tex]/mathtools"]),

docs/src/basics/ContextualVariables.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,24 @@ Constants are like parameters that:
2828
- do not show up in the list of parameters of a system.
2929

3030
The intended use-cases for constants are:
31-
- representing literals (eg, π) symbolically, which results in cleaner
31+
- representing literals (eg, π) symbolically, which results in cleaner
3232
Latexification of equations (avoids turning `d ~ 2π*r` into `d = 6.283185307179586 r`)
33-
- allowing auto-generated unit conversion factors to live outside the list of
33+
- allowing auto-generated unit conversion factors to live outside the list of
3434
parameters
3535
- representing fundamental constants (eg, speed of light `c`) that should never
3636
be adjusted inadvertently.
3737

38+
## Wildcard Variable Arguments
39+
40+
```julia
41+
@variables u(..)
42+
```
43+
44+
It is possible to define a dependent variable which is an open function as above,
45+
for which its arguments must be specified each time it is used. This is useful with
46+
PDEs for example, where one may need to use `u(t, x)` in the equations, but will
47+
need to be able to write `u(t, 0.0)` to define a boundary condition at `x = 0`.
48+
3849
## Variable metadata [Experimental/TODO]
3950

4051
In many engineering systems some variables act like "flows" while others do not.

src/ModelingToolkit.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ $(DocStringExtensions.README)
33
"""
44
module ModelingToolkit
55
using DocStringExtensions
6+
using Compat
67
using AbstractTrees
78
using DiffEqBase, SciMLBase, ForwardDiff, Reexport
89
using SciMLBase: StandardODEProblem, StandardNonlinearProblem, handle_varmap
@@ -146,8 +147,11 @@ include("systems/sparsematrixclil.jl")
146147
include("systems/discrete_system/discrete_system.jl")
147148
include("systems/validation.jl")
148149
include("systems/dependency_graphs.jl")
150+
include("clock.jl")
151+
include("discretedomain.jl")
149152
include("systems/systemstructure.jl")
150153
using .SystemStructures
154+
include("systems/clock_inference.jl")
151155

152156
include("debugging.jl")
153157
include("systems/alias_elimination.jl")
@@ -216,4 +220,10 @@ export @variables, @parameters, @constants
216220
export @named, @nonamespace, @namespace, extend, compose, complete
217221
export debug_system
218222

223+
export Continuous, Discrete, sampletime, input_timedomain, output_timedomain
224+
#export has_discrete_domain, has_continuous_domain
225+
#export is_discrete_domain, is_continuous_domain, is_hybrid_domain
226+
export Sample, Hold, Shift, ShiftIndex
227+
export Clock #, InferredDiscrete,
228+
219229
end # module

src/clock.jl

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
abstract type TimeDomain end
2+
abstract type AbstractDiscrete <: TimeDomain end
3+
4+
Base.Broadcast.broadcastable(d::TimeDomain) = Ref(d)
5+
6+
struct Inferred <: TimeDomain end
7+
struct InferredDiscrete <: AbstractDiscrete end
8+
struct Continuous <: TimeDomain end
9+
10+
const UnknownDomain = Union{Nothing, Inferred, InferredDiscrete}
11+
const InferredDomain = Union{Inferred, InferredDiscrete}
12+
13+
Symbolics.option_to_metadata_type(::Val{:timedomain}) = TimeDomain
14+
15+
"""
16+
is_continuous_domain(x::Sym)
17+
Determine if variable `x` is a continuous-time variable.
18+
"""
19+
is_continuous_domain(x::Sym) = getmetadata(x, TimeDomain, false) isa Continuous
20+
21+
"""
22+
is_discrete_domain(x::Sym)
23+
Determine if variable `x` is a discrete-time variable.
24+
"""
25+
is_discrete_domain(x::Sym) = getmetadata(x, TimeDomain, false) isa Discrete
26+
27+
# is_discrete_domain(x::Sym) = isvarkind(Discrete, x)
28+
29+
has_continuous_domain(x::Sym) = is_continuous_domain(x)
30+
has_discrete_domain(x::Sym) = is_discrete_domain(x)
31+
32+
function get_time_domain(x)
33+
if istree(x) && operation(x) isa Operator
34+
output_timedomain(x)
35+
else
36+
getmetadata(x, TimeDomain, nothing)
37+
end
38+
end
39+
get_time_domain(x::Num) = get_time_domain(value(x))
40+
41+
"""
42+
has_time_domain(x::Sym)
43+
Determine if variable `x` has a time-domain attributed to it.
44+
"""
45+
function has_time_domain(x::Union{Sym, Term})
46+
# getmetadata(x, Continuous, nothing) !== nothing ||
47+
# getmetadata(x, Discrete, nothing) !== nothing
48+
getmetadata(x, TimeDomain, nothing) !== nothing
49+
end
50+
has_time_domain(x::Num) = has_time_domain(value(x))
51+
has_time_domain(x) = false
52+
53+
for op in [Differential, Difference]
54+
@eval input_timedomain(::$op, arg = nothing) = Continuous()
55+
@eval output_timedomain(::$op, arg = nothing) = Continuous()
56+
end
57+
58+
"""
59+
has_discrete_domain(x)
60+
true if `x` contains discrete signals (`x` may or may not contain continuous-domain signals). `x` may be an expression or equation.
61+
See also [`is_discrete_domain`](@ref)
62+
"""
63+
has_discrete_domain(x) = hasshift(x) || hassample(x) || hashold(x)
64+
65+
"""
66+
has_continuous_domain(x)
67+
true if `x` contains continuous signals (`x` may or may not contain discrete-domain signals). `x` may be an expression or equation.
68+
See also [`is_continuous_domain`](@ref)
69+
"""
70+
has_continuous_domain(x) = hasderiv(x) || hasdiff(x) || hassample(x) || hashold(x)
71+
72+
"""
73+
is_hybrid_domain(x)
74+
true if `x` contains both discrete and continuous-domain signals. `x` may be an expression or equation.
75+
"""
76+
is_hybrid_domain(x) = has_discrete_domain(x) && has_continuous_domain(x)
77+
78+
"""
79+
is_discrete_domain(x)
80+
true if `x` contains only discrete-domain signals.
81+
See also [`has_discrete_domain`](@ref)
82+
"""
83+
is_discrete_domain(x) = has_discrete_domain(x) && !has_continuous_domain(x)
84+
85+
"""
86+
is_continuous_domain(x)
87+
true if `x` contains only continuous-domain signals.
88+
See also [`has_continuous_domain`](@ref)
89+
"""
90+
is_continuous_domain(x) = !has_discrete_domain(x) && has_continuous_domain(x)
91+
92+
struct ClockInferenceException <: Exception
93+
msg::Any
94+
end
95+
96+
function Base.showerror(io::IO, cie::ClockInferenceException)
97+
print(io, "ClockInferenceException: ", cie.msg)
98+
end
99+
100+
abstract type AbstractClock <: AbstractDiscrete end
101+
102+
"""
103+
Clock <: AbstractClock
104+
Clock(t; dt)
105+
The default periodic clock with independent variables `t` and tick interval `dt`.
106+
If `dt` is left unspecified, it will be inferred (if possible).
107+
"""
108+
struct Clock <: AbstractClock
109+
"Independent variable"
110+
t::Any
111+
"Period"
112+
dt::Any
113+
Clock(t, dt = nothing) = new(value(t), dt)
114+
end
115+
116+
sampletime(c) = isdefined(c, :dt) ? c.dt : nothing

0 commit comments

Comments
 (0)