Skip to content

Commit 659bac2

Browse files
* Add RedistributeTools.jl from GridapSolvers.jl
and adapted it to PArrays v0.3 * redistribute_fe_function(...) working.
1 parent cf93940 commit 659bac2

File tree

4 files changed

+401
-91
lines changed

4 files changed

+401
-91
lines changed

src/GridapP4est.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module GridapP4est
1717
include("OctreeDistributedDiscreteModels.jl")
1818
include("GridapFixes.jl")
1919
include("FESpaces.jl")
20+
include("RedistributeTools.jl")
2021

2122
export UniformlyRefinedForestOfOctreesDiscreteModel
2223
export OctreeDistributedDiscreteModel
@@ -27,5 +28,6 @@ module GridapP4est
2728
export MPIVoidVector
2829
export i_am_in
2930
export nothing_flag, refine_flag, coarsen_flag
31+
export redistribute_fe_function
3032

3133
end

src/OctreeDistributedDiscreteModels.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,14 +1185,14 @@ function _redistribute_parts_subseteq_parts_redistributed(model::OctreeDistribut
11851185
pXest_ghost_destroy(Val{Dc},ptr_pXest_ghost)
11861186

11871187
red_model = OctreeDistributedDiscreteModel(Dc,Dp,
1188-
parts,
1189-
fmodel,
1190-
non_conforming_glue,
1191-
model.coarse_model,
1192-
model.ptr_pXest_connectivity,
1193-
ptr_pXest_new,
1194-
false,
1195-
model)
1188+
parts,
1189+
fmodel,
1190+
non_conforming_glue,
1191+
model.coarse_model,
1192+
model.ptr_pXest_connectivity,
1193+
ptr_pXest_new,
1194+
false,
1195+
model)
11961196
return red_model, glue
11971197
end
11981198

src/RedistributeTools.jl

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
2+
# It is defined here just to avoid syntax errors below
3+
# To be REMOVED in the future
4+
struct VoidDistributedFESpace{A} <: Gridap.GridapType
5+
parts::A
6+
end
7+
8+
# It is defined here just to avoid syntax errors below
9+
# To be REMOVED in the future
10+
function change_parts(x::Union{MPIArray,Nothing}, new_parts; default=nothing)
11+
x_new = map(new_parts) do _p
12+
if isa(x,MPIArray)
13+
PartitionedArrays.getany(x)
14+
else
15+
default
16+
end
17+
end
18+
return x_new
19+
end
20+
21+
# It is defined here just to avoid syntax errors below
22+
# To be REMOVED in the future
23+
function change_parts(::Type{<:GridapDistributed.DistributedCellField},x,new_parts)
24+
if isa(x,GridapDistributed.DistributedCellField)
25+
fields = change_parts(local_views(x),new_parts)
26+
else
27+
fields = change_parts(nothing,new_parts;default=void(CellField))
28+
end
29+
return GridapDistributed.DistributedCellField(fields)
30+
end
31+
32+
function _allocate_cell_wise_dofs(cell_to_ldofs)
33+
map(cell_to_ldofs) do cell_to_ldofs
34+
cache = array_cache(cell_to_ldofs)
35+
ncells = length(cell_to_ldofs)
36+
ptrs = Vector{Int32}(undef,ncells+1)
37+
for cell in 1:ncells
38+
ldofs = getindex!(cache,cell_to_ldofs,cell)
39+
ptrs[cell+1] = length(ldofs)
40+
end
41+
PartitionedArrays.length_to_ptrs!(ptrs)
42+
ndata = ptrs[end]-1
43+
data = Vector{Float64}(undef,ndata)
44+
PartitionedArrays.JaggedArray(data,ptrs)
45+
end
46+
end
47+
48+
function _update_cell_dof_values_with_local_info!(cell_dof_values_new,
49+
cell_dof_values_old,
50+
new2old)
51+
map(cell_dof_values_new,
52+
cell_dof_values_old,
53+
new2old) do cell_dof_values_new,cell_dof_values_old,new2old
54+
ocache = array_cache(cell_dof_values_old)
55+
for (ncell,ocell) in enumerate(new2old)
56+
if ocell!=0
57+
# Copy ocell to ncell
58+
oentry = getindex!(ocache,cell_dof_values_old,ocell)
59+
range = cell_dof_values_new.ptrs[ncell]:cell_dof_values_new.ptrs[ncell+1]-1
60+
cell_dof_values_new.data[range] .= oentry
61+
end
62+
end
63+
end
64+
end
65+
66+
function _allocate_comm_data(num_dofs_x_cell,lids)
67+
map(num_dofs_x_cell,lids) do num_dofs_x_cell,lids
68+
n = length(lids)
69+
ptrs = Vector{Int32}(undef,n+1)
70+
ptrs.= 0
71+
for i = 1:n
72+
for j = lids.ptrs[i]:lids.ptrs[i+1]-1
73+
ptrs[i+1] = ptrs[i+1] + num_dofs_x_cell.data[j]
74+
end
75+
end
76+
PartitionedArrays.length_to_ptrs!(ptrs)
77+
ndata = ptrs[end]-1
78+
data = Vector{Float64}(undef,ndata)
79+
PartitionedArrays.JaggedArray(data,ptrs)
80+
end
81+
end
82+
83+
function _pack_snd_data!(snd_data,cell_dof_values,snd_lids)
84+
map(snd_data,cell_dof_values,snd_lids) do snd_data,cell_dof_values,snd_lids
85+
cache = array_cache(cell_dof_values)
86+
s = 1
87+
for i = 1:length(snd_lids)
88+
for j = snd_lids.ptrs[i]:snd_lids.ptrs[i+1]-1
89+
cell = snd_lids.data[j]
90+
ldofs = getindex!(cache,cell_dof_values,cell)
91+
92+
e = s+length(ldofs)-1
93+
range = s:e
94+
snd_data.data[range] .= ldofs
95+
s = e+1
96+
end
97+
end
98+
end
99+
end
100+
101+
function _unpack_rcv_data!(cell_dof_values,rcv_data,rcv_lids)
102+
map(cell_dof_values,rcv_data,rcv_lids) do cell_dof_values,rcv_data,rcv_lids
103+
s = 1
104+
for i = 1:length(rcv_lids.ptrs)-1
105+
for j = rcv_lids.ptrs[i]:rcv_lids.ptrs[i+1]-1
106+
cell = rcv_lids.data[j]
107+
range_cell_dof_values = cell_dof_values.ptrs[cell]:cell_dof_values.ptrs[cell+1]-1
108+
109+
e = s+length(range_cell_dof_values)-1
110+
range_rcv_data = s:e
111+
cell_dof_values.data[range_cell_dof_values] .= rcv_data.data[range_rcv_data]
112+
s = e+1
113+
end
114+
end
115+
end
116+
end
117+
118+
function get_glue_components(glue::GridapDistributed.RedistributeGlue,reverse::Val{false})
119+
return glue.lids_rcv, glue.lids_snd, glue.parts_rcv, glue.parts_snd, glue.new2old
120+
end
121+
122+
function get_glue_components(glue::GridapDistributed.RedistributeGlue,reverse::Val{true})
123+
return glue.lids_snd, glue.lids_rcv, glue.parts_snd, glue.parts_rcv, glue.old2new
124+
end
125+
126+
function _num_dofs_x_cell(cell_dofs_array,lids)
127+
map(cell_dofs_array,lids) do cell_dofs_array, lids
128+
data = [length(cell_dofs_array[i]) for i = 1:length(cell_dofs_array) ]
129+
PartitionedArrays.JaggedArray(data,lids.ptrs)
130+
end
131+
end
132+
133+
function get_redistribute_cell_dofs_cache(cell_dof_values_old,
134+
cell_dof_ids_new,
135+
model_new,
136+
glue::GridapDistributed.RedistributeGlue;
137+
reverse=false)
138+
139+
lids_rcv, lids_snd, parts_rcv, parts_snd, new2old = get_glue_components(glue,Val(reverse))
140+
141+
cell_dof_values_old = change_parts(cell_dof_values_old,get_parts(glue);default=[])
142+
cell_dof_ids_new = change_parts(cell_dof_ids_new,get_parts(glue);default=[[]])
143+
144+
num_dofs_x_cell_snd = _num_dofs_x_cell(cell_dof_values_old, lids_snd)
145+
num_dofs_x_cell_rcv = _num_dofs_x_cell(cell_dof_ids_new, lids_rcv)
146+
snd_data = _allocate_comm_data(num_dofs_x_cell_snd, lids_snd)
147+
rcv_data = _allocate_comm_data(num_dofs_x_cell_rcv, lids_rcv)
148+
149+
cell_dof_values_new = _allocate_cell_wise_dofs(cell_dof_ids_new)
150+
151+
caches = snd_data, rcv_data, cell_dof_values_new
152+
return caches
153+
end
154+
155+
function redistribute_cell_dofs(cell_dof_values_old,
156+
cell_dof_ids_new,
157+
model_new,
158+
glue::GridapDistributed.RedistributeGlue;
159+
reverse=false)
160+
caches = get_redistribute_cell_dofs_cache(cell_dof_values_old,cell_dof_ids_new,model_new,glue;reverse=reverse)
161+
return redistribute_cell_dofs!(caches,cell_dof_values_old,cell_dof_ids_new,model_new,glue;reverse=reverse)
162+
end
163+
164+
function redistribute_cell_dofs!(caches,
165+
cell_dof_values_old,
166+
cell_dof_ids_new,
167+
model_new,
168+
glue::GridapDistributed.RedistributeGlue;
169+
reverse=false)
170+
171+
snd_data, rcv_data, cell_dof_values_new = caches
172+
lids_rcv, lids_snd, parts_rcv, parts_snd, new2old = get_glue_components(glue,Val(reverse))
173+
174+
cell_dof_values_old = change_parts(cell_dof_values_old,get_parts(glue);default=[])
175+
cell_dof_ids_new = change_parts(cell_dof_ids_new,get_parts(glue);default=[[]])
176+
177+
_pack_snd_data!(snd_data,cell_dof_values_old,lids_snd)
178+
179+
graph=ExchangeGraph(parts_snd,parts_rcv)
180+
t=exchange!(rcv_data,snd_data,graph)
181+
182+
# We have to build the owned part of "cell_dof_values_new" out of
183+
# 1. cell_dof_values_old (for those cells s.t. new2old[:]!=0)
184+
# 2. cell_dof_values_new_rcv (for those cells s.t. new2old[:]=0)
185+
_update_cell_dof_values_with_local_info!(cell_dof_values_new,
186+
cell_dof_values_old,
187+
new2old)
188+
189+
wait(t)
190+
191+
_unpack_rcv_data!(cell_dof_values_new,rcv_data,lids_rcv)
192+
193+
# Now that every part knows it's new owned dofs, exchange ghosts
194+
new_parts = model_new.parts
195+
cell_dof_values_new = change_parts(cell_dof_values_new,new_parts)
196+
if i_am_in(new_parts)
197+
cache = fetch_vector_ghost_values_cache(cell_dof_values_new,
198+
partition(get_cell_gids(model_new)))
199+
fetch_vector_ghost_values!(cell_dof_values_new,cache) |> wait
200+
end
201+
return cell_dof_values_new
202+
end
203+
204+
function get_redistribute_free_values_cache(fv_new::Union{PVector,Nothing},
205+
Uh_new::Union{GridapDistributed.DistributedSingleFieldFESpace,VoidDistributedFESpace},
206+
fv_old::Union{PVector,Nothing},
207+
dv_old::Union{AbstractArray,Nothing},
208+
Uh_old::Union{GridapDistributed.DistributedSingleFieldFESpace,VoidDistributedFESpace},
209+
model_new,
210+
glue::GridapDistributed.RedistributeGlue;
211+
reverse=false)
212+
cell_dof_values_old = !isa(fv_old,Nothing) ? map(scatter_free_and_dirichlet_values,local_views(Uh_old),local_views(fv_old),dv_old) : nothing
213+
cell_dof_ids_new = !isa(fv_new,Nothing) ? map(get_cell_dof_ids, local_views(Uh_new)) : nothing
214+
caches = get_redistribute_cell_dofs_cache(cell_dof_values_old,cell_dof_ids_new,model_new,glue;reverse=reverse)
215+
216+
return caches
217+
end
218+
219+
function redistribute_free_values!(fv_new::Union{PVector,Nothing},
220+
Uh_new::Union{GridapDistributed.DistributedSingleFieldFESpace,VoidDistributedFESpace},
221+
fv_old::Union{PVector,Nothing},
222+
dv_old::Union{AbstractArray,Nothing},
223+
Uh_old::Union{GridapDistributed.DistributedSingleFieldFESpace,VoidDistributedFESpace},
224+
model_new,
225+
glue::GridapDistributed.RedistributeGlue;
226+
reverse=false)
227+
228+
caches = get_redistribute_free_values_cache(fv_new,Uh_new,fv_old,dv_old,Uh_old,model_new,glue;reverse=reverse)
229+
return redistribute_free_values!(caches,fv_new,Uh_new,fv_old,dv_old,Uh_old,model_new,glue;reverse=reverse)
230+
end
231+
232+
function redistribute_free_values!(caches,
233+
fv_new::Union{PVector,Nothing},
234+
Uh_new::Union{GridapDistributed.DistributedSingleFieldFESpace,VoidDistributedFESpace},
235+
fv_old::Union{PVector,Nothing},
236+
dv_old::Union{AbstractArray,Nothing},
237+
Uh_old::Union{GridapDistributed.DistributedSingleFieldFESpace,VoidDistributedFESpace},
238+
model_new,
239+
glue::GridapDistributed.RedistributeGlue;
240+
reverse=false)
241+
242+
cell_dof_values_old = !isa(fv_old,Nothing) ? map(scatter_free_and_dirichlet_values,local_views(Uh_old),local_views(fv_old),dv_old) : nothing
243+
cell_dof_ids_new = !isa(fv_new,Nothing) ? map(get_cell_dof_ids, local_views(Uh_new)) : nothing
244+
cell_dof_values_new = redistribute_cell_dofs!(caches,cell_dof_values_old,cell_dof_ids_new,model_new,glue;reverse=reverse)
245+
246+
# Gather the new free dofs
247+
if !isa(fv_new,Nothing)
248+
Gridap.FESpaces.gather_free_values!(fv_new,Uh_new,cell_dof_values_new)
249+
end
250+
return fv_new
251+
end
252+
253+
function redistribute_fe_function(uh_old::Union{GridapDistributed.DistributedSingleFieldFEFunction,Nothing},
254+
Uh_new::Union{GridapDistributed.DistributedSingleFieldFESpace,VoidDistributedFESpace},
255+
model_new,
256+
glue::GridapDistributed.RedistributeGlue;
257+
reverse=false)
258+
259+
cell_dof_values_old = !isa(uh_old,Nothing) ? map(get_cell_dof_values,local_views(uh_old)) : nothing
260+
cell_dof_ids_new = !isa(Uh_new,VoidDistributedFESpace) ? map(get_cell_dof_ids,local_views(Uh_new)) : nothing
261+
262+
map(cell_dof_values_old,partition(Uh_new.gids)) do cell_dof_values_old, indices
263+
print("[$(part_id(indices))]: $(cell_dof_values_old)"); print("\n")
264+
end
265+
266+
cell_dof_values_new = redistribute_cell_dofs(cell_dof_values_old,cell_dof_ids_new,model_new,glue;reverse=reverse)
267+
268+
map(cell_dof_values_new,partition(Uh_new.gids)) do cell_dof_values_new, indices
269+
print("[$(part_id(indices))]: $(cell_dof_values_new)"); print("\n")
270+
end
271+
272+
# Assemble the new FEFunction
273+
if i_am_in(get_parts(Uh_new))
274+
free_values, dirichlet_values = Gridap.FESpaces.gather_free_and_dirichlet_values(Uh_new,cell_dof_values_new)
275+
free_values = PVector(free_values,partition(Uh_new.gids))
276+
uh_new = FEFunction(Uh_new,free_values,dirichlet_values)
277+
return uh_new
278+
else
279+
return nothing
280+
end
281+
end
282+
283+
function Gridap.FESpaces.gather_free_and_dirichlet_values(f::GridapDistributed.DistributedFESpace,cv)
284+
free_values, dirichlet_values = map(local_views(f),cv) do f, cv
285+
Gridap.FESpaces.gather_free_and_dirichlet_values(f,cv)
286+
end |> tuple_of_arrays
287+
return free_values, dirichlet_values
288+
end

0 commit comments

Comments
 (0)