65 const std::size_t posBytes = Dim *
sizeof(double);
66 const std::size_t recBytes = posBytes + stride;
71 double org[Dim], csz[Dim];
74 for (
int d = 0; d < Dim; ++d) {
76 csz[d] = cellSize_[d];
78 per[d] = periodic_[d];
80 View<int> dest(Kokkos::view_alloc(
"pmd::dest", Kokkos::WithoutInitializing),
81 static_cast<std::size_t
>(n));
83 "pmd::wrap_bin", Kokkos::RangePolicy<ExecSpace>(0, n), KOKKOS_LAMBDA(
const Index i) {
85 for (
int d = 0; d < Dim; ++d)
86 x[d] = pos(i * Dim + d);
87 for (
int d = 0; d < Dim; ++d)
89 const double L = csz[d] *
static_cast<double>(gsz[d]);
90 double rel = x[d] - org[d];
91 rel -= L * Kokkos::floor(rel / L);
94 for (
int d = 0; d < Dim; ++d)
95 pos(i * Dim + d) = x[d];
97 for (
int d = 0; d < Dim; ++d) {
98 const double rel = (x[d] - org[d]) / csz[d];
99 Index c =
static_cast<Index>(Kokkos::floor(rel));
101 c = ((c % gsz[d]) + gsz[d]) % gsz[d];
103 c = c < 0 ? 0 : (c >= gsz[d] ? gsz[d] - 1 : c);
107 while (sd(node) != -1)
108 node = (g[sd(node)] < sv(node)) ? 2 * node + 1 : 2 * node + 2;
109 dest(i) =
static_cast<int>(sv(node));
113 auto hdest = Kokkos::create_mirror_view(dest);
114 Kokkos::deep_copy(hdest, dest);
115 std::vector<Index> keepIdx;
116 keepIdx.reserve(
static_cast<std::size_t
>(n));
117 std::map<int, std::vector<Index>> sendByRank;
118 for (
Index i = 0; i < n; ++i) {
119 if (hdest(i) == rank_)
120 keepIdx.push_back(i);
122 sendByRank[hdest(i)].push_back(i);
124 const Index keep =
static_cast<Index>(keepIdx.size());
125 std::vector<int> sendRanks, sendCounts;
126 std::vector<Index> sendIdxFlat;
127 for (
auto& kv : sendByRank) {
128 sendRanks.push_back(kv.first);
129 sendCounts.push_back(
static_cast<int>(kv.second.size()));
130 for (
Index s : kv.second)
131 sendIdxFlat.push_back(s);
133 const Index nSend =
static_cast<Index>(sendIdxFlat.size());
134 sent_ =
static_cast<std::size_t
>(nSend);
139 std::vector<double> hSendPos(
static_cast<std::size_t
>(nSend) * Dim);
140 std::vector<char> hSendPay(
static_cast<std::size_t
>(nSend) * stride);
143 View<double> sp(Kokkos::view_alloc(
"pmd::sendPos", Kokkos::WithoutInitializing),
144 static_cast<std::size_t
>(nSend) * Dim);
145 View<char> spay(Kokkos::view_alloc(
"pmd::sendPay", Kokkos::WithoutInitializing),
146 static_cast<std::size_t
>(nSend) * stride);
147 Kokkos::parallel_for(
148 "pmd::pack", Kokkos::RangePolicy<ExecSpace>(0, nSend), KOKKOS_LAMBDA(
const Index j) {
149 const Index s = si(j);
150 for (
int d = 0; d < Dim; ++d)
151 sp(j * Dim + d) = pos(s * Dim + d);
152 for (std::size_t b = 0; b < stride; ++b)
153 spay(j * stride + b) = payload(s * stride + b);
156 auto hsp = Kokkos::create_mirror_view(sp);
157 Kokkos::deep_copy(hsp, sp);
158 for (std::size_t k = 0; k < hSendPos.size(); ++k)
159 hSendPos[k] = hsp(k);
161 auto hspay = Kokkos::create_mirror_view(spay);
162 Kokkos::deep_copy(hspay, spay);
163 for (std::size_t k = 0; k < hSendPay.size(); ++k)
164 hSendPay[k] = hspay(k);
170 ensureScratch(pos.extent(0), payload.extent(0));
175 Kokkos::parallel_for(
176 "pmd::compact", Kokkos::RangePolicy<ExecSpace>(0, keep), KOKKOS_LAMBDA(
const Index k) {
177 const Index s = ki(k);
178 for (
int d = 0; d < Dim; ++d)
179 tp(k * Dim + d) = pos(s * Dim + d);
180 for (std::size_t b = 0; b < stride; ++b)
181 tpay(k * stride + b) = payload(s * stride + b);
183 Kokkos::deep_copy(Kokkos::subview(pos, std::pair<std::size_t, std::size_t>(
184 0,
static_cast<std::size_t
>(keep) * Dim)),
185 Kokkos::subview(tmpPos_, std::pair<std::size_t, std::size_t>(
186 0,
static_cast<std::size_t
>(keep) * Dim)));
189 Kokkos::subview(payload, std::pair<std::size_t, std::size_t>(
190 0,
static_cast<std::size_t
>(keep) * stride)),
191 Kokkos::subview(tmpPay_, std::pair<std::size_t, std::size_t>(
192 0,
static_cast<std::size_t
>(keep) * stride)));
197 std::vector<std::vector<char>> outbox(sendRanks.size());
200 for (std::size_t r = 0; r < sendRanks.size(); ++r) {
201 const Index cnt = sendCounts[r];
202 std::vector<char>& buf = outbox[r];
203 buf.resize(
static_cast<std::size_t
>(cnt) * recBytes);
204 for (
Index j = 0; j < cnt; ++j) {
205 char* rec = buf.data() +
static_cast<std::size_t
>(j) * recBytes;
206 std::memcpy(rec, &hSendPos[(
static_cast<std::size_t
>(base) + j) * Dim], posBytes);
208 std::memcpy(rec + posBytes, &hSendPay[(
static_cast<std::size_t
>(base) + j) * stride],
214 std::vector<double> hRecvPos;
215 std::vector<char> hRecvPay;
220 auto packNext = [&](std::vector<char>& out) ->
int {
221 if (q >= outbox.size())
223 int d = sendRanks[q];
228 auto onRecv = [&](
int , std::vector<char>& msg) {
229 const std::size_t cnt = msg.size() / recBytes;
230 for (std::size_t i = 0; i < cnt; ++i) {
231 const char* rec = msg.data() + i * recBytes;
232 std::size_t po = hRecvPos.size();
233 hRecvPos.resize(po + Dim);
234 std::memcpy(&hRecvPos[po], rec, posBytes);
236 std::size_t yo = hRecvPay.size();
237 hRecvPay.resize(yo + stride);
238 std::memcpy(&hRecvPay[yo], rec + posBytes, stride);
243 nbx.
exchange(packNext, onRecv, 7411);
247 const Index recv =
static_cast<Index>(received_);
250 Kokkos::parallel_for(
251 "pmd::unpack_pos", Kokkos::RangePolicy<ExecSpace>(0, recv), KOKKOS_LAMBDA(
const Index j) {
252 for (
int d = 0; d < Dim; ++d)
253 pos((keep + j) * Dim + d) = rp(j * Dim + d);
257 Kokkos::parallel_for(
258 "pmd::unpack_pay", Kokkos::RangePolicy<ExecSpace>(0, recv),
259 KOKKOS_LAMBDA(
const Index j) {
260 for (std::size_t b = 0; b < stride; ++b)
261 payload((keep + j) * stride + b) = ry(j * stride + b);