-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathutils.jl
146 lines (123 loc) · 4.19 KB
/
utils.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
@connector function RealInput(; name, nin = 1, u_start = nin > 1 ? zeros(nin) : 0.0)
if nin == 1
@variables u(t)=u_start [
input = true,
description = "Inner variable in RealInput $name",
]
else
@variables u(t)[1:nin]=u_start [
input = true,
description = "Inner variable in RealInput $name",
]
u = collect(u)
end
ODESystem(Equation[], t, [u...], []; name = name)
end
@doc """
RealInput(;name, nin, u_start)
Connector with one input signal of type Real.
# Parameters:
- `nin=1`: Number of inputs
- `u_start=0`: Initial value for `u`
# States:
- `u`: Value of the connector; if nin=1 this is a scalar
""" RealInput
@connector function RealOutput(; name, nout = 1, u_start = nout > 1 ? zeros(nout) : 0.0)
if nout == 1
@variables u(t)=u_start [
output = true,
description = "Inner variable in RealOutput $name",
]
else
@variables u(t)[1:nout]=u_start [
output = true,
description = "Inner variable in RealOutput $name",
]
u = collect(u)
end
ODESystem(Equation[], t, [u...], []; name = name)
end
@doc """
RealOutput(;name, nout, u_start)
Connector with one output signal of type Real.
# Parameters:
- `nout=1`: Number of inputs
- `u_start=0`: Initial value for `u`
# States:
- `u`: Value of the connector; if nout=1 this is a scalar
""" RealOutput
"""
SISO(;name, u_start = 0.0, y_start = 0.0)
Single input single output (SISO) continuous system block.
# Parameters:
- `u`: Initial value for the input
- `y`: Initial value for the output
"""
@mtkmodel SISO begin
@parameters begin
u_start = 0.0
y_start = 0.0
end
@variables begin
u(t) = u_start, [description = "Input of SISO system"]
y(t) = y_start, [description = "Output of SISO system"]
end
@components begin
input = RealInput(u_start = u_start)
output = RealOutput(u_start = y_start)
end
@equations begin
u ~ input.u
y ~ output.u
end
end
"""
MIMO(; name, nin = 1, nout = 1, u_start = zeros(nin), y_start = zeros(nout))
Base class for a multiple input multiple output (MIMO) continuous system block.
# Parameters:
- `nin`: Input dimension
- `nout`: Output dimension
- `u_start`: Initial value for the input
- `y_start`: Initial value for the output
"""
@component function MIMO(; name, nin = 1, nout = 1, u_start = zeros(nin),
y_start = zeros(nout))
@named input = RealInput(nin = nin, u_start = u_start)
@named output = RealOutput(nout = nout, u_start = y_start)
@variables(u(t)[1:nin]=u_start, [description = "Input of MIMO system $name"],
y(t)[1:nout]=y_start, [description = "Output of MIMO system $name"],)
eqs = [
[u[i] ~ input.u[i] for i in 1:nin]...,
[y[i] ~ output.u[i] for i in 1:nout]...,
]
return ODESystem(eqs, t, vcat(u..., y...), []; name = name, systems = [input, output])
end
using Symbolics: Struct, symbolic_getproperty
@connector function StructInput(; structdef, name)
@variables u(t)::Struct [input = true] # Dummy default value due to bug in Symbolics
ODESystem(Equation[], t, [u], []; name)
end
@connector function StructOutput(; structdef, name)
@variables u(t)::Struct [output = true] # Dummy default value due to bug in Symbolics
ODESystem(Equation[], t, [u], []; name)
end
function _structelem2connector(elem::StructElement)
T = Symbolics.decodetyp(elem.typ)
if T <: Bool
return BoolOutput(; name = elem.name)
elseif T <: Real
return RealOutput(; name = elem.name)
end
end
@component function BusSelect(;name, structdef, selected_fields)
@parameters t
nout = length(selected_fields)
inputbus = Blocks.StructInput(; structdef, name = Symbol("inputbus"))
@variables input(t)
output_elements = filter(e->e.name in selected_fields, getelements(structdef))
output_connectors = map(_structelem2connector, output_elements)
eqs = [
symbolic_getproperty(inputbus.u, field) ~ con.u for (field, con) in zip(selected_fields, output_connectors)
]
return ODESystem(eqs, t; name = name, systems = [inputbus; output_connectors])
end