Skip to content

Commit 2a71fe7

Browse files
Added/modified code required in order to have MPI-parallel Stokes test
working with global FE spaces
1 parent 1663849 commit 2a71fe7

File tree

2 files changed

+152
-109
lines changed

2 files changed

+152
-109
lines changed

src/MultiFieldDistributedFESpaces.jl

+126-81
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,183 @@
11
struct MultiFieldDistributedFESpace{V} <: DistributedFESpace{V}
2-
vector_type :: Type{V}
3-
distributed_spaces :: Vector{<:DistributedFESpace}
4-
spaces :: DistributedData{<:MultiFieldFESpace}
5-
gids :: DistributedIndexSet
6-
end
2+
vector_type::Type{V}
3+
distributed_spaces::Vector{<:DistributedFESpace}
4+
spaces::DistributedData{<:MultiFieldFESpace}
5+
gids::DistributedIndexSet
6+
end
77

8-
function Gridap.MultiFieldFESpace(test_space::MultiFieldDistributedFESpace{V},
8+
function Gridap.MultiFieldFESpace(test_space::MultiFieldDistributedFESpace{V},
99
trial_spaces::Vector{<:DistributedFESpace{V}}) where V
10-
spaces = DistributedData(trial_spaces...) do part, spaces_and_gids...
11-
MultiFieldFESpace([s[1] for s in spaces_and_gids])
12-
end
13-
MultiFieldDistributedFESpace(V,trial_spaces,spaces,test_space.gids)
14-
end
10+
spaces = DistributedData(trial_spaces...) do part, spaces_and_gids...
11+
MultiFieldFESpace([s[1] for s in spaces_and_gids])
12+
end
13+
MultiFieldDistributedFESpace(V, trial_spaces, spaces, test_space.gids)
14+
end
1515

1616

17-
function Gridap.FESpaces.FEFunction(dV::MultiFieldDistributedFESpace{T},x) where {T}
18-
_gen_multifield_distributed_fe_function(dV,x,FEFunction)
17+
function Gridap.FESpaces.FEFunction(dV::MultiFieldDistributedFESpace{T}, x) where {T}
18+
_gen_multifield_distributed_fe_function(dV, x, FEFunction)
1919
end
2020

2121

22-
function _gen_multifield_distributed_fe_function(dV::MultiFieldDistributedFESpace{T},x,f) where {T}
23-
single_fe_functions = DistributedFEFunction{T}[]
24-
for (field, U) in enumerate(dV.distributed_spaces)
25-
free_values_i = restrict_to_field(dV,x,field)
26-
uhi = f(U,free_values_i)
27-
push!(single_fe_functions,uhi)
28-
end
22+
function _gen_multifield_distributed_fe_function(dV::MultiFieldDistributedFESpace{T}, x, f) where {T}
23+
single_fe_functions = DistributedFEFunction{T}[]
24+
for (field, U) in enumerate(dV.distributed_spaces)
25+
free_values_i = restrict_to_field(dV, x, field)
26+
uhi = f(U, free_values_i)
27+
push!(single_fe_functions, uhi)
28+
end
2929

30-
funs = DistributedData(get_comm(dV.distributed_spaces[1]),
30+
funs = DistributedData(get_comm(dV.distributed_spaces[1]),
3131
dV.spaces, single_fe_functions...,) do part, V, fe_functions...
32-
mfv=zero_free_values(V)
33-
current=1
34-
for fun in fe_functions
35-
fv = get_free_values(fun)
36-
for i=1:length(fv)
37-
mfv[current]=fv[i]
38-
current=current+1
32+
mfv = zero_free_values(V)
33+
current = 1
34+
for fun in fe_functions
35+
fv = get_free_values(fun)
36+
for i = 1:length(fv)
37+
mfv[current] = fv[i]
38+
current = current + 1
39+
end
3940
end
40-
end
41-
f(V,mfv)
42-
end
43-
multifield_fe_function=DistributedFEFunction(funs,x,dV)
44-
MultiFieldDistributedFEFunction{T}(single_fe_functions,
41+
f(V, mfv)
42+
end
43+
multifield_fe_function = DistributedFEFunction(funs, x, dV)
44+
MultiFieldDistributedFEFunction{T}(single_fe_functions,
4545
multifield_fe_function,
4646
dV)
4747
end
4848

4949

50-
function restrict_to_field(dV::MultiFieldDistributedFESpace,x::Vector,field)
51-
@assert isa(dV.gids,SequentialDistributedIndexSet)
52-
ngids = dV.distributed_spaces[field].gids.ngids
53-
xi = Vector{eltype(x)}(undef,ngids)
54-
do_on_parts(dV.spaces,dV.gids,xi,x,dV.distributed_spaces...) do part, mfspace, mfgids, xi, x,fspaces_and_gids...
55-
offset=0
56-
for i=1:field-1
57-
fspace = fspaces_and_gids[i][1]
58-
offset = offset + num_free_dofs(fspace)
50+
function restrict_to_field(dV::MultiFieldDistributedFESpace, x::Vector, field)
51+
@assert isa(dV.gids, SequentialDistributedIndexSet)
52+
53+
xi = Gridap.Algebra.allocate_vector(Vector{eltype(x)},
54+
dV.distributed_spaces[field].gids)
55+
56+
do_on_parts(dV.spaces, dV.gids, xi, x, dV.distributed_spaces...) do part, mfspace, mfgids, xi, x, fspaces_and_gids...
57+
offset = 0
58+
for i = 1:field - 1
59+
fspace = fspaces_and_gids[i][1]
60+
offset = offset + num_free_dofs(fspace)
61+
end
62+
fspace = fspaces_and_gids[field][1]
63+
fgids = fspaces_and_gids[field][2]
64+
for i = 1:num_free_dofs(fspace)
65+
if fgids.lid_to_owner[i] == part
66+
xi[fgids.lid_to_gid[i]] = x[mfgids.lid_to_gid[offset + i]]
67+
end
68+
end
5969
end
60-
fspace = fspaces_and_gids[field][1]
61-
fgids = fspaces_and_gids[field][2]
62-
for i=1:num_free_dofs(fspace)
63-
if fgids.lid_to_owner[i] == part
64-
xi[fgids.lid_to_gid[i]]=x[mfgids.lid_to_gid[offset+i]]
65-
end
70+
xi
71+
end
72+
73+
function restrict_to_field(dV::MultiFieldDistributedFESpace, x::PETSc.Vec{Float64}, field)
74+
fgids = dV.distributed_spaces[field].gids
75+
mfgids = dV.gids
76+
@assert isa(fgids, MPIPETScDistributedIndexSet)
77+
78+
xi = Gridap.Algebra.allocate_vector(PETSc.Vec{Float64},
79+
dV.distributed_spaces[field].gids)
80+
81+
comm = get_comm(fgids)
82+
part = get_part(comm)
83+
84+
fis_gids = [ PETSc.PetscInt(fgids.lid_to_gid_petsc[i] - 1)
85+
for i = 1:length(fgids.lid_to_gid_petsc)
86+
if fgids.parts.part.lid_to_owner[i] == part ]
87+
88+
mfis_gids = Vector{PETSc.PetscInt}(undef,length(fis_gids))
89+
90+
do_on_parts(dV.gids, dV.distributed_spaces...) do part, lmfgids, fspaces_and_gids...
91+
offset = 0
92+
for i = 1:field - 1
93+
fspace = fspaces_and_gids[i][1]
94+
offset = offset + num_free_dofs(fspace)
95+
end
96+
fspace = fspaces_and_gids[field][1]
97+
current=1
98+
for i = 1:num_free_dofs(fspace)
99+
if lmfgids.lid_to_owner[offset+i] == part
100+
mfis_gids[current]=mfgids.lid_to_gid_petsc[offset+i]-1
101+
current=current+1
102+
end
103+
end
66104
end
67-
end
68-
xi
105+
106+
fis = PETSc.IS_(Float64, fis_gids; comm=comm.comm)
107+
mfis = PETSc.IS_(Float64, mfis_gids; comm=comm.comm)
108+
109+
vscatter = PETSc.VecScatter(x, mfis, xi, fis)
110+
scatter!(vscatter,x,xi)
111+
xi
69112
end
70113

71-
function Gridap.FESpaces.EvaluationFunction(dV::MultiFieldDistributedFESpace,x)
72-
_gen_multifield_distributed_fe_function(dV,x,EvaluationFEFunction)
114+
115+
116+
function Gridap.FESpaces.EvaluationFunction(dV::MultiFieldDistributedFESpace, x)
117+
_gen_multifield_distributed_fe_function(dV, x, EvaluationFEFunction)
73118
end
74119

75120

76121
function Gridap.MultiFieldFESpace(model::DistributedDiscreteModel,
77122
distributed_spaces::Vector{<:DistributedFESpace{V}}) where V
78123

79-
spaces = DistributedData(distributed_spaces...) do part, spaces_and_gids...
80-
MultiFieldFESpace([s[1] for s in spaces_and_gids])
81-
end
82-
83-
function init_lid_to_owner(part,lspace,spaces_and_gids...)
84-
nlids = num_free_dofs(lspace)
85-
lid_to_owner = zeros(Int,nlids)
86-
current_lid = 1
87-
for current_field_space_gids in spaces_and_gids
88-
gids = current_field_space_gids[2]
89-
for i=1:length(gids.lid_to_owner)
90-
lid_to_owner[current_lid]=gids.lid_to_owner[i]
91-
current_lid += 1
92-
end
124+
spaces = DistributedData(distributed_spaces...) do part, spaces_and_gids...
125+
MultiFieldFESpace([s[1] for s in spaces_and_gids])
126+
end
127+
128+
function init_lid_to_owner(part, lspace, spaces_and_gids...)
129+
nlids = num_free_dofs(lspace)
130+
lid_to_owner = zeros(Int, nlids)
131+
current_lid = 1
132+
for current_field_space_gids in spaces_and_gids
133+
gids = current_field_space_gids[2]
134+
for i = 1:length(gids.lid_to_owner)
135+
lid_to_owner[current_lid] = gids.lid_to_owner[i]
136+
current_lid += 1
137+
end
138+
end
139+
lid_to_owner
93140
end
94-
lid_to_owner
95-
end
96141

97-
comm = get_comm(model)
142+
comm = get_comm(model)
98143

99-
part_to_lid_to_owner = DistributedData{Vector{Int}}(init_lid_to_owner,
144+
part_to_lid_to_owner = DistributedData{Vector{Int}}(init_lid_to_owner,
100145
comm,
101146
spaces,
102147
distributed_spaces...)
103148

104-
offsets, ngids = _compute_offsets_and_ngids(part_to_lid_to_owner)
149+
offsets, ngids = _compute_offsets_and_ngids(part_to_lid_to_owner)
105150

106-
num_dofs_x_cell = compute_num_dofs_x_cell(comm,spaces)
151+
num_dofs_x_cell = compute_num_dofs_x_cell(comm, spaces)
107152

108-
part_to_lid_to_gid = _compute_part_to_lid_to_gid(model,
153+
part_to_lid_to_gid = _compute_part_to_lid_to_gid(model,
109154
spaces,
110155
num_dofs_x_cell,
111156
part_to_lid_to_owner,
112157
offsets)
113158

114-
function init_free_gids(part, lid_to_gid, lid_to_owner, ngids)
115-
IndexSet(ngids, lid_to_gid, lid_to_owner)
116-
end
159+
function init_free_gids(part, lid_to_gid, lid_to_owner, ngids)
160+
IndexSet(ngids, lid_to_gid, lid_to_owner)
161+
end
117162

118-
gids = DistributedIndexSet(init_free_gids,
163+
gids = DistributedIndexSet(init_free_gids,
119164
comm,
120165
ngids,
121166
part_to_lid_to_gid,
122167
part_to_lid_to_owner,
123168
ngids)
124169

125-
MultiFieldDistributedFESpace(V,
170+
MultiFieldDistributedFESpace(V,
126171
distributed_spaces,
127172
spaces,
128173
gids)
129174
end
130175

131176
# FE Function
132177
struct MultiFieldDistributedFEFunction{T}
133-
single_fe_functions :: Vector{DistributedFEFunction{T}}
134-
multifield_fe_function :: DistributedFEFunction{T}
135-
space :: MultiFieldDistributedFESpace{T}
178+
single_fe_functions::Vector{DistributedFEFunction{T}}
179+
multifield_fe_function::DistributedFEFunction{T}
180+
space::MultiFieldDistributedFESpace{T}
136181
end
137182

138183
Gridap.FESpaces.FEFunctionStyle(::Type{MultiFieldDistributedFEFunction}) = Val{true}()

test/MPIPETScDistributedStokesTests.jl

+26-28
Original file line numberDiff line numberDiff line change
@@ -48,35 +48,33 @@ function run(comm,assembly_strategy::AbstractString, global_dofs::Bool)
4848
add_tag_from_tags!(labels,"neumann",[5])
4949
end
5050

51-
# Build local and global test FE spaces
52-
spaces = DistributedData(comm, model) do part, (model,gids)
53-
labels = get_face_labeling(model)
54-
V = TestFESpace(
55-
reffe=:QLagrangian,
56-
conformity=:H1,
57-
valuetype=VectorValue{2,Float64},
58-
model=model,
59-
labels=labels,
60-
order=2,
61-
dirichlet_tags=["diri0","diri1"])
62-
Q = TestFESpace(
63-
reffe=:PLagrangian,
64-
conformity=:L2,
65-
valuetype=Float64,
66-
model=model,
67-
order=1) #,
68-
#constraint=:zeromean)
69-
MultiFieldFESpace([V,Q])
70-
end
71-
Y=GridapDistributed.DistributedFESpaceFromLocalFESpaces(vector_type,model,spaces)
7251

73-
# Build local and global trial FE spaces
74-
trialspaces = DistributedData(comm, Y) do part, (y,gids)
75-
U=TrialFESpace(y.spaces[1],[u,u])
76-
P=TrialFESpace(y.spaces[2])
77-
MultiFieldFESpace([U,P])
78-
end
79-
X=GridapDistributed.DistributedFESpaceFromLocalFESpaces(vector_type,trialspaces,Y.gids)
52+
# FE Spaces
53+
order = 2
54+
V = FESpace(
55+
vector_type,
56+
valuetype = VectorValue{2,Float64},
57+
reffe=:QLagrangian,
58+
order = order,
59+
model = model,
60+
conformity = :H1,
61+
dirichlet_tags=["diri0","diri1"],
62+
)
63+
64+
Q = FESpace(
65+
vector_type,
66+
reffe=:PLagrangian,
67+
conformity=:L2,
68+
valuetype=Float64,
69+
model=model,
70+
order=order-1)
71+
#constraint=:zeromean)
72+
73+
Y=MultiFieldFESpace(model,[V,Q])
74+
75+
U=TrialFESpace(V,[u,u])
76+
P=TrialFESpace(Q)
77+
X=MultiFieldFESpace(Y,[U,P])
8078

8179
if (assembly_strategy == "RowsComputedLocally")
8280
strategy = RowsComputedLocally(Y; global_dofs=global_dofs)

0 commit comments

Comments
 (0)