26 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
35 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
42 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
44 const auto rank =
Comm->rank();
45 const auto hLocalRegions = this->
rlayout_m.gethLocalRegions();
46 for (
unsigned d = 0; d <
Dim; ++d) {
48 "Cutoff is too big with respect to region. "
49 "Particle could be on 3 or more ranks ins one dimension");
58 for (
unsigned d = 0; d <
Dim; ++d) {
59 const T length = hLocalRegions(rank)[d].length();
87 constexpr auto is = std::make_index_sequence<Dim>();
89 Kokkos::parallel_scan(
94 localPrefixSum(i) =
update;
98 Kokkos::parallel_scan(
103 ghostPrefixSum(i) =
update;
110 Kokkos::parallel_for(
111 "assign_permutations", Kokkos::RangePolicy(0,
totalCells_m),
115 const size_type localIdx = localPrefixSum(i);
116 cellPermutationForward(i) = localIdx;
117 cellPermutationBackward(localIdx) = i;
119 const size_type ghostIdx = numLocalCells + ghostPrefixSum(i);
120 cellPermutationForward(i) = ghostIdx;
121 cellPermutationBackward(ghostIdx) = i;
129 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
130 template <std::size_t... Idx>
131 KOKKOS_INLINE_FUNCTION
constexpr bool
136 && (pos[Idx] < globalRegion[Idx].
min() + overlap
137 || pos[Idx] > globalRegion[Idx].
max() - overlap))
143 template <
typename ParticleContainer,
typename index_type>
146 const auto numBoundaryParticles = boundaryIndices.size();
148 size_t numAttributesInSpace = 0;
149 pc.template forAllAttributes<MemorySpace>(
150 [&numAttributesInSpace]<
typename Attribute>(Attribute&) {
151 ++numAttributesInSpace;
153 if (numAttributesInSpace == 0) {
157 pc.template forAllAttributes<MemorySpace>(
158 [boundaryIndicesMirror = Kokkos::create_mirror_view_and_copy(
159 MemorySpace(), boundaryIndices)]<
typename Attribute>(Attribute& att) {
160 att->internalCopy(boundaryIndicesMirror);
172 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
173 template <
class ParticleContainer>
182 for (
unsigned d = 0; d <
Dim; ++d) {
187 return bc == BC::PERIODIC;
192 const auto& globalRegion = this->
rlayout_m.getDomain();
195 const auto positions = pc.
R.getView();
197 constexpr auto is = std::make_index_sequence<Dim>();
200 Kokkos::parallel_reduce(
201 "count boundary particles", numLoc,
202 KOKKOS_LAMBDA(
const size_t& i,
size_type& sum) {
207 Kokkos::Sum<size_type>(numBoundaryParticles));
208 if (numBoundaryParticles == 0) {
213 hash_type boundaryIndices(
"boundaryIndices", numBoundaryParticles);
214 Kokkos::parallel_scan(
215 "count boundary particles", numLoc,
216 KOKKOS_LAMBDA(
const size_t& i,
size_type& sum,
bool final) {
219 boundaryIndices(sum) = i;
232 for (
unsigned d = 0; d <
Dim; ++d) {
236 const auto min = globalRegion[d].min();
237 const auto length = globalRegion[d].length();
238 const auto middle =
min + length / 2;
239 Kokkos::parallel_for(
242 Kokkos::RangePolicy<position_execution_space>(numLoc,
243 numLoc + numBoundaryParticles),
244 KOKKOS_LAMBDA(
const size_t& i) {
245 positions(i)[d] += positions(i)[d] > middle ? -length : length;
252 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
253 template <
class ParticleContainer>
259 this->
applyBC(pc.
R, this->rlayout_m.getDomain());
267 int nRanks =
Comm->size();
294 locate_type particleRankOffsets(
"particles' MPI rank offsets", localnum + 1);
301 bool_type invalidParticles(
"validity of particles", localnum);
306 locate_type rankSendCount_dview(
"rankSendCount Device", nRanks);
311 locate_type destinationRanks_dview(
"destinationRanks Device", nRanks);
316 const auto [nInvalid, nDestinationRanks] =
317 locateParticles(pc, particleRanks, particleRankOffsets, invalidParticles,
318 rankSendCount_dview, destinationRanks_dview);
321 auto rankSendCount_hview =
322 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), rankSendCount_dview);
325 auto destinationRanks_hview =
326 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), destinationRanks_dview);
338 std::fill(this->
nRecvs_m.begin(), this->nRecvs_m.end(), 0);
343 for (
size_t ridx = 0; ridx < nDestinationRanks; ridx++) {
344 int rank = destinationRanks_hview[ridx];
345 if (rank ==
Comm->rank()) {
349 const int* src_ptr = &rankSendCount_hview(rank);
350 this->
window_m.template put<int>(src_ptr, rank,
Comm->rank());
361 std::vector<MPI_Request> requests(0);
365 for (
size_t ridx = 0; ridx < nDestinationRanks; ridx++) {
366 int rank = destinationRanks_hview[ridx];
367 if (rank ==
Comm->rank()) {
370 hash_type hash(
"hash", rankSendCount_hview(rank));
371 fillHash(rank, particleRanks, particleRankOffsets, hash);
392 for (
int rank = 0; rank < nRanks; ++rank) {
401 if (requests.size() > 0) {
402 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
409 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
410 template <
class ParticleContainer>
416 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
423 using policy_type = Kokkos::RangePolicy<position_execution_space>;
424 Kokkos::parallel_reduce(
425 "ParticleSpatialLayout::numberOfSends()", policy_type(0, ranks.extent(0)),
426 KOKKOS_LAMBDA(
const size_t i,
size_t& num) {
427 num +=
static_cast<size_t>(rank == ranks(i));
434 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
439 using policy_type = Kokkos::RangePolicy<position_execution_space>;
440 Kokkos::parallel_scan(
441 "ParticleSpatialLayout::fillHash()", policy_type(0, offsets.extent(0) - 1),
442 KOKKOS_LAMBDA(
const size_t i,
int& idx,
const bool final) {
446 bool belongs_to_rank =
false;
447 const size_t start_rank_idx = offsets(i);
448 const size_t end_rank_idx = offsets(i + 1);
450 for (
size_t rank_idx = start_rank_idx; rank_idx < end_rank_idx; ++rank_idx) {
451 if (ranks(rank_idx) == rank) {
452 belongs_to_rank =
true;
457 if (
final && belongs_to_rank) {
461 if (belongs_to_rank) {
470 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
477 std::set<int> neighborSet;
478 for (
const auto& componentNeighbors : neighbors) {
479 for (
const auto& nrank : componentNeighbors) {
480 neighborSet.insert(nrank);
485 locate_type flatNeighbors(
"Nearest neighbors IDs", neighborSet.size());
486 auto hostMirror = Kokkos::create_mirror_view(flatNeighbors);
489 for (
const auto& neighbor : neighborSet) {
490 hostMirror(i) = neighbor;
494 Kokkos::deep_copy(flatNeighbors, hostMirror);
496 return flatNeighbors;
501 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
506 const auto numNonNeighborRanks =
Comm->size() - neighbors_view.extent(0) - 1;
507 locate_type nonNeighborRanks(
"Non Neighbor Ranks", numNonNeighborRanks);
508 if (numNonNeighborRanks == 0) {
509 return nonNeighborRanks;
513 const auto total_ranks =
Comm->rank();
514 bool_type is_remaining(
"is_remaining", total_ranks);
515 Kokkos::deep_copy(is_remaining,
true);
518 const auto myRank =
Comm->rank();
519 Kokkos::parallel_for(
520 "mark_comm_ranks", Kokkos::RangePolicy(myRank, myRank + 1),
521 KOKKOS_LAMBDA(
const size_t& i) { is_remaining(i) =
false; });
522 Kokkos::parallel_for(
523 "mark_comm_ranks", neighbors_view.extent(0),
524 KOKKOS_LAMBDA(
const size_t& i) { is_remaining(neighbors_view(i)) =
false; });
528 Kokkos::View<size_type> counter(
"counter");
529 Kokkos::parallel_for(
530 "fill_remaining", total_ranks, KOKKOS_LAMBDA(
const size_t& i) {
531 if (is_remaining(i)) {
532 const size_type idx = Kokkos::atomic_fetch_inc(&counter());
533 nonNeighborRanks(idx) = i;
536 return nonNeighborRanks;
539 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
540 template <
typename ParticleContainer>
541 std::pair<detail::size_type, detail::size_type>
545 const auto positions = pc.
R.getView();
546 const auto regions = this->
rlayout_m.getdLocalRegions();
547 const auto myRank =
Comm->rank();
550 constexpr auto is = std::make_index_sequence<Dim>();
555 locate_type outsideIds(
"Particles outside of neighborhood", localNum);
583 Kokkos::parallel_for(
584 "ParticleSpatialLayout::locateParticles()", localNum, KOKKOS_LAMBDA(
const size_t& i) {
585 const bool inCurr =
positionInRegion(is, positions(i), regions(myRank), overlap);
588 invalid(i) = !inCurr;
590 for (
size_type j = 0; j < neighbors_view.extent(0); ++j) {
591 const size_type rank = neighbors_view(j);
607 Kokkos::parallel_scan(
608 "count_outside", localNum,
610 const bool inCurr = !invalid(i);
611 if (
final && !inCurr) {
612 outsideIds(val.
count[1]) = i;
614 bool increment[2] = {invalid(i), !inCurr};
620 invalidCount = red_val.
count[0];
621 outsideCount = red_val.
count[1];
633 locate_type outsideCounts(
"counts of outside neighbors", outsideCount);
635 if (outsideCount > 0 && nonNeighborsView.extent(0) > 0) {
636 Kokkos::deep_copy(outsideCounts, 0);
637 Kokkos::parallel_for(
638 "ParticleSpatialLayout::leftParticles()",
639 mdrange_type({0, 0}, {outsideCount, nonNeighborsView.extent(0)}),
640 KOKKOS_LAMBDA(
const size_t i,
const size_type j) {
643 const auto rank = nonNeighborsView(j);
647 Kokkos::atomic_increment(&outsideCounts(i));
651 Kokkos::parallel_for(
652 "ParticleSpatialLayout::leftParticles()", outsideCount,
653 KOKKOS_LAMBDA(
const size_t& i) { counts(outsideIds(i)) += outsideCounts(i); });
660 Kokkos::deep_copy(Kokkos::subview(rankOffsets, 0), 0);
661 Kokkos::parallel_scan(
662 "ParticleSpatialLayout::locateParticles()", localNum,
663 KOKKOS_LAMBDA(
const size_t i,
size_type& localSum,
const bool final) {
664 const auto count_i = counts(i);
666 rankOffsets(i + 1) = localSum + count_i;
673 auto total_assignments = Kokkos::create_mirror_view(Kokkos::subview(rankOffsets, localNum));
674 Kokkos::deep_copy(total_assignments, Kokkos::subview(rankOffsets, localNum));
676 Kokkos::resize(ranks, total_assignments());
679 Kokkos::parallel_for(
680 "ParticleSpatialLayout::locateParticles()", localNum, KOKKOS_LAMBDA(
const size_t& i) {
681 const size_t offset = rankOffsets(i);
684 ranks(offset) = myRank;
687 for (
size_t j = 0; j < neighbors_view.extent(0); ++j) {
688 const auto nRank = neighbors_view(j);
690 ranks(offset + local_count) = nRank;
701 if (outsideCount > 0) {
702 Kokkos::parallel_for(
703 "ParticleSpatialLayout::leftParticles()", outsideCount,
704 KOKKOS_LAMBDA(
const size_t& i) {
707 const size_type offset = rankOffsets(pId) + counts(pId);
708 for (
size_t local_count = 0, j = 0; j < nonNeighborsView.extent(0); ++j) {
709 const auto rank = nonNeighborsView(j);
711 ranks(offset + local_count) = rank;
721 Kokkos::deep_copy(nSends_dview, 0);
722 Kokkos::parallel_for(
723 "Calculate nSends", Kokkos::RangePolicy<size_t>(0, ranks.extent(0)),
724 KOKKOS_LAMBDA(
const size_t i) {
726 Kokkos::atomic_increment(&nSends_dview(rank));
731 Kokkos::View<size_type> rankSends(
"Number of Ranks we need to send to");
732 Kokkos::parallel_for(
733 "Calculate sends", Kokkos::RangePolicy<size_t>(0, nSends_dview.extent(0)),
734 KOKKOS_LAMBDA(
const size_t rank) {
735 if (nSends_dview(rank) != 0) {
736 size_type index = Kokkos::atomic_fetch_inc(&rankSends());
737 sends_dview(index) = rank;
742 Kokkos::deep_copy(temp, rankSends);
745 return {invalidCount, temp};
748 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
749 template <std::size_t... Idx>
750 KOKKOS_INLINE_FUNCTION
constexpr bool
754 return ((pos[Idx] > region[Idx].
min() - overlap) && ...)
755 && ((pos[Idx] <= region[Idx].max() + overlap) && ...);
758 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
759 KOKKOS_INLINE_FUNCTION
constexpr
764 return cellPermutationForward(cellIndex.
dot(cellStrides));
767 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
768 KOKKOS_INLINE_FUNCTION
constexpr
775 ndIndex[d] = nonPermutedIndex % numCells[d];
776 nonPermutedIndex /= numCells[d];
781 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
782 KOKKOS_INLINE_FUNCTION
constexpr
787 for (
unsigned d = 0; d <
Dim; ++d) {
794 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
795 template <std::size_t... Idx>
797 const std::index_sequence<Idx...>&,
const CellIndex_t& index,
799 return !((index[Idx] == 0 || index[Idx] == numCells[Idx] - 1) || ...);
803 template <
typename ParticleContainer,
typename index_type>
806 size_t num_attributes_in_space = 0;
807 pc.template forAllAttributes<MemorySpace>([&]<
typename Attribute>(Attribute&) {
808 ++num_attributes_in_space;
810 if (num_attributes_in_space == 0) {
814 pc.template forAllAttributes<MemorySpace>(
815 [newIndexMirror = Kokkos::create_mirror_view_and_copy(
816 MemorySpace(), newIndex)]<
typename Attribute>(Attribute& att) {
817 att->applyPermutation(newIndexMirror);
824 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
825 template <
class ParticleContainer>
832 const auto rank =
Comm->rank();
834 const auto positions = pc.
R.getView();
837 const auto localRegion = this->
rlayout_m.gethLocalRegions()(rank);
842 using int_type =
typename particle_neighbor_list_type::value_type;
845 hash_type cellIndex(
"cellIndex", numLoc);
848 hash_type cellCurrentIdx(
"cellCurrentIdx", totalCells + 1);
850 using range_policy = Kokkos::RangePolicy<position_execution_space>;
855 Kokkos::deep_copy(cellParticleCount, 0);
856 Kokkos::parallel_for(
857 "CalcCellIndices", range_policy(0, numLoc), KOKKOS_LAMBDA(
const size_t& i) {
858 const auto locCellIndex =
getCellIndex(positions(i), localRegion, cellWidth);
859 const auto locCellIndexFlat =
861 Kokkos::atomic_increment(&cellParticleCount(locCellIndexFlat));
862 cellIndex(i) = locCellIndexFlat;
867 Kokkos::parallel_scan(
868 "CalcStartingIndices", range_policy(0, totalCells),
869 KOKKOS_LAMBDA(
const size_t i, int_type& localSum,
bool isFinal) {
871 cellStartingIdx(i) = localSum;
873 localSum += cellParticleCount(i);
877 Kokkos::subview(cellStartingIdx, Kokkos::make_pair(totalCells, totalCells + 1)),
881 Kokkos::deep_copy(cellCurrentIdx, cellStartingIdx);
885 hash_type newCellIndex(
"cellIndex", numLoc);
890 Kokkos::parallel_for(
891 "Calculate new Indices", range_policy(0, numLoc), KOKKOS_LAMBDA(
const size_type& i) {
892 const auto locCellIndex = cellIndex(i);
893 const size_type newIdx = Kokkos::atomic_fetch_inc(&cellCurrentIdx(locCellIndex));
894 newIndex(i) = newIdx;
895 newCellIndex(newIdx) = locCellIndex;
907 auto numLocalParticles =
908 Kokkos::create_mirror_view(Kokkos::subview(cellStartingIdx, numLocalCells));
909 Kokkos::deep_copy(numLocalParticles, Kokkos::subview(cellStartingIdx, numLocalCells));
920 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
921 KOKKOS_INLINE_FUNCTION
constexpr
923 Properties...>::cell_particle_neighbor_list_type
926 const hash_type& cellPermutationForward) {
933 for (
size_type neighborIdx = 0; neighborIdx < numNeighbors; ++neighborIdx) {
937 auto neighborCellIndex = cellIndex;
938 for (
unsigned d = 0; d <
Dim; ++d) {
939 neighborCellIndex(d) += (temp % 3) - 1;
943 neighborIndices[neighborIdx] =
944 toFlatCellIndex(neighborCellIndex, cellStrides, cellPermutationForward);
946 return neighborIndices;
949 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
958 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
961 Properties...>::particle_neighbor_list_type
965 const auto locCellIndex =
978 Kokkos::Array<typename hash_type::value_type, numNeighbors> neighborSizes;
979 Kokkos::Array<typename hash_type::value_type, numNeighbors> neighborOffsets;
981 for (
size_type neighborIdx = 0; neighborIdx < numNeighbors; ++neighborIdx) {
983 neighborSizes[neighborIdx] = n;
984 maxParticleInNeighbors = std::max<size_type>(n, maxParticleInNeighbors);
985 neighborOffsets[neighborIdx] = totalParticleInNeighbors;
986 totalParticleInNeighbors += n;
993 Kokkos::parallel_for(
994 "collect neighbors", mdrange_policy({0, 0}, {numNeighbors, maxParticleInNeighbors}),
996 if (j < neighborSizes[i]) {
997 neighborList(neighborOffsets[i] + j) =
1003 return neighborList;
1006 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
1009 Properties...>::particle_neighbor_list_type
1016 const auto locCellIndexFlat = particleNeighborData.
cellIndex(particleIndex);
1017 const auto locCellIndex =
1029 Kokkos::Array<size_type, numNeighbors> neighborSizes;
1030 Kokkos::Array<size_type, numNeighbors + 1> neighborOffsets;
1032 for (
size_type neighborIdx = 0; neighborIdx < numNeighbors; ++neighborIdx) {
1034 maxParticleInNeighbors = std::max<size_type>(n, maxParticleInNeighbors);
1035 neighborOffsets[neighborIdx] = totalParticleInNeighbors;
1036 totalParticleInNeighbors += n;
1038 neighborOffsets[numNeighbors] = totalParticleInNeighbors;
1044 Kokkos::parallel_for(
1045 "collect neighbors", mdrange_policy({0, 0}, {numNeighbors, maxParticleInNeighbors}),
1047 const auto numParticlesInCell = neighborOffsets[i + 1] - neighborOffsets[i];
1048 if (j < numParticlesInCell) {
1049 neighborList(neighborOffsets[i] + j) =
1056 return neighborList;
1059 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
1060 template <
typename ExecutionSpace,
typename Functor>
1078 using team_policy_t = Kokkos::TeamPolicy<ExecutionSpace>;
1079 using team_t =
typename team_policy_t::member_type;
1080 Kokkos::parallel_for(
1081 "ParticleSpatialOverlapLayout::forEachPair()",
1082 team_policy_t(
numLocalCells_m, Kokkos::AUTO()), KOKKOS_LAMBDA(
const team_t& team) {
1083 const size_type cellIdxFlat = team.league_rank();
1084 if (cellParticleCount(cellIdxFlat) == 0) {
1088 const auto cellParticleOffset = cellStartingIdx(cellIdxFlat);
1089 const auto numCellParticles = cellParticleCount(cellIdxFlat);
1092 const auto cellIdx =
toCellIndex(cellPermutationBackward(cellIdxFlat), numCells);
1093 const auto cellNeighbors =
1097 Kokkos::parallel_for(
1098 Kokkos::TeamThreadRange(team, numCellNeighbors), [&](
const size_t& n) {
1099 const auto neighborCellIdx = cellNeighbors[n];
1100 const auto neighborCellParticleOffset = cellStartingIdx(neighborCellIdx);
1101 const auto numNeighborCellParticles = cellParticleCount(neighborCellIdx);
1106 Kokkos::parallel_for(Kokkos::ThreadVectorMDRange<Kokkos::Rank<2>, team_t>(
1107 team, numCellParticles, numNeighborCellParticles),
1108 [&](
const size_t& i,
const size_t& j) {
1109 const auto particleIdx = cellParticleOffset + i;
1110 const auto neighborIdx =
1111 neighborCellParticleOffset + j;
1113 if (neighborIdx == particleIdx) {
1117 f(particleIdx, neighborIdx);
KOKKOS_INLINE_FUNCTION Vector< T, Dim > min(const Vector< T, Dim > &a, const Vector< T, Dim > &b)
std::unique_ptr< mpi::Communicator > Comm
void copyAttributes(ParticleContainer &pc, const index_type &boundaryIndices)
void sortParticles(ParticleContainer &pc, const index_type &newIndex)
KOKKOS_INLINE_FUNCTION constexpr unsigned int countHypercubes(unsigned int dim)
void runForAllSpaces(Functor &&f)
void internalDestroy(const Kokkos::View< bool *, Properties... > &invalid, const size_type destroyNum)
void recvFromRank(int rank, int tag, size_type nRecvs)
void setLocalNum(size_type size)
void sendToRank(int rank, int tag, std::vector< MPI_Request > &requests, const HashType &hash)
particle_position_type R
view of particle positions
size_type getLocalNum() const
const bc_container_type & getParticleBC() const
void applyBC(const particle_position_type &R, const NDRegion< T, Dim > &nr)
typename particle_position_type::execution_space position_execution_space
mpi::rma::Window< mpi::rma::Active > window_m
RegionLayout_t rlayout_m
The RegionLayout which determines where our particles go.
std::vector< size_type > nRecvs_m
typename detail::ViewType< bool, 1, position_memory_space >::view_type bool_type
typename region_view_type::value_type region_type
Type of a single Region object.
typename detail::ViewType< int, 1, position_memory_space >::view_type locate_type
detail::hash_type< position_memory_space > hash_type
void updateLayout(FieldLayout< Dim > &, Mesh &)
typename Base::vector_type vector_type
FieldLayout_t & flayout_m
The FieldLayout containing information on nearest neighbors.
KOKKOS_FUNCTION void init()
Vector< size_type, Dim > numCells_m
! number of cells in each dimension
ParticleNeighborData getParticleNeighborData() const
void fillHash(int rank, const locate_type &ranks, const locate_type &offsets, hash_type &hash)
utility function to collect all indices of particles to send to given rank
Vector< size_type, Dim > cellStrides_m
! strides to compute cell indices
static constexpr size_type numGhostCellsPerDim_m
! number of ghost cells
KOKKOS_INLINE_FUNCTION static constexpr cell_particle_neighbor_list_type getCellNeighbors(const CellIndex_t &cellIndex, const Vector< size_type, Dim > &cellStrides, const hash_type &cellPermutationForward)
get all indices of cell neighbors of a given nd-cell-index
void updateLayout(FieldLayout< Dim > &, Mesh &)
size_type numGhostCells_m
! the number of interior cells
KOKKOS_INLINE_FUNCTION static constexpr CellIndex_t toCellIndex(FlatCellIndex_t nonPermutedIndex, const Vector< size_type, Dim > &numCells)
size_type numberOfSends(int rank, const locate_type &ranks)
utility function to compute how many particles to sent to a given rank
locate_type getNonNeighborRanks(const locate_type &neighbors_view) const
utility function to get a view of all non-neighboring ranks
KOKKOS_INLINE_FUNCTION static constexpr bool isLocalCellIndex(const std::index_sequence< Idx... > &, const CellIndex_t &index, const Vector< size_type, Dim > &numCells)
determines whether cell index is local cell index
ParticleSpatialLayout< T, Dim, Mesh, PositionProperties... > Base
KOKKOS_INLINE_FUNCTION static constexpr FlatCellIndex_t toFlatCellIndex(const CellIndex_t &cellIndex, const Vector< size_type, Dim > &cellStrides, hash_type cellPermutationForward)
convert a nd-cell-index to flat cell index
static KOKKOS_FUNCTION particle_neighbor_list_type getParticleNeighbors(index_t particleIndex, const ParticleNeighborData &particleNeighborData)
Function to get particle neighbors depending on index (possible inside Kokkos parallel region) make s...
const T rcutoff_m
! overlap in each dimension
void particleExchange(ParticleContainer &pc)
exchange particles by scanning neighbor ranks first, only scan other ranks if needed....
hash_type cellPermutationBackward_m
! the inverse of cellPermutationForward_m
size_type numLocalParticles_m
! the number of local particles (particles in local cells)
hash_type cellParticleCount_m
! view of number of particles in each cell
detail::size_type size_type
hash_type cellStartingIdx_m
! cell i contains particles cellStartingIdx_m(i), ..., cellStartingIdx_m(i + 1) - 1
typename FieldLayout_t::neighbor_list neighbor_list
Array of N rank lists, where N = number of hypercubes for the dimension Dim.
Vector< size_type, Dim > CellIndex_t
std::pair< detail::size_type, detail::size_type > locateParticles(const ParticleContainer &pc, locate_type &ranks, locate_type &rankOffsets, bool_type &invalid, locate_type &nSends_dview, locate_type &sends_dview) const
This function determines to which rank particles need to be sent after the iteration step....
typename hash_type::value_type index_t
KOKKOS_INLINE_FUNCTION static constexpr CellIndex_t getCellIndex(const vector_type &pos, const region_type ®ion, const Vector< T, Dim > &cellWidth)
get the nd-cell-index of a position
void createPeriodicGhostParticles(ParticleContainer &pc)
copies particles close to the boundary and offsets them to their closest periodic image
KOKKOS_INLINE_FUNCTION static constexpr bool positionInRegion(const std::index_sequence< Idx... > &, const vector_type &pos, const region_type ®ion, T overlap)
determines whether a position is in a region including its overlap
size_type totalCells_m
! the number of total cells
KOKKOS_INLINE_FUNCTION static constexpr bool isCloseToBoundary(const std::index_sequence< Idx... > &, const vector_type &pos, const region_type ®ion, Vector< bool, Dim > periodic, T overlap)
determines whether a position is within overlap to the boundary of a region
void update(ParticleContainer &pc)
updates particles by exchanging them across ranks according to their positions. then constructs the p...
ParticleSpatialOverlapLayout()
hash_type particle_neighbor_list_type
typename CellIndex_t::value_type FlatCellIndex_t
void forEachPair(Functor &&f) const
call functor for each combination i, j. make sure to call update first
size_type numLocalCells_m
! the number of ghost cells
hash_type cellPermutationForward_m
void buildCells(ParticleContainer &pc)
builds the cell structure, sorts the particles according to the cells and makes sure only local parti...
locate_type getFlatNeighbors(const neighbor_list &neighbors) const
utility function to get a flat view of all neighbor processes
void initializeCells()
initializes all data necessary for the cells
Kokkos::Array< size_type, detail::countHypercubes(Dim)> cell_particle_neighbor_list_type
Vector< T, Dim > cellWidth_m
! width of cells in each dimension
Vector< size_type, Dim > cellStrides
hash_type cellPermutationBackward
hash_type cellParticleCount
hash_type cellPermutationForward
hash_type cellStartingIdx
Vector< T, Dim > cellWidth
Vector< size_type, Dim > numCells
KOKKOS_INLINE_FUNCTION T dot(const Vector< T, Dim > &rhs) const
Timing::TimerRef TimerRef
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)