Skip to content

Commit 99e2d97

Browse files
committed
suggested changes to Example301 to demonstrate iterative solvers
1 parent 7281df1 commit 99e2d97

File tree

1 file changed

+67
-15
lines changed

1 file changed

+67
-15
lines changed

examples/Example301_PoissonProblem.jl

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,46 +15,98 @@ parameters looks like this:
1515
1616
![](example301.png)
1717
18+
This examples uses an iterative solver with an IncompleteLU preconditioner as the default solver.
19+
It can be changed via the arguments 'method_linear' and 'precon_linear', see the runtests function
20+
for more examples.
21+
1822
=#
1923

2024
module Example301_PoissonProblem
2125

2226
using ExtendableFEM
2327
using ExtendableGrids
24-
using Test #hide
28+
using LinearSolve
29+
using IncompleteLU
30+
using LinearAlgebra
31+
using Test
32+
33+
function f!(result, qpinfo)
34+
result[1] = qpinfo.params[1]*(1.7^2 + 3.9^2)*sin(1.7*qpinfo.x[1])*cos(3.9*qpinfo.x[2])
35+
return nothing
36+
end
2537

26-
function f!(fval, qpinfo)
27-
fval[1] = qpinfo.x[1] * qpinfo.x[2] * qpinfo.x[3]
38+
function u!(result, qpinfo)
39+
result[1] = sin(1.7*qpinfo.x[1])*cos(3.9*qpinfo.x[2])
2840
return nothing
2941
end
3042

31-
function main(; μ = 1.0, nrefs = 3, Plotter = nothing, kwargs...)
43+
function main(;
44+
μ = 1.0,
45+
nrefs = 4,
46+
method_linear = KrylovJL_GMRES(),
47+
precon_linear = method_linear == KrylovJL_GMRES() ? IncompleteLU.ilu : nothing,
48+
Plotter = nothing,
49+
kwargs...)
3250

3351
## problem description
3452
PD = ProblemDescription()
3553
u = Unknown("u"; name = "potential")
3654
assign_unknown!(PD, u)
37-
assign_operator!(PD, BilinearOperator([grad(u)]; factor = μ, kwargs...))
38-
assign_operator!(PD, LinearOperator(f!, [id(u)]; kwargs...))
39-
assign_operator!(PD, HomogeneousBoundaryData(u; regions = 1:4))
55+
assign_operator!(PD, BilinearOperator([grad(u)]; factor = μ))
56+
assign_operator!(PD, LinearOperator(f!, [id(u)]; params = [μ]))
57+
assign_operator!(PD, InterpolateBoundaryData(u, u!; regions = 1:6))
4058

4159
## discretize
4260
xgrid = uniform_refine(grid_unitcube(Tetrahedron3D), nrefs)
4361
FES = FESpace{H1P2{1, 3}}(xgrid)
4462

4563
## solve
46-
sol = solve(PD, FES; kwargs...)
64+
sol = solve(PD, FES; method_linear, precon_linear, kwargs...)
65+
66+
## compute error
67+
function exact_error!(result, u, qpinfo)
68+
u!(result, qpinfo)
69+
result .-= u
70+
result .= result .^ 2
71+
return nothing
72+
end
73+
ErrorIntegratorExact = ItemIntegrator(exact_error!, [id(u)]; quadorder = 8)
74+
75+
## calculate error
76+
error = evaluate(ErrorIntegratorExact, sol)
77+
L2error = sqrt(sum(view(error, 1, :)))
78+
@info "L2 error = $L2error"
4779

4880
## plot
4981
plt = plot([id(u)], sol; Plotter = Plotter)
5082

51-
return sol, plt
83+
return L2error, plt
5284
end
5385

54-
generateplots = ExtendableFEM.default_generateplots(Example301_PoissonProblem, "example301.png") #hide
55-
function runtests() #hide
56-
sol, plt = main() #hide
57-
@test sum(sol.entries) 21.874305144549524 #hide
58-
return nothing #hide
59-
end #hide
86+
generateplots = ExtendableFEM.default_generateplots(Example301_PoissonProblem, "example301.png")
87+
function runtests()
88+
expected_error = 8.56e-5
89+
90+
## test direct solver
91+
L2error, plt = main(; nrefs = 4)
92+
@test L2error <= expected_error
93+
94+
## test iterative solver with IncompleteLU (fastest)
95+
method_linear = KrylovJL_GMRES()
96+
precon_linear = IncompleteLU.ilu
97+
L2error, plt = main(; method_linear, precon_linear, nrefs = 4)
98+
@test L2error <= expected_error
99+
100+
## test other iterative solvers
101+
method_linear = KrylovJL_GMRES(precs = (A, p) -> (Diagonal(A), I))
102+
precon_linear = nothing
103+
L2error, plt = main(; method_linear, precon_linear, nrefs = 4)
104+
@test L2error <= expected_error
105+
106+
## also working:
107+
## method_linear = KrylovJL_GMRES(precs = (A, p) -> (AMGCLWrap.AMGPrecon(ruge_stuben(A)), I))
108+
## method_linear = KrylovJL_GMRES(precs = (A, p) -> (AlgebraicMultigrid.aspreconditioner(ruge_stuben(A)), I))
109+
110+
return nothing
111+
end
60112
end # module

0 commit comments

Comments
 (0)