Skip to content

Commit f767f39

Browse files
committed
Merge branch 'master' into fb/discrete_timing
2 parents c47f844 + 1bd482d commit f767f39

Some content is hidden

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

55 files changed

+2210
-345
lines changed

.github/dependabot.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ updates:
55
directory: "/" # Location of package manifests
66
schedule:
77
interval: "weekly"
8+
ignore:
9+
- dependency-name: "crate-ci/typos"
10+
update-types: ["version-update:semver-patch"]

.github/workflows/SpellCheck.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Spell Check
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
typos-check:
7+
name: Spell Check with Typos
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Checkout Actions Repository
11+
uses: actions/checkout@v4
12+
- name: Check spelling
13+
uses: crate-ci/typos@v1.16.25

.github/workflows/ci.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ jobs:
2121
test:
2222
runs-on: ubuntu-latest
2323
strategy:
24+
fail-fast: false
2425
matrix:
2526
group:
26-
- All
27+
- InterfaceI
28+
- InterfaceII
29+
- Extensions
2730
version:
2831
- '1'
2932
steps:
@@ -43,6 +46,8 @@ jobs:
4346
${{ runner.os }}-
4447
- uses: julia-actions/julia-buildpkg@v1
4548
- uses: julia-actions/julia-runtest@v1
49+
env:
50+
GROUP: ${{ matrix.group }}
4651
- uses: julia-actions/julia-processcoverage@v1
4752
- uses: codecov/codecov-action@v3
4853
with:

.typos.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[default.extend-words]
2+
nin = "nin"
3+
nd = "nd"
4+
Strat = "Strat"
5+
eles = "eles"
6+
ser = "ser"

Project.toml

Lines changed: 9 additions & 7 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 = ["Yingbo Ma <mayingbo5@gmail.com>", "Chris Rackauckas <accounts@chrisrackauckas.com> and contributors"]
4-
version = "8.73.0"
4+
version = "9.0.0"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
@@ -17,6 +17,7 @@ Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
1717
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
1818
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1919
DomainSets = "5b8099bc-c8ec-5219-889f-1d9e522a28bf"
20+
DynamicQuantities = "06fc5a27-2a28-4c7c-a15d-362465fb6821"
2021
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
2122
FunctionWrappersWrappers = "77dc65aa-8811-40c2-897b-53d922fa7daf"
2223
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
@@ -72,6 +73,7 @@ Distributed = "1"
7273
Distributions = "0.23, 0.24, 0.25"
7374
DocStringExtensions = "0.7, 0.8, 0.9"
7475
DomainSets = "0.6"
76+
DynamicQuantities = "0.8, 0.9, 0.10"
7577
ForwardDiff = "0.10.3"
7678
FunctionWrappersWrappers = "0.1"
7779
Graphs = "1.5.2"
@@ -88,19 +90,19 @@ MacroTools = "0.5"
8890
NaNMath = "0.3, 1"
8991
OrdinaryDiffEq = "6"
9092
PrecompileTools = "1"
91-
RecursiveArrayTools = "2.3"
93+
RecursiveArrayTools = "2.3, 3"
9294
Reexport = "0.2, 1"
9395
RuntimeGeneratedFunctions = "0.5.9"
9496
SciMLBase = "2.0.1"
9597
Serialization = "1"
9698
Setfield = "0.7, 0.8, 1"
97-
SimpleNonlinearSolve = "0.1.0"
99+
SimpleNonlinearSolve = "0.1.0, 1"
98100
SparseArrays = "1"
99101
SpecialFunctions = "0.7, 0.8, 0.9, 0.10, 1.0, 2"
100102
StaticArrays = "0.10, 0.11, 0.12, 1.0"
101-
SymbolicIndexingInterface = "0.1, 0.2"
103+
SymbolicIndexingInterface = "0.3.1"
102104
SymbolicUtils = "1.0"
103-
Symbolics = "5.0"
105+
Symbolics = "5.7"
104106
URIs = "1"
105107
UnPack = "0.1, 1.0"
106108
Unitful = "1.1"
@@ -109,7 +111,6 @@ julia = "1.9"
109111
[extras]
110112
AmplNLWriter = "7c4d4715-977e-5154-bfe0-e096adeac482"
111113
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
112-
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
113114
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
114115
ControlSystemsMTK = "687d7614-c7e5-45fc-bfc3-9ee385575c88"
115116
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"
@@ -121,6 +122,7 @@ NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
121122
Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba"
122123
OptimizationMOI = "fd9f6733-72f4-499f-8506-86b2bdd0dea1"
123124
OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e"
125+
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
124126
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
125127
ReferenceTests = "324d217c-45ce-50fc-942e-d289b448e8cf"
126128
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
@@ -133,4 +135,4 @@ Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"
133135
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
134136

135137
[targets]
136-
test = ["AmplNLWriter", "BenchmarkTools", "BifurcationKit", "ControlSystemsBase", "ControlSystemsMTK", "NonlinearSolve", "ForwardDiff", "Ipopt", "Ipopt_jll", "ModelingToolkitStandardLibrary", "Optimization", "OptimizationOptimJL", "OptimizationMOI", "Random", "ReferenceTests", "SafeTestsets", "StableRNGs", "Statistics", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials", "StochasticDelayDiffEq"]
138+
test = ["AmplNLWriter", "BenchmarkTools", "ControlSystemsBase", "ControlSystemsMTK", "NonlinearSolve", "ForwardDiff", "Ipopt", "Ipopt_jll", "ModelingToolkitStandardLibrary", "Optimization", "OptimizationOptimJL", "OptimizationMOI", "Random", "ReferenceTests", "SafeTestsets", "StableRNGs", "Statistics", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials", "StochasticDelayDiffEq", "Pkg"]

docs/Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ Distributions = "0.25"
2727
Documenter = "1"
2828
ModelingToolkit = "8.33"
2929
ModelingToolkitDesigner = "1"
30-
NonlinearSolve = "0.3, 1, 2"
30+
NonlinearSolve = "0.3, 1, 2, 3"
3131
Optim = "1.7"
3232
Optimization = "3.9"
3333
OptimizationOptimJL = "0.1"
3434
OrdinaryDiffEq = "6.31"
3535
Plots = "1.36"
3636
StochasticDiffEq = "6"
37-
StructuralIdentifiability = "0.4"
37+
StructuralIdentifiability = "0.4, 0.5"
3838
SymbolicUtils = "1"
3939
Symbolics = "5"
4040
Unitful = "1.12"

docs/src/basics/AbstractSystem.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ patterns via an abstract interpretation without requiring differentiation.
121121

122122
At the end, the system types have `DEProblem` constructors, like `ODEProblem`,
123123
which allow for directly generating the problem types required for numerical
124-
methods. The first argument is always the `AbstractSystem`, and the proceding
124+
methods. The first argument is always the `AbstractSystem`, and the next
125125
arguments match the argument order of their original constructors. Whenever an
126126
array would normally be provided, such as `u0` the initial condition of an
127127
`ODEProblem`, it is instead replaced with a variable map, i.e., an array of

docs/src/basics/Linearization.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ If linearization is to be performed around multiple operating points, the simpli
5151

5252
## Symbolic linearization
5353

54-
The function [`ModelingToolkit.linearize_symbolic`](@ref) works simiar to [`ModelingToolkit.linearize`](@ref) but returns symbolic rather than numeric Jacobians. Symbolic linearization have several limitations and no all systems that can be linearized numerically can be linearized symbolically.
54+
The function [`ModelingToolkit.linearize_symbolic`](@ref) works similar to [`ModelingToolkit.linearize`](@ref) but returns symbolic rather than numeric Jacobians. Symbolic linearization have several limitations and no all systems that can be linearized numerically can be linearized symbolically.
5555

5656
## Input derivatives
5757

docs/src/basics/MTKModel_Connector.md

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ equations.
2929
- `@icon` : for embedding the model icon
3030
- `@parameters`: for specifying the symbolic parameters
3131
- `@structural_parameters`: for specifying non-symbolic parameters
32-
- `@variables`: for specifing the states
32+
- `@variables`: for specifying the states
3333

3434
Let's explore these in more detail with the following example:
3535

@@ -104,7 +104,7 @@ end
104104

105105
#### `@structural_parameters` begin block
106106

107-
- This block is for non symbolic input arguements. These are for inputs that usually are not meant to be part of components; but influence how they are defined. One can list inputs like boolean flags, functions etc... here.
107+
- This block is for non symbolic input arguments. These are for inputs that usually are not meant to be part of components; but influence how they are defined. One can list inputs like boolean flags, functions etc... here.
108108
- Whenever default values are specified, unlike parameters/variables, they are reflected in the keyword argument list.
109109

110110
#### `@parameters` and `@variables` begin block
@@ -251,3 +251,104 @@ Dict{Symbol, Any} with 7 entries:
251251
:extend => Any[[:p2, :p1], Symbol("#mtkmodel__anonymous__ModelB"), :ModelB]
252252
:equations => ["model_a.k ~ f(v)"]
253253
```
254+
255+
### Using conditional statements
256+
257+
#### Conditional elements of the system
258+
259+
Both `@mtkmodel` and `@connector` support conditionally defining parameters,
260+
variables, equations, and components.
261+
262+
The if-elseif-else statements can be used inside `@equations`, `@parameters`,
263+
`@variables`, `@components`.
264+
265+
```@example branches-in-components
266+
using ModelingToolkit
267+
268+
@mtkmodel C begin end
269+
270+
@mtkmodel BranchInsideTheBlock begin
271+
@structural_parameters begin
272+
flag = true
273+
end
274+
@parameters begin
275+
if flag
276+
a1
277+
else
278+
a2
279+
end
280+
end
281+
@components begin
282+
if flag
283+
sys1 = C()
284+
else
285+
sys2 = C()
286+
end
287+
end
288+
end
289+
```
290+
291+
Alternatively, the `@equations`, `@parameters`, `@variables`, `@components` can be
292+
used inside the if-elseif-else statements.
293+
294+
```@example branches-in-components
295+
@mtkmodel BranchOutsideTheBlock begin
296+
@structural_parameters begin
297+
flag = true
298+
end
299+
if flag
300+
@parameters begin
301+
a1
302+
end
303+
@components begin
304+
sys1 = C()
305+
end
306+
@equations begin
307+
a1 ~ 0
308+
end
309+
else
310+
@parameters begin
311+
a2
312+
end
313+
@equations begin
314+
a2 ~ 0
315+
end
316+
end
317+
end
318+
```
319+
320+
The conditional parts are reflected in the `structure`. For `BranchOutsideTheBlock`, the metadata is:
321+
322+
```julia
323+
julia> BranchOutsideTheBlock.structure
324+
Dict{Symbol, Any} with 5 entries:
325+
:components => Any[(:if, :flag, [[:sys1, :C]], Any[])]
326+
:kwargs => Dict{Symbol, Any}(:flag=>true)
327+
:independent_variable => t
328+
:parameters => Dict{Symbol, Dict{Symbol, Any}}(:a1=>Dict(:condition=>(:if, :flag, Dict{Symbol, Any}(:kwargs => Dict{Any, Any}(:a1 => nothing), :parameters => Any[Dict{Symbol, Dict{Symbol, Any}}(:a1 => Dict())]), Dict{Symbol, Any}(:kwargs => Dict{Any, Any}(:a2 => nothing), :parameters => Any[Dict{Symbol, Dict{Symbol, Any}}(:a2 => Dict())]))
329+
:equations => Any[(:if, :flag, ["a1 ~ 0"], ["a2 ~ 0"])]
330+
```
331+
332+
Conditional entries are entered in the format of `(branch, condition, [case when it is true], [case when it is false])`;
333+
where `branch` is either `:if` or `:elseif`.<br>
334+
The `[case when it is false]` is either an empty vector or `nothing` when only if branch is
335+
present; it is a vector or dictionary whenever else branch is present; it is a conditional tuple
336+
whenever elseif branches are present.
337+
338+
For the conditional components and equations these condition tuples are added
339+
directly, while for parameters and variables these are added as `:condition` metadata.
340+
341+
#### Conditional initial guess of symbolic variables
342+
343+
Using ternary operator or if-elseif-else statement, conditional initial guesses can be assigned to parameters and variables.
344+
345+
```@example branches-in-components
346+
@mtkmodel DefaultValues begin
347+
@structural_parameters begin
348+
flag = true
349+
end
350+
@parameters begin
351+
p = flag ? 1 : 2
352+
end
353+
end
354+
```

docs/src/basics/Variable_metadata.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ hasbounds(u)
8383
getbounds(u)
8484
```
8585

86+
## Guess
87+
88+
Specify an initial guess for custom initial conditions of an `ODESystem`.
89+
90+
```@example metadata
91+
@variables u [guess = 1]
92+
hasguess(u)
93+
```
94+
95+
```@example metadata
96+
getguess(u)
97+
```
98+
8699
## Mark input as a disturbance
87100

88101
Indicate that an input is not available for control, i.e., it's a disturbance input.

docs/src/tutorials/bifurcation_diagram_computation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# [Bifurcation Diagrams](@id bifurcation_diagrams)
22

3-
Bifurcation diagrams describes how, for a dynamic system, the quantity and quality of its steady states changes with a parameter's value. These can be computed through the [BifurcationKit.jl](https://github.com/bifurcationkit/BifurcationKit.jl) package. ModelingToolkit provides a simple interface for creating BifurcationKit compatible `BifurcationProblem`s from `NonlinearSystem`s and `ODESystem`s. All teh features provided by BifurcationKit can then be applied to these systems. This tutorial provides a brief introduction for these features, with BifurcationKit.jl providing [a more extensive documentation](https://bifurcationkit.github.io/BifurcationKitDocs.jl/stable/).
3+
Bifurcation diagrams describes how, for a dynamic system, the quantity and quality of its steady states changes with a parameter's value. These can be computed through the [BifurcationKit.jl](https://github.com/bifurcationkit/BifurcationKit.jl) package. ModelingToolkit provides a simple interface for creating BifurcationKit compatible `BifurcationProblem`s from `NonlinearSystem`s and `ODESystem`s. All the features provided by BifurcationKit can then be applied to these systems. This tutorial provides a brief introduction for these features, with BifurcationKit.jl providing [a more extensive documentation](https://bifurcationkit.github.io/BifurcationKitDocs.jl/stable/).
44

55
### Creating a `BifurcationProblem`
66

docs/src/tutorials/domain_connections.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ nothing #hide
205205

206206
![actsys2](https://github.com/SciML/ModelingToolkit.jl/assets/40798837/8ed50035-f6ac-48cb-a585-1ef415154a02)
207207

208-
After running `structural_simplify()` on `actsys2`, the defaults will show that `act.port_a.ρ` points to `fluid_a₊ρ` and `act.port_b.ρ` points to `fluid_b₊ρ`. This is a special case, in most cases a hydraulic system will have only 1 fluid, however this simple system has 2 separate domain networks. Therefore, we can connect a single fluid to both networks. This does not interfer with the mathmatical equations of the system, since no states are connected.
208+
After running `structural_simplify()` on `actsys2`, the defaults will show that `act.port_a.ρ` points to `fluid_a₊ρ` and `act.port_b.ρ` points to `fluid_b₊ρ`. This is a special case, in most cases a hydraulic system will have only 1 fluid, however this simple system has 2 separate domain networks. Therefore, we can connect a single fluid to both networks. This does not interfere with the mathematical equations of the system, since no states are connected.
209209

210210
```@example domain
211211
@component function ActuatorSystem1(; name)
@@ -239,7 +239,7 @@ nothing #hide
239239

240240
## Special Connection Cases (`domain_connect()`)
241241

242-
In some cases a component will be defined with 2 connectors of the same domain, but they are not connected. For example the `Restrictor` defined here gives equations to define the behavior of how the 2 connectors `port_a` and `port_b` are physcially connected.
242+
In some cases a component will be defined with 2 connectors of the same domain, but they are not connected. For example the `Restrictor` defined here gives equations to define the behavior of how the 2 connectors `port_a` and `port_b` are physically connected.
243243

244244
```@example domain
245245
@component function Restrictor(; name, p_int)

docs/src/tutorials/ode_modeling.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ plot(solve(prob))
327327

328328
More on this topic may be found in [Composing Models and Building Reusable Components](@ref acausal).
329329

330-
## Inital Guess
330+
## Initial Guess
331331

332332
It is often a good idea to specify reasonable values for the initial state and the
333333
parameters of a model component. Then, these do not have to be explicitly specified when constructing the `ODEProblem`.
@@ -347,7 +347,7 @@ end
347347
```
348348

349349
While defining the model `UnitstepFOLFactory`, an initial guess of 0.0 is assigned to `x(t)` and 1.0 to `τ`.
350-
Additionaly, these initial guesses can be modified while creating instances of `UnitstepFOLFactory` by passing arguements.
350+
Additionally, these initial guesses can be modified while creating instances of `UnitstepFOLFactory` by passing arguments.
351351

352352
```@example ode2
353353
@named fol = UnitstepFOLFactory(; x = 0.1)

ext/MTKBifurcationKitExt.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ struct ObservableRecordFromSolution{S, T}
2020
param_end_idxs::Int64
2121
# The index (in subs_vals) that contain the bifurcation parameter.
2222
bif_par_idx::Int64
23-
# A Vector of pairs (Symbolic => value) with teh default values of all system variables and parameters.
23+
# A Vector of pairs (Symbolic => value) with the default values of all system variables and parameters.
2424
subs_vals::T
2525

2626
function ObservableRecordFromSolution(nsys::NonlinearSystem,
@@ -34,17 +34,17 @@ struct ObservableRecordFromSolution{S, T}
3434
param_end_idxs = state_end_idxs + length(parameters(nsys))
3535

3636
bif_par_idx = state_end_idxs + bif_idx
37-
# Gets the (base) substitution values for states.
37+
# Gets the (base) substitution values for states.
3838
subs_vals_states = Pair.(states(nsys), u0_vals)
39-
# Gets the (base) substitution values for parameters.
39+
# Gets the (base) substitution values for parameters.
4040
subs_vals_params = Pair.(parameters(nsys), p_vals)
41-
# Gets the (base) substitution values for observables.
41+
# Gets the (base) substitution values for observables.
4242
subs_vals_obs = [obs.lhs => substitute(obs.rhs,
4343
[subs_vals_states; subs_vals_params]) for obs in observed(nsys)]
44-
# Sometimes observables depend on other observables, hence we make a second upate to this vector.
44+
# Sometimes observables depend on other observables, hence we make a second update to this vector.
4545
subs_vals_obs = [obs.lhs => substitute(obs.rhs,
4646
[subs_vals_states; subs_vals_params; subs_vals_obs]) for obs in observed(nsys)]
47-
# During the bifurcation process, teh value of some states, parameters, and observables may vary (and are calculated in each step). Those that are not are stored in this vector
47+
# During the bifurcation process, the value of some states, parameters, and observables may vary (and are calculated in each step). Those that are not are stored in this vector
4848
subs_vals = [subs_vals_states; subs_vals_params; subs_vals_obs]
4949

5050
param_end_idxs = state_end_idxs + length(parameters(nsys))
@@ -136,7 +136,7 @@ function BifurcationKit.BifurcationProblem(osys::ODESystem, args...; kwargs...)
136136
nsys = NonlinearSystem([0 ~ eq.rhs for eq in equations(osys)],
137137
states(osys),
138138
parameters(osys);
139-
name = osys.name)
139+
name = nameof(osys))
140140
return BifurcationKit.BifurcationProblem(nsys, args...; kwargs...)
141141
end
142142

ext/MTKDeepDiffsExt.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ function Base.show(io::IO, l::BipartiteAdjacencyListDiff)
7272
new_nonempty = isnothing(l.new.u) ? nothing : !isempty(l.new.u)
7373
old_nonempty = isnothing(l.old.u) ? nothing : !isempty(l.old.u)
7474
if new_nonempty === true && old_nonempty === true
75-
if (!isempty(setdiff(l.new.highligh_u, l.new.u)) ||
76-
!isempty(setdiff(l.old.highligh_u, l.old.u)))
77-
throw(ArgumentError("The provided `highligh_u` must be a sub-graph of `u`."))
75+
if (!isempty(setdiff(l.new.highlight_u, l.new.u)) ||
76+
!isempty(setdiff(l.old.highlight_u, l.old.u)))
77+
throw(ArgumentError("The provided `highlight_u` must be a sub-graph of `u`."))
7878
end
7979

8080
new_items = Dict(i => HighlightInt(i, :nothing, i === l.new.match) for i in l.new.u)

0 commit comments

Comments
 (0)