Skip to content

Commit f29213c

Browse files
Merge pull request #3526 from ven-k/vkb/system-type
MTKModel: Provision to specify the type of `System`
2 parents 0a9134e + 070659d commit f29213c

File tree

5 files changed

+69
-16
lines changed

5 files changed

+69
-16
lines changed

docs/src/basics/MTKLanguage.md

+33-6
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ equations.
1616
### [Defining components with `@mtkmodel`](@id mtkmodel)
1717

1818
`@mtkmodel` is a convenience macro to define components. It returns
19-
`ModelingToolkit.Model`, which includes a constructor that returns the ODESystem, a
20-
`structure` dictionary with metadata, and flag `isconnector` which is set to `false`.
19+
`ModelingToolkit.Model`, which includes a system constructor (`ODESystem` by
20+
default), a `structure` dictionary with metadata, and flag `isconnector` which is
21+
set to `false`.
2122

2223
### What can an MTK-Model definition have?
2324

@@ -26,7 +27,7 @@ equations.
2627
- `@description`: for describing the whole system with a human-readable string
2728
- `@components`: for listing sub-components of the system
2829
- `@constants`: for declaring constants
29-
- `@defaults`: for passing `defaults` to ODESystem
30+
- `@defaults`: for passing `defaults` to the system
3031
- `@equations`: for the list of equations
3132
- `@extend`: for extending a base system and unpacking its unknowns
3233
- `@icon` : for embedding the model icon
@@ -196,7 +197,7 @@ getdefault(model_c3.model_a.k_array[2])
196197
#### `@defaults` begin block
197198

198199
- Default values can be passed as pairs.
199-
- This is equivalent to passing `defaults` argument to `ODESystem`.
200+
- This is equivalent to passing `defaults` argument to the system.
200201

201202
#### `@continuous_events` begin block
202203

@@ -256,6 +257,32 @@ end
256257

257258
- Any other Julia operations can be included with dedicated begin blocks.
258259

260+
### Setting the type of system:
261+
262+
By default `@mtkmodel` returns an ODESystem. Different types of system can be
263+
defined with the following syntax:
264+
265+
```
266+
@mtkmodel ModelName::SystemType begin
267+
...
268+
end
269+
270+
```
271+
272+
Example:
273+
274+
```@example mtkmodel-example
275+
@mtkmodel Float2Bool::DiscreteSystem begin
276+
@variables begin
277+
u(t)::Float64
278+
y(t)::Bool
279+
end
280+
@equations begin
281+
y ~ u != 0
282+
end
283+
end
284+
```
285+
259286
## Connectors
260287

261288
Connectors are special models that can be used to connect different components together.
@@ -270,7 +297,7 @@ MTK provides 3 distinct connectors:
270297
### [Defining connectors with `@connector`](@id connector)
271298

272299
`@connector` returns `ModelingToolkit.Model`. It includes a constructor that returns
273-
a connector ODESystem, a `structure` dictionary with metadata, and flag `isconnector`
300+
a connector system (`ODESystem` by default), a `structure` dictionary with metadata, and flag `isconnector`
274301
which is set to `true`.
275302

276303
A simple connector can be defined with syntax similar to following example:
@@ -498,7 +525,7 @@ end
498525

499526
## Build structurally simplified models:
500527

501-
`@mtkbuild` builds an instance of a component and returns a structurally simplied `ODESystem`.
528+
`@mtkbuild` builds an instance of a component and returns a structurally simplied system.
502529

503530
```julia
504531
@mtkbuild sys = CustomModel()

src/systems/model_parsing.jl

+17-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ModelingToolkit component or connector with metadata
77
$(FIELDS)
88
"""
99
struct Model{F, S}
10-
"""The constructor that returns ODESystem."""
10+
"""The constructor that returns System."""
1111
f::F
1212
"""
1313
The dictionary with metadata like keyword arguments (:kwargs), base
@@ -29,8 +29,8 @@ Base.parentmodule(m::Model) = parentmodule(m.f)
2929
for f in (:connector, :mtkmodel)
3030
isconnector = f == :connector ? true : false
3131
@eval begin
32-
macro $f(name::Symbol, body)
33-
esc($(:_model_macro)(__module__, name, body, $isconnector))
32+
macro $f(fullname::Union{Expr, Symbol}, body)
33+
esc($(:_model_macro)(__module__, fullname, body, $isconnector))
3434
end
3535
end
3636
end
@@ -41,7 +41,16 @@ function flatten_equations(eqs::Vector{Union{Equation, Vector{Equation}}})
4141
foldl(flatten_equations, eqs; init = Equation[])
4242
end
4343

44-
function _model_macro(mod, name, expr, isconnector)
44+
function _model_macro(mod, fullname::Union{Expr, Symbol}, expr, isconnector)
45+
if fullname isa Symbol
46+
name, type = fullname, :System
47+
else
48+
if fullname.head == :(::)
49+
name, type = fullname.args
50+
else
51+
error("`$fullname` is not a valid name.")
52+
end
53+
end
4554
exprs = Expr(:block)
4655
dict = Dict{Symbol, Any}(
4756
:constants => Dict{Symbol, Dict}(),
@@ -61,7 +70,9 @@ function _model_macro(mod, name, expr, isconnector)
6170

6271
push!(exprs.args, :(variables = []))
6372
push!(exprs.args, :(parameters = []))
64-
push!(exprs.args, :(systems = ODESystem[]))
73+
# We build `System` by default; vectors can't be created for `System` as it is
74+
# a function.
75+
push!(exprs.args, :(systems = ModelingToolkit.AbstractSystem[]))
6576
push!(exprs.args, :(equations = Union{Equation, Vector{Equation}}[]))
6677
push!(exprs.args, :(defaults = Dict{Num, Union{Number, Symbol, Function}}()))
6778

@@ -114,7 +125,7 @@ function _model_macro(mod, name, expr, isconnector)
114125
@inline pop_structure_dict!.(
115126
Ref(dict), [:constants, :defaults, :kwargs, :structural_parameters])
116127

117-
sys = :($ODESystem($(flatten_equations)(equations), $iv, variables, parameters;
128+
sys = :($type($(flatten_equations)(equations), $iv, variables, parameters;
118129
name, description = $description, systems, gui_metadata = $gui_metadata, defaults))
119130

120131
if length(ext) == 0

test/initializationsystem.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ end
216216
end
217217
end
218218

219-
@mtkmodel System begin
219+
@mtkmodel HydraulicSystem begin
220220
@components begin
221221
res₁ = Orifice(p′ = 300e5)
222222
res₂ = Orifice(p′ = 0)
@@ -234,7 +234,7 @@ end
234234
end
235235
end
236236

237-
@mtkbuild sys = System()
237+
@mtkbuild sys = HydraulicSystem()
238238
initprob = ModelingToolkit.InitializationProblem(sys, 0.0)
239239
conditions = getfield.(equations(initprob.f.sys), :rhs)
240240

test/model_parsing.jl

+15
Original file line numberDiff line numberDiff line change
@@ -1011,3 +1011,18 @@ end
10111011
@test any(isequal(u), vars)
10121012
end
10131013
end
1014+
1015+
@testset "Specify the type of system" begin
1016+
@mtkmodel Float2Bool::DiscreteSystem begin
1017+
@variables begin
1018+
u(t)::Float64
1019+
y(t)::Bool
1020+
end
1021+
@equations begin
1022+
y ~ u != 0
1023+
end
1024+
end
1025+
1026+
@named sys = Float2Bool()
1027+
@test typeof(sys) == DiscreteSystem
1028+
end

test/split_parameters.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ end
285285
end
286286
end
287287

288-
@mtkmodel System begin
288+
@mtkmodel ApexSystem begin
289289
@components begin
290290
subsys = SubSystem()
291291
end
@@ -300,7 +300,7 @@ end
300300
end
301301
end
302302

303-
@named sys = System()
303+
@named sys = ApexSystem()
304304
sysref = complete(sys)
305305
sys2 = complete(sys; split = true, flatten = false)
306306
ps = Set(full_parameters(sys2))

0 commit comments

Comments
 (0)