@@ -223,6 +223,123 @@ labels = hcat(
223223plot(wp, label=labels, markershape=:auto, title="IMEX Methods, Krylov Linsolve, Low Tolerances")
224224```
225225
226+ Krylov solvers with preconditioners.
227+ ```julia
228+ # Weighted diagonal preconditioner
229+ import LinearAlgebra as LA
230+ Base.@kwdef struct WeightedDiagonalPreconBuilder
231+ w::Float64
232+ end
233+
234+ (builder::WeightedDiagonalPreconBuilder)(A, du, u, p, t, newW, Plprev, Prprev, solverdata) = (builder.w * LA.Diagonal(convert(AbstractMatrix, A)), LA.I)
235+
236+ # Incomplete LU factorization
237+ using IncompleteLU
238+ Base.@kwdef struct IncompleteLUPreconBuilder
239+ τ::Float64
240+ end
241+ function (builder::IncompleteLUPreconBuilder)(W, du, u, p, t, newW, Plprev, Prprev, solverdata)
242+ if newW === nothing || newW
243+ Pl = ilu(convert(AbstractMatrix, W), τ = builder.τ)
244+ else
245+ Pl = Plprev
246+ end
247+ Pl, nothing
248+ end
249+
250+ # Algebraic multigrid
251+ using AlgebraicMultigrid
252+ function algebraicmultigrid(W, du, u, p, t, newW, Plprev, Prprev, solverdata)
253+ if newW === nothing || newW
254+ Pl = aspreconditioner(ruge_stuben(convert(AbstractMatrix, W)))
255+ else
256+ Pl = Plprev
257+ end
258+ Pl, nothing
259+ end
260+ function algebraicmultigrid2(W, du, u, p, t, newW, Plprev, Prprev, solverdata)
261+ if newW === nothing || newW
262+ A = convert(AbstractMatrix, W)
263+ Pl = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(A,
264+ presmoother = AlgebraicMultigrid.Jacobi(rand(size(A,
265+ 1))),
266+ postsmoother = AlgebraicMultigrid.Jacobi(rand(size(A,
267+ 1)))))
268+ else
269+ Pl = Plprev
270+ end
271+ Pl, nothing
272+ end
273+
274+ # Cholesky
275+ using Preconditioners
276+ function cholesky(W, du, u, p, t, newW, Plprev, Prprev, solverdata)
277+ W = convert(AbstractMatrix, W)
278+ if newW === nothing || newW
279+ Pl = CholeskyPreconditioner(W)
280+ else
281+ Pl = Plprev
282+ end
283+ Pl, nothing
284+ end
285+
286+ # Aliases
287+ chol = cholesky
288+ inc_lu = IncompleteLUPreconBuilder(τ = 50.0)
289+ w_diag = WeightedDiagonalPreconBuilder(w = 0.9)
290+ amg = algebraicmultigrid
291+ amg2 = algebraicmultigrid2
292+
293+ abstols = 0.1 .^ (8:13)
294+ reltols = 0.1 .^ (5:10)
295+ N = length(abstols)
296+ setups = [
297+ # Dict(:alg => KenCarp3(linsolve=KrylovJL_GMRES(), :dts => 1e-2 * ones(N), :adaptive => true),
298+ # Dict(:alg => KenCarp4(linsolve=KrylovJL_GMRES(), :dts => 1e-2 * ones(N), :adaptive => true),
299+ # Dict(:alg => KenCarp5(linsolve=KrylovJL_GMRES(), :dts => 1e-2 * ones(N), :adaptive => true),
300+ Dict(:alg => KenCarp3(linsolve=KrylovJL_GMRES(), precs = inc_lu, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
301+ Dict(:alg => KenCarp4(linsolve=KrylovJL_GMRES(), precs = inc_lu, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
302+ Dict(:alg => KenCarp5(linsolve=KrylovJL_GMRES(), precs = inc_lu, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
303+ Dict(:alg => KenCarp3(linsolve=KrylovJL_GMRES(), precs = w_diag, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
304+ Dict(:alg => KenCarp4(linsolve=KrylovJL_GMRES(), precs = w_diag, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
305+ Dict(:alg => KenCarp5(linsolve=KrylovJL_GMRES(), precs = w_diag, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
306+ Dict(:alg => KenCarp3(linsolve=KrylovJL_GMRES(), precs = amg, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
307+ Dict(:alg => KenCarp4(linsolve=KrylovJL_GMRES(), precs = amg, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
308+ Dict(:alg => KenCarp5(linsolve=KrylovJL_GMRES(), precs = amg, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
309+ Dict(:alg => KenCarp3(linsolve=KrylovJL_GMRES(), precs = amg2, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
310+ Dict(:alg => KenCarp4(linsolve=KrylovJL_GMRES(), precs = amg2, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
311+ Dict(:alg => KenCarp5(linsolve=KrylovJL_GMRES(), precs = amg2, concrete_jac = true), :dts => 1e-2 * ones(N), :adaptive => true),
312+ Dict(:alg => KenCarp3(linsolve=KrylovJL_GMRES()), :dts => 1e-2 * ones(N), :adaptive => true),
313+ Dict(:alg => KenCarp4(linsolve=KrylovJL_GMRES()), :dts => 1e-2 * ones(N), :adaptive => true),
314+ Dict(:alg => KenCarp5(linsolve=KrylovJL_GMRES()), :dts => 1e-2 * ones(N), :adaptive => true),
315+ ]
316+ labels = hcat(
317+ # "KenCarp3 (Cholesky)",
318+ # "KenCarp4 (Cholesky)",
319+ # "KenCarp5 (Cholesky)",
320+ "KenCarp3 (ILU, τ = $(inc_lu.τ))",
321+ "KenCarp4 (ILU, τ = $(inc_lu.τ))",
322+ "KenCarp5 (ILU, τ = $(inc_lu.τ))",
323+ "KenCarp3 (Diagonal, w = $(w_diag.w))",
324+ "KenCarp4 (Diagonal, w = $(w_diag.w))",
325+ "KenCarp5 (Diagonal, w = $(w_diag.w))",
326+ "KenCarp3 (AMG)",
327+ "KenCarp4 (AMG)",
328+ "KenCarp5 (AMG)",
329+ "KenCarp3 (AMG-Jacobi)",
330+ "KenCarp4 (AMG-Jacobi)",
331+ "KenCarp5 (AMG-Jacobi)",
332+ "KenCarp3 (Identity)",
333+ "KenCarp4 (Identity)",
334+ "KenCarp5 (Identity)",
335+ )
336+ @time wp = WorkPrecisionSet(prob, abstols, reltols, setups;
337+ print_names=true, names=labels, numruns=5, error_estimate=:l2,
338+ save_everystep=false, appxsol=test_sol, maxiters=Int(1e5));
339+
340+ plot(wp, label=labels, markershape=:auto, title="IMEX Methods, Krylov Linsolve, Low Tolerances")
341+ ```
342+
226343#### Exponential Integrators
227344
228345```julia
0 commit comments