|
| 1 | +using Gridap |
| 2 | + |
| 3 | +using Test |
| 4 | +using LinearAlgebra |
| 5 | +using FillArrays, BlockArrays |
| 6 | + |
| 7 | +using Gridap |
| 8 | +using Gridap.ReferenceFEs, Gridap.Algebra, Gridap.Geometry, Gridap.FESpaces |
| 9 | +using Gridap.CellData, Gridap.MultiField, Gridap.Algebra |
| 10 | +using PartitionedArrays |
| 11 | +using GridapDistributed |
| 12 | + |
| 13 | +using GridapSolvers |
| 14 | +using GridapSolvers.LinearSolvers, GridapSolvers.MultilevelTools, GridapSolvers.PatchBasedSmoothers |
| 15 | + |
| 16 | +function get_patch_smoothers(mh,tests,biform,patch_decompositions,qdegree) |
| 17 | + patch_spaces = PatchFESpace(tests,patch_decompositions) |
| 18 | + nlevs = num_levels(mh) |
| 19 | + smoothers = map(view(tests,1:nlevs-1),patch_decompositions,patch_spaces) do tests, PD, Ph |
| 20 | + Vh = get_fe_space(tests) |
| 21 | + Ω = Triangulation(PD) |
| 22 | + dΩ = Measure(Ω,qdegree) |
| 23 | + ap = (u,v) -> biform(u,v,dΩ) |
| 24 | + patch_smoother = PatchBasedLinearSolver(ap,Ph,Vh) |
| 25 | + return RichardsonSmoother(patch_smoother,10,0.2) |
| 26 | + end |
| 27 | + return smoothers |
| 28 | +end |
| 29 | + |
| 30 | +function get_bilinear_form(mh_lev,biform,qdegree) |
| 31 | + model = get_model(mh_lev) |
| 32 | + Ω = Triangulation(model) |
| 33 | + dΩ = Measure(Ω,qdegree) |
| 34 | + return (u,v) -> biform(u,v,dΩ) |
| 35 | +end |
| 36 | + |
| 37 | +u(x) = VectorValue(x[1],-x[2]) |
| 38 | +nc = (4,4) |
| 39 | + |
| 40 | +np = (1,1) |
| 41 | +np_per_level = fill(np,2) |
| 42 | +parts = with_mpi() do distribute |
| 43 | + distribute(LinearIndices((prod(np),))) |
| 44 | +end |
| 45 | + |
| 46 | +Dc = length(nc) |
| 47 | +domain = (Dc == 2) ? (0,1,0,1) : (0,1,0,1,0,1) |
| 48 | +mh = CartesianModelHierarchy(parts,np_per_level,domain,nc) |
| 49 | +model = get_model(mh,1) |
| 50 | + |
| 51 | +order = 2 |
| 52 | +qdegree = 2*(order+1) |
| 53 | +reffe_u = ReferenceFE(lagrangian,VectorValue{Dc,Float64},order) |
| 54 | +reffe_p = ReferenceFE(lagrangian,Float64,order-1;space=:P) |
| 55 | + |
| 56 | +tests_u = TestFESpace(mh,reffe_u,dirichlet_tags="boundary"); |
| 57 | +trials_u = TrialFESpace(tests_u,u); |
| 58 | +U, V = get_fe_space(trials_u,1), get_fe_space(tests_u,1) |
| 59 | +Q = TestFESpace(model,reffe_p;conformity=:L2,constraint=:zeromean) |
| 60 | + |
| 61 | +α = 1.0 |
| 62 | +β = 1.0 |
| 63 | +Π_Qh = LocalProjectionMap(divergence,reffe_p,qdegree) |
| 64 | + |
| 65 | +biform(u,v,dΩ) = ∫(∇(v)⊙∇(u) + α*(∇⋅v)⋅Π_Qh(u) + β*(u×B)⋅(v×B))dΩ |
| 66 | + |
| 67 | +Ω = Triangulation(model) |
| 68 | +dΩ = Measure(Ω,qdegree) |
| 69 | + |
| 70 | +a(u,v) = biform(u,v,dΩ) |
| 71 | +l(v) = liform(v,dΩ) |
| 72 | +op = AffineFEOperator(a,l,X,Y) |
| 73 | +A, b = get_matrix(op), get_vector(op); |
| 74 | + |
| 75 | +biforms = map(mhl -> get_bilinear_form(mhl,biform_u,qdegree),mh) |
| 76 | +patch_decompositions = PatchDecomposition(mh) |
| 77 | +smoothers = get_patch_smoothers( |
| 78 | + mh,tests_u,biform_u,patch_decompositions,qdegree |
| 79 | +) |
| 80 | +prolongations = setup_patch_prolongation_operators( |
| 81 | + tests_u,biform_u,graddiv,qdegree |
| 82 | +) |
| 83 | +restrictions = setup_patch_restriction_operators( |
| 84 | + tests_u,prolongations,graddiv,qdegree;solver=CGSolver(JacobiLinearSolver()) |
| 85 | +) |
| 86 | +gmg = GMGLinearSolver( |
| 87 | + trials_u,tests_u,biforms, |
| 88 | + prolongations,restrictions, |
| 89 | + pre_smoothers=smoothers, |
| 90 | + post_smoothers=smoothers, |
| 91 | + coarsest_solver=LUSolver(), |
| 92 | + maxiter=4,mode=:preconditioner,verbose=i_am_main(parts) |
| 93 | +) |
| 94 | + |
| 95 | +solver_u = gmg |
| 96 | +solver_p = CGSolver(JacobiLinearSolver();maxiter=20,atol=1e-14,rtol=1.e-6,verbose=i_am_main(parts)) |
| 97 | +solver_u.log.depth = 2 |
| 98 | +solver_p.log.depth = 2 |
| 99 | + |
| 100 | +diag_blocks = [LinearSystemBlock(),BiformBlock((p,q) -> ∫(-1.0/α*p*q)dΩ,Q,Q)] |
| 101 | +bblocks = map(CartesianIndices((2,2))) do I |
| 102 | + (I[1] == I[2]) ? diag_blocks[I[1]] : LinearSystemBlock() |
| 103 | +end |
| 104 | +coeffs = [1.0 1.0; |
| 105 | + 0.0 1.0] |
| 106 | +P = BlockTriangularSolver(bblocks,[solver_u,solver_p],coeffs,:upper) |
| 107 | +solver = FGMRESSolver(20,P;atol=1e-10,rtol=1.e-12,verbose=i_am_main(parts)) |
| 108 | +ns = numerical_setup(symbolic_setup(solver,A),A) |
| 109 | + |
| 110 | +x = allocate_in_domain(A); fill!(x,0.0) |
| 111 | +solve!(x,ns,b) |
| 112 | +xh = FEFunction(X,x) |
0 commit comments