Skip to content

Commit bd097c0

Browse files
authored
AD examples (#64)
1 parent fbaf55a commit bd097c0

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "RootedTrees"
22
uuid = "47965b36-3f3e-11e9-0dcf-4570dfd42a8c"
33
authors = ["Hendrik Ranocha <mail@ranocha.de> and contributors"]
4-
version = "2.8.2"
4+
version = "2.8.3"
55

66
[deps]
77
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"

docs/Project.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
4+
SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6"
5+
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
36

47
[compat]
58
Documenter = "0.27"
9+
ForwardDiff = "0.10"
10+
SymPy = "1"
11+
Zygote = "0.6"

docs/src/tutorials/RK_order_conditions.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,73 @@ using Test
8989
end
9090
nothing # hide
9191
```
92+
93+
94+
## Symbolic computation and automatic differentiation
95+
96+
The implementation is fully generic using plain Julia code. In particular,
97+
this enables automatic differentiation (AD) and symbolic computations.
98+
99+
### Symbolic computations
100+
101+
For example, you can determine the order conditions symbolically as follows.
102+
```@example
103+
using RootedTrees, SymPy
104+
105+
s = 3 # number of stages
106+
A = [symbols("a_$(i)$(j)", real=true) for i in 1:s, j in 1:s]
107+
b = [symbols("b_$(i)", real=true) for i in 1:s]
108+
rk = RungeKuttaMethod(A, b)
109+
110+
for o in 1:3
111+
println("Order ", o)
112+
for t in RootedTreeIterator(o)
113+
println("t = ", t)
114+
println(residual_order_condition(t, rk))
115+
end
116+
println()
117+
end
118+
119+
nothing # hide
120+
```
121+
122+
### Automatic differentiation
123+
124+
The order conditions can be differentiated with respect to the Runge-Kutta
125+
coefficients. For example, we can use
126+
[ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) and
127+
[Zygote.jl](https://github.com/FluxML/Zygote.jl)
128+
as follows.
129+
130+
```@example AD-Jacobian
131+
using RootedTrees, ForwardDiff, Zygote
132+
133+
# collect all rooted trees up to order 4
134+
trees = [copy(t) for o in 1:4 for t in RootedTreeIterator(o)]
135+
136+
# classical RK4 method
137+
A = [0 0 0 0; 1//2 0 0 0; 0 1//2 0 0; 0 0 1 0]
138+
b = [1//6, 1//3, 1//3, 1//6]
139+
coeffs = vcat(vec(A), vec(b)) # one vector of all parameters
140+
141+
function all_order_conditions(trees, coeffs)
142+
# extract Butcher coefficients from the vector of all coefficients
143+
# for an RK method with four stages
144+
A = reshape(view(coeffs, 1:16), 4, 4)
145+
b = view(coeffs, 17:20)
146+
rk = RungeKuttaMethod(A, b)
147+
map(t -> residual_order_condition(t, rk), trees)
148+
end
149+
150+
@assert iszero(all_order_conditions(trees, coeffs)) # fourth-order accurate
151+
152+
ForwardDiff.jacobian(coeffs -> all_order_conditions(trees, coeffs), coeffs)
153+
```
154+
155+
```@example AD-Jacobian
156+
Zygote.jacobian(coeffs -> all_order_conditions(trees, coeffs), coeffs)
157+
```
158+
159+
```@example AD-Jacobian
160+
ForwardDiff.jacobian(coeffs -> all_order_conditions(trees, coeffs), coeffs) == first(Zygote.jacobian(coeffs -> all_order_conditions(trees, coeffs), coeffs))
161+
```

0 commit comments

Comments
 (0)