Skip to content

Commit da40001

Browse files
committed
Merge branch 'expand-ghost' of github.com:gridap/GridapDistributed.jl into polytopal
2 parents f489bfb + 9908b60 commit da40001

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
@@ -260,19 +260,20 @@ function _setup_face_gids!(dmodel::GenericDistributedDiscreteModel{Dc},dim) wher
260260
end
261261

262262
# CartesianDiscreteModel
263-
struct DistributedCartesianDescriptor{A,B,C}
263+
struct DistributedCartesianDescriptor{A,B,C,D}
264264
ranks::A
265265
mesh_partition::B
266266
descriptor::C
267+
ghost::D
267268
function DistributedCartesianDescriptor(
268269
ranks::AbstractArray{<:Integer},
269270
mesh_partition::NTuple{Dc,<:Integer},
270-
descriptor::CartesianDescriptor{Dc}
271+
descriptor::CartesianDescriptor{Dc},
272+
ghost = map(i -> true, mesh_partition)
271273
) where Dc
272-
A = typeof(ranks)
273-
B = typeof(mesh_partition)
274-
C = typeof(descriptor)
275-
new{A,B,C}(ranks,mesh_partition,descriptor)
274+
A, B = typeof(ranks), typeof(mesh_partition)
275+
C, D = typeof(descriptor), typeof(ghost)
276+
new{A,B,C,D}(ranks,mesh_partition,descriptor,ghost)
276277
end
277278
end
278279

@@ -292,44 +293,47 @@ function emit_cartesian_descriptor(
292293
new_mesh_partition
293294
) where Dc
294295
f(a) = Tuple(PartitionedArrays.getany(emit(a)))
295-
a, b, c, d = map(new_ranks) do rank
296+
a, b, c, d, e = map(new_ranks) do rank
296297
if rank == 1
297298
desc = pdesc.descriptor
298299
@assert desc.map === identity
299-
Float64[desc.origin.data...], Float64[desc.sizes...], Int[desc.partition...], Bool[desc.isperiodic...]
300+
Float64[desc.origin.data...], Float64[desc.sizes...], Int[desc.partition...], Bool[desc.isperiodic...], Int16[pdesc.ghost...]
300301
else
301-
Float64[], Float64[], Int[], Bool[]
302+
Float64[], Float64[], Int[], Bool[], Int16[]
302303
end
303304
end |> tuple_of_arrays
304-
origin, sizes, partition, isperiodic = VectorValue(f(a)...), f(b), f(c), f(d)
305+
origin, sizes, partition, isperiodic, ghost = VectorValue(f(a)...), f(b), f(c), f(d), f(e)
305306
new_desc = CartesianDescriptor(origin,sizes,partition;isperiodic)
306-
return DistributedCartesianDescriptor(new_ranks,new_mesh_partition,new_desc)
307+
return DistributedCartesianDescriptor(new_ranks,new_mesh_partition,new_desc,ghost)
307308
end
308309

309310
const DistributedCartesianDiscreteModel{Dc,Dp,A,B,C} =
310311
GenericDistributedDiscreteModel{Dc,Dp,<:AbstractArray{<:CartesianDiscreteModel},B,<:DistributedCartesianDescriptor}
311312

312313
function Geometry.CartesianDiscreteModel(
313-
ranks::AbstractArray{<:Integer},parts::NTuple{N,<:Integer},args...;kwargs...
314+
ranks::AbstractArray{<:Integer}, # Distributed array with the rank IDs
315+
parts::NTuple{N,<:Integer}, # Number of ranks (parts) in each direction
316+
args...; ghost = map(i -> true, parts), kwargs...
314317
) where N
315318
desc = CartesianDescriptor(args...;kwargs...)
316319
@check N == length(desc.partition)
317320
@check prod(parts) == length(ranks)
318-
pdesc = DistributedCartesianDescriptor(ranks,parts,desc)
321+
pdesc = DistributedCartesianDescriptor(ranks,parts,desc,ghost)
319322
return CartesianDiscreteModel(pdesc)
320323
end
321324

322325
function Geometry.CartesianDiscreteModel(pdesc::DistributedCartesianDescriptor)
323326
desc = pdesc.descriptor
324327
isperiodic = desc.isperiodic
325328
if any(isperiodic)
329+
@notimplementedif pdesc.ghost != map(i->true,pdesc.mesh_partition)
326330
models, cell_indices = _cartesian_model_with_periodic_bcs(pdesc)
327331
else
328332
nc = desc.partition
329333
ranks = pdesc.ranks
330334
parts = pdesc.mesh_partition
331-
ghost = map(i->true,parts)
332-
cell_indices = uniform_partition(ranks,parts,nc,ghost,isperiodic)
335+
ghost = pdesc.ghost
336+
cell_indices = _uniform_partition(ranks,parts,nc,ghost,isperiodic)
333337
gcids = CartesianIndices(nc)
334338
models = map(cell_indices) do cell_indices
335339
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)