WarpX
GetExternalFields.H
Go to the documentation of this file.
1 #ifndef WARPX_PARTICLES_GATHER_GETEXTERNALFIELDS_H_
2 #define WARPX_PARTICLES_GATHER_GETEXTERNALFIELDS_H_
3 
5 
7 #include "Utils/WarpXConst.H"
8 
10 
11 #include <AMReX.H>
12 #include <AMReX_Array.H>
13 #include <AMReX_Extension.H>
14 #include <AMReX_GpuQualifiers.H>
15 #include <AMReX_Parser.H>
16 #include <AMReX_REAL.H>
17 
18 #include <optional>
19 
20 
25 {
27 
28  GetExternalEBField () = default;
29 
30  GetExternalEBField (const WarpXParIter& a_pti, long a_offset = 0) noexcept;
31 
34 
35  amrex::ParticleReal m_gamma_boost;
36  amrex::ParticleReal m_uz_boost;
37 
38  amrex::GpuArray<amrex::ParticleReal, 3> m_Efield_value;
39  amrex::GpuArray<amrex::ParticleReal, 3> m_Bfield_value;
40 
41  amrex::ParserExecutor<4> m_Exfield_partparser;
42  amrex::ParserExecutor<4> m_Eyfield_partparser;
43  amrex::ParserExecutor<4> m_Ezfield_partparser;
44  amrex::ParserExecutor<4> m_Bxfield_partparser;
45  amrex::ParserExecutor<4> m_Byfield_partparser;
46  amrex::ParserExecutor<4> m_Bzfield_partparser;
47 
49  amrex::Real m_time;
50 
52  const amrex::ParticleReal* AMREX_RESTRICT m_repeated_plasma_lens_starts = nullptr;
53  const amrex::ParticleReal* AMREX_RESTRICT m_repeated_plasma_lens_lengths = nullptr;
54  const amrex::ParticleReal* AMREX_RESTRICT m_repeated_plasma_lens_strengths_E = nullptr;
55  const amrex::ParticleReal* AMREX_RESTRICT m_repeated_plasma_lens_strengths_B = nullptr;
57  amrex::Real m_dt;
58  const amrex::ParticleReal* AMREX_RESTRICT m_ux = nullptr;
59  const amrex::ParticleReal* AMREX_RESTRICT m_uy = nullptr;
60  const amrex::ParticleReal* AMREX_RESTRICT m_uz = nullptr;
61 
63 
64  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
65  bool isNoOp () const { return (m_Etype == None && m_Btype == None && !d_lattice_element_finder.has_value()); }
66 
68  void operator () (long i,
69  amrex::ParticleReal& field_Ex,
70  amrex::ParticleReal& field_Ey,
71  amrex::ParticleReal& field_Ez,
72  amrex::ParticleReal& field_Bx,
73  amrex::ParticleReal& field_By,
74  amrex::ParticleReal& field_Bz) const noexcept
75  {
76  using namespace amrex::literals;
77 
79  // Note that the "*" is needed since d_lattice_element_finder is optional
80  (*d_lattice_element_finder)(i, field_Ex, field_Ey, field_Ez,
81  field_Bx, field_By, field_Bz);
82  }
83 
84  if (m_Etype == None && m_Btype == None) return;
85 
86  amrex::ParticleReal Ex = 0._prt;
87  amrex::ParticleReal Ey = 0._prt;
88  amrex::ParticleReal Ez = 0._prt;
89  amrex::ParticleReal Bx = 0._prt;
90  amrex::ParticleReal By = 0._prt;
91  amrex::ParticleReal Bz = 0._prt;
92 
93  constexpr amrex::ParticleReal inv_c2 = 1._prt/(PhysConst::c*PhysConst::c);
94 
95  if (m_Etype == Constant)
96  {
97  Ex = m_Efield_value[0];
98  Ey = m_Efield_value[1];
99  Ez = m_Efield_value[2];
100  }
101  else if (m_Etype == ExternalFieldInitType::Parser)
102  {
103  amrex::ParticleReal x, y, z;
104  m_get_position(i, x, y, z);
105  amrex::Real lab_time = m_time;
106  if (m_gamma_boost > 1._prt) {
107  lab_time = m_gamma_boost*m_time + m_uz_boost*z*inv_c2;
109  }
110  Ex = m_Exfield_partparser((amrex::ParticleReal) x, (amrex::ParticleReal) y, (amrex::ParticleReal) z, lab_time);
111  Ey = m_Eyfield_partparser((amrex::ParticleReal) x, (amrex::ParticleReal) y, (amrex::ParticleReal) z, lab_time);
112  Ez = m_Ezfield_partparser((amrex::ParticleReal) x, (amrex::ParticleReal) y, (amrex::ParticleReal) z, lab_time);
113  }
114 
115  if (m_Btype == Constant)
116  {
117  Bx = m_Bfield_value[0];
118  By = m_Bfield_value[1];
119  Bz = m_Bfield_value[2];
120  }
121  else if (m_Btype == ExternalFieldInitType::Parser)
122  {
123  amrex::ParticleReal x, y, z;
124  m_get_position(i, x, y, z);
125  amrex::Real lab_time = m_time;
126  if (m_gamma_boost > 1._prt) {
127  lab_time = m_gamma_boost*m_time + m_uz_boost*z*inv_c2;
129  }
130  Bx = m_Bxfield_partparser(x, y, z, lab_time);
131  By = m_Byfield_partparser(x, y, z, lab_time);
132  Bz = m_Bzfield_partparser(x, y, z, lab_time);
133  }
134 
135  if (m_Etype == RepeatedPlasmaLens ||
137  {
138  amrex::ParticleReal x, y, z;
139  m_get_position(i, x, y, z);
140 
141  const amrex::ParticleReal uxp = m_ux[i];
142  const amrex::ParticleReal uyp = m_uy[i];
143  const amrex::ParticleReal uzp = m_uz[i];
144 
145  const amrex::ParticleReal gamma = std::sqrt(1._prt + (uxp*uxp + uyp*uyp + uzp*uzp)*inv_c2);
146  const amrex::ParticleReal vzp = uzp/gamma;
147 
148  // the current slice in z between now and the next time step
149  amrex::ParticleReal zl = z;
150  amrex::ParticleReal zr = z + vzp*m_dt;
151 
152  if (m_gamma_boost > 1._prt) {
153  zl = m_gamma_boost*zl + m_uz_boost*m_time;
154  zr = m_gamma_boost*zr + m_uz_boost*(m_time + m_dt);
155  }
156 
157  // the plasma lens periods do not start before z=0
158  if (zl > 0) {
159  // find which is the next lens
160  int i_lens = static_cast<int>(std::floor(zl/m_repeated_plasma_lens_period));
161  if (i_lens < m_n_lenses) {
162  amrex::ParticleReal const lens_start = m_repeated_plasma_lens_starts[i_lens] + i_lens*m_repeated_plasma_lens_period;
163  amrex::ParticleReal const lens_end = lens_start + m_repeated_plasma_lens_lengths[i_lens];
164 
165  // Calculate the residence correction
166  // frac will be 1 if the step is completely inside the lens, between 0 and 1
167  // when entering or leaving the lens, and otherwise 0.
168  // This accounts for the case when particles step over the element without landing in it.
169  // This assumes that vzp > 0.
170  amrex::ParticleReal const zl_bounded = std::min(std::max(zl, lens_start), lens_end);
171  amrex::ParticleReal const zr_bounded = std::min(std::max(zr, lens_start), lens_end);
172  amrex::ParticleReal const frac = ((zr - zl) == 0._rt ? 1._rt : (zr_bounded - zl_bounded)/(zr - zl));
173 
174  // Note that "+=" is used since the fields may have been set above
175  // if a different E or Btype was specified.
176  Ex += x*frac*m_repeated_plasma_lens_strengths_E[i_lens];
177  Ey += y*frac*m_repeated_plasma_lens_strengths_E[i_lens];
178  Bx += +y*frac*m_repeated_plasma_lens_strengths_B[i_lens];
179  By += -x*frac*m_repeated_plasma_lens_strengths_B[i_lens];
180  }
181  }
182 
183  }
184 
185  if (m_gamma_boost > 1._prt) {
186  // Transform the fields to the boosted frame
187  const amrex::ParticleReal Ex_boost = m_gamma_boost*Ex - m_uz_boost*By;
188  const amrex::ParticleReal Ey_boost = m_gamma_boost*Ey + m_uz_boost*Bx;
189  const amrex::ParticleReal Bx_boost = m_gamma_boost*Bx + m_uz_boost*Ey*inv_c2;
190  const amrex::ParticleReal By_boost = m_gamma_boost*By - m_uz_boost*Ex*inv_c2;
191  Ex = Ex_boost;
192  Ey = Ey_boost;
193  Bx = Bx_boost;
194  By = By_boost;
195  }
196 
197  field_Ex += Ex;
198  field_Ey += Ey;
199  field_Ez += Ez;
200  field_Bx += Bx;
201  field_By += By;
202  field_Bz += Bz;
203 
204  }
205 };
206 
207 #endif
#define AMREX_FORCE_INLINE
#define AMREX_GPU_HOST_DEVICE
Definition: WarpXParticleContainer.H:52
static constexpr auto c
vacuum speed of light [m/s]
Definition: constant.H:44
i
Definition: check_interp_points_and_weights.py:174
int gamma
boosted frame
Definition: stencil.py:431
Functor class that assigns external field values (E and B) to particles.
Definition: GetExternalFields.H:25
const amrex::ParticleReal *AMREX_RESTRICT m_repeated_plasma_lens_lengths
Definition: GetExternalFields.H:53
const amrex::ParticleReal *AMREX_RESTRICT m_ux
Definition: GetExternalFields.H:58
amrex::ParserExecutor< 4 > m_Bzfield_partparser
Definition: GetExternalFields.H:46
const amrex::ParticleReal *AMREX_RESTRICT m_uy
Definition: GetExternalFields.H:59
amrex::Real m_time
Definition: GetExternalFields.H:49
amrex::GpuArray< amrex::ParticleReal, 3 > m_Efield_value
Definition: GetExternalFields.H:38
const amrex::ParticleReal *AMREX_RESTRICT m_repeated_plasma_lens_strengths_B
Definition: GetExternalFields.H:55
amrex::Real m_dt
Definition: GetExternalFields.H:57
GetExternalEBField()=default
amrex::ParticleReal m_uz_boost
Definition: GetExternalFields.H:36
amrex::ParticleReal m_gamma_boost
Definition: GetExternalFields.H:35
int m_n_lenses
Definition: GetExternalFields.H:56
ExternalFieldInitType m_Etype
Definition: GetExternalFields.H:32
std::optional< LatticeElementFinderDevice > d_lattice_element_finder
Definition: GetExternalFields.H:62
GetParticlePosition< PIdx > m_get_position
Definition: GetExternalFields.H:48
ExternalFieldInitType
Definition: GetExternalFields.H:26
@ Parser
Definition: GetExternalFields.H:26
@ Unknown
Definition: GetExternalFields.H:26
@ Constant
Definition: GetExternalFields.H:26
@ None
Definition: GetExternalFields.H:26
@ RepeatedPlasmaLens
Definition: GetExternalFields.H:26
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void operator()(long i, amrex::ParticleReal &field_Ex, amrex::ParticleReal &field_Ey, amrex::ParticleReal &field_Ez, amrex::ParticleReal &field_Bx, amrex::ParticleReal &field_By, amrex::ParticleReal &field_Bz) const noexcept
Definition: GetExternalFields.H:68
ExternalFieldInitType m_Btype
Definition: GetExternalFields.H:33
amrex::ParserExecutor< 4 > m_Exfield_partparser
Definition: GetExternalFields.H:41
amrex::GpuArray< amrex::ParticleReal, 3 > m_Bfield_value
Definition: GetExternalFields.H:39
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool isNoOp() const
Definition: GetExternalFields.H:65
amrex::ParticleReal m_repeated_plasma_lens_period
Definition: GetExternalFields.H:51
amrex::ParserExecutor< 4 > m_Bxfield_partparser
Definition: GetExternalFields.H:44
const amrex::ParticleReal *AMREX_RESTRICT m_uz
Definition: GetExternalFields.H:60
const amrex::ParticleReal *AMREX_RESTRICT m_repeated_plasma_lens_strengths_E
Definition: GetExternalFields.H:54
const amrex::ParticleReal *AMREX_RESTRICT m_repeated_plasma_lens_starts
Definition: GetExternalFields.H:52
amrex::ParserExecutor< 4 > m_Byfield_partparser
Definition: GetExternalFields.H:45
amrex::ParserExecutor< 4 > m_Ezfield_partparser
Definition: GetExternalFields.H:43
amrex::ParserExecutor< 4 > m_Eyfield_partparser
Definition: GetExternalFields.H:42
Functor that can be used to extract the positions of the macroparticles inside a ParallelFor kernel.
Definition: GetAndSetPosition.H:61
The lattice element finder class that can be trivially copied to the device. This only has simple dat...
Definition: LatticeElementFinder.H:145
Definition: NamedComponentParticleContainer.H:24