OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
BoxLibLayout.hpp
Go to the documentation of this file.
1 #ifndef BoxLibLayout_HPP
2 #define BoxLibLayout_HPP
3 
4 #include "BoxLibLayout.h"
5 
6 #include "Message/Formatter.h"
8 
9 #include <cassert>
10 #include <cmath>
11 
12 template <class T, unsigned Dim>
14 
15 
16 template <class T, unsigned Dim>
18 
19 
20 template<class T, unsigned Dim>
22  : ParticleAmrLayout<T, Dim>(),
23  ParGDB(),
24  refRatio_m(0)
25 {
26  /* FIXME There might be a better solution
27  *
28  *
29  * Figure out the number of grid points in each direction
30  * such that all processes have some data at the beginning
31  *
32  * ( nGridPoints / maxGridSize ) ^3 = max. #procs
33  *
34  */
35  int nProcs = Ippl::getNodes();
36  int maxGridSize = 16;
37 
38  int nGridPoints = std::ceil( std::cbrt( nProcs ) ) * maxGridSize;
39 
40  this->initBaseBox_m(nGridPoints, maxGridSize);
41 }
42 
43 
44 template<class T, unsigned Dim>
46  : ParticleAmrLayout<T, Dim>(),
47  ParGDB(layout_p->m_geom,
48  layout_p->m_dmap,
49  layout_p->m_ba,
50  layout_p->m_rr)
51 {
52  this->maxLevel_m = layout_p->maxLevel_m;
53  refRatio_m.resize(layout_p->m_geom.size()-1);
54  for (int i = 0; i < refRatio_m.size(); ++i)
55  refRatio_m[i] = layout_p->refRatio(i);
56 }
57 
58 
59 template<class T, unsigned Dim>
60 BoxLibLayout<T, Dim>::BoxLibLayout(int nGridPoints, int maxGridSize)
61  : ParticleAmrLayout<T, Dim>(),
62  ParGDB(),
63  refRatio_m(0)
64 {
65  this->initBaseBox_m(nGridPoints, maxGridSize);
66 }
67 
68 
69 template<class T, unsigned Dim>
71  const AmrProcMap_t &dmap,
72  const AmrGrid_t &ba)
73  : ParticleAmrLayout<T, Dim>(),
74  ParGDB(geom, dmap, ba),
75  refRatio_m(0)
76 { }
77 
78 
79 template<class T, unsigned Dim>
81  const AmrProcMapContainer_t &dmap,
82  const AmrGridContainer_t &ba,
83  const AmrIntArray_t &rr)
84  : ParticleAmrLayout<T, Dim>(),
85  ParGDB(geom, dmap, ba, rr),
86  refRatio_m(0)
87 { }
88 
89 
90 template<class T, unsigned Dim>
92 
93  // cubic box
94  int nGridPoints = this->m_geom[0].Domain().length(0);
95  int maxGridSize = this->m_ba[0][0].length(0);
96 
97  this->initBaseBox_m(nGridPoints, maxGridSize, dh);
98 }
99 
100 
101 template <class T, unsigned Dim>
102 void BoxLibLayout<T, Dim>::setDomainRatio(const std::vector<double>& ratio) {
103 
104  static bool isCalled = false;
105 
106  if ( isCalled ) {
107  return;
108  }
109 
110  isCalled = true;
111 
112  if ( ratio.size() != Dim ) {
113  throw OpalException("BoxLibLayout::setDomainRatio() ",
114  "Length " + std::to_string(ratio.size()) +
115  " != " + std::to_string(Dim));
116  }
117 
118  for (unsigned int i = 0; i < Dim; ++i) {
119  if ( ratio[i] <= 0.0 ) {
120  throw OpalException("BoxLibLayout::setDomainRatio() ",
121  "The ratio has to be larger than zero.");
122  }
123 
124  lowerBound[i] *= ratio[i];
125  upperBound[i] *= ratio[i];
126  }
127 }
128 
129 
130 template<class T, unsigned Dim>
132  const ParticleAttrib<char>* canSwap)
133 {
134  /* Exit since we need AmrParticleBase with grids and levels for particles for this layout
135  * if IpplParticleBase is used something went wrong
136  */
137  throw OpalException("BoxLibLayout::update(IpplParticleBase, ParticleAttrib) ",
138  "Wrong update method called.");
139 }
140 
141 
142 // // Function from AMReX adjusted to work with Ippl AmrParticleBase class
143 // // redistribute the particles using BoxLibs ParGDB class to determine where particle should go
144 template<class T, unsigned Dim>
146  int lev_min, int lev_max, bool isRegrid)
147 {
148  // in order to avoid transforms when already done
149  if ( !PData.isForbidTransform() ) {
150  /* we need to update on Amr domain + boosted frame (Lorentz transform,
151  * has to be undone at end of function
152  */
153  PData.domainMapping();
154  }
155 
156  int nGrow = 0;
157 
158  unsigned N = Ippl::getNodes();
159  unsigned myN = Ippl::myNode();
160 
161  int theEffectiveFinestLevel = this->finestLevel();
162  while (!this->LevelDefined(theEffectiveFinestLevel)) {
163  theEffectiveFinestLevel--;
164  }
165 
166  if (lev_max == -1)
167  lev_max = theEffectiveFinestLevel;
168  else if ( lev_max > theEffectiveFinestLevel )
169  lev_max = theEffectiveFinestLevel;
170 
171  //loop trough the particles and assign the grid and level where each particle belongs
172  size_t LocalNum = PData.getLocalNum();
173 
174  auto& LocalNumPerLevel = PData.getLocalNumPerLevel();
175 
176  if ( LocalNum != LocalNumPerLevel.getLocalNumAllLevel() )
177  throw OpalException("BoxLibLayout::update()",
178  "Local #particles disagrees with sum over levels");
179 
180  std::multimap<unsigned, unsigned> p2n; //node ID, particle
181 
182  int *msgsend = new int[N];
183  std::fill(msgsend, msgsend+N, 0);
184  int *msgrecv = new int[N];
185  std::fill(msgrecv, msgrecv+N, 0);
186 
187  unsigned sent = 0;
188  size_t lBegin = LocalNumPerLevel.begin(lev_min);
189  size_t lEnd = LocalNumPerLevel.end(lev_max);
190 
191  /* in the case of regrid we might lose a level
192  * and therefore the level counter is invalidated
193  */
194  if ( isRegrid ) {
195  lBegin = 0;
196  lEnd = LocalNum;
197  }
198 
199 
200  //loop trough particles and assign grid and level to each particle
201  //if particle doesn't belong to this process save the index of the particle to be sent
202  for (unsigned int ip = lBegin; ip < lEnd; ++ip) {
203  // old level
204  const size_t& lold = PData.Level[ip];
205 
206 // /*
207 // * AMReX sets m_grid = -1 and m_lev = -1
208 // */
209 // PData.Level[ip] = -1;
210 // PData.Grid[ip] = -1;
211 
212  //check to which level and grid the particle belongs to
213  locateParticle(PData, ip, lev_min, lev_max, nGrow);
214 
215  // The owner of the particle is the CPU owning the finest grid
216  // in state data that contains the particle.
217  const size_t& lnew = PData.Level[ip];
218 
219  const unsigned int who = ParticleDistributionMap(lnew)[PData.Grid[ip]];
220 
221  --LocalNumPerLevel[lold];
222 
223  if (who != myN) {
224  // we lost the particle to another process
225  msgsend[who] = 1;
226  p2n.insert(std::pair<unsigned, unsigned>(who, ip));
227  sent++;
228  } else {
229  /* if we still own the particle it may have moved to
230  * another level
231  */
232  ++LocalNumPerLevel[lnew];
233  }
234  }
235 
236  //reduce message count so every node knows how many messages to receive
237  MPI_Allreduce(msgsend, msgrecv, N, MPI_INT, MPI_SUM, Ippl::getComm());
238 
240 
241  typename std::multimap<unsigned, unsigned>::iterator i = p2n.begin();
242 
243  Format *format = PData.getFormat();
244 
245  std::vector<MPI_Request> requests;
246  std::vector<MsgBuffer*> buffers;
247 
248  //create a message and send particles to nodes they belong to
249  while (i!=p2n.end())
250  {
251  unsigned cur_destination = i->first;
252 
253  MsgBuffer *msgbuf = new MsgBuffer(format, p2n.count(i->first));
254 
255  for (; i!=p2n.end() && i->first == cur_destination; ++i)
256  {
257  Message msg;
258  PData.putMessage(msg, i->second);
259  PData.destroy(1, i->second);
260  msgbuf->add(&msg);
261  }
262 
263  MPI_Request request = Ippl::Comm->raw_isend(msgbuf->getBuffer(),
264  msgbuf->getSize(),
265  cur_destination, tag);
266 
267  //remember request and buffer so we can delete them later
268  requests.push_back(request);
269  buffers.push_back(msgbuf);
270 
271  }
272 
273  //destroy the particles that are sent to other domains
274  if ( LocalNum < PData.getDestroyNum() )
275  throw OpalException("BoxLibLayout::update()",
276  "Rank " + std::to_string(myN) +
277  " can't destroy more particles than possessed.");
278  else {
279  LocalNum -= PData.getDestroyNum(); // update local num
280  PData.performDestroy();
281  }
282 
283  for (int lev = lev_min; lev <= lev_max; ++lev) {
284  if ( LocalNumPerLevel[lev] < 0 )
285  throw OpalException("BoxLibLayout::update()",
286  "Negative particle level count.");
287  }
288 
289  //receive new particles
290  for (int k = 0; k<msgrecv[myN]; ++k)
291  {
292  int node = Communicate::COMM_ANY_NODE;
293  char *buffer = 0;
294  int bufsize = Ippl::Comm->raw_probe_receive(buffer, node, tag);
295  MsgBuffer recvbuf(format, buffer, bufsize);
296 
297  Message *msg = recvbuf.get();
298  while (msg != 0)
299  {
300  /* pBeginIdx is the start index of the new particle data
301  * pEndIdx is the last index of the new particle data
302  */
303  size_t pBeginIdx = LocalNum;
304 
305  LocalNum += PData.getSingleMessage(*msg);
306 
307  size_t pEndIdx = LocalNum;
308 
309  for (size_t idx = pBeginIdx; idx < pEndIdx; ++idx)
310  ++LocalNumPerLevel[ PData.Level[idx] ];
311 
312  delete msg;
313  msg = recvbuf.get();
314  }
315  }
316 
317  //wait for communication to finish and clean up buffers
318  MPI_Waitall(requests.size(), &(requests[0]), MPI_STATUSES_IGNORE);
319  for (unsigned int j = 0; j<buffers.size(); ++j)
320  {
321  delete buffers[j];
322  }
323 
324  delete[] msgsend;
325  delete[] msgrecv;
326  delete format;
327 
328  // there is extra work to do if there are multipple nodes, to distribute
329  // the particle layout data to all nodes
330  //TODO: do we need info on how many particles are on each node?
331 
332  //save how many total particles we have
333  size_t TotalNum = 0;
334  MPI_Allreduce(&LocalNum, &TotalNum, 1, MPI_INT, MPI_SUM, Ippl::getComm());
335 
336  // update our particle number counts
337  PData.setTotalNum(TotalNum); // set the total atom count
338  PData.setLocalNum(LocalNum); // set the number of local atoms
339 
340  // final check
341  if ( LocalNum != LocalNumPerLevel.getLocalNumAllLevel() )
342  throw OpalException("BoxLibLayout::update()",
343  "Local #particles disagrees with sum over levels");
344 
345  if ( !PData.isForbidTransform() ) {
346  // undo domain transformation + undo Lorentz transform
347  PData.domainMapping(true);
348  }
349 }
350 
351 
352 // Function from AMReX adjusted to work with Ippl AmrParticleBase class
353 //get the cell where particle is located - uses AmrParticleBase object and particle id
354 template <class T, unsigned Dim>
357  const unsigned int ip,
358  int lev) const
359 {
360  return Index(p.R[ip], lev);
361 }
362 
363 //get the cell where particle is located - uses the particle position vector R
364 template <class T, unsigned Dim>
367  int lev) const
368 {
369  AmrIntVect_t iv;
370  const AmrGeometry_t& geom = Geom(lev);
371 
372  D_TERM(iv[0]=floor((R[0]-geom.ProbLo(0))/geom.CellSize(0));,
373  iv[1]=floor((R[1]-geom.ProbLo(1))/geom.CellSize(1));,
374  iv[2]=floor((R[2]-geom.ProbLo(2))/geom.CellSize(2)););
375 
376  iv += geom.Domain().smallEnd();
377 
378  return iv;
379 }
380 
381 
382 template <class T, unsigned Dim>
383 void BoxLibLayout<T, Dim>::buildLevelMask(int lev, const int ncells) {
384  int covered = 0;
385  int notcovered = 1;
386  int physbnd = 1;
387  int interior = 0;
388 
389  if ( lev >= (int)masks_m.size() )
390  masks_m.resize(lev + 1);
391 
392  masks_m[lev].reset(new mask_t(ParticleBoxArray(lev),
393  ParticleDistributionMap(lev), 1, 1));
394 
395  masks_m[lev]->setVal(1, 1);
396 
397  mask_t tmp_mask(ParticleBoxArray(lev),
398  ParticleDistributionMap(lev),
399  1, ncells);
400 
401  tmp_mask.setVal(0, ncells);
402 
403  tmp_mask.BuildMask(Geom(lev).Domain(), Geom(lev).periodicity(),
404  covered, notcovered, physbnd, interior);
405 
406  tmp_mask.FillBoundary(Geom(lev).periodicity());
407 
408  for (amrex::MFIter mfi(tmp_mask); mfi.isValid(); ++mfi) {
409  const AmrBox_t& bx = mfi.validbox();
410  const int* lo = bx.loVect();
411  const int* hi = bx.hiVect();
412 
413  basefab_t& mfab = (*masks_m[lev])[mfi];
414  const basefab_t& fab = tmp_mask[mfi];
415 
416  for (int i = lo[0]; i <= hi[0]; ++i) {
417  for (int j = lo[1]; j <= hi[1]; ++j) {
418  for (int k = lo[2]; k <= hi[2]; ++k) {
419  int total = 0;
420 
421  for (int ii = i - ncells; ii <= i + ncells; ++ii) {
422  for (int jj = j - ncells; jj <= j + ncells; ++jj) {
423  for (int kk = k - ncells; kk <= k + ncells; ++kk) {
424  AmrIntVect_t iv(ii, jj, kk);
425  total += fab(iv);
426  }
427  }
428  }
429 
430  AmrIntVect_t iv(i, j, k);
431  if (total == 0) {
432  mfab(iv) = 0;
433  }
434  }
435  }
436  }
437  }
438 
439  masks_m[lev]->FillBoundary(Geom(lev).periodicity());
440 }
441 
442 
443 template <class T, unsigned Dim>
445  assert(lev < (int)masks_m.size());
446  masks_m[lev].reset(nullptr);
447 }
448 
449 
450 template <class T, unsigned Dim>
451 const std::unique_ptr<typename BoxLibLayout<T, Dim>::mask_t>&
453  if ( lev >= (int)masks_m.size() ) {
454  throw OpalException("BoxLibLayout::getLevelMask()",
455  "Unable to access level " + std::to_string(lev) + ".");
456  }
457  return masks_m[lev];
458 }
459 
460 
461 // template <class T, unsigned Dim>
462 // int BoxLibLayout<T, Dim>::getTileIndex(const AmrIntVect_t& iv, const Box& box, Box& tbx) {
463 // if (do_tiling == false) {
464 // tbx = box;
465 // return 0;
466 // } else {
467 // //
468 // // This function must be consistent with FabArrayBase::buildTileArray function!!!
469 // //
470 // auto tiling_1d = [](int i, int lo, int hi, int tilesize,
471 // int& ntile, int& tileidx, int& tlo, int& thi) {
472 // int ncells = hi-lo+1;
473 // ntile = std::max(ncells/tilesize, 1);
474 // int ts_right = ncells/ntile;
475 // int ts_left = ts_right+1;
476 // int nleft = ncells - ntile*ts_right;
477 // int ii = i - lo;
478 // int nbndry = nleft*ts_left;
479 // if (ii < nbndry) {
480 // tileidx = ii / ts_left; // tiles on the left of nbndry have size of ts_left
481 // tlo = lo + tileidx * ts_left;
482 // thi = tlo + ts_left - 1;
483 // } else {
484 // tileidx = nleft + (ii-nbndry) / ts_right; // tiles on the right: ts_right
485 // tlo = lo + tileidx * ts_right + nleft;
486 // thi = tlo + ts_right - 1;
487 // }
488 // };
489 // const AmrIntVect_t& small = box.smallEnd();
490 // const AmrIntVect_t& big = box.bigEnd();
491 // AmrIntVect_t ntiles, ivIndex, tilelo, tilehi;
492 //
493 // D_TERM(int iv0 = std::min(std::max(iv[0], small[0]), big[0]);,
494 // int iv1 = std::min(std::max(iv[1], small[1]), big[1]);,
495 // int iv2 = std::min(std::max(iv[2], small[2]), big[2]););
496 //
497 // D_TERM(tiling_1d(iv0, small[0], big[0], tile_size[0], ntiles[0], ivIndex[0], tilelo[0], tilehi[0]);,
498 // tiling_1d(iv1, small[1], big[1], tile_size[1], ntiles[1], ivIndex[1], tilelo[1], tilehi[1]);,
499 // tiling_1d(iv2, small[2], big[2], tile_size[2], ntiles[2], ivIndex[2], tilelo[2], tilehi[2]););
500 //
501 // tbx = Box(tilelo, tilehi);
502 //
503 // return D_TERM(ivIndex[0], + ntiles[0]*ivIndex[1], + ntiles[0]*ntiles[1]*ivIndex[2]);
504 // }
505 // }
506 
507 
508 //sets the grid and level where particle belongs - returns false if particle is outside the domain
509 template <class T, unsigned Dim>
511  const unsigned int ip,
512  int lev_min,
513  int lev_max,
514  int nGrow) const
515 {
516 
517  if (lev_max == -1)
518  lev_max = finestLevel();
519 
520  BL_ASSERT(lev_max <= finestLevel());
521 
522  BL_ASSERT(nGrow == 0 || (nGrow >= 0 && lev_min == lev_max));
523 
524  std::vector< std::pair<int, AmrBox_t> > isects;
525 
526  for (int lev = lev_max; lev >= lev_min; lev--)
527  {
528  const AmrIntVect_t& iv = Index(p, ip, lev);
529  const AmrGrid_t& ba = ParticleBoxArray(lev);
530  BL_ASSERT(ba.ixType().cellCentered());
531 
532  if (lev == (int)p.Level[ip]) {
533  // The fact that we are here means this particle does not belong to any finer grids.
534  if (0 <= p.Grid[ip] && p.Grid[ip] < ba.size())
535  {
536  const AmrBox_t& bx = ba.getCellCenteredBox(p.Grid[ip]);
537  const AmrBox_t& gbx = amrex::grow(bx,nGrow);
538  if (gbx.contains(iv))
539  {
540 // if (bx != pld.m_gridbox || !pld.m_tilebox.contains(iv)) {
541 // pld.m_tile = getTileIndex(iv, bx, pld.m_tilebox);
542 // pld.m_gridbox = bx;
543 // }
544  return true;
545  }
546  }
547  }
548 
549  ba.intersections(AmrBox_t(iv, iv), isects, true, nGrow);
550 
551  if (!isects.empty())
552  {
553  p.Level[ip] = lev;
554  p.Grid[ip] = isects[0].first;
555 
556  return true;
557  }
558  }
559  return false;
560 }
561 
562 
563 //Function from AMReX adjusted to work with Ippl AmrParticleBase class
564 //Checks/sets whether the particle has crossed a periodic boundary in such a way
565 //that it is on levels lev_min and higher.
566 template <class T, unsigned Dim>
568  const unsigned int ip,
569  int lev_min,
570  int lev_max) const
571 {
572  if (!Geom(0).isAnyPeriodic()) return false;
573 
574  if (lev_max == -1)
575  lev_max = finestLevel();
576 
577  BL_ASSERT(lev_max <= finestLevel());
578  //
579  // Create a copy "dummy" particle to check for periodic outs.
580  //
581  SingleParticlePos_t R = p.R[ip];
582 
583  if (PeriodicShift(R))
584  {
585  std::vector< std::pair<int, AmrBox_t> > isects;
586 
587  for (int lev = lev_max; lev >= lev_min; lev--)
588  {
589  const AmrIntVect_t& iv = Index(R, lev);
590  const AmrGrid_t& ba = ParticleBoxArray(lev);
591 
592  ba.intersections(AmrBox_t(iv,iv),isects,true,0);
593 
594  if (!isects.empty())
595  {
596  D_TERM(p.R[ip][0] = R[0];,
597  p.R[ip][1] = R[1];,
598  p.R[ip][2] = R[2];);
599 
600  p.Level[ip] = lev;
601  p.Grid[ip] = isects[0].first;
602 
603  return true;
604  }
605  }
606  }
607 
608  return false;
609 }
610 
611 
612 // Function from AMReX adjusted to work with Ippl AmrParticleBase class
613 // Returns true if the particle was shifted.
614 template <class T, unsigned Dim>
616 {
617  //
618  // This routine should only be called when Where() returns false.
619  //
620  //
621  // We'll use level 0 stuff since ProbLo/ProbHi are the same for every level.
622  //
623  const AmrGeometry_t& geom = Geom(0);
624  const AmrBox_t& dmn = geom.Domain();
625  const AmrIntVect_t& iv = Index(R, 0);
626  bool shifted = false;
627 
628  for (int i = 0; i < AMREX_SPACEDIM; i++)
629  {
630  if (!geom.isPeriodic(i)) continue;
631 
632  if (iv[i] > dmn.bigEnd(i))
633  {
634  if (R[i] == geom.ProbHi(i))
635  //
636  // Don't let particles lie exactly on the domain face.
637  // Force the particle to be outside the domain so the
638  // periodic shift will bring it back inside.
639  //
640  R[i] += .125*geom.CellSize(i);
641 
642  R[i] -= geom.ProbLength(i);
643 
644  if (R[i] <= geom.ProbLo(i))
645  //
646  // This can happen due to precision issues.
647  //
648  R[i] += .125*geom.CellSize(i);
649 
650  BL_ASSERT(R[i] >= geom.ProbLo(i));
651 
652  shifted = true;
653  }
654  else if (iv[i] < dmn.smallEnd(i))
655  {
656  if (R[i] == geom.ProbLo(i))
657  //
658  // Don't let particles lie exactly on the domain face.
659  // Force the particle to be outside the domain so the
660  // periodic shift will bring it back inside.
661  //
662  R[i] -= .125*geom.CellSize(i);
663 
664  R[i] += geom.ProbLength(i);
665 
666  if (R[i] >= geom.ProbHi(i))
667  //
668  // This can happen due to precision issues.
669  //
670  R[i] -= .125*geom.CellSize(i);
671 
672  BL_ASSERT(R[i] <= geom.ProbHi(i));
673 
674  shifted = true;
675  }
676  }
677  //
678  // The particle may still be outside the domain in the case
679  // where we aren't periodic on the face out which it travelled.
680  //
681  return shifted;
682 }
683 
684 
685 template <class T, unsigned Dim>
688  const unsigned int ip,
689  int lev_min, int lev_max, int nGrow) const
690 {
691  bool outside = D_TERM( p.R[ip](0) < AmrGeometry_t::ProbLo(0)
692  || p.R[ip](0) >= AmrGeometry_t::ProbHi(0),
693  || p.R[ip](1) < AmrGeometry_t::ProbLo(1)
694  || p.R[ip](1) >= AmrGeometry_t::ProbHi(1),
695  || p.R[ip](2) < AmrGeometry_t::ProbLo(2)
696  || p.R[ip](2) >= AmrGeometry_t::ProbHi(2));
697 
698  bool success = false;
699 
700  if (outside)
701  {
702  // Note that EnforcePeriodicWhere may shift the particle if it is successful.
703  success = EnforcePeriodicWhere(p, ip, lev_min, lev_max);
704  if (!success && lev_min == 0)
705  {
706  // The particle has left the domain; invalidate it.
707  p.destroy(1, ip);
708  success = true;
709 
710  /* We shouldn't lose particles since they are mapped to be within
711  * [-1, 1]^3.
712  */
713  throw OpalException("BoxLibLayout::locateParticle()",
714  "We're losing particles although we shouldn't");
715 
716  }
717  }
718  else
719  {
720  success = Where(p, ip, lev_min, lev_max);
721  }
722 
723  if (!success)
724  {
725  success = (nGrow > 0) && Where(p, ip, lev_min, lev_min, nGrow);
726  }
727 
728  if (!success)
729  {
730  std::stringstream ss;
731  ss << "Invalid particle with ID " << ip << " at position " << p.R[ip] << ".";
732  throw OpalException("BoxLibLayout::locateParticle()", ss.str());
733  }
734 }
735 
736 
737 // overwritten functions
738 template <class T, unsigned Dim>
739 bool BoxLibLayout<T, Dim>::LevelDefined (int level) const {
740  return level <= this->maxLevel_m && !m_ba[level].empty() && !m_dmap[level].empty();
741 }
742 
743 
744 template <class T, unsigned Dim>
746  return this->finestLevel_m;
747 }
748 
749 
750 template <class T, unsigned Dim>
752  return this->maxLevel_m;
753 }
754 
755 
756 template <class T, unsigned Dim>
759 {
760  return refRatio_m[level];
761 }
762 
763 
764 template <class T, unsigned Dim>
765 int BoxLibLayout<T, Dim>::MaxRefRatio (int level) const {
766  int maxval = 0;
767  for (int n = 0; n<AMREX_SPACEDIM; n++)
768  maxval = std::max(maxval, refRatio_m[level][n]);
769  return maxval;
770 }
771 
772 
773 template <class T, unsigned Dim>
775  int maxGridSize,
776  double dh)
777 {
778  // physical box (in meters)
779  AmrDomain_t real_box;
780  for (int d = 0; d < AMREX_SPACEDIM; ++d) {
781 
782  assert(lowerBound[d] < 0);
783  assert(upperBound[d] > 0);
784 
785  real_box.setLo(d, lowerBound[d] * (1.0 + dh));
786  real_box.setHi(d, upperBound[d] * (1.0 + dh));
787  }
788 
789  AmrGeometry_t::ProbDomain(real_box);
790 
791  // define underlying box for physical domain
792  AmrIntVect_t domain_lo(0 , 0, 0);
793  AmrIntVect_t domain_hi(nGridPoints - 1, nGridPoints - 1, nGridPoints - 1);
794  const AmrBox_t domain(domain_lo, domain_hi);
795 
796  // use Cartesian coordinates
797  int coord = 0;
798 
799  // Dirichlet boundary conditions
800  int is_per[AMREX_SPACEDIM];
801  for (int i = 0; i < AMREX_SPACEDIM; i++)
802  is_per[i] = 0;
803 
804  AmrGeometry_t geom;
805  geom.define(domain, &real_box, coord, is_per);
806 
807  AmrGrid_t ba;
808  ba.define(domain);
809  // break the BoxArrays at both levels into max_grid_size^3 boxes
810  ba.maxSize(maxGridSize);
811 
812  AmrProcMap_t dmap;
813  dmap.define(ba, Ippl::getNodes());
814 
815  // set protected ParGDB member variables
816  this->m_geom.resize(1);
817  this->m_geom[0] = geom;
818 
819  this->m_dmap.resize(1);
820  this->m_dmap[0] = dmap;
821 
822  this->m_ba.resize(1);
823  this->m_ba[0] = ba;
824 
825  this->m_nlevels = ba.size();
826 }
827 
828 #endif
static int getNodes()
Definition: IpplInfo.cpp:773
void update(IpplParticleBase< BoxLibLayout< T, Dim > > &PData, const ParticleAttrib< char > *canSwap=0)
AmrIntVect_t refRatio(int level) const
int getSize()
Definition: Formatter.h:81
const std::unique_ptr< mask_t > & getLevelMask(int lev) const
Definition: TSVMeta.h:24
void locateParticle(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int lev_min, int lev_max, int nGrow) const
Definition: rbendmap.h:8
amrex::BaseFab< int > basefab_t
Definition: BoxLibLayout.h:60
void * getBuffer()
Definition: Formatter.h:85
amr::AmrIntVect_t AmrIntVect_t
Definition: BoxLibLayout.h:53
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
The base class for all OPAL exceptions.
Definition: OpalException.h:28
amr::AmrGeomContainer_t AmrGeomContainer_t
Definition: BoxLibLayout.h:50
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
Definition: PETE.h:811
virtual MPI_Request raw_isend(void *, int, int, int)
Definition: Communicate.h:196
virtual int raw_probe_receive(char *&, int &, int &)
Definition: Communicate.h:208
static int myNode()
Definition: IpplInfo.cpp:794
amr::AmrProcMapContainer_t AmrProcMapContainer_t
Definition: BoxLibLayout.h:52
int next_tag(int t, int s=1000)
Definition: TagMaker.h:43
amrex::FabArray< basefab_t > mask_t
Definition: BoxLibLayout.h:61
int finestLevel() const
amr::AmrDomain_t AmrDomain_t
Definition: BoxLibLayout.h:56
Definition: Index.h:236
amr::AmrGridContainer_t AmrGridContainer_t
Definition: BoxLibLayout.h:51
#define P_LAYOUT_CYCLE
Definition: Tags.h:86
void setDomainRatio(const std::vector< double > &ratio)
amr::AmrGrid_t AmrGrid_t
Definition: BoxLibLayout.h:48
amrex::Box AmrBox_t
Definition: AmrDefs.h:30
bool Where(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int lev_min=0, int lev_max=-1, int nGrow=0) const
Message * get()
Definition: Formatter.cpp:76
int maxLevel() const
amr::AmrBox_t AmrBox_t
Definition: BoxLibLayout.h:57
bool EnforcePeriodicWhere(AmrParticleBase< BoxLibLayout< T, Dim > > &prt, const unsigned int ip, int lev_min=0, int lev_max=-1) const
int MaxRefRatio(int level) const
void clearLevelMask(int lev)
AmrIntVect_t Index(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int level) const
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
amr::AmrGeometry_t AmrGeometry_t
Definition: BoxLibLayout.h:49
static MPI_Comm getComm()
Definition: IpplInfo.h:178
void buildLevelMask(int lev, const int ncells=1)
int maxLevel_m
Maximum level allowed.
bool LevelDefined(int level) const
amr::AmrProcMap_t AmrProcMap_t
Definition: BoxLibLayout.h:47
bool PeriodicShift(SingleParticlePos_t R) const
amr::AmrIntArray_t AmrIntArray_t
Definition: BoxLibLayout.h:55
void initBaseBox_m(int nGridPoints, int maxGridSize, double dh=0.04)
void setBoundingBox(double dh)
std::string::iterator iterator
Definition: MSLang.h:16
const unsigned Dim
AmrIntVectContainer_t refRatio_m
Definition: BoxLibLayout.h:368
static Communicate * Comm
Definition: IpplInfo.h:93
#define P_SPATIAL_TRANSFER_TAG
Definition: Tags.h:82
bool add(Message *)
Definition: Formatter.cpp:49
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:816