Skip to content

Commit 98a14f2

Browse files
Flux injection from EB: Pick a random point instead of the centroid (#5493)
Co-authored-by: Remi Lehe <remi.lehe@normalesup.org>
1 parent ceb172e commit 98a14f2

11 files changed

+72
-82
lines changed

Examples/Tests/flux_injection/CMakeLists.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ add_warpx_test(
2626
3 # dims
2727
2 # nprocs
2828
inputs_test_3d_flux_injection_from_eb # inputs
29-
"analysis_flux_injection_from_eb.py diags/diag1000010" # analysis
30-
"analysis_default_regression.py --path diags/diag1000010" # checksum
29+
"analysis_flux_injection_from_eb.py diags/diag1000020" # analysis
30+
"analysis_default_regression.py --path diags/diag1000020" # checksum
3131
OFF # dependency
3232
)
3333

@@ -36,8 +36,8 @@ add_warpx_test(
3636
RZ # dims
3737
2 # nprocs
3838
inputs_test_rz_flux_injection_from_eb # inputs
39-
"analysis_flux_injection_from_eb.py diags/diag1000010" # analysis
40-
"analysis_default_regression.py --path diags/diag1000010" # checksum
39+
"analysis_flux_injection_from_eb.py diags/diag1000020" # analysis
40+
"analysis_default_regression.py --path diags/diag1000020" # checksum
4141
OFF # dependency
4242
)
4343

@@ -46,7 +46,7 @@ add_warpx_test(
4646
2 # dims
4747
2 # nprocs
4848
inputs_test_2d_flux_injection_from_eb # inputs
49-
"analysis_flux_injection_from_eb.py diags/diag1000010" # analysis
50-
"analysis_default_regression.py --path diags/diag1000010" # checksum
49+
"analysis_flux_injection_from_eb.py diags/diag1000020" # analysis
50+
"analysis_default_regression.py --path diags/diag1000020" # checksum
5151
OFF # dependency
5252
)

Examples/Tests/flux_injection/analysis_flux_injection_from_eb.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ def compare_gaussian_flux(u, w, u_th, u_m, label=""):
147147
wy = nz * vx - nx * vz
148148
wz = nx * vy - ny * vx
149149
u_perp2 = ux * wx + uy * wy + uz * wz
150-
compare_gaussian(u_perp2, w, u_th=0.01, label="u_perp")
150+
compare_gaussian(u_perp2, w, u_th=0.01, label="u_perp2")
151151

152+
plt.legend()
152153
plt.tight_layout()
153154
plt.savefig("Distribution.png")

Examples/Tests/flux_injection/inputs_base_from_eb

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Maximum number of time steps
2-
max_step = 10
2+
max_step = 20
33

44
# The lo and hi ends of grids are multipliers of blocking factor
55
amr.blocking_factor = 8
@@ -13,7 +13,7 @@ amr.max_level = 0
1313

1414
# Deactivate Maxwell solver
1515
algo.maxwell_solver = none
16-
warpx.const_dt = 1e-9
16+
warpx.const_dt = 0.5e-9
1717

1818
# Embedded boundary
1919
warpx.eb_implicit_function = "-(x**2+y**2+z**2-2**2)"

Examples/Tests/flux_injection/inputs_test_2d_flux_injection_from_eb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FILE = inputs_base_from_eb
22

33
# number of grid points
4-
amr.n_cell = 16 16
4+
amr.n_cell = 32 32
55

66
# Geometry
77
geometry.dims = 2

Examples/Tests/flux_injection/inputs_test_3d_flux_injection_from_eb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FILE = inputs_base_from_eb
22

33
# number of grid points
4-
amr.n_cell = 16 16 16
4+
amr.n_cell = 32 32 32
55

66
# Geometry
77
geometry.dims = 3

Examples/Tests/flux_injection/inputs_test_rz_flux_injection_from_eb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FILE = inputs_base_from_eb
22

33
# number of grid points
4-
amr.n_cell = 8 16
4+
amr.n_cell = 16 32
55

66
# Geometry
77
geometry.dims = RZ
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"lev=0": {},
33
"electron": {
4-
"particle_momentum_x": 3.4911323396038835e-19,
5-
"particle_momentum_y": 2.680312173420972e-20,
6-
"particle_momentum_z": 3.4918430443688734e-19,
7-
"particle_position_x": 17950.08139982036,
8-
"particle_position_y": 17949.47183079554,
9-
"particle_weight": 6.269e-08
4+
"particle_momentum_x": 1.4013860393698154e-18,
5+
"particle_momentum_y": 1.0934049057929508e-19,
6+
"particle_momentum_z": 1.4066623146535866e-18,
7+
"particle_position_x": 72129.9049362857,
8+
"particle_position_y": 72178.76505490103,
9+
"particle_weight": 6.279375e-08
1010
}
1111
}
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"lev=0": {},
33
"electron": {
4-
"particle_momentum_x": 2.1855512033870577e-18,
5-
"particle_momentum_y": 2.1826030840183147e-18,
6-
"particle_momentum_z": 2.181852403122796e-18,
7-
"particle_position_x": 111042.81925863726,
8-
"particle_position_y": 111012.52928910403,
9-
"particle_position_z": 111015.90903542604,
10-
"particle_weight": 2.4775750000000003e-07
4+
"particle_momentum_x": 1.7587772989573373e-17,
5+
"particle_momentum_y": 1.7608560965806728e-17,
6+
"particle_momentum_z": 1.7596701993624562e-17,
7+
"particle_position_x": 902783.9285213391,
8+
"particle_position_y": 902981.7980528818,
9+
"particle_position_z": 902777.1246066706,
10+
"particle_weight": 2.503818749999996e-07
1111
}
12-
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"lev=0": {},
33
"electron": {
4-
"particle_momentum_x": 3.3665608248716305e-19,
5-
"particle_momentum_y": 3.392690322852239e-19,
6-
"particle_momentum_z": 5.254577143779578e-19,
7-
"particle_position_x": 26933.772112044953,
8-
"particle_position_y": 26926.994273876346,
9-
"particle_theta": 29492.77423173835,
10-
"particle_weight": 2.4953304765944705e-07
4+
"particle_momentum_x": 1.3547613622259754e-18,
5+
"particle_momentum_y": 1.3539614160696825e-18,
6+
"particle_momentum_z": 2.102305484242805e-18,
7+
"particle_position_x": 108281.74349700565,
8+
"particle_position_y": 108222.91506078152,
9+
"particle_theta": 118597.06004310239,
10+
"particle_weight": 2.5087578786544294e-07
1111
}
12-
}
12+
}

Source/Particles/AddPlasmaUtilities.H

+18-21
Original file line numberDiff line numberDiff line change
@@ -111,28 +111,24 @@ AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
111111
amrex::Real compute_scale_fac_area_eb (
112112
const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dx,
113113
const amrex::Real num_ppc_real,
114-
amrex::Array4<const amrex::Real> const& eb_bnd_normal_arr,
115-
int i, int j, int k ) {
114+
AMREX_D_DECL(const amrex::Real n0,
115+
const amrex::Real n1,
116+
const amrex::Real n2)) {
116117
using namespace amrex::literals;
117118
// Scale particle weight by the area of the emitting surface, within one cell
118119
// By definition, eb_bnd_area_arr is normalized (unitless).
119120
// Here we undo the normalization (i.e. multiply by the surface used for normalization in amrex:
120121
// see https://amrex-codes.github.io/amrex/docs_html/EB.html#embedded-boundary-data-structures)
121122
#if defined(WARPX_DIM_3D)
122-
const amrex::Real nx = eb_bnd_normal_arr(i,j,k,0);
123-
const amrex::Real ny = eb_bnd_normal_arr(i,j,k,1);
124-
const amrex::Real nz = eb_bnd_normal_arr(i,j,k,2);
125-
amrex::Real scale_fac = std::sqrt(amrex::Math::powi<2>(nx*dx[1]*dx[2]) +
126-
amrex::Math::powi<2>(ny*dx[0]*dx[2]) +
127-
amrex::Math::powi<2>(nz*dx[0]*dx[1]));
123+
amrex::Real scale_fac = std::sqrt(amrex::Math::powi<2>(n0*dx[1]*dx[2]) +
124+
amrex::Math::powi<2>(n1*dx[0]*dx[2]) +
125+
amrex::Math::powi<2>(n2*dx[0]*dx[1]));
128126

129127
#elif defined(WARPX_DIM_RZ) || defined(WARPX_DIM_XZ)
130-
const amrex::Real nx = eb_bnd_normal_arr(i,j,k,0);
131-
const amrex::Real nz = eb_bnd_normal_arr(i,j,k,1);
132-
amrex::Real scale_fac = std::sqrt(amrex::Math::powi<2>(nx*dx[1]) +
133-
amrex::Math::powi<2>(nz*dx[0]));
128+
amrex::Real scale_fac = std::sqrt(amrex::Math::powi<2>(n0*dx[1]) +
129+
amrex::Math::powi<2>(n1*dx[0]));
134130
#else
135-
amrex::ignore_unused(dx, eb_bnd_normal_arr, i, j, k);
131+
amrex::ignore_unused(dx, AMREX_D_DECL(n0,n1,n2));
136132
amrex::Real scale_fac = 0.0_rt;
137133
#endif
138134
// Do not multiply by eb_bnd_area_arr(i,j,k) here because this
@@ -159,18 +155,19 @@ amrex::Real compute_scale_fac_area_eb (
159155
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
160156
void rotate_momentum_eb (
161157
PDim3 & pu,
162-
amrex::Array4<const amrex::Real> const& eb_bnd_normal_arr,
163-
int i, int j, int k )
158+
AMREX_D_DECL(const amrex::Real n0,
159+
const amrex::Real n1,
160+
const amrex::Real n2))
164161
{
165162
using namespace amrex::literals;
166163

167164
#if defined(WARPX_DIM_3D)
168165
// The minus sign below takes into account the fact that eb_bnd_normal_arr
169166
// points towards the covered region, while particles are to be emitted
170167
// *away* from the covered region.
171-
amrex::Real const nx = -eb_bnd_normal_arr(i,j,k,0);
172-
amrex::Real const ny = -eb_bnd_normal_arr(i,j,k,1);
173-
amrex::Real const nz = -eb_bnd_normal_arr(i,j,k,2);
168+
amrex::Real const nx = -n0;
169+
amrex::Real const ny = -n1;
170+
amrex::Real const nz = -n2;
174171

175172
// Rotate the momentum in theta and phi
176173
amrex::Real const cos_theta = nz;
@@ -194,14 +191,14 @@ void rotate_momentum_eb (
194191
// The minus sign below takes into account the fact that eb_bnd_normal_arr
195192
// points towards the covered region, while particles are to be emitted
196193
// *away* from the covered region.
197-
amrex::Real const sin_theta = -eb_bnd_normal_arr(i,j,k,0);
198-
amrex::Real const cos_theta = -eb_bnd_normal_arr(i,j,k,1);
194+
amrex::Real const sin_theta = -n0;
195+
amrex::Real const cos_theta = -n1;
199196
amrex::Real const uz = pu.z*cos_theta - pu.x*sin_theta;
200197
amrex::Real const ux = pu.x*cos_theta + pu.z*sin_theta;
201198
pu.x = ux;
202199
pu.z = uz;
203200
#else
204-
amrex::ignore_unused(pu, eb_bnd_normal_arr, i, j, k);
201+
amrex::ignore_unused(pu, AMREX_D_DECL(n0,n1,n2));
205202
#endif
206203
}
207204
#endif //AMREX_USE_EB

Source/Particles/PhysicalParticleContainer.cpp

+19-27
Original file line numberDiff line numberDiff line change
@@ -1351,16 +1351,11 @@ PhysicalParticleContainer::AddPlasmaFlux (PlasmaInjector const& plasma_injector,
13511351
#ifdef AMREX_USE_EB
13521352
bool const inject_from_eb = plasma_injector.m_inject_from_eb; // whether to inject from EB or from a plane
13531353
// Extract data structures for embedded boundaries
1354+
amrex::EBFArrayBoxFactory const* eb_factory = nullptr;
13541355
amrex::FabArray<amrex::EBCellFlagFab> const* eb_flag = nullptr;
1355-
amrex::MultiCutFab const* eb_bnd_area = nullptr;
1356-
amrex::MultiCutFab const* eb_bnd_normal = nullptr;
1357-
amrex::MultiCutFab const* eb_bnd_cent = nullptr;
13581356
if (inject_from_eb) {
1359-
amrex::EBFArrayBoxFactory const& eb_box_factory = WarpX::GetInstance().fieldEBFactory(0);
1360-
eb_flag = &eb_box_factory.getMultiEBCellFlagFab();
1361-
eb_bnd_area = &eb_box_factory.getBndryArea();
1362-
eb_bnd_normal = &eb_box_factory.getBndryNormal();
1363-
eb_bnd_cent = &eb_box_factory.getBndryCent();
1357+
eb_factory = &(WarpX::GetInstance().fieldEBFactory(0));
1358+
eb_flag = &(eb_factory->getMultiEBCellFlagFab());
13641359
}
13651360
#endif
13661361

@@ -1456,17 +1451,8 @@ PhysicalParticleContainer::AddPlasmaFlux (PlasmaInjector const& plasma_injector,
14561451
}
14571452

14581453
#ifdef AMREX_USE_EB
1459-
// Extract data structures for embedded boundaries
1460-
amrex::Array4<const typename FabArray<EBCellFlagFab>::value_type> eb_flag_arr;
1461-
amrex::Array4<const amrex::Real> eb_bnd_area_arr;
1462-
amrex::Array4<const amrex::Real> eb_bnd_normal_arr;
1463-
amrex::Array4<const amrex::Real> eb_bnd_cent_arr;
1464-
if (inject_from_eb) {
1465-
eb_flag_arr = eb_flag->array(mfi);
1466-
eb_bnd_area_arr = eb_bnd_area->array(mfi);
1467-
eb_bnd_normal_arr = eb_bnd_normal->array(mfi);
1468-
eb_bnd_cent_arr = eb_bnd_cent->array(mfi);
1469-
}
1454+
auto eb_flag_arr = eb_flag ? eb_flag->const_array(mfi) : Array4<EBCellFlag const>{};
1455+
auto eb_data = eb_factory ? eb_factory->getEBData(mfi) : EBData{};
14701456
#endif
14711457

14721458
amrex::ParallelForRNG(overlap_box, [=] AMREX_GPU_DEVICE (int i, int j, int k, amrex::RandomEngine const& engine) noexcept
@@ -1482,7 +1468,7 @@ PhysicalParticleContainer::AddPlasmaFlux (PlasmaInjector const& plasma_injector,
14821468
// Skip cells that are not partially covered by the EB
14831469
if (eb_flag_arr(i,j,k).isRegular() || eb_flag_arr(i,j,k).isCovered()) { return; }
14841470
// Scale by the (normalized) area of the EB surface in this cell
1485-
num_ppc_real_in_this_cell *= eb_bnd_area_arr(i,j,k);
1471+
num_ppc_real_in_this_cell *= eb_data.get<amrex::EBData_t::bndryarea>(i,j,k);
14861472
}
14871473
#else
14881474
amrex::Real const num_ppc_real_in_this_cell = num_ppc_real; // user input: number of macroparticles per cell
@@ -1574,7 +1560,10 @@ PhysicalParticleContainer::AddPlasmaFlux (PlasmaInjector const& plasma_injector,
15741560
Real scale_fac;
15751561
#ifdef AMREX_USE_EB
15761562
if (inject_from_eb) {
1577-
scale_fac = compute_scale_fac_area_eb(dx, num_ppc_real, eb_bnd_normal_arr, i, j, k );
1563+
scale_fac = compute_scale_fac_area_eb(dx, num_ppc_real,
1564+
AMREX_D_DECL(eb_data.get<amrex::EBData_t::bndrynorm>(i,j,k,0),
1565+
eb_data.get<amrex::EBData_t::bndrynorm>(i,j,k,1),
1566+
eb_data.get<amrex::EBData_t::bndrynorm>(i,j,k,2)));
15781567
} else
15791568
#endif
15801569
{
@@ -1595,14 +1584,15 @@ PhysicalParticleContainer::AddPlasmaFlux (PlasmaInjector const& plasma_injector,
15951584
XDim3 r;
15961585
#ifdef AMREX_USE_EB
15971586
if (inject_from_eb) {
1587+
auto const& pt = eb_data.randomPointOnEB(i,j,k,engine);
15981588
#if defined(WARPX_DIM_3D)
1599-
pos.x = overlap_corner[0] + (iv[0] + 0.5_rt + eb_bnd_cent_arr(i,j,k,0))*dx[0];
1600-
pos.y = overlap_corner[1] + (iv[1] + 0.5_rt + eb_bnd_cent_arr(i,j,k,1))*dx[1];
1601-
pos.z = overlap_corner[2] + (iv[2] + 0.5_rt + eb_bnd_cent_arr(i,j,k,2))*dx[2];
1589+
pos.x = overlap_corner[0] + (iv[0] + 0.5_rt + pt[0])*dx[0];
1590+
pos.y = overlap_corner[1] + (iv[1] + 0.5_rt + pt[1])*dx[1];
1591+
pos.z = overlap_corner[2] + (iv[2] + 0.5_rt + pt[2])*dx[2];
16021592
#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
1603-
pos.x = overlap_corner[0] + (iv[0] + 0.5_rt + eb_bnd_cent_arr(i,j,k,0))*dx[0];
1593+
pos.x = overlap_corner[0] + (iv[0] + 0.5_rt + pt[0])*dx[0];
16041594
pos.y = 0.0_rt;
1605-
pos.z = overlap_corner[1] + (iv[1] + 0.5_rt + eb_bnd_cent_arr(i,j,k,1))*dx[1];
1595+
pos.z = overlap_corner[1] + (iv[1] + 0.5_rt + pt[1])*dx[1];
16061596
#endif
16071597
} else
16081598
#endif
@@ -1661,7 +1651,9 @@ PhysicalParticleContainer::AddPlasmaFlux (PlasmaInjector const& plasma_injector,
16611651
// Injection from EB: rotate momentum according to the normal of the EB surface
16621652
// (The above code initialized the momentum by assuming that z is the direction
16631653
// normal to the EB surface. Thus we need to rotate from z to the normal.)
1664-
rotate_momentum_eb(pu, eb_bnd_normal_arr, i, j , k);
1654+
rotate_momentum_eb(pu, AMREX_D_DECL(eb_data.get<amrex::EBData_t::bndrynorm>(i,j,k,0),
1655+
eb_data.get<amrex::EBData_t::bndrynorm>(i,j,k,1),
1656+
eb_data.get<amrex::EBData_t::bndrynorm>(i,j,k,2)));
16651657
}
16661658
#endif
16671659

0 commit comments

Comments
 (0)