Skip to content

Commit 4c1b1ae

Browse files
committed
Merge branch 'master' into id-tutorial
2 parents 33d5c7f + 72a3978 commit 4c1b1ae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2884
-1485
lines changed

.github/workflows/Downstream.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@ on:
77

88
jobs:
99
test:
10-
name: ${{ matrix.package.repo }}/${{ matrix.package.group }}
10+
name: ${{ matrix.package.repo }}/${{ matrix.package.group }}/${{ matrix.julia-version }}
1111
runs-on: ${{ matrix.os }}
1212
env:
1313
GROUP: ${{ matrix.package.group }}
1414
strategy:
1515
fail-fast: false
1616
matrix:
17-
julia-version: [1]
17+
julia-version: [1,1.6]
1818
os: [ubuntu-latest]
1919
package:
20+
- {user: SciML, repo: SciMLBase.jl, group: Downstream}
2021
- {user: SciML, repo: Catalyst.jl, group: All}
2122
- {user: SciML, repo: CellMLToolkit.jl, group: All}
2223
- {user: SciML, repo: SBMLToolkit.jl, group: All}
2324
- {user: SciML, repo: NeuralPDE.jl, group: NNPDE}
2425
- {user: SciML, repo: DataDrivenDiffEq.jl, group: Standard}
2526
- {user: SciML, repo: StructuralIdentifiability.jl, group: All}
26-
27+
- {user: SciML, repo: ModelingToolkitStandardLibrary.jl}
2728
steps:
2829
- uses: actions/checkout@v2
2930
- uses: julia-actions/setup-julia@v1

.github/workflows/ci.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,18 @@ on:
99
jobs:
1010
test:
1111
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
group:
15+
- All
16+
version:
17+
- '1'
18+
- '1.6'
1219
steps:
1320
- uses: actions/checkout@v2
1421
- uses: julia-actions/setup-julia@v1
1522
with:
16-
version: 1
23+
version: ${{ matrix.version }}
1724
- uses: actions/cache@v1
1825
env:
1926
cache-name: cache-artifacts

NEWS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# ModelingToolkit v8 Release Notes
2+
3+
4+
### Upgrade guide
5+
6+
- `connect` should not be overloaded by users anymore. `[connect = Flow]`
7+
informs ModelingToolkit that particular variable in a connector ought to sum
8+
to zero, and by default, variables are equal in a connection. Please check out
9+
[acausal components tutorial](https://mtk.sciml.ai/dev/tutorials/acausal_components/)
10+
for examples.

Project.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ModelingToolkit"
22
uuid = "961ee093-0014-501f-94e3-6117800e7a78"
33
authors = ["Chris Rackauckas <[email protected]>"]
4-
version = "7.0.0"
4+
version = "8.3.1"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
@@ -45,19 +45,19 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
4545

4646
[compat]
4747
AbstractTrees = "0.3"
48-
ArrayInterface = "3.1.39"
48+
ArrayInterface = "3.1.39, 4"
4949
ConstructionBase = "1"
5050
DataStructures = "0.17, 0.18"
51-
DiffEqBase = "6.54.0"
51+
DiffEqBase = "6.81.0"
5252
DiffEqCallbacks = "2.16"
53-
DiffEqJump = "7.0"
53+
DiffEqJump = "7.0, 8"
5454
DiffRules = "0.1, 1.0"
5555
Distributions = "0.23, 0.24, 0.25"
5656
DocStringExtensions = "0.7, 0.8"
5757
DomainSets = "0.5"
5858
Graphs = "1.4"
5959
IfElse = "0.1"
60-
JuliaFormatter = "0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18"
60+
JuliaFormatter = "0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21"
6161
LabelledArrays = "1.3"
6262
Latexify = "0.11, 0.12, 0.13, 0.14, 0.15"
6363
MacroTools = "0.5"
@@ -70,13 +70,13 @@ RuntimeGeneratedFunctions = "0.4.3, 0.5"
7070
SafeTestsets = "0.0.1"
7171
SciMLBase = "1.3"
7272
Setfield = "0.7, 0.8"
73-
SpecialFunctions = "0.7, 0.8, 0.9, 0.10, 1.0"
73+
SpecialFunctions = "0.7, 0.8, 0.9, 0.10, 1.0, 2"
7474
StaticArrays = "0.10, 0.11, 0.12, 1.0"
75-
SymbolicUtils = "0.18"
75+
SymbolicUtils = "0.18, 0.19"
7676
Symbolics = "4.0.0"
7777
UnPack = "0.1, 1.0"
7878
Unitful = "1.1"
79-
julia = "1.2"
79+
julia = "1.6"
8080

8181
[extras]
8282
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"

docs/src/basics/Composition.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,17 @@ before numerically solving. The `structural_simplify` function removes
167167
these trivial equality relationships and trivial singularity equations,
168168
i.e. equations which result in `0~0` expressions, in over-specified systems.
169169

170-
## Inheritance and Combine (TODO)
170+
## Inheritance and Combine
171171

172-
Model inheritance can be done in two ways: explicitly or implicitly.
173-
The explicit way is to shadow variables with equality expressions.
174-
For example, let's assume we have three separate systems which we
175-
want to compose to a single one. This is how one could explicitly
176-
forward all states and parameters to the higher level system:
172+
Model inheritance can be done in two ways: implicitly or explicitly. First, one
173+
can use the `extend` function to extend a base model with another set of
174+
equations, states, and parameters. An example can be found in the
175+
[acausal components tutorial](@ref acausal).
176+
177+
The explicit way is to shadow variables with equality expressions. For example,
178+
let's assume we have three separate systems which we want to compose to a single
179+
one. This is how one could explicitly forward all states and parameters to the
180+
higher level system:
177181

178182
```julia
179183
using ModelingToolkit, OrdinaryDiffEq, Plots
@@ -259,7 +263,7 @@ ODESystem(eqs, ...; continuous_events::Pair{Vector{Equation}, Vector{Equation}})
259263
```
260264
where equations can be added that evaluate to 0 at discontinuities.
261265

262-
To model events that have an affect on the state, provide `events::Pair{Vector{Equation}, Vector{Equation}}` where the first entry in the pair is a vector of equations describing event conditions, and the second vector of equations describe the affect on the state. The affect equations must be on the form
266+
To model events that have an effect on the state, provide `events::Pair{Vector{Equation}, Vector{Equation}}` where the first entry in the pair is a vector of equations describing event conditions, and the second vector of equations describe the effect on the state. The effect equations must be of the form
263267
```
264268
single_state_variable ~ expression_involving_any_variables
265269
```
@@ -275,7 +279,7 @@ function UnitMassWithFriction(k; name)
275279
D(x) ~ v
276280
D(v) ~ sin(t) - k*sign(v) # f = ma, sinusoidal force acting on the mass, and Coulomb friction opposing the movement
277281
]
278-
ODESystem(eqs, t, continuous_events=[v ~ 0], name=name) # when v = 0 there is a discontinuity
282+
ODESystem(eqs, t; continuous_events=[v ~ 0], name) # when v = 0 there is a discontinuity
279283
end
280284
@named m = UnitMassWithFriction(0.7)
281285
prob = ODEProblem(m, Pair[], (0, 10pi))
@@ -296,7 +300,7 @@ affect = [v ~ -v] # the effect is that the velocity changes sign
296300
@named ball = ODESystem([
297301
D(x) ~ v
298302
D(v) ~ -9.8
299-
], t, continuous_events = root_eqs => affect) # equation => affect
303+
], t; continuous_events = root_eqs => affect) # equation => affect
300304

301305
ball = structural_simplify(ball)
302306

@@ -323,7 +327,7 @@ continuous_events = [ # This time we have a vector of pairs
323327
D(y) ~ vy,
324328
D(vx) ~ -9.8-0.1vx, # gravity + some small air resistance
325329
D(vy) ~ -0.1vy,
326-
], t, continuous_events = continuous_events)
330+
], t; continuous_events)
327331

328332

329333
ball = structural_simplify(ball)
@@ -340,4 +344,4 @@ tv = sort([LinRange(0, 10, 200); sol.t])
340344
plot(sol(tv)[y], sol(tv)[x], line_z=tv)
341345
vline!([-1.5, 1.5], l=(:black, 5), primary=false)
342346
hline!([0], l=(:black, 5), primary=false)
343-
```
347+
```

docs/src/mtkitize_tutorials/modelingtoolkitize.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,5 @@ sys = modelingtoolkitize(prob)
2727
Using this, we can symbolically build the Jacobian and then rebuild the ODEProblem:
2828

2929
```julia
30-
jac = eval(ModelingToolkit.generate_jacobian(sys)[2])
31-
f = ODEFunction(rober, jac=jac)
32-
prob_jac = ODEProblem(f,[1.0,0.0,0.0],(0.0,1e5),(0.04,3e7,1e4))
30+
prob_jac = ODEProblem(sys,[],(0.0,1e5),jac=true)
3331
```

docs/src/systems/NonlinearSystem.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ tearing
2323
## Analyses
2424

2525
```@docs
26+
ModelingToolkit.isaffine
2627
ModelingToolkit.islinear
2728
```
2829

docs/src/systems/ODESystem.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ tearing
2929
```@docs
3030
ModelingToolkit.islinear
3131
ModelingToolkit.isautonomous
32+
ModelingToolkit.isaffine
3233
```
3334

3435
## Applicable Calculation and Generation Functions

docs/src/tutorials/acausal_components.md

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,10 @@ using ModelingToolkit, Plots, DifferentialEquations
1616

1717
@variables t
1818
@connector function Pin(;name)
19-
sts = @variables v(t)=1.0 i(t)=1.0
19+
sts = @variables v(t)=1.0 i(t)=1.0 [connect = Flow]
2020
ODESystem(Equation[], t, sts, []; name=name)
2121
end
2222

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
31-
32-
return eqs
33-
end
34-
3523
function Ground(;name)
3624
@named g = Pin()
3725
eqs = [g.v ~ 0]
@@ -92,7 +80,8 @@ V = 1.0
9280
rc_eqs = [
9381
connect(source.p, resistor.p)
9482
connect(resistor.n, capacitor.p)
95-
connect(capacitor.n, source.n, ground.g)
83+
connect(capacitor.n, source.n)
84+
connect(capacitor.n, ground.g)
9685
]
9786

9887
@named _rc_model = ODESystem(rc_eqs, t)
@@ -117,11 +106,15 @@ For each of our components we use a Julia function which emits an `ODESystem`.
117106
At the top we start with defining the fundamental qualities of an electrical
118107
circuit component. At every input and output pin a circuit component has
119108
two values: the current at the pin and the voltage. Thus we define the `Pin`
120-
component (connector) to simply be the values there:
109+
component (connector) to simply be the values there. Whenever two `Pin`s in a
110+
circuit are connected together, the system satisfies [Kirchoff's laws](https: //en.wikipedia.org/wiki/Kirchhoff%27s_circuit_laws),
111+
i.e. that currents sum to zero and voltages across the pins are equal.
112+
`[connect = Flow]` informs MTK that currents ought to sum to zero, and by
113+
default, variables are equal in a connection.
121114

122115
```julia
123116
@connector function Pin(;name)
124-
sts = @variables v(t)=1.0 i(t)=1.0
117+
sts = @variables v(t)=1.0 i(t)=1.0 [connect = Flow]
125118
ODESystem(Equation[], t, sts, []; name=name)
126119
end
127120
```
@@ -253,26 +246,6 @@ V = 1.0
253246
@named ground = Ground()
254247
```
255248

256-
Next we have to define how we connect the circuit. Whenever two `Pin`s in a
257-
circuit are connected together, the system satisfies
258-
[Kirchoff's laws](https://en.wikipedia.org/wiki/Kirchhoff%27s_circuit_laws),
259-
i.e. that currents sum to zero and voltages across the pins are equal. Thus
260-
we will build a helper function `connect_pins` which implements these rules:
261-
262-
```julia
263-
function ModelingToolkit.connect(::Type{Pin}, ps...)
264-
eqs = [
265-
0 ~ sum(p->p.i, ps) # KCL
266-
]
267-
# KVL
268-
for i in 1:length(ps)-1
269-
push!(eqs, ps[i].v ~ ps[i+1].v)
270-
end
271-
272-
return eqs
273-
end
274-
```
275-
276249
Finally we will connect the pieces of our circuit together. Let's connect the
277250
positive pin of the resistor to the source, the negative pin of the resistor
278251
to the capacitor, and the negative pin of the capacitor to a junction between
@@ -282,7 +255,8 @@ the source and the ground. This would mean our connection equations are:
282255
rc_eqs = [
283256
connect(source.p, resistor.p)
284257
connect(resistor.n, capacitor.p)
285-
connect(capacitor.n, source.n, ground.g)
258+
connect(capacitor.n, source.n)
259+
connect(capacitor.n, ground.g)
286260
]
287261
```
288262

docs/src/tutorials/spring_mass.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ In this tutorial we will build a simple component-based model of a spring-mass s
66

77
```julia
88
using ModelingToolkit, Plots, DifferentialEquations, LinearAlgebra
9+
using Symbolics: scalarize
910

1011
@variables t
1112
D = Differential(t)
1213

1314
function Mass(; name, m = 1.0, xy = [0., 0.], u = [0., 0.])
1415
ps = @parameters m=m
1516
sts = @variables pos[1:2](t)=xy v[1:2](t)=u
16-
eqs = collect(D.(pos) .~ v)
17+
eqs = scalarize(D.(pos) .~ v)
1718
ODESystem(eqs, t, [pos..., v...], ps; name)
1819
end
1920

@@ -25,12 +26,12 @@ end
2526

2627
function connect_spring(spring, a, b)
2728
[
28-
spring.x ~ norm(collect(a .- b))
29-
collect(spring.dir .~ collect(a .- b))
29+
spring.x ~ norm(scalarize(a .- b))
30+
scalarize(spring.dir .~ scalarize(a .- b))
3031
]
3132
end
3233

33-
spring_force(spring) = -spring.k .* collect(spring.dir) .* (spring.x - spring.l) ./ spring.x
34+
spring_force(spring) = -spring.k .* scalarize(spring.dir) .* (spring.x - spring.l) ./ spring.x
3435

3536
m = 1.0
3637
xy = [1., -1.]
@@ -43,7 +44,7 @@ g = [0., -9.81]
4344

4445
eqs = [
4546
connect_spring(spring, mass.pos, center)
46-
collect(D.(mass.v) .~ spring_force(spring) / mass.m .+ g)
47+
scalarize(D.(mass.v) .~ spring_force(spring) / mass.m .+ g)
4748
]
4849

4950
@named _model = ODESystem(eqs, t)
@@ -65,7 +66,7 @@ For each component we use a Julia function that returns an `ODESystem`. At the t
6566
function Mass(; name, m = 1.0, xy = [0., 0.], u = [0., 0.])
6667
ps = @parameters m=m
6768
sts = @variables pos[1:2](t)=xy v[1:2](t)=u
68-
eqs = collect(D.(pos) .~ v)
69+
eqs = scalarize(D.(pos) .~ v)
6970
ODESystem(eqs, t, [pos..., v...], ps; name)
7071
end
7172
```
@@ -97,16 +98,16 @@ We now define functions that help construct the equations for a mass-spring syst
9798
```julia
9899
function connect_spring(spring, a, b)
99100
[
100-
spring.x ~ norm(collect(a .- b))
101-
collect(spring.dir .~ collect(a .- b))
101+
spring.x ~ norm(scalarize(a .- b))
102+
scalarize(spring.dir .~ scalarize(a .- b))
102103
]
103104
end
104105
```
105106

106107
Lastly, we define the `spring_force` function that takes a `spring` and returns the force exerted by this spring.
107108

108109
```julia
109-
spring_force(spring) = -spring.k .* collect(spring.dir) .* (spring.x - spring.l) ./ spring.x
110+
spring_force(spring) = -spring.k .* scalarize(spring.dir) .* (spring.x - spring.l) ./ spring.x
110111
```
111112

112113
To create our system, we will first create the components: a mass and a spring. This is done as follows:
@@ -127,7 +128,7 @@ We can now create the equations describing this system, by connecting `spring` t
127128
```julia
128129
eqs = [
129130
connect_spring(spring, mass.pos, center)
130-
collect(D.(mass.v) .~ spring_force(spring) / mass.m .+ g)
131+
scalarize(D.(mass.v) .~ spring_force(spring) / mass.m .+ g)
131132
]
132133
```
133134

@@ -230,4 +231,4 @@ We can also plot the path of the mass:
230231
plot(sol, vars = (mass.pos[1], mass.pos[2]))
231232
```
232233

233-
![plotpos](https://user-images.githubusercontent.com/23384717/130322197-cff35eb7-0739-471d-a3d9-af83d87f1cc7.png)
234+
![plotpos](https://user-images.githubusercontent.com/23384717/130322197-cff35eb7-0739-471d-a3d9-af83d87f1cc7.png)

0 commit comments

Comments
 (0)