diff options
Diffstat (limited to 'Source/Particles')
-rw-r--r-- | Source/Particles/Deposition/CurrentDeposition.H | 109 | ||||
-rw-r--r-- | Source/Particles/Gather/FieldGather.H | 80 | ||||
-rw-r--r-- | Source/Particles/MultiParticleContainer.cpp | 2 | ||||
-rw-r--r-- | Source/Particles/PhysicalParticleContainer.cpp | 42 | ||||
-rw-r--r-- | Source/Particles/RigidInjectedParticleContainer.cpp | 3 | ||||
-rw-r--r-- | Source/Particles/WarpXParticleContainer.H | 3 | ||||
-rw-r--r-- | Source/Particles/WarpXParticleContainer.cpp | 46 |
7 files changed, 214 insertions, 71 deletions
diff --git a/Source/Particles/Deposition/CurrentDeposition.H b/Source/Particles/Deposition/CurrentDeposition.H index e8e7fab0a..608c0109a 100644 --- a/Source/Particles/Deposition/CurrentDeposition.H +++ b/Source/Particles/Deposition/CurrentDeposition.H @@ -2,6 +2,7 @@ #define CURRENTDEPOSITION_H_ #include "ShapeFactors.H" +#include <WarpX_Complex.H> /* \brief Current Deposition for thread thread_num * /param xp, yp, zp : Pointer to arrays of particle positions. @@ -169,7 +170,7 @@ void doDepositionShapeN(const amrex::Real * const xp, } /* \brief Esirkepov Current Deposition for thread thread_num - * /param xp, yp, zp : Pointer to arrays of particle positions. + * \param xp, yp, zp : Pointer to arrays of particle positions. * \param wp : Pointer to array of particle weights. * \param uxp uyp uzp : Pointer to arrays of particle momentum. * \param ion_lev : Pointer to array of particle ionization level. This is @@ -184,7 +185,8 @@ void doDepositionShapeN(const amrex::Real * const xp, * \param dx : 3D cell size * \param xyzmin : Physical lower bounds of domain. * \param lo : Index lower bounds of domain. - * /param q : species charge. + * \param q : species charge. + * \param n_rz_azimuthal_modes: Number of azimuthal modes when using RZ geometry */ template <int depos_order> void doEsirkepovDepositionShapeN (const amrex::Real * const xp, @@ -203,7 +205,8 @@ void doEsirkepovDepositionShapeN (const amrex::Real * const xp, const std::array<amrex::Real,3>& dx, const std::array<amrex::Real, 3> xyzmin, const amrex::Dim3 lo, - const amrex::Real q) + const amrex::Real q, + const long n_rz_azimuthal_modes) { // Whether ion_lev is a null pointer (do_ionization=0) or a real pointer // (do_ionization=1) @@ -230,6 +233,10 @@ void doEsirkepovDepositionShapeN (const amrex::Real * const xp, const amrex::Real invvol = 1.0/(dx[0]*dx[2]); #endif +#if (defined WARPX_DIM_RZ) + const Complex I = Complex{0., 1.}; +#endif + const amrex::Real clightsq = 1.0/PhysConst::c/PhysConst::c; // Loop over particles and deposit into Jx_arr, Jy_arr and Jz_arr @@ -255,11 +262,42 @@ void doEsirkepovDepositionShapeN (const amrex::Real * const xp, // computes current and old position in grid units #if (defined WARPX_DIM_RZ) - const amrex::Real r_new = std::sqrt(xp[ip]*xp[ip] + yp[ip]*yp[ip]); - const amrex::Real r_old = std::sqrt((xp[ip] - dt*uxp[ip]*gaminv)*(xp[ip] - dt*uxp[ip]*gaminv) + - (yp[ip] - dt*uyp[ip]*gaminv)*(yp[ip] - dt*uyp[ip]*gaminv)); - const amrex::Real x_new = (r_new - xmin)*dxi; - const amrex::Real x_old = (r_old - xmin)*dxi; + const amrex::Real xp_mid = xp[ip] - 0.5*dt*uxp[ip]*gaminv; + const amrex::Real yp_mid = yp[ip] - 0.5*dt*uyp[ip]*gaminv; + const amrex::Real xp_old = xp[ip] - dt*uxp[ip]*gaminv; + const amrex::Real yp_old = yp[ip] - dt*uyp[ip]*gaminv; + const amrex::Real rp_new = std::sqrt(xp[ip]*xp[ip] + yp[ip]*yp[ip]); + const amrex::Real rp_mid = std::sqrt(xp_mid*xp_mid + yp_mid*yp_mid); + const amrex::Real rp_old = std::sqrt(xp_old*xp_old + yp_old*yp_old); + amrex::Real costheta_new, sintheta_new; + if (rp_new > 0.) { + costheta_new = xp[ip]/rp_new; + sintheta_new = yp[ip]/rp_new; + } else { + costheta_new = 1.; + sintheta_new = 0.; + } + amrex::Real costheta_mid, sintheta_mid; + if (rp_mid > 0.) { + costheta_mid = xp_mid/rp_mid; + sintheta_mid = yp_mid/rp_mid; + } else { + costheta_mid = 1.; + sintheta_mid = 0.; + } + amrex::Real costheta_old, sintheta_old; + if (rp_old > 0.) { + costheta_old = xp_old/rp_old; + sintheta_old = yp_old/rp_old; + } else { + costheta_old = 1.; + sintheta_old = 0.; + } + const Complex xy_new0 = Complex{costheta_new, sintheta_new}; + const Complex xy_mid0 = Complex{costheta_mid, sintheta_mid}; + const Complex xy_old0 = Complex{costheta_old, sintheta_old}; + const amrex::Real x_new = (rp_new - xmin)*dxi; + const amrex::Real x_old = (rp_old - xmin)*dxi; #else const amrex::Real x_new = (xp[ip] - xmin)*dxi; const amrex::Real x_old = x_new - dtsdx0*uxp[ip]*gaminv; @@ -272,16 +310,7 @@ void doEsirkepovDepositionShapeN (const amrex::Real * const xp, const amrex::Real z_old = z_new - dtsdz0*uzp[ip]*gaminv; #if (defined WARPX_DIM_RZ) - amrex::Real costheta; - amrex::Real sintheta; - if (r_new > 0.) { - costheta = xp[ip]/r_new; - sintheta = yp[ip]/r_new; - } else { - costheta = 1.; - sintheta = 0.; - } - const amrex::Real vy = (-uxp[ip]*sintheta + uyp[ip]*costheta)*gaminv; + const amrex::Real vy = (-uxp[ip]*sintheta_mid + uyp[ip]*costheta_mid)*gaminv; #elif (defined WARPX_DIM_2D) const amrex::Real vy = uyp[ip]*gaminv; #endif @@ -363,25 +392,61 @@ void doEsirkepovDepositionShapeN (const amrex::Real * const xp, amrex::Real sdxi = 0.; for (int i=dil; i<=depos_order+1-diu; i++) { sdxi += wqx*(sx_old[i] - sx_new[i])*(sz_new[k] + 0.5*(sz_old[k] - sz_new[k])); - amrex::Gpu::Atomic::Add( &Jx_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0), sdxi); + amrex::Gpu::Atomic::Add( &Jx_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 0), sdxi); +#if (defined WARPX_DIM_RZ) + Complex xy_mid = xy_mid0; // Throughout the following loop, xy_mid takes the value e^{i m theta} + for (int imode=1 ; imode < n_rz_azimuthal_modes ; imode++) { + // The factor 2 comes from the normalization of the modes + const Complex djr_cmplx = 2.*sdxi*xy_mid; + amrex::Gpu::Atomic::Add( &Jx_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 2*imode-1), djr_cmplx.real()); + amrex::Gpu::Atomic::Add( &Jx_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 2*imode), djr_cmplx.imag()); + xy_mid = xy_mid*xy_mid0; + } +#endif } } for (int k=dkl; k<=depos_order+2-dku; k++) { for (int i=dil; i<=depos_order+2-diu; i++) { const amrex::Real sdyj = wq*vy*invvol*((sz_new[k] + 0.5*(sz_old[k] - sz_new[k]))*sx_new[i] + (0.5*sz_new[k] + 1./3.*(sz_old[k] - sz_new[k]))*(sx_old[i] - sx_new[i])); - amrex::Gpu::Atomic::Add( &Jy_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0), sdyj); + amrex::Gpu::Atomic::Add( &Jy_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 0), sdyj); +#if (defined WARPX_DIM_RZ) + Complex xy_new = xy_new0; + Complex xy_mid = xy_mid0; + Complex xy_old = xy_old0; + // Throughout the following loop, xy_ takes the value e^{i m theta_} + for (int imode=1 ; imode < n_rz_azimuthal_modes ; imode++) { + // The factor 2 comes from the normalization of the modes + // The minus sign comes from the different convention with respect to Davidson et al. + const Complex djt_cmplx = -2.*I*(i_new-1 + i + xmin*dxi)*wq*invdtdx/(double)imode* + (sx_new[i]*sz_new[k]*(xy_new - xy_mid) + sx_old[i]*sz_old[k]*(xy_mid - xy_old)); + amrex::Gpu::Atomic::Add( &Jy_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 2*imode-1), djt_cmplx.real()); + amrex::Gpu::Atomic::Add( &Jy_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 2*imode), djt_cmplx.imag()); + xy_new = xy_new*xy_new0; + xy_mid = xy_mid*xy_mid0; + xy_old = xy_old*xy_old0; + } +#endif } } for (int i=dil; i<=depos_order+2-diu; i++) { amrex::Real sdzk = 0.; for (int k=dkl; k<=depos_order+1-dku; k++) { sdzk += wqz*(sz_old[k] - sz_new[k])*(sx_new[i] + 0.5*(sx_old[i] - sx_new[i])); - amrex::Gpu::Atomic::Add( &Jz_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0), sdzk); + amrex::Gpu::Atomic::Add( &Jz_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 0), sdzk); +#if (defined WARPX_DIM_RZ) + Complex xy_mid = xy_mid0; // Throughout the following loop, xy_mid takes the value e^{i m theta} + for (int imode=1 ; imode < n_rz_azimuthal_modes ; imode++) { + // The factor 2 comes from the normalization of the modes + const Complex djz_cmplx = 2.*sdzk*xy_mid; + amrex::Gpu::Atomic::Add( &Jz_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 2*imode-1), djz_cmplx.real()); + amrex::Gpu::Atomic::Add( &Jz_arr(lo.x+i_new-1+i, lo.y+k_new-1+k, 0, 2*imode), djz_cmplx.imag()); + xy_mid = xy_mid*xy_mid0; + } +#endif } } - #endif } ); diff --git a/Source/Particles/Gather/FieldGather.H b/Source/Particles/Gather/FieldGather.H index 1978e8141..d8d1d78ef 100644 --- a/Source/Particles/Gather/FieldGather.H +++ b/Source/Particles/Gather/FieldGather.H @@ -2,9 +2,10 @@ #define FIELDGATHER_H_ #include "ShapeFactors.H" +#include <WarpX_Complex.H> /* \brief Field gather for particles handled by thread thread_num - * /param xp, yp, zp : Pointer to arrays of particle positions. + * \param xp, yp, zp : Pointer to arrays of particle positions. * \param Exp, Eyp, Ezp: Pointer to array of electric field on particles. * \param Bxp, Byp, Bzp: Pointer to array of magnetic field on particles. * \param ex_arr ey_arr: Array4 of current density, either full array or tile. @@ -15,6 +16,7 @@ * \param xyzmin : Physical lower bounds of domain. * \param lo : Index lower bounds of domain. * \param stagger_shift: 0 if nodal, 0.5 if staggered. + * \param n_rz_azimuthal_modes: Number of azimuthal modes when using RZ geometry */ template <int depos_order, int lower_in_v> void doGatherShapeN(const amrex::Real * const xp, @@ -33,7 +35,8 @@ void doGatherShapeN(const amrex::Real * const xp, const std::array<amrex::Real, 3>& dx, const std::array<amrex::Real, 3> xyzmin, const amrex::Dim3 lo, - const amrex::Real stagger_shift) + const amrex::Real stagger_shift, + const long n_rz_azimuthal_modes) { const amrex::Real dxi = 1.0/dx[0]; const amrex::Real dzi = 1.0/dx[2]; @@ -56,8 +59,8 @@ void doGatherShapeN(const amrex::Real * const xp, // x direction // Get particle position #ifdef WARPX_DIM_RZ - const amrex::Real r = std::sqrt(xp[ip]*xp[ip] + yp[ip]*yp[ip]); - const amrex::Real x = (r - xmin)*dxi; + const amrex::Real rp = std::sqrt(xp[ip]*xp[ip] + yp[ip]*yp[ip]); + const amrex::Real x = (rp - xmin)*dxi; #else const amrex::Real x = (xp[ip]-xmin)*dxi; #endif @@ -103,7 +106,7 @@ void doGatherShapeN(const amrex::Real * const xp, for (int iz=0; iz<=depos_order; iz++){ for (int ix=0; ix<=depos_order; ix++){ Eyp[ip] += sx[ix]*sz[iz]* - ey_arr(lo.x+j+ix, lo.y+l+iz, 0); + ey_arr(lo.x+j+ix, lo.y+l+iz, 0, 0); } } // Gather field on particle Exp[i] from field on grid ex_arr @@ -111,9 +114,9 @@ void doGatherShapeN(const amrex::Real * const xp, for (int iz=0; iz<=depos_order; iz++){ for (int ix=0; ix<=depos_order-lower_in_v; ix++){ Exp[ip] += sx0[ix]*sz[iz]* - ex_arr(lo.x+j0+ix, lo.y+l +iz, 0); + ex_arr(lo.x+j0+ix, lo.y+l +iz, 0, 0); Bzp[ip] += sx0[ix]*sz[iz]* - bz_arr(lo.x+j0+ix, lo.y+l +iz, 0); + bz_arr(lo.x+j0+ix, lo.y+l +iz, 0, 0); } } // Gather field on particle Ezp[i] from field on grid ez_arr @@ -121,30 +124,79 @@ void doGatherShapeN(const amrex::Real * const xp, for (int iz=0; iz<=depos_order-lower_in_v; iz++){ for (int ix=0; ix<=depos_order; ix++){ Ezp[ip] += sx[ix]*sz0[iz]* - ez_arr(lo.x+j+ix, lo.y+l0 +iz, 0); + ez_arr(lo.x+j+ix, lo.y+l0 +iz, 0, 0); Bxp[ip] += sx[ix]*sz0[iz]* - bx_arr(lo.x+j+ix, lo.y+l0 +iz, 0); + bx_arr(lo.x+j+ix, lo.y+l0 +iz, 0, 0); } } // Gather field on particle Byp[i] from field on grid by_arr for (int iz=0; iz<=depos_order-lower_in_v; iz++){ for (int ix=0; ix<=depos_order-lower_in_v; ix++){ Byp[ip] += sx0[ix]*sz0[iz]* - by_arr(lo.x+j0+ix, lo.y+l0+iz, 0); + by_arr(lo.x+j0+ix, lo.y+l0+iz, 0, 0); } } #ifdef WARPX_DIM_RZ - // Convert Exp and Eyp (which are actually Er and Etheta) to Ex and Ey + amrex::Real costheta; amrex::Real sintheta; - if (r > 0.) { - costheta = xp[ip]/r; - sintheta = yp[ip]/r; + if (rp > 0.) { + costheta = xp[ip]/rp; + sintheta = yp[ip]/rp; } else { costheta = 1.; sintheta = 0.; } + const Complex xy0 = Complex{costheta, -sintheta}; + Complex xy = xy0; + + for (int imode=1 ; imode < n_rz_azimuthal_modes ; imode++) { + + // Gather field on particle Eyp[i] from field on grid ey_arr + for (int iz=0; iz<=depos_order; iz++){ + for (int ix=0; ix<=depos_order; ix++){ + const amrex::Real dEy = (+ ey_arr(lo.x+j+ix, lo.y+l+iz, 0, 2*imode-1)*xy.real() + - ey_arr(lo.x+j+ix, lo.y+l+iz, 0, 2*imode)*xy.imag()); + Eyp[ip] += sx[ix]*sz[iz]*dEy; + } + } + // Gather field on particle Exp[i] from field on grid ex_arr + // Gather field on particle Bzp[i] from field on grid bz_arr + for (int iz=0; iz<=depos_order; iz++){ + for (int ix=0; ix<=depos_order-lower_in_v; ix++){ + const amrex::Real dEx = (+ ex_arr(lo.x+j0+ix, lo.y+l +iz, 0, 2*imode-1)*xy.real() + - ex_arr(lo.x+j0+ix, lo.y+l +iz, 0, 2*imode)*xy.imag()); + Exp[ip] += sx0[ix]*sz[iz]*dEx; + const amrex::Real dBz = (+ bz_arr(lo.x+j0+ix, lo.y+l +iz, 0, 2*imode-1)*xy.real() + - bz_arr(lo.x+j0+ix, lo.y+l +iz, 0, 2*imode)*xy.imag()); + Bzp[ip] += sx0[ix]*sz[iz]*dBz; + } + } + // Gather field on particle Ezp[i] from field on grid ez_arr + // Gather field on particle Bxp[i] from field on grid bx_arr + for (int iz=0; iz<=depos_order-lower_in_v; iz++){ + for (int ix=0; ix<=depos_order; ix++){ + const amrex::Real dEz = (+ ez_arr(lo.x+j+ix, lo.y+l0 +iz, 0, 2*imode-1)*xy.real() + - ez_arr(lo.x+j+ix, lo.y+l0 +iz, 0, 2*imode)*xy.imag()); + Ezp[ip] += sx[ix]*sz0[iz]*dEz; + const amrex::Real dBx = (+ bx_arr(lo.x+j+ix, lo.y+l0 +iz, 0, 2*imode-1)*xy.real() + - bx_arr(lo.x+j+ix, lo.y+l0 +iz, 0, 2*imode)*xy.imag()); + Bxp[ip] += sx[ix]*sz0[iz]*dBx; + } + } + // Gather field on particle Byp[i] from field on grid by_arr + for (int iz=0; iz<=depos_order-lower_in_v; iz++){ + for (int ix=0; ix<=depos_order-lower_in_v; ix++){ + const amrex::Real dBy = (+ by_arr(lo.x+j0+ix, lo.y+l0+iz, 0, 2*imode-1)*xy.real() + - by_arr(lo.x+j0+ix, lo.y+l0+iz, 0, 2*imode)*xy.imag()); + Byp[ip] += sx0[ix]*sz0[iz]*dBy; + } + } + xy = xy*xy0; + } + + // Convert Exp and Eyp (which are actually Er and Etheta) to Ex and Ey const amrex::Real Exp_save = Exp[ip]; Exp[ip] = costheta*Exp[ip] - sintheta*Eyp[ip]; Eyp[ip] = costheta*Eyp[ip] + sintheta*Exp_save; diff --git a/Source/Particles/MultiParticleContainer.cpp b/Source/Particles/MultiParticleContainer.cpp index 143f4b7f9..7803bdae1 100644 --- a/Source/Particles/MultiParticleContainer.cpp +++ b/Source/Particles/MultiParticleContainer.cpp @@ -257,7 +257,7 @@ MultiParticleContainer::GetChargeDensity (int lev, bool local) std::unique_ptr<MultiFab> rho = allcontainers[0]->GetChargeDensity(lev, true); for (unsigned i = 1, n = allcontainers.size(); i < n; ++i) { std::unique_ptr<MultiFab> rhoi = allcontainers[i]->GetChargeDensity(lev, true); - MultiFab::Add(*rho, *rhoi, 0, 0, 1, rho->nGrow()); + MultiFab::Add(*rho, *rhoi, 0, 0, rho->nComp(), rho->nGrow()); } if (!local) { const Geometry& gm = allcontainers[0]->Geom(lev); diff --git a/Source/Particles/PhysicalParticleContainer.cpp b/Source/Particles/PhysicalParticleContainer.cpp index 73acd60fa..1513297a1 100644 --- a/Source/Particles/PhysicalParticleContainer.cpp +++ b/Source/Particles/PhysicalParticleContainer.cpp @@ -160,12 +160,12 @@ PhysicalParticleContainer::AddGaussianBeam(Real x_m, Real y_m, Real z_m, npart /= 4; } for (long i = 0; i < npart; ++i) { -#if ( AMREX_SPACEDIM == 3 | WARPX_DIM_RZ) +#if (defined WARPX_DIM_3D) || (WARPX_DIM_RZ) Real weight = q_tot/npart/charge; Real x = distx(mt); Real y = disty(mt); Real z = distz(mt); -#elif ( AMREX_SPACEDIM == 2 ) +#elif (defined WARPX_DIM_2D) Real weight = q_tot/npart/charge/y_rms; Real x = distx(mt); Real y = 0.; @@ -332,6 +332,7 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox) Real density_max = plasma_injector->density_max; #ifdef WARPX_DIM_RZ + const long nmodes = WarpX::n_rz_azimuthal_modes; bool radially_weighted = plasma_injector->radially_weighted; #endif @@ -489,7 +490,12 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox) #else Real x = overlap_corner[0] + (iv[0]+r.x)*dx[0]; Real y = 0.0; +#ifdef WARPX_DIM_2D Real z = overlap_corner[1] + (iv[1]+r.y)*dx[1]; +#elif defined WARPX_DIM_RZ + // Note that for RZ, r.y will be theta + Real z = overlap_corner[1] + (iv[1]+r.z)*dx[1]; +#endif #endif #if (AMREX_SPACEDIM == 3) @@ -510,9 +516,16 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox) Real yb = y; #ifdef WARPX_DIM_RZ - // Replace the x and y, choosing the angle randomly. + // Replace the x and y, setting an angle theta. // These x and y are used to get the momentum and density - Real theta = 2.*MathConst::pi*amrex::Random(); + Real theta; + if (nmodes == 1) { + // With only 1 mode, the angle doesn't matter so + // choose it randomly. + theta = 2.*MathConst::pi*amrex::Random(); + } else { + theta = 2.*MathConst::pi*r.y; + } x = xb*std::cos(theta); y = xb*std::sin(theta); #endif @@ -903,7 +916,8 @@ PhysicalParticleContainer::FieldGather (int lev, int e_is_nodal = Ex.is_nodal() and Ey.is_nodal() and Ez.is_nodal(); FieldGather(pti, Exp, Eyp, Ezp, Bxp, Byp, Bzp, &exfab, &eyfab, &ezfab, &bxfab, &byfab, &bzfab, - Ex.nGrow(), e_is_nodal, 0, np, thread_num, lev, lev); + Ex.nGrow(), e_is_nodal, + 0, np, thread_num, lev, lev); if (cost) { const Box& tbx = pti.tilebox(); @@ -1201,7 +1215,8 @@ PhysicalParticleContainer::Evolve (int lev, BL_PROFILE_VAR_START(blp_pxr_fg); FieldGather(pti, Exp, Eyp, Ezp, Bxp, Byp, Bzp, exfab, eyfab, ezfab, bxfab, byfab, bzfab, - Ex.nGrow(), e_is_nodal, 0, np_gather, thread_num, lev, lev); + Ex.nGrow(), e_is_nodal, + 0, np_gather, thread_num, lev, lev); if (np_gather < np) { @@ -1646,7 +1661,8 @@ PhysicalParticleContainer::PushP (int lev, Real dt, int e_is_nodal = Ex.is_nodal() and Ey.is_nodal() and Ez.is_nodal(); FieldGather(pti, Exp, Eyp, Ezp, Bxp, Byp, Bzp, &exfab, &eyfab, &ezfab, &bxfab, &byfab, &bzfab, - Ex.nGrow(), e_is_nodal, 0, np, thread_num, lev, lev); + Ex.nGrow(), e_is_nodal, + 0, np, thread_num, lev, lev); // This wraps the momentum advance so that inheritors can modify the call. // Extract pointers to the different particle quantities @@ -1939,7 +1955,7 @@ PhysicalParticleContainer::FieldGather (WarpXParIter& pti, Byp.dataPtr() + offset, Bzp.dataPtr() + offset, ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr, np_to_gather, dx, - xyzmin, lo, stagger_shift); + xyzmin, lo, stagger_shift, WarpX::n_rz_azimuthal_modes); } else if (WarpX::nox == 2){ doGatherShapeN<2,1>(xp, yp, zp, Exp.dataPtr() + offset, Eyp.dataPtr() + offset, @@ -1947,7 +1963,7 @@ PhysicalParticleContainer::FieldGather (WarpXParIter& pti, Byp.dataPtr() + offset, Bzp.dataPtr() + offset, ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr, np_to_gather, dx, - xyzmin, lo, stagger_shift); + xyzmin, lo, stagger_shift, WarpX::n_rz_azimuthal_modes); } else if (WarpX::nox == 3){ doGatherShapeN<3,1>(xp, yp, zp, Exp.dataPtr() + offset, Eyp.dataPtr() + offset, @@ -1955,7 +1971,7 @@ PhysicalParticleContainer::FieldGather (WarpXParIter& pti, Byp.dataPtr() + offset, Bzp.dataPtr() + offset, ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr, np_to_gather, dx, - xyzmin, lo, stagger_shift); + xyzmin, lo, stagger_shift, WarpX::n_rz_azimuthal_modes); } } else { if (WarpX::nox == 1){ @@ -1965,7 +1981,7 @@ PhysicalParticleContainer::FieldGather (WarpXParIter& pti, Byp.dataPtr() + offset, Bzp.dataPtr() + offset, ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr, np_to_gather, dx, - xyzmin, lo, stagger_shift); + xyzmin, lo, stagger_shift, WarpX::n_rz_azimuthal_modes); } else if (WarpX::nox == 2){ doGatherShapeN<2,0>(xp, yp, zp, Exp.dataPtr() + offset, Eyp.dataPtr() + offset, @@ -1973,7 +1989,7 @@ PhysicalParticleContainer::FieldGather (WarpXParIter& pti, Byp.dataPtr() + offset, Bzp.dataPtr() + offset, ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr, np_to_gather, dx, - xyzmin, lo, stagger_shift); + xyzmin, lo, stagger_shift, WarpX::n_rz_azimuthal_modes); } else if (WarpX::nox == 3){ doGatherShapeN<3,0>(xp, yp, zp, Exp.dataPtr() + offset, Eyp.dataPtr() + offset, @@ -1981,7 +1997,7 @@ PhysicalParticleContainer::FieldGather (WarpXParIter& pti, Byp.dataPtr() + offset, Bzp.dataPtr() + offset, ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr, np_to_gather, dx, - xyzmin, lo, stagger_shift); + xyzmin, lo, stagger_shift, WarpX::n_rz_azimuthal_modes); } } } diff --git a/Source/Particles/RigidInjectedParticleContainer.cpp b/Source/Particles/RigidInjectedParticleContainer.cpp index 0c94d1e33..4893b3294 100644 --- a/Source/Particles/RigidInjectedParticleContainer.cpp +++ b/Source/Particles/RigidInjectedParticleContainer.cpp @@ -409,7 +409,8 @@ RigidInjectedParticleContainer::PushP (int lev, Real dt, int e_is_nodal = Ex.is_nodal() and Ey.is_nodal() and Ez.is_nodal(); FieldGather(pti, Exp, Eyp, Ezp, Bxp, Byp, Bzp, &exfab, &eyfab, &ezfab, &bxfab, &byfab, &bzfab, - Ex.nGrow(), e_is_nodal, 0, np, thread_num, lev, lev); + Ex.nGrow(), e_is_nodal, + 0, np, thread_num, lev, lev); // Save the position and momenta, making copies auto uxp_save = uxp; diff --git a/Source/Particles/WarpXParticleContainer.H b/Source/Particles/WarpXParticleContainer.H index c4bb5e410..bc46a116b 100644 --- a/Source/Particles/WarpXParticleContainer.H +++ b/Source/Particles/WarpXParticleContainer.H @@ -51,6 +51,9 @@ namespace ParticleStringNames {"Bx", PIdx::Bx }, {"By", PIdx::By }, {"Bz", PIdx::Bz } +#ifdef WARPX_DIM_RZ + ,{"theta", PIdx::theta} +#endif }; } diff --git a/Source/Particles/WarpXParticleContainer.cpp b/Source/Particles/WarpXParticleContainer.cpp index b34e71178..8d2499a35 100644 --- a/Source/Particles/WarpXParticleContainer.cpp +++ b/Source/Particles/WarpXParticleContainer.cpp @@ -337,9 +337,9 @@ WarpXParticleContainer::DepositCurrentFortran(WarpXParIter& pti, tby.grow(ngJ); tbz.grow(ngJ); - local_jx[thread_num].resize(tbx); - local_jy[thread_num].resize(tby); - local_jz[thread_num].resize(tbz); + local_jx[thread_num].resize(tbx, jx->nComp()); + local_jy[thread_num].resize(tby, jy->nComp()); + local_jz[thread_num].resize(tbz, jz->nComp()); Real* jx_ptr = local_jx[thread_num].dataPtr(); Real* jy_ptr = local_jy[thread_num].dataPtr(); @@ -362,6 +362,7 @@ WarpXParticleContainer::DepositCurrentFortran(WarpXParIter& pti, jx_ptr, &ngJ, jxntot.getVect(), jy_ptr, &ngJ, jyntot.getVect(), jz_ptr, &ngJ, jzntot.getVect(), + &WarpX::n_rz_azimuthal_modes, &np_to_depose, m_xp[thread_num].dataPtr() + offset, m_yp[thread_num].dataPtr() + offset, @@ -382,9 +383,9 @@ WarpXParticleContainer::DepositCurrentFortran(WarpXParIter& pti, BL_PROFILE_VAR_START(blp_accumulate); // CPU, tiling: atomicAdd local_jx into jx // (same for jx and jz) - (*jx)[pti].atomicAdd(local_jx[thread_num], tbx, tbx, 0, 0, 1); - (*jy)[pti].atomicAdd(local_jy[thread_num], tby, tby, 0, 0, 1); - (*jz)[pti].atomicAdd(local_jz[thread_num], tbz, tbz, 0, 0, 1); + (*jx)[pti].atomicAdd(local_jx[thread_num], tbx, tbx, 0, 0, local_jx[thread_num].nComp()); + (*jy)[pti].atomicAdd(local_jy[thread_num], tby, tby, 0, 0, local_jy[thread_num].nComp()); + (*jz)[pti].atomicAdd(local_jz[thread_num], tbz, tbz, 0, 0, local_jz[thread_num].nComp()); BL_PROFILE_VAR_STOP(blp_accumulate); #endif } @@ -460,9 +461,9 @@ WarpXParticleContainer::DepositCurrent(WarpXParIter& pti, tby.grow(ngJ); tbz.grow(ngJ); - local_jx[thread_num].resize(tbx); - local_jy[thread_num].resize(tby); - local_jz[thread_num].resize(tbz); + local_jx[thread_num].resize(tbx, jx->nComp()); + local_jy[thread_num].resize(tby, jy->nComp()); + local_jz[thread_num].resize(tbz, jz->nComp()); // local_jx[thread_num] is set to zero local_jx[thread_num].setVal(0.0); @@ -496,17 +497,20 @@ WarpXParticleContainer::DepositCurrent(WarpXParIter& pti, doEsirkepovDepositionShapeN<1>( xp, yp, zp, wp.dataPtr() + offset, uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, - jx_arr, jy_arr, jz_arr, np_to_depose, dt, dx, xyzmin, lo, q); + jx_arr, jy_arr, jz_arr, np_to_depose, dt, dx, xyzmin, lo, q, + WarpX::n_rz_azimuthal_modes); } else if (WarpX::nox == 2){ doEsirkepovDepositionShapeN<2>( xp, yp, zp, wp.dataPtr() + offset, uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, - jx_arr, jy_arr, jz_arr, np_to_depose, dt, dx, xyzmin, lo, q); + jx_arr, jy_arr, jz_arr, np_to_depose, dt, dx, xyzmin, lo, q, + WarpX::n_rz_azimuthal_modes); } else if (WarpX::nox == 3){ doEsirkepovDepositionShapeN<3>( xp, yp, zp, wp.dataPtr() + offset, uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, - jx_arr, jy_arr, jz_arr, np_to_depose, dt, dx, xyzmin, lo, q); + jx_arr, jy_arr, jz_arr, np_to_depose, dt, dx, xyzmin, lo, q, + WarpX::n_rz_azimuthal_modes); } } else { if (WarpX::nox == 1){ @@ -534,9 +538,9 @@ WarpXParticleContainer::DepositCurrent(WarpXParIter& pti, BL_PROFILE_VAR_START(blp_accumulate); // CPU, tiling: atomicAdd local_jx into jx // (same for jx and jz) - (*jx)[pti].atomicAdd(local_jx[thread_num], tbx, tbx, 0, 0, 1); - (*jy)[pti].atomicAdd(local_jy[thread_num], tby, tby, 0, 0, 1); - (*jz)[pti].atomicAdd(local_jz[thread_num], tbz, tbz, 0, 0, 1); + (*jx)[pti].atomicAdd(local_jx[thread_num], tbx, tbx, 0, 0, jx->nComp()); + (*jy)[pti].atomicAdd(local_jy[thread_num], tby, tby, 0, 0, jy->nComp()); + (*jz)[pti].atomicAdd(local_jz[thread_num], tbz, tbz, 0, 0, jz->nComp()); BL_PROFILE_VAR_STOP(blp_accumulate); #endif } @@ -593,15 +597,17 @@ WarpXParticleContainer::DepositCharge (WarpXParIter& pti, RealVector& wp, tilebox.grow(ngRho); + const int nc = (rho->nComp() == 1 ? 1 : rho->nComp()/2); + #ifdef AMREX_USE_GPU // No tiling on GPU: rho_arr points to the full rho array. - MultiFab rhoi(*rho, amrex::make_alias, icomp, 1); + MultiFab rhoi(*rho, amrex::make_alias, icomp*nc, nc); Array4<Real> const& rho_arr = rhoi.array(pti); #else // Tiling is on: rho_arr points to local_rho[thread_num] const Box tb = amrex::convert(tilebox, IntVect::TheUnitVector()); - local_rho[thread_num].resize(tb); + local_rho[thread_num].resize(tb, nc); // local_rho[thread_num] is set to zero local_rho[thread_num].setVal(0.0); @@ -637,7 +643,7 @@ WarpXParticleContainer::DepositCharge (WarpXParIter& pti, RealVector& wp, #ifndef AMREX_USE_GPU BL_PROFILE_VAR_START(blp_accumulate); - (*rho)[pti].atomicAdd(local_rho[thread_num], tb, tb, 0, icomp, 1); + (*rho)[pti].atomicAdd(local_rho[thread_num], tb, tb, 0, icomp*nc, nc); BL_PROFILE_VAR_STOP(blp_accumulate); #endif @@ -691,7 +697,7 @@ WarpXParticleContainer::DepositCharge (Vector<std::unique_ptr<MultiFab> >& rho, BoxArray coarsened_fine_BA = fine_BA; coarsened_fine_BA.coarsen(m_gdb->refRatio(lev)); - MultiFab coarsened_fine_data(coarsened_fine_BA, fine_dm, 1, 0); + MultiFab coarsened_fine_data(coarsened_fine_BA, fine_dm, rho[lev+1]->nComp(), 0); coarsened_fine_data.setVal(0.0); IntVect ratio(AMREX_D_DECL(2, 2, 2)); // FIXME @@ -720,7 +726,7 @@ WarpXParticleContainer::GetChargeDensity (int lev, bool local) const int ng = WarpX::nox; - auto rho = std::unique_ptr<MultiFab>(new MultiFab(nba,dm,1,ng)); + auto rho = std::unique_ptr<MultiFab>(new MultiFab(nba,dm,WarpX::ncomps,ng)); rho->setVal(0.0); #ifdef _OPENMP |