37#include <AMReX_BCUtil.H>
38#include <AMReX_MultiFabUtil.H>
39#include <AMReX_ParmParse.H>
52 , amrex::AmrMesh(&domain,
maxLevel, nGridPts, 0 )
82 AmrDomain_t domain = layout_p->Geom(0).ProbDomain();
90 int maxlevel = info.maxlevel;
97 return std::unique_ptr<AmrBoxLib>(
new AmrBoxLib(domain,
109 *
gmsg <<
"* Start regriding:" <<
endl
110 <<
"* Old finest level: "
111 << finest_level <<
endl;
119 int old_finest = finest_level;
121 int lev_top = std::min(finest_level, max_level - 1);
122 for (
int i = 0; i <= lev_top; ++i) {
124 lev_top = std::min(finest_level, max_level - 1);
129 *
gmsg <<
"* New finest level: "
130 << finest_level <<
endl
131 <<
"* Finished regriding" <<
endl;
138 std::vector<int>& gridsPerLevel)
const {
140 typedef std::vector<int> container_t;
142 gridPtsPerCore.clear();
143 gridsPerLevel.clear();
145 gridsPerLevel.resize(max_level + 1);
147 for (
int lev = 0; lev <= finest_level; ++lev) {
151 const container_t& pmap = this->dmap[lev].ProcessorMap();
154 gridsPerLevel[lev] = pmap.size();
157 for (
unsigned int i = 0; i < ba.size(); ++i) {
158 gridPtsPerCore[pmap[i]] += ba[i].numPts();
166 *
gmsg <<
"* Initialization of all levels" <<
endl;
176 if ( !isForbidTransform ) {
181 if ( max_level > 0 ) {
185 if ( !isForbidTransform ) {
191 *
gmsg <<
"* Initialization done." <<
endl;
203 for (
unsigned int lev = 0; lev <
efield_m.size(); ++lev) {
204 for (std::size_t i = 0; i <
bunch_mp->Dimension; ++i) {
210 maxE[i] = (maxE[i] <
max) ?
max : maxE[i];
213 minE[i] = (minE[i] >
min) ?
min : minE[i];
223 throw OpalException(
"AmrBoxLib::getRho(x, y, z)",
"Not yet Implemented.");
230 throw OpalException(
"AmrBoxLib::computeSelfFields",
"Not yet Implemented.");
236 throw OpalException(
"AmrBoxLib::computeSelfFields(int bin)",
"Not yet Implemented.");
255 bunch_mp->updateLorentzFactor(gamma);
264 double invGamma = 1.0 / gamma;
265 int nLevel = finest_level + 1;
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);
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) +
".");
301 double betaC = std::sqrt(gamma * gamma - 1.0) * invGamma /
Physics::c;
315 for (
int i = 0; i < finest_level; ++i)
316 rr[i] = this->MaxRefRatio(i);
321 for (
int i = 0; i <= finest_level; ++i)
326 nLevel, time, scalefactor);
339 double gamma =
bunch_mp->getBinGamma(bin);
375 for (
int i = 0; i <= finest_level; ++i) {
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) +
".");
385 for (
int i = 0; i <= finest_level; ++i)
386 l0norm = std::max(l0norm, this->
rho_m[i]->norm0(0));
388 for (
int i = 0; i <= finest_level; ++i) {
389 this->
rho_m[i]->mult(1.0 / l0norm, 0, 1);
399 for (
int i = 0; i <= finest_level; ++i) {
401 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
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());
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);
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) +
".");
449 double betaC = std::sqrt(gamma * gamma - 1.0) / gamma /
Physics::c;
463 int nLevel = finest_level + 1;
466 for (
int i = 0; i < finest_level; ++i)
467 rr[i] = this->MaxRefRatio(i);
472 for (
int i = 0; i <= finest_level; ++i)
477 nLevel, time, scalefactor);
488 const AmrReal_t* tmp = this->geom[0].CellSize();
491 for (
int i = 0; i < 3; ++i)
494 bunch_mp->setBaseLevelMeshSpacing(hr);
504 const Box_t& bx = this->geom[0].Domain();
510 high[1] - low[1] + 1,
511 high[2] - low[2] + 1);
516 return this->max_level;
521 return this->finest_level;
595 SetBoxArray(lev, new_grids);
596 SetDistributionMap(lev, new_dmap);
601 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
606 rho_m[lev]->setVal(0.0, 0);
607 phi_m[lev]->setVal(0.0, 1);
609 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
617 layout_mp->SetParticleBoxArray(lev, new_grids);
618 layout_mp->SetParticleDistributionMap(lev, new_dmap);
620 layout_mp->buildLevelMask(lev, this->nErrorBuf(lev));
627 SetBoxArray(lev, new_grids);
628 SetDistributionMap(lev, new_dmap);
634 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
639 rho_m[lev]->setVal(0.0, 0);
640 phi_m[lev]->setVal(0.0, 1);
641 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
649 layout_mp->SetParticleBoxArray(lev, new_grids);
650 layout_mp->SetParticleDistributionMap(lev, new_dmap);
652 layout_mp->buildLevelMask(lev, this->nErrorBuf(lev));
657 rho_m[lev].reset(
nullptr);
658 phi_m[lev].reset(
nullptr);
659 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
663 ClearDistributionMap(lev);
706 throw OpalException(
"AmrBoxLib::MakeNewLevelFromScratch()",
"Shouldn't be called.");
714 throw OpalException(
"AmrBoxLib::MakeNewLevelFromCoarse()",
"Shouldn't be called.");
722 MakeNewGrids(lbase, time, new_finest, new_grids);
724 PAssert(new_finest <= finest_level+1);
726 for (
int lev = lbase+1; lev <= new_finest; ++lev)
728 if (lev <= finest_level)
730 if (new_grids[lev] != grids[lev])
746 for (
int lev = new_finest+1; lev <= finest_level; ++lev) {
750 finest_level = new_finest;
782 amrpbase_p->
update(0, finest_level,
true);
787 for (
int lev = finest_level+1; lev <= old_finest; ++lev) {
788 if ( LocalNumPerLevel.getLocalNumAtLevel(lev) != 0 ) {
790 "Still particles on level " + std::to_string(lev) +
"!");
793 layout_mp->ClearParticleDistributionMap(lev);
797 if (
bunch_mp->getLocalNum() != LocalNumPerLevel.getLocalNumUpToLevel(finest_level) ) {
798 std::string localnum = std::to_string(
bunch_mp->getLocalNum());
799 std::string levelnum = std::to_string(LocalNumPerLevel.getLocalNumUpToLevel(finest_level));
801 "Number of particles do not agree: " + localnum +
" != " + levelnum);
822 for (
int i = 0; i <= finest_level; ++i) {
823 if ( this->
rho_m[i]->contains_nan(
false) )
825 "NANs at level " + std::to_string(i) +
".");
831 for (
int i = 0; i <= finest_level; ++i)
832 l0norm = std::max(l0norm, this->
rho_m[i]->norm0(0));
834 for (
int i = 0; i <= finest_level; ++i) {
835 this->
rho_m[i]->mult(1.0 / l0norm, 0, 1);
845 for (
int i = 0; i <= finest_level; ++i) {
846 phi_m[i]->FillBoundary(geom[i].periodicity());
847 for (
int j = 0; j < AMREX_SPACEDIM; ++j) {
848 efield_m[i][j]->FillBoundary(geom[i].periodicity());
863 amrpbase_p->
update(0, lev,
true);
865 for (
int i = lev; i <= finest_level; ++i)
874 for (
int i = lev; i <= finest_level; ++i)
875 rho_m[i]->mult(scalefactor, 0, 1);
877 const int clearval = TagBox_t::CLEAR;
878 const int tagval = TagBox_t::SET;
884 for (
MFIter_t mfi(*
rho_m[lev],
true); mfi.isValid(); ++mfi) {
885 const Box_t& tilebx = mfi.tilebox();
890 const int* tlo = tilebx.loVect();
891 const int* thi = tilebx.hiVect();
893 for (
int i = tlo[0]; i <= thi[0]; ++i) {
894 for (
int j = tlo[1]; j <= thi[1]; ++j) {
895 for (
int k = tlo[2]; k <= thi[2]; ++k) {
897 amrex::IntVect iv(D_DECL(i,j,k));
902 tagfab(iv) = clearval;
919 *
gmsg <<
level2 <<
"* Level " << lev <<
": We need to perform "
920 <<
"charge tagging if a new level is created." <<
endl;
927 const int clearval = TagBox_t::CLEAR;
928 const int tagval = TagBox_t::SET;
938 for (
MFIter_t mfi(*
phi_m[lev],
true); mfi.isValid(); ++mfi) {
940 const Box_t& tilebx = mfi.tilebox();
944 const int* tlo = tilebx.loVect();
945 const int* thi = tilebx.hiVect();
947 for (
int i = tlo[0]; i <= thi[0]; ++i) {
948 for (
int j = tlo[1]; j <= thi[1]; ++j) {
949 for (
int k = tlo[2]; k <= thi[2]; ++k) {
951 amrex::IntVect iv(D_DECL(i,j,k));
953 if ( std::abs( fab(iv) ) >= threshold )
956 tagfab(iv) = clearval;
973 *
gmsg <<
level2 <<
"* Level " << lev <<
": We need to perform "
974 <<
"charge tagging if a new level is created." <<
endl;
981 const int clearval = TagBox_t::CLEAR;
982 const int tagval = TagBox_t::SET;
985 amrex::Vector<AmrReal_t> threshold(AMREX_SPACEDIM);
987 for (
int i = 0; i < 3; ++i) {
988 threshold[i] =
efield_m[lev][i]->norm0(0,
999 for (
MFIter_t mfi(this->grids[lev], this->dmap[lev],
true); mfi.isValid(); ++mfi) {
1001 const Box_t& tilebx = mfi.tilebox();
1007 const int* tlo = tilebx.loVect();
1008 const int* thi = tilebx.hiVect();
1010 for (
int i = tlo[0]; i <= thi[0]; ++i) {
1011 for (
int j = tlo[1]; j <= thi[1]; ++j) {
1012 for (
int k = tlo[2]; k <= thi[2]; ++k) {
1014 if (std::abs(xfab(iv)) >= threshold[0])
1015 tagfab(iv) = tagval;
1016 else if (std::abs(yfab(iv)) >= threshold[1])
1017 tagfab(iv) = tagval;
1018 else if (std::abs(zfab(iv)) >= threshold[2])
1019 tagfab(iv) = tagval;
1021 tagfab(iv) = clearval;
1035 amrpbase_p->
update(0, lev,
true);
1038 size_t lBegin = LocalNumPerLevel.
begin(lev);
1039 size_t lEnd = LocalNumPerLevel.end(lev);
1042 for (
size_t i = lBegin; i < lEnd; ++i) {
1044 pmax = (
dot(tmp, tmp) >
dot(pmax, pmax) ) ? tmp : pmax;
1049 std::map<AmrIntVect_t, bool> cells;
1050 for (
size_t i = lBegin; i < lEnd; ++i) {
1057 const int clearval = TagBox_t::CLEAR;
1058 const int tagval = TagBox_t::SET;
1065 for (
MFIter_t mfi(*
rho_m[lev],
true); mfi.isValid(); ++mfi) {
1067 const Box_t& tilebx = mfi.tilebox();
1070 const int* tlo = tilebx.loVect();
1071 const int* thi = tilebx.hiVect();
1073 for (
int i = tlo[0]; i <= thi[0]; ++i) {
1074 for (
int j = tlo[1]; j <= thi[1]; ++j) {
1075 for (
int k = tlo[2]; k <= thi[2]; ++k) {
1077 if ( cells.find(iv) != cells.end() )
1078 tagfab(iv) = tagval;
1080 tagfab(iv) = clearval;
1094 amrpbase_p->
update(0, lev,
true);
1097 size_t lBegin = LocalNumPerLevel.
begin(lev);
1098 size_t lEnd = LocalNumPerLevel.end(lev);
1101 std::map<AmrIntVect_t, size_t> cells;
1102 for (
size_t i = lBegin; i < lEnd; ++i) {
1107 const int clearval = TagBox_t::CLEAR;
1108 const int tagval = TagBox_t::SET;
1115 for (
MFIter_t mfi(*
rho_m[lev],
true); mfi.isValid(); ++mfi) {
1117 const Box_t& tilebx = mfi.tilebox();
1120 const int* tlo = tilebx.loVect();
1121 const int* thi = tilebx.hiVect();
1123 for (
int i = tlo[0]; i <= thi[0]; ++i) {
1124 for (
int j = tlo[1]; j <= thi[1]; ++j) {
1125 for (
int k = tlo[2]; k <= thi[2]; ++k) {
1127 if ( cells.find(iv) != cells.end() && cells[iv] <=
maxNumPart_m )
1128 tagfab(iv) = tagval;
1130 tagfab(iv) = clearval;
1144 amrpbase_p->
update(0, lev,
true);
1147 size_t lBegin = LocalNumPerLevel.
begin(lev);
1148 size_t lEnd = LocalNumPerLevel.end(lev);
1151 std::map<AmrIntVect_t, size_t> cells;
1152 for (
size_t i = lBegin; i < lEnd; ++i) {
1157 const int clearval = TagBox_t::CLEAR;
1158 const int tagval = TagBox_t::SET;
1165 for (
MFIter_t mfi(*
rho_m[lev],
true); mfi.isValid(); ++mfi) {
1167 const Box_t& tilebx = mfi.tilebox();
1170 const int* tlo = tilebx.loVect();
1171 const int* thi = tilebx.hiVect();
1173 for (
int i = tlo[0]; i <= thi[0]; ++i) {
1174 for (
int j = tlo[1]; j <= thi[1]; ++j) {
1175 for (
int k = tlo[2]; k <= thi[2]; ++k) {
1177 if ( cells.find(iv) != cells.end() &&
1179 tagfab(iv) = tagval;
1181 tagfab(iv) = clearval;
1200 const Box_t bx(low, high);
1202 ba.maxSize( this->maxGridSize(0) );
1205 ba = this->MakeBaseGrids();
1208 dmap.define(ba, amrex::ParallelDescriptor::NProcs());
1222 amrex::ParmParse pAmr(
"amr");
1223 pAmr.add(
"max_grid_size_x", info.maxgrid[0]);
1224 pAmr.add(
"max_grid_size_y", info.maxgrid[1]);
1225 pAmr.add(
"max_grid_size_z", info.maxgrid[2]);
1227 pAmr.add(
"blocking_factor_x", info.bf[0]);
1228 pAmr.add(
"blocking_factor_y", info.bf[1]);
1229 pAmr.add(
"blocking_factor_z", info.bf[2]);
1231 const int nratios_vect = info.maxlevel * AMREX_SPACEDIM;
1235 for (
int i = 0; i < info.maxlevel; ++i) {
1236 refratio[i * AMREX_SPACEDIM] = info.refratio[0];
1237 refratio[i * AMREX_SPACEDIM + 1] = info.refratio[1];
1238 refratio[i * AMREX_SPACEDIM + 2] = info.refratio[2];
1241 pAmr.addarr(
"ref_ratio_vect", refratio);
1243 amrex::ParmParse pGeom(
"geometry");
1245 layout_p->Geom(0).isPeriodic(0),
1246 layout_p->Geom(0).isPeriodic(1),
1247 layout_p->Geom(0).isPeriodic(2)
1249 pGeom.addarr(
"is_periodic", isPeriodic);
1461 pAmr.add(
"n_proper", 1);
1464 pAmr.add(
"grid_eff", 0.95);
1466 int nlev = info.maxlevel + 1;
1471 pAmr.addarr(
"n_error_buf", error_buf);
1474 pAmr.add(
"refine_grid_layout",
true);
1486 amrex::ParmParse pDmap(
"DistributionMapping");
1492 pDmap.add(
"efficiency", 0.9);
1495 pDmap.add(
"sfc_threshold", 0);
1505 pDmap.add(
"node_size", 0);
1514 pDmap.add(
"strategy",
"SFC");
1529 if (AmrGeometry_t::isAllPeriodic()) {
1534 amrex::Vector<amrex::BCRec> bc(mf.nComp());
1535 for (
int n = 0; n < mf.nComp(); ++n) {
1536 for (
int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
1537 if (AmrGeometry_t::isPeriodic(idim)) {
1538 bc[n].setLo(idim, amrex::BCType::int_dir);
1539 bc[n].setHi(idim, amrex::BCType::int_dir);
1541 bc[n].setLo(idim, amrex::BCType::foextrap);
1542 bc[n].setHi(idim, amrex::BCType::foextrap);
1547 amrex::FillDomainBoundary(mf, this->geom[lev], bc);
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
BoxLibLayout< double, 3 > AmrLayout_t
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Inform & level2(Inform &inf)
Inform & endl(Inform &inf)
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
constexpr double c
The velocity of light in m/s.
int amrRegridFreq
After how many steps the AMR grid hierarchy is updated.
int amrYtDumpFreq
The frequency to dump AMR grid data and particles into file.
ParticleLayout< T, Dim > & getLayout()
amr::AmrProcMap_t AmrProcMap_t
Vector_t meshScaling_m
in particle rest frame, the longitudinal length enlarged
const Vector_t & getMeshScaling() const
void redistributeGrids(int how)
void MakeNewLevelFromScratch(int lev, AmrReal_t time, const AmrGrid_t &ba, const AmrProcMap_t &dm)
virtual void ErrorEst(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow) override
const int & maxLevel() const
AmrBoxLib(const AmrDomain_t &domain, const AmrIntArray_t &nGridPts, int maxLevel, AmrPartBunch *bunch_p)
AmrScalarFieldContainer_t rho_m
charge density on the grid for all levels
void tagForPotentialStrength_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
VectorPair_t getEExtrema()
void getGridStatistics(std::map< int, long > &gridPtsPerCore, std::vector< int > &gridsPerLevel) const
void tagForMaxNumParticles_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
void postRegrid_m(int old_finest)
void RemakeLevel(int lev, AmrReal_t time, const AmrGrid_t &new_grids, const AmrProcMap_t &new_dmap)
AmrScalarFieldContainer_t phi_m
scalar potential on the grid for all levels
amr::AmrField_t AmrField_t
amr::AmrIntArray_t AmrIntArray_t
std::vector< bool > isFirstTagging_m
void computeSelfFields_cycl(double gamma)
amrex::FArrayBox FArrayBox_t
AmrPartBunch * bunch_mp
bunch used for tagging strategies
void MakeNewLevel(int lev, AmrReal_t time, const AmrGrid_t &new_grids, const AmrProcMap_t &new_dmap)
void tagForEfield_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
void tagForMinNumParticles_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
amrex::TagBoxArray TagBoxArray_t
void initBaseLevel_m(const AmrIntArray_t &nGridPts)
void MakeNewLevelFromCoarse(int lev, AmrReal_t time, const AmrGrid_t &ba, const AmrProcMap_t &dm)
const int & finestLevel() const
void doRegrid_m(int lbase, double time)
void tagForMomenta_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
void fillPhysbc_m(AmrField_t &mf, int lev=0)
static std::unique_ptr< AmrBoxLib > create(const AmrInfo &info, AmrPartBunch *bunch_p)
void tagForChargeDensity_m(int lev, TagBoxArray_t &tags, AmrReal_t time, int ngrow)
amr::AmrDomain_t AmrDomain_t
AmrVectorFieldContainer_t efield_m
vector field on the grid for all levels
static void initParmParse_m(const AmrInfo &info, AmrLayout_t *layout_p)
Vektor< int, 3 > getBaseLevelGridPoints() const
amr::AmrGridContainer_t AmrGridContainer_t
amr::AmrIntVect_t AmrIntVect_t
double getRho(int x, int y, int z)
@ MAX_NUM_PARTICLES
max. particles per cell
@ MIN_NUM_PARTICLES
min. particles per cell
double scaling_m
Scaling factor for tagging [0, 1].
IpplTimings::TimerRef amrRegridTimer_m
std::pair< Vector_t, Vector_t > VectorPair_t
double chargedensity_m
Tagging value for CHARGE_DENSITY.
bool refined_m
Only set to true in AmrObject::initFineLevels().
TaggingCriteria tagging_m
Tagging strategy.
IpplTimings::TimerRef amrSolveTimer_m
timer for selfField calculation (used in concrete AmrObject classes)
size_t minNumPart_m
Tagging value for MIN_NUM_PARTICLES.
size_t maxNumPart_m
Tagging value for MAX_NUM_PARTICLES.
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)
void writeBunch(const AmrPartBunch *bunch_p, const double &time, const double &gamma)
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)
virtual void solve(AmrScalarFieldContainer_t &, AmrScalarFieldContainer_t &, AmrVectorFieldContainer_t &, unsigned short, unsigned short, bool=true)
virtual void hasToRegrid()
The base class for all OPAL exceptions.
bool isForbidTransform() const
const double & getScalingFactor() const
const ParticleLevelCounter_t & getLocalNumPerLevel() const
void setForbidTransform(bool forbidTransform)
const double & domainMapping(bool inverse=false)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)
Vektor< double, 3 > Vector_t