OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
AmrBoxLib.cpp
Go to the documentation of this file.
1 //
2 // Class AmrBoxLib
3 // Concrete AMR object. It is based on the AMReX library
4 // (cf. https://amrex-codes.github.io/ or https://ccse.lbl.gov/AMReX/).
5 // AMReX is the successor of BoxLib. This class represents the interface
6 // to AMReX and the AMR framework in OPAL. It implements the functions of
7 // the AmrObject class.
8 //
9 // Copyright (c) 2016 - 2020, Matthias Frey, Paul Scherrer Institut, Villigen PSI, Switzerland
10 // All rights reserved
11 //
12 // Implemented as part of the PhD thesis
13 // "Precise Simulations of Multibunches in High Intensity Cyclotrons"
14 //
15 // This file is part of OPAL.
16 //
17 // OPAL is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
24 //
25 #include "AmrBoxLib.h"
26 
28 #include "Structure/FieldSolver.h"
29 #include "Solvers/PoissonSolver.h"
30 #include "Utility/PAssert.h"
31 
32 #include "Amr/AmrYtWriter.h"
33 
34 #include <AMReX_MultiFabUtil.H>
35 
36 #include <AMReX_ParmParse.H> // used in initialize function
37 #include <AMReX_BCUtil.H>
38 
39 #include <map>
40 
41 extern Inform* gmsg;
42 
43 
45  const AmrIntArray_t& nGridPts,
46  int maxLevel,
47  AmrPartBunch* bunch_p)
48  : AmrObject()
49  , amrex::AmrMesh(&domain, maxLevel, nGridPts, 0 /* cartesian */)
50  , bunch_mp(bunch_p)
51  , layout_mp(static_cast<AmrLayout_t*>(&bunch_p->getLayout()))
52  , rho_m(maxLevel + 1)
53  , phi_m(maxLevel + 1)
54  , efield_m(maxLevel + 1)
55  , meshScaling_m(Vector_t(1.0, 1.0, 1.0))
56  , isFirstTagging_m(maxLevel + 1, true)
57  , isPoissonSolved_m(false)
58 {
59  /*
60  * The layout needs to know how many levels we can make.
61  */
63 
64  initBaseLevel_m(nGridPts);
65 
66  // set mesh spacing of bunch
67  updateMesh();
68 }
69 
70 
71 std::unique_ptr<AmrBoxLib> AmrBoxLib::create(const AmrInfo& info,
72  AmrPartBunch* bunch_p)
73 {
74  /* The bunch is initialized first with a Geometry,
75  * BoxArray and DistributionMapping on
76  * the base level (level = 0). Thus, we take the domain specified there in
77  * order to create the Amr object.
78  */
79  AmrLayout_t* layout_p = static_cast<AmrLayout_t*>(&bunch_p->getLayout());
80  AmrDomain_t domain = layout_p->Geom(0).ProbDomain();
81 
82  AmrIntArray_t nGridPts = {
83  info.grid[0],
84  info.grid[1],
85  info.grid[2]
86  };
87 
88  int maxlevel = info.maxlevel;
89 
90  /*
91  * further attributes are given by the BoxLib's ParmParse class.
92  */
93  initParmParse_m(info, layout_p);
94 
95  return std::unique_ptr<AmrBoxLib>(new AmrBoxLib(domain,
96  nGridPts,
97  maxlevel,
98  bunch_p
99  )
100  );
101 }
102 
103 
104 void AmrBoxLib::regrid(double time) {
106 
107  *gmsg << "* Start regriding:" << endl
108  << "* Old finest level: "
109  << finest_level << endl;
110 
111  this->preRegrid_m();
112 
113  /* ATTENTION: The bunch might be updated during
114  * the regrid process!
115  * We regrid from base level 0 up to the finest level.
116  */
117  int old_finest = finest_level;
118 
119  int lev_top = std::min(finest_level, max_level - 1);
120  for (int i = 0; i <= lev_top; ++i) {
121  this->doRegrid_m(i, time);
122  lev_top = std::min(finest_level, max_level - 1);
123  }
124 
125  this->postRegrid_m(old_finest);
126 
127  *gmsg << "* New finest level: "
128  << finest_level << endl
129  << "* Finished regriding" << endl;
130 
132 }
133 
134 
135 void AmrBoxLib::getGridStatistics(std::map<int, long>& gridPtsPerCore,
136  std::vector<int>& gridsPerLevel) const
137 {
138  typedef std::vector<int> container_t;
139 
140  gridPtsPerCore.clear();
141  gridsPerLevel.clear();
142 
143  gridsPerLevel.resize(max_level + 1);
144 
145  for (int lev = 0; lev <= finest_level; ++lev) {
146  /* container index: box
147  * container value: cores that owns box
148  */
149  const container_t& pmap = this->dmap[lev].ProcessorMap();
150  const AmrGrid_t& ba = this->grids[lev];
151 
152  gridsPerLevel[lev] = pmap.size();
153 
154  // iterate over all boxes
155  for (unsigned int i = 0; i < ba.size(); ++i) {
156  gridPtsPerCore[pmap[i]] += ba[i].numPts();
157  }
158  }
159 }
160 
161 
163  if ( bunch_mp->getNumBunch() > 1 && !refined_m ) {
164  *gmsg << "* Initialization of all levels" << endl;
165 
167 
168  /* we do an explicit domain mapping of the particles and then
169  * forbid it during the regrid process, this way it's only
170  * executed ones --> saves computation
171  */
172  bool isForbidTransform = amrpbase_p->isForbidTransform();
173 
174  if ( !isForbidTransform ) {
175  amrpbase_p->domainMapping();
176  amrpbase_p->setForbidTransform(true);
177  }
178 
179  if ( max_level > 0 ) {
180  this->regrid(bunch_mp->getT() * 1.0e9 /*time [ns] */);
181  }
182 
183  if ( !isForbidTransform ) {
184  amrpbase_p->setForbidTransform(false);
185  // map particles back
186  amrpbase_p->domainMapping(true);
187  }
188 
189  *gmsg << "* Initialization done." << endl;
190 
191  refined_m = true;
192  }
193 }
194 
195 
197  Vector_t maxE = Vector_t(0, 0, 0), minE = Vector_t(0, 0, 0);
198  /* check for maximum / minimum values over all levels
199  * and all components, i.e. Ex, Ey, Ez
200  */
201  for (unsigned int lev = 0; lev < efield_m.size(); ++lev) {
202  for (std::size_t i = 0; i < bunch_mp->Dimension; ++i) {
203  /* calls:
204  * - max(comp, nghost (to search), local)
205  * - min(cmop, nghost, local)
206  */
207  double max = efield_m[lev][i]->max(0, false);
208  maxE[i] = (maxE[i] < max) ? max : maxE[i];
209 
210  double min = efield_m[lev][i]->min(0, false);
211  minE[i] = (minE[i] > min) ? min : minE[i];
212  }
213  }
214 
215  return VectorPair_t(maxE, minE);
216 }
217 
218 
219 double AmrBoxLib::getRho(int /*x*/, int /*y*/, int /*z*/) {
220  //TODO
221  throw OpalException("AmrBoxLib::getRho(x, y, z)", "Not yet Implemented.");
222  return 0.0;
223 }
224 
225 
227  //TODO
228  throw OpalException("AmrBoxLib::computeSelfFields", "Not yet Implemented.");
229 }
230 
231 
232 void AmrBoxLib::computeSelfFields(int /*bin*/) {
233  //TODO
234  throw OpalException("AmrBoxLib::computeSelfFields(int bin)", "Not yet Implemented.");
235 }
236 
237 
239  /*
240  * The potential is not scaled according to domain modification.
241  *
242  */
243  if ( !bunch_mp->hasFieldSolver() )
244  return;
245 
246  /*
247  * scatter charges onto grid
248  */
250 
254 
255  // map on Amr domain + Lorentz transform
256  double scalefactor = amrpbase_p->domainMapping();
257 
258  amrpbase_p->setForbidTransform(true);
259  amrpbase_p->update();
260  amrpbase_p->setForbidTransform(false);
261 
262  double invGamma = 1.0 / gamma;
263  int nLevel = finest_level + 1;
264 
265  double l0norm = this->solvePoisson_m();
266 
267  /* apply scale of electric-field in order to undo the transformation
268  * + undo normalization
269  */
270  for (int i = 0; i <= finestLevel(); ++i) {
271  this->phi_m[i]->mult(scalefactor * l0norm, 0, 1);
272  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
273  this->efield_m[i][j]->mult(scalefactor * scalefactor * l0norm, 0, 1);
274  }
275  }
276 
277  for (int i = 0; i <= finest_level; ++i) {
278  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
279  if ( this->efield_m[i][j]->contains_nan(false) )
280  throw OpalException("AmrBoxLib::computeSelfFields_cycl(double gamma) ",
281  "Ef: NANs at level " + std::to_string(i) + ".");
282  }
283  }
284 
285  amrpbase_p->gather(bunch_mp->Ef, this->efield_m, bunch_mp->R, 0, finest_level);
286 
287  // undo domain change + undo Lorentz transform
288  amrpbase_p->domainMapping(true);
289 
291  bunch_mp->Ef *= Vector_t(gamma,
292  1.0,
293  gamma);
294 
296  // Relativistic E&M says gamma*v/c^2 = gamma*beta/c = sqrt(gamma*gamma-1)/c
297  // but because we already transformed E_trans into the moving frame we have to
298  // add 1/gamma so we are using the E_trans from the rest frame -DW
299  double betaC = std::sqrt(gamma * gamma - 1.0) * invGamma / Physics::c;
300 
302  bunch_mp->Bf(0) = betaC * bunch_mp->Ef(2);
303  bunch_mp->Bf(2) = -betaC * bunch_mp->Ef(0);
304 
305  /*
306  * dumping only
307  */
308 
311 
312  AmrIntArray_t rr(finest_level);
313  for (int i = 0; i < finest_level; ++i)
314  rr[i] = this->MaxRefRatio(i);
315 
316  double time = bunch_mp->getT(); // in seconds
317 
318  // we need to undo coefficient when writing charge density
319  for (int i = 0; i <= finest_level; ++i)
320  this->rho_m[i]->mult(- Physics::epsilon_0 * l0norm, 0, 1);
321 
322 
323  ytWriter.writeFields(rho_m, phi_m, efield_m, rr, this->geom,
324  nLevel, time, scalefactor);
325 
326  ytWriter.writeBunch(bunch_mp, time, gamma);
327  }
328 }
329 
330 
332 
333  if ( !bunch_mp->hasFieldSolver() )
334  return;
335 
337  double gamma = bunch_mp->getBinGamma(bin);
338 
339  /* relativistic factor is always gamma >= 1
340  * --> if no particle --> gamma = 0 --> leave computation
341  */
342  if ( gamma < 1.0 )
343  return;
344 
345  /*
346  * scatter charges onto grid
347  */
349 
350  // Lorentz transformation: apply Lorentz factor of that particle bin
352 
353  // map on Amr domain + Lorentz transform
354  double scalefactor = amrpbase_p->domainMapping();
355 
356  amrpbase_p->setForbidTransform(true);
357 
358  amrpbase_p->update();
359 
361  this->regrid(bunch_mp->getT() * 1.0e9 /*time [ns] */);
362  }
363 
364  amrpbase_p->setForbidTransform(false);
365 
368  amrpbase_p->scatter(bunch_mp->Q, this->rho_m, bunch_mp->R, 0, finest_level, bunch_mp->Bin, bin);
369 
371  // In particle rest frame, the longitudinal length (y for cyclotron) enlarged
372  // calculate Possion equation (with coefficient: -1/(eps))
373  for (int i = 0; i <= finest_level; ++i) {
374  this->rho_m[i]->mult(-1.0 / (Physics::epsilon_0), 0 /*comp*/, 1 /*ncomp*/);
375 
376  if ( this->rho_m[i]->contains_nan(false) )
377  throw OpalException("AmrBoxLib::computeSelfFields_cycl(int bin) ",
378  "NANs at level " + std::to_string(i) + ".");
379  }
380 
381  // find maximum and normalize each level (faster convergence)
382  double l0norm = 1.0;
383  for (int i = 0; i <= finest_level; ++i)
384  l0norm = std::max(l0norm, this->rho_m[i]->norm0(0));
385 
386  for (int i = 0; i <= finest_level; ++i) {
387  this->rho_m[i]->mult(1.0 / l0norm, 0, 1);
388  }
389 
390  // mesh scaling for solver
391  meshScaling_m = Vector_t(1.0, 1.0, 1.0);
392 
394 
396 
397  for (int i = 0; i <= finest_level; ++i) {
398  phi_m[i]->setVal(0.0, 0, phi_m[i]->nComp(), phi_m[i]->nGrow());
399  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
400  efield_m[i][j]->setVal(0.0, 0, efield_m[i][j]->nComp(), efield_m[i][j]->nGrow());
401  }
402  }
403 
404  // in case of binning we reset phi every time
405  solver->solve(rho_m, phi_m, efield_m, 0, finest_level, false);
406 
408 
409  // make sure ghost cells are filled
410  for (int i = 0; i <= finest_level; ++i) {
411  phi_m[i]->FillBoundary(geom[i].periodicity());
412  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
413  efield_m[i][j]->FillBoundary(geom[i].periodicity());
414  }
415  }
416 
417  this->fillPhysbc_m(*(this->phi_m[0]), 0);
418 
419 
420  /* apply scale of electric-field in order to undo the transformation
421  * + undo normalization
422  */
423  for (int i = 0; i <= finestLevel(); ++i) {
424  this->phi_m[i]->mult(scalefactor * l0norm, 0, 1);
425  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
426  this->efield_m[i][j]->mult(scalefactor * scalefactor * l0norm, 0, 1);
427  }
428  }
429 
430  for (int i = 0; i <= finest_level; ++i) {
431  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
432  if ( this->efield_m[i][j]->contains_nan(false) )
433  throw OpalException("AmrBoxLib::computeSelfFields_cycl(double gamma) ",
434  "Ef: NANs at level " + std::to_string(i) + ".");
435  }
436  }
437 
438  amrpbase_p->gather(bunch_mp->Eftmp, this->efield_m, bunch_mp->R, 0, finest_level);
439 
440  // undo domain change + undo Lorentz transform
441  amrpbase_p->domainMapping(true);
442 
444  bunch_mp->Eftmp *= Vector_t(gamma, 1.0, gamma);
445 
447  double betaC = std::sqrt(gamma * gamma - 1.0) / gamma / Physics::c;
448 
450  bunch_mp->Bf(0) += betaC * bunch_mp->Eftmp(2);
451  bunch_mp->Bf(2) -= betaC * bunch_mp->Eftmp(0);
452 
453  bunch_mp->Ef += bunch_mp->Eftmp;
454 
455  /*
456  * dumping only
457  */
459  AmrYtWriter ytWriter(bunch_mp->getLocalTrackStep(), bin);
460 
461  int nLevel = finest_level + 1;
462 
463  AmrIntArray_t rr(finest_level);
464  for (int i = 0; i < finest_level; ++i)
465  rr[i] = this->MaxRefRatio(i);
466 
467  double time = bunch_mp->getT(); // in seconds
468 
469  // we need to undo coefficient when writing charge density
470  for (int i = 0; i <= finest_level; ++i)
471  this->rho_m[i]->mult(- Physics::epsilon_0 * l0norm, 0, 1);
472 
473 
474  ytWriter.writeFields(rho_m, phi_m, efield_m, rr, this->geom,
475  nLevel, time, scalefactor);
476 
477  ytWriter.writeBunch(bunch_mp, time, gamma);
478  }
479 
480  isPoissonSolved_m = true;
481 }
482 
483 
485  //FIXME What about resizing mesh, i.e. geometry?
486  const AmrReal_t* tmp = this->geom[0].CellSize();
487 
488  Vector_t hr;
489  for (int i = 0; i < 3; ++i)
490  hr[i] = tmp[i];
491 
493 }
494 
495 
497  return meshScaling_m;
498 }
499 
500 
502  const Box_t& bx = this->geom[0].Domain();
503 
504  const AmrIntVect_t& low = bx.smallEnd();
505  const AmrIntVect_t& high = bx.bigEnd();
506 
507  return Vektor<int, 3>(high[0] - low[0] + 1,
508  high[1] - low[1] + 1,
509  high[2] - low[2] + 1);
510 }
511 
512 
513 inline const int& AmrBoxLib::maxLevel() const {
514  return this->max_level;
515 }
516 
517 
518 inline const int& AmrBoxLib::finestLevel() const {
519  return this->finest_level;
520 }
521 
522 
523 inline double AmrBoxLib::getT() const {
524  return bunch_mp->getT();
525 }
526 
527 
528 void AmrBoxLib::redistributeGrids(int /*how*/) {
529 //
530 // // copied + modified version of AMReX_Amr.cpp
531 // AmrProcMap_t::InitProximityMap();
533 //
534 // AmrGridContainer_t allBoxes(finest_level + 1);
535 // for(unsigned int ilev = 0; ilev < allBoxes.size(); ++ilev) {
536 // allBoxes[ilev] = boxArray(ilev);
537 // }
538 // amrex::Vector<AmrIntArray_t> mLDM;
539 //
540 // switch ( how ) {
541 // case RANK_ZERO:
542 // mLDM = AmrProcMap_t::MultiLevelMapRandom(this->ref_ratio,
543 // allBoxes,
544 // maxGridSize(0),
545 // 0/*maxRank*/,
546 // 0/*minRank*/);
547 // break;
548 // case PFC:
549 // mLDM = AmrProcMap_t::MultiLevelMapPFC(this->ref_ratio,
550 // allBoxes,
551 // maxGridSize(0));
552 // break;
553 // case RANDOM:
554 // mLDM = AmrProcMap_t::MultiLevelMapRandom(this->ref_ratio,
555 // allBoxes,
556 // maxGridSize(0));
557 // break;
558 // case KNAPSACK:
559 // mLDM = AmrProcMap_t::MultiLevelMapKnapSack(this->ref_ratio,
560 // allBoxes,
561 // maxGridSize(0));
562 // break;
563 // default:
564 // *gmsg << "We didn't redistribute the grids." << endl;
565 // return;
566 // }
567 //
568 // for(unsigned int iMap = 0; iMap < mLDM.size(); ++iMap) {
569 // AmrField_t::MoveAllFabs(mLDM[iMap]);
570 // }
571 //
572 // /*
573 // * particles need to know the BoxArray
574 // * and DistributionMapping
575 // */
576 // for(unsigned int ilev = 0; ilev < allBoxes.size(); ++ilev) {
577 // layout_mp->SetParticleBoxArray(ilev, this->grids[ilev]);
578 // layout_mp->SetParticleDistributionMap(ilev, this->dmap[ilev]);
579 // }
580 //
581 // for(unsigned int iMap = 0; iMap < mLDM.size(); ++iMap) {
582 // rho_m[iMap]->MoveFabs(mLDM[iMap]);
583 // phi_m[iMap]->MoveFabs(mLDM[iMap]);
584 // efield_m[iMap]->MoveFabs(mLDM[iMap]);
585 // }
586 }
587 
588 
589 void AmrBoxLib::RemakeLevel (int lev, AmrReal_t /*time*/,
590  const AmrGrid_t& new_grids,
591  const AmrProcMap_t& new_dmap)
592 {
593  SetBoxArray(lev, new_grids);
594  SetDistributionMap(lev, new_dmap);
595 
596  // #comp #ghosts cells
597  rho_m[lev].reset(new AmrField_t(new_grids, new_dmap, 1, 0));
598  phi_m[lev].reset(new AmrField_t(new_grids, new_dmap, 1, 1));
599  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
600  efield_m[lev][j].reset(new AmrField_t(new_grids, new_dmap, 1, 1));
601  }
602 
603  // including nghost = 1
604  rho_m[lev]->setVal(0.0, 0);
605  phi_m[lev]->setVal(0.0, 1);
606 
607  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
608  efield_m[lev][j]->setVal(0.0, 1);
609  }
610 
611  /*
612  * particles need to know the BoxArray
613  * and DistributionMapping
614  */
615  layout_mp->SetParticleBoxArray(lev, new_grids);
616  layout_mp->SetParticleDistributionMap(lev, new_dmap);
617 
618  layout_mp->buildLevelMask(lev, this->nErrorBuf(lev));
619 }
620 
621 
622 void AmrBoxLib::MakeNewLevel (int lev, AmrReal_t /*time*/,
623  const AmrGrid_t& new_grids,
624  const AmrProcMap_t& new_dmap)
625 {
626  SetBoxArray(lev, new_grids);
627  SetDistributionMap(lev, new_dmap);
628 
629  // #comp #ghosts cells
630  rho_m[lev].reset(new AmrField_t(new_grids, new_dmap, 1, 0));
631  phi_m[lev].reset(new AmrField_t(new_grids, new_dmap, 1, 1));
632 
633  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
634  efield_m[lev][j].reset(new AmrField_t(new_grids, new_dmap, 1, 1));
635  }
636 
637  // including nghost = 1
638  rho_m[lev]->setVal(0.0, 0);
639  phi_m[lev]->setVal(0.0, 1);
640  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
641  efield_m[lev][j]->setVal(0.0, 1);
642  }
643 
644 
645 
646  /*
647  * particles need to know the BoxArray
648  * and DistributionMapping
649  */
650  layout_mp->SetParticleBoxArray(lev, new_grids);
651  layout_mp->SetParticleDistributionMap(lev, new_dmap);
652 
653  layout_mp->buildLevelMask(lev, this->nErrorBuf(lev));
654 }
655 
656 
657 void AmrBoxLib::ClearLevel(int lev) {
658  rho_m[lev].reset(nullptr);
659  phi_m[lev].reset(nullptr);
660  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
661  efield_m[lev][j].reset(nullptr);
662  }
663  ClearBoxArray(lev);
664  ClearDistributionMap(lev);
665 
666  this->isFirstTagging_m[lev] = true;
667 }
668 
669 
670 void AmrBoxLib::ErrorEst(int lev, TagBoxArray_t& tags,
671  AmrReal_t time, int ngrow)
672 {
673  *gmsg << level2 << "* Start tagging of level " << lev << endl;
674 
675  switch ( tagging_m ) {
676  case CHARGE_DENSITY:
677  tagForChargeDensity_m(lev, tags, time, ngrow);
678  break;
679  case POTENTIAL:
680  tagForPotentialStrength_m(lev, tags, time, ngrow);
681  break;
682  case EFIELD:
683  tagForEfield_m(lev, tags, time, ngrow);
684  break;
685  case MOMENTA:
686  tagForMomenta_m(lev, tags, time, ngrow);
687  break;
688  case MAX_NUM_PARTICLES:
689  tagForMaxNumParticles_m(lev, tags, time, ngrow);
690  break;
691  case MIN_NUM_PARTICLES:
692  tagForMinNumParticles_m(lev, tags, time, ngrow);
693  break;
694  default:
695  tagForChargeDensity_m(lev, tags, time, ngrow);
696  break;
697  }
698 
699  *gmsg << level2 << "* Finished tagging of level " << lev << endl;
700 }
701 
702 
704  const AmrGrid_t& /*ba*/,
705  const AmrProcMap_t& /*dm*/)
706 {
707  throw OpalException("AmrBoxLib::MakeNewLevelFromScratch()", "Shouldn't be called.");
708 }
709 
710 
711 void AmrBoxLib::MakeNewLevelFromCoarse (int /*lev*/, AmrReal_t /*time*/,
712  const AmrGrid_t& /*ba*/,
713  const AmrProcMap_t& /*dm*/)
714 {
715  throw OpalException("AmrBoxLib::MakeNewLevelFromCoarse()", "Shouldn't be called.");
716 }
717 
718 
719 void AmrBoxLib::doRegrid_m(int lbase, double time) {
720  int new_finest = 0;
721  AmrGridContainer_t new_grids(finest_level+2);
722 
723  MakeNewGrids(lbase, time, new_finest, new_grids);
724 
725  PAssert(new_finest <= finest_level+1);
726 
727  for (int lev = lbase+1; lev <= new_finest; ++lev)
728  {
729  if (lev <= finest_level) // an old level
730  {
731  if (new_grids[lev] != grids[lev]) // otherwise nothing
732  {
733  AmrProcMap_t new_dmap(new_grids[lev]);
734  RemakeLevel(lev, time, new_grids[lev], new_dmap);
735  }
736  }
737  else // a new level
738  {
739  AmrProcMap_t new_dmap(new_grids[lev]);
740  MakeNewLevel(lev, time, new_grids[lev], new_dmap);
741  }
742 
743  layout_mp->setFinestLevel(new_finest);
744  }
745 
746  // now we are safe to delete deprecated levels
747  for (int lev = new_finest+1; lev <= finest_level; ++lev) {
748  ClearLevel(lev);
749  }
750 
751  finest_level = new_finest;
752 }
753 
754 
756  /* In case of E-field or potential tagging
757  * in combination of binning we need to make
758  * sure we do not lose accuracy when tagging since
759  * the grid data of the potential or e-field are only
760  * non-zero for the last bin causing the tagging to refine
761  * only there.
762  * So, we need to solve the Poisson problem first assuming
763  * a single bin only
764  */
765  if ( tagging_m == POTENTIAL || tagging_m == EFIELD ) {
766  this->solvePoisson_m();
767  }
768 }
769 
770 
771 void AmrBoxLib::postRegrid_m(int old_finest) {
772  /* ATTENTION: In this call the bunch has to be updated
773  * since each particle needs to be assigned to its latest
774  * grid and sent to the corresponding MPI-process.
775  *
776  * We need to update the bunch before we clear
777  * levels, otherwise the particle level counter
778  * is invalidated.
779  */
780 
781  // redistribute particles and assign correct grid and level
783  amrpbase_p->update(0, finest_level, true);
784 
785  // check if no particles left on higher levels
786  const auto& LocalNumPerLevel = amrpbase_p->getLocalNumPerLevel();
787 
788  for (int lev = finest_level+1; lev <= old_finest; ++lev) {
789  if ( LocalNumPerLevel.getLocalNumAtLevel(lev) != 0 ) {
790  throw OpalException("AmrBoxLib::postRegrid_m()",
791  "Still particles on level " + std::to_string(lev) + "!");
792  }
793  layout_mp->ClearParticleBoxArray(lev);
794  layout_mp->ClearParticleDistributionMap(lev);
796  }
797 
798  if ( bunch_mp->getLocalNum() != LocalNumPerLevel.getLocalNumUpToLevel(finest_level) ) {
799  std::string localnum = std::to_string(bunch_mp->getLocalNum());
800  std::string levelnum = std::to_string(LocalNumPerLevel.getLocalNumUpToLevel(finest_level));
801  throw OpalException("AmrBoxLib::postRegrid_m()",
802  "Number of particles do not agree: " + localnum + " != " + levelnum);
803  }
804 
806  solver->hasToRegrid();
807 }
808 
809 
812 
814  amrpbase_p->scatter(bunch_mp->Q, this->rho_m, bunch_mp->R, 0, finest_level, bunch_mp->Bin);
815 
816  int baseLevel = 0;
817 
818  // mesh scaling for solver
819  meshScaling_m = Vector_t(1.0, 1.0, 1.0);
820 
821  // charge density is in rho_m
822  // calculate Possion equation (with coefficient: -1/(eps))
823  for (int i = 0; i <= finest_level; ++i) {
824  if ( this->rho_m[i]->contains_nan(false) )
825  throw OpalException("AmrBoxLib::solvePoisson_m() ",
826  "NANs at level " + std::to_string(i) + ".");
827  this->rho_m[i]->mult(-1.0 / Physics::epsilon_0, 0, 1);
828  }
829 
830  // find maximum and normalize each level (faster convergence)
831  double l0norm = 1.0;
832  for (int i = 0; i <= finest_level; ++i)
833  l0norm = std::max(l0norm, this->rho_m[i]->norm0(0));
834 
835  for (int i = 0; i <= finest_level; ++i) {
836  this->rho_m[i]->mult(1.0 / l0norm, 0, 1);
837  }
838 
840 
842  solver->solve(rho_m, phi_m, efield_m, baseLevel, finest_level);
844 
845  // make sure ghost cells are filled
846  for (int i = 0; i <= finest_level; ++i) {
847  phi_m[i]->FillBoundary(geom[i].periodicity());
848  for (int j = 0; j < AMREX_SPACEDIM; ++j) {
849  efield_m[i][j]->FillBoundary(geom[i].periodicity());
850  }
851  }
852 
853  this->fillPhysbc_m(*(this->phi_m[0]), 0);
854 
855  return l0norm;
856 }
857 
858 
860  AmrReal_t /*time*/, int /*ngrow*/)
861 {
862  // we need to update first
864  amrpbase_p->update(0, lev, true);
865 
866  for (int i = lev; i <= finest_level; ++i)
867  rho_m[i]->setVal(0.0, rho_m[i]->nGrow());
868 
869  // the new scatter function averages the value also down to the coarsest level
870  amrpbase_p->scatter(bunch_mp->Q, rho_m,
871  bunch_mp->R, 0, lev, bunch_mp->Bin);
872 
873  const double& scalefactor = amrpbase_p->getScalingFactor();
874 
875  for (int i = lev; i <= finest_level; ++i)
876  rho_m[i]->mult(scalefactor, 0, 1);
877 
878  const int clearval = TagBox_t::CLEAR;
879  const int tagval = TagBox_t::SET;
880 
881 #ifdef _OPENMP
882 #pragma omp parallel
883 #endif
884  {
885  for (MFIter_t mfi(*rho_m[lev], true); mfi.isValid(); ++mfi) {
886  const Box_t& tilebx = mfi.tilebox();
887 
888  TagBox_t& tagfab = tags[mfi];
889  FArrayBox_t& fab = (*rho_m[lev])[mfi];
890 
891  const int* tlo = tilebx.loVect();
892  const int* thi = tilebx.hiVect();
893 
894  for (int i = tlo[0]; i <= thi[0]; ++i) {
895  for (int j = tlo[1]; j <= thi[1]; ++j) {
896  for (int k = tlo[2]; k <= thi[2]; ++k) {
897 
898  amrex::IntVect iv(D_DECL(i,j,k));
899 
900  if ( std::abs( fab(iv) ) >= chargedensity_m )
901  tagfab(iv) = tagval;
902  else
903  tagfab(iv) = clearval;
904  }
905  }
906  }
907  }
908  }
909 }
910 
911 
913  AmrReal_t time, int ngrow)
914 {
915  /* Tag all cells for refinement
916  * where the value of the potential is higher than 75 percent of the maximum potential
917  * value of this level.
918  */
919  if ( !isPoissonSolved_m || !phi_m[lev]->ok() || this->isFirstTagging_m[lev] ) {
920  *gmsg << level2 << "* Level " << lev << ": We need to perform "
921  << "charge tagging if a new level is created." << endl;
922  this->tagForChargeDensity_m(lev, tags, time, ngrow);
923  this->isFirstTagging_m[lev] = false;
924  return;
925  }
926 
927  // tag cells for refinement
928  const int clearval = TagBox_t::CLEAR;
929  const int tagval = TagBox_t::SET;
930 
931  AmrReal_t threshold = phi_m[lev]->norm0(0, 0 /*nghost*/, false /*local*/);
932 
933  threshold *= scaling_m;
934 
935 #ifdef _OPENMP
936 #pragma omp parallel
937 #endif
938  {
939  for (MFIter_t mfi(*phi_m[lev], true); mfi.isValid(); ++mfi) {
940 
941  const Box_t& tilebx = mfi.tilebox();
942  TagBox_t& tagfab = tags[mfi];
943  FArrayBox_t& fab = (*phi_m[lev])[mfi];
944 
945  const int* tlo = tilebx.loVect();
946  const int* thi = tilebx.hiVect();
947 
948  for (int i = tlo[0]; i <= thi[0]; ++i) {
949  for (int j = tlo[1]; j <= thi[1]; ++j) {
950  for (int k = tlo[2]; k <= thi[2]; ++k) {
951 
952  amrex::IntVect iv(D_DECL(i,j,k));
953 
954  if ( std::abs( fab(iv) ) >= threshold )
955  tagfab(iv) = tagval;
956  else
957  tagfab(iv) = clearval;
958  }
959  }
960  }
961  }
962  }
963 }
964 
965 
967  AmrReal_t time, int ngrow)
968 {
969  /* Tag all cells for refinement
970  * where the value of the efield is higher than 75 percent of the maximum efield
971  * value of this level.
972  */
973  if ( !isPoissonSolved_m || !efield_m[lev][0]->ok() || this->isFirstTagging_m[lev] ) {
974  *gmsg << level2 << "* Level " << lev << ": We need to perform "
975  << "charge tagging if a new level is created." << endl;
976  this->tagForChargeDensity_m(lev, tags, time, ngrow);
977  this->isFirstTagging_m[lev] = false;
978  return;
979  }
980 
981  // tag cells for refinement
982  const int clearval = TagBox_t::CLEAR;
983  const int tagval = TagBox_t::SET;
984 
985  // obtain maximum absolute value
986  amrex::Vector<AmrReal_t> threshold(AMREX_SPACEDIM);
987 
988  for (int i = 0; i < 3; ++i) {
989  threshold[i] = efield_m[lev][i]->norm0(0,
990  0 /*nghosts*/,
991  false /*local*/);
992 
993  threshold[i] *= scaling_m;
994  }
995 
996 #ifdef _OPENMP
997 #pragma omp parallel
998 #endif
999  {
1000  for (MFIter_t mfi(this->grids[lev], this->dmap[lev], true); mfi.isValid(); ++mfi) {
1001 
1002  const Box_t& tilebx = mfi.tilebox();
1003  TagBox_t& tagfab = tags[mfi];
1004  FArrayBox_t& xfab = (*efield_m[lev][0])[mfi];
1005  FArrayBox_t& yfab = (*efield_m[lev][1])[mfi];
1006  FArrayBox_t& zfab = (*efield_m[lev][2])[mfi];
1007 
1008  const int* tlo = tilebx.loVect();
1009  const int* thi = tilebx.hiVect();
1010 
1011  for (int i = tlo[0]; i <= thi[0]; ++i) {
1012  for (int j = tlo[1]; j <= thi[1]; ++j) {
1013  for (int k = tlo[2]; k <= thi[2]; ++k) {
1014  AmrIntVect_t iv(i,j,k);
1015  if (std::abs(xfab(iv)) >= threshold[0])
1016  tagfab(iv) = tagval;
1017  else if (std::abs(yfab(iv)) >= threshold[1])
1018  tagfab(iv) = tagval;
1019  else if (std::abs(zfab(iv)) >= threshold[2])
1020  tagfab(iv) = tagval;
1021  else
1022  tagfab(iv) = clearval;
1023  }
1024  }
1025  }
1026  }
1027  }
1028 }
1029 
1030 
1032  AmrReal_t /*time*/, int /*ngrow*/)
1033 {
1035  // we need to update first
1036  amrpbase_p->update(0, lev, true);
1037  const auto& LocalNumPerLevel = amrpbase_p->getLocalNumPerLevel();
1038 
1039  size_t lBegin = LocalNumPerLevel.begin(lev);
1040  size_t lEnd = LocalNumPerLevel.end(lev);
1041 
1042  Vector_t pmax = Vector_t(0.0, 0.0, 0.0);
1043  for (size_t i = lBegin; i < lEnd; ++i) {
1044  const Vector_t& tmp = bunch_mp->P[i];
1045  pmax = ( dot(tmp, tmp) > dot(pmax, pmax) ) ? tmp : pmax;
1046  }
1047 
1048  double momentum2 = scaling_m * dot(pmax, pmax);
1049 
1050  std::map<AmrIntVect_t, bool> cells;
1051  for (size_t i = lBegin; i < lEnd; ++i) {
1052  if ( dot(bunch_mp->P[i], bunch_mp->P[i]) >= momentum2 ) {
1053  AmrIntVect_t iv = layout_mp->Index(bunch_mp->R[i], lev);
1054  cells[iv] = true;
1055  }
1056  }
1057 
1058  const int clearval = TagBox_t::CLEAR;
1059  const int tagval = TagBox_t::SET;
1060 
1061 
1062 #ifdef _OPENMP
1063 #pragma omp parallel
1064 #endif
1065  {
1066  for (MFIter_t mfi(*rho_m[lev], true); mfi.isValid(); ++mfi) {
1067 
1068  const Box_t& tilebx = mfi.tilebox();
1069  TagBox_t& tagfab = tags[mfi];
1070 
1071  const int* tlo = tilebx.loVect();
1072  const int* thi = tilebx.hiVect();
1073 
1074  for (int i = tlo[0]; i <= thi[0]; ++i) {
1075  for (int j = tlo[1]; j <= thi[1]; ++j) {
1076  for (int k = tlo[2]; k <= thi[2]; ++k) {
1077  AmrIntVect_t iv(i, j, k);
1078  if ( cells.find(iv) != cells.end() )
1079  tagfab(iv) = tagval;
1080  else
1081  tagfab(iv) = clearval;
1082  }
1083  }
1084  }
1085  }
1086  }
1087 }
1088 
1089 
1091  AmrReal_t /*time*/, int /*ngrow*/)
1092 {
1094  // we need to update first
1095  amrpbase_p->update(0, lev, true);
1096  const auto& LocalNumPerLevel = amrpbase_p->getLocalNumPerLevel();
1097 
1098  size_t lBegin = LocalNumPerLevel.begin(lev);
1099  size_t lEnd = LocalNumPerLevel.end(lev);
1100 
1101  // count particles per cell
1102  std::map<AmrIntVect_t, size_t> cells;
1103  for (size_t i = lBegin; i < lEnd; ++i) {
1104  AmrIntVect_t iv = layout_mp->Index(bunch_mp->R[i], lev);
1105  ++cells[iv];
1106  }
1107 
1108  const int clearval = TagBox_t::CLEAR;
1109  const int tagval = TagBox_t::SET;
1110 
1111 
1112 #ifdef _OPENMP
1113 #pragma omp parallel
1114 #endif
1115  {
1116  for (MFIter_t mfi(*rho_m[lev], true); mfi.isValid(); ++mfi) {
1117 
1118  const Box_t& tilebx = mfi.tilebox();
1119  TagBox_t& tagfab = tags[mfi];
1120 
1121  const int* tlo = tilebx.loVect();
1122  const int* thi = tilebx.hiVect();
1123 
1124  for (int i = tlo[0]; i <= thi[0]; ++i) {
1125  for (int j = tlo[1]; j <= thi[1]; ++j) {
1126  for (int k = tlo[2]; k <= thi[2]; ++k) {
1127  AmrIntVect_t iv(i, j, k);
1128  if ( cells.find(iv) != cells.end() && cells[iv] <= maxNumPart_m )
1129  tagfab(iv) = tagval;
1130  else
1131  tagfab(iv) = clearval;
1132  }
1133  }
1134  }
1135  }
1136  }
1137 }
1138 
1139 
1141  AmrReal_t /*time*/, int /*ngrow*/)
1142 {
1144  // we need to update first
1145  amrpbase_p->update(0, lev, true);
1146  const auto& LocalNumPerLevel = amrpbase_p->getLocalNumPerLevel();
1147 
1148  size_t lBegin = LocalNumPerLevel.begin(lev);
1149  size_t lEnd = LocalNumPerLevel.end(lev);
1150 
1151  // count particles per cell
1152  std::map<AmrIntVect_t, size_t> cells;
1153  for (size_t i = lBegin; i < lEnd; ++i) {
1154  AmrIntVect_t iv = layout_mp->Index(bunch_mp->R[i], lev);
1155  ++cells[iv];
1156  }
1157 
1158  const int clearval = TagBox_t::CLEAR;
1159  const int tagval = TagBox_t::SET;
1160 
1161 
1162 #ifdef _OPENMP
1163 #pragma omp parallel
1164 #endif
1165  {
1166  for (MFIter_t mfi(*rho_m[lev], true); mfi.isValid(); ++mfi) {
1167 
1168  const Box_t& tilebx = mfi.tilebox();
1169  TagBox_t& tagfab = tags[mfi];
1170 
1171  const int* tlo = tilebx.loVect();
1172  const int* thi = tilebx.hiVect();
1173 
1174  for (int i = tlo[0]; i <= thi[0]; ++i) {
1175  for (int j = tlo[1]; j <= thi[1]; ++j) {
1176  for (int k = tlo[2]; k <= thi[2]; ++k) {
1177  AmrIntVect_t iv(i, j, k);
1178  if ( cells.find(iv) != cells.end() &&
1179  cells[iv] >= minNumPart_m )
1180  {
1181  tagfab(iv) = tagval;
1182  } else
1183  tagfab(iv) = clearval;
1184  }
1185  }
1186  }
1187  }
1188  }
1189 }
1190 
1191 
1193  // we need to set the AmrCore variable
1194  finest_level = 0;
1195 
1196  AmrIntVect_t low(0, 0, 0);
1197  AmrIntVect_t high(nGridPts[0] - 1,
1198  nGridPts[1] - 1,
1199  nGridPts[2] - 1);
1200 
1201  const Box_t bx(low, high);
1202  AmrGrid_t ba(bx);
1203  ba.maxSize( this->maxGridSize(0) );
1204 
1205  // chop grids to guarantee #grids == #procs on base level
1206  ba = this->MakeBaseGrids();
1207 
1208  AmrProcMap_t dmap;
1209  dmap.define(ba, amrex::ParallelDescriptor::NProcs());
1210 
1211  this->RemakeLevel(0, 0.0, ba, dmap);
1212 
1213  layout_mp->define(this->geom);
1214  layout_mp->define(this->ref_ratio);
1215 }
1216 
1217 
1219 
1220  /*
1221  * All parameters that we set with the OPAL input file
1222  */
1223  amrex::ParmParse pAmr("amr");
1224  pAmr.add("max_grid_size_x", info.maxgrid[0]);
1225  pAmr.add("max_grid_size_y", info.maxgrid[1]);
1226  pAmr.add("max_grid_size_z", info.maxgrid[2]);
1227 
1228  pAmr.add("blocking_factor_x", info.bf[0]);
1229  pAmr.add("blocking_factor_y", info.bf[1]);
1230  pAmr.add("blocking_factor_z", info.bf[2]);
1231 
1232  const int nratios_vect = info.maxlevel * AMREX_SPACEDIM;
1233 
1234  AmrIntArray_t refratio(nratios_vect);
1235 
1236  for (int i = 0; i < info.maxlevel; ++i) {
1237  refratio[i * AMREX_SPACEDIM] = info.refratio[0];
1238  refratio[i * AMREX_SPACEDIM + 1] = info.refratio[1];
1239  refratio[i * AMREX_SPACEDIM + 2] = info.refratio[2];
1240  }
1241 
1242  pAmr.addarr("ref_ratio_vect", refratio);
1243 
1244  amrex::ParmParse pGeom("geometry");
1245  AmrIntArray_t isPeriodic = {
1246  layout_p->Geom(0).isPeriodic(0),
1247  layout_p->Geom(0).isPeriodic(1),
1248  layout_p->Geom(0).isPeriodic(2)
1249  };
1250  pGeom.addarr("is_periodic", isPeriodic);
1251 
1252 
1253  /*
1254  * "All" other parameters, we moslty take the
1255  * defaults of the code
1256  *
1257  * ATTENTION Be careful with default values since they might
1258  * be changed by the AMReX developers!
1259  *
1260  * Parmparse parameters not to be set because
1261  * alreday given due to constructor
1262  * ----------------------------------
1263  *
1264  * AMReX_AmrMesh:
1265  * - amr.max_level
1266  *
1267  * AMReX_Geometry:
1268  * - geometry.coord_sys
1269  * - geometry.prob_lo
1270  * - geometry.prob_hi
1271  * - geometry.is_periodic
1272  * - geometry.spherical_origin_fix [default: 0]
1273  * (not set because we're using Cartesian coordinates)
1274  *
1275  *
1276  * ParmParse left out
1277  * ------------------
1278  * AMReX_FabArrayBase:
1279  * - fabarray.mfiter_tile_size [default: IntVect(1024000,8,8)]
1280  * - fabarray.mfghostiter_tile_size [default: IntVect(1024000, 8, 8)]
1281  * - fabarray.comm_tile_size [default: IntVect(1024000, 8, 8)]
1282  * - fabarray.maxcomp [default: 25]
1283  * - fabarray.do_async_sends [default: true]
1284  *
1285  * AMReX_MemPool:
1286  * - fab.init_snan [default: 0, if not BL_TESTING or DEBUG enabled]
1287  *
1288  * AMReX_MemProfiler:
1289  * - amrex.memory.log [default: "memlog"]
1290  *
1291  * AMReX_VisMF:
1292  * - vismf.v [verbose, default: 0]
1293  * - vismf.headerversion [default: VisMF::Header::Version_v1 = 1]
1294  * - vismf.groupsets [default: false]
1295  * - vismf.setbuf [default: true]
1296  * - vismf.usesingleread [default: false]
1297  * - vismf.usesinglewrite [default: false]
1298  * - vismf.checkfilepositions [default: false]
1299  * - vismf.usepersistentifstreams [default: true]
1300  * - vismf.usesynchronousreads [default: false]
1301  * - vismf.usedynamicsetselection [default: true]
1302  * - vismf.iobuffersize [default: VisMF::IO_Buffer_Size = 262144 * 8]
1303  *
1304  * AMReX_ParallelDescriptor:
1305  * Needs change of ParallelDescriptor::SetNProcsSidecars in the function
1306  * ParallelDescriptor::StartParallel()
1307  * - amrex.ncolors [default: m_nCommColors = 1]
1308  * - team.size [default: disabled, enable by BL_USE_UPCXX or BL_USE_MPI3]
1309  * - team.reduce [default: disabled, enable by BL_USE_UPCXX or BL_USE_MPI3]
1310  * - mpi.onesided [default: disabled, enable by BL_USE_UPCXX or BL_USE_MPI3]
1311  *
1312  * AMReX:
1313  * Debugging purposes
1314  * - amrex.v [verbose, default: 0]
1315  * - amrex.verbose [default: 0]
1316  * - amrex.fpe_trap_invalid [invalid, default: 0]
1317  * - amrex.fpe_trap_zero [divbyzero, default: 0]
1318  * - amrex.fpe_trap_overflow [overflow, 0]
1319  *
1320  * AMReX_FArrayBox:
1321  * For output only
1322  * - fab.format [default: FABio::FAB_NATIVE]
1323  * For reading in an old FAB
1324  * - fab.ordering
1325  * - fab.initval [default: quiet_NaN() or max()]
1326  * - fab.do_initval [default: false, if not DEBUG or BL_TESTING enabled]
1327  * - fab.init_snan [default: false, if not DEBUG or BL_TESTING enabled]
1328  *
1329  * AMReX_MCMultiGrid:
1330  * We do NOT use this solver
1331  * - mg.maxiter [default: 40]
1332  * - mg.numiter [default: -1]
1333  * - mg.nu_0 [default: 1]
1334  * - mg.nu_1 [default: 2]
1335  * - mg.nu_2 [default: 2]
1336  * - mg.nu_f [default: 8]
1337  * - mg.v [verbose, default: 0]
1338  * - mg.usecg [default: 1]
1339  * - mg.rtol_b [default: 0.01]
1340  * - mg.bot_atol [default: -1.0]
1341  * - mg.nu_b [default: 0]
1342  * - mg.numLevelsMAX [default: 1024]
1343  *
1344  * AMReX_MCLinOp:
1345  * We do NOT use this solver
1346  * - MCLp.harmavg [default: 0]
1347  * - MCLp.v [verbose, default: 0]
1348  * - MCLp.maxorder [default: 2]
1349  *
1350  * AMReX_MCCGSolver:
1351  * We do NOT use this solver
1352  * - cg.maxiter [default: 40]
1353  * - cg.v [verbose, default: 0]
1354  * - cg.isExpert [default: 0]
1355  * - MCCGSolver::def_unstable_criterion [default: 10]
1356  *
1357  * AMReX_LinOp:
1358  * We do NOT use this class
1359  * - Lp.harmavg [default: 0]
1360  * - Lp.v [verbose, default: 0]
1361  * - Lp.maxorder [default: 2]
1362  * - LinOp::LinOp_grow [default: 1]
1363  *
1364  * AMReX_MultiGrid (single level solver):
1365  * We do NOT use this solver, see BoxLibSolvers/FMGPoissonSolver for
1366  * explanation of parameters
1367  * - mg.v [verbose, default: 0]
1368  * - mg.nu_0 [default: 1]
1369  * - mg.nu_1 [default: 2]
1370  * - mg.nu_2 [default: 2]
1371  * - mg.nu_f [default: 8]
1372  * - mg.nu_b [default: 0]
1373  * - mg.usecg [default: 1]
1374  * - mg.rtol_b [default: 0.0001 or 0.01 (if CG_USE_OLD_CONVERGENCE_CRITERIA enabled)]
1375  * - mg.verbose [default: 0]
1376  * - mg.maxiter [default: 40]
1377  * - mg.bot_atol [default: -1.0]
1378  * - mg.maxiter_b [default: 120]
1379  * - mg.numLevelsMAX [default: 1024]
1380  * - mg.smooth_on_cg_unstable [default: 1]
1381  * - mg.use_Anorm_for_convergence [default: 1]
1382  *
1383  * AMReX_CGSolver (single level solver):
1384  * We do NOT use this solver
1385  * - cg.v [verbose, default: 0]
1386  * - cg.SSS [default: SSS_MAX = 4]
1387  * - cg.maxiter [default: 80]
1388  * - cg.verbose [default: 0]
1389  * - cg.variable_SSS [default: true]
1390  * - cg.use_jbb_precond [default: 0]
1391  * - cg.use_jacobi_precond [default: 0]
1392  * - cg.unstable_criterion [default: 10]
1393  * - CGSolver::def_cg_solver [default: BiCGStab]
1394  * - cg.cg_solver [default: CGSolver::def_cg_solver]
1395  *
1396  * AMReX_Amr:
1397  * We do NOT use this class
1398  * - amr.regrid_on_restart [default: 0]
1399  * - amr.use_efficient_regrid [default: 0]
1400  * - amr.plotfile_on_restart [default: 0]
1401  * - amr.checkpoint_on_restart [default: 0]
1402  * - amr.compute_new_dt_on_regrid [default: 0]
1403  * - amr.mffile_nstreams [default: 1]
1404  * - amr.probinit_natonce [default: 32]
1405  * - amr.file_name_digits [default: 5]
1406  * - amr.initial_grid_file
1407  * - amr.regrid_file
1408  * - amr.message_int [default: 10]
1409  * - amr.run_log [default: not parsed]
1410  * - amr.run_log_terse [default: not parsed]
1411  * - amr.grid_log [default: not parsed]
1412  * - amr.data_log [default: not parsed]
1413  * - amr.probin_file [default: not parsed]
1414  * - amr.restart
1415  * - amr.restart_from_plotfile
1416  * - amr.regrid_int [default: 1 at all levels]
1417  * - amr.rebalance_grids [default: 0]
1418  * - amr.nosub [default: not parsed]
1419  * - amr.subcycling_mode [default: "Auto"]
1420  * - amr.subcycling_iterations [default: 0]
1421  * - amr.checkpoint_files_output
1422  * - amr.plot_files_output
1423  * - amr.plot_nfiles
1424  * - amr.checkpoint_nfiles
1425  * - amr.check_file [default: "chk"]
1426  * - amr.check_int [default: -1]
1427  * - amr.check_per [default: -1.0]
1428  * - amr.plot_file [default: "plt"]
1429  * - amr.plot_int [default: -1]
1430  * - amr.plot_per [default: -1.0]
1431  * - amr.small_plot_file [default: "smallplt"]
1432  * - amr.small_plot_int [default: -1]
1433  * - amr.small_plot_per [default: -1.0]
1434  * - amr.write_plotfile_with_checkpoint [default: 1]
1435  * - amr.stream_max_tries [default: 4]
1436  * - amr.abort_on_stream_retry_failure [default: false]
1437  * - amr.precreateDirectories
1438  * - amr.prereadFAHeaders
1439  * - amr.plot_headerversion
1440  * - amr.checkpoint_headerversion
1441  *
1442  * AMReX_SlabStat:
1443  * We do NOT use this class
1444  * - slabstat.boxes
1445  *
1446  * AMReX_AmrLevel:
1447  * We do NOT use this class
1448  * - amr.plot_vars [default: not parsed]
1449  * - amr.derive_plot_vars [default: not parsed]
1450  * - amr.small_plot_vars [default: not parsed]
1451  *
1452  * AMReX_StationData:
1453  * We do NOT use this class
1454  * - StationData.vars [default: not parsed]
1455  * - StationData.coord [default: not parsed]
1456  */
1457 
1458  // verbosity
1459  pAmr.add("v", 0);
1460 
1461  // # cells required for proper nesting.
1462  pAmr.add("n_proper", 1);
1463 
1464  // Grid efficiency. (default: 0.7)
1465  pAmr.add("grid_eff", 0.95);
1466 
1467  int nlev = info.maxlevel + 1;
1468 
1469  // Buffer cells around each tagged cell.
1470  AmrIntArray_t error_buf(nlev, 4 /*buffer*/);
1471  error_buf[0] = 0;
1472  pAmr.addarr("n_error_buf", error_buf);
1473 
1474  // chop up grids to have more grids than the number of procs
1475  pAmr.add("refine_grid_layout", true);
1476 
1477 
1478  /*
1479  * ParmParse for DistributionMapping
1480  *
1481  * round-robin: FAB i is owned by CPU i%N where N is total number of CPUs
1482  * knapsack: FABs are partitioned across CPUs such that the total volume
1483  * of the Boxes in the underlying BoxArray are as equal across
1484  * CPUs as is possible.
1485  * SFC: Is based on a space filling curve (default)
1486  */
1487  amrex::ParmParse pDmap("DistributionMapping");
1488 
1489  // verbosity
1490  pDmap.add("v", 0);
1491 
1492  // max_efficiency = 0.9
1493  pDmap.add("efficiency", 0.9);
1494 
1495  // SFC = space filling curve
1496  pDmap.add("sfc_threshold", 0);
1497 
1498  /* if > 0:
1499  * nworkers = node_size
1500  * nteams = nprocs / node_size
1501  *
1502  * if nwokers * nteams != nprocs:
1503  * nteams = nprocs
1504  * nworkers = 1
1505  */
1506  pDmap.add("node_size", 0);
1507 
1508  /* Possibilities:
1509  * - ROUNDROBIN
1510  * - KNAPSACK
1511  * - SFC
1512  * - PFC
1513  * - RRSFC
1514  */
1515  pDmap.add("strategy", "SFC");
1516 }
1517 
1518 
1520  /* Copied from one of the miniapps:
1521  *
1522  * amrex/Src/AmrTask/tutorials/MiniApps/HeatEquation/physbc.cpp
1523  *
1524  * AMReX - Revision:
1525  *
1526  * commit 8174212e898677d6413cf5e4db44148a52b4b732
1527  * Author: Weiqun Zhang <weiqunzhang@lbl.gov>
1528  * Date: Mon Jul 2 10:40:21 2018 -0700
1529  */
1530  if (AmrGeometry_t::isAllPeriodic())
1531  return;
1532  // Set up BC; see Src/Base/AMReX_BC_TYPES.H for supported types
1533  amrex::Vector<amrex::BCRec> bc(mf.nComp());
1534  for (int n = 0; n < mf.nComp(); ++n)
1535  {
1536  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim)
1537  {
1538  if (AmrGeometry_t::isPeriodic(idim))
1539  {
1540  bc[n].setLo(idim, amrex::BCType::int_dir); // interior
1541  bc[n].setHi(idim, amrex::BCType::int_dir);
1542  }
1543  else
1544  {
1545  bc[n].setLo(idim, amrex::BCType::foextrap); // first-order extrapolation.
1546  bc[n].setHi(idim, amrex::BCType::foextrap);
1547  }
1548  }
1549  }
1550 
1551  amrex::FillDomainBoundary(mf, this->geom[lev], bc);
1552 }
Inform * gmsg
Definition: Main.cpp:62
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
#define PAssert(c)
Definition: PAssert.h:102
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
Definition: Physics.h:57
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:51
int amrRegridFreq
After how many steps the AMR grid hierarchy is updated.
Definition: Options.cpp:103
int amrYtDumpFreq
The frequency to dump AMR grid data and particles into file.
Definition: Options.cpp:101
bool info
Info flag.
Definition: Options.cpp:28
ParticleLayout< T, Dim > & getLayout()
ParticleAttrib< Vector_t > Ef
ParticlePos_t & R
ParticleAttrib< int > Bin
ParticleAttrib< Vector_t > Eftmp
size_t getLocalNum() const
ParticleAttrib< Vector_t > P
double getBinGamma(int bin)
Get gamma of one bin.
ParticleAttrib< double > Q
long long getLocalTrackStep() const
short getNumBunch() const
static const unsigned Dimension
Definition: PartBunchBase.h:77
ParticleAttrib< Vector_t > Bf
double getT() const
amr::AmrProcMap_t AmrProcMap_t
Definition: AmrBoxLib.h:51
Vector_t meshScaling_m
in particle rest frame, the longitudinal length enlarged
Definition: AmrBoxLib.h:403
const Vector_t & getMeshScaling() const
Definition: AmrBoxLib.cpp:496
void redistributeGrids(int how)
Definition: AmrBoxLib.cpp:528
void MakeNewLevelFromScratch(int lev, AmrReal_t time, const AmrGrid_t &ba, const AmrProcMap_t &dm)
Definition: AmrBoxLib.cpp:703
virtual void ErrorEst(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow) override
Definition: AmrBoxLib.cpp:670
const int & maxLevel() const
Definition: AmrBoxLib.cpp:513
void preRegrid_m()
Definition: AmrBoxLib.cpp:755
AmrBoxLib(const AmrDomain_t &domain, const AmrIntArray_t &nGridPts, int maxLevel, AmrPartBunch *bunch_p)
Definition: AmrBoxLib.cpp:44
amrex::Box Box_t
Definition: AmrBoxLib.h:56
AmrScalarFieldContainer_t rho_m
charge density on the grid for all levels
Definition: AmrBoxLib.h:394
void tagForPotentialStrength_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
Definition: AmrBoxLib.cpp:912
VectorPair_t getEExtrema()
Definition: AmrBoxLib.cpp:196
void getGridStatistics(std::map< int, long > &gridPtsPerCore, std::vector< int > &gridsPerLevel) const
Definition: AmrBoxLib.cpp:135
void tagForMaxNumParticles_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
Definition: AmrBoxLib.cpp:1090
amrex::MFIter MFIter_t
Definition: AmrBoxLib.h:59
void postRegrid_m(int old_finest)
Definition: AmrBoxLib.cpp:771
void RemakeLevel(int lev, AmrReal_t time, const AmrGrid_t &new_grids, const AmrProcMap_t &new_dmap)
Definition: AmrBoxLib.cpp:589
AmrScalarFieldContainer_t phi_m
scalar potential on the grid for all levels
Definition: AmrBoxLib.h:397
amr::AmrField_t AmrField_t
Definition: AmrBoxLib.h:41
void computeSelfFields()
Definition: AmrBoxLib.cpp:226
amr::AmrIntArray_t AmrIntArray_t
Definition: AmrBoxLib.h:48
void updateMesh()
Definition: AmrBoxLib.cpp:484
std::vector< bool > isFirstTagging_m
Definition: AmrBoxLib.h:406
amr::AmrReal_t AmrReal_t
Definition: AmrBoxLib.h:49
void computeSelfFields_cycl(double gamma)
Definition: AmrBoxLib.cpp:238
amrex::FArrayBox FArrayBox_t
Definition: AmrBoxLib.h:55
double solvePoisson_m()
Definition: AmrBoxLib.cpp:810
double getT() const
Definition: AmrBoxLib.cpp:523
AmrLayout_t * layout_mp
Definition: AmrBoxLib.h:391
amr::AmrGrid_t AmrGrid_t
Definition: AmrBoxLib.h:50
AmrPartBunch * bunch_mp
bunch used for tagging strategies
Definition: AmrBoxLib.h:388
void MakeNewLevel(int lev, AmrReal_t time, const AmrGrid_t &new_grids, const AmrProcMap_t &new_dmap)
Definition: AmrBoxLib.cpp:622
void tagForEfield_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
Definition: AmrBoxLib.cpp:966
void tagForMinNumParticles_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
Definition: AmrBoxLib.cpp:1140
amrex::TagBoxArray TagBoxArray_t
Definition: AmrBoxLib.h:58
void initFineLevels()
Definition: AmrBoxLib.cpp:162
void regrid(double time)
Definition: AmrBoxLib.cpp:104
void initBaseLevel_m(const AmrIntArray_t &nGridPts)
Definition: AmrBoxLib.cpp:1192
void MakeNewLevelFromCoarse(int lev, AmrReal_t time, const AmrGrid_t &ba, const AmrProcMap_t &dm)
Definition: AmrBoxLib.cpp:711
const int & finestLevel() const
Definition: AmrBoxLib.cpp:518
void doRegrid_m(int lbase, double time)
Definition: AmrBoxLib.cpp:719
void tagForMomenta_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
Definition: AmrBoxLib.cpp:1031
void fillPhysbc_m(AmrField_t &mf, int lev=0)
Definition: AmrBoxLib.cpp:1519
amrex::TagBox TagBox_t
Definition: AmrBoxLib.h:57
static std::unique_ptr< AmrBoxLib > create(const AmrInfo &info, AmrPartBunch *bunch_p)
Definition: AmrBoxLib.cpp:71
void tagForChargeDensity_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
Definition: AmrBoxLib.cpp:859
amr::AmrDomain_t AmrDomain_t
Definition: AmrBoxLib.h:47
AmrVectorFieldContainer_t efield_m
vector field on the grid for all levels
Definition: AmrBoxLib.h:400
static void initParmParse_m(const AmrInfo &info, AmrLayout_t *layout_p)
Definition: AmrBoxLib.cpp:1218
void ClearLevel(int lev)
Definition: AmrBoxLib.cpp:657
Vektor< int, 3 > getBaseLevelGridPoints() const
Definition: AmrBoxLib.cpp:501
bool isPoissonSolved_m
Definition: AmrBoxLib.h:408
amr::AmrGridContainer_t AmrGridContainer_t
Definition: AmrBoxLib.h:45
amr::AmrIntVect_t AmrIntVect_t
Definition: AmrBoxLib.h:53
double getRho(int x, int y, int z)
Definition: AmrBoxLib.cpp:219
double scaling_m
Scaling factor for tagging [0, 1].
Definition: AmrObject.h:184
IpplTimings::TimerRef amrRegridTimer_m
Definition: AmrObject.h:196
@ MIN_NUM_PARTICLES
min. #particles per cell
Definition: AmrObject.h:44
@ CHARGE_DENSITY
Definition: AmrObject.h:40
@ MAX_NUM_PARTICLES
max. #particles per cell
Definition: AmrObject.h:45
@ POTENTIAL
Definition: AmrObject.h:41
std::pair< Vector_t, Vector_t > VectorPair_t
Definition: AmrObject.h:35
double chargedensity_m
Tagging value for CHARGE_DENSITY.
Definition: AmrObject.h:186
bool refined_m
Only set to true in AmrObject::initFineLevels()
Definition: AmrObject.h:192
TaggingCriteria tagging_m
Tagging strategy.
Definition: AmrObject.h:182
IpplTimings::TimerRef amrSolveTimer_m
timer for selfField calculation (used in concrete AmrObject classes)
Definition: AmrObject.h:195
size_t minNumPart_m
Tagging value for MIN_NUM_PARTICLES.
Definition: AmrObject.h:190
size_t maxNumPart_m
Tagging value for MAX_NUM_PARTICLES.
Definition: AmrObject.h:188
void writeFields(const amr::AmrScalarFieldContainer_t &rho, const amr::AmrScalarFieldContainer_t &phi, const amr::AmrVectorFieldContainer_t &efield, const amr::AmrIntArray_t &refRatio, const amr::AmrGeomContainer_t &geom, const int &nLevel, const double &time, const double &scale)
Definition: AmrYtWriter.cpp:93
void writeBunch(const AmrPartBunch *bunch_p, const double &time, const double &gamma)
void buildLevelMask(int lev, const int ncells=1)
void clearLevelMask(int lev)
AmrIntVect_t Index(AmrParticleBase< BoxLibLayout< T, Dim > > &p, const unsigned int ip, int level) const
void resize(int maxLevel)
Definition: BoxLibLayout.h:241
void define(const AmrGeomContainer_t &geom)
Definition: BoxLibLayout.h:259
void gather(ParticleAttrib< FT > &attrib, AmrVectorFieldContainer_t &f, ParticleAttrib< Vektor< PT, Dim > > &pp, int lbase, int lfine)
void scatter(ParticleAttrib< FT > &attrib, AmrScalarFieldContainer_t &f, ParticleAttrib< Vektor< PT, Dim > > &pp, int lbase, int lfine, const ParticleAttrib< int > &pbin, int bin=-1)
void updateLorentzFactor(int bin=0)
void setBaseLevelMeshSpacing(const Vector_t &hr)
Definition: AmrPartBunch.h:94
PoissonSolver * getFieldSolver()
Definition: AmrPartBunch.h:86
pbase_t * getAmrParticleBase()
virtual void solve(AmrScalarFieldContainer_t &, AmrScalarFieldContainer_t &, AmrVectorFieldContainer_t &, unsigned short, unsigned short, bool=true)
Definition: PoissonSolver.h:39
virtual void hasToRegrid()
Definition: PoissonSolver.h:52
The base class for all OPAL exceptions.
Definition: OpalException.h:28
bool isForbidTransform() const
const double & getScalingFactor() const
const ParticleLevelCounter_t & getLocalNumPerLevel() const
void setForbidTransform(bool forbidTransform)
const double & domainMapping(bool inverse=false)
void setFinestLevel(int finestLevel)
Definition: Inform.h:42
static void stopTimer(TimerRef t)
Definition: IpplTimings.h:192
static void startTimer(TimerRef t)
Definition: IpplTimings.h:187
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6