Skip to content

Commit a700dab

Browse files
Merge branch 'main' of github.com:gridap/GridapP4est.jl into facet_integration_non_conforming_meshes
2 parents 6e73860 + 368c559 commit a700dab

6 files changed

+295
-29
lines changed

Project.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "GridapP4est"
22
uuid = "c2c8e14b-f5fd-423d-9666-1dd9ad120af9"
33
authors = ["Alberto F. Martin <alberto.f.martin@anu.edu.au>"]
4-
version = "0.3.6"
4+
version = "0.3.7"
55

66
[deps]
77
ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"
@@ -17,8 +17,8 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1717
[compat]
1818
ArgParse = "1"
1919
FillArrays = "0.8.4, 0.9, 0.10, 0.11, 0.12, 1"
20-
Gridap = "0.17.22, 0.18"
21-
GridapDistributed = "0.3.1, 0.4"
20+
Gridap = "0.18.2"
21+
GridapDistributed = "0.4"
2222
MPI = "0.20"
2323
P4est_wrapper = "0.2.2"
2424
PartitionedArrays = "0.3.3"

src/FESpaces.jl

+27-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2+
const LagragianOrNedelec =
3+
Union{Tuple{Gridap.ReferenceFEs.Lagrangian,Any,Any},Tuple{Gridap.ReferenceFEs.Nedelec,Any,Any}}
4+
15
function _generate_ref_constraints(modelH,modelh,cell_reffe)
26
VH=TestFESpace(modelH,cell_reffe)
37
Vh=TestFESpace(modelh,cell_reffe)
@@ -31,7 +35,7 @@ end
3135

3236
function _build_constraint_coefficients_matrix_in_ref_space(::PXestUniformRefinementRuleType,
3337
Dc,
34-
reffe::Tuple{<:Lagrangian,Any,Any})
38+
reffe::LagragianOrNedelec)
3539
cell_polytope = Dc == 2 ? QUAD : HEX
3640
basis, reffe_args, reffe_kwargs = reffe
3741
cell_reffe = ReferenceFE(cell_polytope, basis, reffe_args...; reffe_kwargs...)
@@ -94,7 +98,7 @@ function _fill_face_subface_ldof_to_cell_ldof!(face_subface_ldof_to_cell_ldof,
9498
end
9599

96100
function _generate_face_subface_ldof_to_cell_ldof(ref_rule::PXestUniformRefinementRuleType,
97-
Df,Dc,reffe::Tuple{<:Lagrangian,Any,Any})
101+
Df,Dc,reffe::LagragianOrNedelec)
98102

99103
cell_polytope = (Dc == 2) ? QUAD : HEX
100104
_coarse_faces_to_child_ids = coarse_faces_to_child_ids(ref_rule,Df,Dc)
@@ -276,9 +280,6 @@ function coarse_faces_to_child_ids(::PXestVerticalRefinementRuleType,Df,Dc)
276280
end
277281
end
278282

279-
280-
281-
282283
function coarse_faces_to_child_ids(::PXestHorizontalRefinementRuleType,Df,Dc)
283284
@assert Dc==3
284285
if (Df==2)
@@ -419,7 +420,10 @@ function _restrict_face_dofs_to_face_dim(cell_reffe,Df)
419420
first_face = Gridap.ReferenceFEs.get_offset(polytope,Df)+1
420421
face_own_dofs=get_face_own_dofs(cell_reffe)
421422
first_face_faces = Gridap.ReferenceFEs.get_faces(polytope)[first_face]
422-
face_dofs_to_face_dim = face_own_dofs[first_face_faces]
423+
face_dofs_to_face_dim = Vector{Vector{Int}}()
424+
for face in first_face_faces
425+
push!(face_dofs_to_face_dim,copy(face_own_dofs[face]))
426+
end
423427
touched=Dict{Int,Int}()
424428
dofs=Int64[]
425429
current=1
@@ -612,7 +616,22 @@ end
612616
function get_face_dofs_permutations(
613617
reffe::Gridap.ReferenceFEs.GenericRefFE{Gridap.ReferenceFEs.RaviartThomas, Dc},Df::Integer) where Dc
614618
first_face = get_offset(get_polytope(reffe),Df)
615-
order = length(get_face_dofs(reffe)[first_face])-1
619+
order = length(get_face_dofs(reffe)[first_face+1])-1
620+
nfaces=num_faces(reffe,Df)
621+
if (Df==Dc-1)
622+
facet_polytope = Dc == 2 ? SEGMENT : QUAD
623+
nodes, _ = Gridap.ReferenceFEs.compute_nodes(facet_polytope, [order for i = 1:Dc-1])
624+
Fill(Gridap.ReferenceFEs._compute_node_permutations(facet_polytope, nodes),nfaces)
625+
elseif (Dc == 3 && Df==1)
626+
nodes, _ = Gridap.ReferenceFEs.compute_nodes(SEGMENT, [order for i = 1:Dc-2])
627+
Fill(Gridap.ReferenceFEs._compute_node_permutations(SEGMENT, nodes),nfaces)
628+
end
629+
end
630+
631+
function get_face_dofs_permutations(
632+
reffe::Gridap.ReferenceFEs.GenericRefFE{Gridap.ReferenceFEs.Nedelec, Dc},Df::Integer) where Dc
633+
first_face = get_offset(get_polytope(reffe),Df)
634+
order = length(get_face_dofs(reffe)[first_face+1])-1
616635
nfaces=num_faces(reffe,Df)
617636
if (Df==Dc-1)
618637
facet_polytope = Dc == 2 ? SEGMENT : QUAD
@@ -897,7 +916,7 @@ end
897916
# Generates a new DistributedSingleFieldFESpace composed
898917
# by local FE spaces with linear multipoint constraints added
899918
function Gridap.FESpaces.FESpace(model::OctreeDistributedDiscreteModel{Dc},
900-
reffe::Tuple{Gridap.ReferenceFEs.Lagrangian,Any,Any};
919+
reffe::LagragianOrNedelec;
901920
kwargs...) where {Dc}
902921
spaces_wo_constraints = map(local_views(model)) do m
903922
FESpace(m, reffe; kwargs...)

test/DarcyNonConformingOctreeModelsTests.jl

+4-18
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ module DarcyNonConformingOctreeModelsTests
142142
dΩh = Measure(trian,degree)
143143

144144
el2 = sqrt(sum( ( ee )*dΩh ))
145-
tol=1e-7
145+
tol=1e-6
146146
@assert el2 < tol
147147
end
148148

@@ -247,25 +247,11 @@ module DarcyNonConformingOctreeModelsTests
247247
ep_l2 = l2(ep)
248248
ep_h1 = h1(ep)
249249

250-
tol = 1.0e-9
250+
tol = 1.0e-6
251251
@test eu_l2 < tol
252252
@test ep_l2 < tol
253253
@test ep_h1 < tol
254-
end
255-
256-
function driver(ranks,coarse_model,order)
257-
model=OctreeDistributedDiscreteModel(ranks,coarse_model,1)
258-
ref_coarse_flags=map(ranks,partition(get_cell_gids(model.dmodel))) do rank,indices
259-
flags=zeros(Cint,length(indices))
260-
flags.=nothing_flag
261-
#flags[1:2^2].=coarsen_flag
262-
flags[own_length(indices)]=refine_flag
263-
flags
264-
end
265-
fmodel,glue=Gridap.Adaptivity.adapt(model,ref_coarse_flags)
266-
xh,Xh = solve_darcy(fmodel,order)
267-
check_error_darcy(fmodel,order,xh)
268-
end
254+
end
269255

270256
function run(distribute)
271257
# debug_logger = ConsoleLogger(stderr, Logging.Debug)
@@ -276,7 +262,7 @@ module DarcyNonConformingOctreeModelsTests
276262
order=1
277263
test_2d(ranks,order)
278264

279-
order=1
265+
order=2
280266
test_3d(ranks,order)
281267
end
282268
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
module MaxwellNonConformingOctreeModelsTests
2+
using P4est_wrapper
3+
using GridapP4est
4+
using Gridap
5+
using PartitionedArrays
6+
using GridapDistributed
7+
using MPI
8+
using Gridap.FESpaces
9+
using FillArrays
10+
using Logging
11+
using Test
12+
13+
function test_transfer_ops_and_redistribute(ranks,
14+
dmodel::GridapDistributed.DistributedDiscreteModel{Dc},
15+
order) where Dc
16+
ref_coarse_flags=map(ranks,partition(get_cell_gids(dmodel.dmodel))) do rank,indices
17+
flags=zeros(Cint,length(indices))
18+
flags.=nothing_flag
19+
20+
flags[1]=refine_flag
21+
flags[own_length(indices)]=refine_flag
22+
23+
# To create some unbalance
24+
if (rank%2==0 && own_length(indices)>1)
25+
flags[div(own_length(indices),2)]=refine_flag
26+
end
27+
flags
28+
end
29+
fmodel,glue=Gridap.Adaptivity.adapt(dmodel,ref_coarse_flags);
30+
31+
# Solve coarse
32+
uH,UH=solve_maxwell(dmodel,order)
33+
check_error_maxwell(dmodel,order,uH)
34+
35+
# Solve fine
36+
uh,Uh=solve_maxwell(fmodel,order)
37+
check_error_maxwell(fmodel,order,uh)
38+
39+
Ωh = Triangulation(fmodel)
40+
degree = 2*(order+1)
41+
dΩh = Measure(Ωh,degree)
42+
43+
# prolongation via interpolation
44+
uHh=interpolate(uH,Uh)
45+
e = uh - uHh
46+
el2 = sqrt(sum( ( ee )*dΩh ))
47+
tol=1e-6
48+
println("[INTERPOLATION] el2 < tol: $(el2) < $(tol)")
49+
@assert el2 < tol
50+
51+
# prolongation via L2-projection
52+
# Coarse FEFunction -> Fine FEFunction, by projection
53+
ahp(u,v) = (vu)*dΩh
54+
lhp(v) = (vuH)*dΩh
55+
oph = AffineFEOperator(ahp,lhp,Uh,Uh)
56+
uHh = solve(oph)
57+
e = uh - uHh
58+
el2 = sqrt(sum( ( ee )*dΩh ))
59+
println("[L2 PROJECTION] el2 < tol: $(el2) < $(tol)")
60+
@assert el2 < tol
61+
62+
# restriction via interpolation
63+
uhH=interpolate(uh,UH)
64+
e = uH - uhH
65+
el2 = sqrt(sum( ( ee )*dΩh ))
66+
println("[INTERPOLATION] el2 < tol: $(el2) < $(tol)")
67+
@assert el2 < tol
68+
69+
# restriction via L2-projection
70+
ΩH = Triangulation(dmodel)
71+
degree = 2*(order+1)
72+
dΩH = Measure(ΩH,degree)
73+
74+
dΩhH = Measure(ΩH,Ωh,2*order)
75+
aHp(u,v) = (vu)*dΩH
76+
lHp(v) = (vuh)*dΩhH
77+
oph = AffineFEOperator(aHp,lHp,UH,UH)
78+
uhH = solve(oph)
79+
e = uH - uhH
80+
el2 = sqrt(sum( ( ee )*dΩH ))
81+
82+
fmodel_red, red_glue=GridapDistributed.redistribute(fmodel);
83+
uh_red,Uh_red=solve_maxwell(fmodel_red,order)
84+
check_error_maxwell(fmodel_red,order,uh_red)
85+
86+
trian = Triangulation(fmodel_red)
87+
degree = 2*(order+1)
88+
dΩhred = Measure(trian,degree)
89+
90+
u_ex, f_ex=get_analytical_functions(Dc)
91+
92+
uhred2 = GridapDistributed.redistribute_fe_function(uh,Uh_red,fmodel_red,red_glue)
93+
94+
e = u_ex - uhred2
95+
el2 = sqrt(sum( ( ee )*dΩhred ))
96+
println("[REDISTRIBUTE SOLUTION] el2 < tol: $(el2) < $(tol)")
97+
@assert el2 < tol
98+
99+
fmodel_red
100+
end
101+
102+
function test_refine_and_coarsen_at_once(ranks,
103+
dmodel::OctreeDistributedDiscreteModel{Dc},
104+
order) where Dc
105+
degree = 2*order+1
106+
ref_coarse_flags=map(ranks,partition(get_cell_gids(dmodel.dmodel))) do rank,indices
107+
flags=zeros(Cint,length(indices))
108+
flags.=nothing_flag
109+
if (rank==1)
110+
flags[1:min(2^Dc,own_length(indices))].=coarsen_flag
111+
end
112+
flags[own_length(indices)]=refine_flag
113+
flags
114+
end
115+
fmodel,glue=Gridap.Adaptivity.adapt(dmodel,ref_coarse_flags);
116+
117+
# Solve coarse
118+
uH,UH=solve_maxwell(dmodel,order)
119+
check_error_maxwell(dmodel,order,uH)
120+
121+
# Solve fine
122+
uh,Uh=solve_maxwell(fmodel,order)
123+
check_error_maxwell(fmodel,order,uh)
124+
125+
# # prolongation via interpolation
126+
uHh=interpolate(uH,Uh)
127+
e = uh - uHh
128+
129+
trian = Triangulation(fmodel)
130+
degree = 2*(order+1)
131+
dΩh = Measure(trian,degree)
132+
133+
el2 = sqrt(sum( ( ee )*dΩh ))
134+
tol=1e-6
135+
@assert el2 < tol
136+
end
137+
138+
function test_2d(ranks,order)
139+
coarse_model=CartesianDiscreteModel((0,1,0,1),(1,1))
140+
dmodel=OctreeDistributedDiscreteModel(ranks,coarse_model,1)
141+
test_refine_and_coarsen_at_once(ranks,dmodel,order)
142+
rdmodel=dmodel
143+
for i=1:5
144+
rdmodel=test_transfer_ops_and_redistribute(ranks,rdmodel,order)
145+
end
146+
end
147+
148+
function test_3d(ranks,order)
149+
coarse_model=CartesianDiscreteModel((0,1,0,1,0,1),(2,2,2))
150+
dmodel=OctreeDistributedDiscreteModel(ranks,coarse_model,0)
151+
test_refine_and_coarsen_at_once(ranks,dmodel,order)
152+
rdmodel=dmodel
153+
for i=1:5
154+
rdmodel=test_transfer_ops_and_redistribute(ranks,rdmodel,order)
155+
end
156+
end
157+
158+
u_ex_2D((x,y)) = 2*VectorValue(-y,x)
159+
f_ex_2D(x) = u_ex_2D(x)
160+
u_ex_3D((x,y,z)) = 2*VectorValue(-y,x,0.) - VectorValue(0.,-z,y)
161+
f_ex_3D(x) = u_ex_3D(x)
162+
163+
function get_analytical_functions(Dc)
164+
if Dc==2
165+
return u_ex_2D, f_ex_2D
166+
else
167+
@assert Dc==3
168+
return u_ex_3D, f_ex_3D
169+
end
170+
end
171+
172+
include("CoarseDiscreteModelsTools.jl")
173+
174+
function solve_maxwell(model::GridapDistributed.DistributedDiscreteModel{Dc},order) where {Dc}
175+
u_ex, f_ex=get_analytical_functions(Dc)
176+
177+
V = FESpace(model,
178+
ReferenceFE(nedelec,order),
179+
conformity=:Hcurl,
180+
dirichlet_tags="boundary")
181+
182+
U = TrialFESpace(V,u_ex)
183+
184+
trian = Triangulation(model)
185+
degree = 2*(order+1)
186+
= Measure(trian,degree)
187+
188+
a(u,v) = ( (∇×u)(∇×v) + uv )dΩ
189+
l(v) = (f_exv)dΩ
190+
191+
op = AffineFEOperator(a,l,U,V)
192+
if (num_free_dofs(U)==0)
193+
# UMFPACK cannot handle empty linear systems
194+
uh = zero(U)
195+
else
196+
uh = solve(op)
197+
end
198+
199+
# uh_ex=interpolate(u_ex_3D,U)
200+
# map(local_views(get_free_dof_values(uh_ex)), local_views(op.op.matrix), local_views(op.op.vector)) do U_ex, A, b
201+
# r_ex = A*U_ex - b
202+
# println(r_ex)
203+
# end
204+
uh,U
205+
end
206+
207+
function check_error_maxwell(model::GridapDistributed.DistributedDiscreteModel{Dc},order,uh) where {Dc}
208+
trian = Triangulation(model)
209+
degree = 2*(order+1)
210+
= Measure(trian,degree)
211+
212+
u_ex, f_ex = get_analytical_functions(Dc)
213+
214+
eu = u_ex - uh
215+
216+
l2(v) = sqrt(sum((vv)*dΩ))
217+
hcurl(v) = sqrt(sum((vv + (∇×v)(∇×v))*dΩ))
218+
219+
eu_l2 = l2(eu)
220+
eu_hcurl = hcurl(eu)
221+
222+
tol = 1.0e-6
223+
@test eu_l2 < tol
224+
@test eu_hcurl < tol
225+
end
226+
227+
function run(distribute)
228+
# debug_logger = ConsoleLogger(stderr, Logging.Debug)
229+
# global_logger(debug_logger); # Enable the debug logger globally
230+
np = MPI.Comm_size(MPI.COMM_WORLD)
231+
ranks = distribute(LinearIndices((np,)))
232+
233+
for order=0:2
234+
test_2d(ranks,order)
235+
end
236+
237+
for order=0:2
238+
test_3d(ranks,order)
239+
end
240+
end
241+
end

0 commit comments

Comments
 (0)