Skip to content

Commit 5ab4c57

Browse files
committed
Update docs
1 parent d829719 commit 5ab4c57

File tree

4 files changed

+155
-117
lines changed

4 files changed

+155
-117
lines changed

docs/src/systems/SDESystem.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ SDESystem
1010

1111
- `get_eqs(sys)` or `equations(sys)`: The equations that define the SDE.
1212
- `get_states(sys)` or `states(sys)`: The set of states in the SDE.
13-
- `get_ps(sys)s` or `parameters(sys)`: The parameters of the SDE.
13+
- `get_ps(sys)` or `parameters(sys)`: The parameters of the SDE.
1414
- `independent_variable(sys)`: The independent variable of the SDE.
1515

1616
## Transformations

docs/src/tutorials/acausal_components.md

+144-104
Original file line numberDiff line numberDiff line change
@@ -15,58 +15,70 @@ equalities before solving. Let's see this in action.
1515
using ModelingToolkit, Plots, DifferentialEquations
1616

1717
@parameters t
18+
@connector function Pin(;name)
19+
sts = @variables v(t)=1.0 i(t)=1.0
20+
ODESystem(Equation[], t, sts, []; name=name)
21+
end
22+
23+
function ModelingToolkit.connect(::Type{Pin}, ps...)
24+
eqs = [
25+
0 ~ sum(p->p.i, ps) # KCL
26+
]
27+
# KVL
28+
for i in 1:length(ps)-1
29+
push!(eqs, ps[i].v ~ ps[i+1].v)
30+
end
1831

19-
# Basic electric components
20-
function Pin(;name)
21-
@variables v(t) i(t)
22-
ODESystem(Equation[], t, [v, i], [], name=name, defaults=[v=>1.0, i=>1.0])
32+
return eqs
2333
end
2434

2535
function Ground(;name)
2636
@named g = Pin()
2737
eqs = [g.v ~ 0]
28-
ODESystem(eqs, t, [], [], systems=[g], name=name)
38+
ODESystem(eqs, t, [], [], systems=[g]; name=name)
2939
end
3040

31-
function Resistor(;name, R = 1.0)
32-
val = R
41+
function OnePort(;name)
3342
@named p = Pin()
3443
@named n = Pin()
35-
@variables v(t)
36-
@parameters R
44+
sts = @variables v(t)=1.0 i(t)=1.0
3745
eqs = [
3846
v ~ p.v - n.v
3947
0 ~ p.i + n.i
40-
v ~ p.i * R
48+
i ~ p.i
4149
]
42-
ODESystem(eqs, t, [v], [R], systems=[p, n], defaults=Dict(R => val), name=name)
50+
ODESystem(eqs, t, sts, [], systems=[p, n]; name=name)
4351
end
4452

45-
function Capacitor(; name, C = 1.0)
46-
val = C
47-
@named p = Pin()
48-
@named n = Pin()
49-
@variables v(t)
50-
@parameters C
53+
function Resistor(;name, R = 1.0)
54+
@named oneport = OnePort()
55+
@unpack v, i = oneport
56+
ps = @parameters R=R
57+
eqs = [
58+
v ~ i * R
59+
]
60+
extend(oneport, ODESystem(eqs, t, [], ps; name=name); name=name)
61+
end
62+
63+
function Capacitor(;name, C = 1.0)
64+
@named oneport = OnePort()
65+
@unpack v, i = oneport
66+
ps = @parameters C=C
5167
D = Differential(t)
5268
eqs = [
53-
v ~ p.v - n.v
54-
0 ~ p.i + n.i
55-
D(v) ~ p.i / C
69+
D(v) ~ i / C
5670
]
57-
ODESystem(eqs, t, [v], [C], systems=[p, n], defaults=Dict(C => val), name=name)
71+
extend(oneport, ODESystem(eqs, t, [], ps; name=name); name=name)
5872
end
5973

6074
function ConstantVoltage(;name, V = 1.0)
61-
val = V
62-
@named p = Pin()
63-
@named n = Pin()
64-
@parameters V
75+
@named oneport = OnePort()
76+
@unpack v = oneport
77+
ps = @parameters V=V
6578
eqs = [
66-
V ~ p.v - n.v
67-
0 ~ p.i + n.i
79+
V ~ v
6880
]
69-
ODESystem(eqs, t, [], [V], systems=[p, n], defaults=Dict(V => val), name=name)
81+
extend(oneport, ODESystem(eqs, t, [], ps; name=name); name=name)
7082
end
7183

7284
R = 1.0
@@ -77,22 +89,10 @@ V = 1.0
7789
@named source = ConstantVoltage(V=V)
7890
@named ground = Ground()
7991

80-
function connect_pins(ps...)
81-
eqs = [
82-
0 ~ sum(p->p.i, ps) # KCL
83-
]
84-
# KVL
85-
for i in 1:length(ps)-1
86-
push!(eqs, ps[i].v ~ ps[i+1].v)
87-
end
88-
89-
return eqs
90-
end
91-
9292
rc_eqs = [
93-
connect_pins(source.p, resistor.p)
94-
connect_pins(resistor.n, capacitor.p)
95-
connect_pins(capacitor.n, source.n, ground.g)
93+
connect(source.p, resistor.p)
94+
connect(resistor.n, capacitor.p)
95+
connect(capacitor.n, source.n, ground.g)
9696
]
9797

9898
@named rc_model = ODESystem(rc_eqs, t,
@@ -117,12 +117,12 @@ For each of our components we use a Julia function which emits an `ODESystem`.
117117
At the top we start with defining the fundamental qualities of an electrical
118118
circuit component. At every input and output pin a circuit component has
119119
two values: the current at the pin and the voltage. Thus we define the `Pin`
120-
component to simply be the values there:
120+
component (connector) to simply be the values there:
121121

122122
```julia
123-
function Pin(;name)
124-
@variables v(t) i(t)
125-
ODESystem(Equation[], t, [v, i], [], name=name, defaults=[v=>1.0, i=>1.0])
123+
@connector function Pin(;name)
124+
sts = @variables v(t)=1.0 i(t)=1.0
125+
ODESystem(Equation[], t, sts, []; name=name)
126126
end
127127
```
128128

@@ -153,7 +153,27 @@ that the voltage in such a `Pin` is equal to zero. This gives:
153153
function Ground(;name)
154154
@named g = Pin()
155155
eqs = [g.v ~ 0]
156-
ODESystem(eqs, t, [], [], systems=[g], name=name)
156+
ODESystem(eqs, t, [], [], systems=[g]; name=name)
157+
end
158+
```
159+
160+
Next we build a `OnePort`: an abstraction for all simple electrical component
161+
with two pins. The voltage difference between the positive pin and the negative
162+
pin is the voltage of the component, the current between two pins must sum to
163+
zero, and the current of the component equals to the current of the positive
164+
pin.
165+
166+
```julia
167+
function OnePort(;name)
168+
@named p = Pin()
169+
@named n = Pin()
170+
sts = @variables v(t)=1.0 i(t)=1.0
171+
eqs = [
172+
v ~ p.v - n.v
173+
0 ~ p.i + n.i
174+
i ~ p.i
175+
]
176+
ODESystem(eqs, t, sts, [], systems=[p, n]; name=name)
157177
end
158178
```
159179

@@ -166,41 +186,37 @@ zero. This leads to our resistor equations:
166186

167187
```julia
168188
function Resistor(;name, R = 1.0)
169-
val = R
170-
@named p = Pin()
171-
@named n = Pin()
172-
@variables v(t)
173-
@parameters R
189+
@named oneport = OnePort()
190+
@unpack v, i = oneport
191+
ps = @parameters R=R
174192
eqs = [
175-
v ~ p.v - n.v
176-
0 ~ p.i + n.i
177-
v ~ p.i * R
193+
v ~ i * R
178194
]
179-
ODESystem(eqs, t, [v], [R], systems=[p, n], defaults=Dict(R => val), name=name)
195+
extend(oneport, ODESystem(eqs, t, [], ps; name=name); name=name)
180196
end
181197
```
182198

183-
Notice that we have created this system with a `defaults` for the resistor's
184-
resistance. By doing so, if the resistance of this resistor is not overridden
185-
by a higher level default or overridden at `ODEProblem` construction time, this
186-
will be the value of the resistance.
199+
Notice that we have created this system with a default parameter `R` for the
200+
resistor's resistance. By doing so, if the resistance of this resistor is not
201+
overridden by a higher level default or overridden at `ODEProblem` construction
202+
time, this will be the value of the resistance. Also, note the use of `@unpack`
203+
and `extend`. For the `Resistor`, we want to simply inherit `OnePort`'s
204+
equations and states and extend them with a new equation. ModelingToolkit makes
205+
a new namespaced variable `oneport₊v(t)` when using the syntax `oneport.v`, and
206+
we can use `@unpack` avoid the namespacing.
187207

188-
Using our knowledge of circuits we similarly construct the Capacitor:
208+
Using our knowledge of circuits we similarly construct the `Capacitor`:
189209

190210
```julia
191-
function Capacitor(; name, C = 1.0)
192-
val = C
193-
@named p = Pin()
194-
@named n = Pin()
195-
@variables v(t)
196-
@parameters C
211+
function Capacitor(;name, C = 1.0)
212+
@named oneport = OnePort()
213+
@unpack v, i = oneport
214+
ps = @parameters C=C
197215
D = Differential(t)
198216
eqs = [
199-
v ~ p.v - n.v
200-
0 ~ p.i + n.i
201-
D(v) ~ p.i / C
217+
D(v) ~ i / C
202218
]
203-
ODESystem(eqs, t, [v], [C], systems=[p, n], defaults=Dict(C => val), name=name)
219+
extend(oneport, ODESystem(eqs, t, [], ps; name=name); name=name)
204220
end
205221
```
206222

@@ -211,15 +227,13 @@ model this as:
211227

212228
```julia
213229
function ConstantVoltage(;name, V = 1.0)
214-
val = V
215-
@named p = Pin()
216-
@named n = Pin()
217-
@parameters V
230+
@named oneport = OnePort()
231+
@unpack v = oneport
232+
ps = @parameters V=V
218233
eqs = [
219-
V ~ p.v - n.v
220-
0 ~ p.i + n.i
234+
V ~ v
221235
]
222-
ODESystem(eqs, t, [], [V], systems=[p, n], defaults=Dict(V => val), name=name)
236+
extend(oneport, ODESystem(eqs, t, [], ps; name=name); name=name)
223237
end
224238
```
225239

@@ -246,7 +260,7 @@ i.e. that currents sum to zero and voltages across the pins are equal. Thus
246260
we will build a helper function `connect_pins` which implements these rules:
247261

248262
```julia
249-
function connect_pins(ps...)
263+
function ModelingToolkit.connect(::Type{Pin}, ps...)
250264
eqs = [
251265
0 ~ sum(p->p.i, ps) # KCL
252266
]
@@ -266,9 +280,9 @@ the source and the ground. This would mean our connection equations are:
266280

267281
```julia
268282
rc_eqs = [
269-
connect_pins(source.p, resistor.p)
270-
connect_pins(resistor.n, capacitor.p)
271-
connect_pins(capacitor.n, source.n, ground.g)
283+
connect(source.p, resistor.p)
284+
connect(resistor.n, capacitor.p)
285+
connect(capacitor.n, source.n, ground.g)
272286
]
273287
```
274288

@@ -288,15 +302,26 @@ equations are:
288302
```julia
289303
equations(rc_model)
290304

291-
16-element Vector{Equation}:
305+
20-element Vector{Equation}:
292306
0 ~ resistor₊p₊i(t) + source₊p₊i(t)
293307
source₊p₊v(t) ~ resistor₊p₊v(t)
294308
0 ~ capacitor₊p₊i(t) + resistor₊n₊i(t)
295309
resistor₊n₊v(t) ~ capacitor₊p₊v(t)
296-
297-
Differential(t)(capacitor₊v(t)) ~ capacitor₊p₊i(t)*(capacitor₊C^-1)
298-
source₊V ~ source₊p₊v(t) - (source₊n₊v(t))
310+
0 ~ capacitor₊n₊i(t) + ground₊g₊i(t) + source₊n₊i(t)
311+
capacitor₊n₊v(t) ~ source₊n₊v(t)
312+
source₊n₊v(t) ~ ground₊g₊v(t)
313+
resistor₊v(t) ~ resistor₊p₊v(t) - resistor₊n₊v(t)
314+
0 ~ resistor₊n₊i(t) + resistor₊p₊i(t)
315+
resistor₊i(t) ~ resistor₊p₊i(t)
316+
resistor₊v(t) ~ resistor₊R*resistor₊i(t)
317+
capacitor₊v(t) ~ capacitor₊p₊v(t) - capacitor₊n₊v(t)
318+
0 ~ capacitor₊n₊i(t) + capacitor₊p₊i(t)
319+
capacitor₊i(t) ~ capacitor₊p₊i(t)
320+
Differential(t)(capacitor₊v(t)) ~ capacitor₊i(t)*(capacitor₊C^-1)
321+
source₊v(t) ~ source₊p₊v(t) - source₊n₊v(t)
299322
0 ~ source₊n₊i(t) + source₊p₊i(t)
323+
source₊i(t) ~ source₊p₊i(t)
324+
source₊V ~ source₊v(t)
300325
ground₊g₊v(t) ~ 0
301326
```
302327

@@ -305,16 +330,27 @@ the states are:
305330
```julia
306331
states(rc_model)
307332

308-
16-element Vector{Term{Real}}:
309-
resistor₊p₊i(t)
333+
20-element Vector{Term{Real, Base.ImmutableDict{DataType, Any}}}:
310334
source₊p₊i(t)
335+
resistor₊p₊i(t)
311336
source₊p₊v(t)
312337
resistor₊p₊v(t)
313-
338+
capacitor₊p₊i(t)
339+
resistor₊n₊i(t)
340+
resistor₊n₊v(t)
341+
capacitor₊p₊v(t)
342+
source₊n₊i(t)
343+
capacitor₊n₊i(t)
344+
ground₊g₊i(t)
345+
capacitor₊n₊v(t)
314346
source₊n₊v(t)
315347
ground₊g₊v(t)
316348
resistor₊v(t)
349+
resistor₊i(t)
317350
capacitor₊v(t)
351+
capacitor₊i(t)
352+
source₊v(t)
353+
source₊i(t)
318354
```
319355

320356
and the parameters are:
@@ -342,8 +378,8 @@ sys = structural_simplify(rc_model)
342378
equations(sys)
343379

344380
2-element Vector{Equation}:
345-
0 ~ capacitor₊v(t) + resistor₊R*capacitor₊p₊i(t) - source₊V
346-
Differential(t)(capacitor₊v(t)) ~ capacitor₊p₊i(t)*(capacitor₊C^-1)
381+
0 ~ capacitor₊v(t) + resistor₊R*resistor₊i(t) - source₊V
382+
Differential(t)(capacitor₊v(t)) ~ resistor₊i(t)*(capacitor₊C^-1)
347383
```
348384

349385
```julia
@@ -401,21 +437,25 @@ variables. Let's see what our observed variables are:
401437
```julia
402438
observed(sys)
403439

404-
14-element Vector{Equation}:
405-
resistor₊p₊i(t) ~ capacitor₊p₊i(t)
440+
18-element Vector{Equation}:
441+
capacitor₊i(t) ~ resistor₊i(t)
442+
ground₊g₊i(t) ~ 0.0
443+
source₊n₊i(t) ~ resistor₊i(t)
444+
source₊i(t) ~ -resistor₊i(t)
445+
source₊p₊i(t) ~ -resistor₊i(t)
446+
capacitor₊n₊i(t) ~ -resistor₊i(t)
447+
resistor₊n₊v(t) ~ capacitor₊v(t)
448+
resistor₊n₊i(t) ~ -resistor₊i(t)
449+
resistor₊p₊i(t) ~ resistor₊i(t)
450+
capacitor₊p₊i(t) ~ resistor₊i(t)
451+
capacitor₊p₊v(t) ~ capacitor₊v(t)
406452
capacitor₊n₊v(t) ~ 0.0
407453
source₊n₊v(t) ~ 0.0
408-
ground₊g₊i(t) ~ 0.0
409-
source₊n₊i(t) ~ capacitor₊p₊i(t)
410-
source₊p₊i(t) ~ -capacitor₊p₊i(t)
411-
capacitor₊n₊i(t) ~ -capacitor₊p₊i(t)
412-
resistor₊n₊i(t) ~ -capacitor₊p₊i(t)
413454
ground₊g₊v(t) ~ 0.0
414-
source₊p₊v(t) ~ source₊V
415-
capacitor₊p₊v(t) ~ capacitor₊v(t)
416-
resistor₊p₊v(t) ~ source₊p₊v(t)
417-
resistor₊n₊v(t) ~ capacitor₊p₊v(t)
418-
resistor₊v(t) ~ -((capacitor₊p₊v(t)) - (source₊p₊v(t)))
455+
source₊v(t) ~ source₊V
456+
source₊p₊v(t) ~ source₊v(t)
457+
resistor₊p₊v(t) ~ source₊v(t)
458+
resistor₊v(t) ~ source₊v(t) - capacitor₊v(t)
419459
```
420460

421461
These are explicit algebraic equations which can then be used to reconstruct

0 commit comments

Comments
 (0)