Skip to content

Commit 411d91f

Browse files
authored
Merge pull request #263 from ECP-WarpX/convert_charge_deposition
Convert charge deposition
2 parents a7c1afc + a38e581 commit 411d91f

File tree

13 files changed

+259
-351
lines changed

13 files changed

+259
-351
lines changed

Source/Evolve/WarpXEvolveEM.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,17 @@ WarpX::PushParticlesandDepose (int lev, Real cur_time)
483483
Bfield_cax[lev][0].get(), Bfield_cax[lev][1].get(), Bfield_cax[lev][2].get(),
484484
cur_time, dt[lev]);
485485
#ifdef WARPX_DIM_RZ
486-
// This is called after all particles have deposited their current.
486+
// This is called after all particles have deposited their current and charge.
487487
ApplyInverseVolumeScalingToCurrentDensity(current_fp[lev][0].get(), current_fp[lev][1].get(), current_fp[lev][2].get(), lev);
488488
if (current_buf[lev][0].get()) {
489489
ApplyInverseVolumeScalingToCurrentDensity(current_buf[lev][0].get(), current_buf[lev][1].get(), current_buf[lev][2].get(), lev-1);
490490
}
491+
if (rho_fp[lev].get()) {
492+
ApplyInverseVolumeScalingToChargeDensity(rho_fp[lev].get(), lev);
493+
if (charge_buf[lev].get()) {
494+
ApplyInverseVolumeScalingToChargeDensity(charge_buf[lev].get(), lev-1);
495+
}
496+
}
491497
#endif
492498
}
493499

Source/FieldSolver/WarpXPushFieldsEM.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,4 +671,53 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu
671671
});
672672
}
673673
}
674+
675+
void
676+
WarpX::ApplyInverseVolumeScalingToChargeDensity (MultiFab* Rho, int lev)
677+
{
678+
const long ngRho = Rho->nGrow();
679+
const std::array<Real,3>& dx = WarpX::CellSize(lev);
680+
const Real dr = dx[0];
681+
682+
Box tilebox;
683+
684+
for ( MFIter mfi(*Rho, TilingIfNotGPU()); mfi.isValid(); ++mfi )
685+
{
686+
687+
Array4<Real> const& Rho_arr = Rho->array(mfi);
688+
689+
tilebox = mfi.tilebox();
690+
Box tb = convert(tilebox, IntVect::TheUnitVector());
691+
692+
// Lower corner of tile box physical domain
693+
// Note that this is done before the tilebox.grow so that
694+
// these do not include the guard cells.
695+
const std::array<Real, 3>& xyzmin = WarpX::LowerCorner(tilebox, lev);
696+
const Dim3 lo = lbound(tilebox);
697+
const Real rmin = xyzmin[0];
698+
const int irmin = lo.x;
699+
700+
// Rescale charge in r-z mode since the inverse volume factor was not
701+
// included in the charge deposition.
702+
amrex::ParallelFor(tb, Rho->nComp(),
703+
[=] AMREX_GPU_DEVICE (int i, int j, int k, int icomp)
704+
{
705+
// Wrap the charge density deposited in the guard cells around
706+
// to the cells above the axis.
707+
// Rho is located on the boundary
708+
if (rmin == 0. && 0 < i && i <= ngRho) {
709+
Rho_arr(i,j,0,icomp) += Rho_arr(-i,j,0,icomp);
710+
}
711+
712+
// Apply the inverse volume scaling
713+
const amrex::Real r = std::abs(rmin + (i - irmin)*dr);
714+
if (r == 0.) {
715+
// Verboncoeur JCP 164, 421-427 (2001) : corrected volume on axis
716+
Rho_arr(i,j,0,icomp) /= (MathConst::pi*dr/3.);
717+
} else {
718+
Rho_arr(i,j,0,icomp) /= (2.*MathConst::pi*r);
719+
}
720+
});
721+
}
722+
}
674723
#endif

Source/FortranInterface/WarpX_f.H

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,6 @@ extern "C"
7575
{
7676
#endif
7777

78-
// Charge deposition
79-
void warpx_charge_deposition(amrex::Real* rho,
80-
const long* np, const amrex::Real* xp, const amrex::Real* yp, const amrex::Real* zp, const amrex::Real* w,
81-
const amrex::Real* q, const amrex::Real* xmin, const amrex::Real* ymin, const amrex::Real* zmin,
82-
const amrex::Real* dx, const amrex::Real* dy, const amrex::Real* dz,
83-
const long* nx, const long* ny, const long* nz,
84-
const long* nxguard, const long* nyguard, const long* nzguard,
85-
const long* nox, const long* noy,const long* noz,
86-
const long* lvect, const long* charge_depo_algo);
87-
88-
// Charge deposition finalize for RZ
89-
void warpx_charge_deposition_rz_volume_scaling(
90-
amrex::Real* rho, const long* rho_ng, const int* rho_ntot,
91-
const amrex::Real* rmin,
92-
const amrex::Real* dr);
93-
9478
// Current deposition
9579
void warpx_current_deposition(
9680
amrex::Real* jx, const long* jx_ng, const int* jx_ntot,

Source/FortranInterface/WarpX_picsar.F90

Lines changed: 0 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#ifdef WARPX_DIM_RZ
88

99
#define WRPX_PXR_CURRENT_DEPOSITION depose_jrjtjz_generic_rz
10-
#define WRPX_PXR_RZ_VOLUME_SCALING_RHO apply_rz_volume_scaling_rho
1110

1211
#else
1312

@@ -49,149 +48,6 @@ module warpx_to_pxr_module
4948

5049
contains
5150

52-
! _________________________________________________________________
53-
!>
54-
!> @brief
55-
!> Main subroutine for the charge deposition
56-
!>
57-
!> @details
58-
!> This subroutines enable to controle the interpolation order
59-
!> via the parameters nox,noy,noz and the type of algorithm via
60-
!> the parameter charge_depo_algo
61-
!
62-
!> @param[inout] rho charge array
63-
!> @param[in] np number of particles
64-
!> @param[in] xp,yp,zp particle position arrays
65-
!> @param[in] w particle weight arrays
66-
!> @param[in] q particle species charge
67-
!> @param[in] xmin,ymin,zmin tile grid minimum position
68-
!> @param[in] dx,dy,dz space discretization steps
69-
!> @param[in] nx,ny,nz number of cells
70-
!> @param[in] nxguard,nyguard,nzguard number of guard cells
71-
!> @param[in] nox,noy,noz interpolation order
72-
!> @param[in] lvect vector length
73-
!> @param[in] charge_depo_algo algorithm choice for the charge deposition
74-
!>
75-
subroutine warpx_charge_deposition(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
76-
nxguard,nyguard,nzguard,nox,noy,noz,lvect,charge_depo_algo) &
77-
bind(C, name="warpx_charge_deposition")
78-
79-
integer(c_long), intent(IN) :: np
80-
integer(c_long), intent(IN) :: nx,ny,nz
81-
integer(c_long), intent(IN) :: nxguard,nyguard,nzguard
82-
integer(c_long), intent(IN) :: nox,noy,noz
83-
real(amrex_real), intent(IN OUT) :: rho(*)
84-
real(amrex_real), intent(IN) :: q
85-
real(amrex_real), intent(IN) :: dx,dy,dz
86-
real(amrex_real), intent(IN) :: xmin,ymin,zmin
87-
real(amrex_real), intent(IN), dimension(np) :: xp,yp,zp,w
88-
integer(c_long), intent(IN) :: lvect
89-
integer(c_long), intent(IN) :: charge_depo_algo
90-
91-
92-
! Dimension 3
93-
#if (AMREX_SPACEDIM==3)
94-
95-
SELECT CASE(charge_depo_algo)
96-
97-
! Scalar classical charge deposition subroutines
98-
CASE(1)
99-
IF ((nox.eq.1).and.(noy.eq.1).and.(noz.eq.1)) THEN
100-
101-
CALL depose_rho_scalar_1_1_1(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
102-
nxguard,nyguard,nzguard,lvect)
103-
104-
ELSE IF ((nox.eq.2).and.(noy.eq.2).and.(noz.eq.2)) THEN
105-
106-
CALL depose_rho_scalar_2_2_2(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
107-
nxguard,nyguard,nzguard,lvect)
108-
109-
ELSE IF ((nox.eq.3).and.(noy.eq.3).and.(noz.eq.3)) THEN
110-
111-
CALL depose_rho_scalar_3_3_3(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
112-
nxguard,nyguard,nzguard,lvect)
113-
114-
ELSE
115-
CALL pxr_depose_rho_n(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
116-
nxguard,nyguard,nzguard,nox,noy,noz, &
117-
.TRUE._c_long,.FALSE._c_long)
118-
ENDIF
119-
120-
! Optimized subroutines
121-
CASE DEFAULT
122-
123-
IF ((nox.eq.1).and.(noy.eq.1).and.(noz.eq.1)) THEN
124-
CALL depose_rho_vecHVv2_1_1_1(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
125-
nxguard,nyguard,nzguard,lvect)
126-
127-
ELSE IF ((nox.eq.2).and.(noy.eq.2).and.(noz.eq.2)) THEN
128-
CALL depose_rho_vecHVv2_2_2_2(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
129-
nxguard,nyguard,nzguard,lvect)
130-
131-
ELSE
132-
CALL pxr_depose_rho_n(rho,np,xp,yp,zp,w,q,xmin,ymin,zmin,dx,dy,dz,nx,ny,nz,&
133-
nxguard,nyguard,nzguard,nox,noy,noz, &
134-
.TRUE._c_long,.FALSE._c_long)
135-
ENDIF
136-
END SELECT
137-
138-
! Dimension 2
139-
#elif (AMREX_SPACEDIM==2)
140-
141-
#ifdef WARPX_DIM_RZ
142-
logical(pxr_logical) :: l_2drz = .TRUE._c_long
143-
#else
144-
logical(pxr_logical) :: l_2drz = .FALSE._c_long
145-
#endif
146-
147-
CALL pxr_depose_rho_n_2dxz(rho,np,xp,yp,zp,w,q,xmin,zmin,dx,dz,nx,nz,&
148-
nxguard,nzguard,nox,noz, &
149-
.TRUE._c_long, .FALSE._c_long, l_2drz, 0_c_long)
150-
151-
#endif
152-
153-
end subroutine warpx_charge_deposition
154-
155-
! _________________________________________________________________
156-
!>
157-
!> @brief
158-
!> Applies the inverse volume scaling for RZ charge deposition
159-
!>
160-
!> @details
161-
!> The scaling is done for both single mode (FDTD) and
162-
!> multi mode (spectral) (todo)
163-
!
164-
!> @param[inout] rho charge array
165-
!> @param[in] rmin tile grid minimum radius
166-
!> @param[in] dr radial space discretization steps
167-
!> @param[in] nx,ny,nz number of cells
168-
!> @param[in] nxguard,nyguard,nzguard number of guard cells
169-
!>
170-
subroutine warpx_charge_deposition_rz_volume_scaling(rho,rho_ng,rho_ntot,rmin,dr) &
171-
bind(C, name="warpx_charge_deposition_rz_volume_scaling")
172-
173-
integer, intent(in) :: rho_ntot(AMREX_SPACEDIM)
174-
integer(c_long), intent(in) :: rho_ng
175-
real(amrex_real), intent(IN OUT):: rho(*)
176-
real(amrex_real), intent(IN) :: rmin, dr
177-
178-
#ifdef WARPX_DIM_RZ
179-
integer(c_long) :: type_rz_depose = 1
180-
#endif
181-
182-
! Compute the number of valid cells and guard cells
183-
integer(c_long) :: rho_nvalid(AMREX_SPACEDIM), rho_nguards(AMREX_SPACEDIM)
184-
rho_nvalid = rho_ntot - 2*rho_ng
185-
rho_nguards = rho_ng
186-
187-
#ifdef WARPX_DIM_RZ
188-
CALL WRPX_PXR_RZ_VOLUME_SCALING_RHO( &
189-
rho,rho_nguards,rho_nvalid, &
190-
rmin,dr,type_rz_depose)
191-
#endif
192-
193-
end subroutine warpx_charge_deposition_rz_volume_scaling
194-
19551
! _________________________________________________________________
19652
!>
19753
!> @brief

Source/Laser/LaserParticleContainer.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,12 @@ LaserParticleContainer::Evolve (int lev,
453453
pti.GetPosition(m_xp[thread_num], m_yp[thread_num], m_zp[thread_num]);
454454
BL_PROFILE_VAR_STOP(blp_copy);
455455

456-
if (rho) DepositCharge(pti, wp, rho, crho, 0, np_current, np, thread_num, lev);
456+
if (rho) {
457+
DepositCharge(pti, wp, rho, 0, 0, np_current, thread_num, lev, lev);
458+
if (crho) {
459+
DepositCharge(pti, wp, crho, 0, np_current, np-np_current, thread_num, lev, lev-1);
460+
}
461+
}
457462

458463
//
459464
// Particle Push
@@ -522,7 +527,12 @@ LaserParticleContainer::Evolve (int lev,
522527
pti.SetPosition(m_xp[thread_num], m_yp[thread_num], m_zp[thread_num]);
523528
BL_PROFILE_VAR_STOP(blp_copy);
524529

525-
if (rho) DepositCharge(pti, wp, rho, crho, 1, np_current, np, thread_num, lev);
530+
if (rho) {
531+
DepositCharge(pti, wp, rho, 1, 0, np_current, thread_num, lev, lev);
532+
if (crho) {
533+
DepositCharge(pti, wp, crho, 1, np_current, np-np_current, thread_num, lev, lev-1);
534+
}
535+
}
526536

527537
if (cost) {
528538
const Box& tbx = pti.tilebox();
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#ifndef CHARGEDEPOSITION_H_
2+
#define CHARGEDEPOSITION_H_
3+
4+
#include "ShapeFactors.H"
5+
6+
/* \brief Charge Deposition for thread thread_num
7+
* /param xp, yp, zp : Pointer to arrays of particle positions.
8+
* \param wp : Pointer to array of particle weights.
9+
* \param rho_arr : Array4 of charge density, either full array or tile.
10+
* \param np_to_depose : Number of particles for which current is deposited.
11+
* \param dx : 3D cell size
12+
* \param xyzmin : Physical lower bounds of domain.
13+
* \param lo : Index lower bounds of domain.
14+
* /param q : species charge.
15+
*/
16+
template <int depos_order>
17+
void doChargeDepositionShapeN(const amrex::Real * const xp,
18+
const amrex::Real * const yp,
19+
const amrex::Real * const zp,
20+
const amrex::Real * const wp,
21+
const amrex::Array4<amrex::Real>& rho_arr,
22+
const long np_to_depose,
23+
const std::array<amrex::Real,3>& dx,
24+
const std::array<amrex::Real, 3> xyzmin,
25+
const amrex::Dim3 lo,
26+
const amrex::Real q)
27+
{
28+
const amrex::Real dxi = 1.0/dx[0];
29+
const amrex::Real dzi = 1.0/dx[2];
30+
#if (AMREX_SPACEDIM == 2)
31+
const amrex::Real invvol = dxi*dzi;
32+
#elif (defined WARPX_DIM_3D)
33+
const amrex::Real dyi = 1.0/dx[1];
34+
const amrex::Real invvol = dxi*dyi*dzi;
35+
#endif
36+
37+
const amrex::Real xmin = xyzmin[0];
38+
const amrex::Real ymin = xyzmin[1];
39+
const amrex::Real zmin = xyzmin[2];
40+
41+
// Loop over particles and deposit into rho_arr
42+
amrex::ParallelFor(
43+
np_to_depose,
44+
[=] AMREX_GPU_DEVICE (long ip) {
45+
// --- Get particle quantities
46+
const amrex::Real wq = q*wp[ip]*invvol;
47+
48+
// --- Compute shape factors
49+
// x direction
50+
// Get particle position in grid coordinates
51+
#if (defined WARPX_DIM_RZ)
52+
const amrex::Real r = std::sqrt(xp[ip]*xp[ip] + yp[ip]*yp[ip]);
53+
const amrex::Real x = (r - xmin)*dxi;
54+
#else
55+
const amrex::Real x = (xp[ip] - xmin)*dxi;
56+
#endif
57+
// Compute shape factors for node-centered quantities
58+
amrex::Real AMREX_RESTRICT sx[depos_order + 1];
59+
// i: leftmost grid point (node-centered) that the particle touches
60+
const int i = compute_shape_factor<depos_order>(sx, x);
61+
62+
#if (defined WARPX_DIM_3D)
63+
// y direction
64+
const amrex::Real y = (yp[ip] - ymin)*dyi;
65+
amrex::Real AMREX_RESTRICT sy[depos_order + 1];
66+
const int j = compute_shape_factor<depos_order>(sy, y);
67+
#endif
68+
// z direction
69+
const amrex::Real z = (zp[ip] - zmin)*dzi;
70+
amrex::Real AMREX_RESTRICT sz[depos_order + 1];
71+
const int k = compute_shape_factor<depos_order>(sz, z);
72+
73+
// Deposit charge into rho_arr
74+
#if (defined WARPX_DIM_2D) || (defined WARPX_DIM_RZ)
75+
for (int iz=0; iz<=depos_order; iz++){
76+
for (int ix=0; ix<=depos_order; ix++){
77+
amrex::Gpu::Atomic::Add(
78+
&rho_arr(lo.x+i+ix, lo.y+k+iz, 0),
79+
sx[ix]*sz[iz]*wq);
80+
}
81+
}
82+
#elif (defined WARPX_DIM_3D)
83+
for (int iz=0; iz<=depos_order; iz++){
84+
for (int iy=0; iy<=depos_order; iy++){
85+
for (int ix=0; ix<=depos_order; ix++){
86+
amrex::Gpu::Atomic::Add(
87+
&rho_arr(lo.x+i+ix, lo.y+j+iy, lo.z+k+iz),
88+
sx[ix]*sy[iy]*sz[iz]*wq);
89+
}
90+
}
91+
}
92+
#endif
93+
}
94+
);
95+
}
96+
97+
#endif // CHARGEDEPOSITION_H_
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
CEXE_headers += CurrentDeposition.H
2+
CEXE_headers += ChargeDeposition.H
23
INCLUDE_LOCATIONS += $(WARPX_HOME)/Source/Particles/Deposition
34
VPATH_LOCATIONS += $(WARPX_HOME)/Source/Particles/Deposition

0 commit comments

Comments
 (0)