@@ -15,46 +15,98 @@ parameters looks like this:
1515
1616
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
2024module Example301_PoissonProblem
2125
2226using ExtendableFEM
2327using 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
2941end
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
5284end
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
60112end # module
0 commit comments