Skip to content

Commit c4aafce

Browse files
Merge pull request #631 from SciML/sm/docs
Doc updates for 4.x
2 parents 9abb2f4 + 2594ea1 commit c4aafce

File tree

8 files changed

+83
-80
lines changed

8 files changed

+83
-80
lines changed

docs/src/IR.md

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,39 @@
11
# ModelingToolkit IR
22

3-
ModelingToolkit IR, which falls under the `Expression` abstract type, mirrors
4-
the Julia AST but allows for easy mathematical manipulation by itself following
5-
mathematical semantics. The base of the IR is the `Variable` type, which defines
6-
a symbolic variable. These variables are combined using `Operation`s, which are
7-
registered functions applied to the various variables. These `Operation`s then
8-
perform automatic tracing, so normal mathematical functions applied to an `Operation`
9-
generate a new `Operation`. For example, `op1 = x+y` is one `Operation` and
10-
`op2 = 2z` is another, and so `op1*op2` is another `Operation`. Then, at the top,
11-
an `Equation`, normally written as `op1 ~ op2`, defines the symbolic equality
12-
between two operations.
3+
ModelingToolkit IR mirrors the Julia AST but allows for easy mathematical
4+
manipulation by itself following mathematical semantics. The base of the IR is
5+
the `Sym` type, which defines a symbolic variable. Registered (mathematical)
6+
functions on `Sym`s (or `Term`s) return `Term`s. For example, `op1 = x+y` is
7+
one `Term` and `op2 = 2z` is another, and so `op1*op2` is another `Term`. Then,
8+
at the top, an `Equation`, normally written as `op1 ~ op2`, defines the
9+
symbolic equality between two operations.
1310

1411
### Types
1512

1613
```@docs
17-
Expression
18-
Variable
19-
ModelingToolkit.Constant
20-
Operation
14+
Sym
15+
Term
2116
Equation
2217
```
2318

19+
### A note about functions restricted to `Number`s
20+
21+
`Sym` and `Term` objects are NOT subtypes of `Number`. ModelingToolkit provides
22+
a simple wrapper type called `Num` which is a subtype of `Real`. `Num` wraps
23+
either a Sym or a Term or any other object, defines the same set of operations
24+
as symbolic expressions and forwards those to the values it wraps. You can use
25+
`ModelingToolkit.value` function to unwrap a `Num`.
26+
27+
By default, the `@variables` and `@parameters` functions return Num-wrapped
28+
objects so as to allow calling functions which are restricted to `Number` or
29+
`Real`.
30+
2431
### Function Registration
2532

2633
The ModelingToolkit graph only allowed for registered Julia functions for the
2734
operations. All other functions are automatically traced down to registered
2835
functions. By default, ModelingToolkit.jl pre-registers the common functions
29-
utilized in the AD package ruleset [DiffRules.jl](https://github.com/JuliaDiff/DiffRules.jl)
36+
utilized in [SymbolicUtils.jl](https://github.com/JuliaSymbolics/SymbolicUtils.jl)
3037
and pre-defines their derivatives. However, the user can utilize the `@register`
3138
macro to add their function to allowed functions of the computation graph.
3239

@@ -36,7 +43,7 @@ macro to add their function to allowed functions of the computation graph.
3643

3744
### Derivatives and Differentials
3845

39-
A `Differential(op)` is a partial derivative with respect to the operation `op`,
46+
A `Differential(op)` is a partial derivative with respect to `op`,
4047
which can then be applied to some other operations. For example, `D=Differential(t)`
4148
is what would commonly be referred to as `d/dt`, which can then be applied to
4249
other operations using its function call, so `D(x+y)` is `d(x+y)/dt`.
@@ -50,18 +57,18 @@ of the differentials down to basic one-variable expressions.
5057
ModelingToolkit.derivative
5158
Differential
5259
expand_derivatives
60+
ModelingToolkit.jacobian
61+
ModelingToolkit.gradient
62+
ModelingToolkit.hessian
5363
```
5464

55-
Note that the generation of sparse matrices simply follows from the Julia semantics
56-
imbued on the IR, so `sparse(jac)` changes a dense Jacobian to a sparse Jacobian
57-
matrix.
65+
For jacobians which are sparse, use the `sparsejacobian` function.
66+
For hessians which are sparse, use the `sparsehessian` function.
5867

5968
### Adding Derivatives
6069

6170
There is a large amount of derivatives pre-defined by
62-
[DiffRules.jl](https://github.com/JuliaDiff/DiffRules.jl). Note that `Expression`
63-
types are defined as `<:Real`, and thus any functions which allow the use of real
64-
numbers can automatically be traced by the derivative mechanism. Thus, for example:
71+
[DiffRules.jl](https://github.com/JuliaDiff/DiffRules.jl).
6572

6673
```julia
6774
f(x,y,z) = x^2 + sin(x+y) - z
@@ -84,7 +91,7 @@ ModelingToolkit.derivative(::typeof(my_function), args::NTuple{N,Any}, ::Val{i})
8491

8592
where `i` means that it's the derivative with respect to the `i`th argument. `args` is the
8693
array of arguments, so, for example, if your function is `f(x,t)`, then `args = [x,t]`.
87-
You should return an `Operation` for the derivative of your function.
94+
You should return an `Term` for the derivative of your function.
8895

8996
For example, `sin(t)`'s derivative (by `t`) is given by the following:
9097

@@ -94,14 +101,14 @@ ModelingToolkit.derivative(::typeof(sin), args::NTuple{1,Any}, ::Val{1}) = cos(a
94101

95102
### IR Manipulation
96103

97-
ModelingToolkit.jl provides functionality for easily manipulating `Expression`
98-
types. Most of the functionality comes by the `Expression` type obeying the
99-
standard mathematical semantics. For example, if one has `A` a matrix of
100-
`Expression`, then `A^2` calculates the `Expression`s for the squared matrix.
101-
In that sense, it is encouraged that one uses standard Julia for performing a
102-
lot of the manipulation on the IR, as, for example, calculating the sparse form
103-
of the matrix via `sparse(A)` is valid, legible, and easily understandable
104-
to all Julia programmers.
104+
ModelingToolkit.jl provides functionality for easily manipulating expressions.
105+
Most of the functionality comes by the expression objects obeying the standard
106+
mathematical semantics. For example, if one has `A` a matrix of symbolic
107+
expressions wrapped in `Num`, then `A^2` calculates the expressions for the
108+
squared matrix. In that sense, it is encouraged that one uses standard Julia
109+
for performing a lot of the manipulation on the IR, as, for example,
110+
calculating the sparse form of the matrix via `sparse(A)` is valid, legible,
111+
and easily understandable to all Julia programmers.
105112

106113
Other additional manipulation functions are given below.
107114

docs/src/build_function.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Function Building and Compilation (build_function)
22

3-
At any time, callable functions can be generated from ModelingToolkit IR by using
4-
`convert(Expr,x)`. This performs some cleaning to return an expression without
5-
extraneous pieces that commonly matches expressions one would write in functions
6-
like those for differential equation solvers and optimization libraries. These
7-
functions can be automatically parallelize and specialize on Julia types like
8-
static arrays and sparse matrices.
3+
At any time, callable functions can be generated from ModelingToolkit IR by
4+
using `ModelingToolkit.toexpr`. This performs some cleaning to return an
5+
expression without extraneous pieces that commonly matches expressions one
6+
would write in functions like those for differential equation solvers and
7+
optimization libraries. These functions can be automatically parallelize and
8+
specialize on Julia types like static arrays and sparse matrices.
99

1010
The core compilation process of ModelingToolkit IR is `build_function`.
1111
`build_function` takes an operation or an `AbstractArray` of operations and

docs/src/highlevel.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ methods.
1111
@parameters
1212
@variables
1313
@derivatives
14-
Base.:~(::Expression, ::Expression)
14+
Base.:~(::Num, ::Num)
1515
modelingtoolkitize
1616
```
1717

@@ -42,7 +42,7 @@ latexify(ex)
4242
```
4343

4444
will produce LaTeX output from ModelingToolkit models and expressions.
45-
This works on basics like `Operation` all the way to higher primitives
45+
This works on basics like `Term` all the way to higher primitives
4646
like `ODESystem` and `ReactionSystem`.
4747

4848
## The Auto-Detecting System Constructors
@@ -78,7 +78,7 @@ du
7878
```
7979

8080
```julia
81-
3-element Array{Operation,1}:
81+
3-element Array{Num,1}:
8282
10.0 * (u₂(t) - u₁(t))
8383
u₁(t) * (28.0 - u₃(t)) - u₂(t)
8484
u₁(t) * u₂(t) - 2.6666666666666665 * u₃(t)
@@ -97,7 +97,7 @@ du
9797
```
9898

9999
```julia
100-
3-element Array{Operation,1}:
100+
3-element Array{Num,1}:
101101
10.0 * (y(t) - x(t))
102102
x(t) * (28.0 - z(t)) - y(t)
103103
x(t) * y(t) - 2.6666666666666665 * z(t)
@@ -106,7 +106,7 @@ x(t) * y(t) - 2.6666666666666665 * z(t)
106106
## Intermediate Calculations
107107

108108
The system building functions can handle intermediate calculations by simply
109-
defining and using an `Operation` of `Variable`s. For example:
109+
defining and using an `Term` of `Sym`s. For example:
110110

111111
```julia
112112
@variables x y z

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ ModelingToolkit has 3 layers:
2323
At the system level, there are *transformations* which take one system to
2424
another, and *targets* which output code for numerical solvers.
2525
3. The IR level, also referred to as the direct level. At this level, one
26-
directly acts on arrays of `Equation`, `Operation`, and `Variable` types to
26+
directly acts on arrays of `Equation`s, and symbolic expressions to
2727
generate functions.
2828

2929
Each level above is built on the level below, giving more context to allow for

docs/src/tutorials/auto_parallel.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Automated Sparse Parallelism of ODEs via Tracing
22

3-
Because the ModelingToolkit `Expression` types obey Julia semantics, one can
3+
Because the ModelingToolkit expressions obey Julia semantics, one can
44
directly transform existing Julia functions into ModelingToolkit symbolic
55
representations of the function by simply inputting the symbolic values into
66
the function and using what is returned. For example, let's take [the following

docs/src/tutorials/converting_to_C.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ lotka_volterra!(du, u, p, t)
2525
which gives:
2626

2727
```julia
28-
du = Operation[p₁ * u₁ - (p₂ * u₁) * u₂, -p₃ * u₂ + (p₄ * u₁) * u₂]
28+
du = Num[p₁ * u₁ - (p₂ * u₁) * u₂, -p₃ * u₂ + (p₄ * u₁) * u₂]
2929
```
3030

3131
Now we build the equations we want to solve:

docs/src/tutorials/ode_modeling.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ eqs = [D(x) ~ σ*(y-x),
6969
D(z) ~ x*y - β*z]
7070
```
7171

72-
Each operation builds an `Operation` type, and thus `eqs` is an array of
73-
`Operation` and `Variable`s. This holds a tree of the full system that can be
72+
Each operation builds an `Term` type, and thus `eqs` is an array of
73+
`Term` and `Sym`s (possibly wrapped in Num). This holds a tree of the full system that can be
7474
analyzed by other programs. We can turn this into a `ODESystem` via:
7575

7676
```julia

docs/src/tutorials/symbolic_functions.md

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ The way to define symbolic variables is via the `@variables` macro:
88
```
99

1010
After defining variables as symbolic, symbolic expressions, which we
11-
call an `Operation`, can be generated by utilizing Julia expressions.
11+
call a `Term`, can be generated by utilizing Julia expressions.
1212
For example:
1313

1414
```julia
1515
z = x^2 + y
1616
```
1717

18-
Here, `z` is the `Operation` for "square `x` and add `y`". To
18+
Here, `z` is the `Term` for "square `x` and add `y`". To
1919
make an array of symbolic expressions, simply make an array of
2020
symbolic expressions:
2121

@@ -24,12 +24,14 @@ A = [x^2+y 0 2x
2424
0 0 2y
2525
y^2+x 0 0]
2626

27-
3×3 Array{Expression,2}:
28-
x ^ 2 + y Constant(0) 2x
29-
Constant(0) Constant(0) 2y
30-
y ^ 2 + x Constant(0) Constant(0)
27+
3×3 Array{Num,2}:
28+
x ^ 2 + y 0 2x
29+
0 0 2y
30+
y ^ 2 + x 0 0
3131
```
3232

33+
Note that by default, `@variables` returns `Sym` or `Term` objects wrapped in `Num` in order to make them behave like subtypes of `Real`. Any operation on these `Num` objects will return a new `Num` object, wrapping the result of computing symbolically on the underlying values.
34+
3335
To better view the results, we can use [Latexify.jl](https://github.com/korsbo/Latexify.jl).
3436
ModelingToolkit.jl comes with Latexify recipes so it works automatically:
3537

@@ -42,9 +44,9 @@ latexify(A)
4244
\begin{equation}
4345
\left[
4446
\begin{array}{ccc}
45-
x ^ 2 + y & ModelingToolkit.Constant(0) & 2x \\
46-
ModelingToolkit.Constant(0) & ModelingToolkit.Constant(0) & 2y \\
47-
y ^ 2 + x & ModelingToolkit.Constant(0) & ModelingToolkit.Constant(0) \\
47+
(x ^ 2) + y & 0 & 2 * x \\
48+
0 & 0 & 2 * y \\
49+
(y ^ 2) + x & 0 & 0 \\
4850
\end{array}
4951
\right]
5052
\end{equation}
@@ -57,11 +59,11 @@ want to create the sparse version of `A` we would just call `sparse`:
5759
using SparseArrays
5860
spA = sparse(A)
5961

60-
3×3 SparseMatrixCSC{Expression,Int64} with 4 stored entries:
61-
[1, 1] = x ^ 2 + y
62-
[3, 1] = y ^ 2 + x
63-
[1, 3] = 2x
64-
[2, 3] = 2y
62+
3×3 SparseMatrixCSC{Num,Int64} with 4 stored entries:
63+
[1, 1] = (x ^ 2) + y
64+
[3, 1] = (y ^ 2) + x
65+
[1, 3] = 2 * x
66+
[2, 3] = 2 * y
6567
```
6668

6769
We can thus use normal Julia functions as generators for sparse
@@ -73,7 +75,7 @@ function f(u)
7375
end
7476
f([x,y,z]) # Recall that z = x^2 + y
7577

76-
3-element Array{Operation,1}:
78+
3-element Array{Num,1}:
7779
x - (x ^ 2 + y)
7880
x ^ 2 - y
7981
(x ^ 2 + y) + y
@@ -85,7 +87,7 @@ Or we can build array variables and use these to trace:
8587
@variables u[1:3]
8688
f(u)
8789

88-
3-element Array{Operation,1}:
90+
3-element Array{Num,1}:
8991
u₁ - u₃
9092
u₁ ^ 2 - u₂
9193
u₃ + u₂
@@ -178,7 +180,7 @@ a function via a sparse matrix. For example:
178180
N = 8
179181
A = sparse(Tridiagonal([x^i for i in 1:N-1],[x^i * y^(8-i) for i in 1:N], [y^i for i in 1:N-1]))
180182

181-
8×8 SparseMatrixCSC{Operation,Int64} with 22 stored entries:
183+
8×8 SparseMatrixCSC{Num,Int64} with 22 stored entries:
182184
[1, 1] = x ^ 1 * y ^ 7
183185
[2, 1] = x ^ 1
184186
[1, 2] = y ^ 1
@@ -314,7 +316,7 @@ like:
314316
```julia
315317
ModelingToolkit.jacobian([x+x*y,x^2+y],[x,y])
316318

317-
2×2 Array{Expression,2}:
319+
2×2 Array{Num,2}:
318320
1 + y x
319321
2x Constant(1)
320322
```
@@ -338,7 +340,7 @@ This can be applied to arrays by using Julia's broadcast mechanism:
338340
B = simplify.([t^2+t+t^2 2t+4t
339341
x+y+y+2t x^2 - x^2 + y^2])
340342

341-
2×2 Array{Operation,2}:
343+
2×2 Array{Num,2}:
342344
2 * t ^ 2 + t 6t
343345
x + 2 * (t + y) y ^ 2
344346
```
@@ -348,7 +350,7 @@ We can then use `substitute` to change values of an expression around:
348350
```julia
349351
simplify.(substitute.(B,[x=>y^2]))
350352

351-
2×2 Array{Operation,2}:
353+
2×2 Array{Num,2}:
352354
2 * t ^ 2 + t 6t
353355
y ^ 2 + 2 * (t + y) y ^ 2
354356
```
@@ -380,8 +382,8 @@ the user's code. For these cases, ModelingToolkit.jl allows for fully
380382
macro-free usage. For example:
381383

382384
```julia
383-
x = Variable{Float64}(:x)()
384-
y = Variable{Float64}(:y)()
385+
x = Sym{Float64}(:x)()
386+
y = Sym{Float64}(:y)()
385387
x+y^2.0
386388
```
387389

@@ -396,23 +398,17 @@ convert the output to an `Expr`:
396398
Expr(x+y^2)
397399
```
398400

399-
## Variables as Operations
400-
401-
`Operation` is the type name the ModelingToolkit.jl gives to symbolic
402-
expressions. In ModelingToolkit.jl, essentially everything is an
403-
`Operation`. Notice that when we defined our variables above, they
404-
were represented as an `Operation` as well, which means that variables
405-
alone are an operation that can then be composed to make bigger
406-
operations.
401+
## `Sym`s and callable `Sym`s
407402

408-
But since variables are functions, we can represent their dependencies
409-
as well. For example:
403+
In the definition
410404

411405
```julia
412406
@variables t x(t) y(t)
413407
```
414408

415-
defines `t` as a dependent variable while `x(t)` and `y(t)` are
409+
`t` is of type `Sym{Real}` but the name `x` refers to an object that represents the `Term` `x(t)`. The operation of this expression is itself the object `Sym{FnType{Tuple{Real}, Real}}(:x)`. The type `Sym{FnType{...}}` represents a callable object. In this case specifically it's a function that takes 1 Real argument (noted by `Tuple{Real}`) and returns a `Real` result. You can call such a callable `Sym` with either a number or a symbolic expression of a permissible type.
410+
411+
this expression also defines `t` as a dependent variable while `x(t)` and `y(t)` are
416412
independent variables. This is accounted for in differentiation:
417413

418414
```julia

0 commit comments

Comments
 (0)