36 #ifndef BoxLibLayout_HPP
37 #define BoxLibLayout_HPP
52 template <
class T,
unsigned Dim>
56 template <
class T,
unsigned Dim>
60 template<
class T,
unsigned Dim>
78 int nGridPoints =
std::ceil( std::cbrt( nProcs ) ) * maxGridSize;
84 template<
class T,
unsigned Dim>
87 ParGDB(layout_p->m_geom,
99 template<
class T,
unsigned Dim>
109 template<
class T,
unsigned Dim>
114 ParGDB(geom, dmap, ba),
119 template<
class T,
unsigned Dim>
125 ParGDB(geom, dmap, ba, rr),
130 template<
class T,
unsigned Dim>
134 int nGridPoints = this->m_geom[0].Domain().length(0);
135 int maxGridSize = this->m_ba[0][0].length(0);
137 this->initBaseBox_m(nGridPoints, maxGridSize, dh);
141 template <
class T,
unsigned Dim>
144 static bool isCalled =
false;
152 if ( ratio.size() !=
Dim ) {
154 "Length " + std::to_string(ratio.size()) +
155 " != " + std::to_string(
Dim));
158 for (
unsigned int i = 0; i <
Dim; ++i) {
159 if ( ratio[i] <= 0.0 ) {
161 "The ratio has to be larger than zero.");
164 lowerBound[i] *= ratio[i];
165 upperBound[i] *= ratio[i];
170 template<
class T,
unsigned Dim>
177 throw OpalException(
"BoxLibLayout::update(IpplParticleBase, ParticleAttrib) ",
178 "Wrong update method called.");
184 template<
class T,
unsigned Dim>
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);
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];
251 locateParticle(PData, ip, lev_min, lev_max, nGrow);
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>());
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) {
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);
387 template <
class T,
unsigned Dim>
390 const unsigned int ip,
393 return Index(p.R[ip], lev);
397 template <
class T,
unsigned Dim>
405 D_TERM(iv[0]=
floor((R[0]-geom.ProbLo(0))/geom.CellSize(0));,
406 iv[1]=
floor((R[1]-geom.ProbLo(1))/geom.CellSize(1));,
407 iv[2]=
floor((R[2]-geom.ProbLo(2))/geom.CellSize(2)););
409 iv += geom.Domain().smallEnd();
415 template <
class T,
unsigned Dim>
422 if ( lev >= (
int)masks_m.size() )
423 masks_m.resize(lev + 1);
425 masks_m[lev].reset(
new mask_t(ParticleBoxArray(lev),
426 ParticleDistributionMap(lev), 1, 1));
428 masks_m[lev]->setVal(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());
476 template <
class T,
unsigned Dim>
478 PAssert(lev < (
int)masks_m.size());
479 masks_m[lev].reset(
nullptr);
483 template <
class T,
unsigned Dim>
484 const std::unique_ptr<typename BoxLibLayout<T, Dim>::mask_t>&
486 if ( lev >= (
int)masks_m.size() ) {
488 "Unable to access level " + std::to_string(lev) +
".");
542 template <
class T,
unsigned Dim>
544 const unsigned int ip,
551 lev_max = finestLevel();
553 PAssert(lev_max <= finestLevel());
555 PAssert(nGrow == 0 || (nGrow >= 0 && lev_min == lev_max));
557 std::vector< std::pair<int, AmrBox_t> > isects;
559 for (
int lev = lev_max; lev >= lev_min; lev--)
562 const AmrGrid_t& ba = ParticleBoxArray(lev);
563 PAssert(ba.ixType().cellCentered());
565 if (lev == (
int)p.Level[ip]) {
567 if (0 <= p.Grid[ip] && p.Grid[ip] < ba.size()) {
568 const AmrBox_t& bx = ba.getCellCenteredBox(p.Grid[ip]);
569 const AmrBox_t& gbx = amrex::grow(bx,nGrow);
570 if (gbx.contains(iv)) {
580 ba.intersections(
AmrBox_t(iv, iv), isects,
true, nGrow);
582 if (!isects.empty()) {
584 p.Grid[ip] = isects[0].first;
596 template <
class T,
unsigned Dim>
598 const unsigned int ip,
602 if (!Geom(0).isAnyPeriodic())
return false;
605 lev_max = finestLevel();
607 PAssert(lev_max <= finestLevel());
613 if (PeriodicShift(R)) {
614 std::vector< std::pair<int, AmrBox_t> > isects;
616 for (
int lev = lev_max; lev >= lev_min; lev--) {
618 const AmrGrid_t& ba = ParticleBoxArray(lev);
620 ba.intersections(
AmrBox_t(iv,iv),isects,
true,0);
622 if (!isects.empty()) {
623 D_TERM(p.R[ip][0] = R[0];,
628 p.Grid[ip] = isects[0].first;
641 template <
class T,
unsigned Dim>
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));
709 template <
class T,
unsigned Dim>
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;
726 success = EnforcePeriodicWhere(p, ip, lev_min, lev_max);
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());
756 template <
class T,
unsigned Dim>
758 return level <= this->maxLevel_m && !m_ba[level].empty() && !m_dmap[level].empty();
762 template <
class T,
unsigned Dim>
764 return this->finestLevel_m;
768 template <
class T,
unsigned Dim>
770 return this->maxLevel_m;
774 template <
class T,
unsigned Dim>
777 return refRatio_m[level];
781 template <
class T,
unsigned Dim>
784 for (
int n = 0;
n<AMREX_SPACEDIM;
n++)
785 maxval =
std::max(maxval, refRatio_m[level][
n]);
790 template <
class T,
unsigned Dim>
796 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
801 real_box.setLo(d, lowerBound[d] * (1.0 + dh));
802 real_box.setHi(d, upperBound[d] * (1.0 + dh));
805 AmrGeometry_t::ProbDomain(real_box);
809 AmrIntVect_t domain_hi(nGridPoints - 1, nGridPoints - 1, nGridPoints - 1);
810 const AmrBox_t domain(domain_lo, domain_hi);
816 int is_per[AMREX_SPACEDIM];
817 for (
int i = 0; i < AMREX_SPACEDIM; i++)
821 geom.define(domain, &real_box, coord, is_per);
826 ba.maxSize(maxGridSize);
832 this->m_geom.resize(1);
833 this->m_geom[0] = geom;
835 this->m_dmap.resize(1);
836 this->m_dmap[0] = dmap;
838 this->m_ba.resize(1);
841 this->m_nlevels = ba.size();
void clearLevelMask(int lev)
amr::AmrGeometry_t AmrGeometry_t
void buildLevelMask(int lev, const int ncells=1)
AmrIntVect_t refRatio(int level) const
AmrIntVect_t Index(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int level) const
amr::AmrIntArray_t AmrIntArray_t
amrex::BaseFab< int > basefab_t
amr::AmrProcMapContainer_t AmrProcMapContainer_t
Vektor< double, 3 > Vector_t
bool LevelDefined(int level) const
int next_tag(int t, int s=1000)
virtual MPI_Request raw_isend(void *, int, int, int)
void setBoundingBox(double dh)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
std::string::iterator iterator
amrex::FabArray< basefab_t > mask_t
bool EnforcePeriodicWhere(AmrParticleBase< BoxLibLayout< T, Dim > > &prt, const unsigned int ip, int lev_min=0, int lev_max=-1) const
static Communicate * Comm
The base class for all OPAL exceptions.
amr::AmrDomain_t AmrDomain_t
#define P_SPATIAL_TRANSFER_TAG
void locateParticle(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int lev_min, int lev_max, int nGrow) const
void allreduce(const T *input, T *output, int count, Op op)
void update(IpplParticleBase< BoxLibLayout< T, Dim > > &PData, const ParticleAttrib< char > *canSwap=0)
virtual int raw_probe_receive(char *&, int &, int &)
const std::unique_ptr< mask_t > & getLevelMask(int lev) const
amr::AmrIntVect_t AmrIntVect_t
bool Where(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int lev_min=0, int lev_max=-1, int nGrow=0) const
bool PeriodicShift(SingleParticlePos_t R) const
int MaxRefRatio(int level) const
amr::AmrGeomContainer_t AmrGeomContainer_t
amr::AmrProcMap_t AmrProcMap_t
int maxLevel_m
Maximum level allowed.
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
amr::AmrGridContainer_t AmrGridContainer_t
void initBaseBox_m(int nGridPoints, int maxGridSize, double dh=0.04)
void setDomainRatio(const std::vector< double > &ratio)
AmrIntVectContainer_t refRatio_m