Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
85bc5d9
Implement cropping of particles at boundaries for deposition
dpgrote Feb 8, 2025
ddfc2e4
Fix const
dpgrote Feb 10, 2025
b1be5a8
Rework how the cropping is done, doing it correctly
dpgrote Feb 10, 2025
b7c9808
Fix another const
dpgrote Feb 10, 2025
845df6e
Add more consts
dpgrote Feb 11, 2025
ab7e95d
Set absorbing for PECInsulator BC
dpgrote Feb 11, 2025
60f68f3
Updates of the test_2d_theta_implicit_jfnk_vandb CI test
dpgrote Feb 14, 2025
a654f23
Bug fix
dpgrote Feb 14, 2025
085d335
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 14, 2025
a44ac51
Fix to use domain box
dpgrote Feb 14, 2025
8050683
Make step size consistent with previous code
dpgrote Feb 18, 2025
ae3c87e
Merge branch 'development' into stop_particles_at_boundary
dpgrote Feb 18, 2025
51682b7
Add option crop_on_PEC_boundary
dpgrote Feb 18, 2025
d45fb6e
Rework the cropping to minimize changes relative to development
dpgrote Feb 22, 2025
f8b19a3
Remove debugging print statement
dpgrote Feb 22, 2025
554ed24
Fix min and max type in crop_at_boundary
dpgrote Feb 22, 2025
1e89fbb
Add crop_at_boundary to Esirkepov deposition
dpgrote Feb 22, 2025
bdfde81
Fix type cast
dpgrote Feb 24, 2025
bee8c68
Fix types in crop_at_boundary
dpgrote Feb 24, 2025
2b2e208
Merge branch 'development' into stop_particles_at_boundary
dpgrote Mar 1, 2025
e7a90f0
Merge branch 'development' into stop_particles_at_boundary
dpgrote Mar 6, 2025
b026d10
Fix Esirkepov when the trajectory length is zero
dpgrote Mar 6, 2025
fb436bf
Another fix for Esirkepov len_ratio
dpgrote Mar 7, 2025
82f1c79
Merge branch 'development' into stop_particles_at_boundary
dpgrote Apr 4, 2025
05ba514
Undo changes in call to doDirectGatherVectorField
dpgrote Apr 9, 2025
1ef6861
Revert test changes
dpgrote Apr 10, 2025
731bf83
Merge branch 'development' into stop_particles_at_boundary
dpgrote Apr 10, 2025
761ead6
Merge branch 'development' into stop_particles_at_boundary
dpgrote May 7, 2025
b2f1975
Merge branch 'development' into stop_particles_at_boundary
dpgrote May 19, 2025
32f9538
Fix erroneous const
dpgrote May 20, 2025
64ef08a
Cleanup after merge
dpgrote May 20, 2025
e670e2a
Merge branch 'development' into stop_particles_at_boundary
dpgrote Aug 11, 2025
6c2e335
Fix param lists
dpgrote Aug 12, 2025
208d42f
Fix more param lists
dpgrote Aug 12, 2025
86fbaea
Merge branch 'development' into stop_particles_at_boundary
dpgrote Nov 10, 2025
8cfec91
Merge branch 'development' into stop_particles_at_boundary
dpgrote Nov 17, 2025
d87ce90
Fix domain_box to include update boundary node
dpgrote Nov 18, 2025
c7c7255
For Esirkepov, use std:abs for length in 1D
dpgrote Nov 18, 2025
4e2330e
Fix cropping for Esirkepov
dpgrote Nov 18, 2025
650fe5e
Add CI test case
dpgrote Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions Source/Particles/Deposition/CurrentDeposition.H
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ablastr/parallelization/KernelTimer.H"
#include "Particles/Pusher/GetAndSetPosition.H"
#include "Particles/ShapeFactors.H"
#include "Utils/ParticleUtils.H"
#include "Utils/TextMsg.H"
#include "Utils/WarpXAlgorithmSelection.H"
#include "Utils/WarpXConst.H"
Expand Down Expand Up @@ -1352,6 +1353,8 @@ void doVillasenorDepositionShapeNImplicit ([[maybe_unused]]const amrex::Particle
const amrex::Real dt,
const amrex::XDim3 & dinv,
const amrex::XDim3 & xyzmin,
const amrex::XDim3 & xyzmax,
const amrex::GpuArray<amrex::GpuArray<bool,2>, AMREX_SPACEDIM> & is_absorbing,
const amrex::Dim3 lo,
const amrex::Real q,
[[maybe_unused]] const int n_rz_azimuthal_modes)
Expand Down Expand Up @@ -1425,13 +1428,15 @@ void doVillasenorDepositionShapeNImplicit ([[maybe_unused]]const amrex::Particle
const Complex xy_mid0 = Complex{costheta_mid, sintheta_mid};

// Keep these double to avoid bug in single precision
double const x_new = (rp_new - xyzmin.x)*dinv.x;
amrex::Real const rp_new_c = ParticleUtils::crop_at_boundary(rp_new, xyzmin.x, xyzmax.x, is_absorbing[0]);
double const x_new = (rp_new_c - xyzmin.x)*dinv.x;
double const x_old = (rp_old - xyzmin.x)*dinv.x;
amrex::Real const vx = (rp_new - rp_old)/dt;
amrex::Real const vy = (-uxp_nph[ip]*sintheta_mid + uyp_nph[ip]*costheta_mid)*gaminv;
#elif defined(WARPX_DIM_XZ)
// Keep these double to avoid bug in single precision
double const x_new = (xp_np1 - xyzmin.x)*dinv.x;
amrex::Real const xp_np1_c = ParticleUtils::crop_at_boundary(xp_np1, xyzmin.x, xyzmax.x, is_absorbing[0]);
double const x_new = (xp_np1_c - xyzmin.x)*dinv.x;
double const x_old = (xp_n[ip] - xyzmin.x)*dinv.x;
amrex::Real const vx = (xp_np1 - xp_n[ip])/dt;
amrex::Real const vy = uyp_nph[ip]*gaminv;
Expand All @@ -1440,16 +1445,19 @@ void doVillasenorDepositionShapeNImplicit ([[maybe_unused]]const amrex::Particle
amrex::Real const vy = uyp_nph[ip]*gaminv;
#elif defined(WARPX_DIM_3D)
// Keep these double to avoid bug in single precision
double const x_new = (xp_np1 - xyzmin.x)*dinv.x;
amrex::Real const xp_np1_c = ParticleUtils::crop_at_boundary(xp_np1, xyzmin.x, xyzmax.x, is_absorbing[0]);
amrex::Real const yp_np1_c = ParticleUtils::crop_at_boundary(yp_np1, xyzmin.y, xyzmax.y, is_absorbing[1]);
double const x_new = (xp_np1_c - xyzmin.x)*dinv.x;
double const x_old = (xp_n[ip] - xyzmin.x)*dinv.x;
double const y_new = (yp_np1 - xyzmin.y)*dinv.y;
double const y_new = (yp_np1_c - xyzmin.y)*dinv.y;
double const y_old = (yp_n[ip] - xyzmin.y)*dinv.y;
amrex::Real const vx = (xp_np1 - xp_n[ip])/dt;
amrex::Real const vy = (yp_np1 - yp_n[ip])/dt;
#endif

// Keep these double to avoid bug in single precision
double const z_new = (zp_np1 - xyzmin.z)*dinv.z;
amrex::Real const zp_np1_c = ParticleUtils::crop_at_boundary(zp_np1, xyzmin.z, xyzmax.z, is_absorbing[WARPX_ZINDEX]);
double const z_new = (zp_np1_c - xyzmin.z)*dinv.z;
double const z_old = (zp_n[ip] - xyzmin.z)*dinv.z;
amrex::Real const vz = (zp_np1 - zp_n[ip])/dt;

Expand Down
33 changes: 21 additions & 12 deletions Source/Particles/Gather/FieldGather.H
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "Particles/Pusher/GetAndSetPosition.H"
#include "Particles/ShapeFactors.H"
#include "Utils/WarpX_Complex.H"
#include "Utils/ParticleUtils.H"

#include <AMReX.H>

Expand Down Expand Up @@ -887,6 +888,8 @@ void doGatherPicnicShapeN (
[[maybe_unused]] const amrex::IndexType Bz_type,
const amrex::XDim3 & dinv,
const amrex::XDim3 & xyzmin,
const amrex::XDim3 & xyzmax,
const amrex::GpuArray<amrex::GpuArray<bool,2>, AMREX_SPACEDIM> & is_absorbing,
const amrex::Dim3& lo,
const int n_rz_azimuthal_modes)
{
Expand Down Expand Up @@ -928,26 +931,30 @@ void doGatherPicnicShapeN (
sintheta_mid = 0._rt;
}
const Complex xy_mid0 = Complex{costheta_mid, sintheta_mid};
amrex::Real const rp_new_c = ParticleUtils::crop_at_boundary(rp_new, xyzmin.x, xyzmax.x, is_absorbing[0]);
// Keep these double to avoid bug in single precision
double const x_new = (rp_new - xyzmin.x)*dinv.x;
double const x_new = (rp_new_c - xyzmin.x)*dinv.x;
double const x_old = (rp_old - xyzmin.x)*dinv.x;
double const x_bar = (rp_mid - xyzmin.x)*dinv.x;
double const x_bar = (x_new + x_old)*0.5_rt;
#elif !defined(WARPX_DIM_1D_Z)
amrex::Real const xp_np1_c = ParticleUtils::crop_at_boundary(xp_np1, xyzmin.x, xyzmax.x, is_absorbing[0]);
// Keep these double to avoid bug in single precision
double const x_new = (xp_np1 - xyzmin.x)*dinv.x;
double const x_new = (xp_np1_c - xyzmin.x)*dinv.x;
double const x_old = (xp_n - xyzmin.x)*dinv.x;
double const x_bar = (xp_nph - xyzmin.x)*dinv.x;
double const x_bar = (x_new + x_old)*0.5_rt;
#endif
#if defined(WARPX_DIM_3D)
amrex::Real const yp_np1_c = ParticleUtils::crop_at_boundary(yp_np1, xyzmin.y, xyzmax.y, is_absorbing[1]);
// Keep these double to avoid bug in single precision
double const y_new = (yp_np1 - xyzmin.y)*dinv.y;
double const y_new = (yp_np1_c - xyzmin.y)*dinv.y;
double const y_old = (yp_n - xyzmin.y)*dinv.y;
double const y_bar = (yp_nph - xyzmin.y)*dinv.y;
double const y_bar = (y_new + y_old)*0.5_rt;
#endif
amrex::Real const zp_np1_c = ParticleUtils::crop_at_boundary(zp_np1, xyzmin.z, xyzmax.z, is_absorbing[WARPX_ZINDEX]);
// Keep these double to avoid bug in single precision
double const z_new = (zp_np1 - xyzmin.z)*dinv.z;
double const z_new = (zp_np1_c - xyzmin.z)*dinv.z;
double const z_old = (zp_n - xyzmin.z)*dinv.z;
double const z_bar = (zp_nph - xyzmin.z)*dinv.z;
double const z_bar = (z_new + z_old)*0.5_rt;

// 1) Determine the number of segments.
// 2) Loop over segments and gather electric field.
Expand Down Expand Up @@ -1711,6 +1718,8 @@ void doGatherShapeNImplicit (
const amrex::IndexType bz_type,
const amrex::XDim3 & dinv,
const amrex::XDim3 & xyzmin,
const amrex::XDim3 & xyzmax,
const amrex::GpuArray<amrex::GpuArray<bool,2>, AMREX_SPACEDIM> & is_absorbing,
const amrex::Dim3& lo,
const int n_rz_azimuthal_modes,
const int nox,
Expand Down Expand Up @@ -1749,25 +1758,25 @@ void doGatherShapeNImplicit (
Exp, Eyp, Ezp, Bxp, Byp, Bzp,
ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dinv, xyzmin, lo, n_rz_azimuthal_modes);
dinv, xyzmin, xyzmax, is_absorbing, lo, n_rz_azimuthal_modes);
} else if (nox == 2) {
doGatherPicnicShapeN<2>(xp_n, yp_n, zp_n, xp_nph, yp_nph, zp_nph,
Exp, Eyp, Ezp, Bxp, Byp, Bzp,
ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dinv, xyzmin, lo, n_rz_azimuthal_modes);
dinv, xyzmin, xyzmax, is_absorbing, lo, n_rz_azimuthal_modes);
} else if (nox == 3) {
doGatherPicnicShapeN<3>(xp_n, yp_n, zp_n, xp_nph, yp_nph, zp_nph,
Exp, Eyp, Ezp, Bxp, Byp, Bzp,
ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dinv, xyzmin, lo, n_rz_azimuthal_modes);
dinv, xyzmin, xyzmax, is_absorbing, lo, n_rz_azimuthal_modes);
} else if (nox == 4) {
doGatherPicnicShapeN<4>(xp_n, yp_n, zp_n, xp_nph, yp_nph, zp_nph,
Exp, Eyp, Ezp, Bxp, Byp, Bzp,
ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dinv, xyzmin, lo, n_rz_azimuthal_modes);
dinv, xyzmin, xyzmax, is_absorbing, lo, n_rz_azimuthal_modes);
}
}
else if (depos_type == CurrentDepositionAlgo::Direct) {
Expand Down
18 changes: 17 additions & 1 deletion Source/Particles/PhysicalParticleContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2832,6 +2832,22 @@ PhysicalParticleContainer::ImplicitPushXP (WarpXParIter& pti,

// Lower corner of tile box physical domain (take into account Galilean shift)
const amrex::XDim3 xyzmin = WarpX::LowerCorner(box, gather_lev, 0._rt);
const amrex::XDim3 xyzmax = WarpX::UpperCorner(box, gather_lev, 0._rt);

const WarpX& warpx = WarpX::GetInstance();
amrex::Box const& domain_box = warpx.Geom(0).Domain();
auto & field_boundary_lo = warpx.GetFieldBoundaryLo();
auto & field_boundary_hi = warpx.GetFieldBoundaryHi();

amrex::GpuArray<amrex::GpuArray<bool,2>, AMREX_SPACEDIM> is_absorbing;
for (int idim=0; idim < AMREX_SPACEDIM; ++idim) {
is_absorbing[idim][0] = (box.smallEnd(idim) <= domain_box.smallEnd(idim) &&
(field_boundary_lo[idim] == FieldBoundaryType::PEC
|| field_boundary_lo[idim] == FieldBoundaryType::PMC));
is_absorbing[idim][1] = (box.bigEnd(idim) >= domain_box.bigEnd(idim) &&
(field_boundary_hi[idim] == FieldBoundaryType::PEC
|| field_boundary_hi[idim] == FieldBoundaryType::PMC));
}

const Dim3 lo = lbound(box);

Expand Down Expand Up @@ -2986,7 +3002,7 @@ PhysicalParticleContainer::ImplicitPushXP (WarpXParIter& pti,
doGatherShapeNImplicit(xp_n, yp_n, zp_n, xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dinv, xyzmin, lo, n_rz_azimuthal_modes, nox,
dinv, xyzmin, xyzmax, is_absorbing, lo, n_rz_azimuthal_modes, nox,
depos_type );
}

Expand Down
23 changes: 19 additions & 4 deletions Source/Particles/WarpXParticleContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,21 @@ WarpXParticleContainer::DepositCurrent (WarpXParIter& pti,
const Dim3 lo = lbound(tilebox);
// Take into account Galilean shift
const amrex::XDim3 xyzmin = WarpX::LowerCorner(tilebox, depos_lev, 0.5_rt*dt);
const amrex::XDim3 xyzmax = WarpX::UpperCorner(tilebox, depos_lev, 0.5_rt*dt);
amrex::Box const& domain_box = warpx.Geom(0).Domain();

auto & field_boundary_lo = warpx.GetFieldBoundaryLo();
auto & field_boundary_hi = warpx.GetFieldBoundaryHi();

amrex::GpuArray<amrex::GpuArray<bool,2>, AMREX_SPACEDIM> is_absorbing;
for (int idim=0; idim < AMREX_SPACEDIM; ++idim) {
is_absorbing[idim][0] = (tilebox.smallEnd(idim) <= domain_box.smallEnd(idim) &&
(field_boundary_lo[idim] == FieldBoundaryType::PEC
|| field_boundary_lo[idim] == FieldBoundaryType::PMC));
is_absorbing[idim][1] = (tilebox.bigEnd(idim) >= domain_box.bigEnd(idim) &&
(field_boundary_hi[idim] == FieldBoundaryType::PEC
|| field_boundary_hi[idim] == FieldBoundaryType::PMC));
}

if (WarpX::current_deposition_algo == CurrentDepositionAlgo::Esirkepov ||
WarpX::current_deposition_algo == CurrentDepositionAlgo::Villasenor) {
Expand Down Expand Up @@ -702,31 +717,31 @@ WarpXParticleContainer::DepositCurrent (WarpXParIter& pti,
GetPosition, wp.dataPtr() + offset,
uxp_n.dataPtr() + offset, uyp_n.dataPtr() + offset, uzp_n.dataPtr() + offset,
uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, lo, q,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, xyzmax, is_absorbing, lo, q,
WarpX::n_rz_azimuthal_modes);
} else if (WarpX::nox == 2){
doVillasenorDepositionShapeNImplicit<2>(
xp_n_data, yp_n_data, zp_n_data,
GetPosition, wp.dataPtr() + offset,
uxp_n.dataPtr() + offset, uyp_n.dataPtr() + offset, uzp_n.dataPtr() + offset,
uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, lo, q,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, xyzmax, is_absorbing, lo, q,
WarpX::n_rz_azimuthal_modes);
} else if (WarpX::nox == 3){
doVillasenorDepositionShapeNImplicit<3>(
xp_n_data, yp_n_data, zp_n_data,
GetPosition, wp.dataPtr() + offset,
uxp_n.dataPtr() + offset, uyp_n.dataPtr() + offset, uzp_n.dataPtr() + offset,
uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, lo, q,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, xyzmax, is_absorbing, lo, q,
WarpX::n_rz_azimuthal_modes);
} else if (WarpX::nox == 4){
doVillasenorDepositionShapeNImplicit<4>(
xp_n_data, yp_n_data, zp_n_data,
GetPosition, wp.dataPtr() + offset,
uxp_n.dataPtr() + offset, uyp_n.dataPtr() + offset, uzp_n.dataPtr() + offset,
uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, lo, q,
jx_arr, jy_arr, jz_arr, np_to_deposit, dt, dinv, xyzmin, xyzmax, is_absorbing, lo, q,
WarpX::n_rz_azimuthal_modes);
}
}
Expand Down
13 changes: 13 additions & 0 deletions Source/Utils/ParticleUtils.H
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,19 @@ namespace ParticleUtils {
&& (xlo[2] <= point.z) && (point.z <= xhi[2]));
}

/* \brief Crops the position at the specified boundary if check is true
* \param[in] x The particle position
* \param[in] xmin The lower boundary of the domain
* \param[in] xmax The upper boundary of the domain
* \param[in] check Whether to crop at each of the boundaries
*/
AMREX_GPU_HOST_DEVICE AMREX_INLINE
amrex::Real crop_at_boundary(amrex::Real x, amrex::Real xmin, amrex::Real xmax, amrex::GpuArray<bool,2> const& check) {
if (check[0] && x < xmin) { return xmin; }
if (check[1] && x > xmax) { return xmax; }
return x;
}

}

#endif // WARPX_PARTICLE_UTILS_H_
Loading