36#ifndef BoxLibLayout_HPP
37#define BoxLibLayout_HPP
48template <
class T,
unsigned Dim>
52template <
class T,
unsigned Dim>
56template<
class T,
unsigned Dim>
74 int nGridPoints =
std::ceil( std::cbrt( nProcs ) ) * maxGridSize;
80template<
class T,
unsigned Dim>
83 ParGDB(layout_p->m_geom,
95template<
class T,
unsigned Dim>
105template<
class T,
unsigned Dim>
110 ParGDB(geom, dmap, ba),
115template<
class T,
unsigned Dim>
121 ParGDB(geom, dmap, ba, rr),
126template<
class T,
unsigned Dim>
130 int nGridPoints = this->m_geom[0].Domain().length(0);
131 int maxGridSize = this->m_ba[0][0].length(0);
133 this->initBaseBox_m(nGridPoints, maxGridSize, dh);
137template <
class T,
unsigned Dim>
140 static bool isCalled =
false;
148 if ( ratio.size() !=
Dim ) {
150 "Length " + std::to_string(ratio.size()) +
151 " != " + std::to_string(
Dim));
154 for (
unsigned int i = 0; i <
Dim; ++i) {
155 if ( ratio[i] <= 0.0 ) {
157 "The ratio has to be larger than zero.");
160 lowerBound[i] *= ratio[i];
161 upperBound[i] *= ratio[i];
166template<
class T,
unsigned Dim>
173 throw OpalException(
"BoxLibLayout::update(IpplParticleBase, ParticleAttrib) ",
174 "Wrong update method called.");
180template<
class T,
unsigned Dim>
182 int lev_min,
int lev_max,
bool isRegrid)
185 if ( !PData.isForbidTransform() ) {
189 PData.domainMapping();
197 int theEffectiveFinestLevel = this->finestLevel();
198 while (!this->LevelDefined(theEffectiveFinestLevel)) {
199 theEffectiveFinestLevel--;
203 lev_max = theEffectiveFinestLevel;
204 else if ( lev_max > theEffectiveFinestLevel )
205 lev_max = theEffectiveFinestLevel;
208 size_t LocalNum = PData.getLocalNum();
210 auto& LocalNumPerLevel = PData.getLocalNumPerLevel();
212 if ( LocalNum != LocalNumPerLevel.getLocalNumAllLevel() )
214 "Local #particles disagrees with sum over levels");
216 std::multimap<unsigned, unsigned> p2n;
218 std::vector<int> msgsend(N);
219 std::vector<int> msgrecv(N);
222 size_t lBegin = LocalNumPerLevel.begin(lev_min);
223 size_t lEnd = LocalNumPerLevel.end(lev_max);
236 for (
unsigned int ip = lBegin; ip < lEnd; ++ip) {
238 const size_t& lold = PData.Level[ip];
247 locateParticle(PData, ip, lev_min, lev_max, nGrow);
251 const size_t& lnew = PData.Level[ip];
253 const unsigned int who = ParticleDistributionMap(lnew)[PData.Grid[ip]];
255 --LocalNumPerLevel[lold];
260 p2n.insert(std::pair<unsigned, unsigned>(who, ip));
266 ++LocalNumPerLevel[lnew];
271 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
277 Format *format = PData.getFormat();
279 std::vector<MPI_Request> requests;
280 std::vector<MsgBuffer*> buffers;
285 unsigned cur_destination = i->first;
289 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.");
324 for (
int k = 0; k<msgrecv[myN]; ++k)
329 MsgBuffer recvbuf(format, buffer, bufsize);
337 size_t pBeginIdx = LocalNum;
339 LocalNum += PData.getSingleMessage(*msg);
341 size_t pEndIdx = LocalNum;
343 for (
size_t idx = pBeginIdx; idx < pEndIdx; ++idx)
344 ++LocalNumPerLevel[ PData.Level[idx] ];
352 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
353 MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
354 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);
387template <
class T,
unsigned Dim>
390 const unsigned int ip,
393 return Index(p.R[ip], lev);
397template <
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();
415template <
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());
476template <
class T,
unsigned Dim>
478 PAssert(lev < (
int)masks_m.size());
479 masks_m[lev].reset(
nullptr);
483template <
class T,
unsigned Dim>
484const 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) +
".");
542template <
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())
569 const AmrBox_t& bx = ba.getCellCenteredBox(p.Grid[ip]);
570 const AmrBox_t& gbx = amrex::grow(bx,nGrow);
571 if (gbx.contains(iv))
582 ba.intersections(
AmrBox_t(iv, iv), isects,
true, nGrow);
587 p.Grid[ip] = isects[0].first;
599template <
class T,
unsigned Dim>
601 const unsigned int ip,
605 if (!Geom(0).isAnyPeriodic())
return false;
608 lev_max = finestLevel();
610 PAssert(lev_max <= finestLevel());
616 if (PeriodicShift(
R))
618 std::vector< std::pair<int, AmrBox_t> > isects;
620 for (
int lev = lev_max; lev >= lev_min; lev--)
623 const AmrGrid_t& ba = ParticleBoxArray(lev);
625 ba.intersections(
AmrBox_t(iv,iv),isects,
true,0);
629 D_TERM(p.R[ip][0] =
R[0];,
634 p.Grid[ip] = isects[0].first;
647template <
class T,
unsigned Dim>
657 const AmrBox_t& dmn = geom.Domain();
659 bool shifted =
false;
661 for (
int i = 0; i < AMREX_SPACEDIM; i++)
663 if (!geom.isPeriodic(i))
continue;
665 if (iv[i] > dmn.bigEnd(i))
667 if (
R[i] == geom.ProbHi(i))
673 R[i] += .125*geom.CellSize(i);
675 R[i] -= geom.ProbLength(i);
677 if (
R[i] <= geom.ProbLo(i))
681 R[i] += .125*geom.CellSize(i);
687 else if (iv[i] < dmn.smallEnd(i))
689 if (
R[i] == geom.ProbLo(i))
695 R[i] -= .125*geom.CellSize(i);
697 R[i] += geom.ProbLength(i);
699 if (
R[i] >= geom.ProbHi(i))
703 R[i] -= .125*geom.CellSize(i);
718template <
class T,
unsigned Dim>
721 const unsigned int ip,
722 int lev_min,
int lev_max,
int nGrow)
const
724 bool outside = D_TERM( p.R[ip](0) < AmrGeometry_t::ProbLo(0)
725 || p.R[ip](0) >= AmrGeometry_t::ProbHi(0),
726 || p.R[ip](1) < AmrGeometry_t::ProbLo(1)
727 || p.R[ip](1) >= AmrGeometry_t::ProbHi(1),
728 || p.R[ip](2) < AmrGeometry_t::ProbLo(2)
729 || p.R[ip](2) >= AmrGeometry_t::ProbHi(2));
731 bool success =
false;
736 success = EnforcePeriodicWhere(p, ip, lev_min, lev_max);
737 if (!success && lev_min == 0)
747 "We're losing particles although we shouldn't");
753 success = Where(p, ip, lev_min, lev_max);
758 success = (nGrow > 0) && Where(p, ip, lev_min, lev_min, nGrow);
763 std::stringstream ss;
764 ss <<
"Invalid particle with ID " << ip <<
" at position " << p.R[ip] <<
".";
765 throw OpalException(
"BoxLibLayout::locateParticle()", ss.str());
771template <
class T,
unsigned Dim>
773 return level <= this->maxLevel_m && !m_ba[level].empty() && !m_dmap[level].empty();
777template <
class T,
unsigned Dim>
779 return this->finestLevel_m;
783template <
class T,
unsigned Dim>
785 return this->maxLevel_m;
789template <
class T,
unsigned Dim>
793 return refRatio_m[level];
797template <
class T,
unsigned Dim>
800 for (
int n = 0;
n<AMREX_SPACEDIM;
n++)
801 maxval =
std::max(maxval, refRatio_m[level][
n]);
806template <
class T,
unsigned Dim>
813 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
818 real_box.setLo(d, lowerBound[d] * (1.0 + dh));
819 real_box.setHi(d, upperBound[d] * (1.0 + dh));
822 AmrGeometry_t::ProbDomain(real_box);
826 AmrIntVect_t domain_hi(nGridPoints - 1, nGridPoints - 1, nGridPoints - 1);
827 const AmrBox_t domain(domain_lo, domain_hi);
833 int is_per[AMREX_SPACEDIM];
834 for (
int i = 0; i < AMREX_SPACEDIM; i++)
838 geom.define(domain, &real_box, coord, is_per);
843 ba.maxSize(maxGridSize);
849 this->m_geom.resize(1);
850 this->m_geom[0] = geom;
852 this->m_dmap.resize(1);
853 this->m_dmap[0] = dmap;
855 this->m_ba.resize(1);
858 this->m_nlevels = ba.size();
void allreduce(const T *input, T *output, int count, Op op)
#define P_SPATIAL_TRANSFER_TAG
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
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)
std::string::iterator iterator
void setBoundingBox(double dh)
amr::AmrProcMapContainer_t AmrProcMapContainer_t
amr::AmrDomain_t AmrDomain_t
const std::unique_ptr< mask_t > & getLevelMask(int lev) const
void setDomainRatio(const std::vector< double > &ratio)
void locateParticle(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int lev_min, int lev_max, int nGrow) const
AmrIntVectContainer_t refRatio_m
void buildLevelMask(int lev, const int ncells=1)
void initBaseBox_m(int nGridPoints, int maxGridSize, double dh=0.04)
bool LevelDefined(int level) const
void clearLevelMask(int lev)
amr::AmrIntVect_t AmrIntVect_t
amr::AmrIntArray_t AmrIntArray_t
amr::AmrGeometry_t AmrGeometry_t
amrex::BaseFab< int > basefab_t
amrex::FabArray< basefab_t > mask_t
amr::AmrGeomContainer_t AmrGeomContainer_t
bool PeriodicShift(SingleParticlePos_t R) const
void update(IpplParticleBase< BoxLibLayout< T, Dim > > &PData, const ParticleAttrib< char > *canSwap=0)
amr::AmrGridContainer_t AmrGridContainer_t
bool EnforcePeriodicWhere(AmrParticleBase< BoxLibLayout< T, Dim > > &prt, const unsigned int ip, int lev_min=0, int lev_max=-1) const
AmrIntVect_t Index(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int level) const
amr::AmrProcMap_t AmrProcMap_t
int MaxRefRatio(int level) const
AmrIntVect_t refRatio(int level) const
bool Where(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int lev_min=0, int lev_max=-1, int nGrow=0) const
The base class for all OPAL exceptions.
int maxLevel_m
Maximum level allowed.
virtual MPI_Request raw_isend(void *, int, int, int)
virtual int raw_probe_receive(char *&, int &, int &)
int next_tag(int t, int s=1000)
static Communicate * Comm
Vektor< double, 3 > Vector_t