Skip to content

Commit 088f652

Browse files
committed
Merge branch 'master' into careful-event-affects
2 parents 7f7f65c + b60c152 commit 088f652

37 files changed

+1203
-121
lines changed

Project.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
name = "ModelingToolkit"
22
uuid = "961ee093-0014-501f-94e3-6117800e7a78"
33
authors = ["Yingbo Ma <[email protected]>", "Chris Rackauckas <[email protected]> and contributors"]
4-
version = "9.46.1"
4+
version = "9.47.0"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
88
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
99
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
1010
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
11+
CommonSolve = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
1112
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
1213
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
1314
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
@@ -61,21 +62,24 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
6162
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
6263
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
6364
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"
65+
HomotopyContinuation = "f213a82b-91d6-5c5d-acf7-10f1c761b327"
6466
LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
6567

6668
[extensions]
6769
MTKBifurcationKitExt = "BifurcationKit"
6870
MTKChainRulesCoreExt = "ChainRulesCore"
6971
MTKDeepDiffsExt = "DeepDiffs"
72+
MTKHomotopyContinuationExt = "HomotopyContinuation"
7073
MTKLabelledArraysExt = "LabelledArrays"
7174

7275
[compat]
7376
AbstractTrees = "0.3, 0.4"
7477
ArrayInterface = "6, 7"
75-
BifurcationKit = "0.3"
78+
BifurcationKit = "0.4"
7679
BlockArrays = "1.1"
7780
ChainRulesCore = "1"
7881
Combinatorics = "1"
82+
CommonSolve = "0.2.4"
7983
Compat = "3.42, 4"
8084
ConstructionBase = "1"
8185
DataInterpolations = "6.4"
@@ -97,6 +101,7 @@ ForwardDiff = "0.10.3"
97101
FunctionWrappers = "1.1"
98102
FunctionWrappersWrappers = "0.1"
99103
Graphs = "1.5.2"
104+
HomotopyContinuation = "2.11"
100105
InteractiveUtils = "1"
101106
JuliaFormatter = "1.0.47"
102107
JumpProcesses = "9.13.1"
@@ -126,7 +131,7 @@ SpecialFunctions = "0.7, 0.8, 0.9, 0.10, 1.0, 2"
126131
StaticArrays = "0.10, 0.11, 0.12, 1.0"
127132
SymbolicIndexingInterface = "0.3.31"
128133
SymbolicUtils = "3.7"
129-
Symbolics = "6.14"
134+
Symbolics = "6.15.2"
130135
URIs = "1"
131136
UnPack = "0.1, 1.0"
132137
Unitful = "1.1"

docs/Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[deps]
22
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
33
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
4+
DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
45
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
56
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
67
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
@@ -23,7 +24,8 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
2324

2425
[compat]
2526
BenchmarkTools = "1.3"
26-
BifurcationKit = "0.3"
27+
BifurcationKit = "0.4"
28+
DataInterpolations = "6.5"
2729
DifferentialEquations = "7.6"
2830
Distributions = "0.25"
2931
Documenter = "1"

docs/pages.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ pages = [
1212
"tutorials/parameter_identifiability.md",
1313
"tutorials/bifurcation_diagram_computation.md",
1414
"tutorials/SampledData.md",
15-
"tutorials/domain_connections.md"],
15+
"tutorials/domain_connections.md",
16+
"tutorials/callable_params.md"],
1617
"Examples" => Any[
1718
"Basic Examples" => Any["examples/higher_order.md",
1819
"examples/spring_mass.md",

docs/src/basics/MTKLanguage.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ end
7373
v_array(t)[1:N, 1:M]
7474
v_for_defaults(t)
7575
end
76-
@extend ModelB(; p1)
76+
@extend ModelB(p1 = 1)
7777
@components begin
7878
model_a = ModelA(; k_array)
7979
model_array_a = [ModelA(; k = i) for i in 1:N]
@@ -149,14 +149,18 @@ julia> ModelingToolkit.getdefault(model_c1.v)
149149

150150
#### `@extend` begin block
151151

152-
- Partial systems can be extended in a higher system as `@extend PartialSystem(; kwargs)`.
153-
- Keyword arguments pf partial system in the `@extend` definition are added as the keyword arguments of the base system.
154-
- Note that in above example, `p1` is promoted as an argument of `ModelC`. Users can set the value of `p1`. However, as `p2` isn't listed in the model definition, its initial guess can't be specified while creating an instance of `ModelC`.
152+
Partial systems can be extended in a higher system in two ways:
155153

156-
```julia
157-
julia> @mtkbuild model_c2 = ModelC(; p1 = 2.0)
154+
- `@extend PartialSystem(var1 = value1)`
155+
156+
+ This is the recommended way of extending a base system.
157+
+ The default values for the arguments of the base system can be declared in the `@extend` statement.
158+
+ Note that all keyword arguments of the base system are added as the keyword arguments of the main system.
158159

159-
```
160+
- `@extend var_to_unpack1, var_to_unpack2 = partial_sys = PartialSystem(var1 = value1)`
161+
162+
+ In this method: explicitly list the variables that should be unpacked, provide a name for the partial system and declare the base system.
163+
+ Note that only the arguments listed out in the declaration of the base system (here: `var1`) are added as the keyword arguments of the higher system.
160164

161165
#### `@components` begin block
162166

@@ -325,11 +329,11 @@ For example, the structure of `ModelC` is:
325329
julia> ModelC.structure
326330
Dict{Symbol, Any} with 10 entries:
327331
:components => Any[Union{Expr, Symbol}[:model_a, :ModelA], Union{Expr, Symbol}[:model_array_a, :ModelA, :(1:N)], Union{Expr, Symbol}[:model_array_b, :ModelA, :(1:N)]]
328-
:variables => Dict{Symbol, Dict{Symbol, Any}}(:v=>Dict(:default=>:v_var, :type=>Real), :v_for_defaults=>Dict(:type=>Real))
332+
:variables => Dict{Symbol, Dict{Symbol, Any}}(:v=>Dict(:default=>:v_var, :type=>Real), :v_array=>Dict(:value=>nothing, :type=>Real, :size=>(:N, :M)), :v_for_defaults=>Dict(:type=>Real))
329333
:icon => URI("https://github.com/SciML/SciMLDocs/blob/main/docs/src/assets/logo.png")
330-
:kwargs => Dict{Symbol, Dict}(:f => Dict(:value => :sin), :N => Dict(:value => 2), :M => Dict(:value => 3), :v => Dict{Symbol, Any}(:value => :v_var, :type => Real), :v_for_defaults => Dict{Symbol, Union{Nothing, DataType}}(:value => nothing, :type => Real), :p1 => Dict(:value => nothing)),
331-
:structural_parameters => Dict{Symbol, Dict}(:f => Dict(:value => :sin), :N => Dict(:value => 2), :M => Dict(:value => 3))
332-
:independent_variable => t
334+
:kwargs => Dict{Symbol, Dict}(:f=>Dict(:value=>:sin), :p2=>Dict(:value=>NoValue()), :N=>Dict(:value=>2), :M=>Dict(:value=>3), :v=>Dict{Symbol, Any}(:value=>:v_var, :type=>Real), :v_array=>Dict{Symbol, Any}(:value=>nothing, :type=>Real, :size=>(:N, :M)), :v_for_defaults=>Dict{Symbol, Union{Nothing, DataType}}(:value=>nothing, :type=>Real), :p1=>Dict(:value=>1))
335+
:structural_parameters => Dict{Symbol, Dict}(:f=>Dict(:value=>:sin), :N=>Dict(:value=>2), :M=>Dict(:value=>3))
336+
:independent_variable => :t
333337
:constants => Dict{Symbol, Dict}(:c=>Dict{Symbol, Any}(:value=>1, :type=>Int64, :description=>"Example constant."))
334338
:extend => Any[[:p2, :p1], Symbol("#mtkmodel__anonymous__ModelB"), :ModelB]
335339
:defaults => Dict{Symbol, Any}(:v_for_defaults=>2.0)

docs/src/tutorials/callable_params.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Callable parameters and interpolating data
2+
3+
ModelingToolkit.jl allows creating parameters that represent functions to be called. This
4+
is especially useful for including interpolants and/or lookup tables inside ODEs. In this
5+
tutorial we will create an `ODESystem` which employs callable parameters to interpolate data
6+
inside an ODE and go over the various syntax options and their implications.
7+
8+
## Callable parameter syntax
9+
10+
The syntax for callable parameters declared via `@parameters` must be one of the following
11+
12+
1. `(fn::FType)(..)`
13+
2. `fn(::argType1, ::argType2, ...)`
14+
15+
In the first case, the parameter is callable with any number/combination of arguments, and
16+
has a type of `FType` (the callable must be a subtype of `FType`). In the second case,
17+
the parameter is callable with as many arguments as declared, and all must match the
18+
declared types.
19+
20+
By default, the return type of the callable symbolic is inferred to be `Real`. To change
21+
this, a `::retType` annotation can be added at the end.
22+
23+
To declare a function that returns an array of values, the same array syntax can be used
24+
as for normal variables:
25+
26+
```julia
27+
@parameters (foo::FType)(..)[1:3]::retType
28+
@parameters foo(::argType1, ::argType2)[1:3]::retType
29+
```
30+
31+
`retType` here is the `eltype` of the returned array.
32+
33+
## Storage of callable parameters
34+
35+
Callable parameters declared with the `::FType` syntax will be stored in a `Vector{FType}`.
36+
Thus, if `FType` is non-concrete, the buffer will also be non-concrete. This is sometimes
37+
necessary to allow the value of the callable to be switched out for a different type without
38+
rebuilding the model. Typically this syntax is preferable when `FType` is concrete or
39+
a small union.
40+
41+
Callable parameters declared with the `::argType1, ...` syntax will be stored in a
42+
`Vector{FunctionWrappers.FunctionWrapper{retType, Tuple{argType1, ...}}}`. This suffers
43+
the small overhead of a `FunctionWrapper` and restricts the signature of the callable,
44+
symbolic, but allows storing the parameter in a type-stable manner and swapping it out.
45+
This is preferable when the values that the callable can take do not share a common
46+
subtype. For example, when a callable can represent the activation of a neural network
47+
and can be `tanh`, `sigmoid`, etc. which have a common ancestor of `Function`.
48+
49+
If both `::FType` and `::argType`s are specified, `::FType` takes priority. For example,
50+
51+
```julia
52+
@parameters (p::LinearInterpolation)(::Real)
53+
```
54+
55+
`p` will be stored in a `Vector{LinearInterpolation}`. If `::LinearInterpolation` was not
56+
specified, it would be stored in a `Vector{FunctionWrapper{Real, Tuple{Real}}}`.
57+
58+
## Example using interpolations
59+
60+
```@example callable
61+
using ModelingToolkit
62+
using OrdinaryDiffEq
63+
using DataInterpolations
64+
using ModelingToolkit: t_nounits as t, D_nounits as D
65+
66+
ts = collect(0.0:0.1:10.0)
67+
spline = LinearInterpolation(ts .^ 2, ts)
68+
Tspline = typeof(spline)
69+
@variables x(t)
70+
@parameters (interp::Tspline)(..)
71+
72+
@mtkbuild sys = ODESystem(D(x) ~ interp(t), t)
73+
```
74+
75+
The derivative of `x` is obtained via an interpolation from DataInterpolations.jl. Note
76+
the parameter syntax. The `(..)` marks the parameter as callable. `(interp::Tspline)`
77+
indicates that the parameter is of type `Tspline`.
78+
79+
```@example callable
80+
prob = ODEProblem(sys, [x => 0.0], (0.0, 1.0), [interp => spline])
81+
solve(prob)
82+
```
83+
84+
Note that the the following will not work:
85+
86+
```julia
87+
ODEProblem(
88+
sys; [x => 0.0], (0.0, 1.0), [interp => LinearInterpolation(0.0:0.1:1.0, 0.0:0.1:1.0)])
89+
```
90+
91+
Since the type of the spline doesn't match.

ext/MTKBifurcationKitExt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ function BifurcationKit.BifurcationProblem(nsys::NonlinearSystem,
113113
# If the plot var is a normal state.
114114
if any(isequal(plot_var, var) for var in unknowns(nsys))
115115
plot_idx = findfirst(isequal(plot_var), unknowns(nsys))
116-
record_from_solution = (x, p) -> x[plot_idx]
116+
record_from_solution = (x, p; k...) -> x[plot_idx]
117117

118118
# If the plot var is an observed state.
119119
elseif any(isequal(plot_var, eq.lhs) for eq in observed(nsys))
@@ -132,7 +132,7 @@ function BifurcationKit.BifurcationProblem(nsys::NonlinearSystem,
132132
return BifurcationKit.BifurcationProblem(F,
133133
u0_bif_vals,
134134
p_vals,
135-
(@lens _[bif_idx]),
135+
(BifurcationKit.@optic _[bif_idx]),
136136
args...;
137137
record_from_solution = record_from_solution,
138138
J = J,

0 commit comments

Comments
 (0)