Skip to content

Commit

Permalink
Merge branch 'master' into fb/discrete_timing
Browse files Browse the repository at this point in the history
  • Loading branch information
YingboMa committed Jan 5, 2024
2 parents c47f844 + 1bd482d commit f767f39
Show file tree
Hide file tree
Showing 55 changed files with 2,210 additions and 345 deletions.
3 changes: 3 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ updates:
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
ignore:
- dependency-name: "crate-ci/typos"
update-types: ["version-update:semver-patch"]
13 changes: 13 additions & 0 deletions .github/workflows/SpellCheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Spell Check

on: [pull_request]

jobs:
typos-check:
name: Spell Check with Typos
runs-on: ubuntu-latest
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v4
- name: Check spelling
uses: crate-ci/[email protected]
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
group:
- All
- InterfaceI
- InterfaceII
- Extensions
version:
- '1'
steps:
Expand All @@ -43,6 +46,8 @@ jobs:
${{ runner.os }}-
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
env:
GROUP: ${{ matrix.group }}
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
with:
Expand Down
6 changes: 6 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[default.extend-words]
nin = "nin"
nd = "nd"
Strat = "Strat"
eles = "eles"
ser = "ser"
16 changes: 9 additions & 7 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ModelingToolkit"
uuid = "961ee093-0014-501f-94e3-6117800e7a78"
authors = ["Yingbo Ma <[email protected]>", "Chris Rackauckas <[email protected]> and contributors"]
version = "8.73.0"
version = "9.0.0"

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

[targets]
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"]
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"]
4 changes: 2 additions & 2 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ Distributions = "0.25"
Documenter = "1"
ModelingToolkit = "8.33"
ModelingToolkitDesigner = "1"
NonlinearSolve = "0.3, 1, 2"
NonlinearSolve = "0.3, 1, 2, 3"
Optim = "1.7"
Optimization = "3.9"
OptimizationOptimJL = "0.1"
OrdinaryDiffEq = "6.31"
Plots = "1.36"
StochasticDiffEq = "6"
StructuralIdentifiability = "0.4"
StructuralIdentifiability = "0.4, 0.5"
SymbolicUtils = "1"
Symbolics = "5"
Unitful = "1.12"
2 changes: 1 addition & 1 deletion docs/src/basics/AbstractSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ patterns via an abstract interpretation without requiring differentiation.

At the end, the system types have `DEProblem` constructors, like `ODEProblem`,
which allow for directly generating the problem types required for numerical
methods. The first argument is always the `AbstractSystem`, and the proceding
methods. The first argument is always the `AbstractSystem`, and the next
arguments match the argument order of their original constructors. Whenever an
array would normally be provided, such as `u0` the initial condition of an
`ODEProblem`, it is instead replaced with a variable map, i.e., an array of
Expand Down
2 changes: 1 addition & 1 deletion docs/src/basics/Linearization.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ If linearization is to be performed around multiple operating points, the simpli

## Symbolic linearization

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.
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.

## Input derivatives

Expand Down
105 changes: 103 additions & 2 deletions docs/src/basics/MTKModel_Connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ equations.
- `@icon` : for embedding the model icon
- `@parameters`: for specifying the symbolic parameters
- `@structural_parameters`: for specifying non-symbolic parameters
- `@variables`: for specifing the states
- `@variables`: for specifying the states

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

Expand Down Expand Up @@ -104,7 +104,7 @@ end

#### `@structural_parameters` begin block

- 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.
- 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.
- Whenever default values are specified, unlike parameters/variables, they are reflected in the keyword argument list.

#### `@parameters` and `@variables` begin block
Expand Down Expand Up @@ -251,3 +251,104 @@ Dict{Symbol, Any} with 7 entries:
:extend => Any[[:p2, :p1], Symbol("#mtkmodel__anonymous__ModelB"), :ModelB]
:equations => ["model_a.k ~ f(v)"]
```

### Using conditional statements

#### Conditional elements of the system

Both `@mtkmodel` and `@connector` support conditionally defining parameters,
variables, equations, and components.

The if-elseif-else statements can be used inside `@equations`, `@parameters`,
`@variables`, `@components`.

```@example branches-in-components
using ModelingToolkit
@mtkmodel C begin end
@mtkmodel BranchInsideTheBlock begin
@structural_parameters begin
flag = true
end
@parameters begin
if flag
a1
else
a2
end
end
@components begin
if flag
sys1 = C()
else
sys2 = C()
end
end
end
```

Alternatively, the `@equations`, `@parameters`, `@variables`, `@components` can be
used inside the if-elseif-else statements.

```@example branches-in-components
@mtkmodel BranchOutsideTheBlock begin
@structural_parameters begin
flag = true
end
if flag
@parameters begin
a1
end
@components begin
sys1 = C()
end
@equations begin
a1 ~ 0
end
else
@parameters begin
a2
end
@equations begin
a2 ~ 0
end
end
end
```

The conditional parts are reflected in the `structure`. For `BranchOutsideTheBlock`, the metadata is:

```julia
julia> BranchOutsideTheBlock.structure
Dict{Symbol, Any} with 5 entries:
:components => Any[(:if, :flag, [[:sys1, :C]], Any[])]
:kwargs => Dict{Symbol, Any}(:flag=>true)
:independent_variable => t
: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())]))
:equations => Any[(:if, :flag, ["a1 ~ 0"], ["a2 ~ 0"])]
```
Conditional entries are entered in the format of `(branch, condition, [case when it is true], [case when it is false])`;
where `branch` is either `:if` or `:elseif`.<br>
The `[case when it is false]` is either an empty vector or `nothing` when only if branch is
present; it is a vector or dictionary whenever else branch is present; it is a conditional tuple
whenever elseif branches are present.
For the conditional components and equations these condition tuples are added
directly, while for parameters and variables these are added as `:condition` metadata.
#### Conditional initial guess of symbolic variables
Using ternary operator or if-elseif-else statement, conditional initial guesses can be assigned to parameters and variables.
```@example branches-in-components
@mtkmodel DefaultValues begin
@structural_parameters begin
flag = true
end
@parameters begin
p = flag ? 1 : 2
end
end
```
13 changes: 13 additions & 0 deletions docs/src/basics/Variable_metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ hasbounds(u)
getbounds(u)
```

## Guess

Specify an initial guess for custom initial conditions of an `ODESystem`.

```@example metadata
@variables u [guess = 1]
hasguess(u)
```

```@example metadata
getguess(u)
```

## Mark input as a disturbance

Indicate that an input is not available for control, i.e., it's a disturbance input.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorials/bifurcation_diagram_computation.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# [Bifurcation Diagrams](@id bifurcation_diagrams)

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/).
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/).

### Creating a `BifurcationProblem`

Expand Down
4 changes: 2 additions & 2 deletions docs/src/tutorials/domain_connections.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ nothing #hide

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

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.
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.

```@example domain
@component function ActuatorSystem1(; name)
Expand Down Expand Up @@ -239,7 +239,7 @@ nothing #hide

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

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.
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.

```@example domain
@component function Restrictor(; name, p_int)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/tutorials/ode_modeling.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ plot(solve(prob))

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

## Inital Guess
## Initial Guess

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

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

```@example ode2
@named fol = UnitstepFOLFactory(; x = 0.1)
Expand Down
14 changes: 7 additions & 7 deletions ext/MTKBifurcationKitExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct ObservableRecordFromSolution{S, T}
param_end_idxs::Int64
# The index (in subs_vals) that contain the bifurcation parameter.
bif_par_idx::Int64
# A Vector of pairs (Symbolic => value) with teh default values of all system variables and parameters.
# A Vector of pairs (Symbolic => value) with the default values of all system variables and parameters.
subs_vals::T

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

bif_par_idx = state_end_idxs + bif_idx
# Gets the (base) substitution values for states.
# Gets the (base) substitution values for states.
subs_vals_states = Pair.(states(nsys), u0_vals)
# Gets the (base) substitution values for parameters.
# Gets the (base) substitution values for parameters.
subs_vals_params = Pair.(parameters(nsys), p_vals)
# Gets the (base) substitution values for observables.
# Gets the (base) substitution values for observables.
subs_vals_obs = [obs.lhs => substitute(obs.rhs,
[subs_vals_states; subs_vals_params]) for obs in observed(nsys)]
# Sometimes observables depend on other observables, hence we make a second upate to this vector.
# Sometimes observables depend on other observables, hence we make a second update to this vector.
subs_vals_obs = [obs.lhs => substitute(obs.rhs,
[subs_vals_states; subs_vals_params; subs_vals_obs]) for obs in observed(nsys)]
# 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
# 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
subs_vals = [subs_vals_states; subs_vals_params; subs_vals_obs]

param_end_idxs = state_end_idxs + length(parameters(nsys))
Expand Down Expand Up @@ -136,7 +136,7 @@ function BifurcationKit.BifurcationProblem(osys::ODESystem, args...; kwargs...)
nsys = NonlinearSystem([0 ~ eq.rhs for eq in equations(osys)],
states(osys),
parameters(osys);
name = osys.name)
name = nameof(osys))
return BifurcationKit.BifurcationProblem(nsys, args...; kwargs...)
end

Expand Down
6 changes: 3 additions & 3 deletions ext/MTKDeepDiffsExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ function Base.show(io::IO, l::BipartiteAdjacencyListDiff)
new_nonempty = isnothing(l.new.u) ? nothing : !isempty(l.new.u)
old_nonempty = isnothing(l.old.u) ? nothing : !isempty(l.old.u)
if new_nonempty === true && old_nonempty === true
if (!isempty(setdiff(l.new.highligh_u, l.new.u)) ||
!isempty(setdiff(l.old.highligh_u, l.old.u)))
throw(ArgumentError("The provided `highligh_u` must be a sub-graph of `u`."))
if (!isempty(setdiff(l.new.highlight_u, l.new.u)) ||
!isempty(setdiff(l.old.highlight_u, l.old.u)))
throw(ArgumentError("The provided `highlight_u` must be a sub-graph of `u`."))
end

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

0 comments on commit f767f39

Please sign in to comment.