Skip to content

Commit aa71c9c

Browse files
authored
Merge pull request #182 from gridap/expand-ghost
CartesianDiscreteModels with multiple ghost layers
2 parents c49e9ac + 9908b60 commit aa71c9c

6 files changed

Lines changed: 117 additions & 15 deletions

File tree

NEWS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
- Added support for multiple ghost layers on cartesian models. Since PR[#182](https://github.com/gridap/GridapDistributed.jl/pull/182).
13+
814
## [0.4.9] - 2025-08-08
915

1016
### Added

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.4.9"
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.4"

src/Geometry.jl

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -191,19 +191,20 @@ function _setup_face_gids!(dmodel::GenericDistributedDiscreteModel{Dc},dim) wher
191191
end
192192

193193
# CartesianDiscreteModel
194-
struct DistributedCartesianDescriptor{A,B,C}
194+
struct DistributedCartesianDescriptor{A,B,C,D}
195195
ranks::A
196196
mesh_partition::B
197197
descriptor::C
198+
ghost::D
198199
function DistributedCartesianDescriptor(
199200
ranks::AbstractArray{<:Integer},
200201
mesh_partition::NTuple{Dc,<:Integer},
201-
descriptor::CartesianDescriptor{Dc}
202+
descriptor::CartesianDescriptor{Dc},
203+
ghost = map(i -> true, mesh_partition)
202204
) where Dc
203-
A = typeof(ranks)
204-
B = typeof(mesh_partition)
205-
C = typeof(descriptor)
206-
new{A,B,C}(ranks,mesh_partition,descriptor)
205+
A, B = typeof(ranks), typeof(mesh_partition)
206+
C, D = typeof(descriptor), typeof(ghost)
207+
new{A,B,C,D}(ranks,mesh_partition,descriptor,ghost)
207208
end
208209
end
209210

@@ -223,44 +224,47 @@ function emit_cartesian_descriptor(
223224
new_mesh_partition
224225
) where Dc
225226
f(a) = Tuple(PartitionedArrays.getany(emit(a)))
226-
a, b, c, d = map(new_ranks) do rank
227+
a, b, c, d, e = map(new_ranks) do rank
227228
if rank == 1
228229
desc = pdesc.descriptor
229230
@assert desc.map === identity
230-
Float64[desc.origin.data...], Float64[desc.sizes...], Int[desc.partition...], Bool[desc.isperiodic...]
231+
Float64[desc.origin.data...], Float64[desc.sizes...], Int[desc.partition...], Bool[desc.isperiodic...], Int16[pdesc.ghost...]
231232
else
232-
Float64[], Float64[], Int[], Bool[]
233+
Float64[], Float64[], Int[], Bool[], Int16[]
233234
end
234235
end |> tuple_of_arrays
235-
origin, sizes, partition, isperiodic = VectorValue(f(a)...), f(b), f(c), f(d)
236+
origin, sizes, partition, isperiodic, ghost = VectorValue(f(a)...), f(b), f(c), f(d), f(e)
236237
new_desc = CartesianDescriptor(origin,sizes,partition;isperiodic)
237-
return DistributedCartesianDescriptor(new_ranks,new_mesh_partition,new_desc)
238+
return DistributedCartesianDescriptor(new_ranks,new_mesh_partition,new_desc,ghost)
238239
end
239240

240241
const DistributedCartesianDiscreteModel{Dc,Dp,A,B,C} =
241242
GenericDistributedDiscreteModel{Dc,Dp,<:AbstractArray{<:CartesianDiscreteModel},B,<:DistributedCartesianDescriptor}
242243

243244
function Geometry.CartesianDiscreteModel(
244-
ranks::AbstractArray{<:Integer},parts::NTuple{N,<:Integer},args...;kwargs...
245+
ranks::AbstractArray{<:Integer}, # Distributed array with the rank IDs
246+
parts::NTuple{N,<:Integer}, # Number of ranks (parts) in each direction
247+
args...; ghost = map(i -> true, parts), kwargs...
245248
) where N
246249
desc = CartesianDescriptor(args...;kwargs...)
247250
@check N == length(desc.partition)
248251
@check prod(parts) == length(ranks)
249-
pdesc = DistributedCartesianDescriptor(ranks,parts,desc)
252+
pdesc = DistributedCartesianDescriptor(ranks,parts,desc,ghost)
250253
return CartesianDiscreteModel(pdesc)
251254
end
252255

253256
function Geometry.CartesianDiscreteModel(pdesc::DistributedCartesianDescriptor)
254257
desc = pdesc.descriptor
255258
isperiodic = desc.isperiodic
256259
if any(isperiodic)
260+
@notimplementedif pdesc.ghost != map(i->true,pdesc.mesh_partition)
257261
models, cell_indices = _cartesian_model_with_periodic_bcs(pdesc)
258262
else
259263
nc = desc.partition
260264
ranks = pdesc.ranks
261265
parts = pdesc.mesh_partition
262-
ghost = map(i->true,parts)
263-
cell_indices = uniform_partition(ranks,parts,nc,ghost,isperiodic)
266+
ghost = pdesc.ghost
267+
cell_indices = _uniform_partition(ranks,parts,nc,ghost,isperiodic)
264268
gcids = CartesianIndices(nc)
265269
models = map(cell_indices) do cell_indices
266270
cmin = gcids[first(cell_indices)]

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/GeometryTests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ function main(distribute,parts)
109109
Λs = Skeleton(Ωs)
110110
Γs = Boundary(Ωs)
111111

112+
# Multiple ghost layers
113+
model = CartesianDiscreteModel(ranks,parts,domain,cells;ghost=map(i->2,parts))
114+
112115
end
113116

114117
function test_local_part_face_labelings_consistency(lmodel::CartesianDiscreteModel{D},gids,gmodel) where {D}

0 commit comments

Comments
 (0)