186 int lev_min,
int lev_max,
bool isRegrid)
189 if ( !PData.isForbidTransform() ) {
193 PData.domainMapping();
201 int theEffectiveFinestLevel = this->finestLevel();
202 while (!this->LevelDefined(theEffectiveFinestLevel)) {
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);
225 size_t lBegin = LocalNumPerLevel.begin(lev_min);
226 size_t lEnd = LocalNumPerLevel.end(lev_max);
239 for (
unsigned int ip = lBegin; ip < lEnd; ++ip) {
241 const size_t& lold = PData.Level[ip];
250 locateParticle(PData, ip, lev_min, lev_max, nGrow);
254 const size_t& lnew = PData.Level[ip];
256 const unsigned int who = ParticleDistributionMap(lnew)[PData.Grid[ip]];
258 --LocalNumPerLevel[lold];
263 p2n.insert(std::pair<unsigned, unsigned>(who, ip));
268 ++LocalNumPerLevel[lnew];
273 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
277 typename std::multimap<unsigned, unsigned>::iterator i = p2n.begin();
279 Format *format = PData.getFormat();
281 std::vector<MPI_Request> requests;
282 std::vector<MsgBuffer*> buffers;
285 while (i!=p2n.end()) {
286 unsigned cur_destination = i->first;
290 for (; i!=p2n.end() && i->first == cur_destination; ++i) {
292 PData.putMessage(msg, i->second);
293 PData.destroy(1, i->second);
299 cur_destination, tag);
302 requests.push_back(request);
303 buffers.push_back(msgbuf);
308 if ( LocalNum < PData.getDestroyNum() ) {
310 "Rank " + std::to_string(myN) +
311 " can't destroy more particles than possessed.");
313 LocalNum -= PData.getDestroyNum();
314 PData.performDestroy();
317 for (
int lev = lev_min; lev <= lev_max; ++lev) {
318 if ( LocalNumPerLevel[lev] < 0 ) {
320 "Negative particle level count.");
325 for (
int k = 0; k<msgrecv[myN]; ++k) {
329 MsgBuffer recvbuf(format, buffer, bufsize);
336 size_t pBeginIdx = LocalNum;
338 LocalNum += PData.getSingleMessage(*msg);
340 size_t pEndIdx = LocalNum;
342 for (
size_t idx = pBeginIdx; idx < pEndIdx; ++idx)
343 ++LocalNumPerLevel[ PData.Level[idx] ];
351 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
352 MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
353 for (
unsigned int j = 0; j<buffers.size(); ++j) {
365 allreduce(&LocalNum, &TotalNum, 1, std::plus<size_t>());
368 PData.setTotalNum(TotalNum);
369 PData.setLocalNum(LocalNum);
372 if ( LocalNum != LocalNumPerLevel.getLocalNumAllLevel() )
374 "Local #particles disagrees with sum over levels");
376 if ( !PData.isForbidTransform() ) {
378 PData.domainMapping(
true);
420 if ( lev >= (
int)masks_m.size() )
421 masks_m.resize(lev + 1);
423 masks_m[lev].reset(
new mask_t(ParticleBoxArray(lev),
424 ParticleDistributionMap(lev), 1, 1));
426 masks_m[lev]->setVal(1, 1);
428 mask_t tmp_mask(ParticleBoxArray(lev),
429 ParticleDistributionMap(lev),
432 tmp_mask.setVal(0, ncells);
434 tmp_mask.BuildMask(Geom(lev).Domain(), Geom(lev).periodicity(),
435 covered, notcovered, physbnd, interior);
437 tmp_mask.FillBoundary(Geom(lev).periodicity());
439 for (amrex::MFIter mfi(tmp_mask); mfi.isValid(); ++mfi) {
440 const AmrBox_t& bx = mfi.validbox();
441 const int* lo = bx.loVect();
442 const int* hi = bx.hiVect();
447 for (
int i = lo[0]; i <= hi[0]; ++i) {
448 for (
int j = lo[1]; j <= hi[1]; ++j) {
449 for (
int k = lo[2]; k <= hi[2]; ++k) {
452 for (
int ii = i - ncells; ii <= i + ncells; ++ii) {
453 for (
int jj = j - ncells; jj <= j + ncells; ++jj) {
454 for (
int kk = k - ncells; kk <= k + ncells; ++kk) {
470 masks_m[lev]->FillBoundary(Geom(lev).periodicity());
542 const unsigned int ip,
549 lev_max = finestLevel();
551 PAssert(lev_max <= finestLevel());
553 PAssert(nGrow == 0 || (nGrow >= 0 && lev_min == lev_max));
555 std::vector< std::pair<int, AmrBox_t> > isects;
557 for (
int lev = lev_max; lev >= lev_min; lev--)
560 const AmrGrid_t& ba = ParticleBoxArray(lev);
561 PAssert(ba.ixType().cellCentered());
563 if (lev == (
int)p.Level[ip]) {
565 if (0 <= p.Grid[ip] && p.Grid[ip] < ba.size()) {
566 const AmrBox_t& bx = ba.getCellCenteredBox(p.Grid[ip]);
567 const AmrBox_t& gbx = amrex::grow(bx,nGrow);
568 if (gbx.contains(iv)) {
578 ba.intersections(
AmrBox_t(iv, iv), isects,
true, nGrow);
580 if (!isects.empty()) {
582 p.Grid[ip] = isects[0].first;
649 const AmrBox_t& dmn = geom.Domain();
651 bool shifted =
false;
653 for (
int i = 0; i < AMREX_SPACEDIM; i++) {
654 if (!geom.isPeriodic(i))
continue;
656 if (iv[i] > dmn.bigEnd(i)) {
657 if (R[i] == geom.ProbHi(i)) {
663 R[i] += .125*geom.CellSize(i);
665 R[i] -= geom.ProbLength(i);
667 if (R[i] <= geom.ProbLo(i))
671 R[i] += .125*geom.CellSize(i);
673 PAssert(R[i] >= geom.ProbLo(i));
677 }
else if (iv[i] < dmn.smallEnd(i)) {
678 if (R[i] == geom.ProbLo(i)) {
684 R[i] -= .125*geom.CellSize(i);
686 R[i] += geom.ProbLength(i);
688 if (R[i] >= geom.ProbHi(i)) {
692 R[i] -= .125*geom.CellSize(i);
694 PAssert(R[i] <= geom.ProbHi(i));
710 const unsigned int ip,
711 int lev_min,
int lev_max,
int nGrow)
const
713 bool outside = D_TERM( p.R[ip](0) < AmrGeometry_t::ProbLo(0)
714 || p.R[ip](0) >= AmrGeometry_t::ProbHi(0),
715 || p.R[ip](1) < AmrGeometry_t::ProbLo(1)
716 || p.R[ip](1) >= AmrGeometry_t::ProbHi(1),
717 || p.R[ip](2) < AmrGeometry_t::ProbLo(2)
718 || p.R[ip](2) >= AmrGeometry_t::ProbHi(2));
720 bool success =
false;
724 success = EnforcePeriodicWhere(p, ip, lev_min, lev_max);
725 if (!success && lev_min == 0) {
734 "We're losing particles although we shouldn't");
738 success = Where(p, ip, lev_min, lev_max);
742 success = (nGrow > 0) && Where(p, ip, lev_min, lev_min, nGrow);
746 std::stringstream ss;
747 ss <<
"Invalid particle with ID " << ip <<
" at position " << p.R[ip] <<
".";
748 throw OpalException(
"BoxLibLayout::locateParticle()", ss.str());
794 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
799 real_box.setLo(d, lowerBound[d] * (1.0 + dh));
800 real_box.setHi(d, upperBound[d] * (1.0 + dh));
803 AmrGeometry_t::ProbDomain(real_box);
807 AmrIntVect_t domain_hi(nGridPoints - 1, nGridPoints - 1, nGridPoints - 1);
808 const AmrBox_t domain(domain_lo, domain_hi);
814 int is_per[AMREX_SPACEDIM];
815 for (
int i = 0; i < AMREX_SPACEDIM; i++)
819 geom.define(domain, &real_box, coord, is_per);
824 ba.maxSize(maxGridSize);
830 this->m_geom.resize(1);
831 this->m_geom[0] = geom;
833 this->m_dmap.resize(1);
834 this->m_dmap[0] = dmap;
836 this->m_ba.resize(1);
839 this->m_nlevels = ba.size();