aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Evolve/WarpXEvolveEM.cpp115
-rw-r--r--Source/Parallelization/GuardCellManager.H42
-rw-r--r--Source/Parallelization/GuardCellManager.cpp160
-rw-r--r--Source/Parallelization/Make.package2
-rw-r--r--Source/Parallelization/WarpXComm.cpp99
-rw-r--r--Source/Python/WarpXWrappers.cpp4
-rw-r--r--Source/Utils/WarpXMovingWindow.cpp56
-rw-r--r--Source/WarpX.H40
-rw-r--r--Source/WarpX.cpp111
9 files changed, 430 insertions, 199 deletions
diff --git a/Source/Evolve/WarpXEvolveEM.cpp b/Source/Evolve/WarpXEvolveEM.cpp
index f5491ffe3..dcf984bdf 100644
--- a/Source/Evolve/WarpXEvolveEM.cpp
+++ b/Source/Evolve/WarpXEvolveEM.cpp
@@ -75,8 +75,9 @@ WarpX::EvolveEM (int numsteps)
// Particles have p^{n} and x^{n}.
// is_synchronized is true.
if (is_synchronized) {
- FillBoundaryE();
- FillBoundaryB();
+ // Not called at each iteration, so exchange all guard cells
+ FillBoundaryE(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
+ FillBoundaryB(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
UpdateAuxilaryData();
// on first step, push p by -0.5*dt
for (int lev = 0; lev <= finest_level; ++lev) {
@@ -89,14 +90,23 @@ WarpX::EvolveEM (int numsteps)
} else {
// Beyond one step, we have E^{n} and B^{n}.
// Particles have p^{n-1/2} and x^{n}.
- FillBoundaryE();
- FillBoundaryB();
- UpdateAuxilaryData();
+ // E and B are up-to-date inside the domain only
+ FillBoundaryE(guard_cells.ng_FieldGather, guard_cells.ng_Extra);
+ FillBoundaryB(guard_cells.ng_FieldGather, guard_cells.ng_Extra);
+ // E and B: enough guard cells to update Aux or call Field Gather in fp and cp
+ // Need to update Aux on lower levels, to interpolate to higher levels.
+#ifndef WARPX_USE_PSATD
+ FillBoundaryAux(guard_cells.ng_UpdateAux);
+#endif
+ UpdateAuxilaryData();
}
if (do_subcycling == 0 || finest_level == 0) {
OneStep_nosub(cur_time);
+ // E : guard cells are up-to-date
+ // B : guard cells are NOT up-to-date
+ // F : guard cells are NOT up-to-date
} else if (do_subcycling == 1 && finest_level == 1) {
OneStep_sub1(cur_time);
} else {
@@ -106,6 +116,8 @@ WarpX::EvolveEM (int numsteps)
if (num_mirrors>0){
applyMirrors(cur_time);
+ // E : guard cells are NOT up-to-date
+ // B : guard cells are NOT up-to-date
}
#ifdef WARPX_USE_PY
@@ -185,8 +197,14 @@ WarpX::EvolveEM (int numsteps)
// slice gen //
if (to_make_plot || do_insitu || to_make_slice_plot)
{
- FillBoundaryE();
- FillBoundaryB();
+ // This is probably overkill, but it's not called often
+ FillBoundaryE(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
+ // This is probably overkill, but it's not called often
+ FillBoundaryB(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
+ // This is probably overkill, but it's not called often
+#ifndef WARPX_USE_PSATD
+ FillBoundaryAux(guard_cells.ng_UpdateAux);
+#endif
UpdateAuxilaryData();
for (int lev = 0; lev <= finest_level; ++lev) {
@@ -237,8 +255,14 @@ WarpX::EvolveEM (int numsteps)
if (write_plot_file || do_insitu)
{
- FillBoundaryE();
- FillBoundaryB();
+ // This is probably overkill, but it's not called often
+ FillBoundaryE(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
+ // This is probably overkill, but it's not called often
+ FillBoundaryB(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
+ // This is probably overkill
+#ifndef WARPX_USE_PSATD
+ FillBoundaryAux(guard_cells.ng_UpdateAux);
+#endif
UpdateAuxilaryData();
for (int lev = 0; lev <= finest_level; ++lev) {
@@ -300,6 +324,10 @@ WarpX::OneStep_nosub (Real cur_time)
SyncRho();
+ // At this point, J is up-to-date inside the domain, and E and B are
+ // up-to-date including enough guard cells for first step of the field
+ // solve.
+
// For extended PML: copy J from regular grid to PML, and damp J in PML
if (do_pml && pml_has_particles) CopyJPML();
if (do_pml && do_pml_j_damping) DampJPML();
@@ -309,24 +337,27 @@ WarpX::OneStep_nosub (Real cur_time)
#ifdef WARPX_USE_PSATD
PushPSATD(dt[0]);
if (do_pml) DampPML();
- FillBoundaryE();
- FillBoundaryB();
+ FillBoundaryE(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
+ FillBoundaryB(guard_cells.ng_alloc_EB, guard_cells.ng_Extra);
#else
EvolveF(0.5*dt[0], DtType::FirstHalf);
- FillBoundaryF();
+ FillBoundaryF(guard_cells.ng_FieldSolverF);
EvolveB(0.5*dt[0]); // We now have B^{n+1/2}
- FillBoundaryB();
+ FillBoundaryB(guard_cells.ng_FieldSolver, IntVect::TheZeroVector());
EvolveE(dt[0]); // We now have E^{n+1}
- FillBoundaryE();
+
+ FillBoundaryE(guard_cells.ng_FieldSolver, IntVect::TheZeroVector());
EvolveF(0.5*dt[0], DtType::SecondHalf);
EvolveB(0.5*dt[0]); // We now have B^{n+1}
if (do_pml) {
+ FillBoundaryF(guard_cells.ng_alloc_F);
DampPML();
- FillBoundaryE();
+ FillBoundaryE(guard_cells.ng_MovingWindow, IntVect::TheZeroVector());
+ FillBoundaryB(guard_cells.ng_MovingWindow, IntVect::TheZeroVector());
}
- FillBoundaryB();
-
+ // E and B are up-to-date in the domain, but all guard cells are
+ // outdated.
#endif
}
@@ -369,21 +400,22 @@ WarpX::OneStep_sub1 (Real curtime)
EvolveB(fine_lev, PatchType::fine, 0.5*dt[fine_lev]);
EvolveF(fine_lev, PatchType::fine, 0.5*dt[fine_lev], DtType::FirstHalf);
- FillBoundaryB(fine_lev, PatchType::fine);
- FillBoundaryF(fine_lev, PatchType::fine);
+ FillBoundaryB(fine_lev, PatchType::fine, guard_cells.ng_FieldSolver);
+ FillBoundaryF(fine_lev, PatchType::fine, guard_cells.ng_alloc_F);
EvolveE(fine_lev, PatchType::fine, dt[fine_lev]);
- FillBoundaryE(fine_lev, PatchType::fine);
+ FillBoundaryE(fine_lev, PatchType::fine, guard_cells.ng_FieldGather);
EvolveB(fine_lev, PatchType::fine, 0.5*dt[fine_lev]);
EvolveF(fine_lev, PatchType::fine, 0.5*dt[fine_lev], DtType::SecondHalf);
if (do_pml) {
+ FillBoundaryF(fine_lev, PatchType::fine, guard_cells.ng_alloc_F);
DampPML(fine_lev, PatchType::fine);
- FillBoundaryE(fine_lev, PatchType::fine);
+ FillBoundaryE(fine_lev, PatchType::fine, guard_cells.ng_FieldGather);
}
- FillBoundaryB(fine_lev, PatchType::fine);
+ FillBoundaryB(fine_lev, PatchType::fine, guard_cells.ng_FieldGather);
// ii) Push particles on the coarse patch and mother grid.
// Push the fields on the coarse patch and mother grid
@@ -395,20 +427,21 @@ WarpX::OneStep_sub1 (Real curtime)
EvolveB(fine_lev, PatchType::coarse, dt[fine_lev]);
EvolveF(fine_lev, PatchType::coarse, dt[fine_lev], DtType::FirstHalf);
- FillBoundaryB(fine_lev, PatchType::coarse);
- FillBoundaryF(fine_lev, PatchType::coarse);
+ FillBoundaryB(fine_lev, PatchType::coarse, guard_cells.ng_FieldGather);
+ FillBoundaryF(fine_lev, PatchType::coarse, guard_cells.ng_FieldSolverF);
EvolveE(fine_lev, PatchType::coarse, dt[fine_lev]);
- FillBoundaryE(fine_lev, PatchType::coarse);
+ FillBoundaryE(fine_lev, PatchType::coarse, guard_cells.ng_FieldGather);
EvolveB(coarse_lev, PatchType::fine, 0.5*dt[coarse_lev]);
EvolveF(coarse_lev, PatchType::fine, 0.5*dt[coarse_lev], DtType::FirstHalf);
- FillBoundaryB(coarse_lev, PatchType::fine);
- FillBoundaryF(coarse_lev, PatchType::fine);
+ FillBoundaryB(coarse_lev, PatchType::fine, guard_cells.ng_FieldGather + guard_cells.ng_Extra);
+ FillBoundaryF(coarse_lev, PatchType::fine, guard_cells.ng_FieldSolverF);
EvolveE(coarse_lev, PatchType::fine, 0.5*dt[coarse_lev]);
- FillBoundaryE(coarse_lev, PatchType::fine);
+ FillBoundaryE(coarse_lev, PatchType::fine, guard_cells.ng_FieldGather + guard_cells.ng_Extra);
+ FillBoundaryAux(guard_cells.ng_UpdateAux);
// iii) Get auxiliary fields on the fine grid, at dt[fine_lev]
UpdateAuxilaryData();
@@ -423,22 +456,21 @@ WarpX::OneStep_sub1 (Real curtime)
EvolveB(fine_lev, PatchType::fine, 0.5*dt[fine_lev]);
EvolveF(fine_lev, PatchType::fine, 0.5*dt[fine_lev], DtType::FirstHalf);
- FillBoundaryB(fine_lev, PatchType::fine);
- FillBoundaryF(fine_lev, PatchType::fine);
+ FillBoundaryB(fine_lev, PatchType::fine, guard_cells.ng_FieldSolver);
+ FillBoundaryF(fine_lev, PatchType::fine, guard_cells.ng_FieldSolverF);
EvolveE(fine_lev, PatchType::fine, dt[fine_lev]);
- FillBoundaryE(fine_lev, PatchType::fine);
+ FillBoundaryE(fine_lev, PatchType::fine, guard_cells.ng_FieldSolver);
EvolveB(fine_lev, PatchType::fine, 0.5*dt[fine_lev]);
EvolveF(fine_lev, PatchType::fine, 0.5*dt[fine_lev], DtType::SecondHalf);
if (do_pml) {
DampPML(fine_lev, PatchType::fine);
- FillBoundaryE(fine_lev, PatchType::fine);
+ FillBoundaryE(fine_lev, PatchType::fine, guard_cells.ng_FieldSolver);
}
- FillBoundaryB(fine_lev, PatchType::fine);
- FillBoundaryF(fine_lev, PatchType::fine);
+ FillBoundaryB(fine_lev, PatchType::fine, guard_cells.ng_FieldSolver);
// v) Push the fields on the coarse patch and mother grid
// by only half a coarse step (second half)
@@ -447,32 +479,31 @@ WarpX::OneStep_sub1 (Real curtime)
AddRhoFromFineLevelandSumBoundary(coarse_lev, ncomps, ncomps);
EvolveE(fine_lev, PatchType::coarse, dt[fine_lev]);
- FillBoundaryE(fine_lev, PatchType::coarse);
+ FillBoundaryE(fine_lev, PatchType::coarse, guard_cells.ng_FieldSolver);
EvolveB(fine_lev, PatchType::coarse, dt[fine_lev]);
EvolveF(fine_lev, PatchType::coarse, dt[fine_lev], DtType::SecondHalf);
if (do_pml) {
+ FillBoundaryF(fine_lev, PatchType::fine, guard_cells.ng_FieldSolverF);
DampPML(fine_lev, PatchType::coarse); // do it twice
DampPML(fine_lev, PatchType::coarse);
- FillBoundaryE(fine_lev, PatchType::coarse);
+ FillBoundaryE(fine_lev, PatchType::coarse, guard_cells.ng_alloc_EB);
}
- FillBoundaryB(fine_lev, PatchType::coarse);
- FillBoundaryF(fine_lev, PatchType::coarse);
+ FillBoundaryB(fine_lev, PatchType::coarse, guard_cells.ng_FieldSolver);
+
+ FillBoundaryF(fine_lev, PatchType::coarse, guard_cells.ng_FieldSolverF);
EvolveE(coarse_lev, PatchType::fine, 0.5*dt[coarse_lev]);
- FillBoundaryE(coarse_lev, PatchType::fine);
+ FillBoundaryE(coarse_lev, PatchType::fine, guard_cells.ng_FieldSolver);
EvolveB(coarse_lev, PatchType::fine, 0.5*dt[coarse_lev]);
EvolveF(coarse_lev, PatchType::fine, 0.5*dt[coarse_lev], DtType::SecondHalf);
if (do_pml) {
DampPML(coarse_lev, PatchType::fine);
- FillBoundaryE(coarse_lev, PatchType::fine);
}
-
- FillBoundaryB(coarse_lev, PatchType::fine);
}
void
diff --git a/Source/Parallelization/GuardCellManager.H b/Source/Parallelization/GuardCellManager.H
new file mode 100644
index 000000000..2e1cebff8
--- /dev/null
+++ b/Source/Parallelization/GuardCellManager.H
@@ -0,0 +1,42 @@
+#ifndef GUARDCELLMANAGER_H_
+#define GUARDCELLMANAGER_H_
+
+#include <AMReX_IntVect.H>
+
+class guardCellManager{
+
+public:
+
+ int Init(
+ const bool do_subcycling,
+ const bool do_fdtd_nci_corr,
+ const bool do_nodal,
+ const bool do_moving_window,
+ const bool do_fft_mpi_dec,
+ const bool aux_is_nodal,
+ const int moving_window_dir,
+ const int nox,
+ const int nox_fft, const int noy_fft, const int noz_fft,
+ const int nci_corr_stencil,
+ const int maxwell_fdtd_solver_id,
+ const int max_level);
+
+ // Guard cells allocated for each multifab
+ amrex::IntVect ng_alloc_EB = amrex::IntVect::TheZeroVector();
+ amrex::IntVect ng_alloc_J = amrex::IntVect::TheZeroVector();
+ amrex::IntVect ng_alloc_Rho = amrex::IntVect::TheZeroVector();
+ amrex::IntVect ng_alloc_F = amrex::IntVect::TheZeroVector();
+ int ng_alloc_F_int = 0;
+
+ // Guard cells exchanged for specific in the PIC loop
+ amrex::IntVect ng_FieldSolver = amrex::IntVect::TheZeroVector();
+ amrex::IntVect ng_FieldSolverF = amrex::IntVect::TheZeroVector();
+ amrex::IntVect ng_FieldGather = amrex::IntVect::TheZeroVector();
+ amrex::IntVect ng_UpdateAux = amrex::IntVect::TheZeroVector();
+ amrex::IntVect ng_MovingWindow = amrex::IntVect::TheZeroVector();
+
+ // Extra guard cells for fine level of E and B
+ amrex::IntVect ng_Extra = amrex::IntVect::TheZeroVector();
+};
+
+#endif // GUARDCELLMANAGER_H_
diff --git a/Source/Parallelization/GuardCellManager.cpp b/Source/Parallelization/GuardCellManager.cpp
new file mode 100644
index 000000000..34454bd7e
--- /dev/null
+++ b/Source/Parallelization/GuardCellManager.cpp
@@ -0,0 +1,160 @@
+#include "GuardCellManager.H"
+#include "NCIGodfreyFilter.H"
+#include <AMReX_Print.H>
+
+using namespace amrex;
+
+int
+guardCellManager::Init(
+ const bool do_subcycling,
+ const bool do_fdtd_nci_corr,
+ const bool do_nodal,
+ const bool do_moving_window,
+ const bool do_fft_mpi_dec,
+ const bool aux_is_nodal,
+ const int moving_window_dir,
+ const int nox,
+ const int nox_fft, const int noy_fft, const int noz_fft,
+ const int nci_corr_stencil,
+ const int maxwell_fdtd_solver_id,
+ const int max_level)
+{
+ // When using subcycling, the particles on the fine level perform two pushes
+ // before being redistributed ; therefore, we need one extra guard cell
+ // (the particles may move by 2*c*dt)
+ const int ngx_tmp = (max_level > 0 && do_subcycling == 1) ? nox+1 : nox;
+ const int ngy_tmp = (max_level > 0 && do_subcycling == 1) ? nox+1 : nox;
+ const int ngz_tmp = (max_level > 0 && do_subcycling == 1) ? nox+1 : nox;
+
+ // Ex, Ey, Ez, Bx, By, and Bz have the same number of ghost cells.
+ // jx, jy, jz and rho have the same number of ghost cells.
+ // E and B have the same number of ghost cells as j and rho if NCI filter is not used,
+ // but different number of ghost cells in z-direction if NCI filter is used.
+ // The number of cells should be even, in order to easily perform the
+ // interpolation from coarse grid to fine grid.
+ int ngx = (ngx_tmp % 2) ? ngx_tmp+1 : ngx_tmp; // Always even number
+ int ngy = (ngy_tmp % 2) ? ngy_tmp+1 : ngy_tmp; // Always even number
+ int ngz_nonci = (ngz_tmp % 2) ? ngz_tmp+1 : ngz_tmp; // Always even number
+ int ngz;
+ if (do_fdtd_nci_corr) {
+ int ng = ngz_tmp + nci_corr_stencil;
+ ngz = (ng % 2) ? ng+1 : ng;
+ } else {
+ ngz = ngz_nonci;
+ }
+
+ // J is only interpolated from fine to coarse (not coarse to fine)
+ // and therefore does not need to be even.
+ int ngJx = ngx_tmp;
+ int ngJy = ngy_tmp;
+ int ngJz = ngz_tmp;
+
+ // When calling the moving window (with one level of refinement), we shift
+ // the fine grid by 2 cells ; therefore, we need at least 2 guard cells
+ // on level 1. This may not be necessary for level 0.
+ if (do_moving_window) {
+ ngx = std::max(ngx,2);
+ ngy = std::max(ngy,2);
+ ngz = std::max(ngz,2);
+ ngJx = std::max(ngJx,2);
+ ngJy = std::max(ngJy,2);
+ ngJz = std::max(ngJz,2);
+ }
+
+#if (AMREX_SPACEDIM == 3)
+ ng_alloc_EB = IntVect(ngx,ngy,ngz);
+ ng_alloc_J = IntVect(ngJx,ngJy,ngJz);
+#elif (AMREX_SPACEDIM == 2)
+ ng_alloc_EB = IntVect(ngx,ngz);
+ ng_alloc_J = IntVect(ngJx,ngJz);
+#endif
+
+ int nJ_buffer = ng_alloc_J.max(); // guard cells for J required for deposition only.
+
+ ng_alloc_Rho = ng_alloc_J+1; //One extra ghost cell, so that it's safe to deposit charge density
+ // after pushing particle.
+ ng_alloc_F_int = (do_moving_window) ? 2 : 0;
+ // CKC solver requires one additional guard cell
+ if (maxwell_fdtd_solver_id == 1) ng_alloc_F_int = std::max( ng_alloc_F_int, 1 );
+ ng_alloc_F = IntVect(AMREX_D_DECL(ng_alloc_F_int, ng_alloc_F_int, ng_alloc_F_int));
+
+#ifdef WARPX_USE_PSATD
+ if (do_fft_mpi_dec == false){
+ // All boxes should have the same number of guard cells
+ // (to avoid temporary parallel copies)
+ // Thus take the max of the required number of guards for each field
+ // Also: the number of guard cell should be enough to contain
+ // the stencil of the FFT solver. Here, this number (`ngFFT`)
+ // is determined *empirically* to be the order of the solver
+ // for nodal, and half the order of the solver for staggered.
+ IntVect ngFFT;
+ if (do_nodal) {
+ ngFFT = IntVect(AMREX_D_DECL(nox_fft, noy_fft, noz_fft));
+ } else {
+ ngFFT = IntVect(AMREX_D_DECL(nox_fft/2, noy_fft/2, noz_fft/2));
+ }
+ for (int i_dim=0; i_dim<AMREX_SPACEDIM; i_dim++ ){
+ int ng_required = ngFFT[i_dim];
+ // Get the max
+ ng_required = std::max( ng_required, ng_alloc_EB[i_dim] );
+ ng_required = std::max( ng_required, ng_alloc_J[i_dim] );
+ ng_required = std::max( ng_required, ng_alloc_Rho[i_dim] );
+ ng_required = std::max( ng_required, ng_alloc_F[i_dim] );
+ // Set the guard cells to this max
+ ng_alloc_EB[i_dim] = ng_required;
+ ng_alloc_J[i_dim] = ng_required;
+ ng_alloc_F[i_dim] = ng_required;
+ ng_alloc_Rho[i_dim] = ng_required;
+ ng_alloc_F_int = ng_required;
+ }
+ }
+ ng_alloc_F = IntVect(AMREX_D_DECL(ng_alloc_F_int, ng_alloc_F_int, ng_alloc_F_int));
+#endif
+
+ ng_Extra = IntVect(static_cast<int>(aux_is_nodal and !do_nodal));
+
+ // Compute number of cells required for Field Solver
+#ifdef WARPX_USE_PSATD
+ ng_FieldSolver = ng_alloc_EB;
+ ng_FieldSolverF = ng_alloc_EB;
+#else
+ ng_FieldSolver = IntVect(AMREX_D_DECL(1,1,1));
+ ng_FieldSolverF = IntVect(AMREX_D_DECL(1,1,1));
+#endif
+ ng_FieldSolver = ng_FieldSolver.min(ng_alloc_EB);
+
+ // Compute number of cells required for Field Gather
+ int FGcell[4] = {0,1,1,2}; // Index is nox
+ IntVect ng_FieldGather_noNCI = IntVect(AMREX_D_DECL(FGcell[nox],FGcell[nox],FGcell[nox]));
+ // Add one cell if momentum_conserving gather in a staggered-field simulation
+ ng_FieldGather_noNCI += ng_Extra;
+ // Not sure why, but need one extra guard cell when using MR
+ if (max_level >= 1) ng_FieldGather_noNCI += ng_Extra;
+ ng_FieldGather_noNCI = ng_FieldGather_noNCI.min(ng_alloc_EB);
+ // If NCI filter, add guard cells in the z direction
+ IntVect ng_NCIFilter = IntVect::TheZeroVector();
+ if (do_fdtd_nci_corr)
+ ng_NCIFilter[AMREX_SPACEDIM-1] = NCIGodfreyFilter::m_stencil_width;
+ // Note: communications of guard cells for bilinear filter are handled
+ // separately.
+ ng_FieldGather = ng_FieldGather_noNCI + ng_NCIFilter;
+
+ // Guard cells for auxiliary grid.
+ // Not sure why there is a 2* here...
+ ng_UpdateAux = 2*ng_FieldGather_noNCI + ng_NCIFilter;
+
+ // Make sure we do not exchange more guard cells than allocated.
+ ng_FieldGather = ng_FieldGather.min(ng_alloc_EB);
+ ng_UpdateAux = ng_UpdateAux.min(ng_alloc_EB);
+ ng_FieldSolverF = ng_FieldSolverF.min(ng_alloc_F);
+ // Only FillBoundary(ng_FieldGather) is called between consecutive
+ // field solves. So ng_FieldGather must have enough cells
+ // for the field solve too.
+ ng_FieldGather = ng_FieldGather.max(ng_FieldSolver);
+
+ if (do_moving_window){
+ ng_MovingWindow[moving_window_dir] = 1;
+ }
+
+ return nJ_buffer;
+}
diff --git a/Source/Parallelization/Make.package b/Source/Parallelization/Make.package
index 7c3c38627..065556b33 100644
--- a/Source/Parallelization/Make.package
+++ b/Source/Parallelization/Make.package
@@ -1,7 +1,9 @@
CEXE_sources += WarpXComm.cpp
CEXE_sources += WarpXRegrid.cpp
+CEXE_sources += GuardCellManager.cpp
CEXE_headers += WarpXSumGuardCells.H
CEXE_headers += WarpXComm_K.H
+CEXE_headers += GuardCellManager.H
CEXE_headers += WarpXComm.H
INCLUDE_LOCATIONS += $(WARPX_HOME)/Source/Parallelization
diff --git a/Source/Parallelization/WarpXComm.cpp b/Source/Parallelization/WarpXComm.cpp
index b61ae4fc7..2e0cbdfad 100644
--- a/Source/Parallelization/WarpXComm.cpp
+++ b/Source/Parallelization/WarpXComm.cpp
@@ -321,41 +321,41 @@ WarpX::UpdateAuxilaryDataSameType ()
}
void
-WarpX::FillBoundaryB ()
+WarpX::FillBoundaryB (IntVect ng, IntVect ng_extra_fine)
{
for (int lev = 0; lev <= finest_level; ++lev)
{
- FillBoundaryB(lev);
+ FillBoundaryB(lev, ng, ng_extra_fine);
}
}
void
-WarpX::FillBoundaryE ()
+WarpX::FillBoundaryE (IntVect ng, IntVect ng_extra_fine)
{
for (int lev = 0; lev <= finest_level; ++lev)
{
- FillBoundaryE(lev);
+ FillBoundaryE(lev, ng, ng_extra_fine);
}
}
void
-WarpX::FillBoundaryF ()
+WarpX::FillBoundaryF (IntVect ng)
{
for (int lev = 0; lev <= finest_level; ++lev)
{
- FillBoundaryF(lev);
+ FillBoundaryF(lev, ng);
}
}
void
-WarpX::FillBoundaryE(int lev)
+WarpX::FillBoundaryE(int lev, IntVect ng, IntVect ng_extra_fine)
{
- FillBoundaryE(lev, PatchType::fine);
- if (lev > 0) FillBoundaryE(lev, PatchType::coarse);
+ FillBoundaryE(lev, PatchType::fine, ng+ng_extra_fine);
+ if (lev > 0) FillBoundaryE(lev, PatchType::coarse, ng);
}
void
-WarpX::FillBoundaryE (int lev, PatchType patch_type)
+WarpX::FillBoundaryE (int lev, PatchType patch_type, IntVect ng)
{
if (patch_type == PatchType::fine)
{
@@ -370,8 +370,12 @@ WarpX::FillBoundaryE (int lev, PatchType patch_type)
}
const auto& period = Geom(lev).periodicity();
- Vector<MultiFab*> mf{Efield_fp[lev][0].get(),Efield_fp[lev][1].get(),Efield_fp[lev][2].get()};
- amrex::FillBoundary(mf, period);
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ ng <= Efield_fp[lev][0]->nGrowVect(),
+ "Error: in FillBoundaryE, requested more guard cells than allocated");
+ Efield_fp[lev][0]->FillBoundary(ng, period);
+ Efield_fp[lev][1]->FillBoundary(ng, period);
+ Efield_fp[lev][2]->FillBoundary(ng, period);
}
else if (patch_type == PatchType::coarse)
{
@@ -386,20 +390,24 @@ WarpX::FillBoundaryE (int lev, PatchType patch_type)
}
const auto& cperiod = Geom(lev-1).periodicity();
- Vector<MultiFab*> mf{Efield_cp[lev][0].get(),Efield_cp[lev][1].get(),Efield_cp[lev][2].get()};
- amrex::FillBoundary(mf, cperiod);
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ ng <= Efield_cp[lev][0]->nGrowVect(),
+ "Error: in FillBoundaryE, requested more guard cells than allocated");
+ Efield_cp[lev][0]->FillBoundary(ng, cperiod);
+ Efield_cp[lev][1]->FillBoundary(ng, cperiod);
+ Efield_cp[lev][2]->FillBoundary(ng, cperiod);
}
}
void
-WarpX::FillBoundaryB (int lev)
+WarpX::FillBoundaryB (int lev, IntVect ng, IntVect ng_extra_fine)
{
- FillBoundaryB(lev, PatchType::fine);
- if (lev > 0) FillBoundaryB(lev, PatchType::coarse);
+ FillBoundaryB(lev, PatchType::fine, ng + ng_extra_fine);
+ if (lev > 0) FillBoundaryB(lev, PatchType::coarse, ng);
}
void
-WarpX::FillBoundaryB (int lev, PatchType patch_type)
+WarpX::FillBoundaryB (int lev, PatchType patch_type, IntVect ng)
{
if (patch_type == PatchType::fine)
{
@@ -413,8 +421,12 @@ WarpX::FillBoundaryB (int lev, PatchType patch_type)
pml[lev]->FillBoundaryB(patch_type);
}
const auto& period = Geom(lev).periodicity();
- Vector<MultiFab*> mf{Bfield_fp[lev][0].get(),Bfield_fp[lev][1].get(),Bfield_fp[lev][2].get()};
- amrex::FillBoundary(mf, period);
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ ng <= Bfield_fp[lev][0]->nGrowVect(),
+ "Error: in FillBoundaryB, requested more guard cells than allocated");
+ Bfield_fp[lev][0]->FillBoundary(ng, period);
+ Bfield_fp[lev][1]->FillBoundary(ng, period);
+ Bfield_fp[lev][2]->FillBoundary(ng, period);
}
else if (patch_type == PatchType::coarse)
{
@@ -428,20 +440,24 @@ WarpX::FillBoundaryB (int lev, PatchType patch_type)
pml[lev]->FillBoundaryB(patch_type);
}
const auto& cperiod = Geom(lev-1).periodicity();
- Vector<MultiFab*> mf{Bfield_cp[lev][0].get(),Bfield_cp[lev][1].get(),Bfield_cp[lev][2].get()};
- amrex::FillBoundary(mf, cperiod);
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ ng <= Bfield_cp[lev][0]->nGrowVect(),
+ "Error: in FillBoundaryB, requested more guard cells than allocated");
+ Bfield_cp[lev][0]->FillBoundary(ng, cperiod);
+ Bfield_cp[lev][1]->FillBoundary(ng, cperiod);
+ Bfield_cp[lev][2]->FillBoundary(ng, cperiod);
}
}
void
-WarpX::FillBoundaryF (int lev)
+WarpX::FillBoundaryF (int lev, IntVect ng)
{
- FillBoundaryF(lev, PatchType::fine);
- if (lev > 0) FillBoundaryF(lev, PatchType::coarse);
+ FillBoundaryF(lev, PatchType::fine, ng);
+ if (lev > 0) FillBoundaryF(lev, PatchType::coarse, ng);
}
void
-WarpX::FillBoundaryF (int lev, PatchType patch_type)
+WarpX::FillBoundaryF (int lev, PatchType patch_type, IntVect ng)
{
if (patch_type == PatchType::fine && F_fp[lev])
{
@@ -453,7 +469,10 @@ WarpX::FillBoundaryF (int lev, PatchType patch_type)
}
const auto& period = Geom(lev).periodicity();
- F_fp[lev]->FillBoundary(period);
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ ng <= F_fp[lev]->nGrowVect(),
+ "Error: in FillBoundaryF, requested more guard cells than allocated");
+ F_fp[lev]->FillBoundary(ng, period);
}
else if (patch_type == PatchType::coarse && F_cp[lev])
{
@@ -465,11 +484,35 @@ WarpX::FillBoundaryF (int lev, PatchType patch_type)
}
const auto& cperiod = Geom(lev-1).periodicity();
- F_cp[lev]->FillBoundary(cperiod);
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ ng <= F_cp[lev]->nGrowVect(),
+ "Error: in FillBoundaryF, requested more guard cells than allocated");
+ F_cp[lev]->FillBoundary(ng, cperiod);
}
}
void
+WarpX::FillBoundaryAux (IntVect ng)
+{
+ for (int lev = 0; lev <= finest_level-1; ++lev)
+ {
+ FillBoundaryAux(lev, ng);
+ }
+}
+
+void
+WarpX::FillBoundaryAux (int lev, IntVect ng)
+{
+ const auto& period = Geom(lev).periodicity();
+ Efield_aux[lev][0]->FillBoundary(ng, period);
+ Efield_aux[lev][1]->FillBoundary(ng, period);
+ Efield_aux[lev][2]->FillBoundary(ng, period);
+ Bfield_aux[lev][0]->FillBoundary(ng, period);
+ Bfield_aux[lev][1]->FillBoundary(ng, period);
+ Bfield_aux[lev][2]->FillBoundary(ng, period);
+}
+
+void
WarpX::SyncCurrent ()
{
BL_PROFILE("SyncCurrent()");
diff --git a/Source/Python/WarpXWrappers.cpp b/Source/Python/WarpXWrappers.cpp
index 3074b1990..ad34d71ee 100644
--- a/Source/Python/WarpXWrappers.cpp
+++ b/Source/Python/WarpXWrappers.cpp
@@ -379,11 +379,11 @@ extern "C"
}
void warpx_FillBoundaryE () {
WarpX& warpx = WarpX::GetInstance();
- warpx.FillBoundaryE ();
+ warpx.FillBoundaryE (warpx.getngE());
}
void warpx_FillBoundaryB () {
WarpX& warpx = WarpX::GetInstance();
- warpx.FillBoundaryB ();
+ warpx.FillBoundaryB (warpx.getngE());
}
void warpx_SyncCurrent () {
WarpX& warpx = WarpX::GetInstance();
diff --git a/Source/Utils/WarpXMovingWindow.cpp b/Source/Utils/WarpXMovingWindow.cpp
index c577da7f3..2c0c6eac9 100644
--- a/Source/Utils/WarpXMovingWindow.cpp
+++ b/Source/Utils/WarpXMovingWindow.cpp
@@ -1,3 +1,4 @@
+#include "GuardCellManager.H"
#include <WarpX.H>
#include <WarpXConst.H>
@@ -28,6 +29,9 @@ WarpX::MoveWindow (bool move_j)
{
if (do_moving_window == 0) return 0;
+ IntVect ng_extra = guard_cells.ng_Extra;
+ IntVect ng_zero = IntVect::TheZeroVector();
+
// Update the continuous position of the moving window,
// and of the plasma injection
moving_window_x += moving_window_v * dt[0];
@@ -99,32 +103,32 @@ WarpX::MoveWindow (bool move_j)
for (int dim = 0; dim < 3; ++dim) {
// Fine grid
- shiftMF(*Bfield_fp[lev][dim], geom[lev], num_shift, dir, B_external_grid[dim]);
- shiftMF(*Efield_fp[lev][dim], geom[lev], num_shift, dir, E_external_grid[dim]);
+ shiftMF(*Bfield_fp[lev][dim], geom[lev], num_shift, dir, ng_extra, B_external_grid[dim]);
+ shiftMF(*Efield_fp[lev][dim], geom[lev], num_shift, dir, ng_extra, E_external_grid[dim]);
if (move_j) {
- shiftMF(*current_fp[lev][dim], geom[lev], num_shift, dir);
+ shiftMF(*current_fp[lev][dim], geom[lev], num_shift, dir, ng_zero);
}
if (do_pml && pml[lev]->ok()) {
const std::array<MultiFab*, 3>& pml_B = pml[lev]->GetB_fp();
const std::array<MultiFab*, 3>& pml_E = pml[lev]->GetE_fp();
- shiftMF(*pml_B[dim], geom[lev], num_shift, dir);
- shiftMF(*pml_E[dim], geom[lev], num_shift, dir);
+ shiftMF(*pml_B[dim], geom[lev], num_shift, dir, ng_extra);
+ shiftMF(*pml_E[dim], geom[lev], num_shift, dir, ng_extra);
}
if (lev > 0) {
// Coarse grid
- shiftMF(*Bfield_cp[lev][dim], geom[lev-1], num_shift_crse, dir, B_external_grid[dim]);
- shiftMF(*Efield_cp[lev][dim], geom[lev-1], num_shift_crse, dir, E_external_grid[dim]);
- shiftMF(*Bfield_aux[lev][dim], geom[lev], num_shift, dir);
- shiftMF(*Efield_aux[lev][dim], geom[lev], num_shift, dir);
+ shiftMF(*Bfield_cp[lev][dim], geom[lev-1], num_shift_crse, dir, ng_zero, B_external_grid[dim]);
+ shiftMF(*Efield_cp[lev][dim], geom[lev-1], num_shift_crse, dir, ng_zero, E_external_grid[dim]);
+ shiftMF(*Bfield_aux[lev][dim], geom[lev], num_shift, dir, ng_zero);
+ shiftMF(*Efield_aux[lev][dim], geom[lev], num_shift, dir, ng_zero);
if (move_j) {
- shiftMF(*current_cp[lev][dim], geom[lev-1], num_shift_crse, dir);
+ shiftMF(*current_cp[lev][dim], geom[lev-1], num_shift_crse, dir, ng_zero);
}
if (do_pml && pml[lev]->ok()) {
const std::array<MultiFab*, 3>& pml_B = pml[lev]->GetB_cp();
const std::array<MultiFab*, 3>& pml_E = pml[lev]->GetE_cp();
- shiftMF(*pml_B[dim], geom[lev-1], num_shift_crse, dir);
- shiftMF(*pml_E[dim], geom[lev-1], num_shift_crse, dir);
+ shiftMF(*pml_B[dim], geom[lev-1], num_shift_crse, dir, ng_extra);
+ shiftMF(*pml_E[dim], geom[lev-1], num_shift_crse, dir, ng_extra);
}
}
}
@@ -132,19 +136,19 @@ WarpX::MoveWindow (bool move_j)
// Shift scalar component F for dive cleaning
if (do_dive_cleaning) {
// Fine grid
- shiftMF(*F_fp[lev], geom[lev], num_shift, dir);
+ shiftMF(*F_fp[lev], geom[lev], num_shift, dir, ng_zero);
if (do_pml && pml[lev]->ok()) {
MultiFab* pml_F = pml[lev]->GetF_fp();
- shiftMF(*pml_F, geom[lev], num_shift, dir);
+ shiftMF(*pml_F, geom[lev], num_shift, dir, ng_extra);
}
if (lev > 0) {
// Coarse grid
- shiftMF(*F_cp[lev], geom[lev-1], num_shift_crse, dir);
+ shiftMF(*F_cp[lev], geom[lev-1], num_shift_crse, dir, ng_zero);
if (do_pml && pml[lev]->ok()) {
MultiFab* pml_F = pml[lev]->GetF_cp();
- shiftMF(*pml_F, geom[lev-1], num_shift_crse, dir);
+ shiftMF(*pml_F, geom[lev-1], num_shift_crse, dir, ng_zero);
}
- shiftMF(*rho_cp[lev], geom[lev-1], num_shift_crse, dir);
+ shiftMF(*rho_cp[lev], geom[lev-1], num_shift_crse, dir, ng_zero);
}
}
@@ -152,10 +156,10 @@ WarpX::MoveWindow (bool move_j)
if (move_j) {
if (rho_fp[lev]){
// Fine grid
- shiftMF(*rho_fp[lev], geom[lev], num_shift, dir);
+ shiftMF(*rho_fp[lev], geom[lev], num_shift, dir, ng_zero);
if (lev > 0){
// Coarse grid
- shiftMF(*rho_cp[lev], geom[lev-1], num_shift_crse, dir);
+ shiftMF(*rho_cp[lev], geom[lev-1], num_shift_crse, dir, ng_zero);
}
}
}
@@ -204,7 +208,7 @@ WarpX::MoveWindow (bool move_j)
void
WarpX::shiftMF (MultiFab& mf, const Geometry& geom, int num_shift, int dir,
- amrex::Real external_field)
+ IntVect ng_extra, amrex::Real external_field)
{
BL_PROFILE("WarpX::shiftMF()");
const BoxArray& ba = mf.boxArray();
@@ -216,7 +220,17 @@ WarpX::shiftMF (MultiFab& mf, const Geometry& geom, int num_shift, int dir,
MultiFab tmpmf(ba, dm, nc, ng);
MultiFab::Copy(tmpmf, mf, 0, 0, nc, ng);
- tmpmf.FillBoundary(geom.periodicity());
+
+ // Not sure why this is needed, but it is...
+ IntVect ng_mw = IntVect::TheUnitVector();
+ // Enough guard cells in the MW direction
+ ng_mw[dir] = num_shift;
+ // Add the extra cell (if momentum-conserving gather with staggered field solve)
+ ng_mw += ng_extra;
+ // Make sure we don't exceed number of guard cells allocated
+ ng_mw = ng_mw.min(ng);
+ // Fill guard cells.
+ tmpmf.FillBoundary(ng_mw, geom.periodicity());
// Make a box that covers the region that the window moved into
const IndexType& typ = ba.ixType();
diff --git a/Source/WarpX.H b/Source/WarpX.H
index 7fa93c156..eec397fd1 100644
--- a/Source/WarpX.H
+++ b/Source/WarpX.H
@@ -25,6 +25,8 @@
#include <AMReX_Interpolater.H>
#include <AMReX_FillPatchUtil.H>
+#include "GuardCellManager.H"
+
#ifdef _OPENMP
# include <omp.h>
#endif
@@ -74,7 +76,7 @@ public:
MultiParticleContainer& GetPartContainer () { return *mypc; }
static void shiftMF(amrex::MultiFab& mf, const amrex::Geometry& geom, int num_shift, int dir,
- amrex::Real external_field = 0.);
+ amrex::IntVect ng_extra, amrex::Real external_field = 0.);
static void GotoNextLine (std::istream& is);
@@ -217,12 +219,14 @@ public:
void UpdateAuxilaryDataSameType ();
// Fill boundary cells including coarse/fine boundaries
- void FillBoundaryB ();
- void FillBoundaryE ();
- void FillBoundaryF ();
- void FillBoundaryE (int lev);
- void FillBoundaryB (int lev);
- void FillBoundaryF (int lev);
+ void FillBoundaryB (amrex::IntVect ng, amrex::IntVect ng_extra_fine=amrex::IntVect::TheZeroVector());
+ void FillBoundaryE (amrex::IntVect ng, amrex::IntVect ng_extra_fine=amrex::IntVect::TheZeroVector());
+ void FillBoundaryF (amrex::IntVect ng);
+ void FillBoundaryAux (amrex::IntVect ng);
+ void FillBoundaryE (int lev, amrex::IntVect ng, amrex::IntVect ng_extra_fine=amrex::IntVect::TheZeroVector());
+ void FillBoundaryB (int lev, amrex::IntVect ng, amrex::IntVect ng_extra_fine=amrex::IntVect::TheZeroVector());
+ void FillBoundaryF (int lev, amrex::IntVect ng);
+ void FillBoundaryAux (int lev, amrex::IntVect ng);
void SyncCurrent ();
void SyncRho ();
@@ -306,6 +310,8 @@ public:
const std::array<const amrex::MultiFab*, 3>& B,
const std::array<amrex::Real,3>& dx, int ngrow);
+ const amrex::IntVect getngE() const { return guard_cells.ng_alloc_EB; };
+ const amrex::IntVect getngF() const { return guard_cells.ng_alloc_F; };
void InitSpaceChargeField (WarpXParticleContainer& pc);
void computePhi (const amrex::Vector<std::unique_ptr<amrex::MultiFab> >& rho,
@@ -356,9 +362,9 @@ private:
///
void EvolveEM(int numsteps);
- void FillBoundaryB (int lev, PatchType patch_type);
- void FillBoundaryE (int lev, PatchType patch_type);
- void FillBoundaryF (int lev, PatchType patch_type);
+ void FillBoundaryB (int lev, PatchType patch_type, amrex::IntVect ng);
+ void FillBoundaryE (int lev, PatchType patch_type, amrex::IntVect ng);
+ void FillBoundaryF (int lev, PatchType patch_type, amrex::IntVect ng);
void OneStep_nosub (amrex::Real t);
void OneStep_sub1 (amrex::Real t);
@@ -447,7 +453,8 @@ private:
void AllocLevelMFs (int lev, const amrex::BoxArray& ba, const amrex::DistributionMapping& dm,
const amrex::IntVect& ngE, const amrex::IntVect& ngJ,
- const amrex::IntVect& ngRho, int ngF);
+ const amrex::IntVect& ngRho, int ngF, const amrex::IntVect& ngextra,
+ const bool aux_is_nodal);
amrex::Vector<int> istep; // which step?
amrex::Vector<int> nsubsteps; // how many substeps on each level?
@@ -585,6 +592,8 @@ private:
bool is_synchronized = true;
+ guardCellManager guard_cells;
+
//Slice Parameters
int slice_max_grid_size;
int slice_plot_int = -1;
@@ -610,18 +619,19 @@ private:
amrex::Vector< std::unique_ptr<amrex::MultiFab> > rho_cp_fft;
#endif
+ bool fft_hybrid_mpi_decomposition = false;
+ int nox_fft = 16;
+ int noy_fft = 16;
+ int noz_fft = 16;
+
#ifdef WARPX_USE_PSATD
private:
void EvolvePSATD (int numsteps);
void PushPSATD (amrex::Real dt);
void PushPSATD_localFFT (int lev, amrex::Real dt);
- bool fft_hybrid_mpi_decomposition = false;
int ngroups_fft = 4;
int fftw_plan_measure = 1;
- int nox_fft = 16;
- int noy_fft = 16;
- int noz_fft = 16;
amrex::Vector<std::unique_ptr<SpectralSolver>> spectral_solver_fp;
amrex::Vector<std::unique_ptr<SpectralSolver>> spectral_solver_cp;
diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp
index 53728b54f..3d1650617 100644
--- a/Source/WarpX.cpp
+++ b/Source/WarpX.cpp
@@ -717,58 +717,22 @@ WarpX::ClearLevel (int lev)
void
WarpX::AllocLevelData (int lev, const BoxArray& ba, const DistributionMapping& dm)
{
- // When using subcycling, the particles on the fine level perform two pushes
- // before being redistributed ; therefore, we need one extra guard cell
- // (the particles may move by 2*c*dt)
- const int ngx_tmp = (maxLevel() > 0 && do_subcycling == 1) ? WarpX::nox+1 : WarpX::nox;
- const int ngy_tmp = (maxLevel() > 0 && do_subcycling == 1) ? WarpX::noy+1 : WarpX::noy;
- const int ngz_tmp = (maxLevel() > 0 && do_subcycling == 1) ? WarpX::noz+1 : WarpX::noz;
-
- // Ex, Ey, Ez, Bx, By, and Bz have the same number of ghost cells.
- // jx, jy, jz and rho have the same number of ghost cells.
- // E and B have the same number of ghost cells as j and rho if NCI filter is not used,
- // but different number of ghost cells in z-direction if NCI filter is used.
- // The number of cells should be even, in order to easily perform the
- // interpolation from coarse grid to fine grid.
- int ngx = (ngx_tmp % 2) ? ngx_tmp+1 : ngx_tmp; // Always even number
- int ngy = (ngy_tmp % 2) ? ngy_tmp+1 : ngy_tmp; // Always even number
- int ngz_nonci = (ngz_tmp % 2) ? ngz_tmp+1 : ngz_tmp; // Always even number
- int ngz;
- if (WarpX::use_fdtd_nci_corr) {
- int ng = ngz_tmp + NCIGodfreyFilter::m_stencil_width;
- ngz = (ng % 2) ? ng+1 : ng;
- } else {
- ngz = ngz_nonci;
- }
- // J is only interpolated from fine to coarse (not coarse to fine)
- // and therefore does not need to be even.
- int ngJx = ngx_tmp;
- int ngJy = ngy_tmp;
- int ngJz = ngz_tmp;
-
- // When calling the moving window (with one level of refinement), we shift
- // the fine grid by 2 cells ; therefore, we need at least 2 guard cells
- // on level 1. This may not be necessary for level 0.
- if (do_moving_window) {
- ngx = std::max(ngx,2);
- ngy = std::max(ngy,2);
- ngz = std::max(ngz,2);
- ngJx = std::max(ngJx,2);
- ngJy = std::max(ngJy,2);
- ngJz = std::max(ngJz,2);
- }
-
-#if (AMREX_SPACEDIM == 3)
- IntVect ngE(ngx,ngy,ngz);
- IntVect ngJ(ngJx,ngJy,ngJz);
-#elif (AMREX_SPACEDIM == 2)
- IntVect ngE(ngx,ngz);
- IntVect ngJ(ngJx,ngJz);
-#endif
+ bool aux_is_nodal = (field_gathering_algo == GatheringAlgo::MomentumConserving);
- IntVect ngRho = ngJ+1; //One extra ghost cell, so that it's safe to deposit charge density
- // after pushing particle.
+ int nJ_buffer = guard_cells.Init(
+ do_subcycling,
+ WarpX::use_fdtd_nci_corr,
+ do_nodal,
+ do_moving_window,
+ fft_hybrid_mpi_decomposition,
+ aux_is_nodal,
+ moving_window_dir,
+ WarpX::nox,
+ nox_fft, noy_fft, noz_fft,
+ NCIGodfreyFilter::m_stencil_width,
+ maxwell_fdtd_solver_id,
+ maxLevel());
if (mypc->nSpeciesDepositOnMainGrid() && n_current_deposition_buffer == 0) {
n_current_deposition_buffer = 1;
@@ -779,54 +743,22 @@ WarpX::AllocLevelData (int lev, const BoxArray& ba, const DistributionMapping& d
}
if (n_current_deposition_buffer < 0) {
- n_current_deposition_buffer = ngJ.max();
+ n_current_deposition_buffer = nJ_buffer;
}
if (n_field_gather_buffer < 0) {
// Field gather buffer should be larger than current deposition buffers
n_field_gather_buffer = n_current_deposition_buffer + 1;
}
- int ngF = (do_moving_window) ? 2 : 0;
- // CKC solver requires one additional guard cell
- if (maxwell_fdtd_solver_id == 1) ngF = std::max( ngF, 1 );
-
-#ifdef WARPX_USE_PSATD
- if (fft_hybrid_mpi_decomposition == false){
- // All boxes should have the same number of guard cells
- // (to avoid temporary parallel copies)
- // Thus take the max of the required number of guards for each field
- // Also: the number of guard cell should be enough to contain
- // the stencil of the FFT solver. Here, this number (`ngFFT`)
- // is determined *empirically* to be the order of the solver
- // for nodal, and half the order of the solver for staggered.
- IntVect ngFFT;
- if (do_nodal) {
- ngFFT = IntVect(AMREX_D_DECL(nox_fft, noy_fft, noz_fft));
- } else {
- ngFFT = IntVect(AMREX_D_DECL(nox_fft/2, noy_fft/2, noz_fft/2));
- }
- for (int i_dim=0; i_dim<AMREX_SPACEDIM; i_dim++ ){
- int ng_required = ngFFT[i_dim];
- // Get the max
- ng_required = std::max( ng_required, ngE[i_dim] );
- ng_required = std::max( ng_required, ngJ[i_dim] );
- ng_required = std::max( ng_required, ngRho[i_dim] );
- ng_required = std::max( ng_required, ngF );
- // Set the guard cells to this max
- ngE[i_dim] = ng_required;
- ngJ[i_dim] = ng_required;
- ngRho[i_dim] = ng_required;
- ngF = ng_required;
- }
- }
-#endif
-
- AllocLevelMFs(lev, ba, dm, ngE, ngJ, ngRho, ngF);
+ AllocLevelMFs(lev, ba, dm, guard_cells.ng_alloc_EB, guard_cells.ng_alloc_J,
+ guard_cells.ng_alloc_Rho, guard_cells.ng_alloc_F_int,
+ guard_cells.ng_Extra, aux_is_nodal);
}
void
WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm,
- const IntVect& ngE, const IntVect& ngJ, const IntVect& ngRho, int ngF)
+ const IntVect& ngE, const IntVect& ngJ, const IntVect& ngRho, int ngF,
+ const IntVect& ngextra, const bool aux_is_nodal)
{
#if defined WARPX_DIM_RZ
@@ -838,9 +770,6 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm
ncomps = n_rz_azimuthal_modes*2 - 1;
#endif
- bool aux_is_nodal = (field_gathering_algo == GatheringAlgo::MomentumConserving);
- IntVect ngextra(static_cast<int>(aux_is_nodal and !do_nodal));
-
//
// The fine patch
//