13#ifndef PECLET_CORE_HALO_PARTICLE_MIGRATOR_HPP
14#define PECLET_CORE_HALO_PARTICLE_MIGRATOR_HPP
56 for (
int i = 0;
i < Dim; ++
i) {
57 double rel = (x[
i] - map_.origin[
i]) / map_.cellSize[
i];
59 if (map_.periodic[
i]) {
62 c = std::clamp<Index>(
c, 0,
gsize[
i] - 1);
75 for (
int i = 0;
i < Dim; ++
i) {
76 if (!map_.periodic[
i])
78 double L = map_.cellSize[
i] *
static_cast<double>(
gsize[
i]);
79 double rel = x[
i] - map_.origin[
i];
80 rel = std::fmod(std::fmod(
rel,
L) +
L,
L);
81 x[
i] = map_.origin[
i] +
rel;
90 const std::size_t n =
pos.size();
94 std::map<int, std::vector<char>>
outbox;
97 for (std::size_t
i = 0;
i < n; ++
i) {
100 if (owner == rank_) {
107 std::size_t off =
buf.size();
119 std::vector<std::pair<int, const std::vector<char>*>>
queue;
127 auto packNext = [&](std::vector<char>&
out) ->
int {
135 auto onRecv = [&](
int , std::vector<char>&
msg) {
137 for (std::size_t
i = 0;
i <
cnt; ++
i) {
143 std::size_t off =
payload.size();
157 int rank()
const {
return rank_; }
164 const auto&
o = dec_->origins()[
r];
165 const auto&
s = dec_->sizes()[
r];
168 for (
int i = 0;
i < Dim; ++
i) {
169 double lo = map_.origin[
i] +
o[
i] * map_.cellSize[
i];
170 double hi = map_.origin[
i] + (
o[
i] +
s[
i]) * map_.cellSize[
i];
171 double L = map_.cellSize[
i] *
static_cast<double>(
gsize[
i]);
175 if (map_.periodic[
i]) {
179 double bestGap = std::numeric_limits<double>::infinity();
181 for (
int c = 0;
c < nc; ++
c) {
183 double gap = (p <
lo) ? (
lo - p) : (p >
hi) ? (p -
hi) : 0.0;
204 const auto&
o = dec_->origins()[
r];
205 const auto&
s = dec_->sizes()[
r];
207 double lo[Dim],
hi[Dim],
cand[Dim][3];
209 for (
int d = 0; d < Dim; ++d) {
210 lo[d] = map_.origin[d] +
o[d] * map_.cellSize[d];
211 hi[d] = map_.origin[d] + (
o[d] +
s[d]) * map_.cellSize[d];
212 const double L = map_.cellSize[d] *
static_cast<double>(
gsize[d]);
215 if (map_.periodic[d]) {
222 for (
int d = 0; d < Dim; ++d)
225 for (
int idx = 0; idx <
total; ++idx) {
230 for (
int d = 0; d < Dim; ++d) {
231 const int k =
t % nc[d];
233 shift[d] =
cand[d][k];
236 const double p = x[d] + shift[d];
237 const double gap = (p <
lo[d]) ? (
lo[d] - p) : (p >
hi[d]) ? (p -
hi[d]) : 0.0;
261 std::map<int, std::vector<char>>
outbox;
263 for (std::size_t
i = 0;
i <
pos.size(); ++
i) {
270 std::size_t off =
buf.size();
278 std::vector<std::pair<int, const std::vector<char>*>>
queue;
281 queue.emplace_back(
kv.first, &
kv.second);
282 std::size_t
q = 0,
recv = 0;
284 auto packNext = [&](std::vector<char>&
out) ->
int {
292 auto onRecv = [&](
int , std::vector<char>&
msg) {
294 for (std::size_t
i = 0;
i <
cnt; ++
i) {
316 std::size_t sent_ = 0, received_ = 0;
IVec< Dim > cellOf(const Vec< Dim > &x) const
Global decomposition cell containing position x (after periodic wrap / boundary clamp).
std::size_t gatherGhosts(const std::vector< Vec< Dim > > &pos, const std::vector< char > &payload, std::size_t stride, double rcut, std::vector< Vec< Dim > > &ghostPos, std::vector< char > &ghostPayload)
Gather ghost copies of particles within rcut of this rank's block boundary.
const decomp::BlockDecomposer< Dim > & decomposer() const
std::size_t lastReceived() const
Vec< Dim > wrapPosition(Vec< Dim > x) const
Wrap a position into the periodic box (no-op on non-periodic axes).
std::size_t migrate(std::vector< Vec< Dim > > &pos, std::vector< char > &payload, std::size_t stride)
Reassign every particle to its owning rank.
void imagesWithinRcutOfBlock(const Vec< Dim > &x, int r, double rcut, bool allowIdentity, std::vector< Vec< Dim > > &outShifts) const
Append the shift (= image − x) of EVERY periodic image of x that comes within rcut of block r's AABB ...
bool withinRcutOfBlock(const Vec< Dim > &x, int r, double rcut, Vec< Dim > &img) const
True if x (via its closest periodic image) comes within rcut of block r's physical AABB.
void init(const decomp::BlockDecomposer< Dim > &dec, int rank, DomainMap< Dim > map, MPI_Comm comm=MPI_COMM_WORLD)
int ownerOf(const Vec< Dim > &x) const
Rank that owns the block containing position x (after periodic wrap / boundary clamp).
std::size_t lastSent() const
int MPI_Comm_size(MPI_Comm, int *s)
Index wrap(Index x, Index n)
Periodic wrap of a coordinate into [0, n): wrap(x, n) = (x % n + n) % n.
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).
Physical-space layout that maps a position to a global cell of the decomposition.
Vec< Dim > origin
physical coordinate of global cell (0,...)
std::array< bool, Dim > periodic
per-axis periodicity
Vec< Dim > cellSize
physical size of one global cell