186 int lev_min,
int lev_max,
bool isRegrid)
189 if ( !PData.isForbidTransform() ) {
193 PData.domainMapping();
203 theEffectiveFinestLevel--;
207 lev_max = theEffectiveFinestLevel;
208 else if ( lev_max > theEffectiveFinestLevel )
209 lev_max = theEffectiveFinestLevel;
212 size_t LocalNum = PData.getLocalNum();
214 auto& LocalNumPerLevel = PData.getLocalNumPerLevel();
216 if ( LocalNum != LocalNumPerLevel.getLocalNumAllLevel() )
218 "Local #particles disagrees with sum over levels");
220 std::multimap<unsigned, unsigned> p2n;
222 std::vector<int> msgsend(N);
223 std::vector<int> msgrecv(N);
226 size_t lBegin = LocalNumPerLevel.begin(lev_min);
227 size_t lEnd = LocalNumPerLevel.end(lev_max);
240 for (
unsigned int ip = lBegin; ip < lEnd; ++ip) {
242 const size_t& lold = PData.Level[ip];
255 const size_t& lnew = PData.Level[ip];
257 const unsigned int who = ParticleDistributionMap(lnew)[PData.Grid[ip]];
259 --LocalNumPerLevel[lold];
264 p2n.insert(std::pair<unsigned, unsigned>(who, ip));
270 ++LocalNumPerLevel[lnew];
275 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
279 typename std::multimap<unsigned, unsigned>::iterator i = p2n.begin();
281 Format *format = PData.getFormat();
283 std::vector<MPI_Request> requests;
284 std::vector<MsgBuffer*> buffers;
287 while (i!=p2n.end()) {
288 unsigned cur_destination = i->first;
292 for (; i!=p2n.end() && i->first == cur_destination; ++i) {
294 PData.putMessage(msg, i->second);
295 PData.destroy(1, i->second);
301 cur_destination, tag);
304 requests.push_back(request);
305 buffers.push_back(msgbuf);
310 if ( LocalNum < PData.getDestroyNum() ) {
312 "Rank " + std::to_string(myN) +
313 " can't destroy more particles than possessed.");
315 LocalNum -= PData.getDestroyNum();
316 PData.performDestroy();
319 for (
int lev = lev_min; lev <= lev_max; ++lev) {
320 if ( LocalNumPerLevel[lev] < 0 ) {
322 "Negative particle level count.");
327 for (
int k = 0; k<msgrecv[myN]; ++k) {
330 int bufsize =
Ippl::Comm->raw_probe_receive(buffer, node, tag);
331 MsgBuffer recvbuf(format, buffer, bufsize);
338 size_t pBeginIdx = LocalNum;
340 LocalNum += PData.getSingleMessage(*msg);
342 size_t pEndIdx = LocalNum;
344 for (
size_t idx = pBeginIdx; idx < pEndIdx; ++idx)
345 ++LocalNumPerLevel[ PData.Level[idx] ];
353 MPI_Request* requests_ptr = requests.empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
354 MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
355 for (
unsigned int j = 0; j<buffers.size(); ++j) {
367 allreduce(&LocalNum, &TotalNum, 1, std::plus<size_t>());
370 PData.setTotalNum(TotalNum);
371 PData.setLocalNum(LocalNum);
374 if ( LocalNum != LocalNumPerLevel.getLocalNumAllLevel() )
376 "Local #particles disagrees with sum over levels");
378 if ( !PData.isForbidTransform() ) {
380 PData.domainMapping(
true);
422 if ( lev >= (
int)
masks_m.size() )
426 ParticleDistributionMap(lev), 1, 1));
430 mask_t tmp_mask(ParticleBoxArray(lev),
431 ParticleDistributionMap(lev),
434 tmp_mask.setVal(0, ncells);
436 tmp_mask.BuildMask(Geom(lev).Domain(), Geom(lev).periodicity(),
437 covered, notcovered, physbnd, interior);
439 tmp_mask.FillBoundary(Geom(lev).periodicity());
441 for (amrex::MFIter mfi(tmp_mask); mfi.isValid(); ++mfi) {
442 const AmrBox_t& bx = mfi.validbox();
443 const int* lo = bx.loVect();
444 const int* hi = bx.hiVect();
449 for (
int i = lo[0]; i <= hi[0]; ++i) {
450 for (
int j = lo[1]; j <= hi[1]; ++j) {
451 for (
int k = lo[2]; k <= hi[2]; ++k) {
454 for (
int ii = i - ncells; ii <= i + ncells; ++ii) {
455 for (
int jj = j - ncells; jj <= j + ncells; ++jj) {
456 for (
int kk = k - ncells; kk <= k + ncells; ++kk) {
472 masks_m[lev]->FillBoundary(Geom(lev).periodicity());
651 const AmrBox_t& dmn = geom.Domain();
653 bool shifted =
false;
655 for (
int i = 0; i < AMREX_SPACEDIM; i++) {
656 if (!geom.isPeriodic(i))
continue;
658 if (iv[i] > dmn.bigEnd(i)) {
659 if (R[i] == geom.ProbHi(i)) {
665 R[i] += .125*geom.CellSize(i);
667 R[i] -= geom.ProbLength(i);
669 if (R[i] <= geom.ProbLo(i))
673 R[i] += .125*geom.CellSize(i);
675 PAssert(R[i] >= geom.ProbLo(i));
679 }
else if (iv[i] < dmn.smallEnd(i)) {
680 if (R[i] == geom.ProbLo(i)) {
686 R[i] -= .125*geom.CellSize(i);
688 R[i] += geom.ProbLength(i);
690 if (R[i] >= geom.ProbHi(i)) {
694 R[i] -= .125*geom.CellSize(i);
696 PAssert(R[i] <= geom.ProbHi(i));
712 const unsigned int ip,
713 int lev_min,
int lev_max,
int nGrow)
const
715 bool outside = D_TERM( p.R[ip](0) < AmrGeometry_t::ProbLo(0)
716 || p.R[ip](0) >= AmrGeometry_t::ProbHi(0),
717 || p.R[ip](1) < AmrGeometry_t::ProbLo(1)
718 || p.R[ip](1) >= AmrGeometry_t::ProbHi(1),
719 || p.R[ip](2) < AmrGeometry_t::ProbLo(2)
720 || p.R[ip](2) >= AmrGeometry_t::ProbHi(2));
722 bool success =
false;
727 if (!success && lev_min == 0) {
736 "We're losing particles although we shouldn't");
740 success =
Where(p, ip, lev_min, lev_max);
744 success = (nGrow > 0) &&
Where(p, ip, lev_min, lev_min, nGrow);
748 std::stringstream ss;
749 ss <<
"Invalid particle with ID " << ip <<
" at position " << p.R[ip] <<
".";
750 throw OpalException(
"BoxLibLayout::locateParticle()", ss.str());