WarpX
ChargeDeposition.H
Go to the documentation of this file.
1 /* Copyright 2019 Axel Huebl, David Grote, Maxence Thevenet
2  * Weiqun Zhang
3  *
4  * This file is part of WarpX.
5  *
6  * License: BSD-3-Clause-LBNL
7  */
8 #ifndef CHARGEDEPOSITION_H_
9 #define CHARGEDEPOSITION_H_
10 
12 #include "Particles/ShapeFactors.H"
13 
14 #include <AMReX.H>
15 
16 /* \brief Charge Deposition for thread thread_num
17  * /param GetPosition : A functor for returning the particle position.
18  * \param wp : Pointer to array of particle weights.
19  * \param ion_lev : Pointer to array of particle ionization level. This is
20  required to have the charge of each macroparticle
21  since q is a scalar. For non-ionizable species,
22  ion_lev is a null pointer.
23  * \param rho_fab : FArrayBox of charge density, either full array or tile.
24  * \param np_to_depose : Number of particles for which current is deposited.
25  * \param dx : 3D cell size
26  * \param xyzmin : Physical lower bounds of domain.
27  * \param lo : Index lower bounds of domain.
28  * /param q : species charge.
29  */
30 template <int depos_order>
32  const amrex::ParticleReal * const wp,
33  const int * const ion_lev,
34  amrex::FArrayBox& rho_fab,
35  const long np_to_depose,
36  const std::array<amrex::Real,3>& dx,
37  const std::array<amrex::Real, 3> xyzmin,
38  const amrex::Dim3 lo,
39  const amrex::Real q,
40  const long n_rz_azimuthal_modes)
41 {
42  using namespace amrex;
43 
44  // Whether ion_lev is a null pointer (do_ionization=0) or a real pointer
45  // (do_ionization=1)
46  const bool do_ionization = ion_lev;
47  const amrex::Real dxi = 1.0/dx[0];
48  const amrex::Real dzi = 1.0/dx[2];
49 #if (AMREX_SPACEDIM == 2)
50  const amrex::Real invvol = dxi*dzi;
51 #elif (defined WARPX_DIM_3D)
52  const amrex::Real dyi = 1.0/dx[1];
53  const amrex::Real invvol = dxi*dyi*dzi;
54 #endif
55 
56  const amrex::Real xmin = xyzmin[0];
57 #if (defined WARPX_DIM_3D)
58  const amrex::Real ymin = xyzmin[1];
59 #endif
60  const amrex::Real zmin = xyzmin[2];
61 
62  amrex::Array4<amrex::Real> const& rho_arr = rho_fab.array();
63  amrex::IntVect const rho_type = rho_fab.box().type();
64 
65  constexpr int zdir = (AMREX_SPACEDIM - 1);
66  constexpr int NODE = amrex::IndexType::NODE;
67  constexpr int CELL = amrex::IndexType::CELL;
68 
69  // Loop over particles and deposit into rho_fab
70  amrex::ParallelFor(
71  np_to_depose,
72  [=] AMREX_GPU_DEVICE (long ip) {
73  // --- Get particle quantities
74  amrex::Real wq = q*wp[ip]*invvol;
75  if (do_ionization){
76  wq *= ion_lev[ip];
77  }
78 
79  amrex::ParticleReal xp, yp, zp;
80  GetPosition(ip, xp, yp, zp);
81 
82  // --- Compute shape factors
83  // x direction
84  // Get particle position in grid coordinates
85 #if (defined WARPX_DIM_RZ)
86  const amrex::Real rp = std::sqrt(xp*xp + yp*yp);
87  amrex::Real costheta;
88  amrex::Real sintheta;
89  if (rp > 0.) {
90  costheta = xp/rp;
91  sintheta = yp/rp;
92  } else {
93  costheta = 1.;
94  sintheta = 0.;
95  }
96  const Complex xy0 = Complex{costheta, sintheta};
97  const amrex::Real x = (rp - xmin)*dxi;
98 #else
99  const amrex::Real x = (xp - xmin)*dxi;
100 #endif
101 
102  // Compute shape factor along x
103  // i: leftmost grid point that the particle touches
104  amrex::Real sx[depos_order + 1];
105  int i = 0;
106  Compute_shape_factor< depos_order > const compute_shape_factor;
107  if (rho_type[0] == NODE) {
108  i = compute_shape_factor(sx, x);
109  } else if (rho_type[0] == CELL) {
110  i = compute_shape_factor(sx, x - 0.5_rt);
111  }
112 
113 #if (defined WARPX_DIM_3D)
114  // y direction
115  const amrex::Real y = (yp - ymin)*dyi;
116  amrex::Real sy[depos_order + 1];
117  int j = 0;
118  if (rho_type[1] == NODE) {
119  j = compute_shape_factor(sy, y);
120  } else if (rho_type[1] == CELL) {
121  j = compute_shape_factor(sy, y - 0.5_rt);
122  }
123 #endif
124  // z direction
125  const amrex::Real z = (zp - zmin)*dzi;
126  amrex::Real sz[depos_order + 1];
127  int k = 0;
128  if (rho_type[zdir] == NODE) {
129  k = compute_shape_factor(sz, z);
130  } else if (rho_type[zdir] == CELL) {
131  k = compute_shape_factor(sz, z - 0.5_rt);
132  }
133 
134  // Deposit charge into rho_arr
135 #if (defined WARPX_DIM_XZ) || (defined WARPX_DIM_RZ)
136  for (int iz=0; iz<=depos_order; iz++){
137  for (int ix=0; ix<=depos_order; ix++){
138  amrex::Gpu::Atomic::Add(
139  &rho_arr(lo.x+i+ix, lo.y+k+iz, 0, 0),
140  sx[ix]*sz[iz]*wq);
141 #if (defined WARPX_DIM_RZ)
142  Complex xy = xy0; // Throughout the following loop, xy takes the value e^{i m theta}
143  for (int imode=1 ; imode < n_rz_azimuthal_modes ; imode++) {
144  // The factor 2 on the weighting comes from the normalization of the modes
145  amrex::Gpu::Atomic::Add( &rho_arr(lo.x+i+ix, lo.y+k+iz, 0, 2*imode-1), 2._rt*sx[ix]*sz[iz]*wq*xy.real());
146  amrex::Gpu::Atomic::Add( &rho_arr(lo.x+i+ix, lo.y+k+iz, 0, 2*imode ), 2._rt*sx[ix]*sz[iz]*wq*xy.imag());
147  xy = xy*xy0;
148  }
149 #endif
150  }
151  }
152 #elif (defined WARPX_DIM_3D)
153  for (int iz=0; iz<=depos_order; iz++){
154  for (int iy=0; iy<=depos_order; iy++){
155  for (int ix=0; ix<=depos_order; ix++){
156  amrex::Gpu::Atomic::Add(
157  &rho_arr(lo.x+i+ix, lo.y+j+iy, lo.z+k+iz),
158  sx[ix]*sy[iy]*sz[iz]*wq);
159  }
160  }
161  }
162 #endif
163  }
164  );
165 
166 #ifndef WARPX_DIM_RZ
167  amrex::ignore_unused(n_rz_azimuthal_modes);
168 #endif
169 }
170 
171 #endif // CHARGEDEPOSITION_H_
amrex::GpuComplex< amrex::Real > Complex
Definition: WarpX_Complex.H:22
Definition: wp_parser.tab.cpp:115
def x
Definition: read_lab_particles.py:25
int dx
Definition: compute_domain.py:35
def z
Definition: read_lab_particles.py:26
Definition: ShapeFactors.H:22
void doChargeDepositionShapeN(const GetParticlePosition &GetPosition, const amrex::ParticleReal *const wp, const int *const ion_lev, amrex::FArrayBox &rho_fab, const long np_to_depose, const std::array< amrex::Real, 3 > &dx, const std::array< amrex::Real, 3 > xyzmin, const amrex::Dim3 lo, const amrex::Real q, const long n_rz_azimuthal_modes)
Definition: ChargeDeposition.H:31
i
Definition: check_interp_points_and_weights.py:171
Functor that can be used to extract the positions of the macroparticles inside a ParallelFor kernel...
Definition: GetAndSetPosition.H:25
Definition: PML.H:52