aboutsummaryrefslogtreecommitdiff
path: root/Source/WarpX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WarpX.cpp')
-rw-r--r--Source/WarpX.cpp201
1 files changed, 123 insertions, 78 deletions
diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp
index 0f57cbee1..1e48d659d 100644
--- a/Source/WarpX.cpp
+++ b/Source/WarpX.cpp
@@ -193,7 +193,7 @@ IntVect WarpX::filter_npass_each_dir(1);
int WarpX::n_field_gather_buffer = -1;
int WarpX::n_current_deposition_buffer = -1;
-bool WarpX::do_nodal = false;
+short WarpX::grid_type;
amrex::IntVect m_rho_nodal_flag;
int WarpX::do_similar_dm_pml = 1;
@@ -908,9 +908,12 @@ WarpX::ReadParameters ()
pp_warpx.query("do_dynamic_scheduling", do_dynamic_scheduling);
- pp_warpx.query("do_nodal", do_nodal);
+ // Integer that corresponds to the type of grid used in the simulation
+ // (collocated, staggered, hybrid)
+ grid_type = GetAlgorithmInteger(pp_warpx, "grid_type");
+
// Use same shape factors in all directions, for gathering
- if (do_nodal) galerkin_interpolation = false;
+ if (grid_type == GridType::Collocated) galerkin_interpolation = false;
#ifdef WARPX_DIM_RZ
// Only needs to be set with WARPX_DIM_RZ, otherwise defaults to 1
@@ -919,13 +922,47 @@ WarpX::ReadParameters ()
"The number of azimuthal modes (n_rz_azimuthal_modes) must be at least 1");
#endif
- // If true, the current is deposited on a nodal grid and centered onto a staggered grid.
- // Setting warpx.do_current_centering = 1 makes sense only if warpx.do_nodal = 0. Instead,
- // if warpx.do_nodal = 1, Maxwell's equations are solved on a nodal grid and the current
- // should not be centered onto a staggered grid.
- if (WarpX::do_nodal == 0)
+ // Set default parameters with hybrid grid (parsed later below)
+ if (grid_type == GridType::Hybrid)
+ {
+ // Finite-order centering of fields (staggered to nodal)
+ // Default field gathering algorithm will be set below
+ field_centering_nox = 8;
+ field_centering_noy = 8;
+ field_centering_noz = 8;
+ // Finite-order centering of currents (nodal to staggered)
+ do_current_centering = true;
+ current_centering_nox = 8;
+ current_centering_noy = 8;
+ current_centering_noz = 8;
+ }
+
+ // If true, the current is deposited on a nodal grid and centered onto
+ // a staggered grid. Setting warpx.do_current_centering=1 makes sense
+ // only if warpx.grid_type=hybrid. Instead, if warpx.grid_type=nodal or
+ // warpx.grid_type=staggered, Maxwell's equations are solved either on a
+ // collocated grid or on a staggered grid without current centering.
+ pp_warpx.query("do_current_centering", do_current_centering);
+ if (do_current_centering)
{
- pp_warpx.query("do_current_centering", do_current_centering);
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
+ grid_type == GridType::Hybrid,
+ "warpx.do_current_centering=1 can be used only with warpx.grid_type=hybrid");
+
+ utils::parser::queryWithParser(
+ pp_warpx, "current_centering_nox", current_centering_nox);
+ utils::parser::queryWithParser(
+ pp_warpx, "current_centering_noy", current_centering_noy);
+ utils::parser::queryWithParser(
+ pp_warpx, "current_centering_noz", current_centering_noz);
+
+ AllocateCenteringCoefficients(device_current_centering_stencil_coeffs_x,
+ device_current_centering_stencil_coeffs_y,
+ device_current_centering_stencil_coeffs_z,
+ current_centering_nox,
+ current_centering_noy,
+ current_centering_noz,
+ grid_type);
}
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
@@ -957,9 +994,9 @@ WarpX::ReadParameters ()
}
if (electromagnetic_solver_id == ElectromagneticSolverAlgo::PSATD) {
- // Force do_nodal=true (that is, not staggered) and
- // use same shape factors in all directions, for gathering
- do_nodal = true;
+ // Force grid_type=collocated (neither staggered nor hybrid)
+ // and use same shape factors in all directions for gathering
+ grid_type = GridType::Collocated;
galerkin_interpolation = false;
}
#endif
@@ -998,12 +1035,40 @@ WarpX::ReadParameters ()
"Vay deposition not implemented with multi-J algorithm");
}
+ // Query algo.field_gathering from input, set field_gathering_algo to
+ // "default" if not found (default defined in Utils/WarpXAlgorithmSelection.cpp)
field_gathering_algo = GetAlgorithmInteger(pp_algo, "field_gathering");
- if (field_gathering_algo == GatheringAlgo::MomentumConserving) {
- // Use same shape factors in all directions, for gathering
- galerkin_interpolation = false;
+
+ // Set default field gathering algorithm for hybrid grids (momentum-conserving)
+ std::string tmp_algo;
+ // - algo.field_gathering not found in the input
+ // - field_gathering_algo set to "default" above
+ // (default defined in Utils/WarpXAlgorithmSelection.cpp)
+ // - reset default value here for hybrid grids
+ if (pp_algo.query("field_gathering", tmp_algo) == false)
+ {
+ if (grid_type == GridType::Hybrid)
+ {
+ field_gathering_algo = GatheringAlgo::MomentumConserving;
+ }
+ }
+ // - algo.field_gathering found in the input
+ // - field_gathering_algo read above and set to user-defined value
+ else
+ {
+ if (grid_type == GridType::Hybrid)
+ {
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
+ field_gathering_algo == GatheringAlgo::MomentumConserving,
+ "Hybrid grid (warpx.grid_type=hybrid) should be used only with "
+ "momentum-conserving field gathering algorithm "
+ "(algo.field_gathering=momentum-conserving)");
+ }
}
+ // Use same shape factors in all directions, for gathering
+ if (field_gathering_algo == GatheringAlgo::MomentumConserving) galerkin_interpolation = false;
+
em_solver_medium = GetAlgorithmInteger(pp_algo, "em_solver_medium");
if (em_solver_medium == MediumForEM::Macroscopic ) {
macroscopic_solver_algo = GetAlgorithmInteger(pp_algo,"macroscopic_sigma_method");
@@ -1106,62 +1171,43 @@ WarpX::ReadParameters ()
ParmParse pp_interpolation("interpolation");
pp_interpolation.query("galerkin_scheme",galerkin_interpolation);
+ }
- // Read order of finite-order centering of fields (staggered to nodal).
- // Read this only if warpx.do_nodal = 0. Instead, if warpx.do_nodal = 1,
- // Maxwell's equations are solved on a nodal grid and the electromagnetic
- // forces are gathered from a nodal grid, hence the fields do not need to
- // be centered onto a nodal grid.
- if (WarpX::field_gathering_algo == GatheringAlgo::MomentumConserving &&
- WarpX::do_nodal == 0)
- {
- utils::parser::queryWithParser(
- pp_interpolation, "field_centering_nox", field_centering_nox);
- utils::parser::queryWithParser(
- pp_interpolation, "field_centering_noy", field_centering_noy);
- utils::parser::queryWithParser(
- pp_interpolation, "field_centering_noz", field_centering_noz);
- }
+ {
+ ParmParse pp_warpx("warpx");
- // Read order of finite-order centering of currents (nodal to staggered)
- if (WarpX::do_current_centering)
+ // If warpx.grid_type=staggered or warpx.grid_type=hybrid,
+ // and algo.field_gathering=momentum-conserving, the fields are solved
+ // on a staggered grid and centered onto a nodal grid for gathering.
+ // Instead, if warpx.grid_type=collocated, the momentum-conserving and
+ // energy conserving field gathering algorithms are equivalent (forces
+ // gathered from the collocated grid) and no fields centering occurs.
+ if (WarpX::field_gathering_algo == GatheringAlgo::MomentumConserving &&
+ WarpX::grid_type != GridType::Collocated)
{
utils::parser::queryWithParser(
- pp_interpolation, "current_centering_nox", current_centering_nox);
+ pp_warpx, "field_centering_nox", field_centering_nox);
utils::parser::queryWithParser(
- pp_interpolation, "current_centering_noy", current_centering_noy);
+ pp_warpx, "field_centering_noy", field_centering_noy);
utils::parser::queryWithParser(
- pp_interpolation, "current_centering_noz", current_centering_noz);
- }
-
- // Finite-order centering is not implemented with mesh refinement
- // (note that when WarpX::do_nodal = 1 finite-order centering is not used anyways)
- if (maxLevel() > 0 && WarpX::do_nodal == 0)
- {
- WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
- field_centering_nox == 2 && field_centering_noy == 2 && field_centering_noz == 2,
- "High-order centering of fields (order > 2) is not implemented with mesh refinement");
- }
+ pp_warpx, "field_centering_noz", field_centering_noz);
- if (WarpX::field_gathering_algo == GatheringAlgo::MomentumConserving &&
- WarpX::do_nodal == 0)
- {
AllocateCenteringCoefficients(device_field_centering_stencil_coeffs_x,
device_field_centering_stencil_coeffs_y,
device_field_centering_stencil_coeffs_z,
field_centering_nox,
field_centering_noy,
- field_centering_noz);
+ field_centering_noz,
+ grid_type);
}
- if (WarpX::do_current_centering)
+ // Finite-order centering is not implemented with mesh refinement
+ // (note that when warpx.grid_type=collocated, finite-order centering is not used anyways)
+ if (maxLevel() > 0 && WarpX::grid_type != GridType::Collocated)
{
- AllocateCenteringCoefficients(device_current_centering_stencil_coeffs_x,
- device_current_centering_stencil_coeffs_y,
- device_current_centering_stencil_coeffs_z,
- current_centering_nox,
- current_centering_noy,
- current_centering_noz);
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
+ field_centering_nox == 2 && field_centering_noy == 2 && field_centering_noz == 2,
+ "High-order centering of fields (order > 2) is not implemented with mesh refinement");
}
}
@@ -1805,7 +1851,7 @@ WarpX::AllocLevelData (int lev, const BoxArray& ba, const DistributionMapping& d
dx,
do_subcycling,
WarpX::use_fdtd_nci_corr,
- do_nodal,
+ grid_type,
do_moving_window,
moving_window_dir,
WarpX::nox,
@@ -1920,7 +1966,7 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm
G_nodal_flag = amrex::IntVect::TheCellVector();
// Overwrite nodal flags if necessary
- if (do_nodal) {
+ if (grid_type == GridType::Collocated) {
Ex_nodal_flag = IntVect::TheNodeVector();
Ey_nodal_flag = IntVect::TheNodeVector();
Ez_nodal_flag = IntVect::TheNodeVector();
@@ -2171,13 +2217,13 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm
#endif
} // ElectromagneticSolverAlgo::PSATD
else {
- m_fdtd_solver_fp[lev] = std::make_unique<FiniteDifferenceSolver>(electromagnetic_solver_id, dx, do_nodal);
+ m_fdtd_solver_fp[lev] = std::make_unique<FiniteDifferenceSolver>(electromagnetic_solver_id, dx, grid_type);
}
//
// The Aux patch (i.e., the full solution)
//
- if (aux_is_nodal and !do_nodal)
+ if (aux_is_nodal and grid_type != GridType::Collocated)
{
// Create aux multifabs on Nodal Box Array
BoxArray const nba = amrex::convert(ba,IntVect::TheNodeVector());
@@ -2266,11 +2312,11 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm
if (do_divb_cleaning)
{
- if (do_nodal)
+ if (grid_type == GridType::Collocated)
{
AllocInitMultiFab(G_cp[lev], amrex::convert(cba, IntVect::TheUnitVector()), dm, ncomps, ngG, tag("G_cp"), 0.0_rt);
}
- else // do_nodal = 0
+ else // grid_type=staggered or grid_type=hybrid
{
AllocInitMultiFab(G_cp[lev], amrex::convert(cba, IntVect::TheZeroVector()), dm, ncomps, ngG, tag("G_cp"), 0.0_rt);
}
@@ -2314,7 +2360,7 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm
} // ElectromagneticSolverAlgo::PSATD
else {
m_fdtd_solver_cp[lev] = std::make_unique<FiniteDifferenceSolver>(electromagnetic_solver_id, cdx,
- do_nodal);
+ grid_type);
}
}
@@ -2401,7 +2447,7 @@ void WarpX::AllocLevelSpectralSolverRZ (amrex::Vector<std::unique_ptr<SpectralSo
dm,
n_rz_azimuthal_modes,
noz_fft,
- do_nodal,
+ grid_type,
m_v_galilean,
dx_vect,
solver_dt,
@@ -2455,7 +2501,7 @@ void WarpX::AllocLevelSpectralSolver (amrex::Vector<std::unique_ptr<SpectralSolv
nox_fft,
noy_fft,
noz_fft,
- do_nodal,
+ grid_type,
m_v_galilean,
m_v_comoving,
dx_vect,
@@ -2557,9 +2603,8 @@ WarpX::ComputeDivB (amrex::MultiFab& divB, int const dcomp,
const std::array<const amrex::MultiFab* const, 3>& B,
const std::array<amrex::Real,3>& dx)
{
- WARPX_ALWAYS_ASSERT_WITH_MESSAGE(!do_nodal,
- "ComputeDivB not implemented with do_nodal."
- "Shouldn't be too hard to make it general with class FiniteDifferenceSolver");
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(grid_type != GridType::Collocated,
+ "ComputeDivB not implemented with warpx.grid_type=Collocated.");
Real dxinv = 1._rt/dx[0], dyinv = 1._rt/dx[1], dzinv = 1._rt/dx[2];
@@ -2595,9 +2640,8 @@ WarpX::ComputeDivB (amrex::MultiFab& divB, int const dcomp,
const std::array<const amrex::MultiFab* const, 3>& B,
const std::array<amrex::Real,3>& dx, IntVect const ngrow)
{
- WARPX_ALWAYS_ASSERT_WITH_MESSAGE(!do_nodal,
- "ComputeDivB not implemented with do_nodal."
- "Shouldn't be too hard to make it general with class FiniteDifferenceSolver");
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(grid_type != GridType::Collocated,
+ "ComputeDivB not implemented with warpx.grid_type=collocated.");
Real dxinv = 1._rt/dx[0], dyinv = 1._rt/dx[1], dzinv = 1._rt/dx[2];
@@ -2795,7 +2839,7 @@ WarpX::BuildBufferMasksInBox ( const amrex::Box tbx, amrex::IArrayBox &buffer_ma
#endif
}
-amrex::Vector<amrex::Real> WarpX::getFornbergStencilCoefficients(const int n_order, const bool nodal)
+amrex::Vector<amrex::Real> WarpX::getFornbergStencilCoefficients(const int n_order, const short a_grid_type)
{
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(n_order % 2 == 0, "n_order must be even");
@@ -2807,8 +2851,8 @@ amrex::Vector<amrex::Real> WarpX::getFornbergStencilCoefficients(const int n_ord
// an overflow when evaluated numerically. One way to avoid the overflow is
// to calculate the coefficients by recurrence.
- // Coefficients for nodal (centered) finite-difference approximation
- if (nodal == true)
+ // Coefficients for collocated (nodal) finite-difference approximation
+ if (a_grid_type == GridType::Collocated)
{
// First coefficient
coeffs.at(0) = m * 2. / (m+1);
@@ -2856,7 +2900,8 @@ void WarpX::AllocateCenteringCoefficients (amrex::Gpu::DeviceVector<amrex::Real>
amrex::Gpu::DeviceVector<amrex::Real>& device_centering_stencil_coeffs_z,
const int centering_nox,
const int centering_noy,
- const int centering_noz)
+ const int centering_noz,
+ const short a_grid_type)
{
// Vectors of Fornberg stencil coefficients
amrex::Vector<amrex::Real> Fornberg_stencil_coeffs_x;
@@ -2868,9 +2913,9 @@ void WarpX::AllocateCenteringCoefficients (amrex::Gpu::DeviceVector<amrex::Real>
amrex::Vector<amrex::Real> host_centering_stencil_coeffs_y;
amrex::Vector<amrex::Real> host_centering_stencil_coeffs_z;
- Fornberg_stencil_coeffs_x = getFornbergStencilCoefficients(centering_nox, false);
- Fornberg_stencil_coeffs_y = getFornbergStencilCoefficients(centering_noy, false);
- Fornberg_stencil_coeffs_z = getFornbergStencilCoefficients(centering_noz, false);
+ Fornberg_stencil_coeffs_x = getFornbergStencilCoefficients(centering_nox, a_grid_type);
+ Fornberg_stencil_coeffs_y = getFornbergStencilCoefficients(centering_noy, a_grid_type);
+ Fornberg_stencil_coeffs_z = getFornbergStencilCoefficients(centering_noz, a_grid_type);
host_centering_stencil_coeffs_x.resize(centering_nox);
host_centering_stencil_coeffs_y.resize(centering_noy);