diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Evolve/WarpXEvolveEM.cpp | 115 | ||||
-rw-r--r-- | Source/Parallelization/GuardCellManager.H | 42 | ||||
-rw-r--r-- | Source/Parallelization/GuardCellManager.cpp | 160 | ||||
-rw-r--r-- | Source/Parallelization/Make.package | 2 | ||||
-rw-r--r-- | Source/Parallelization/WarpXComm.cpp | 99 | ||||
-rw-r--r-- | Source/Python/WarpXWrappers.cpp | 4 | ||||
-rw-r--r-- | Source/Utils/WarpXMovingWindow.cpp | 56 | ||||
-rw-r--r-- | Source/WarpX.H | 40 | ||||
-rw-r--r-- | Source/WarpX.cpp | 111 |
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 // |