22#include "../../alpine/ParticleContainer.hpp"
26 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
31 , numLocalParticles_m(0) {
35 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
38 Base::updateLayout(fl, mesh);
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) {
47 PAssert(rcutoff_m <= hLocalRegions(rank)[d].length() / 2 &&
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();
60 const size_type nLocalCells = std::floor(length / rcutoff_m);
62 numCells_m[d] = nLocalCells + 2 * numGhostCellsPerDim_m;
63 cellWidth_m[d] = length / nLocalCells;
64 totalCells_m *= numCells_m[d];
65 numLocalCells_m *= nLocalCells;
67 numGhostCells_m = totalCells_m - numLocalCells_m;
72 std::exclusive_scan(numCells_m.begin(), numCells_m.end(), cellStrides_m.begin(), 1,
75 cellParticleCount_m =
hash_type(
"cellParticleCount", totalCells_m);
76 cellStartingIdx_m =
hash_type(
"cellStartingIdx", totalCells_m + 1);
80 hash_type cellPermutationForward(
"cell permutation forward", totalCells_m);
81 hash_type cellPermutationBackward(
"cell permutation backward", totalCells_m);
84 hash_type localPrefixSum(
"local prefix sum", totalCells_m);
85 hash_type ghostPrefixSum(
"ghost prefix sum", totalCells_m);
86 const auto& numCells = numCells_m;
87 constexpr auto is = std::make_index_sequence<Dim>();
89 Kokkos::parallel_scan(
90 "scan_local", Kokkos::RangePolicy(0, totalCells_m),
92 const size_type val = isLocalCellIndex(is, toCellIndex(i, numCells), numCells);
94 localPrefixSum(i) = update;
98 Kokkos::parallel_scan(
99 "scan_ghost", Kokkos::RangePolicy(0, totalCells_m),
101 const size_type val = !isLocalCellIndex(is, toCellIndex(i, numCells), numCells);
103 ghostPrefixSum(i) = update;
109 const auto numLocalCells = numLocalCells_m;
111 "assign_permutations", Kokkos::RangePolicy(0, totalCells_m),
113 if (
const auto cellIdx = toCellIndex(i, numCells);
114 isLocalCellIndex(is, cellIdx, numCells)) {
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;
125 cellPermutationForward_m = cellPermutationForward;
126 cellPermutationBackward_m = cellPermutationBackward;
129 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
130 template <std::size_t... Idx>
131 KOKKOS_INLINE_FUNCTION
constexpr bool
133 const std::index_sequence<Idx...>&,
const vector_type& pos,
const region_type& globalRegion,
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>(
151 ++numAttributesInSpace;
153 if (numAttributesInSpace == 0) {
157 pc.template forAllAttributes<MemorySpace>(
158 [boundaryIndicesMirror = Kokkos::create_mirror_view_and_copy(
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) {
183 periodic[d] = this->getParticleBC()[2 * d];
187 return bc == BC::PERIODIC;
192 const auto& globalRegion = this->rlayout_m.getDomain();
193 const auto overlap = rcutoff_m;
195 const auto positions = pc.
R.getView();
197 constexpr auto is = std::make_index_sequence<Dim>();
201 "count boundary particles", numLoc,
202 KOKKOS_LAMBDA(
const size_t& i,
size_type& sum) {
203 if (isCloseToBoundary(is, positions(i), globalRegion,
periodic, overlap)) {
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) {
217 if (isCloseToBoundary(is, positions(i), globalRegion,
periodic, overlap)) {
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;
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());
260 createPeriodicGhostParticles(pc);
267 int nRanks =
Comm->size();
293 locate_type particleRanks(
"particles' MPI ranks");
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);
340 this->window_m.fence(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());
352 this->window_m.fence(0);
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) {
393 if (this->nRecvs_m[rank] > 0) {
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>
412 particleExchange(pc);
416 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
418 int rank,
const locate_type& ranks) {
423 using policy_type = Kokkos::RangePolicy<position_execution_space>;
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>
436 int rank,
const locate_type& ranks,
const locate_type& offsets,
hash_type& hash) {
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>
504 const locate_type& neighbors_view)
const {
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();
520 "mark_comm_ranks", Kokkos::RangePolicy(myRank, myRank + 1),
521 KOKKOS_LAMBDA(
const size_t& i) { is_remaining(i) =
false; });
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");
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>
544 bool_type& invalid, locate_type& nSends_dview, locate_type& sends_dview)
const {
545 const auto positions = pc.
R.getView();
546 const auto regions = this->rlayout_m.getdLocalRegions();
547 const auto myRank =
Comm->rank();
549 const T overlap = rcutoff_m;
550 constexpr auto is = std::make_index_sequence<Dim>();
554 locate_type counts(
"counts", localNum);
555 locate_type outsideIds(
"Particles outside of neighborhood", localNum);
563 locate_type neighbors_view = getFlatNeighbors(this->flayout_m.getNeighbors());
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);
592 if (positionInRegion(is, positions(i), regions(rank), overlap)) {
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);
634 locate_type nonNeighborsView = getNonNeighborRanks(neighbors_view);
635 if (outsideCount > 0 && nonNeighborsView.extent(0) > 0) {
636 Kokkos::deep_copy(outsideCounts, 0);
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);
646 if (positionInRegion(is, positions(pId), regions(rank), overlap)) {
647 Kokkos::atomic_increment(&outsideCounts(i));
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());
680 "ParticleSpatialLayout::locateParticles()", localNum, KOKKOS_LAMBDA(
const size_t& i) {
681 const size_t offset = rankOffsets(i);
683 if (positionInRegion(is, positions(i), regions(myRank), overlap)) {
684 ranks(offset) = myRank;
687 for (
size_t j = 0; j < neighbors_view.extent(0); ++j) {
688 const auto nRank = neighbors_view(j);
689 if (positionInRegion(is, positions(i), regions(nRank), overlap)) {
690 ranks(offset + local_count) = nRank;
701 if (outsideCount > 0) {
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);
710 if (positionInRegion(is, positions(i), regions(rank), overlap)) {
711 ranks(offset + local_count) = rank;
721 Kokkos::deep_copy(nSends_dview, 0);
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");
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
752 const std::index_sequence<Idx...>&,
const vector_type& pos,
const region_type& region,
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
785 const vector_type& pos,
const region_type& region,
const Vector<T, Dim>& cellWidth) {
787 for (
unsigned d = 0; d <
Dim; ++d) {
789 std::floor((pos[d] - region[d].
min()) / cellWidth[d]) + numGhostCellsPerDim_m);
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;
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(
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();
835 const auto totalCells = totalCells_m;
836 const auto numLocalCells = numLocalCells_m;
837 const auto localRegion = this->rlayout_m.gethLocalRegions()(rank);
838 const auto& cellWidth = cellWidth_m;
839 const auto cellStrides = cellStrides_m;
840 const auto cellPermutationForward = cellPermutationForward_m;
842 using int_type =
typename particle_neighbor_list_type::value_type;
845 hash_type cellIndex(
"cellIndex", numLoc);
846 hash_type cellParticleCount = cellParticleCount_m;
847 hash_type cellStartingIdx = cellStartingIdx_m;
848 hash_type cellCurrentIdx(
"cellCurrentIdx", totalCells + 1);
850 using range_policy = Kokkos::RangePolicy<position_execution_space>;
855 Kokkos::deep_copy(cellParticleCount, 0);
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 =
860 toFlatCellIndex(locCellIndex, cellStrides, cellPermutationForward);
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);
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));
911 numLocalParticles_m = numLocalParticles();
915 cellIndex_m = newCellIndex;
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>
953 this->rlayout_m.gethLocalRegions()(
Comm->rank()),
954 cellStartingIdx_m, cellIndex_m, cellParticleCount_m,
955 cellPermutationForward_m, cellPermutationBackward_m);
958 template <
typename T,
unsigned Dim,
class Mesh,
typename... Properties>
961 Properties...>::particle_neighbor_list_type
965 const auto locCellIndex =
971 const auto neighbors = getCellNeighbors(locCellIndex, particleNeighborData.
cellStrides,
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;
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 =
1022 const auto neighbors = getCellNeighbors(locCellIndex, particleNeighborData.
cellStrides,
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;
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>
1066 const auto cellStartingIdx = cellStartingIdx_m;
1067 const auto cellParticleCount = cellParticleCount_m;
1068 const auto cellPermutationForward = cellPermutationForward_m;
1069 const auto cellPermutationBackward = cellPermutationBackward_m;
1070 const auto& cellStrides = cellStrides_m;
1071 const auto& numCells = numCells_m;
1078 using team_policy_t = Kokkos::TeamPolicy<ExecutionSpace>;
1079 using team_t =
typename team_policy_t::member_type;
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 =
1094 getCellNeighbors(cellIdx, cellStrides, cellPermutationForward);
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);
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);
Implementations for FFT constructor/destructor and transforms.
KOKKOS_INLINE_FUNCTION Vector< T, Dim > max(const Vector< T, Dim > &a, const Vector< T, Dim > &b)
KOKKOS_INLINE_FUNCTION Vector< T, Dim > min(const Vector< T, Dim > &a, const Vector< T, Dim > &b)
void parallel_for(const std::string &name, const ExecPolicy &policy, const FunctorType &functor)
void parallel_reduce(const std::string &name, const ExecPolicy &policy, const FunctorType &functor, ReducerArgument &&... reducer)
std::unique_ptr< mpi::Communicator > Comm
void copyAttributes(ParticleContainer &pc, const index_type &boundaryIndices)
typename detail::ViewType< int, 1, MemorySpace >::view_type hash_type
void sortParticles(ParticleContainer &pc, const index_type &newIndex)
KOKKOS_INLINE_FUNCTION constexpr unsigned int countHypercubes(unsigned int dim)
void runForAllSpaces(Functor &&f)
A representation of an Object attribute.
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
typename particle_position_type::execution_space position_execution_space
KOKKOS_FUNCTION void init()
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
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 &)
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
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...
void particleExchange(ParticleContainer &pc)
exchange particles by scanning neighbor ranks first, only scan other ranks if needed....
detail::size_type size_type
typename FieldLayout_t::neighbor_list neighbor_list
Array of N rank lists, where N = number of hypercubes for the dimension Dim.
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
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
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< 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)