21#ifndef PECLET_CORE_HALO_PARTICLE_HALO_TOPOLOGY_HPP
22#define PECLET_CORE_HALO_PARTICLE_HALO_TOPOLOGY_HPP
53 numOwned_ =
pos.size();
56 const int me = mig_->rank();
59 std::map<int, std::vector<Index>>
sendMap;
60 std::map<int, std::vector<Vec<Dim>>>
shiftMap;
62 for (std::size_t
i = 0;
i <
pos.size(); ++
i) {
69 for (
int d = 0; d < Dim; ++d)
79 sendRankPos_[
r] = sendRanks_.size();
80 sendRanks_.push_back(
r);
81 sendIdx_.push_back(std::move(idx));
91 auto packNext = [&](std::vector<char>&
out) ->
int {
92 if (k >= sendRanks_.size())
94 int dst = sendRanks_[k];
98 std::memcpy(
out.data(),
sh.data(),
out.size());
103 recvRankPos_[
src] = recvRanks_.size();
104 recvRanks_.push_back(
src);
105 recvCount_.push_back(
cnt);
107 for (
int i = 0;
i <
cnt; ++
i)
108 shift_.push_back(
sh[
i]);
112 recvOffset_.assign(recvRanks_.size() + 1, 0);
113 for (std::size_t
i = 0;
i < recvCount_.size(); ++
i)
114 recvOffset_[
i + 1] = recvOffset_[
i] + recvCount_[
i];
115 numReceived_ = shift_.size();
123 std::vector<Vec<Dim>>
imgs;
124 for (std::size_t
i = 0;
i <
pos.size(); ++
i) {
127 for (
const auto&
sh :
imgs) {
128 selfIdx_.push_back(
static_cast<Index>(
i));
129 selfShift_.push_back(
sh);
133 for (
const auto&
sh : selfShift_)
134 shift_.push_back(
sh);
135 numGhost_ = shift_.size();
138 ghostPos_.assign(numGhost_,
Vec<Dim>{});
151 Index off = recvOffset_[p];
152 for (
int i = 0;
i < recvCount_[p]; ++
i)
153 for (
int d = 0; d < Dim; ++d)
154 ghost[off +
i][d] =
in[
i][d] + shift_[off +
i][d];
157 for (std::size_t
j = 0;
j < selfIdx_.size(); ++
j)
158 for (
int d = 0; d < Dim; ++d)
159 ghost[numReceived_ +
j][d] =
owned[selfIdx_[
j]][d] + shift_[numReceived_ +
j][d];
163 template <
typename T>
166 Index off = recvOffset_[p];
167 for (
int i = 0;
i < recvCount_[p]; ++
i)
168 ghost[off +
i] =
in[
i];
171 for (std::size_t
j = 0;
j < selfIdx_.size(); ++
j)
172 ghost[numReceived_ +
j] =
owned[selfIdx_[
j]];
177 template <
typename T>
181 const int ns =
static_cast<int>(sendRanks_.size());
182 const int nr =
static_cast<int>(recvRanks_.size());
185 for (
int k = 0; k <
ns; ++k) {
186 rbuf[k].resize(sendIdx_[k].size());
188 sendRanks_[k], 7504, mig_->comm(), &
rreq[k]);
190 for (
int p = 0; p <
nr; ++p) {
191 Index off = recvOffset_[p];
192 sbuf[p].assign(ghost + off, ghost + off + recvCount_[p]);
194 recvRanks_[p], 7504, mig_->comm(), &
sreq[p]);
197 for (
int k = 0; k <
ns; ++k) {
198 auto& idx = sendIdx_[k];
199 for (std::size_t
i = 0;
i < idx.size(); ++
i)
203 for (std::size_t
j = 0;
j < selfIdx_.size(); ++
j)
204 owned[selfIdx_[
j]] += ghost[numReceived_ +
j];
212 template <
typename T,
typename Store>
214 const int ns =
static_cast<int>(sendRanks_.size());
215 const int nr =
static_cast<int>(recvRanks_.size());
218 for (
int p = 0; p <
nr; ++p) {
219 rbuf[p].resize(recvCount_[p]);
221 recvRanks_[p],
tag, mig_->comm(), &
rreq[p]);
223 for (
int k = 0; k <
ns; ++k) {
224 auto& idx = sendIdx_[k];
225 sbuf[k].resize(idx.size());
226 for (std::size_t
i = 0;
i < idx.size(); ++
i)
229 sendRanks_[k],
tag, mig_->comm(), &
sreq[k]);
232 for (
int p = 0; p <
nr; ++p)
233 store(
static_cast<std::size_t
>(p),
rbuf[p].data());
260 t.sendOffsets.push_back(0);
261 for (
const auto& idx : sendIdx_) {
262 t.sendCounts.push_back(
static_cast<int>(idx.size()));
264 t.sendIdx.push_back(
id);
265 t.sendOffsets.push_back(
static_cast<int>(
t.sendIdx.size()));
267 t.recvRanks = recvRanks_;
268 t.recvCounts = recvCount_;
269 t.recvOffsets.assign(recvOffset_.begin(),
270 recvOffset_.begin() +
static_cast<std::ptrdiff_t
>(recvRanks_.size()));
272 t.selfIdx = selfIdx_;
273 t.numReceived =
static_cast<Index>(numReceived_);
279 std::size_t numOwned_ = 0, numGhost_ = 0;
282 std::vector<int> sendRanks_;
283 std::vector<std::vector<Index>> sendIdx_;
284 std::map<int, std::size_t> sendRankPos_;
287 std::vector<int> recvRanks_;
288 std::vector<int> recvCount_;
289 std::vector<Index> recvOffset_;
290 std::map<int, std::size_t> recvRankPos_;
294 std::vector<Index> selfIdx_;
295 std::vector<Vec<Dim>> selfShift_;
296 std::size_t numReceived_ = 0;
298 std::vector<Vec<Dim>>
300 std::vector<Vec<Dim>> ghostPos_;
void init(const ParticleMigrator< Dim > &mig)
Bind to a migrator (provides the decomposition, domain map, rank and comm).
void forwardPositions(const Vec< Dim > *owned, Vec< Dim > *ghost)
owned[N] -> ghost[G], with the periodic image shift added (use for positions).
void forward(const T *owned, T *ghost)
owned[N] -> ghost[G], verbatim (translation-invariant fields: velocity, id, radius,...
std::size_t numOwned() const
void build(const std::vector< Vec< Dim > > &pos, double rcut, bool includePeriodicSelf=false)
(Re)establish the owner<->ghost correspondence: every owned particle within rcut of another rank's bl...
void reverse(const T *ghost, T *owned)
ghost[G] -> owned[N], accumulated (T must have operator+=).
const std::vector< Vec< Dim > > & ghostPositions() const
std::size_t numGhost() const
int MPI_Comm_size(MPI_Comm, int *s)
int MPI_Waitall(int, MPI_Request *, MPI_Status *)
#define MPI_STATUSES_IGNORE
int MPI_Isend(const void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request *)
int MPI_Irecv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request *)
Kokkos::View< T *, MemSpace > View
1D device array.
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).
std::vector< Vec< Dim > > shift
std::vector< int > sendOffsets
std::vector< int > recvRanks
std::vector< Index > sendIdx
std::vector< int > sendCounts
std::vector< Index > recvOffsets
std::vector< int > recvCounts
std::vector< Index > selfIdx
std::vector< int > sendRanks