8inline constexpr bool always_false_v =
false;
11template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
12 template<
class>
class Allocator,
class CellAssignor>
15template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
16 template<
class>
class Allocator,
class CellAssignor>
19template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
20 template<
class>
class Allocator,
class CellAssignor>
21NeighborParticleContainer_impl<T_ParticleType, NArrayReal, NArrayInt, Allocator, CellAssignor>
22::NeighborParticleContainer_impl (
ParGDBBase* gdb,
int ncells)
24 m_num_neighbor_cells(ncells)
29template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
30 template<
class>
class Allocator,
class CellAssignor>
37 m_num_neighbor_cells(nneighbor)
42template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
43 template<
class>
class Allocator,
class CellAssignor>
51 m_num_neighbor_cells(nneighbor)
56template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
57 template<
class>
class Allocator,
class CellAssignor>
61 for (
int ii = 0; ii < numRealCommComps(); ++ii) {
62 ghost_real_comp.push_back(1);
64 for (
int ii = 0; ii < numIntCommComps(); ++ii) {
65 ghost_int_comp.push_back(1);
70template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
71 template<
class>
class Allocator,
class CellAssignor>
75 ghost_real_comp[i] = value;
79template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
80 template<
class>
class Allocator,
class CellAssignor>
84 ghost_int_comp[i] = value;
88template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
89 template<
class>
class Allocator,
class CellAssignor>
94 for (
int ii = 0; ii < numRealCommComps(); ++ii) {
95 if (ghost_real_comp[ii]) {
99 for (
int ii = 0; ii < numIntCommComps(); ++ii) {
100 if (ghost_int_comp[ii]) {
101 comm_size +=
sizeof(
int);
104 if ( enableInverse() ) { comm_size += 4*
sizeof(
int); }
105 cdata_size = comm_size;
108template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
109 template<
class>
class Allocator,
class CellAssignor>
115 this->SetParticleBoxArray(lev, ba);
116 this->SetParticleDistributionMap(lev, dmap);
117 this->Redistribute();
120template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
121 template<
class>
class Allocator,
class CellAssignor>
126 this->SetParticleBoxArray(lev, ba);
127 this->SetParticleDistributionMap(lev, dmap);
128 this->Redistribute();
131template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
132 template<
class>
class Allocator,
class CellAssignor>
137 for (
int lev = 0; lev < this->numLevels(); ++lev)
139 this->SetParticleBoxArray(lev, ba[lev]);
140 this->SetParticleDistributionMap(lev, dmap[lev]);
142 this->Redistribute();
145template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
146 template<
class>
class Allocator,
class CellAssignor>
151 BL_PROFILE(
"NeighborParticleContainer::areMasksValid");
153 resizeContainers(this->numLevels());
155 for (
int lev = 0; lev < this->numLevels(); ++lev)
157 BoxArray ba = this->ParticleBoxArray(lev);
160 if (mask_ptr[lev] ==
nullptr ||
172 const auto* dx_lev = this->Geom(lev).CellSize();
174 for (
int d = 1; d < AMREX_SPACEDIM; ++d) {
175 dx_min = std::min(dx_min, dx_lev[d]);
177 int required =
static_cast<int>(std::ceil(search_radius / dx_min));
178 if (mask_ptr[lev]->nGrow(0) < required) {
return false; }
184template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
185 template<
class>
class Allocator,
class CellAssignor>
190 BL_PROFILE(
"NeighborParticleContainer::BuildMasks");
192 if (this->numLevels() == 1) { use_mask =
true; }
193 else { use_mask =
false; }
195 resizeContainers(this->numLevels());
197 for (
int lev = 0; lev < this->numLevels(); ++lev)
199 BoxArray ba = this->ParticleBoxArray(lev);
202 const Geometry& geom = this->Geom(lev);
208 int mask_ncells = m_num_neighbor_cells;
210 const auto* dx_lev = geom.
CellSize();
212 for (
int d = 1; d < AMREX_SPACEDIM; ++d) {
213 dx_min = std::min(dx_min, dx_lev[d]);
215 mask_ncells = std::max(mask_ncells,
216 static_cast<int>(std::ceil(search_radius / dx_min)));
219 mask_ptr[lev] = std::make_unique<iMultiFab>(ba, dmap,
int(num_mask_comps), mask_ncells);
220 mask_ptr[lev]->setVal(-1, mask_ncells);
227 const Box& box = mfi.tilebox();
228 const int grid_id = mfi.
index();
229 const int tile_id = mfi.LocalTileIndex();
230 (*mask_ptr[lev])[mfi].
template setVal<RunOn::Host>(grid_id, box, MaskComps::grid, 1);
231 (*mask_ptr[lev])[mfi].
template setVal<RunOn::Host>(tile_id, box, MaskComps::tile, 1);
232 (*mask_ptr[lev])[mfi].
template setVal<RunOn::Host>(lev , box, MaskComps::level, 1);
239template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
240 template<
class>
class Allocator,
class CellAssignor>
245 BL_PROFILE(
"NeighborParticleContainer::GetNeighborCommTags");
247 local_neighbors.clear();
248 neighbor_procs.clear();
256 const Box& box = mfi.growntilebox();
258 const int grid = (*mask_ptr[lev])[mfi](iv, MaskComps::grid);
260 const int tile = (*mask_ptr[lev])[mfi](iv, MaskComps::tile);
261 const int level = (*mask_ptr[lev])[mfi](iv, MaskComps::level);
262 const int global_proc = this->ParticleDistributionMap(level)[grid];
264 NeighborCommTag comm_tag(proc, level, grid, tile);
265 local_neighbors.push_back(comm_tag);
267 neighbor_procs.push_back(proc);
275 for (
int lev = 0; lev < this->numLevels(); ++lev)
279 const Box& box = mfi.validbox();
281 GetCommTagsBox(comm_tags, lev, box, search_radius);
282 for (
auto const& tag : comm_tags) {
283 local_neighbors.push_back(tag);
285 neighbor_procs.push_back(tag.proc_id);
296template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
297 template<
class>
class Allocator,
class CellAssignor>
304 for (
int l = src_lev; l < lev; ++l) {
305 ref_fac *= this->GetParGDB()->refRatio(l);
307 }
else if (src_lev > lev) {
308 for (
int l = src_lev; l > lev; --l) {
309 ref_fac *= this->GetParGDB()->refRatio(l-1);
316template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
317 template<
class>
class Allocator,
class CellAssignor>
323 std::vector< std::pair<int, Box> > isects;
326 for (
int lev = 0; lev < this->numLevels(); ++lev) {
338 const auto* dx_lev = this->Geom(lev).CellSize();
340 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
341 grow_cells[d] = std::max(1,
static_cast<int>(
342 std::ceil(search_radius / dx_lev[d])));
344 box.
grow(grow_cells);
348 const Periodicity& periodicity = this->Geom(lev).periodicity();
349 const std::vector<IntVect>& pshifts = periodicity.
shiftIntVect();
350 const BoxArray& ba = this->ParticleBoxArray(lev);
352 for (
auto const& pshift : pshifts)
354 const Box& pbox = box + pshift;
355 bool first_only =
false;
357 for (
const auto& isec : isects) {
358 const int grid = isec.first;
359 const int global_proc = this->ParticleDistributionMap(lev)[grid];
363 if (ba[grid].contains(iv))
366 this->do_tiling, this->tile_size, tbx);
367 tags.push_back(NeighborCommTag(proc, lev, grid, tile));
375template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
376 template<
class>
class Allocator,
class CellAssignor>
381 BL_PROFILE(
"NeighborParticleContainer::cacheNeighborInfo");
385 resizeContainers(this->numLevels());
394 std::map<NeighborCommTag, Vector<NeighborIndexMap> > remote_map;
398 std::map<NeighborCommTag, Vector<Vector<NeighborIndexMap> > > tmp_remote_map;
400 local_map.resize(this->numLevels());
401 tmp_local_map.resize(this->numLevels());
405 for (
int lev = 0; lev < this->numLevels(); ++lev) {
407 for (
int i = 0; i < std::ssize(local_neighbors); ++i) {
408 const NeighborCommTag& comm_tag = local_neighbors[i];
409 tmp_remote_map[comm_tag].resize(num_threads);
410 remote_map[comm_tag];
411 PairIndex index(comm_tag.grid_id, comm_tag.tile_id);
412 tmp_local_map[lev][index].resize(num_threads);
413 local_map[lev][index];
414 buffer_tag_cache[lev][index].resize(num_threads);
418 for (
int lev = 0; lev < this->numLevels(); ++lev) {
427 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
429 const int& grid = pti.index();
430 const int& tile = pti.LocalTileIndex();
433 NeighborCopyTag src_tag(lev, grid, tile);
435 auto& cache = buffer_tag_cache[lev][src_index][thread_num];
437 auto const ptd = pti.GetParticleTile().getConstParticleTileData();
438 for (
int i = 0; i < pti.numParticles(); ++i) {
439 getNeighborTags(tags, ptd[i], m_num_neighbor_cells, src_tag, pti, search_radius);
442 for (
int j = 0; j < std::ssize(tags); ++j) {
443 NeighborCopyTag& tag = tags[j];
445 if (tag.grid < 0) {
continue; }
448 const int cache_index = cache.size();
449 cache.push_back(tag);
451 const int global_who = this->ParticleDistributionMap(tag.level)[tag.grid];
453 NeighborIndexMap nim(tag.level, dst_index.first, dst_index.second, -1,
454 lev, src_index.first, src_index.second,
455 cache_index, thread_num);
457 auto& tmp = tmp_local_map[tag.level][dst_index];
459 buffer.push_back(nim);
461 NeighborCommTag comm_tag(who, tag.level, tag.grid, tag.tile);
463 buffer.push_back(nim);
472 for (
int lev = 0; lev < this->numLevels(); ++lev) {
477 for (
MFIter mfi = this->MakeMFIter(lev); mfi.
isValid(); ++mfi) {
478 const int grid = mfi.index();
479 const int tile = mfi.LocalTileIndex();
481 for (
int i = 0; i < num_threads; ++i) {
482 local_map[lev][index].insert(local_map[lev][index].
end(),
483 tmp_local_map[lev][index][i].
begin(),
484 tmp_local_map[lev][index][i].
end());
485 tmp_local_map[lev][index][i].erase(tmp_local_map[lev][index][i].
begin(),
486 tmp_local_map[lev][index][i].
end());
492 typename std::map<NeighborCommTag, Vector<Vector<NeighborIndexMap> > >::iterator it;
495#pragma omp single nowait
497 for (it=tmp_remote_map.begin(); it != tmp_remote_map.end(); it++) {
499#pragma omp task firstprivate(it)
502 const NeighborCommTag& tag = it->first;
504 for (
int i = 0; i < num_threads; ++i) {
505 remote_map[tag].insert(remote_map[tag].
end(), tmp[i].begin(), tmp[i].end());
506 tmp[i].erase(tmp[i].
begin(), tmp[i].end());
511 for (
int lev = 0; lev < this->numLevels(); ++lev) {
513 for (
MFIter mfi = this->MakeMFIter(lev); mfi.
isValid(); ++mfi) {
514 const int grid = mfi.index();
515 const int tile = mfi.LocalTileIndex();
518 const int num_ghosts = map.
size();
519 neighbors[lev][dst_index].define(this->NumRuntimeRealComps(),
520 this->NumRuntimeIntComps(),
521 nullptr,
nullptr, this->arena());
522 neighbors[lev][dst_index].resize(num_ghosts);
523 local_neighbor_sizes[lev][dst_index] = neighbors[lev][dst_index].size();
527 for (
int lev = 0; lev < this->numLevels(); ++lev) {
528 for (
MFIter mfi = this->MakeMFIter(lev); mfi.
isValid(); ++mfi) {
529 const int grid = mfi.index();
530 const int tile = mfi.LocalTileIndex();
533 const int num_ghosts = map.
size();
535#pragma omp parallel for
537 for (
int i = 0; i < num_ghosts; ++i) {
538 const NeighborIndexMap& nim = map[i];
539 PairIndex src_index(nim.src_grid, nim.src_tile);
542 tags[nim.src_index].dst_index = i;
543 AMREX_ASSERT(
size_t(tags[nim.src_index].dst_index) < neighbors[nim.dst_level][dst_index].size());
549 std::map<int, int> tile_counts;
550 for (
const auto& kv: remote_map) {
551 tile_counts[kv.first.proc_id] += 1;
554 for (
const auto& kv: remote_map) {
555 if (kv.first.proc_id == MyProc) {
continue; }
557 buffer.resize(
sizeof(
int));
558 std::memcpy(buffer.data(), &tile_counts[kv.first.proc_id],
sizeof(
int));
561 for (
auto& kv : remote_map) {
562 if (kv.first.proc_id == MyProc) {
continue; }
563 int np = kv.second.size();
564 int data_size = np * cdata_size;
566 size_t old_size = buffer.
size();
567 size_t new_size = buffer.
size() + 4*
sizeof(
int) + data_size;
568 buffer.resize(new_size);
569 char* dst = &buffer[old_size];
570 std::memcpy(dst, &(kv.first.level_id),
sizeof(
int)); dst +=
sizeof(
int);
571 std::memcpy(dst, &(kv.first.grid_id ),
sizeof(
int)); dst +=
sizeof(
int);
572 std::memcpy(dst, &(kv.first.tile_id ),
sizeof(
int)); dst +=
sizeof(
int);
573 std::memcpy(dst, &data_size,
sizeof(
int)); dst +=
sizeof(
int);
574 size_t buffer_offset = old_size + 4*
sizeof(
int);
576#pragma omp parallel for
578 for (
int i = 0; i < np; ++i) {
579 const NeighborIndexMap& nim = kv.second[i];
580 PairIndex src_index(nim.src_grid, nim.src_tile);
582 tags[nim.src_index].dst_index = buffer_offset + i*cdata_size;
586 if ( enableInverse() )
588 for (
int lev = 0; lev < this->numLevels(); ++lev)
590 for (
const auto& kv : neighbors[lev])
592 inverse_tags[lev][kv.first].resize(kv.second.size());
598template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
599 template<
class>
class Allocator,
class CellAssignor>
604 int nGrow,
const NeighborCopyTag& src_tag,
const MyParIter& pti,
607 getNeighborTags(tags, p,
IntVect(
AMREX_D_DECL(nGrow, nGrow, nGrow)), src_tag, pti, search_radius);
610template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
611 template<
class>
class Allocator,
class CellAssignor>
619 Box shrink_box = pti.tilebox();
620 shrink_box.
grow(-nGrow);
625 const Box& tile_box = pti.tilebox();
626 const int src_lev = src_tag.level;
627 const auto* dx = this->Geom(src_lev).CellSize();
628 const auto* plo = this->Geom(src_lev).ProbLo();
629 bool is_interior =
true;
630 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
633 if ((p.pos(d) - face_lo) < search_radius ||
634 (face_hi - p.pos(d)) < search_radius) {
639 if (is_interior) {
return; }
648 const IntVect& iv = this->Index(p, lev);
649 if (shrink_box.
contains(iv)) {
return; }
651 const Periodicity& periodicity = this->Geom(lev).periodicity();
652 const Box& domain = this->Geom(lev).Domain();
658 for (
int ii = -nGrow[0]; ii < nGrow[0] + 1; ii += nGrow[0]) {,
659 for (
int jj = -nGrow[1]; jj < nGrow[1] + 1; jj += nGrow[1]) {,
660 for (
int kk = -nGrow[2]; kk < nGrow[2] + 1; kk += nGrow[2]) {)
661 if (
AMREX_D_TERM((ii == 0), && (jj == 0), && (kk == 0))) {
continue; }
666 tag.grid =
mask(neighbor_cell, MaskComps::grid);
667 tag.tile =
mask(neighbor_cell, MaskComps::tile);
668 tag.level =
mask(neighbor_cell, MaskComps::level);
670 for (
int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
671 if (! periodicity.
isPeriodic(dir)) {
continue; }
672 if (neighbor_cell[dir] < lo[dir]) {
673 tag.periodic_shift[dir] = -1;
674 }
else if (neighbor_cell[dir] > hi[dir]) {
675 tag.periodic_shift[dir] = 1;
680 if (tag != src_tag) { tags.push_back(tag); }
692 std::vector< std::pair<int, Box> > isects;
694 for (
int lev = 0; lev < this->numLevels(); ++lev)
697 const Periodicity& periodicity = this->Geom(lev).periodicity();
698 const std::vector<IntVect>& pshifts = periodicity.
shiftIntVect();
699 const BoxArray& ba = this->ParticleBoxArray(lev);
700 const IntVect& iv = this->Index(p, lev);
701 for (
auto const& pshift : pshifts)
705 const auto* dx_lev = this->Geom(lev).CellSize();
707 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
708 grow_cells[d] = std::max(1,
static_cast<int>(
709 std::ceil(search_radius / dx_lev[d])));
715 bool first_only =
false;
717 for (
const auto& isec : isects)
719 const Box& grid_box = ba[isec.first];
721 if ( !grid_box.
contains(cell) ) {
continue; }
723 this->do_tiling, this->tile_size, tbx);
724 auto nbor = NeighborCopyTag(lev, isec.first, tile);
725 nbor.periodic_shift = -pshift;
726 if (src_tag != nbor) { tags.push_back(nbor); }
737template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
738 template<
class>
class Allocator,
class CellAssignor>
747 m_has_neighbors =
true;
750template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
751 template<
class>
class Allocator,
class CellAssignor>
760 "fillNeighbors(search_radius) is not implemented for GPU builds.");
762 fillNeighborsCPU(search_radius);
764 m_has_neighbors =
true;
767template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
768 template<
class>
class Allocator,
class CellAssignor>
772 int int_start_comp,
int int_num_comp) {
775 amrex::Abort(
"NeighborParticleContainer::sumNeighbors is not implemented for GPU builds");
777 sumNeighborsCPU(real_start_comp, real_num_comp, int_start_comp, int_num_comp);
781template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
782 template<
class>
class Allocator,
class CellAssignor>
791 updateNeighborsGPU(boundary_neighbors_only);
794 updateNeighborsCPU(
true);
796 m_has_neighbors =
true;
799template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
800 template<
class>
class Allocator,
class CellAssignor>
810 m_has_neighbors =
false;
813template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
814 template<
class>
class Allocator,
class CellAssignor>
815template <
class CheckPair>
822 BL_PROFILE(
"NeighborParticleContainer::buildNeighborList");
824 resizeContainers(this->numLevels());
826 for (
int lev = 0; lev < this->numLevels(); ++lev)
828 m_neighbor_list[lev].clear();
830 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
831 PairIndex index(pti.index(), pti.LocalTileIndex());
832 m_neighbor_list[lev][index];
836 neighbor_list[lev].clear();
837 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
838 PairIndex index(pti.index(), pti.LocalTileIndex());
839 neighbor_list[lev][index];
843 auto& plev = this->GetParticles(lev);
844 const auto& geom = this->Geom(lev);
847#pragma omp parallel if (Gpu::notInLaunchRegion())
849 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti)
851 int gid = pti.index();
852 int tid = pti.LocalTileIndex();
853 auto index = std::make_pair(gid, tid);
855 auto& ptile = plev[index];
857 if (ptile.numParticles() == 0) {
continue; }
859 Box bx = pti.tilebox();
873 dxi_v.
push_back(geom.InvCellSizeArray());
876 m_neighbor_list[lev][index].build(ptile,
878 off_bins_v, dxi_v, plo_v, lo_v, hi_v, ng);
881 const auto& counts = m_neighbor_list[lev][index].GetCounts();
882 const auto& list = m_neighbor_list[lev][index].GetList();
885 for (
int i = 0; i < ptile.numParticles(); ++i)
887 auto cnt = counts[i];
888 neighbor_list[lev][index].push_back(cnt);
889 for (
size_t j = 0; j < cnt; ++j)
891 neighbor_list[lev][index].push_back(list[li++]+1);
899template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
900 template<
class>
class Allocator,
class CellAssignor>
901template <
class CheckPair>
908 BL_PROFILE(
"NeighborParticleContainer::buildNeighborList(bin_size)");
910 resizeContainers(this->numLevels());
912 for (
int lev = 0; lev < this->numLevels(); ++lev)
914 m_neighbor_list[lev].clear();
916 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
917 PairIndex index(pti.index(), pti.LocalTileIndex());
918 m_neighbor_list[lev][index];
922 neighbor_list[lev].clear();
923 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
924 PairIndex index(pti.index(), pti.LocalTileIndex());
925 neighbor_list[lev][index];
929 auto& plev = this->GetParticles(lev);
930 const auto& geom = this->Geom(lev);
931 const auto* dx_arr = geom.CellSize();
932 const auto* plo_arr = geom.ProbLo();
935#pragma omp parallel if (Gpu::notInLaunchRegion())
937 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti)
939 int gid = pti.index();
940 int tid = pti.LocalTileIndex();
941 auto index = std::make_pair(gid, tid);
943 auto& ptile = plev[index];
945 if (ptile.numParticles() == 0) {
continue; }
947 Box tile_box = pti.tilebox();
953 int nbins[AMREX_SPACEDIM];
954 amrex::Real phys_lo[AMREX_SPACEDIM], phys_hi[AMREX_SPACEDIM];
955 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
956 phys_lo[d] = plo_arr[d] + (tile_box.
smallEnd(d) - ng) * dx_arr[d];
957 phys_hi[d] = plo_arr[d] + (tile_box.
bigEnd(d) + 1 + ng) * dx_arr[d];
958 nbins[d] = std::max(1,
static_cast<int>(
959 std::ceil(
static_cast<amrex::Real>(phys_hi[d] - phys_lo[d]) / bin_size)));
964 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
965 fine_dxi[d] =
static_cast<Real>(nbins[d]) / (phys_hi[d] - phys_lo[d]);
966 fine_plo[d] = phys_lo[d];
969 Dim3 fine_lo{.
x=0, .y=0, .z=0};
970 Dim3 fine_hi{.
x=nbins[0]-1,
989 m_neighbor_list[lev][index].build(ptile,
991 off_bins_v, dxi_v, plo_v, lo_v, hi_v, 1);
994 const auto& counts = m_neighbor_list[lev][index].GetCounts();
995 const auto& list = m_neighbor_list[lev][index].GetList();
998 for (
int i = 0; i < ptile.numParticles(); ++i)
1000 auto cnt = counts[i];
1001 neighbor_list[lev][index].push_back(cnt);
1002 for (
size_t j = 0; j < cnt; ++j)
1004 neighbor_list[lev][index].push_back(list[li++]+1);
1012template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
1013 template<
class>
class Allocator,
class CellAssignor>
1014template <
class CheckPair,
class OtherPCType>
1018 Vector<std::map<std::pair<int, int>,
1022 BL_PROFILE(
"NeighborParticleContainer::buildNeighborList");
1031 resizeContainers(this->numLevels());
1032 neighbor_lists.resize(this->numLevels());
1034 for (
int lev = 0; lev < this->numLevels(); ++lev)
1036 neighbor_lists[lev].clear();
1038 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
1039 PairIndex index(pti.index(), pti.LocalTileIndex());
1040 neighbor_lists[lev][index];
1043 auto& plev = this->GetParticles(lev);
1044 const auto& geom = this->Geom(lev);
1047#pragma omp parallel if (Gpu::notInLaunchRegion())
1049 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti)
1051 int gid = pti.index();
1052 int tid = pti.LocalTileIndex();
1053 auto index = std::make_pair(gid, tid);
1055 const auto& ptile = plev[index];
1056 auto& other_ptile = other.ParticlesAt(lev, pti);
1057 if (ptile.numParticles() == 0) {
continue; }
1059 Box bx = pti.tilebox();
1073 dxi_v.
push_back(geom.InvCellSizeArray());
1076 neighbor_lists[lev][index].build(ptile, other_ptile,
1078 off_bins_v, dxi_v, plo_v, lo_v, hi_v, ng);
1083template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
1084 template<
class>
class Allocator,
class CellAssignor>
1085template <
class CheckPair,
class OtherPCType>
1089 Vector<std::map<std::pair<int, int>,
1093 BL_PROFILE(
"NeighborParticleContainer::buildNeighborList(bin_size,other)");
1102 resizeContainers(this->numLevels());
1103 neighbor_lists.resize(this->numLevels());
1105 for (
int lev = 0; lev < this->numLevels(); ++lev)
1107 neighbor_lists[lev].clear();
1109 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
1110 PairIndex index(pti.index(), pti.LocalTileIndex());
1111 neighbor_lists[lev][index];
1114 auto& plev = this->GetParticles(lev);
1115 const auto& geom = this->Geom(lev);
1116 const auto* dx_arr = geom.CellSize();
1117 const auto* plo_arr = geom.ProbLo();
1120#pragma omp parallel if (Gpu::notInLaunchRegion())
1122 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti)
1124 int gid = pti.index();
1125 int tid = pti.LocalTileIndex();
1126 auto index = std::make_pair(gid, tid);
1128 const auto& ptile = plev[index];
1129 auto& other_ptile = other.ParticlesAt(lev, pti);
1130 if (ptile.numParticles() == 0) {
continue; }
1132 Box tile_box = pti.tilebox();
1136 int nbins[AMREX_SPACEDIM];
1137 amrex::Real phys_lo[AMREX_SPACEDIM], phys_hi[AMREX_SPACEDIM];
1138 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1139 phys_lo[d] = plo_arr[d] + (tile_box.
smallEnd(d) - ng) * dx_arr[d];
1140 phys_hi[d] = plo_arr[d] + (tile_box.
bigEnd(d) + 1 + ng) * dx_arr[d];
1141 nbins[d] = std::max(1,
static_cast<int>(
1142 std::ceil(
static_cast<amrex::Real>(phys_hi[d] - phys_lo[d]) / bin_size)));
1147 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1148 fine_dxi[d] =
static_cast<Real>(nbins[d]) / (phys_hi[d] - phys_lo[d]);
1149 fine_plo[d] = phys_lo[d];
1152 Dim3 fine_lo{.
x=0, .y=0, .z=0};
1153 Dim3 fine_hi{.
x=nbins[0]-1,
1172 neighbor_lists[lev][index].build(ptile, other_ptile,
1174 off_bins_v, dxi_v, plo_v, lo_v, hi_v, 1);
1179template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
1180 template<
class>
class Allocator,
class CellAssignor>
1181template <
class CheckPair>
1185 int num_bin_types,
bool )
1189 if (num_bin_types == 1) {
AMREX_ASSERT(ref_ratio[0] == 1); }
1191 BL_PROFILE(
"NeighborParticleContainer::buildNeighborList");
1193 resizeContainers(this->numLevels());
1195 for (
int lev = 0; lev < this->numLevels(); ++lev)
1197 m_neighbor_list[lev].clear();
1199 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
1200 PairIndex index(pti.index(), pti.LocalTileIndex());
1201 m_neighbor_list[lev][index];
1204#ifndef AMREX_USE_GPU
1205 neighbor_list[lev].clear();
1206 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
1207 PairIndex index(pti.index(), pti.LocalTileIndex());
1208 neighbor_list[lev][index];
1212 auto& plev = this->GetParticles(lev);
1213 const auto& geom = this->Geom(lev);
1216#pragma omp parallel if (Gpu::notInLaunchRegion())
1218 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti)
1220 int gid = pti.index();
1221 int tid = pti.LocalTileIndex();
1222 auto index = std::make_pair(gid, tid);
1223 auto& ptile = plev[index];
1225 if (ptile.numParticles() == 0) {
continue; }
1227 Box bx = pti.tilebox();
1230 auto& soa = pti.GetStructOfArrays();
1231 auto TypeVec = soa.GetIntData(type_ind);
1232 int* bin_type_array = TypeVec.data();
1241 for (
int type(0); type<num_bin_types; ++type) {
1243 Box dom = geom.Domain();
1244 const Real* plo = geom.ProbLo();
1245 const Real* phi = geom.ProbHi();
1246 auto lcoord = geom.Coord();
1252 lbx.
refine( ref_ratio[type] );
1253 ldom.
refine( ref_ratio[type] );
1259 Geometry lgeom(ldom,lrb,lcoord,lper);
1262 int NGhost = ref_ratio[type]*m_num_neighbor_cells;
1282 m_neighbor_list[lev][index].build(ptile,
1284 off_bins_v, dxi_v, plo_v, lo_v, hi_v,
1285 ng, num_bin_types, bin_type_array);
1287#ifndef AMREX_USE_GPU
1290 const auto& counts = m_neighbor_list[lev][index].GetCounts();
1291 const auto& list = m_neighbor_list[lev][index].GetList();
1294 for (
int i = 0; i < ptile.numParticles(); ++i) {
1295 auto cnt = counts[i];
1296 neighbor_list[lev][index].push_back(cnt);
1297 for (
size_t j = 0; j < cnt; ++j) {
1298 neighbor_list[lev][index].push_back(list[li++]+1);
1308template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
1309 template<
class>
class Allocator,
class CellAssignor>
1310template <
class CheckPair>
1315 BL_PROFILE(
"NeighborParticleContainer::selectActualNeighbors");
1316 const auto& geom_fine = this->Geom(0);
1317 const auto& ba_fine = this->ParticleBoxArray(0);
1318 if (ba_fine.size() == 1 && !geom_fine.isAnyPeriodic()) {
1322 for (
int lev = 0; lev < this->numLevels(); ++lev)
1325 if (!m_boundary_particle_ids.empty()) {
1326 for (
auto& keyval: m_boundary_particle_ids[lev]) {
1327 keyval.second.clear();
1331 for (
MyParIter pti(*
this, lev); pti.isValid(); ++pti) {
1332 PairIndex index(pti.index(), pti.LocalTileIndex());
1335 m_boundary_particle_ids[lev][index];
1336 m_boundary_particle_ids[lev][index].resize(pti.numNeighborParticles());
1337 auto* p_boundary_particle_ids = m_boundary_particle_ids[lev][index].dataPtr();
1339 auto const& ptile = this->ParticlesAt(lev, pti);
1340 auto ptile_data = ptile.getConstParticleTileData();
1342 Box box = pti.tilebox();
1345 const auto lo =
lbound(grownBox);
1346 const auto hi =
ubound(grownBox);
1348 const auto& geom = this->Geom(lev);
1349 const auto domain = geom.Domain();
1350 const auto dxi = geom.InvCellSizeArray();
1351 const auto plo = geom.ProbLoArray();
1353 const size_t np_real = pti.numRealParticles();
1354 const size_t np_total = ptile.numTotalParticles();
1357 bins.
build(np_total, ptile_data, grownBox,
1360 AMREX_D_TERM(
int i =
static_cast<int>(amrex::Math::floor((p.pos(0)-plo[0])*dxi[0]) - lo.x);,
1361 int j =
static_cast<int>(amrex::Math::floor((p.pos(1)-plo[1])*dxi[1]) - lo.y);,
1362 int k =
static_cast<int>(amrex::Math::floor((p.pos(2)-plo[2])*dxi[2]) - lo.z));
1368 auto pperm = bins.permutationPtr();
1369 auto poffset = bins.offsetsPtr();
1372 unsigned int* p_np_boundary = np_boundary.
data();
1378 auto iv3 = iv.
dim3();
1384 int nx = hi.x-lo.x+1;
1385 int ny = hi.y-lo.y+1;
1386 int nz = hi.z-lo.z+1;
1388 bool isActualNeighbor =
false;
1396 if (isActualNeighbor) {
break; }
1397 int nbr_cell_id = (kk * ny + jj) * nx + ii;
1398 for (
auto p = poffset[nbr_cell_id]; p < poffset[nbr_cell_id+1]; ++p) {
1399 if (pperm[p] ==
int(i)) {
continue; }
1400 if (detail::call_check_pair(check_pair, ptile_data, ptile_data, i, pperm[p])) {
1404 p_boundary_particle_ids[loc] = i;
1405 isActualNeighbor =
true;
1415 unsigned int* p_np_boundary_h = np_boundary.copyToHost();
1416 m_boundary_particle_ids[lev][index].resize(*p_np_boundary_h);
1421template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
1422 template<
class>
class Allocator,
class CellAssignor>
1427 BL_PROFILE(
"NeighborParticleContainer::printNeighborList");
1429 for (
int lev = 0; lev < this->numLevels(); ++lev)
1431 for(
MFIter mfi = this->MakeMFIter(lev); mfi.
isValid(); ++mfi)
1433 int gid = mfi.index();
1434 int tid = mfi.LocalTileIndex();
1435 auto index = std::make_pair(gid, tid);
1436 m_neighbor_list[lev][index].print();
1441template <
typename T_ParticleType,
int NArrayReal,
int NArrayInt,
1442 template<
class>
class Allocator,
class CellAssignor>
1447 this->reserveData();
1449 if ( std::ssize(neighbors) <= num_levels )
1451 neighbors.resize(num_levels);
1452 m_neighbor_list.resize(num_levels);
1453 neighbor_list.resize(num_levels);
1454 mask_ptr.resize(num_levels);
1455 buffer_tag_cache.resize(num_levels);
1456 local_neighbor_sizes.resize(num_levels);
1457 if ( enableInverse() ) { inverse_tags.resize(num_levels); }
1460 AMREX_ASSERT((neighbors.size() == m_neighbor_list.size()) &&
1461 (neighbors.size() == mask_ptr.size() ) );
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define BL_PROFILE_VAR_STOP(vname)
Definition AMReX_BLProfiler.H:563
#define BL_PROFILE_VAR(fname, vname)
Definition AMReX_BLProfiler.H:560
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_FOR_1D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:97
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
Array4< int const > mask
Definition AMReX_InterpFaceRegister.cpp:93
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:172
#define AMREX_D_PICK(a, b, c)
Definition AMReX_SPACE.H:173
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
A FortranArrayBox(FAB)-like object.
Definition AMReX_BaseFab.H:194
A collection of Boxes stored in an Array.
Definition AMReX_BoxArray.H:564
std::vector< std::pair< int, Box > > intersections(const Box &bx) const
Return intersections of Box and BoxArray.
Definition AMReX_BoxArray.cpp:1186
static bool SameRefs(const BoxArray &lhs, const BoxArray &rhs)
whether two BoxArrays share the same data
Definition AMReX_BoxArray.H:837
__host__ __device__ BoxND & grow(int i) noexcept
Definition AMReX_Box.H:649
__host__ __device__ const IntVectND< dim > & bigEnd() const &noexcept
Return the inclusive upper bound of the box.
Definition AMReX_Box.H:124
__host__ __device__ Long numPts() const noexcept
Return the number of points contained in the BoxND.
Definition AMReX_Box.H:364
__host__ __device__ bool contains(const IntVectND< dim > &p) const noexcept
Return true if argument is contained within BoxND.
Definition AMReX_Box.H:216
__host__ __device__ IndexTypeND< dim > ixType() const noexcept
Return the indexing type.
Definition AMReX_Box.H:136
__host__ __device__ BoxND & coarsen(int ref_ratio) noexcept
Coarsen BoxND by given (positive) refinement ratio. NOTE: if type(dir) = CELL centered: lo <- lo/rati...
Definition AMReX_Box.H:730
__host__ __device__ BoxND & refine(int ref_ratio) noexcept
Refine BoxND by given (positive) refinement ratio. NOTE: if type(dir) = CELL centered: lo <- lo*ratio...
Definition AMReX_Box.H:706
__host__ __device__ Long index(const IntVectND< dim > &v) const noexcept
Return offset of point from smallend; i.e. index(smallend) -> 0, bigend would return numPts()-1....
Definition AMReX_Box.H:1063
__host__ __device__ void next(IntVectND< dim > &) const noexcept
Step through the rectangle. It is a runtime error to give a point not inside rectangle....
Definition AMReX_Box.H:1130
__host__ __device__ const IntVectND< dim > & smallEnd() const &noexcept
Return the inclusive lower bound of the box.
Definition AMReX_Box.H:112
const Real * CellSize() const noexcept
Returns the cellsize for each coordinate direction.
Definition AMReX_CoordSys.H:71
GpuArray< Real, 3 > InvCellSizeArray() const noexcept
Definition AMReX_CoordSys.H:87
A container for storing items in a set of bins.
Definition AMReX_DenseBins.H:77
void build(N nitems, const_pointer_input_type v, const Box &bx, F &&f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:130
Calculates the distribution of FABs to MPI processes.
Definition AMReX_DistributionMapping.H:43
static bool SameRefs(const DistributionMapping &lhs, const DistributionMapping &rhs)
Definition AMReX_DistributionMapping.H:189
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:75
Periodicity periodicity() const noexcept
Definition AMReX_Geometry.H:361
GpuArray< Real, 3 > ProbLoArray() const noexcept
Definition AMReX_Geometry.H:192
Definition AMReX_GpuBuffer.H:24
T const * data() const noexcept
Definition AMReX_GpuBuffer.H:51
__host__ __device__ constexpr Dim3 dim3() const noexcept
Definition AMReX_IntVect.H:262
__host__ static __device__ constexpr IntVectND< dim > TheZeroVector() noexcept
This static member function returns a reference to a constant IntVectND object, all of whose dim argu...
Definition AMReX_IntVect.H:771
__host__ __device__ constexpr int max() const noexcept
maximum (no absolute values) value
Definition AMReX_IntVect.H:313
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:88
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:172
Definition AMReX_NeighborList.H:309
Definition AMReX_NeighborParticles.H:39
std::pair< int, int > PairIndex
Definition AMReX_NeighborParticles.H:210
void selectActualNeighbors(CheckPair const &check_pair, int num_cells=1)
Definition AMReX_NeighborParticlesI.H:1313
static bool enable_inverse
Definition AMReX_NeighborParticles.H:480
void buildNeighborList(CheckPair const &check_pair, bool sort=false)
Definition AMReX_NeighborParticlesI.H:818
void printNeighborList()
Definition AMReX_NeighborParticlesI.H:1425
static bool use_mask
Definition AMReX_NeighborParticles.H:478
void initializeCommComps()
Definition AMReX_NeighborParticlesI.H:60
void getNeighborTags(Vector< NeighborCopyTag > &tags, const P &p, int nGrow, const NeighborCopyTag &src_tag, const MyParIter &pti, amrex::Real search_radius=amrex::Real(0))
Definition AMReX_NeighborParticlesI.H:603
typename ParticleContainerType::ParIterType MyParIter
Definition AMReX_NeighborParticles.H:209
void resizeContainers(int num_levels)
Definition AMReX_NeighborParticlesI.H:1445
Dynamically allocated vector for trivially copyable data.
Definition AMReX_PODVector.H:308
iterator begin() noexcept
Definition AMReX_PODVector.H:674
iterator end() noexcept
Definition AMReX_PODVector.H:678
T * data() noexcept
Definition AMReX_PODVector.H:666
void push_back(const T &a_value)
Definition AMReX_PODVector.H:629
Definition AMReX_ParGDB.H:13
A distributed container for Particles sorted onto the levels, grids, and tiles of a block-structured ...
Definition AMReX_ParticleContainer.H:149
This provides length of period for periodic domains. 0 means it is not periodic in that direction....
Definition AMReX_Periodicity.H:17
std::vector< IntVect > shiftIntVect(IntVect const &nghost=IntVect(0)) const
Definition AMReX_Periodicity.cpp:8
bool isAnyPeriodic() const noexcept
Definition AMReX_Periodicity.H:22
bool isPeriodic(int dir) const noexcept
Definition AMReX_Periodicity.H:26
A Box with real dimensions.
Definition AMReX_RealBox.H:28
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
amrex_real Real
Floating Point Type for Fields.
Definition AMReX_REAL.H:79
amrex_particle_real ParticleReal
Floating Point Type for Particles.
Definition AMReX_REAL.H:90
OutIter exclusive_scan(InIter begin, InIter end, OutIter result)
Definition AMReX_Scan.H:1190
__host__ __device__ Dim3 ubound(Array4< T > const &a) noexcept
Return the inclusive upper bounds of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1359
__host__ __device__ Dim3 lbound(Array4< T > const &a) noexcept
Return the inclusive lower bounds of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1345
__host__ __device__ BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Grow BoxND in all directions by given amount.
Definition AMReX_Box.H:1289
std::array< T, N > Array
Definition AMReX_Array.H:26
__host__ __device__ AMREX_FORCE_INLINE T Add(T *sum, T value) noexcept
Definition AMReX_GpuAtomic.H:200
void htod_memcpy_async(void *p_d, const void *p_h, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:421
constexpr int get_thread_num()
Definition AMReX_OpenMP.H:37
constexpr int get_max_threads()
Definition AMReX_OpenMP.H:36
int MyProcSub() noexcept
my sub-rank in current frame
Definition AMReX_ParallelContext.H:76
int global_to_local_rank(int rank) noexcept
Definition AMReX_ParallelContext.H:98
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:139
__host__ __device__ int getTileIndex(const IntVect &iv, const Box &box, const bool a_do_tiling, const IntVect &a_tile_size, Box &tbx)
Definition AMReX_ParticleUtil.H:191
DistributionMapping const & DistributionMap(FabArrayBase const &fa)
Definition AMReX_FabArrayBase.cpp:2867
void EnsureThreadSafeTiles(PC &pc)
Definition AMReX_ParticleUtil.H:737
__host__ __device__ Dim3 begin(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:2018
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:30
__host__ __device__ constexpr const T & min(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:25
__host__ __device__ BoxND< dim > shift(const BoxND< dim > &b, int dir, int nzones) noexcept
Return a BoxND with indices shifted by nzones in dir direction.
Definition AMReX_Box.H:1504
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:33
__host__ __device__ constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:45
int numParticlesOutOfRange(Iterator const &pti, int nGrow)
Returns the number of particles that are more than nGrow cells from the box correspond to the input i...
Definition AMReX_ParticleUtil.H:36
bool SameIteratorsOK(const PC1 &pc1, const PC2 &pc2)
Definition AMReX_ParticleUtil.H:725
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:241
const int[]
Definition AMReX_BLProfiler.cpp:1664
IntVect computeRefFac(const ParGDBBase *a_gdb, int src_lev, int lev)
Definition AMReX_ParticleUtil.cpp:6
void RemoveDuplicates(Vector< T > &vec)
Definition AMReX_Vector.H:210
__host__ __device__ Dim3 end(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:2028
__host__ __device__ IntVect getParticleCell(P const &p, amrex::GpuArray< amrex::Real, 3 > const &plo, amrex::GpuArray< amrex::Real, 3 > const &dxi) noexcept
Returns the cell index for a given particle using the provided lower bounds and cell sizes.
Definition AMReX_ParticleUtil.H:343
BoxArray const & boxArray(FabArrayBase const &fa)
Definition AMReX_FabArrayBase.cpp:2862
Definition AMReX_Dim3.H:13
int x
Definition AMReX_Dim3.H:13
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:43