-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a00ec0b
commit 3ba82d4
Showing
5 changed files
with
321 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# [Symbolic Nonlinear System Definition and Acceleration via ModelingToolkit](@id modelingtoolkit) | ||
|
||
[ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/dev/) is a symbolic-numeric modeling system | ||
for the Julia SciML ecosystem. It adds a high-level interactive interface for the numerical solvers | ||
which can make it easy to symbolically modify and generate equations to be solved. The basic form of | ||
using ModelingToolkit looks as follows: | ||
|
||
```@example mtk | ||
using ModelingToolkit, NonlinearSolve | ||
@variables x y z | ||
@parameters σ ρ β | ||
# Define a nonlinear system | ||
eqs = [0 ~ σ * (y - x), | ||
0 ~ x * (ρ - z) - y, | ||
0 ~ x * y - β * z] | ||
@named ns = NonlinearSystem(eqs, [x, y, z], [σ, ρ, β]) | ||
u0 = [x => 1.0, | ||
y => 0.0, | ||
z => 0.0] | ||
ps = [σ => 10.0 | ||
ρ => 26.0 | ||
β => 8 / 3] | ||
prob = NonlinearProblem(ns, u0, ps) | ||
sol = solve(prob, NewtonRaphson()) | ||
``` | ||
|
||
## Symbolic Derivations of Extra Functions | ||
|
||
As a symbolic system, ModelingToolkit can be used to represent the equations and derive new forms. For example, | ||
let's look at the equations: | ||
|
||
```@example mtk | ||
equations(ns) | ||
``` | ||
|
||
We can ask it what the Jacobian of our system is via `calculate_jacobian`: | ||
|
||
```@example mtk | ||
calculate_jacobian(ns) | ||
``` | ||
|
||
We can tell MTK to generate a computable form of this analytical Jacobian via `jac = true` to help the solver | ||
use efficient forms: | ||
|
||
```@example mtk | ||
prob = NonlinearProblem(ns, guess, ps, jac = true) | ||
sol = solve(prob, NewtonRaphson()) | ||
``` | ||
|
||
## Symbolic Simplification of Nonlinear Systems via Tearing | ||
|
||
One of the major reasons for using ModelingToolkit is to allow structural simplification of the systems. It's very | ||
easy to write down a mathematical model that, in theory, could be solved more simply. Let's take a look at a quick | ||
system: | ||
|
||
```@example mtk | ||
@variables u1 u2 u3 u4 u5 | ||
eqs = [ | ||
0 ~ u1 - sin(u5), | ||
0 ~ u2 - cos(u1), | ||
0 ~ u3 - hypot(u1, u2), | ||
0 ~ u4 - hypot(u2, u3), | ||
0 ~ u5 - hypot(u4, u1), | ||
] | ||
@named sys = NonlinearSystem(eqs, [u1, u2, u3, u4, u5], []) | ||
``` | ||
|
||
If we run structural simplification, we receive the following form: | ||
|
||
```@example mtk | ||
sys = structural_simplify(sys) | ||
``` | ||
|
||
```@example mtk | ||
equations(sys) | ||
``` | ||
|
||
How did it do this? Let's look at the `observed` to see the relationships that it found: | ||
|
||
```@example | ||
observed(sys) | ||
``` | ||
|
||
Using ModelingToolkit, we can build and solve the simplified system: | ||
|
||
```@example mtk | ||
u0 = [u5 .=> 1.0] | ||
prob = NonlinearProblem(sys, u0, ps) | ||
sol = solve(prob, NewtonRaphson()) | ||
``` | ||
|
||
We can then use symbolic indexing to retrieve any variable: | ||
|
||
```@example mtk | ||
sol[u1] | ||
``` | ||
|
||
```@example mtk | ||
sol[u2] | ||
``` | ||
|
||
```@example mtk | ||
sol[u3] | ||
``` | ||
|
||
```@example mtk | ||
sol[u4] | ||
``` | ||
|
||
```@example mtk | ||
sol[u5] | ||
``` | ||
|
||
## Component-Based and Acausal Modeling | ||
|
||
If you're interested in building models in a component or block based form, such as seen in systems like Simulink or Modelica, | ||
take a deeper look at [ModelingToolkit.jl's documentation](https://docs.sciml.ai/ModelingToolkit/stable/) which goes into | ||
detail on such features. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,54 @@ | ||
# Faster Startup and and Static Compilation | ||
|
||
This is a stub article to be completed soon. | ||
In many instances one may want a very lightweight version of NonlinearSolve.jl. For this case there | ||
exists the solver package SimpleNonlinearSolve.jl. SimpleNonlinearSolve.jl solvers all satisfy the | ||
same interface as NonlinearSolve.jl, but they are designed to be simpler, lightweight, and thus | ||
have a faster startup time. Everything that can be done with NonlinearSolve.jl can be done with | ||
SimpleNonlinearSolve.jl. Thus for example, we can solve the core tutorial problem with just SimpleNonlinearSolve.jl | ||
as follows: | ||
|
||
```@example simple | ||
using SimpleNonlinearSolve | ||
f(u, p) = u .* u .- p | ||
u0 = [1.0, 1.0] | ||
p = 2.0 | ||
prob = NonlinearProblem(f, u0, p) | ||
sol = solve(prob, SimpleNewtonRaphson()) | ||
``` | ||
|
||
However, there are a few downsides to SimpleNonlinearSolve's `SimpleX` style algorithms to note: | ||
|
||
1. SimpleNonlinearSolve.jl's methods are not hooked into the LinearSolve.jl system, and thus do not have | ||
the ability to specify linear solvers, use sparse matrices, preconditioners, and all of the other features | ||
which are required to scale for very large systems of equations. | ||
2. SimpleNonlinearSolve.jl's methods have less robust error handling and termination conditions, and thus | ||
these methods are missing some flexibility and give worse hints for debugging. | ||
3. SimpleNonlinearSolve.jl's methods are focused on out-of-place support. There is some in-place support, | ||
but it's designed for simple smaller systems and so some optimizations are missing. | ||
|
||
However, the major upsides of SimpleNonlinearSolve.jl are: | ||
|
||
1. The methods are optimized and non-allocating on StaticArrays | ||
2. The methods are minimal in compilation | ||
|
||
As such, you can use the code as shown above to have very low startup with good methods, but for more scaling and debuggability | ||
we recommend the full NonlinearSolve.jl. But that said, | ||
|
||
```@example simple | ||
using StaticArrays | ||
u0 = SA[1.0, 1.0] | ||
p = 2.0 | ||
prob = NonlinearProblem(f, u0, p) | ||
sol = solve(prob, SimpleNewtonRaphson()) | ||
``` | ||
|
||
using StaticArrays.jl is also the fastest form for small equations, so if you know your system is small then SimpleNonlinearSolve.jl | ||
is not only sufficient but optimal. | ||
|
||
## Static Compilation | ||
|
||
Julia has tools for building small binaries via static compilation with [StaticCompiler.jl](https://github.com/tshort/StaticCompiler.jl). | ||
However, these tools are currently limited to type-stable non-allocating functions. That said, SimpleNonlinearSolve.jl's solvers are | ||
precisely the subset of NonlinearSolve.jl which are compatible with static compilation. |