13template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
14 template<
class>
class Allocator,
class CellAssignor>
18 num_real_comm_comps = 0;
19 int comm_comps_start = 0;
20 if constexpr (!ParticleType::is_soa_particle) {
21 comm_comps_start += AMREX_SPACEDIM + NStructReal;
23 for (
int i = comm_comps_start; i < comm_comps_start + NumRealComps(); ++i) {
24 if (h_redistribute_real_comp[i]) {++num_real_comm_comps;}
27 num_int_comm_comps = 0;
28 comm_comps_start = 2 + NStructInt;
29 for (
int i = comm_comps_start; i < comm_comps_start + NumIntComps(); ++i) {
30 if (h_redistribute_int_comp[i]) {++num_int_comm_comps;}
33 if constexpr (ParticleType::is_soa_particle) {
34 particle_size =
sizeof(uint64_t);
38 superparticle_size = particle_size +
39 num_real_comm_comps*
sizeof(
ParticleReal) + num_int_comm_comps*
sizeof(
int);
42template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
43 template<
class>
class Allocator,
class CellAssignor>
47 levelDirectoriesCreated =
false;
52 if constexpr (ParticleType::is_soa_particle)
54 h_redistribute_real_comp.resize(NArrayReal,
true);
56 h_redistribute_real_comp.resize(AMREX_SPACEDIM + NStructReal + NArrayReal,
true);
58 h_redistribute_int_comp.resize(2 + NStructInt + NArrayInt,
true);
63 m_soa_rdata_names.clear();
64 for (
int i=0; i<NArrayReal; ++i)
66 m_soa_rdata_names.push_back(getDefaultCompNameReal<ParticleType>(i));
68 m_soa_idata_names.clear();
69 for (
int i=0; i<NArrayInt; ++i)
71 m_soa_idata_names.push_back(getDefaultCompNameInt<ParticleType>(i));
74 static bool initialized =
false;
77 static_assert(
sizeof(ParticleType)%
sizeof(RealType) == 0,
78 "sizeof ParticleType is not a multiple of sizeof RealType");
80 ParmParse
pp(
"particles");
82 Vector<int> tilesize(AMREX_SPACEDIM);
83 if (
pp.
queryarr(
"tile_size", tilesize, 0, AMREX_SPACEDIM)) {
84 for (
int i=0; i<AMREX_SPACEDIM; ++i) { tile_size[i] = tilesize[i]; }
87 static_assert(std::is_standard_layout_v<ParticleType>,
88 "Particle type must be standard layout");
92 pp.
query(
"use_prepost", usePrePost);
93 pp.
query(
"do_unlink", doUnlink);
94 pp.
queryAdd(
"do_mem_efficient_sort", memEfficientSort);
95 pp.
queryAdd(
"use_comms_arena", use_comms_arena);
102 typename ParticleType,
105 template<
class>
class Allocator,
110 std::vector<std::string>
const & rdata_name, std::vector<std::string>
const & idata_name
117 std::set<std::string>
const unique_r_names(rdata_name.begin(), rdata_name.end());
118 std::set<std::string>
const unique_i_names(idata_name.begin(), idata_name.end());
122 for (
int i=0; i<NArrayReal; ++i)
124 m_soa_rdata_names.at(i) = rdata_name.at(i);
126 for (
int i=0; i<NArrayInt; ++i)
128 m_soa_idata_names.at(i) = idata_name.at(i);
133 typename ParticleType,
136 template<
class>
class Allocator,
142 return std::find(m_soa_rdata_names.begin(), m_soa_rdata_names.end(), name) != std::end(m_soa_rdata_names);
145template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
146 template<
class>
class Allocator,
class CellAssignor>
150 return std::find(m_soa_idata_names.begin(), m_soa_idata_names.end(), name) != std::end(m_soa_idata_names);
154 typename ParticleType,
157 template<
class>
class Allocator,
163 const auto it = std::find(m_soa_rdata_names.begin(), m_soa_rdata_names.end(), name);
165 if (it == m_soa_rdata_names.end())
167 throw std::runtime_error(
"GetRealCompIndex: Component " + name +
" does not exist!");
171 return std::distance(m_soa_rdata_names.begin(), it);
176 typename ParticleType,
179 template<
class>
class Allocator,
185 const auto it = std::find(m_soa_idata_names.begin(), m_soa_idata_names.end(), name);
187 if (it == m_soa_idata_names.end())
189 throw std::runtime_error(
"GetIntCompIndex: Component " + name +
" does not exist!");
193 return std::distance(m_soa_idata_names.begin(), it);
197template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
198 template<
class>
class Allocator,
class CellAssignor>
199template <
typename P,
typename Assignor>
204 const auto& domain = geom.
Domain();
208 return Assignor{}(p, plo, dxi, domain);
211template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
212 template<
class>
class Allocator,
class CellAssignor>
221 int local_grid)
const
227 lev_max = finestLevel();
232 AMREX_ASSERT(nGrow == 0 || (nGrow >= 0 && lev_min == lev_max));
234 std::vector< std::pair<int, Box> > isects;
236 for (
int lev = lev_max; lev >= lev_min; lev--) {
237 const IntVect& iv = Index(p, lev);
238 if (lev == pld.
m_lev) {
252 const BoxArray& ba = ParticleBoxArray(lev);
255 if (local_grid < 0) {
256 bool findfirst = (nGrow == 0) ?
true :
false;
258 grid = isects.empty() ? -1 : isects[0].first;
259 if (nGrow > 0 && isects.size() > 1) {
260 for (
auto & isect : isects) {
262 for (
int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
274 grid = (*redistribute_mask_ptr)[local_grid](iv, 0);
292template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
293 template<
class>
class Allocator,
class CellAssignor>
301 int local_grid)
const
306 if (!Geom(0).isAnyPeriodic()) {
return false; }
309 lev_max = finestLevel();
317 p_prime.
pos(1) = p.pos(1);,
318 p_prime.
pos(2) = p.pos(2));
319 if (PeriodicShift(p_prime)) {
320 std::vector< std::pair<int,Box> > isects;
321 for (
int lev = lev_max; lev >= lev_min; lev--) {
325 const BoxArray& ba = ParticleBoxArray(lev);
328 if (local_grid < 0) {
331 grid = isects.empty() ? -1 : isects[0].first;
334 if (ba[local_grid].contains(iv))
341 grid = isects.empty() ? -1 : isects[0].first;
344 grid = (*redistribute_mask_ptr)[local_grid](Index(p, lev), 0);
351 p.pos(1) = p_prime.
pos(1);,
352 p.pos(2) = p_prime.
pos(2););
371template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
372 template<
class>
class Allocator,
class CellAssignor>
378 const auto& geom = Geom(0);
379 const auto plo = geom.ProbLoArray();
380 const auto phi = geom.ProbHiArray();
381 const auto rlo = geom.ProbLoArrayInParticleReal();
382 const auto rhi = geom.ProbHiArrayInParticleReal();
383 const auto is_per = geom.isPeriodicArray();
388template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
389 template<
class>
class Allocator,
class CellAssignor>
399 bool ok = Where(p, pld);
401 if (!ok && Geom(0).isAnyPeriodic())
412 amrex::AllPrint()<<
"Invalidating out-of-domain particle: " << p <<
'\n';
417 p.id().make_invalid();
423template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
424 template<
class>
class Allocator,
class CellAssignor>
429 m_particles.reserve(maxLevel()+1);
432template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
433 template<
class>
class Allocator,
class CellAssignor>
438 int nlevs = std::max(0, finestLevel()+1);
439 m_particles.resize(nlevs);
442template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
443 template<
class>
class Allocator,
class CellAssignor>
447 int lev_min,
int lev_max,
int nGrow,
int local_grid)
const
450 if (Geom(0).outsideRoundoffDomain(
AMREX_D_DECL(p.pos(0), p.pos(1), p.pos(2))))
453 success = EnforcePeriodicWhere(p, pld, lev_min, lev_max, local_grid);
454 if (!success && lev_min == 0)
457 p.id().make_invalid();
463 success = Where(p, pld, lev_min, lev_max, 0, local_grid);
468 success = (nGrow > 0) && Where(p, pld, lev_min, lev_min, nGrow);
474 amrex::Abort(
"ParticleContainer::locateParticle(): invalid particle.");
478template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
479 template<
class>
class Allocator,
class CellAssignor>
484 for (
int lev = 0; lev <= finestLevel(); lev++) {
485 nparticles += NumberOfParticlesAtLevel(lev,only_valid,
true);
493template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
494 template<
class>
class Allocator,
class CellAssignor>
498 AMREX_ASSERT(lev >= 0 && lev <
int(m_particles.size()));
501 ParticleDistributionMap(lev));
505 int gid = pti.index();
508 const auto& ptile = ParticlesAt(lev, pti);
509 const int np = ptile.numParticles();
510 auto const ptd = ptile.getConstParticleTileData();
514 using ReduceTuple =
typename decltype(reduce_data)::Type;
516 reduce_op.
eval(np, reduce_data,
519 return (ptd.id(i).is_valid()) ? 1 : 0;
522 int np_valid = amrex::get<0>(reduce_data.
value(reduce_op));
523 np_per_grid_local[gid] += np_valid;
526 np_per_grid_local[gid] += pti.numParticles();
530 Vector<Long> nparticles(np_per_grid_local.
size(), 0);
533 for (ParConstIterType pti(*
this, lev); pti.isValid(); ++pti)
535 nparticles[pti.index()] = np_per_grid_local[pti.index()];
549template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
550 template<
class>
class Allocator,
class CellAssignor>
555 if (level < 0 || level >=
int(m_particles.size())) {
return nparticles; }
560 using ReduceTuple =
typename decltype(reduce_data)::Type;
562 for (
const auto& kv : GetParticles(level)) {
563 const auto& ptile = kv.second;
564 auto const ptd = ptile.getConstParticleTileData();
566 reduce_op.
eval(ptile.numParticles(), reduce_data,
569 return (ptd.id(i).is_valid()) ? 1 : 0;
573 nparticles =
static_cast<Long>(amrex::get<0>(reduce_data.
value(reduce_op)));
576 for (
const auto& kv : GetParticles(level)) {
577 const auto& ptile = kv.second;
578 nparticles += ptile.numParticles();
591template <
typename I, std::enable_if_t<std::is_
integral_v<I> && (sizeof(I) >= sizeof(Long)),
int> FOO>
595 AMREX_ASSERT(lev >= 0 && lev <
int(m_particles.size()));
601 for (ParConstIterType pti(*
this, lev); pti.isValid(); ++pti)
603 int gid = pti.index();
604 mem[gid] +=
static_cast<I
>(pti.capacity());
612template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
620 for (
unsigned lev = 0; lev < m_particles.size(); lev++) {
621 const auto& pmap = m_particles[lev];
622 for (
const auto& kv : pmap) {
623 const auto& ptile = kv.second;
624 cnt += ptile.numParticles();
628 Long mn = cnt, mx = mn;
640 amrex::Print() <<
"ParticleContainer spread across MPI nodes - bytes (num particles): [Min: "
648 <<
" (" << cnt <<
")]\n";
653 return {mn*sz, mx*sz, cnt*sz};
656template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
657 template<
class>
class Allocator,
class CellAssignor>
664 for (
unsigned lev = 0; lev < m_particles.size(); lev++) {
665 const auto& pmap = m_particles[lev];
666 for (
const auto& kv : pmap) {
667 const auto& ptile = kv.second;
668 cnt += ptile.capacity();
672 Long mn = cnt, mx = mn;
683 amrex::Print() <<
"ParticleContainer spread across MPI nodes - bytes: [Min: "
694 return {mn, mx, cnt};
702 for (
unsigned lev = 0; lev < m_particles.size(); lev++) {
703 auto& pmap = m_particles[lev];
704 for (
auto& kv : pmap) {
705 auto& ptile = kv.second;
706 ptile.shrink_to_fit();
717template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
718 template<
class>
class Allocator,
class CellAssignor>
725 if (m_particles.empty()) {
return; }
726 AMREX_ASSERT(lev >= 0 && lev <
int(m_particles.size()));
729 const auto& geom = Geom(lev);
730 const auto plo = geom.ProbLoArray();
731 const auto dxi = geom.InvCellSizeArray();
732 const auto domain = geom.Domain();
737 const auto p = ptd[ip];
739 IntVect iv = assignor(p, plo, dxi, domain);
744template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
745 template<
class>
class Allocator,
class CellAssignor>
749 BL_PROFILE(
"ParticleContainer::IncrementWithTotal(lev)");
751 return TotalNumberOfParticles(
true, local);
754template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
755 template<
class>
class Allocator,
class CellAssignor>
759 BL_PROFILE(
"ParticleContainer::RemoveParticlesAtLevel()");
760 if (level >=
int(this->m_particles.size())) {
return; }
762 if (!this->m_particles[level].empty())
768template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
769 template<
class>
class Allocator,
class CellAssignor>
773 BL_PROFILE(
"ParticleContainer::RemoveParticlesNotAtFinestLevel()");
774 AMREX_ASSERT(this->finestLevel()+1 ==
int(this->m_particles.size()));
778 for (
unsigned lev = 0; lev < m_particles.size() - 1; ++lev) {
779 auto& pmap = m_particles[lev];
781 for (
auto& kv : pmap) {
782 const auto& pbx = kv.second;
783 cnt += pbx.numParticles();
792 if (this->m_verbose > 1 && cnt > 0) {
794 <<
" particles not in finest level\n";
810 template <
typename SrcData>
812 int operator() (
const SrcData& src,
int src_i)
const noexcept
821 template <
typename DstData,
typename SrcData>
824 int src_i,
int dst_i)
const noexcept
834template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
835 template<
class>
class Allocator,
class CellAssignor>
837ParticleContainer_impl<ParticleType, NArrayReal, NArrayInt, Allocator, CellAssignor>
838::CreateVirtualParticles (
int level,
AoS& virts)
const
841 CreateVirtualParticles(level, ptile);
845template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
846 template<
class>
class Allocator,
class CellAssignor>
851 BL_PROFILE(
"ParticleContainer::CreateVirtualParticles()");
855 if (level >=
static_cast<int>(m_particles.size())) {
859 std::string
const& aggregation_type = AggregationType();
860 int aggregation_buffer = AggregationBuffer();
862 if (aggregation_type ==
"None")
867 const auto& src_tile = ParticlesAt(level, pti);
869 auto np = src_tile.numParticles();
870 virts.
resize(virts_offset+np);
875 if (aggregation_type ==
"Cell")
878 int nComp = AMREX_SPACEDIM + NStructReal + NArrayReal;
881 MultiFab mf(ParticleBoxArray(level), ParticleDistributionMap(level),
nComp, nGhost);
883 nComp = 1 + NStructInt + NArrayInt;
884 iMultiFab imf(ParticleBoxArray(level), ParticleDistributionMap(level),
nComp, nGhost);
886 const auto& geom = Geom(level);
887 const auto plo = geom.ProbLoArray();
888 const auto dxi = geom.InvCellSizeArray();
889 const auto domain = geom.Domain();
892 bl_buffer.
complementIn(Geom(level).Domain(), ParticleBoxArray(level));
893 BoxArray buffer(std::move(bl_buffer));
894 buffer.
grow(aggregation_buffer);
897 locator.
build(buffer, geom);
907 if(assign_buffer_grid(iv)==-1)
910 for (
int i = 0; i < NArrayReal; ++i)
915 for (
int i = 0; i < AMREX_SPACEDIM; ++i)
920 for (
int i = 1; i < NStructReal; ++i)
925 for (
int i = 0; i < 1; ++i)
941 if(assign_buffer_grid(iv)==-1)
944 if(partData(iv,0)==0)
948 for (
int i = 0; i < NStructInt; ++i)
952 for (
int i = 0; i < NArrayInt; ++i)
966 const auto bx = mfi.tilebox();
967 const auto partData = mf.
array(mfi);
968 const auto imf_arr = imf.
array(mfi);
971 auto *offsets_ptr = offsets.
dataPtr();
976 if(imf_arr(i,j,k,0)!=0)
978 const auto idx = last_offset + offsets_ptr[
988 p.rdata(0) =
static_cast<ParticleReal>(partData(i,j,k,AMREX_SPACEDIM));;
990 for (
int n = 0; n < AMREX_SPACEDIM; ++n)
992 p.pos(n) =
static_cast<ParticleReal>(partData(i,j,k,n) / p.rdata(0));
995 for (
int n = 1; n < NStructReal; ++n)
997 p.rdata(n) =
static_cast<ParticleReal>(partData(i,j,k,AMREX_SPACEDIM+n) / p.rdata(0));
1000 for (
int n = 0; n < NArrayReal; ++n)
1002 dst.rdata(n)[idx] =
static_cast<ParticleReal>(partData(i,j,k,AMREX_SPACEDIM+NStructReal+n));
1005 for (
int n = 0; n < NStructInt; ++n)
1007 p.idata(n) = imf_arr(i,j,k,1+n);
1010 for (
int n = 0; n < NArrayInt; ++n)
1012 dst.idata(n)[idx] = imf_arr(i,j,k,1+NStructInt+n);
1017 last_offset+=next_offset;
1022 auto virts_offset = last_offset;
1025 const auto& src_tile = ParticlesAt(level, pti);
1027 auto np = src_tile.numParticles();
1028 virts.
resize(virts_offset+np);
1032 virts.
resize(virts_offset);
1051 template <
typename SrcData>
1057 const auto p_boxes = amrex::get<0>(tup_min);
1058 const auto p_boxes_max = amrex::get<0>(tup_max);
1059 const auto p_levs_max = amrex::get<1>(tup_max);
1060 return p_boxes_max >=0 && p_boxes ==
m_gid && p_levs_max ==
m_lev_max;
1067 template <
typename DstData,
typename SrcData>
1070 int src_i,
int dst_i)
const noexcept
1079template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1080 template<
class>
class Allocator,
class CellAssignor>
1082ParticleContainer_impl<ParticleType, NArrayReal, NArrayInt, Allocator, CellAssignor>
1083::CreateGhostParticles (
int level,
int nGrow,
AoS& ghosts)
const
1086 CreateGhostParticles(level, nGrow, ptile);
1090template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1091 template<
class>
class Allocator,
class CellAssignor>
1096 BL_PROFILE(
"ParticleContainer::CreateGhostParticles()");
1100 if (level >=
static_cast<int>(m_particles.size())) {
1104 if (! m_particle_locator.isValid(GetParGDB())) {
1105 m_particle_locator.build(GetParGDB());
1108 m_particle_locator.setGeometry(GetParGDB());
1113 const auto& src_tile = ParticlesAt(level, pti);
1114 int gid = pti.index();
1116 auto np = src_tile.numParticles();
1117 ghosts.
resize(ghost_offset+np);
1120 ghosts.
resize(ghost_offset);
1124template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1125 template<
class>
class Allocator,
class CellAssignor>
1130 BL_PROFILE(
"ParticleContainer::clearParticles()");
1132 for (
int lev = 0; lev < static_cast<int>(m_particles.size()); ++lev)
1134 for (
auto& kv : m_particles[lev]) { kv.second.resize(0); }
1135 particle_detail::clearEmptyEntries(m_particles[lev]);
1139template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1140 template<
class>
class Allocator,
class CellAssignor>
1141template <class PCType, std::enable_if_t<IsParticleContainer<PCType>::value,
int> foo>
1150template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1151 template<
class>
class Allocator,
class CellAssignor>
1152template <class PCType, std::enable_if_t<IsParticleContainer<PCType>::value,
int> foo>
1161template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1162 template<
class>
class Allocator,
class CellAssignor>
1163template <
class F,
class PCType,
1164 std::enable_if_t<IsParticleContainer<PCType>::value,
int> foo,
1165 std::enable_if_t<! std::is_integral_v<F>,
int> bar>
1170 BL_PROFILE(
"ParticleContainer::copyParticles");
1172 addParticles(other, std::forward<F>(f), local);
1175template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1176 template<
class>
class Allocator,
class CellAssignor>
1177template <
class F,
class PCType,
1178 std::enable_if_t<IsParticleContainer<PCType>::value,
int> foo,
1179 std::enable_if_t<! std::is_integral_v<F>,
int> bar>
1184 BL_PROFILE(
"ParticleContainer::addParticles");
1187 for (
int lev = 0; lev < other.numLevels(); ++lev)
1190 const auto& plevel_other = other.GetParticles(lev);
1191 for(
MFIter mfi = other.MakeMFIter(lev); mfi.isValid(); ++mfi)
1193 auto index = std::make_pair(mfi.index(), mfi.LocalTileIndex());
1194 if(plevel_other.find(index) == plevel_other.end()) {
continue; }
1196 DefineAndReturnParticleTile(lev, mfi.index(), mfi.LocalTileIndex());
1201#pragma omp parallel if (Gpu::notInLaunchRegion())
1203 for (
int lev = 0; lev < other.numLevels(); ++lev)
1205 const auto& plevel_other = other.GetParticles(lev);
1206 for(
MFIter mfi = other.MakeMFIter(lev); mfi.isValid(); ++mfi)
1208 auto index = std::make_pair(mfi.index(), mfi.LocalTileIndex());
1209 if(plevel_other.find(index) == plevel_other.end()) {
continue; }
1212 auto& ptile = ParticlesAt(lev, mfi.index(), mfi.LocalTileIndex());
1213 const auto& ptile_other = plevel_other.at(index);
1214 auto np = ptile_other.numParticles();
1215 if (np == 0) {
continue; }
1217 auto dst_index = ptile.numParticles();
1218 ptile.resize(dst_index + np);
1222 ptile.resize(dst_index + count);
1226 if (! local) { Redistribute(); }
1243 RedistributeGPU(lev_min, lev_max, nGrow, local, remove_negative);
1247 RedistributeCPU(lev_min, lev_max, nGrow, local, remove_negative);
1250 RedistributeCPU(lev_min, lev_max, nGrow, local, remove_negative);
1256template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1257 template<
class>
class Allocator,
class CellAssignor>
1258template <
class index_type>
1263 auto& ptile = ParticlesAt(lev, mfi);
1264 const size_t np = ptile.numParticles();
1265 const size_t np_total = np + ptile.numNeighborParticles();
1267 if (memEfficientSort) {
1268#if defined(AMREX_USE_CUDA) && defined(_WIN32)
1269 if (!ParticleType::is_soa_particle) {
1271 if constexpr (!ParticleType::is_soa_particle) {
1273 static_assert(
sizeof(
ParticleType)%4 == 0 &&
sizeof(uint32_t) == 4);
1274 using tmp_t = std::conditional_t<
sizeof(
ParticleType)%8 == 0,
1275 uint64_t, uint32_t>;
1278 auto* ptmp = tmp.data();
1279 auto* paos = (tmp_t*)(ptile.getParticleTileData().m_aos);
1280 for (std::size_t ichunk = 0; ichunk < nchunks; ++ichunk) {
1284 ptmp[i] = paos[permutations[i]*nchunks+ichunk];
1288 paos[i*nchunks+ichunk] = ptmp[i];
1293 typename SoA::IdCPU tmp_idcpu;
1294 if constexpr (has_polymorphic_allocator) {
1295 tmp_idcpu.setArena(arena());
1297 tmp_idcpu.resize(np_total);
1298 auto src = ptile.GetStructOfArrays().GetIdCPUData().data();
1299 uint64_t* dst = tmp_idcpu.data();
1302 dst[i] = i < np ? src[permutations[i]] : src[i];
1307 ptile.GetStructOfArrays().GetIdCPUData().swap(tmp_idcpu);
1311 RealVector tmp_real;
1312 if constexpr (has_polymorphic_allocator) {
1313 tmp_real.setArena(arena());
1315 tmp_real.resize(np_total);
1316 for (
int comp = 0; comp < NArrayReal + m_num_runtime_real; ++comp) {
1317 auto src = ptile.GetStructOfArrays().GetRealData(comp).data();
1321 dst[i] = i < np ? src[permutations[i]] : src[i];
1326 ptile.GetStructOfArrays().GetRealData(comp).swap(tmp_real);
1331 if constexpr (has_polymorphic_allocator) {
1332 tmp_int.setArena(arena());
1334 tmp_int.resize(np_total);
1335 for (
int comp = 0; comp < NArrayInt + m_num_runtime_int; ++comp) {
1336 auto src = ptile.GetStructOfArrays().GetIntData(comp).data();
1337 int* dst = tmp_int.data();
1340 dst[i] = i < np ? src[permutations[i]] : src[i];
1345 ptile.GetStructOfArrays().GetIntData(comp).swap(tmp_int);
1348 ParticleTileType ptile_tmp;
1349 ptile_tmp.define(m_num_runtime_real, m_num_runtime_int,
1350 &m_soa_rdata_names, &m_soa_idata_names, arena());
1351 ptile_tmp.resize(np_total);
1356 ptile.swap(ptile_tmp);
1360template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1361 template<
class>
class Allocator,
class CellAssignor>
1368template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1369 template<
class>
class Allocator,
class CellAssignor>
1374 BL_PROFILE(
"ParticleContainer::SortParticlesByBin()");
1378 for (
int lev = 0; lev < numLevels(); ++lev)
1383 const auto domain = geom.
Domain();
1387 auto& ptile = ParticlesAt(lev, mfi);
1388 const size_t np = ptile.numParticles();
1394 m_bins.build(np, ptile.getParticleTileData(), ntiles,
1396 ReorderParticles(lev, mfi, m_bins.permutationPtr());
1401template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1402 template<
class>
class Allocator,
class CellAssignor>
1407 BL_PROFILE(
"ParticleContainer::SortParticlesForDeposition()");
1409 for (
int lev = 0; lev < numLevels(); ++lev)
1415 const auto& ptile = ParticlesAt(lev, mfi);
1416 const size_t np = ptile.numParticles();
1420 using index_type =
typename decltype(m_bins)::index_type;
1422 PermutationForDeposition<index_type>(perm, np, ptile, box, geom, idx_type);
1423 ReorderParticles(lev, mfi, perm.
dataPtr());
1431template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1432 template<
class>
class Allocator,
class CellAssignor>
1444 BL_PROFILE(
"ParticleContainer::RedistributeGPU()");
1447 int theEffectiveFinestLevel = m_gdb->finestLevel();
1448 while (!m_gdb->LevelDefined(theEffectiveFinestLevel)) { theEffectiveFinestLevel--; }
1450 if (
int(m_particles.size()) < theEffectiveFinestLevel+1) {
1452 amrex::Print() <<
"ParticleContainer::Redistribute() resizing containers from "
1453 << m_particles.size() <<
" to "
1454 << theEffectiveFinestLevel + 1 <<
'\n';
1456 m_particles.resize(theEffectiveFinestLevel+1);
1457 m_dummy_mf.resize(theEffectiveFinestLevel+1);
1460 for (
int lev = 0; lev < theEffectiveFinestLevel+1; ++lev) { RedefineDummyMF(lev); }
1462 int finest_lev_particles;
1463 if (lev_max == -1) {
1464 lev_max = theEffectiveFinestLevel;
1465 finest_lev_particles = m_particles.size() - 1;
1467 finest_lev_particles = lev_max;
1471 this->defineBufferMap();
1473 if (! m_particle_locator.isValid(GetParGDB())) { m_particle_locator.build(GetParGDB()); }
1474 m_particle_locator.setGeometry(GetParGDB());
1475 auto assign_grid = m_particle_locator.getGridAssignor();
1479 int num_levels = finest_lev_particles + 1;
1480 op.setNumLevels(num_levels);
1481 Vector<std::map<int, int> > new_sizes(num_levels);
1482 const auto plo = Geom(0).ProbLoArray();
1483 const auto phi = Geom(0).ProbHiArray();
1484 const auto rlo = Geom(0).ProbLoArrayInParticleReal();
1485 const auto rhi = Geom(0).ProbHiArrayInParticleReal();
1486 const auto is_per = Geom(0).isPeriodicArray();
1487 for (
int lev = lev_min; lev <= finest_lev_particles; ++lev)
1489 auto& plev = m_particles[lev];
1490 for (
auto& kv : plev)
1492 int gid = kv.first.first;
1493 int tid = kv.first.second;
1494 auto index = std::make_pair(gid, tid);
1496 auto& src_tile = plev[index];
1497 const size_t np = src_tile.numParticles();
1502 plo, phi, rlo, rhi, is_per, lev, gid, tid,
1503 lev_min, lev_max, nGrow, remove_negative);
1505 int num_move = np - num_stay;
1506 new_sizes[lev][gid] = num_stay;
1507 op.resize(gid, lev, num_move);
1509 auto p_boxes = op.m_boxes[lev][gid].dataPtr();
1510 auto p_levs = op.m_levels[lev][gid].dataPtr();
1511 auto p_src_indices = op.m_src_indices[lev][gid].dataPtr();
1512 auto p_periodic_shift = op.m_periodic_shift[lev][gid].dataPtr();
1513 auto ptd = src_tile.getParticleTileData();
1517 const auto p = ptd[i + num_stay];
1519 if (!p.id().is_valid())
1526 const auto tup = assign_grid(p, lev_min, lev_max, nGrow,
1527 std::forward<CellAssignor>(CellAssignor{}));
1528 p_boxes[i] = amrex::get<0>(tup);
1529 p_levs[i] = amrex::get<1>(tup);
1532 p_src_indices[i] = i+num_stay;
1538 ParticleCopyPlan plan;
1540 plan.build(*
this, op, h_redistribute_int_comp,
1541 h_redistribute_real_comp, local);
1547 if (use_comms_arena) {
1555 for (
int lev = lev_min; lev <= lev_max; ++lev)
1557 auto& plev = m_particles[lev];
1558 for (
auto& kv : plev)
1560 int gid = kv.first.first;
1561 int tid = kv.first.second;
1562 auto index = std::make_pair(gid, tid);
1563 auto& tile = plev[index];
1564 tile.resize(new_sizes[lev][gid]);
1568 for (
int lev = lev_min; lev <= lev_max; lev++)
1570 particle_detail::clearEmptyEntries(m_particles[lev]);
1573 if (
int(m_particles.size()) > theEffectiveFinestLevel+1) {
1574 if (m_verbose > 0) {
1575 amrex::Print() <<
"ParticleContainer::Redistribute() resizing m_particles from "
1576 << m_particles.size() <<
" to " << theEffectiveFinestLevel+1 <<
'\n';
1580 m_particles.resize(theEffectiveFinestLevel + 1);
1581 m_dummy_mf.resize(theEffectiveFinestLevel + 1);
1586 plan.buildMPIFinish(BufferMap());
1588 this->ReserveForRedistribute(plan);
1589 unpackBuffer(*
this, plan, snd_buffer, RedistributeUnpackPolicy());
1591 unpackRemotes(*
this, plan, rcv_buffer, RedistributeUnpackPolicy());
1596 Gpu::PinnedVector<char> pinned_snd_buffer;
1597 Gpu::PinnedVector<char> pinned_rcv_buffer;
1599 if (snd_buffer.arena()->isPinned()) {
1600 plan.buildMPIFinish(BufferMap());
1604 pinned_snd_buffer.resize(snd_buffer.
size());
1606 plan.buildMPIFinish(BufferMap());
1611 this->ReserveForRedistribute(plan);
1613 rcv_buffer.
resize(pinned_rcv_buffer.size());
1614 unpackBuffer(*
this, plan, snd_buffer, RedistributeUnpackPolicy());
1617 unpackRemotes(*
this, plan, rcv_buffer, RedistributeUnpackPolicy());
1627template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1628 template<
class>
class Allocator,
class CellAssignor>
1630ParticleContainer_impl<ParticleType, NArrayReal, NArrayInt, Allocator, CellAssignor>
1633 BL_PROFILE(
"ParticleContainer::ReserveForRedistribute()");
1635 std::map<ParticleTileType*, int> addsizes;
1637 for (
int lev = 0; lev < this->BufferMap().numLevels(); ++lev) {
1638 for (
MFIter mfi = this->MakeMFIter(lev); mfi.
isValid(); ++mfi) {
1639 int gid = mfi.
index();
1641 auto& tile = this->DefineAndReturnParticleTile(lev, gid, tid);
1642 int num_copies = plan.
m_box_counts_h[this->BufferMap().gridAndLevToBucket(gid, lev)];
1643 if (num_copies > 0) {
1644 addsizes[&tile] += num_copies;
1656 auto& tile = this->DefineAndReturnParticleTile(lev, gid, tid);
1657 addsizes[&tile] += copy_size;
1661 ParticleTileType::reserve(addsizes);
1667template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1668 template<
class>
class Allocator,
class CellAssignor>
1673 BL_PROFILE(
"ParticleContainer::RedistributeCPU()");
1678 if (local > 0) { BuildRedistributeMask(0, local); }
1682 int theEffectiveFinestLevel = m_gdb->finestLevel();
1684 while (!m_gdb->LevelDefined(theEffectiveFinestLevel)) {
1685 theEffectiveFinestLevel--;
1688 if (
int(m_particles.size()) < theEffectiveFinestLevel+1) {
1690 amrex::Print() <<
"ParticleContainer::Redistribute() resizing containers from "
1691 << m_particles.size() <<
" to "
1692 << theEffectiveFinestLevel + 1 <<
'\n';
1694 m_particles.resize(theEffectiveFinestLevel+1);
1695 m_dummy_mf.resize(theEffectiveFinestLevel+1);
1700 for (
int lev = 0; lev < theEffectiveFinestLevel+1; ++lev) {
1701 RedefineDummyMF(lev);
1704 int finest_lev_particles;
1705 if (lev_max == -1) {
1706 lev_max = theEffectiveFinestLevel;
1707 finest_lev_particles = m_particles.size() - 1;
1709 finest_lev_particles = lev_max;
1714 std::map<int, Vector<char> > not_ours;
1719 std::map<int, Vector<Vector<char> > > tmp_remote;
1721 ptile_local.resize(theEffectiveFinestLevel+1);
1724 for (
int lev = lev_min; lev <= lev_max; lev++) {
1728 ptile_local[lev][index].resize(num_threads);
1729 for (
int t = 0; t < num_threads; ++t) {
1730 ptile_local[lev][index][t].define(m_num_runtime_real, m_num_runtime_int,
1731 &m_soa_rdata_names, &m_soa_idata_names, arena());
1736 for (
int i = 0; i < neighbor_procs.size(); ++i) {
1737 tmp_remote[neighbor_procs[i]].resize(num_threads);
1741 tmp_remote[i].resize(num_threads);
1747 for (
int lev = lev_min; lev <= finest_lev_particles; lev++) {
1748 auto& pmap = m_particles[lev];
1752 for (
auto& kv : pmap)
1754 grid_tile_ids.push_back(kv.first);
1755 ptile_ptrs.push_back(&(kv.second));
1759#pragma omp parallel for
1761 for (
int pmap_it = 0; pmap_it < static_cast<int>(ptile_ptrs.
size()); ++pmap_it)
1764 int grid = grid_tile_ids[pmap_it].first;
1765 int tile = grid_tile_ids[pmap_it].second;
1767 unsigned npart = ptile_ptrs[pmap_it]->numParticles();
1770 auto particle_tile = ptile_ptrs[pmap_it];
1771 auto ptd = particle_tile->getParticleTileData();
1774 Long last = npart - 1;
1776 while (pindex <= last) {
1777 decltype(
auto) p = ptd[pindex];
1779 if ((remove_negative ==
false) && (!ptd.id(pindex).is_valid())) {
1784 if (!ptd.id(pindex).is_valid()) {
1786 correctCellVectors(last, pindex, grid, p);
1791 locateParticle(p, pld, lev_min, lev_max, nGrow, local ? grid : -1);
1793 particlePostLocate(p, pld, lev);
1795 if (!ptd.id(pindex).is_valid()) {
1797 correctCellVectors(last, pindex, grid, p);
1803 if (who == MyProc) {
1809 auto& dst = ptile_local[pld.
m_lev][index][thread_num];
1810 auto old_size = dst.
size();
1811 auto new_size = old_size + 1;
1813 auto dst_ptd = dst.getParticleTileData();
1817 ptd.id(pindex).make_invalid();
1820 auto& particles_to_send = tmp_remote[who][thread_num];
1821 auto old_size = particles_to_send.size();
1822 auto new_size = old_size + superparticle_size;
1823 particles_to_send.resize(new_size);
1825 ptd.packParticleData(particles_to_send.data(), pindex, old_size,
1826 h_redistribute_real_comp.data(), h_redistribute_int_comp.data());
1828 ptd.id(pindex).make_invalid();
1831 if (!ptd.id(pindex).is_valid()) {
1833 correctCellVectors(last, pindex, grid, p);
1841 auto tot_npart = particle_tile->numTotalParticles();
1843 if (last != npart - 1) {
1846 while (last < tot_npart) {
1851 particle_tile->resize(pindex);
1857 for (
int lev = lev_min; lev <= lev_max; lev++) {
1858 particle_detail::clearEmptyEntries(m_particles[lev]);
1862 for (
int lev = lev_min; lev <= lev_max; lev++) {
1867 for (
auto pmap_it = ptile_local[lev].
begin(); pmap_it != ptile_local[lev].end(); pmap_it++)
1869 DefineAndReturnParticleTile(lev, pmap_it->first.first, pmap_it->first.second);
1870 grid_tile_ids.push_back(pmap_it->first);
1874#pragma omp parallel for
1876 for (
int pit = 0; pit < static_cast<int>(grid_tile_ids.
size()); ++pit)
1878 auto index = grid_tile_ids[pit];
1879 auto& dst_ptile = ParticlesAt(lev, index.first, index.second);
1880 auto& src_ptile = ptile_local[lev][index];
1882 for (
int i = 0; i < num_threads; ++i) {
1884 auto to_copy = src_ptile[i].numParticles();
1885 auto old_size = dst_ptile.numTotalParticles();
1886 auto new_size = old_size + to_copy;
1887 dst_ptile.resize(new_size);
1889 auto dst_ptd = dst_ptile.getParticleTileData();
1890 auto src_ptd = src_ptile[i].getParticleTileData();
1892 for (
Long j = 0; j < to_copy; ++j) {
1896 src_ptile[i].resize(0);
1897 src_ptile[i].shrink_to_fit();
1902 for (
auto& map_it : tmp_remote) {
1903 int who = map_it.first;
1909 for (
auto& kv : tmp_remote)
1911 dest_proc_ids.push_back(kv.first);
1912 pbuff_ptrs.push_back(&(kv.second));
1916#pragma omp parallel for
1918 for (
int pmap_it = 0; pmap_it < static_cast<int>(pbuff_ptrs.
size()); ++pmap_it)
1920 int who = dest_proc_ids[pmap_it];
1922 for (
int i = 0; i < num_threads; ++i) {
1923 not_ours[who].insert(not_ours[who].
end(), tmp[i].begin(), tmp[i].end());
1924 tmp[i].erase(tmp[i].
begin(), tmp[i].end());
1928 particle_detail::clearEmptyEntries(not_ours);
1930 if (
int(m_particles.size()) > theEffectiveFinestLevel+1) {
1932 if (m_verbose > 0) {
1933 amrex::Print() <<
"ParticleContainer::Redistribute() resizing m_particles from "
1934 << m_particles.size() <<
" to " << theEffectiveFinestLevel+1 <<
'\n';
1938 m_particles.resize(theEffectiveFinestLevel + 1);
1939 m_dummy_mf.resize(theEffectiveFinestLevel + 1);
1946 RedistributeMPI(not_ours, lev_min, lev_max, nGrow, local);
1951 if (m_verbose > 0) {
1962 amrex::Print() <<
"ParticleContainer::Redistribute() time: " << stoptime <<
"\n\n";
1969template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
1970 template<
class>
class Allocator,
class CellAssignor>
1974 int lev_min,
int lev_max,
int nGrow,
int local)
1976 BL_PROFILE(
"ParticleContainer::RedistributeMPI()");
1982 using buffer_type =
unsigned long long;
1984 std::map<int, Vector<buffer_type> > mpi_snd_data;
1985 for (
const auto& kv : not_ours)
1987 auto nbt = (kv.second.size() +
sizeof(buffer_type)-1)/
sizeof(buffer_type);
1988 mpi_snd_data[kv.first].resize(nbt);
1989 std::memcpy((
char*) mpi_snd_data[kv.first].data(), kv.second.data(), kv.second.size());
1993 const int NNeighborProcs = neighbor_procs.size();
1996 Vector<Long> Snds(NProcs, 0), Rcvs(NProcs, 0);
2003 BuildRedistributeMask(0, local);
2013 if ((! local) && NumSnds == 0) {
2019 Long tot_snds_this_proc = 0;
2020 Long tot_rcvs_this_proc = 0;
2021 for (
int i = 0; i < NNeighborProcs; ++i) {
2022 tot_snds_this_proc += Snds[neighbor_procs[i]];
2023 tot_rcvs_this_proc += Rcvs[neighbor_procs[i]];
2025 if ( (tot_snds_this_proc == 0) && (tot_rcvs_this_proc == 0) ) {
2030 Vector<int> RcvProc;
2031 Vector<std::size_t> rOffset;
2033 std::size_t TotRcvInts = 0;
2034 std::size_t TotRcvBytes = 0;
2035 for (
int i = 0; i <
NProcs; ++i) {
2037 RcvProc.push_back(i);
2038 rOffset.push_back(TotRcvInts);
2039 TotRcvBytes += Rcvs[i];
2040 auto nbt = (Rcvs[i] +
sizeof(buffer_type)-1)/
sizeof(buffer_type);
2045 const auto nrcvs =
static_cast<int>(RcvProc.size());
2046 Vector<MPI_Status> stats(nrcvs);
2047 Vector<MPI_Request> rreqs(nrcvs);
2050 Vector<unsigned long long> recvdata(TotRcvInts);
2053 for (
int i = 0; i < nrcvs; ++i) {
2054 const auto Who = RcvProc[i];
2055 const auto offset = rOffset[i];
2056 const auto Cnt = (Rcvs[Who] +
sizeof(buffer_type)-1)/
sizeof(buffer_type);
2058 AMREX_ASSERT(Cnt <
size_t(std::numeric_limits<int>::max()));
2066 for (
const auto& kv : mpi_snd_data) {
2067 const auto Who = kv.first;
2068 const auto Cnt = kv.second.size();
2083 int npart = TotRcvBytes / superparticle_size;
2085 Vector<int> rcv_levs(npart);
2086 Vector<int> rcv_grid(npart);
2087 Vector<int> rcv_tile(npart);
2090 ParticleLocData pld;
2091 for (
int j = 0; j < nrcvs; ++j)
2093 const auto offset = rOffset[j];
2094 const auto Who = RcvProc[j];
2095 const auto Cnt = Rcvs[Who] / superparticle_size;
2096 for (
int i = 0; i <
int(Cnt); ++i)
2098 char* pbuf = ((
char*) &recvdata[
offset]) + i*superparticle_size;
2100 Particle<NStructReal, NStructInt> p;
2102 if constexpr (ParticleType::is_soa_particle) {
2103 std::memcpy(&p.m_idcpu, pbuf,
sizeof(uint64_t));
2106 std::memcpy(&pos[0], pbuf +
sizeof(uint64_t), AMREX_SPACEDIM*
sizeof(
ParticleReal));
2111 std::memcpy(&p, pbuf,
sizeof(ParticleType));
2114 bool success = Where(p, pld, lev_min, lev_max, 0);
2117 success = (nGrow > 0) && Where(p, pld, lev_min, lev_min, nGrow);
2118 pld.m_grown_gridbox = pld.m_gridbox;
2122 amrex::Abort(
"RedistributeMPI_locate:: invalid particle.");
2125 rcv_levs[ipart] = pld.m_lev;
2126 rcv_grid[ipart] = pld.m_grid;
2127 rcv_tile[ipart] = pld.m_tile;
2137#ifndef AMREX_USE_GPU
2139 for (
int i = 0; i < nrcvs; ++i)
2141 const auto offset = rOffset[i];
2142 const auto Who = RcvProc[i];
2143 const auto Cnt = Rcvs[Who] / superparticle_size;
2144 for (
int j = 0; j <
int(Cnt); ++j)
2146 auto& ptile = m_particles[rcv_levs[ipart]][std::make_pair(rcv_grid[ipart],
2148 auto old_size = ptile.numTotalParticles();
2149 auto new_size = old_size + 1;
2152 char* pbuf = ((
char*) &recvdata[
offset]) + j*superparticle_size;
2154 if constexpr (ParticleType::is_soa_particle) {
2156 std::memcpy(&idcpudata, pbuf,
sizeof(uint64_t));
2157 pbuf +=
sizeof(uint64_t);
2158 ptile.GetStructOfArrays().GetIdCPUData()[old_size] = idcpudata;
2161 std::memcpy(&p, pbuf,
sizeof(ParticleType));
2162 pbuf +=
sizeof(ParticleType);
2163 ptile.GetArrayOfStructs()[old_size] = p;
2166 int array_comp_start = 0;
2167 if constexpr (!ParticleType::is_soa_particle) {
2168 array_comp_start = AMREX_SPACEDIM + NStructReal;
2170 for (
int comp = 0; comp < NumRealComps(); ++comp) {
2171 if (h_redistribute_real_comp[array_comp_start + comp]) {
2175 ptile.GetStructOfArrays().GetRealData(comp)[old_size] = rdata;
2177 ptile.GetStructOfArrays().GetRealData(comp)[old_size] = 0.0;
2181 array_comp_start = 2 + NStructInt;
2182 for (
int comp = 0; comp < NumIntComps(); ++comp) {
2183 if (h_redistribute_int_comp[array_comp_start + comp]) {
2185 std::memcpy(&idata, pbuf,
sizeof(
int));
2186 pbuf +=
sizeof(
int);
2187 ptile.GetStructOfArrays().GetIntData(comp)[old_size] = idata;
2189 ptile.GetStructOfArrays().GetIntData(comp)[old_size] = 0;
2197 Vector<std::map<std::pair<int, int>, Gpu::HostVector<ParticleType> > > host_particles;
2198 host_particles.reserve(15);
2199 host_particles.resize(finestLevel()+1);
2201 Vector<std::map<std::pair<int, int>,
2202 std::vector<Gpu::HostVector<ParticleReal> > > > host_real_attribs;
2203 host_real_attribs.reserve(15);
2204 host_real_attribs.resize(finestLevel()+1);
2206 Vector<std::map<std::pair<int, int>,
2207 std::vector<Gpu::HostVector<int> > > > host_int_attribs;
2208 host_int_attribs.reserve(15);
2209 host_int_attribs.resize(finestLevel()+1);
2211 Vector<std::map<std::pair<int, int>, Gpu::HostVector<uint64_t> > > host_idcpu;
2212 host_idcpu.reserve(15);
2213 host_idcpu.resize(finestLevel()+1);
2216 for (
int i = 0; i < nrcvs; ++i)
2218 const auto offset = rOffset[i];
2219 const auto Who = RcvProc[i];
2220 const auto Cnt = Rcvs[Who] / superparticle_size;
2221 for (
auto j =
decltype(Cnt)(0); j < Cnt; ++j)
2223 int lev = rcv_levs[ipart];
2224 std::pair<int, int> ind(std::make_pair(rcv_grid[ipart], rcv_tile[ipart]));
2226 char* pbuf = ((
char*) &recvdata[
offset]) + j*superparticle_size;
2228 host_real_attribs[lev][ind].resize(NumRealComps());
2229 host_int_attribs[lev][ind].resize(NumIntComps());
2231 if constexpr (ParticleType::is_soa_particle) {
2233 std::memcpy(&idcpudata, pbuf,
sizeof(uint64_t));
2234 pbuf +=
sizeof(uint64_t);
2235 host_idcpu[lev][ind].push_back(idcpudata);
2238 std::memcpy(&p, pbuf,
sizeof(ParticleType));
2239 pbuf +=
sizeof(ParticleType);
2240 host_particles[lev][ind].push_back(p);
2243 host_real_attribs[lev][ind].resize(NumRealComps());
2244 host_int_attribs[lev][ind].resize(NumIntComps());
2247 int array_comp_start = 0;
2248 if constexpr (!ParticleType::is_soa_particle) {
2249 array_comp_start = AMREX_SPACEDIM + NStructReal;
2251 for (
int comp = 0; comp < NumRealComps(); ++comp) {
2252 if (h_redistribute_real_comp[array_comp_start + comp]) {
2256 host_real_attribs[lev][ind][comp].push_back(rdata);
2258 host_real_attribs[lev][ind][comp].push_back(0.0);
2263 array_comp_start = 2 + NStructInt;
2264 for (
int comp = 0; comp < NumIntComps(); ++comp) {
2265 if (h_redistribute_int_comp[array_comp_start + comp]) {
2267 std::memcpy(&idata, pbuf,
sizeof(
int));
2268 pbuf +=
sizeof(
int);
2269 host_int_attribs[lev][ind][comp].push_back(idata);
2271 host_int_attribs[lev][ind][comp].push_back(0);
2278 for (
int host_lev = 0; host_lev < static_cast<int>(host_particles.size()); ++host_lev)
2280 for (
auto& kv : host_particles[host_lev]) {
2281 auto grid = kv.first.first;
2282 auto tile = kv.first.second;
2283 const auto& src_tile = kv.second;
2285 auto& dst_tile = GetParticles(host_lev)[std::make_pair(grid,tile)];
2286 auto old_size = dst_tile.size();
2287 auto new_size = old_size + src_tile.size();
2288 dst_tile.resize(new_size);
2290 if constexpr (ParticleType::is_soa_particle) {
2292 host_idcpu[host_lev][std::make_pair(grid,tile)].
begin(),
2293 host_idcpu[host_lev][std::make_pair(grid,tile)].
end(),
2294 dst_tile.GetStructOfArrays().GetIdCPUData().begin() + old_size);
2297 src_tile.begin(), src_tile.end(),
2298 dst_tile.GetArrayOfStructs().begin() + old_size);
2301 for (
int i = 0; i < NumRealComps(); ++i) {
2303 host_real_attribs[host_lev][std::make_pair(grid,tile)][i].
begin(),
2304 host_real_attribs[host_lev][std::make_pair(grid,tile)][i].
end(),
2305 dst_tile.GetStructOfArrays().GetRealData(i).begin() + old_size);
2308 for (
int i = 0; i < NumIntComps(); ++i) {
2310 host_int_attribs[host_lev][std::make_pair(grid,tile)][i].
begin(),
2311 host_int_attribs[host_lev][std::make_pair(grid,tile)][i].
end(),
2312 dst_tile.GetStructOfArrays().GetIntData(i).begin() + old_size);
2327template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
2328 template<
class>
class Allocator,
class CellAssignor>
2334 if (lev_max == -1) {
2335 lev_max = finestLevel();
2341template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
2342 template<
class>
class Allocator,
class CellAssignor>
2349 AddParticlesAtLevel(ptile, level, nGrow);
2352template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
2353 template<
class>
class Allocator,
class CellAssignor>
2358 BL_PROFILE(
"ParticleContainer::AddParticlesAtLevel()");
2360 if (
int(m_particles.size()) < level+1)
2364 amrex::Print() <<
"ParticleContainer::AddParticlesAtLevel resizing m_particles from "
2365 << m_particles.size()
2369 m_particles.resize(level+1);
2370 m_dummy_mf.resize(level+1);
2371 for (
int lev = 0; lev < level+1; ++lev) {
2372 RedefineDummyMF(lev);
2376 auto& ptile = DefineAndReturnParticleTile(level, 0, 0);
2377 int old_np = ptile.size();
2378 int num_to_add = particles.
size();
2379 int new_np = old_np + num_to_add;
2380 ptile.resize(new_np);
2382 Redistribute(level, level, nGrow);
2387template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
2388 template<
class>
class Allocator,
class CellAssignor>
2395 int particle_lvl_offset)
const
2397 BL_PROFILE(
"ParticleContainer::AssignCellDensitySingleLevel()");
2399 if (rho_index != 0) {
amrex::Abort(
"AssignCellDensitySingleLevel only works if rho_index = 0"); }
2403 if (OnSameGrids(lev, mf_to_be_filled)) {
2406 mf_pointer = &mf_to_be_filled;
2411 mf_pointer =
new MultiFab(ParticleBoxArray(lev),
2412 ParticleDistributionMap(lev),
2413 ncomp, mf_to_be_filled.
nGrow());
2420 if (mf_pointer->
nGrow() < 1) {
2421 amrex::Error(
"Must have at least one ghost cell when in AssignCellDensitySingleLevel");
2426 const auto dxi = Geom(lev).InvCellSizeArray();
2427 const auto plo = Geom(lev).ProbLoArray();
2428 const auto pdxi = Geom(lev + particle_lvl_offset).InvCellSizeArray();
2430 if (Geom(lev).isAnyPeriodic() && ! Geom(lev).isAllPeriodic())
2432 amrex::Error(
"AssignCellDensitySingleLevel: problem must be periodic in no or all directions");
2439#pragma omp parallel if (Gpu::notInLaunchRegion())
2444 const Long np = pti.numParticles();
2445 auto ptd = pti.GetParticleTile().getConstParticleTileData();
2447 auto rhoarr = fab.
array();
2452 tile_box = pti.tilebox();
2454 local_rho.
resize(tile_box,ncomp);
2456 rhoarr = local_rho.
array();
2460 if (particle_lvl_offset == 0)
2465 amrex_deposit_cic(p, ncomp, rhoarr, plo, dxi);
2473 amrex_deposit_particle_dx_cic(p, ncomp, rhoarr, plo, dxi, pdxi);
2491 for (
int n = 1; n < ncomp; n++)
2495 (*mf_pointer)[mfi].protected_divide<
RunOn::Device>((*mf_pointer)[mfi],0,n,1);
2502 const Real* dx = Geom(lev).CellSize();
2509 if (mf_pointer != &mf_to_be_filled)
2511 mf_to_be_filled.
ParallelCopy(*mf_pointer,0,0,ncomp,0,0);
2522 amrex::Print() <<
"ParticleContainer::AssignCellDensitySingleLevel) time: "
2523 << stoptime <<
'\n';
2527template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
2528 template<
class>
class Allocator,
class CellAssignor>
2533 int old_size = m_num_runtime_real;
2535 m_runtime_comps_defined = (new_size > 0);
2536 m_num_runtime_real = new_size;
2537 int cur_size = h_redistribute_real_comp.size();
2538 h_redistribute_real_comp.resize(cur_size-old_size+new_size, communicate);
2541 for (
int lev = 0; lev < numLevels(); ++lev) {
2543 auto& tile = DefineAndReturnParticleTile(lev, pti);
2544 auto np = tile.numParticles();
2545 if (np > 0 && new_size > old_size) {
2546 auto& soa = tile.GetStructOfArrays();
2553template <
typename ParticleType,
int NArrayReal,
int NArrayInt,
2554 template<
class>
class Allocator,
class CellAssignor>
2559 int old_size = m_num_runtime_int;
2561 m_runtime_comps_defined = (new_size > 0);
2562 m_num_runtime_int = new_size;
2563 int cur_size = h_redistribute_int_comp.size();
2564 h_redistribute_int_comp.resize(cur_size-old_size+new_size, communicate);
2567 for (
int lev = 0; lev < numLevels(); ++lev) {
2569 auto& tile = DefineAndReturnParticleTile(lev, pti);
2570 auto np = tile.numParticles();
2571 if (np > 0 && new_size > old_size) {
2572 auto& soa = tile.GetStructOfArrays();
#define BL_PROFILE_VAR_START(vname)
Definition AMReX_BLProfiler.H:562
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define BL_PROFILE_VAR_STOP(vname)
Definition AMReX_BLProfiler.H:563
#define BL_PROFILE_SYNC_STOP()
Definition AMReX_BLProfiler.H:645
#define BL_PROFILE_SYNC_START_TIMED(fname)
Definition AMReX_BLProfiler.H:644
#define BL_PROFILE_VAR_NS(fname, vname)
Definition AMReX_BLProfiler.H:561
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_FOR_1D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:97
#define AMREX_HOST_DEVICE_FOR_1D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:105
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
amrex::ParmParse pp
Input file parser instance for the given namespace.
Definition AMReX_HypreIJIface.cpp:15
Array4< int const > offset
Definition AMReX_HypreMLABecLap.cpp:1139
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:172
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
Print on all processors of the default communicator.
Definition AMReX_Print.H:113
BaseFab< T > & atomicAdd(const BaseFab< T > &x) noexcept
Atomic FAB addition (a[i] <- a[i] + b[i]).
Definition AMReX_BaseFab.H:2482
Array4< T const > array() const noexcept
Definition AMReX_BaseFab.H:382
void setVal(T const &x, const Box &bx, int dcomp, int ncomp) noexcept
The setVal functions set sub-regions in the BaseFab to a constant value. This most general form speci...
Definition AMReX_BaseFab.H:1400
A collection of Boxes stored in an Array.
Definition AMReX_BoxArray.H:568
IndexType ixType() const noexcept
Return index type of this BoxArray.
Definition AMReX_BoxArray.H:858
BoxArray & grow(int n)
Grow each Box in the BoxArray by the specified amount.
Definition AMReX_BoxArray.cpp:706
std::vector< std::pair< int, Box > > intersections(const Box &bx) const
Return intersections of Box and BoxArray.
Definition AMReX_BoxArray.cpp:1186
Box getCellCenteredBox(int index) const noexcept
Return cell-centered box at element index of this BoxArray.
Definition AMReX_BoxArray.H:748
static bool SameRefs(const BoxArray &lhs, const BoxArray &rhs)
whether two BoxArrays share the same data
Definition AMReX_BoxArray.H:841
A class for managing a List of Boxes that share a common IndexType. This class implements operations ...
Definition AMReX_BoxList.H:52
BoxList & complementIn(const Box &b, const BoxList &bl)
Definition AMReX_BoxList.cpp:307
__host__ __device__ BoxND & grow(int i) noexcept
Definition AMReX_Box.H:641
__host__ __device__ bool contains(const IntVectND< dim > &p) const noexcept
Return true if argument is contained within BoxND.
Definition AMReX_Box.H:212
GpuArray< Real, 3 > InvCellSizeArray() const noexcept
Definition AMReX_CoordSys.H:87
A Fortran Array of REALs.
Definition AMReX_FArrayBox.H:231
void resize(const Box &b, int N=1, Arena *ar=nullptr)
For debugging purposes we hide BaseFab version and do some extra work.
Definition AMReX_FArrayBox.cpp:178
int size() const noexcept
Return the number of FABs in the FabArray.
Definition AMReX_FabArrayBase.H:110
int nGrow(int direction=0) const noexcept
Return the grow factor that defines the region of definition.
Definition AMReX_FabArrayBase.H:78
const DistributionMapping & DistributionMap() const noexcept
Return constant reference to associated DistributionMapping.
Definition AMReX_FabArrayBase.H:131
const BoxArray & boxArray() const noexcept
Return a constant reference to the BoxArray that defines the valid region associated with this FabArr...
Definition AMReX_FabArrayBase.H:95
void ParallelCopy(const FabArray< FAB > &src, const Periodicity &period=Periodicity::NonPeriodic(), CpOp op=FabArrayBase::COPY)
Definition AMReX_FabArray.H:849
Array4< typename FabArray< FAB >::value_type const > array(const MFIter &mfi) const noexcept
Definition AMReX_FabArray.H:565
void setVal(value_type val)
Set all components in the entire region of each FAB to val.
Definition AMReX_FabArray.H:2656
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:74
const Box & Domain() const noexcept
Returns our rectangular domain.
Definition AMReX_Geometry.H:211
GpuArray< Real, 3 > ProbLoArray() const noexcept
Definition AMReX_Geometry.H:187
static void streamSynchronize() noexcept
Definition AMReX_GpuDevice.cpp:855
__host__ __device__ bool cellCentered() const noexcept
True if the IndexTypeND is CELL based in all directions.
Definition AMReX_IndexType.H:104
__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:679
a one-thingy-per-box distributed object
Definition AMReX_LayoutData.H:13
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:85
int LocalTileIndex() const noexcept
The current local tile index in the current grid;.
Definition AMReX_MFIter.H:178
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:169
Box validbox() const noexcept
Return the valid Box in which the current tile resides.
Definition AMReX_MFIter.H:160
int index() const noexcept
The index into the underlying BoxArray of the current FAB.
Definition AMReX_MFIter.H:172
A collection (stored as an array) of FArrayBox objects.
Definition AMReX_MultiFab.H:40
void mult(Real val, int comp, int num_comp, int nghost=0)
Scales the value of each cell in the specified subregion of the MultiFab by the scalar val (a[i] <- a...
Definition AMReX_MultiFab.cpp:1417
Dynamically allocated vector for trivially copyable data.
Definition AMReX_PODVector.H:308
size_type size() const noexcept
Definition AMReX_PODVector.H:648
void resize(size_type a_new_size, GrowthStrategy strategy=GrowthStrategy::Poisson)
Definition AMReX_PODVector.H:728
T * dataPtr() noexcept
Definition AMReX_PODVector.H:670
Definition AMReX_ParIter.H:144
Definition AMReX_ParIter.H:115
MPI_Request req() const
Definition AMReX_ParallelDescriptor.H:74
int queryAdd(std::string_view name, T &ref)
If name is found, the value in the ParmParse database will be stored in the ref argument....
Definition AMReX_ParmParse.H:1044
int queryarr(std::string_view name, std::vector< int > &ref, int start_ix=FIRST, int num_val=ALL) const
Same as queryktharr() but searches for last occurrence of name.
Definition AMReX_ParmParse.cpp:2022
int query(std::string_view name, bool &ref, int ival=FIRST) const
Same as querykth() but searches for the last occurrence of name.
Definition AMReX_ParmParse.cpp:1936
virtual void reserveData()
Definition AMReX_ParticleContainerBase.cpp:41
virtual void resizeData()
Definition AMReX_ParticleContainerBase.cpp:46
A distributed container for Particles sorted onto the levels, grids, and tiles of a block-structured ...
Definition AMReX_ParticleContainer.H:148
void addParticles(const PCType &other, bool local=false)
Add particles from other to this ParticleContainer. local controls whether or not to call Redistribut...
Definition AMReX_ParticleContainerI.H:1155
IntVect Index(const P &p, int lev) const
Definition AMReX_ParticleContainerI.H:201
void ResizeRuntimeIntComp(int new_size, bool communicate)
Definition AMReX_ParticleContainerI.H:2557
bool OK(int lev_min=0, int lev_max=-1, int nGrow=0) const
OK checks that all particles are in the right places (for some value of right)
Definition AMReX_ParticleContainerI.H:2330
std::map< std::pair< int, int >, ParticleTileType > ParticleLevel
Definition AMReX_ParticleContainer.H:189
void SetSoACompileTimeNames(std::vector< std::string > const &rdata_name, std::vector< std::string > const &idata_name)
Definition AMReX_ParticleContainerI.H:109
typename ParticleTileType::AoS AoS
Definition AMReX_ParticleContainer.H:192
void SetParticleSize()
Definition AMReX_ParticleContainerI.H:16
void RemoveParticlesAtLevel(int level)
The Following methods are for managing Virtual and Ghost Particles.
Definition AMReX_ParticleContainerI.H:757
void clearParticles()
Clear all the particles in this container. This does not free memory.
Definition AMReX_ParticleContainerI.H:1128
void Increment(MultiFab &mf, int level)
Definition AMReX_ParticleContainerI.H:720
void AssignCellDensitySingleLevel(int rho_index, MultiFab &mf, int level, int ncomp=1, int particle_lvl_offset=0) const
Definition AMReX_ParticleContainerI.H:2391
bool HasIntComp(std::string const &name)
Definition AMReX_ParticleContainerI.H:148
void ShrinkToFit()
Definition AMReX_ParticleContainerI.H:700
bool HasRealComp(std::string const &name)
Definition AMReX_ParticleContainerI.H:140
void resizeData() override
This resizes the vector of dummy MultiFabs used by the ParticleContainer for the current number of le...
Definition AMReX_ParticleContainerI.H:435
void ResizeRuntimeRealComp(int new_size, bool communicate)
Definition AMReX_ParticleContainerI.H:2531
Long IncrementWithTotal(MultiFab &mf, int level, bool local=false)
Definition AMReX_ParticleContainerI.H:747
Long NumberOfParticlesAtLevel(int level, bool only_valid=true, bool only_local=false) const
Returns # of particles at specified the level.
Definition AMReX_ParticleContainerI.H:551
void SortParticlesByCell()
Sort the particles on each tile by cell, using Fortran ordering.
Definition AMReX_ParticleContainerI.H:1363
int GetRealCompIndex(std::string const &name)
Definition AMReX_ParticleContainerI.H:161
int GetIntCompIndex(std::string const &name)
Definition AMReX_ParticleContainerI.H:183
void RemoveParticlesNotAtFinestLevel()
Definition AMReX_ParticleContainerI.H:771
Vector< Long > NumberOfParticlesInGrid(int level, bool only_valid=true, bool only_local=false) const
Definition AMReX_ParticleContainerI.H:496
void copyParticles(const PCType &other, bool local=false)
Copy particles from other to this ParticleContainer. Will clear all the particles from this container...
Definition AMReX_ParticleContainerI.H:1144
ParticleLocData Reset(ParticleType &prt, bool update, bool verbose=true, ParticleLocData pld=ParticleLocData()) const
Updates a particle's location (Where), tries to periodic shift any particles that have left the domai...
Definition AMReX_ParticleContainerI.H:392
void CapacityOfParticlesInGrid(LayoutData< I > &mem, int lev) const
Return capacity of memory for particles at specific grid.
Definition AMReX_ParticleContainerI.H:593
Long TotalNumberOfParticles(bool only_valid=true, bool only_local=false) const
Returns # of particles at all levels.
Definition AMReX_ParticleContainerI.H:481
void reserveData() override
This reserves data in the vector of dummy MultiFabs used by the ParticleContainer for the maximum num...
Definition AMReX_ParticleContainerI.H:426
T_ParticleType ParticleType
Definition AMReX_ParticleContainer.H:150
Definition AMReX_ParticleLocator.H:104
AssignGrid< BinIteratorFactory > getGridAssignor() const noexcept
Definition AMReX_ParticleLocator.H:183
void build(const BoxArray &ba, const Geometry &geom)
Definition AMReX_ParticleLocator.H:111
This class provides the user with a few print options.
Definition AMReX_Print.H:35
Definition AMReX_Reduce.H:453
Type value()
Definition AMReX_Reduce.H:488
Definition AMReX_Reduce.H:612
std::enable_if_t< IsFabArray< MF >::value > eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:746
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:28
Long size() const noexcept
Definition AMReX_Vector.H:53
A Collection of IArrayBoxes.
Definition AMReX_iMultiFab.H:34
Long sum(int comp, int nghost=0, bool local=false) const
Returns the sum in component comp.
Definition AMReX_iMultiFab.cpp:454
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
amrex_long Long
Definition AMReX_INT.H:30
T ExclusiveSum(N n, T const *in, T *out, RetSum a_ret_sum=retSum)
Exclusive sum.
Definition AMReX_Scan.H:1290
void SumBoundary(const Periodicity &period=Periodicity::NonPeriodic(), bool deterministic=false)
Sum values in overlapped cells.
Definition AMReX_FabArray.H:3587
__host__ __device__ BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Grow BoxND in all directions by given amount.
Definition AMReX_Box.H:1280
Arena * The_Comms_Arena()
Definition AMReX_Arena.cpp:865
void Min(KeyValuePair< K, V > &vi, int root, MPI_Comm comm)
Definition AMReX_ParallelReduce.H:287
void Max(KeyValuePair< K, V > &vi, int root, MPI_Comm comm)
Definition AMReX_ParallelReduce.H:254
void Sum(T &v, MPI_Comm comm)
Definition AMReX_ParallelReduce.H:221
void Sum(T &v, int root, MPI_Comm comm)
Definition AMReX_ParallelReduce.H:352
__host__ __device__ AMREX_FORCE_INLINE void AddNoRet(T *sum, T value) noexcept
Definition AMReX_GpuAtomic.H:284
void copyAsync(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
A host-to-device copy routine. Note this is just a wrapper around memcpy, so it assumes contiguous st...
Definition AMReX_GpuContainers.H:228
static constexpr HostToDevice hostToDevice
Definition AMReX_GpuContainers.H:105
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:310
void dtoh_memcpy_async(void *p_h, const void *p_d, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:435
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:92
bool notInLaunchRegion() noexcept
Definition AMReX_GpuControl.H:93
void htod_memcpy_async(void *p_d, const void *p_h, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:421
void QueueReduction(Func f)
Definition AMReX_Lazy.cpp:7
constexpr Long GhostParticleID
Definition AMReX_Particle.H:19
constexpr Long VirtualParticleID
Definition AMReX_Particle.H:20
int NProcs()
Process ID in MPI_COMM_WORLD.
Definition AMReX_MPMD.cpp:122
constexpr int get_thread_num()
Definition AMReX_OpenMP.H:37
constexpr int get_max_threads()
Definition AMReX_OpenMP.H:36
MPI_Comm CommunicatorSub() noexcept
sub-communicator for current frame
Definition AMReX_ParallelContext.H:70
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
int NProcsSub() noexcept
number of ranks in current frame
Definition AMReX_ParallelContext.H:74
int IOProcessorNumberSub() noexcept
IO sub-rank in current frame.
Definition AMReX_ParallelContext.H:78
bool UseGpuAwareMpi()
Definition AMReX_ParallelDescriptor.H:113
void Waitall(Vector< MPI_Request > &, Vector< MPI_Status > &)
Definition AMReX_ParallelDescriptor.cpp:1308
Message Send(const T *buf, size_t n, int dst_pid, int tag)
Definition AMReX_ParallelDescriptor.H:1193
void Bcast(void *, int, MPI_Datatype, int, MPI_Comm)
Definition AMReX_ParallelDescriptor.cpp:1295
int SeqNum() noexcept
Returns sequential message sequence numbers, usually used as tags for send/recv.
Definition AMReX_ParallelDescriptor.H:696
void GatherLayoutDataToVector(const LayoutData< T > &sendbuf, Vector< T > &recvbuf, int root)
Gather LayoutData values to a vector on root.
Definition AMReX_ParallelDescriptor.H:1295
Message Arecv(T *, size_t n, int pid, int tag)
Definition AMReX_ParallelDescriptor.H:1214
static constexpr RetSum retSum
Definition AMReX_Scan.H:32
Definition AMReX_Amr.cpp:49
__host__ __device__ void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:139
int nComp(FabArrayBase const &fa)
Definition AMReX_FabArrayBase.cpp:2851
__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:184
void communicateParticlesStart(const PC &pc, ParticleCopyPlan &plan, const SndBuffer &snd_buffer, RcvBuffer &rcv_buffer)
Definition AMReX_ParticleCommunication.H:505
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:193
__host__ __device__ void copyParticle(const ParticleTileData< T_ParticleType, NAR, NAI > &dst, const ConstParticleTileData< T_ParticleType, NAR, NAI > &src, int src_i, int dst_i) noexcept
A general single particle copying routine that can run on the GPU.
Definition AMReX_ParticleTransformation.H:31
void unpackRemotes(PC &pc, const ParticleCopyPlan &plan, Buffer &rcv_buffer, UnpackPolicy const &policy)
Definition AMReX_ParticleCommunication.H:605
void copyParticles(DstTile &dst, const SrcTile &src) noexcept
Copy particles from src to dst. This version copies all the particles, writing them to the beginning ...
Definition AMReX_ParticleTransformation.H:161
Long doHandShake(const std::map< int, Vector< char > > ¬_ours, Vector< Long > &Snds, Vector< Long > &Rcvs)
Definition AMReX_ParticleMPIUtil.cpp:25
Index filterAndTransformParticles(DstTile &dst, const SrcTile &src, Index *mask, F const &f, Index src_start, Index dst_start) noexcept
Conditionally copy particles from src to dst based on the value of mask. A transformation will also b...
Definition AMReX_ParticleTransformation.H:456
__host__ __device__ bool enforcePeriodic(P &p, amrex::GpuArray< amrex::Real, 3 > const &plo, amrex::GpuArray< amrex::Real, 3 > const &phi, amrex::GpuArray< amrex::ParticleReal, 3 > const &rlo, amrex::GpuArray< amrex::ParticleReal, 3 > const &rhi, amrex::GpuArray< int, 3 > const &is_per) noexcept
Definition AMReX_ParticleUtil.H:421
Long doHandShakeLocal(const std::map< int, Vector< char > > ¬_ours, const Vector< int > &neighbor_procs, Vector< Long > &Snds, Vector< Long > &Rcvs)
Definition AMReX_ParticleMPIUtil.cpp:50
__host__ __device__ int numTilesInBox(const Box &box, const bool a_do_tiling, const IntVect &a_tile_size)
Definition AMReX_ParticleUtil.H:232
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:30
__host__ __device__ Dim3 begin(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:2006
double second() noexcept
Definition AMReX_Utility.cpp:940
void communicateParticlesFinish(const ParticleCopyPlan &plan)
Definition AMReX_ParticleCommunication.cpp:384
Index filterParticles(DstTile &dst, const SrcTile &src, const Index *mask) noexcept
Conditionally copy particles from src to dst based on the value of mask.
Definition AMReX_ParticleTransformation.H:330
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:33
void ParticleToMesh(PC const &pc, const Vector< MultiFab * > &mf, int lev_min, int lev_max, F &&f, bool zero_out_input=true, bool vol_weight=true)
Deposit particles onto a hierarchy of MultiFabs.
Definition AMReX_AmrParticles.H:188
void Error(const std::string &msg)
Print out message to cerr and exit via amrex::Abort().
Definition AMReX.cpp:234
void gatherParticles(PTile &dst, const PTile &src, N np, const Index *inds)
Gather particles copies particles into contiguous order from an arbitrary order. Specifically,...
Definition AMReX_ParticleTransformation.H:674
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:34
int Verbose() noexcept
Definition AMReX.cpp:179
int partitionParticlesByDest(PTile &ptile, const PLocator &ploc, CellAssignor const &assignor, const ParticleBufferMap &pmap, const GpuArray< Real, 3 > &plo, const GpuArray< Real, 3 > &phi, const GpuArray< ParticleReal, 3 > &rlo, const GpuArray< ParticleReal, 3 > &rhi, const GpuArray< int, 3 > &is_per, int lev, int gid, int, int lev_min, int lev_max, int nGrow, bool remove_negative)
Definition AMReX_ParticleUtil.H:654
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:240
const int[]
Definition AMReX_BLProfiler.cpp:1664
void transformParticles(DstTile &dst, const SrcTile &src, F &&f) noexcept
Apply the function f to all the particles in src, writing the result to dst. This version does all th...
Definition AMReX_ParticleTransformation.H:213
__host__ __device__ Dim3 end(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:2015
void unpackBuffer(PC &pc, const ParticleCopyPlan &plan, const Buffer &snd_buffer, UnpackPolicy const &policy)
Definition AMReX_ParticleCommunication.H:440
void packBuffer(const PC &pc, const ParticleCopyOp &op, const ParticleCopyPlan &plan, Buffer &snd_buffer)
Definition AMReX_ParticleCommunication.H:336
__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:336
Definition AMReX_ParticleLocator.H:216
A multidimensional array accessor.
Definition AMReX_Array4.H:283
Definition AMReX_ParticleContainerI.H:1038
amrex::AmrAssignGrid< amrex::DenseBinIteratorFactory< amrex::Box > > m_assign_grid
Definition AMReX_ParticleContainerI.H:1041
int m_lev_max
Definition AMReX_ParticleContainerI.H:1040
AssignGridFilter(amrex::AmrAssignGrid< amrex::DenseBinIteratorFactory< amrex::Box > > assign_grid, int gid, int level, int nGrow)
This filters based on matching grids.
Definition AMReX_ParticleContainerI.H:1047
int m_nGrow
Definition AMReX_ParticleContainerI.H:1040
int m_lev_min
Definition AMReX_ParticleContainerI.H:1040
AMREX_GPU_HOST_DEVICE int operator()(const SrcData &src, int src_i) const noexcept
Definition AMReX_ParticleContainerI.H:1053
int m_gid
Definition AMReX_ParticleContainerI.H:1040
Definition AMReX_ParticleLocator.H:14
Definition AMReX_ParticleTile.H:514
Definition AMReX_ParticleUtil.H:394
Definition AMReX_DenseBins.H:32
Definition AMReX_ParticleContainerI.H:799
Box m_domain
Definition AMReX_ParticleContainerI.H:803
GpuArray< Real, 3 > m_dxi
Definition AMReX_ParticleContainerI.H:802
FilterVirt(const amrex::AssignGrid< amrex::DenseBinIteratorFactory< amrex::Box > > &assign_buffer_grid, const GpuArray< Real, 3 > &plo, const GpuArray< Real, 3 > &dxi, const Box &domain)
Definition AMReX_ParticleContainerI.H:805
AMREX_GPU_HOST_DEVICE int operator()(const SrcData &src, int src_i) const noexcept
Definition AMReX_ParticleContainerI.H:812
amrex::AssignGrid< amrex::DenseBinIteratorFactory< amrex::Box > > m_assign_buffer_grid
Definition AMReX_ParticleContainerI.H:801
GpuArray< Real, 3 > m_plo
Definition AMReX_ParticleContainerI.H:802
Definition AMReX_ParticleUtil.H:303
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:43
Definition AMReX_GpuControl.H:184
Definition AMReX_ParticleCommunication.H:81
Vector< int > m_rcv_box_ids
Definition AMReX_ParticleCommunication.H:90
Vector< int > m_rcv_box_counts
Definition AMReX_ParticleCommunication.H:88
Vector< int > m_rcv_box_levs
Definition AMReX_ParticleCommunication.H:92
int m_nrcvs
Definition AMReX_ParticleCommunication.H:95
Gpu::HostVector< unsigned int > m_box_counts_h
Definition AMReX_ParticleCommunication.H:85
A struct used for storing a particle's position in the AMR hierarchy.
Definition AMReX_ParticleContainer.H:92
Box m_grown_gridbox
Definition AMReX_ParticleContainer.H:99
IntVect m_cell
Definition AMReX_ParticleContainer.H:96
int m_grid
Definition AMReX_ParticleContainer.H:94
int m_tile
Definition AMReX_ParticleContainer.H:95
int m_lev
Definition AMReX_ParticleContainer.H:93
Box m_tilebox
Definition AMReX_ParticleContainer.H:98
Box m_gridbox
Definition AMReX_ParticleContainer.H:97
Definition AMReX_ParticleTile.H:721
std::size_t size() const
Returns the total number of particles (real and neighbor)
Definition AMReX_ParticleTile.H:890
ParticleTileDataType getParticleTileData()
Definition AMReX_ParticleTile.H:1203
int numParticles() const
Returns the number of real particles (excluding neighbors)
Definition AMReX_ParticleTile.H:903
void resize(std::size_t count, GrowthStrategy strategy=GrowthStrategy::Poisson)
Definition AMReX_ParticleTile.H:969
AoS & GetArrayOfStructs()
Definition AMReX_ParticleTile.H:878
bool empty() const
Definition AMReX_ParticleTile.H:884
The struct used to store particles.
Definition AMReX_Particle.H:404
__host__ __device__ RealVect pos() const &
Definition AMReX_Particle.H:454