|
| 1 | +# BVP from Solving Nonlinear Equations with Iterative Methods: |
| 2 | + |
| 3 | +using NewtonKrylov, Krylov, LinearAlgebra |
| 4 | + |
| 5 | +function Phi(t, tdag, vp, v) |
| 6 | + phi = 4.0 * tdag * vp + (t * v - 1.0) * v |
| 7 | + return phi |
| 8 | +end |
| 9 | + |
| 10 | +function Fbvp!(res, U, force, tv, tvdag, h, n) |
| 11 | + @assert 2n == length(U) |
| 12 | + res[1] = U[2] |
| 13 | + res[2n] = U[2n - 1] |
| 14 | + v = view(U, 1:2:(2n - 1)) |
| 15 | + vp = view(U, 2:2:2n) |
| 16 | + force .= Phi.(tv, tvdag, vp, v) |
| 17 | + h2 = 0.5 * h |
| 18 | + @inbounds @simd for ip in 1:(n - 1) |
| 19 | + res[2 * ip + 1] = v[ip + 1] - v[ip] - h2 * (vp[ip] + vp[ip + 1]) |
| 20 | + res[2 * ip] = vp[ip + 1] - vp[ip] + h2 * (force[ip] + force[ip + 1]) |
| 21 | + end |
| 22 | + return nothing |
| 23 | +end |
| 24 | + |
| 25 | +function BVP_U0!(U0, n, tv) |
| 26 | + view(U0, 1:2:(2n - 1)) .= exp.(-0.1 .* tv .* tv) |
| 27 | + return view(U0, 2:2:2n) .= -0.2 .* view(U0, 1:2:(2n - 1)) .* tv |
| 28 | +end |
| 29 | + |
| 30 | +struct GmresPreconditioner{JOp} |
| 31 | + J::JOp |
| 32 | + itmax::Int |
| 33 | +end |
| 34 | + |
| 35 | +function LinearAlgebra.mul!(y, P::GmresPreconditioner, x) |
| 36 | + sol, _ = gmres(P.J, x; P.itmax) |
| 37 | + return copyto!(y, sol) |
| 38 | +end |
| 39 | + |
| 40 | +function BVP_solve(n = 801, T = Float64) |
| 41 | + U0 = zeros(T, 2n) |
| 42 | + res = zeros(T, 2n) |
| 43 | + |
| 44 | + h = 20.0 / (n - 1) |
| 45 | + tv = collect(0:h:20.0) |
| 46 | + |
| 47 | + tvdag = collect(0:h:20.0) |
| 48 | + @views tvdag[2:n] .= (1.0 ./ tv[2:n]) |
| 49 | + |
| 50 | + force = zeros(n) |
| 51 | + |
| 52 | + BVP_U0!(U0, n, tv) |
| 53 | + F!(res, u) = Fbvp!(res, u, force, tv, tvdag, h, n) |
| 54 | + |
| 55 | + bvpout, stats = newton_krylov!( |
| 56 | + F!, U0, res, |
| 57 | + Solver = FgmresSolver, |
| 58 | + N = (J) -> GmresPreconditioner(J, 30), |
| 59 | + ) |
| 60 | + return (; bvpout, tv, stats) |
| 61 | +end |
| 62 | + |
| 63 | +BVP_solve() |
0 commit comments