Skip to content

Commit e5d8906

Browse files
authored
Merge pull request #1367 from parthenon-hpc-lab/lroberts36/update-dempsey/bvals
Updates to #1365
2 parents 1ba4121 + 7a7b06a commit e5d8906

20 files changed

+265
-165
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ add_library(parthenon
187187
mesh/mesh-gmg.cpp
188188
mesh/mesh.cpp
189189
mesh/mesh.hpp
190+
mesh/mesh_neighbors.hpp
190191
mesh/meshblock.hpp
191192
mesh/meshblock_pack.hpp
192193
mesh/meshblock.cpp

src/bvals/boundary_conditions.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,7 @@ TaskStatus ApplyBoundaryConditionsOnCoarseOrFine(std::shared_ptr<MeshBlockData<R
4343

4444
// We only need to call the BC on the coarse buffer if one of the neighbors
4545
// is at a coarser level than us.
46-
if (coarse) {
47-
bool has_coarser_neighbor = false;
48-
const int mylevel = pmb->loc.level();
49-
for (const auto &nb : pmb->neighbors) {
50-
if (nb.origin_loc.level() < mylevel) {
51-
has_coarser_neighbor = true;
52-
break;
53-
}
54-
}
55-
if (!has_coarser_neighbor) return TaskStatus::complete;
56-
}
46+
if (coarse && !pmb->HasCoarserNeighbors()) return TaskStatus::complete;
5747

5848
auto &tree_bnd_func = pmesh->forest.GetTreePtr(pmb->loc.tree())->MeshBndryFnctn;
5949
auto &tree_bnd_func_user =

src/bvals/bvals.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ void BoundarySwarm::SetupPersistentMPI() {
7070
std::shared_ptr<MeshBlock> pmb = GetBlockPointer();
7171

7272
// Initialize neighbor communications to other ranks
73-
for (int n = 0; n < pmb->neighbors.size(); n++) {
74-
NeighborBlock &nb = pmb->neighbors[n];
73+
const auto &neighbors = pmb->GetNeighbors();
74+
for (int n = 0; n < neighbors.size(); n++) {
75+
const NeighborBlock &nb = neighbors[n];
7576
// Neighbor on different MPI process
7677
if (nb.rank != Globals::my_rank) {
7778
send_tag[nb.bufid] = pmb->pmy_mesh->tag_map.GetTag(pmb.get(), nb);
@@ -93,8 +94,9 @@ void BoundarySwarm::Send(BoundaryCommSubset phase) {
9394
std::shared_ptr<MeshBlock> pmb = GetBlockPointer();
9495
// Fence to make sure buffers are loaded before sending
9596
pmb->exec_space.fence();
96-
for (int n = 0; n < pmb->neighbors.size(); n++) {
97-
NeighborBlock &nb = pmb->neighbors[n];
97+
const auto &neighbors = pmb->GetNeighbors();
98+
for (int n = 0; n < neighbors.size(); n++) {
99+
const NeighborBlock &nb = neighbors[n];
98100
if (nb.rank != Globals::my_rank) {
99101
#ifdef MPI_PARALLEL
100102
PARTHENON_REQUIRE(bd_var_.req_send[nb.bufid] == MPI_REQUEST_NULL,
@@ -131,8 +133,9 @@ void BoundarySwarm::Receive(BoundaryCommSubset phase) {
131133
#ifdef MPI_PARALLEL
132134
std::shared_ptr<MeshBlock> pmb = GetBlockPointer();
133135
const int &mylevel = pmb->loc.level();
134-
for (int n = 0; n < pmb->neighbors.size(); n++) {
135-
NeighborBlock &nb = pmb->neighbors[n];
136+
const auto &neighbors = pmb->GetNeighbors();
137+
for (int n = 0; n < neighbors.size(); n++) {
138+
const NeighborBlock &nb = neighbors[n];
136139
if (nb.rank != Globals::my_rank) {
137140
// Check to see if we got a message
138141
int test;

src/bvals/comms/bnd_info.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -425,17 +425,11 @@ ProResInfo ProResInfo::GetSet(MeshBlock *pmb, const NeighborBlock &nb,
425425
// This will select a superset of the boundaries that actually need to be restricted,
426426
// more logic could be added to only restrict boundary regions that abut boundary
427427
// regions that were filled by coarser neighbors
428-
bool restricted = false;
429-
int mylevel = pmb->loc.level();
430-
if (mylevel > 0) {
431-
for (const auto &nb : pmb->neighbors) {
432-
restricted = restricted || (nb.origin_loc.level() == (mylevel - 1));
433-
}
434-
}
428+
bool restricted = pmb->HasCoarserNeighbors();
435429

436430
for (auto el : v->GetTopologicalElements()) {
437431
out.IncludeTopoEl(el) = true;
438-
if (nb.origin_loc.level() < mylevel) {
432+
if (nb.origin_loc.level() < pmb->loc.level()) {
439433
out.refinement_op = RefinementOp_t::Prolongation;
440434
} else {
441435
if (restricted) {
@@ -455,7 +449,7 @@ ProResInfo ProResInfo::GetSet(MeshBlock *pmb, const NeighborBlock &nb,
455449
// I doubt that the extra calculations matter, but the storage overhead could
456450
// matter since each 6D indexer contains 18 ints and we are always carrying around
457451
// 10 indexers per bound info even if the field isn't allocated
458-
if (nb.origin_loc.level() < mylevel) {
452+
if (nb.origin_loc.level() < pmb->loc.level()) {
459453
for (auto el : {TE::CC, TE::F1, TE::F2, TE::F3, TE::E1, TE::E2, TE::E3, TE::NN})
460454
out.idxer[static_cast<int>(el)] =
461455
CalcIndices(nb, pmb, v, el, IndexRangeType::BoundaryExteriorRecv, true);

src/bvals/comms/boundary_communication.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ TaskStatus ReceiveBoundBufs(std::shared_ptr<MeshData<Real>> &md) {
233233
int ibound = 0;
234234
if (Globals::sparse_config.enabled && all_received) {
235235
ForEachBoundary<bound_type>(
236-
md, [&](auto pmb, sp_mbd_t rc, nb_t &nb, const sp_cv_t v) {
236+
md, [&](auto pmb, sp_mbd_t rc, const nb_t &nb, const sp_cv_t v) {
237237
const std::size_t ibuf = cache.idx_vec[ibound];
238238
auto &buf = *cache.buf_vec[ibuf];
239239

src/bvals/comms/build_boundary_buffers.cpp

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,23 @@ void BuildBoundaryBufferSubset(std::shared_ptr<MeshData<Real>> &md,
5454
std::unordered_map<std::size_t, std::size_t>
5555
nbufs_allocated; // total that are actually allocated
5656

57-
ForEachBoundary<BTYPE>(md, [&](auto pmb, sp_mbd_t /*rc*/, nb_t &nb, const sp_cv_t v) {
58-
// Calculate the required size of the buffer for this boundary
59-
int buf_size = GetBufferSize(pmb, nb, v);
60-
// LR: Multigrid logic requires blocks sending messages to themselves (since the same
61-
// block can show up on two multigrid levels). This doesn't require any data
62-
// transfer, so the message size can be zero. It is essentially just a flag to show
63-
// that the block is done being used on one level and can be used on the next level.
64-
if (pmb->gid == nb.gid && nb.offsets.IsCell()) buf_size = 0;
65-
66-
nbufs[buf_size] += 1; // relying on value init of int to 0 for initial entry
67-
nbufs_allocated[buf_size] += v->IsAllocated();
68-
});
69-
70-
ForEachBoundary<BTYPE>(md, [&](auto pmb, sp_mbd_t /*rc*/, nb_t &nb, const sp_cv_t v) {
57+
ForEachBoundary<BTYPE>(
58+
md, [&](auto pmb, sp_mbd_t /*rc*/, const nb_t &nb, const sp_cv_t v) {
59+
// Calculate the required size of the buffer for this boundary
60+
int buf_size = GetBufferSize(pmb, nb, v);
61+
// LR: Multigrid logic requires blocks sending messages to themselves (since the
62+
// same block can show up on two multigrid levels). This doesn't require any data
63+
// transfer, so the message size can be zero. It is essentially just a flag to
64+
// show that the block is done being used on one level and can be used on the
65+
// next level.
66+
if (pmb->gid == nb.gid && nb.offsets.IsCell()) buf_size = 0;
67+
68+
nbufs[buf_size] += 1; // relying on value init of int to 0 for initial entry
69+
nbufs_allocated[buf_size] += v->IsAllocated();
70+
});
71+
72+
ForEachBoundary<BTYPE>(md, [&](auto pmb, sp_mbd_t /*rc*/, const nb_t &nb,
73+
const sp_cv_t v) {
7174
// Calculate the required size of the buffer for this boundary
7275
int buf_size = GetBufferSize(pmb, nb, v);
7376
// See comment above on the same logic.
@@ -139,18 +142,19 @@ void BuildBoundaryBufferSubset(std::shared_ptr<MeshData<Real>> &md,
139142
template <BoundaryType BTYPE>
140143
void RegisterCoalescedCommsSubset(std::shared_ptr<MeshData<Real>> &md) {
141144
Mesh *pmesh = md->GetMeshPointer();
142-
ForEachBoundary<BTYPE>(md, [&](auto pmb, sp_mbd_t /*rc*/, nb_t &nb, const sp_cv_t v) {
143-
const int receiver_rank = nb.rank;
144-
const int sender_rank = Globals::my_rank;
145-
if (receiver_rank != sender_rank) {
146-
if constexpr (IsSender(BTYPE)) {
147-
pmesh->pcoalesced_comms->AddSendBuffer(md->partition, pmb, nb, v, BTYPE);
148-
}
149-
if constexpr (IsReceiver(BTYPE)) {
150-
pmesh->pcoalesced_comms->AddRecvBuffer(pmb, nb, v, BTYPE);
151-
}
152-
}
153-
});
145+
ForEachBoundary<BTYPE>(
146+
md, [&](auto pmb, sp_mbd_t /*rc*/, const nb_t &nb, const sp_cv_t v) {
147+
const int receiver_rank = nb.rank;
148+
const int sender_rank = Globals::my_rank;
149+
if (receiver_rank != sender_rank) {
150+
if constexpr (IsSender(BTYPE)) {
151+
pmesh->pcoalesced_comms->AddSendBuffer(md->partition, pmb, nb, v, BTYPE);
152+
}
153+
if constexpr (IsReceiver(BTYPE)) {
154+
pmesh->pcoalesced_comms->AddRecvBuffer(pmb, nb, v, BTYPE);
155+
}
156+
}
157+
});
154158
}
155159

156160
} // namespace

src/bvals/comms/bvals_utils.hpp

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,17 @@ void InitializeBufferCache(std::shared_ptr<MeshData<Real>> &md, COMM_MAP *comm_m
9999
std::vector<std::tuple<int, int, Mesh::channel_key_t>> key_order;
100100

101101
int boundary_idx = 0;
102-
ForEachBoundary<bound_type>(md, [&](auto pmb, sp_mbd_t rc, nb_t &nb, const sp_cv_t v) {
103-
auto key = KeyFunc(pmb, nb, v, bound_type);
104-
PARTHENON_DEBUG_REQUIRE(comm_map->count(key) > 0,
105-
"Boundary communicator does not exist");
106-
// Create a unique index by combining receiver gid (second element of the key
107-
// tuple) and geometric element index (fourth element of the key tuple)
108-
int recvr_idx = 27 * GetReceiverGid(key) + GetLocIdx(key);
109-
key_order.push_back({recvr_idx, boundary_idx, key});
110-
++boundary_idx;
111-
});
102+
ForEachBoundary<bound_type>(
103+
md, [&](auto pmb, sp_mbd_t rc, const nb_t &nb, const sp_cv_t v) {
104+
auto key = KeyFunc(pmb, nb, v, bound_type);
105+
PARTHENON_DEBUG_REQUIRE(comm_map->count(key) > 0,
106+
"Boundary communicator does not exist");
107+
// Create a unique index by combining receiver gid (second element of the key
108+
// tuple) and geometric element index (fourth element of the key tuple)
109+
int recvr_idx = 27 * GetReceiverGid(key) + GetLocIdx(key);
110+
key_order.push_back({recvr_idx, boundary_idx, key});
111+
++boundary_idx;
112+
});
112113

113114
// If desired, sort the keys and boundary indices by receiver_idx
114115
// std::sort(key_order.begin(), key_order.end(),
@@ -155,7 +156,8 @@ inline auto CheckSendBufferCacheForRebuild(std::shared_ptr<MeshData<Real>> md) {
155156
bool rebuild = false;
156157
bool other_communication_unfinished = false;
157158
int nbound = 0;
158-
ForEachBoundary<BOUND_TYPE>(md, [&](auto pmb, sp_mbd_t rc, nb_t &nb, const sp_cv_t v) {
159+
ForEachBoundary<BOUND_TYPE>(md, [&](auto pmb, sp_mbd_t rc, const nb_t &nb,
160+
const sp_cv_t v) {
159161
const std::size_t ibuf = cache.idx_vec[nbound];
160162
auto &buf = *(cache.buf_vec[ibuf]);
161163

@@ -187,7 +189,8 @@ inline auto CheckReceiveBufferCacheForRebuild(std::shared_ptr<MeshData<Real>> md
187189
bool rebuild = false;
188190
int nbound = 0;
189191

190-
ForEachBoundary<BOUND_TYPE>(md, [&](auto pmb, sp_mbd_t rc, nb_t &nb, const sp_cv_t v) {
192+
ForEachBoundary<BOUND_TYPE>(md, [&](auto pmb, sp_mbd_t rc, const nb_t &nb,
193+
const sp_cv_t v) {
191194
const std::size_t ibuf = cache.idx_vec[nbound];
192195
auto &buf = *cache.buf_vec[ibuf];
193196
if (ibuf < cache.bnd_info_h.size()) {
@@ -237,19 +240,20 @@ inline void RebuildBufferCache(std::shared_ptr<MeshData<Real>> md, int nbound,
237240
cache.prores_cache.Initialize(nbound, pkg);
238241

239242
int ibound = 0;
240-
ForEachBoundary<BOUND_TYPE>(md, [&](auto pmb, sp_mbd_t rc, nb_t &nb, const sp_cv_t v) {
241-
// bnd_info
242-
const std::size_t ibuf = cache.idx_vec[ibound];
243-
cache.bnd_info_h(ibuf) = BndInfoCreator(pmb, nb, v, cache.buf_vec[ibuf]);
244-
245-
// subsets ordering is same as in cache.bnd_info
246-
// RefinementFunctions_t owns all relevant functionality, so
247-
// only one ParArray2D needed.
248-
cache.prores_cache.RegisterRegionHost(ibuf, ProResInfoCreator(pmb, nb, v), v.get(),
249-
pkg);
250-
251-
++ibound;
252-
});
243+
ForEachBoundary<BOUND_TYPE>(
244+
md, [&](auto pmb, sp_mbd_t rc, const nb_t &nb, const sp_cv_t v) {
245+
// bnd_info
246+
const std::size_t ibuf = cache.idx_vec[ibound];
247+
cache.bnd_info_h(ibuf) = BndInfoCreator(pmb, nb, v, cache.buf_vec[ibuf]);
248+
249+
// subsets ordering is same as in cache.bnd_info
250+
// RefinementFunctions_t owns all relevant functionality, so
251+
// only one ParArray2D needed.
252+
cache.prores_cache.RegisterRegionHost(ibuf, ProResInfoCreator(pmb, nb, v),
253+
v.get(), pkg);
254+
255+
++ibound;
256+
});
253257
Kokkos::deep_copy(cache.bnd_info, cache.bnd_info_h);
254258
cache.prores_cache.CopyToDevice();
255259
}

src/bvals/comms/tag_map.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,26 @@ void TagMap::AddMeshDataToMap(std::shared_ptr<MeshData<Real>> &md) {
4343
auto pmb = rc->GetBlockPointer();
4444
// type_t var = []{...}() pattern defines and uses a lambda that
4545
// returns to reduce initializations of var
46-
auto *neighbors = [&pmb, &md] {
46+
const auto &neighbors = [&pmb, &md] {
4747
if constexpr (BOUND == BoundaryType::gmg_restrict_send)
48-
return pmb->loc.level() == md->grid.logical_level ? &(pmb->gmg_coarser_neighbors)
49-
: &(pmb->gmg_leaf_neighbors);
48+
return pmb->loc.level() == md->grid.logical_level ? pmb->GetGMGCoarserNeighbors()
49+
: pmb->GetGMGLeafNeighbors();
5050
if constexpr (BOUND == BoundaryType::gmg_restrict_recv)
51-
return pmb->gmg_finer_neighbors.size() > 0 ? &(pmb->gmg_finer_neighbors)
52-
: &(pmb->gmg_leaf_neighbors);
51+
return pmb->GetGMGFinerNeighbors().size() > 0 ? pmb->GetGMGFinerNeighbors()
52+
: pmb->GetGMGLeafNeighbors();
5353
if constexpr (BOUND == BoundaryType::gmg_prolongate_send)
54-
return &(pmb->gmg_finer_neighbors);
54+
return pmb->GetGMGFinerNeighbors();
5555
if constexpr (BOUND == BoundaryType::gmg_prolongate_recv)
56-
return &(pmb->gmg_coarser_neighbors);
56+
return pmb->GetGMGCoarserNeighbors();
5757
if constexpr (BOUND == BoundaryType::gmg_prolongate_recv)
58-
return &(pmb->gmg_coarser_neighbors);
58+
return pmb->GetGMGCoarserNeighbors();
5959
if constexpr (BOUND == BoundaryType::gmg_same)
6060
return pmb->loc.level() == md->grid.logical_level
61-
? &(pmb->gmg_same_neighbors)
62-
: &(pmb->gmg_composite_finer_neighbors);
63-
return &(pmb->neighbors);
61+
? pmb->GetGMGSameNeighbors()
62+
: pmb->GetGMGCompositeFinerNeighbors();
63+
return pmb->GetNeighbors();
6464
}();
65-
for (auto &nb : *neighbors) {
65+
for (const auto &nb : neighbors) {
6666
const int other_rank = nb.rank;
6767
if (map_.count(other_rank) < 1) map_[other_rank] = rank_pair_map_t();
6868
auto &pair_map = map_[other_rank];

0 commit comments

Comments
 (0)