Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 113 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ModelingToolkit v10 Release Notes

### Callbacks
## Callbacks

Callback semantics have changed.

Expand All @@ -17,6 +17,118 @@ event = SymbolicDiscreteCallback(
[t == 1] => [p ~ Pre(p) + 1], discrete_parameters = [p])
```

## New `mtkcompile` and `@mtkcompile`

`structural_simplify` is now renamed to `mtkcompile`. `@mtkbuild` is renamed to
`@mtkcompile`. Their functionality remains the same. However, instead of a second
positional argument `structural_simplify(sys, (inputs, outputs))` the inputs and outputs
should be specified via keyword arguments as `mtkcompile(sys; inputs, outputs, disturbance_inputs)`.

## Reduce reliance on metadata in `mtkcompile`

Previously, `mtkcompile` (formerly `structural_simplify`) used to rely on the metadata of
symbolic variables to identify variables/parameters/brownians. This was regardless of
what the system expected the variable to be. Now, it respects the information in the system.

## Unified `System` type

There is now a single common `System` type for all types of models except PDEs, for which
`PDESystem` still exists. It follows the same syntax as `ODESystem` and `NonlinearSystem`
did. `System(equations, t[, vars, pars])` will construct a time-dependent system.
`System(equations[, vars, pars])` will construct a time-independent system. Refer to the
docstring for `System` for further information.

Utility constructors are defined for:

- `NonlinearSystem(sys)` to convert a time-dependent system to a time-independent one for
its steady state.
- `SDESystem(sys, noise_eqs)` to add noise to a system
- `JumpSystem(jumps, ...)` to define a system with jumps. Note that normal equations can
also be passed to `jumps`.
- `OptimizationSystem(cost, ...)` to define a system for optimization.

All problem constructors validate that the system matches the expected structure for
that problem.

## No more `parameter_dependencies`

The `parameter_dependencies` keyword is deprecated. All equations previously passed here
should now be provided as part of the standard equations of the system. If passing parameters
explicitly to the `System` constructor, the dependent parameters (on the left hand side of
parameter dependencies) should also be provided. These will be separated out when calling
`complete` or `mtkcompile`. Calling `parameter_dependencies` or `dependent_parameters` now
requires that the system is completed. The new `SDESystem` constructor still retains the
`parameter_dependencies` keyword argument since the number of equations has to match the
number of columns in `noise_eqs`.

ModelingToolkit now has discretion of what parameters are eliminated using the parameter
equations during `complete` or `mtkcompile`.

## New problem and constructors

Instead of `XProblem(sys, u0map, tspan, pmap)` for time-dependent problems and
`XProblem(sys, u0map, pmap)` for time-independent problems, the syntax has changed to
`XProblem(sys, op, tspan)` and `XProblem(sys, op)` respectively. `op` refers to the
operating point, and is a variable-value mapping containing both unknowns and parameters.

`XFunction` constructors also no longer accept the list of unknowns and parameters as
positional arguments.

## Removed `DelayParentScope`

The outdated `DelayParentScope` has been removed.

## Removed `XProblemExpr` and `XFunctionExpr`

The old `XProblemExpr` and `XFunctionExpr` constructors used to build an `Expr` that
constructs `XProblem` and `XFunction` respectively are now removed. This functionality
is now available by passing `expression = Val{true}` to any problem or function constructor.

## Renaming of `generate_*` and `calculate_*` methods

Several `generate_*` methods have been renamed, along with some `calculate_*` methods.
The `generate_*` methods also no longer accept a list of unknowns and/or parameters. Refer
to the documentation for more information.

## New behavior of `getproperty` and `setproperty!`

Using `getproperty` to access fields of a system has been deprecated for a long time, and
this functionality is now removed. `setproperty!` previously used to update the default
of the accessed symbolic variable. This is not supported anymore. Defaults can be updated by
mutating `ModelingToolkit.get_defaults(sys)`.

## New behavior of `@constants`

`@constants` now creates parameters with the `tunable = false` metadata by default.

## Removed `FunctionalAffect`

`FunctionalAffect` is now removed in favor of the new `ImperativeAffect`. Refer to the
documentation for more information.

## Improved system metadata

Instead of an empty field that can contain arbitrary data, the `System` type stores metadata
identically to `SymbolicUtils.BasicSymbolic`. Metadata is stored in an immutable dictionary
keyed by a user-provided `DataType` and containing arbitrary values. `System` supports the
same `SymbolicUtils.getmetadata` and `SymbolicUtils.setmetadata` API as symbolic variables.
Refer to the documentation of `System` and the aforementioned functions for more information.

## Moved `connect` and `Connector` to ModelingToolkit

Previously ModelingToolkit used the `connect` function and `Connector` type defined in
Symbolics.jl. These have now been moved to ModelingToolkit along with the experimental
state machine API. If you imported them from Symbolics.jl, it is recommended to import from
ModelingToolkit instead.

## Always wrap with `ParentScope` in `@named`

When creating a system using `@named`, any symbolic quantities passed as keyword arguments
to the subsystem are wrapped in `ParentScope`. Previously, this would only happen if the
variable wasn't already wrapped in a `ParentScope`. However, the old behavior had issues
when passing symbolic quantities down multiple levels of the hierarchy. The `@named` macro
now always performs this wrapping.

# ModelingToolkit v9 Release Notes

### Upgrade guide
Expand Down
5 changes: 0 additions & 5 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,5 @@ StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0"
Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[sources]
ModelingToolkitStandardLibrary = { url = "https://github.com/SciML/ModelingToolkitStandardLibrary.jl/", rev = "mtk-v10" }
OptimizationBase = { url = "https://github.com/AayushSabharwal/OptimizationBase.jl", rev = "as/mtk-v10" }
OptimizationMOI = { url = "https://github.com/AayushSabharwal/Optimization.jl", subdir = "lib/OptimizationMOI", rev = "as/mtk-v10" }

[targets]
test = ["AmplNLWriter", "BenchmarkTools", "BoundaryValueDiffEqMIRK", "BoundaryValueDiffEqAscher", "ControlSystemsBase", "DataInterpolations", "DelayDiffEq", "NonlinearSolve", "ForwardDiff", "Ipopt", "Ipopt_jll", "ModelingToolkitStandardLibrary", "Optimization", "OptimizationOptimJL", "OptimizationMOI", "OrdinaryDiffEq", "OrdinaryDiffEqCore", "OrdinaryDiffEqDefault", "REPL", "Random", "ReferenceTests", "SafeTestsets", "StableRNGs", "Statistics", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials", "StochasticDelayDiffEq", "Pkg", "JET", "OrdinaryDiffEqNonlinearSolve", "Logging", "OptimizationBase"]
10 changes: 0 additions & 10 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
ControlSystemsMTK = "687d7614-c7e5-45fc-bfc3-9ee385575c88"
DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Expand All @@ -16,9 +15,6 @@ ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
ModelingToolkitStandardLibrary = "16a59e39-deab-5bd0-87e4-056b12336739"
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba"
OptimizationBase = "bca83a33-5cc9-4baa-983d-23429ab6bcbb"
OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46"
Expand All @@ -30,10 +26,6 @@ SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[sources]
ModelingToolkitStandardLibrary = {rev = "mtk-v10", url = "https://github.com/SciML/ModelingToolkitStandardLibrary.jl/"}
OptimizationBase = {rev = "as/mtk-v10", url = "https://github.com/AayushSabharwal/OptimizationBase.jl"}

[compat]
Attractors = "1.24"
BenchmarkTools = "1.3"
Expand All @@ -49,8 +41,6 @@ ModelingToolkit = "10"
ModelingToolkitStandardLibrary = "2.19"
NonlinearSolve = "3, 4"
Optim = "1.7"
Optimization = "3.9, 4"
OptimizationOptimJL = "0.1, 0.4"
OrdinaryDiffEq = "6.31"
Plots = "1.36"
PreallocationTools = "0.4"
Expand Down
4 changes: 2 additions & 2 deletions docs/src/API/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ When variables with descriptions are present in systems, they will be printed wh
```@example metadata
@variables u(t) [description = "A short description of u"]
@parameters p [description = "A description of p"]
@named sys = ODESystem([u ~ p], t)
@named sys = System([u ~ p], t)
show(stdout, "text/plain", sys) # hide
```

Expand Down Expand Up @@ -298,7 +298,7 @@ In the example below, we define a system with tunable parameters and extract bou
@parameters k [tunable = true, bounds = (0, Inf)]
eqs = [D(x) ~ (-x + k * u) / T # A first-order system with time constant T and gain k
y ~ x]
sys = ODESystem(eqs, t, name = :tunable_first_order)
sys = System(eqs, t, name = :tunable_first_order)
```

```@example metadata
Expand Down
2 changes: 1 addition & 1 deletion docs/src/basics/AbstractSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ model manipulation and compilation.
There are three immediate subtypes of `AbstractSystem`, classified by how many independent variables each type has:

- `AbstractTimeIndependentSystem`: has no independent variable (e.g.: `NonlinearSystem`)
- `AbstractTimeDependentSystem`: has a single independent variable (e.g.: `ODESystem`)
- `AbstractTimeDependentSystem`: has a single independent variable (e.g.: `System`)
- `AbstractMultivariateSystem`: may have multiple independent variables (e.g.: `PDESystem`)

## Constructors and Naming
Expand Down
26 changes: 13 additions & 13 deletions docs/src/basics/Composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ using ModelingToolkit: t_nounits as t, D_nounits as D
function decay(; name)
@parameters a
@variables x(t) f(t)
ODESystem([
System([
D(x) ~ -a * x + f
], t;
name = name)
Expand All @@ -31,7 +31,7 @@ end
@named decay2 = decay()

connected = compose(
ODESystem([decay2.f ~ decay1.x
System([decay2.f ~ decay1.x
D(decay1.f) ~ 0], t; name = :connected), decay1, decay2)

equations(connected)
Expand Down Expand Up @@ -69,7 +69,7 @@ subsystems. A model is the composition of itself and its subsystems.
For example, if we have:

```julia
@named sys = compose(ODESystem(eqs, indepvar, unknowns, ps), subsys)
@named sys = compose(System(eqs, indepvar, unknowns, ps), subsys)
```

the `equations` of `sys` is the concatenation of `get_eqs(sys)` and
Expand Down Expand Up @@ -122,7 +122,7 @@ With symbolic parameters, it is possible to set the default value of a parameter

```julia
# ...
sys = ODESystem(
sys = System(
# ...
# directly in the defaults argument
defaults = Pair{Num, Any}[x => u,
Expand All @@ -144,20 +144,20 @@ d = GlobalScope(d)

p = [a, b, c, d]

level0 = ODESystem(Equation[], t, [], p; name = :level0)
level1 = ODESystem(Equation[], t, [], []; name = :level1) ∘ level0
level0 = System(Equation[], t, [], p; name = :level0)
level1 = System(Equation[], t, [], []; name = :level1) ∘ level0
parameters(level1)
#level0₊a
#b
#c
#d
level2 = ODESystem(Equation[], t, [], []; name = :level2) ∘ level1
level2 = System(Equation[], t, [], []; name = :level2) ∘ level1
parameters(level2)
#level1₊level0₊a
#level1₊b
#c
#d
level3 = ODESystem(Equation[], t, [], []; name = :level3) ∘ level2
level3 = System(Equation[], t, [], []; name = :level3) ∘ level2
parameters(level3)
#level2₊level1₊level0₊a
#level2₊level1₊b
Expand Down Expand Up @@ -194,12 +194,12 @@ using ModelingToolkit: t_nounits as t, D_nounits as D
N = S + I + R
@parameters β, γ

@named seqn = ODESystem([D(S) ~ -β * S * I / N], t)
@named ieqn = ODESystem([D(I) ~ β * S * I / N - γ * I], t)
@named reqn = ODESystem([D(R) ~ γ * I], t)
@named seqn = System([D(S) ~ -β * S * I / N], t)
@named ieqn = System([D(I) ~ β * S * I / N - γ * I], t)
@named reqn = System([D(R) ~ γ * I], t)

sir = compose(
ODESystem(
System(
[
S ~ ieqn.S,
I ~ seqn.I,
Expand Down Expand Up @@ -266,6 +266,6 @@ equations are discontinuous in either the unknown or one of its derivatives. Thi
causes the solver to take very small steps around the discontinuity, and
sometimes leads to early stopping due to `dt <= dt_min`. The correct way to
handle such dynamics is to tell the solver about the discontinuity by a
root-finding equation, which can be modeling using [`ODESystem`](@ref)'s event
root-finding equation, which can be modeling using [`System`](@ref)'s event
support. Please see the tutorial on [Callbacks and Events](@ref events) for
details and examples.
4 changes: 2 additions & 2 deletions docs/src/basics/Debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ using ModelingToolkit: t_nounits as t, D_nounits as D
@variables u1(t) u2(t) u3(t)
eqs = [D(u1) ~ -√(u1), D(u2) ~ -√(u2), D(u3) ~ -√(u3)]
defaults = [u1 => 1.0, u2 => 2.0, u3 => 3.0]
@named sys = ODESystem(eqs, t; defaults)
@named sys = System(eqs, t; defaults)
sys = mtkcompile(sys)
```

Expand All @@ -38,7 +38,7 @@ We could have figured that out ourselves, but it is not always so obvious for mo
Suppose we also want to validate that `u1 + u2 >= 2.0`. We can do this via the assertions functionality.

```@example debug
@mtkcompile sys = ODESystem(eqs, t; defaults, assertions = [(u1 + u2 >= 2.0) => "Oh no!"])
@mtkcompile sys = System(eqs, t; defaults, assertions = [(u1 + u2 >= 2.0) => "Oh no!"])
```

The assertions must be an iterable of pairs, where the first element is the symbolic condition and
Expand Down
Loading
Loading