Skip to content

Commit 7e10a3a

Browse files
committed
add constructor for Linearised Nedelec space on non-conforming mesh
1 parent cf1e086 commit 7e10a3a

File tree

2 files changed

+246
-198
lines changed

2 files changed

+246
-198
lines changed

src/LinearizedFESpaces.jl

+110-89
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,121 @@
1-
function _create_ref_rule(Dc,ranks::MPIArray, num_uniform_refs)
2-
if Dc==2
3-
coarse_model=CartesianDiscreteModel((0,1,0,1),(1,1))
4-
else
5-
@assert Dc==3
6-
coarse_model=CartesianDiscreteModel((0,1,0,1,0,1),(1,1,1))
7-
end
8-
new_comm=MPI.Comm_split(ranks.comm,MPI.Comm_rank(ranks.comm),0)
9-
new_ranks=MPIArray(1,new_comm,(1,))
10-
model_ref=OctreeDistributedDiscreteModel(new_ranks,coarse_model,num_uniform_refs)
11-
ref_rules=map(local_views(model_ref.dmodel)) do model
12-
Gridap.Adaptivity.RefinementRule(Gridap.Adaptivity.GenericRefinement(),
13-
Dc==2 ? QUAD : HEX,
14-
get_grid(model))
15-
end
16-
ref_rules.item_ref[]
17-
end
18-
19-
function _get_order(reffe::Tuple{<:Lagrangian,Any,Any})
20-
reffe[2][2]
1+
function _create_ref_rule(Dc, ranks::MPIArray, num_uniform_refs)
2+
if Dc == 2
3+
coarse_model = CartesianDiscreteModel((0, 1, 0, 1), (1, 1))
4+
else
5+
@assert Dc == 3
6+
coarse_model = CartesianDiscreteModel((0, 1, 0, 1, 0, 1), (1, 1, 1))
7+
end
8+
new_comm = MPI.Comm_split(ranks.comm, MPI.Comm_rank(ranks.comm), 0)
9+
new_ranks = MPIArray(1, new_comm, (1,))
10+
model_ref = OctreeDistributedDiscreteModel(new_ranks, coarse_model, num_uniform_refs)
11+
ref_rules = map(local_views(model_ref.dmodel)) do model
12+
Gridap.Adaptivity.RefinementRule(Gridap.Adaptivity.GenericRefinement(),
13+
Dc == 2 ? QUAD : HEX,
14+
get_grid(model))
15+
end
16+
ref_rules.item_ref[]
2117
end
2218

2319
function _create_adaptivity_glue(model::OctreeDistributedDiscreteModel{Dc},
24-
ref_model::OctreeDistributedDiscreteModel{Dc},
25-
num_uniform_refinements) where {Dc}
26-
ref_rule=_create_ref_rule(Dc,model.parts,num_uniform_refinements)
27-
num_children=Gridap.Adaptivity.num_subcells(ref_rule)
28-
cell_gids_model = get_cell_gids(model.dmodel)
29-
cell_gids_ref_model = get_cell_gids(ref_model.dmodel)
20+
ref_model::OctreeDistributedDiscreteModel{Dc},
21+
num_uniform_refinements) where {Dc}
22+
ref_rule = _create_ref_rule(Dc, model.parts, num_uniform_refinements)
23+
num_children = Gridap.Adaptivity.num_subcells(ref_rule)
24+
cell_gids_model = get_cell_gids(model.dmodel)
25+
cell_gids_ref_model = get_cell_gids(ref_model.dmodel)
3026

31-
n2o_cell_map,n2o_cell_to_child_id=map(partition(cell_gids_model),partition(cell_gids_ref_model)) do model_partition, ref_model_partition
32-
num_local_cells_model=local_length(model_partition)
33-
num_owned_cells_model=own_length(model_partition)
34-
num_local_cells_ref_model=local_length(ref_model_partition)
35-
n2o_cell_map=Vector{Int}(undef,num_local_cells_ref_model)
36-
n2o_cell_to_child_id=Vector{Int}(undef,num_local_cells_ref_model)
37-
current=1
38-
for i=1:num_owned_cells_model
39-
for j=1:num_children
40-
n2o_cell_map[current]=i
41-
n2o_cell_to_child_id[current]=j
42-
current+=1
43-
end
44-
end
45-
n2o_cell_map,n2o_cell_to_child_id
46-
end |> tuple_of_arrays
27+
n2o_cell_map, n2o_cell_to_child_id = map(partition(cell_gids_model), partition(cell_gids_ref_model)) do model_partition, ref_model_partition
28+
num_local_cells_model = local_length(model_partition)
29+
num_owned_cells_model = own_length(model_partition)
30+
num_local_cells_ref_model = local_length(ref_model_partition)
31+
n2o_cell_map = Vector{Int}(undef, num_local_cells_ref_model)
32+
n2o_cell_to_child_id = Vector{Int}(undef, num_local_cells_ref_model)
33+
current = 1
34+
for i = 1:num_owned_cells_model
35+
for j = 1:num_children
36+
n2o_cell_map[current] = i
37+
n2o_cell_to_child_id[current] = j
38+
current += 1
39+
end
40+
end
41+
n2o_cell_map, n2o_cell_to_child_id
42+
end |> tuple_of_arrays
4743

48-
cache = fetch_vector_ghost_values_cache(n2o_cell_map,partition(cell_gids_ref_model))
49-
fetch_vector_ghost_values!(n2o_cell_map,cache) |> wait
50-
fetch_vector_ghost_values!(n2o_cell_to_child_id,cache) |> wait
44+
cache = fetch_vector_ghost_values_cache(n2o_cell_map, partition(cell_gids_ref_model))
45+
fetch_vector_ghost_values!(n2o_cell_map, cache) |> wait
46+
fetch_vector_ghost_values!(n2o_cell_to_child_id, cache) |> wait
5147

52-
adaptivity_glue=map(n2o_cell_map,n2o_cell_to_child_id) do n2o_cell_map, n2o_cell_to_child_id
53-
n2o_faces_map = [(d==Dc) ? n2o_cell_map : Int[] for d in 0:Dc]
54-
AdaptivityGlue(n2o_faces_map,n2o_cell_to_child_id,ref_rule)
55-
end
56-
end
48+
adaptivity_glue = map(n2o_cell_map, n2o_cell_to_child_id) do n2o_cell_map, n2o_cell_to_child_id
49+
n2o_faces_map = [(d == Dc) ? n2o_cell_map : Int[] for d in 0:Dc]
50+
AdaptivityGlue(n2o_faces_map, n2o_cell_to_child_id, ref_rule)
51+
end
52+
end
5753

5854
function _setup_one_level_refined_octree_model(model::OctreeDistributedDiscreteModel{Dc,Dp},
59-
fmodel::OctreeDistributedDiscreteModel{Dc,Dp},
60-
adaptivity_glue) where {Dc,Dp}
61-
@assert model.parts === fmodel.parts
62-
adaptive_models = map(local_views(model),
63-
local_views(fmodel),
64-
adaptivity_glue) do model, fmodel, glue
65-
Gridap.Adaptivity.AdaptedDiscreteModel(fmodel.model,model,glue)
55+
fmodel::OctreeDistributedDiscreteModel{Dc,Dp},
56+
adaptivity_glue) where {Dc,Dp}
57+
@assert model.parts === fmodel.parts
58+
adaptive_models = map(local_views(model),
59+
local_views(fmodel),
60+
adaptivity_glue) do model, fmodel, glue
61+
Gridap.Adaptivity.AdaptedDiscreteModel(fmodel.model, model, glue)
62+
end
63+
new_fmodel = GridapDistributed.GenericDistributedDiscreteModel(adaptive_models, get_cell_gids(fmodel))
64+
OctreeDistributedDiscreteModel(Dc, Dp,
65+
model.parts,
66+
new_fmodel,
67+
fmodel.non_conforming_glue,
68+
model.coarse_model,
69+
model.ptr_pXest_connectivity,
70+
pXest_copy(fmodel.pXest_type, fmodel.ptr_pXest),
71+
fmodel.pXest_type,
72+
fmodel.pXest_refinement_rule_type,
73+
false,
74+
fmodel)
75+
end
76+
77+
function Gridap.LinearizedFESpace(model::OctreeDistributedDiscreteModel{Dc},
78+
reffe::Tuple{Gridap.ReferenceFEs.Lagrangian,Any,Any};
79+
kwargs...) where {Dc}
80+
lin_reffe = Gridap._linearize_reffe(reffe)
81+
order = reffe[2][2]
82+
@assert floor(log2(order)) == ceil(log2(order)) "The order of the Lagrangian reference FE must be a power of 2"
83+
num_refinements = Int(log2(order))
84+
ref_model = model
85+
for i = 1:num_refinements
86+
cell_gids = get_cell_gids(ref_model.dmodel)
87+
ref_coarse_flags = map(partition(cell_gids)) do indices
88+
flags = Vector{Cint}(undef, local_length(indices))
89+
flags .= refine_flag
6690
end
67-
new_fmodel = GridapDistributed.GenericDistributedDiscreteModel(adaptive_models,get_cell_gids(fmodel))
68-
OctreeDistributedDiscreteModel(Dc,Dp,
69-
model.parts,
70-
new_fmodel,
71-
fmodel.non_conforming_glue,
72-
model.coarse_model,
73-
model.ptr_pXest_connectivity,
74-
pXest_copy(fmodel.pXest_type,fmodel.ptr_pXest),
75-
fmodel.pXest_type,
76-
fmodel.pXest_refinement_rule_type,
77-
false,
78-
fmodel)
79-
end
91+
ref_model, glue = Gridap.Adaptivity.adapt(ref_model, ref_coarse_flags)
92+
end
93+
adaptivity_glue = _create_adaptivity_glue(model, ref_model, num_refinements)
94+
one_level_ref_model = _setup_one_level_refined_octree_model(model, ref_model, adaptivity_glue)
95+
Gridap.FESpace(one_level_ref_model, lin_reffe; kwargs...), one_level_ref_model
96+
end
8097

81-
function Gridap.LinearizedFESpace(model::OctreeDistributedDiscreteModel{Dc},
82-
reffe::Tuple{Gridap.ReferenceFEs.Lagrangian,Any,Any};
83-
kwargs...) where {Dc}
84-
lin_reffe=Gridap._linearize_reffe(reffe)
85-
order=_get_order(reffe)
86-
@assert floor(log2(order)) == ceil(log2(order)) "The order of the Lagrangian reference FE must be a power of 2"
87-
num_refinements=Int(log2(order))
88-
ref_model=model
89-
for i=1:num_refinements
90-
cell_gids=get_cell_gids(ref_model.dmodel)
91-
ref_coarse_flags=map(partition(cell_gids)) do indices
92-
flags=Vector{Cint}(undef,local_length(indices))
93-
flags.=refine_flag
94-
end
95-
ref_model,glue=Gridap.Adaptivity.adapt(ref_model,ref_coarse_flags)
98+
function Gridap.LinearizedFESpace(model::OctreeDistributedDiscreteModel{Dc},
99+
reffe::Tuple{Gridap.ReferenceFEs.Nedelec,Any,Any};
100+
kwargs...) where {Dc}
101+
lin_reffe = (reffe[1], (reffe[2][1], 0), reffe[3])
102+
order = reffe[2][2] + 1
103+
@assert floor(log2(order)) == ceil(log2(order)) "The order of the Nedelec reference FE plus one must be a power of 2"
104+
_build_linearized_space(model, lin_reffe, order; kwargs...)
105+
end
106+
107+
function _build_linearized_space(model, lin_reffe, order; kwargs...)
108+
num_refinements = Int(log2(order))
109+
ref_model = model
110+
for _ in 1:num_refinements
111+
cell_gids = get_cell_gids(ref_model.dmodel)
112+
ref_coarse_flags = map(partition(cell_gids)) do indices
113+
flags = Vector{Cint}(undef, local_length(indices))
114+
flags .= refine_flag
96115
end
97-
adaptivity_glue=_create_adaptivity_glue(model,ref_model,num_refinements)
98-
one_level_ref_model=_setup_one_level_refined_octree_model(model,ref_model,adaptivity_glue)
99-
Gridap.FESpace(one_level_ref_model,lin_reffe; kwargs...), one_level_ref_model
100-
end
116+
ref_model, _ = Gridap.Adaptivity.adapt(ref_model, ref_coarse_flags)
117+
end
118+
adaptivity_glue = _create_adaptivity_glue(model, ref_model, num_refinements)
119+
one_level_ref_model = _setup_one_level_refined_octree_model(model, ref_model, adaptivity_glue)
120+
Gridap.FESpace(one_level_ref_model, lin_reffe; kwargs...), one_level_ref_model
121+
end

0 commit comments

Comments
 (0)