Skip to content

Commit e272dc2

Browse files
committed
Added CartesianDiscreteModels with an arbitrary number of ghost layers
1 parent 72c2b7a commit e272dc2

5 files changed

Lines changed: 132 additions & 3 deletions

File tree

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.4.8"
55

66
[deps]
77
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
8+
CircularArrays = "7a955b69-7140-5f4e-a0ed-f168c5e2e749"
89
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
910
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
1011
Gridap = "56d4f2e9-7ea1-5844-9cf6-b9c51ca7ce8e"
@@ -17,6 +18,7 @@ WriteVTK = "64499a7a-5c06-52f2-abe2-ccb03c286192"
1718

1819
[compat]
1920
BlockArrays = "1"
21+
CircularArrays = "1.4.0"
2022
FillArrays = "1"
2123
ForwardDiff = "0.10, 1"
2224
Gridap = "0.19.1"

src/Geometry.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,11 @@ const DistributedCartesianDiscreteModel{Dc,Dp,A,B,C} =
243243
function Geometry.CartesianDiscreteModel(
244244
ranks::AbstractArray{<:Integer}, # Distributed array with the rank IDs
245245
parts::NTuple{N,<:Integer}, # Number of ranks (parts) in each direction
246-
args...;isperiodic=map(i->false,parts),kwargs...) where N
246+
args...;
247+
ghost = map(i->true,parts),
248+
isperiodic = map(i->false,parts),
249+
kwargs...
250+
) where N
247251

248252
desc = CartesianDescriptor(args...;isperiodic=isperiodic,kwargs...)
249253
nc = desc.partition
@@ -254,10 +258,10 @@ function Geometry.CartesianDiscreteModel(
254258
@assert N == length(nc) msg
255259

256260
if any(isperiodic)
261+
@notimplementedif ghost != map(i->true,parts)
257262
_cartesian_model_with_periodic_bcs(ranks,parts,desc)
258263
else
259-
ghost = map(i->true,parts)
260-
upartition = uniform_partition(ranks,parts,nc,ghost,isperiodic)
264+
upartition = _uniform_partition(ranks,parts,nc,ghost,isperiodic)
261265
gcids = CartesianIndices(nc)
262266
models = map(ranks,upartition) do rank, upartition
263267
cmin = gcids[first(upartition)]

src/GridapDistributed.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ using FillArrays
2525
using BlockArrays
2626
using LinearAlgebra
2727
using ForwardDiff
28+
using CircularArrays
2829

2930
import Gridap.TensorValues: inner, outer, double_contraction, symmetric_part
3031
import LinearAlgebra: det, tr, cross, dot, , diag
@@ -43,6 +44,8 @@ export with_ghost, no_ghost
4344

4445
export redistribute
4546

47+
include("PArraysExtras.jl")
48+
4649
include("BlockPartitionedArrays.jl")
4750

4851
include("Algebra.jl")

src/PArraysExtras.jl

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
2+
# This is copied from PArrays v0.5, which is not yet supported. It is necessary to get
3+
# more than one layers of ghosts.
4+
5+
function _uniform_partition(rank,np,n,args...)
6+
@assert prod(np) == length(rank)
7+
indices = map(rank) do rank
8+
_block_with_constant_size(rank,np,n,args...)
9+
end
10+
if length(args) == 0
11+
map(indices) do indices
12+
cache = assembly_cache(indices)
13+
copy!(cache,empty_assembly_cache())
14+
end
15+
else
16+
assembly_neighbors(indices;symmetric=true)
17+
end
18+
indices
19+
end
20+
21+
function _block_with_constant_size(rank,np,n,ghost,periodic=map(i->false,ghost))
22+
N = length(n)
23+
p = CartesianIndices(np)[rank]
24+
own_ranges = map(_local_range,Tuple(p),np,n)
25+
local_ranges = map(_local_range,Tuple(p),np,n,ghost,periodic)
26+
owners = map(Tuple(p), np, n, local_ranges) do p, np, n, lr
27+
myowners = zeros(Int32,length(lr))
28+
i = 1
29+
for p in Iterators.cycle(1:np)
30+
plr = _local_range(p, np, n)
31+
while mod(lr[i]-1, n)+1 in plr
32+
myowners[i] = p
33+
(i += 1) > length(myowners) && return myowners
34+
end
35+
end
36+
end
37+
n_local = prod(map(length, local_ranges))
38+
n_own = prod(map(length, own_ranges))
39+
n_ghost = n_local - n_own
40+
41+
ghost_to_global = zeros(Int,n_ghost)
42+
ghost_to_owner = zeros(Int32,n_ghost)
43+
perm = zeros(Int32,n_local)
44+
i_ghost = 0
45+
i_own = 0
46+
47+
cis = CartesianIndices(map(length,local_ranges))
48+
lis = CircularArray(LinearIndices(n))
49+
local_cis = CartesianIndices(local_ranges)
50+
owner_lis = LinearIndices(np)
51+
for (i,ci) in enumerate(cis)
52+
flags = map(Tuple(ci), own_ranges, local_ranges) do i, or, lr
53+
i in (or .- first(lr) .+ 1)
54+
end
55+
if !all(flags)
56+
i_ghost += 1
57+
ghost_to_global[i_ghost] = lis[local_cis[i]]
58+
o = map(getindex,owners,Tuple(ci))
59+
o_ci = CartesianIndex(o)
60+
ghost_to_owner[i_ghost] = owner_lis[o_ci]
61+
perm[i] = i_ghost + n_own
62+
else
63+
i_own += 1
64+
perm[i] = i_own
65+
end
66+
end
67+
ghostids = GhostIndices(prod(n),ghost_to_global,ghost_to_owner)
68+
ids = PartitionedArrays.LocalIndicesWithConstantBlockSize(p,np,n,ghostids)
69+
PartitionedArrays.PermutedLocalIndices(ids,perm)
70+
end
71+
72+
function _local_range(p,np,n,ghost=false,periodic=false)
73+
l, rem = divrem(n, np)
74+
offset = l * (p-1)
75+
if rem >= (np-p+1)
76+
l += 1
77+
offset += p - (np-rem) - 1
78+
end
79+
start = 1+offset-ghost
80+
stop = l+offset+ghost
81+
82+
periodic && return start:stop
83+
return max(1, start):min(n,stop)
84+
end

test/ExtraGhostLayers.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
using Gridap
3+
using GridapDistributed
4+
using PartitionedArrays
5+
6+
7+
parts = (2,2)
8+
ranks = with_debug() do distribute
9+
distribute(LinearIndices((prod(parts),)))
10+
end
11+
12+
nc = (4,4)
13+
model = CartesianDiscreteModel(ranks,parts,(0,1,0,1),nc;ghost=(2,2))
14+
15+
num_cells(model)
16+
map(num_cells,local_views(model))
17+
18+
reffe = ReferenceFE(lagrangian,Float64,1)
19+
V = FESpace(model,reffe)
20+
21+
cell_dof_ids = map(get_cell_dof_ids,local_views(V))
22+
23+
gids = get_free_dof_ids(V)
24+
own_to_local(gids)
25+
26+
Ω = Triangulation(model)
27+
map(num_cells,local_views(Ω))
28+
29+
= Measure(Ω,2)
30+
31+
f = 1.0
32+
a(u,v) = ((u)(v))dΩ
33+
l(v) = (fv)dΩ
34+
35+
36+

0 commit comments

Comments
 (0)