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