Skip to content

Commit 31114a0

Browse files
Merge pull request #313 from ven-k/vkb/tutorials-with-mtkmodel
Refactor all tutorials with `@mtkmodel` and `@mtkbuild`
2 parents 7e3f5b8 + 802c415 commit 31114a0

File tree

4 files changed

+98
-87
lines changed

4 files changed

+98
-87
lines changed

docs/src/tutorials/custom_component.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,14 @@ Since the initial voltage of the capacitors was already specified via `v` and th
114114

115115
```@example components
116116
@mtkbuild sys = ChaoticAttractor()
117-
prob = ODEProblem(sys, Pair[], (0, 5e4), saveat = 0.01)
118-
sol = solve(prob)
117+
prob = ODEProblem(sys, Pair[], (0, 5e4))
118+
sol = solve(prob; saveat = 1.0)
119119
120-
plot(sol[capacitor1.v], sol[capacitor2.v], title = "Chaotic Attractor", label = "",
120+
plot(sol[sys.capacitor1.v], sol[sys.capacitor2.v], title = "Chaotic Attractor", label = "",
121121
ylabel = "C1 Voltage in V", xlabel = "C2 Voltage in V")
122122
```
123123

124124
```@example components
125-
plot(sol; idxs = [capacitor1.v, capacitor2.v, inductor.i],
125+
plot(sol; idxs = [sys.capacitor1.v, sys.capacitor2.v, sys.inductor.i],
126126
labels = ["C1 Voltage in V" "C2 Voltage in V" "Inductor Current in A"])
127127
```

docs/src/tutorials/dc_motor_pi.md

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,54 @@ using ModelingToolkitStandardLibrary.Mechanical.Rotational
2020
using ModelingToolkitStandardLibrary.Blocks
2121
using OrdinaryDiffEq
2222
using Plots
23-
24-
R = 0.5 # [Ohm] armature resistance
25-
L = 4.5e-3 # [H] armature inductance
26-
k = 0.5 # [N.m/A] motor constant
27-
J = 0.02 # [kg.m²] inertia
28-
f = 0.01 # [N.m.s/rad] friction factor
29-
tau_L_step = -0.3 # [N.m] amplitude of the load torque step
30-
nothing # hide
3123
```
3224

3325
The actual model can now be composed.
3426

3527
```@example dc_motor_pi
36-
systems = @named begin
37-
ground = Ground()
38-
source = Voltage()
39-
ref = Blocks.Step(height = 1, start_time = 0)
40-
pi_controller = Blocks.LimPI(k = 1.1, T = 0.035, u_max = 10, Ta = 0.035)
41-
feedback = Blocks.Feedback()
42-
R1 = Resistor(R = R)
43-
L1 = Inductor(L = L)
44-
emf = EMF(k = k)
45-
fixed = Fixed()
46-
load = Torque()
47-
load_step = Blocks.Step(height = tau_L_step, start_time = 3)
48-
inertia = Inertia(J = J)
49-
friction = Damper(d = f)
50-
speed_sensor = SpeedSensor()
28+
@mtkmodel DCMotor begin
29+
@parameters begin
30+
R = 0.5, [description = "Armature resistance"] # Ohm
31+
L = 4.5e-3, [description = "Armature inductance"] # H
32+
k = 0.5, [description = "Motor constant"] # N.m/A
33+
J = 0.02, [description = "Inertia"] # kg.m²
34+
f = 0.01, [description = "Friction factor"] # N.m.s/rad
35+
tau_L_step = -0.3, [description = "Amplitude of the load torque step"] # N.m
36+
end
37+
@components begin
38+
ground = Ground()
39+
source = Voltage()
40+
ref = Blocks.Step(height = 1, start_time = 0)
41+
pi_controller = Blocks.LimPI(k = 1.1, T = 0.035, u_max = 10, Ta = 0.035)
42+
feedback = Blocks.Feedback()
43+
R1 = Resistor(R = R)
44+
L1 = Inductor(L = L)
45+
emf = EMF(k = k)
46+
fixed = Fixed()
47+
load = Torque()
48+
load_step = Blocks.Step(height = tau_L_step, start_time = 3)
49+
inertia = Inertia(J = J)
50+
friction = Damper(d = f)
51+
speed_sensor = SpeedSensor()
52+
end
53+
@equations begin
54+
connect(fixed.flange, emf.support, friction.flange_b)
55+
connect(emf.flange, friction.flange_a, inertia.flange_a)
56+
connect(inertia.flange_b, load.flange)
57+
connect(inertia.flange_b, speed_sensor.flange)
58+
connect(load_step.output, load.tau)
59+
connect(ref.output, feedback.input1)
60+
connect(speed_sensor.w, :y, feedback.input2)
61+
connect(feedback.output, pi_controller.err_input)
62+
connect(pi_controller.ctr_output, :u, source.V)
63+
connect(source.p, R1.p)
64+
connect(R1.n, L1.p)
65+
connect(L1.n, emf.p)
66+
connect(emf.n, source.n, ground.g)
67+
end
5168
end
5269
53-
connections = [connect(fixed.flange, emf.support, friction.flange_b)
54-
connect(emf.flange, friction.flange_a, inertia.flange_a)
55-
connect(inertia.flange_b, load.flange)
56-
connect(inertia.flange_b, speed_sensor.flange)
57-
connect(load_step.output, load.tau)
58-
connect(ref.output, feedback.input1)
59-
connect(speed_sensor.w, :y, feedback.input2)
60-
connect(feedback.output, pi_controller.err_input)
61-
connect(pi_controller.ctr_output, :u, source.V)
62-
connect(source.p, R1.p)
63-
connect(R1.n, L1.p)
64-
connect(L1.n, emf.p)
65-
connect(emf.n, source.n, ground.g)]
66-
67-
@named model = ODESystem(connections, t; systems)
70+
@named model = DCMotor()
6871
nothing # hide
6972
```
7073

@@ -75,12 +78,12 @@ so that it can be represented as a system of `ODEs` (ordinary differential equat
7578
```@example dc_motor_pi
7679
sys = structural_simplify(model)
7780
prob = ODEProblem(sys, unknowns(sys) .=> 0.0, (0, 6.0))
78-
sol = solve(prob, Rodas4())
81+
sol = solve(prob)
7982
80-
p1 = plot(sol.t, sol[inertia.w], ylabel = "Angular Vel. in rad/s",
83+
p1 = plot(sol.t, sol[sys.inertia.w], ylabel = "Angular Vel. in rad/s",
8184
label = "Measurement", title = "DC Motor with Speed Controller")
82-
plot!(sol.t, sol[ref.output.u], label = "Reference")
83-
p2 = plot(sol.t, sol[load.tau.u], ylabel = "Disturbance in Nm", label = "")
85+
plot!(sol.t, sol[sys.ref.output.u], label = "Reference")
86+
p2 = plot(sol.t, sol[sys.load.tau.u], ylabel = "Disturbance in Nm", label = "")
8487
plot(p1, p2, layout = (2, 1))
8588
```
8689

@@ -89,8 +92,8 @@ plot(p1, p2, layout = (2, 1))
8992
When implementing and tuning a control system in simulation, it is a good practice to analyze the closed-loop properties and verify robustness of the closed-loop with respect to, e.g., modeling errors. To facilitate this, we added two analysis points to the set of connections above, more specifically, we added the analysis points named `:y` and `:u` to the connections (for more details on analysis points, see [Linear Analysis](@ref))
9093

9194
```julia
92-
connect(speed_sensor.w, :y, feedback.input2)
93-
connect(pi_controller.ctr_output, :u, source.V)
95+
connect(sys.speed_sensor.w, :y, feedback.input2)
96+
connect(sys.pi_controller.ctr_output, :u, source.V)
9497
```
9598

9699
one at the plant output (`:y`) and one at the plant input (`:u`). We may use these analysis points to calculate, e.g., sensitivity functions, illustrated below. Here, we calculate the sensitivity function $S(s)$ and the complimentary sensitivity function $T(s) = I - S(s)$, defined as
@@ -108,7 +111,7 @@ matrices_S, simplified_sys = Blocks.get_sensitivity(
108111
model, :y, op = Dict(unknowns(sys) .=> 0.0))
109112
So = ss(matrices_S...) |> minreal # The output-sensitivity function as a StateSpace system
110113
matrices_T, simplified_sys = Blocks.get_comp_sensitivity(
111-
model, :y, op = Dict(inertia.phi => 0.0, inertia.w => 0.0))
114+
model, :y, op = Dict(model.inertia.phi => 0.0, model.inertia.w => 0.0))
112115
To = ss(matrices_T...)# The output complementary sensitivity function as a StateSpace system
113116
bodeplot([So, To], label = ["S" "T"], plot_title = "Sensitivity functions",
114117
plotphase = false)

docs/src/tutorials/rc_circuit.md

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,32 @@ using ModelingToolkitStandardLibrary.Electrical
1212
using ModelingToolkitStandardLibrary.Blocks: Constant
1313
using ModelingToolkit: t_nounits as t
1414
15-
R = 1.0
16-
C = 1.0
17-
V = 1.0
18-
systems = @named begin
19-
resistor = Resistor(R = R)
20-
capacitor = Capacitor(C = C, v = 0.0)
21-
source = Voltage()
22-
constant = Constant(k = V)
23-
ground = Ground()
15+
@mtkmodel RC begin
16+
@parameters begin
17+
R = 1.0
18+
C = 1.0
19+
V = 1.0
20+
end
21+
@components begin
22+
resistor = Resistor(R = R)
23+
capacitor = Capacitor(C = C, v = 0.0)
24+
source = Voltage()
25+
constant = Constant(k = V)
26+
ground = Ground()
27+
end
28+
@equations begin
29+
connect(constant.output, source.V)
30+
connect(source.p, resistor.p)
31+
connect(resistor.n, capacitor.p)
32+
connect(capacitor.n, source.n, ground.g)
33+
end
2434
end
2535
26-
rc_eqs = [connect(constant.output, source.V)
27-
connect(source.p, resistor.p)
28-
connect(resistor.n, capacitor.p)
29-
connect(capacitor.n, source.n, ground.g)]
30-
31-
@named rc_model = ODESystem(rc_eqs, t; systems)
32-
sys = structural_simplify(rc_model)
36+
@mtkbuild sys = RC()
3337
prob = ODEProblem(sys, Pair[], (0, 10.0))
34-
sol = solve(prob, Tsit5())
35-
plot(sol, idxs = [capacitor.v, resistor.i],
38+
sol = solve(prob)
39+
40+
plot(sol, idxs = [sys.capacitor.v, sys.resistor.i],
3641
title = "RC Circuit Demonstration",
3742
labels = ["Capacitor Voltage" "Resistor Current"])
3843
```

docs/src/tutorials/thermal_model.md

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,34 @@ from dividing the total initial energy in the system by the sum of the heat capa
1010
using ModelingToolkitStandardLibrary.Thermal, ModelingToolkit, OrdinaryDiffEq, Plots
1111
using ModelingToolkit: t_nounits as t
1212
13-
C1 = 15
14-
C2 = 15
15-
systems = @named begin
16-
mass1 = HeatCapacitor(C = C1, T = 373.15)
17-
mass2 = HeatCapacitor(C = C2, T = 273.15)
18-
conduction = ThermalConductor(G = 10)
19-
Tsensor1 = TemperatureSensor()
20-
Tsensor2 = TemperatureSensor()
13+
@mtkmodel HeatConductionModel begin
14+
@parameters begin
15+
C1 = 15
16+
C2 = 15
17+
end
18+
@components begin
19+
mass1 = HeatCapacitor(C = C1, T = 373.15)
20+
mass2 = HeatCapacitor(C = C2, T = 273.15)
21+
conduction = ThermalConductor(G = 10)
22+
Tsensor1 = TemperatureSensor()
23+
Tsensor2 = TemperatureSensor()
24+
end
25+
@equations begin
26+
connect(mass1.port, conduction.port_a)
27+
connect(conduction.port_b, mass2.port)
28+
connect(mass1.port, Tsensor1.port)
29+
connect(mass2.port, Tsensor2.port)
30+
end
2131
end
2232
23-
connections = [
24-
connect(mass1.port, conduction.port_a),
25-
connect(conduction.port_b, mass2.port),
26-
connect(mass1.port, Tsensor1.port),
27-
connect(mass2.port, Tsensor2.port)
28-
]
29-
30-
@named model = ODESystem(connections, t; systems)
31-
sys = structural_simplify(model)
33+
@mtkbuild sys = HeatConductionModel()
3234
prob = ODEProblem(sys, Pair[], (0, 5.0))
33-
sol = solve(prob, Tsit5())
35+
sol = solve(prob)
3436
35-
T_final_K = sol[(mass1.T * C1 + mass2.T * C2) / (C1 + C2)]
37+
T_final_K = sol[(sys.mass1.T * sys.C1 + sys.mass2.T * sys.C2) / (sys.C1 + sys.C2)]
3638
3739
plot(title = "Thermal Conduction Demonstration")
38-
plot!(sol, idxs = [mass1.T, mass2.T], labels = ["Mass 1 Temperature" "Mass 2 Temperature"])
40+
plot!(sol, idxs = [sys.mass1.T, sys.mass2.T],
41+
labels = ["Mass 1 Temperature" "Mass 2 Temperature"])
3942
plot!(sol.t, T_final_K, label = "Steady-State Temperature")
4043
```

0 commit comments

Comments
 (0)