Skip to content

Commit b7dc0b9

Browse files
Adjoint for non-linear solve
Using SGJ notes. Co-authored-by: Sri Hari Krishna Narayanan <[email protected]>
1 parent 47be4af commit b7dc0b9

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

examples/simple_adjoint.jl

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
## Simple 2D example from (Kelley2003)[@cite]
2+
3+
using NewtonKrylov, LinearAlgebra
4+
using CairoMakie
5+
6+
function F!(res, x, p)
7+
res[1] = p[1] * x[1]^2 + p[2] * x[2]^2 - 2
8+
return res[2] = exp(p[1] * x[1] - 1) + p[2] * x[2]^2 - 2
9+
end
10+
11+
function F(x, p)
12+
res = similar(x)
13+
F!(res, x, p)
14+
return res
15+
end
16+
17+
p = [1.0, 1.3, 1.0]
18+
19+
xs = LinRange(-3, 8, 1000)
20+
ys = LinRange(-15, 10, 1000)
21+
22+
levels = [0.1, 0.25, 0.5:2:10..., 10.0:10:200..., 200:100:4000...]
23+
24+
fig, ax = contour(xs, ys, (x, y) -> norm(F([x, y], p)); levels)
25+
26+
27+
x₀ = [2.0, 0.5]
28+
x, stats = newton_krylov((u) -> F(u, p), x₀)
29+
30+
const= [1.0000001797004159, 1.0000001140397106]
31+
32+
function g(x, p)
33+
return sum(abs2, x .- x̂)
34+
end
35+
36+
g(x, p)
37+
38+
using Enzyme
39+
40+
function dg_p(x, p)
41+
dp = Enzyme.make_zero(p)
42+
Enzyme.autodiff(Enzyme.Reverse, g, Const(x), Duplicated(p, dp))
43+
return dp
44+
end
45+
46+
gₚ = dg_p(x, p)
47+
48+
function dg_x(x, p)
49+
dx = Enzyme.make_zero(x)
50+
Enzyme.autodiff(Enzyme.Reverse, g, Duplicated(x, dx), Const(p))
51+
return dx
52+
end
53+
54+
gₓ = dg_x(x, p)
55+
56+
Fₚ = Enzyme.jacobian(Enzyme.Reverse, p -> F(x, p), p) |> only
57+
58+
Jᵀ = Enzyme.jacobian(Enzyme.Reverse, u -> F(u, p), x) |> only
59+
60+
q = Jᵀ \ gₓ
61+
62+
gₚ - reshape(transpose(q) * Fₚ, :)
63+
64+
function everything_all_at_once(p)
65+
x₀ = [2.0, 0.5]
66+
x, _ = newton_krylov((u) -> F(u, p), x₀)
67+
return g(x, p)
68+
end
69+
70+
everything_all_at_once(p)
71+
Enzyme.gradient(Enzyme.Reverse, everything_all_at_once, p)

0 commit comments

Comments
 (0)