WarpX
InjectorMomentum.H
Go to the documentation of this file.
1 /* Copyright 2019-2020 Andrew Myers, Axel Huebl, Cameron Yang,
2  * Maxence Thevenet, Weiqun Zhang
3  *
4  * This file is part of WarpX.
5  *
6  * License: BSD-3-Clause-LBNL
7  */
8 #ifndef INJECTOR_MOMENTUM_H_
9 #define INJECTOR_MOMENTUM_H_
10 
11 #include "GetTemperature.H"
12 #include "GetVelocity.H"
13 #include "TemperatureProperties.H"
14 #include "VelocityProperties.H"
15 #include "Utils/TextMsg.H"
16 #include "Utils/WarpXConst.H"
17 
18 #include <AMReX.H>
19 #include <AMReX_Config.H>
20 #include <AMReX_Dim3.H>
21 #include <AMReX_GpuQualifiers.H>
22 #include <AMReX_REAL.H>
23 #include <AMReX_Parser.H>
24 #include <AMReX_Random.H>
25 
26 #include <AMReX_BaseFwd.H>
27 
28 #include <cmath>
29 #include <string>
30 
31 // struct whose getMomentum returns constant momentum.
33 {
34  InjectorMomentumConstant (amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz) noexcept
35  : m_ux(a_ux), m_uy(a_uy), m_uz(a_uz) {}
36 
39  getMomentum (amrex::Real, amrex::Real, amrex::Real,
40  amrex::RandomEngine const&) const noexcept
41  {
42  return amrex::XDim3{m_ux,m_uy,m_uz};
43  }
44 
47  getBulkMomentum (amrex::Real, amrex::Real, amrex::Real) const noexcept
48  {
49  return amrex::XDim3{m_ux,m_uy,m_uz};
50  }
51 
52 private:
53  amrex::Real m_ux, m_uy, m_uz;
54 };
55 
56 // struct whose getMomentum returns momentum for 1 particle, from random
57 // gaussian distribution.
59 {
60  InjectorMomentumGaussian (amrex::Real a_ux_m, amrex::Real a_uy_m,
61  amrex::Real a_uz_m, amrex::Real a_ux_th,
62  amrex::Real a_uy_th, amrex::Real a_uz_th) noexcept
63  : m_ux_m(a_ux_m), m_uy_m(a_uy_m), m_uz_m(a_uz_m),
64  m_ux_th(a_ux_th), m_uy_th(a_uy_th), m_uz_th(a_uz_th)
65  {}
66 
69  getMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/,
70  amrex::RandomEngine const& engine) const noexcept
71  {
75  }
76 
79  getBulkMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/) const noexcept
80  {
81  return amrex::XDim3{m_ux_m, m_uy_m, m_uz_m};
82  }
83 
84 private:
85  amrex::Real m_ux_m, m_uy_m, m_uz_m;
86  amrex::Real m_ux_th, m_uy_th, m_uz_th;
87 };
88 
89 namespace {
98  amrex::Real
99  generateGaussianFluxDist( amrex::Real u_m, amrex::Real u_th, amrex::RandomEngine const& engine ) {
100 
101  using namespace amrex::literals;
102 
103  // Momentum to be returned at the end of this function
104  amrex::Real u = 0._rt;
105 
106  if (u_th == 0._rt) {
107  u = u_m; // Trivial case ; avoids division by 0 in the rest of the code below
108  } else if (u_m < 0.6*u_th) {
109  // Mean velocity is lower than thermal velocity
110  // Use the distribution u*exp(-u**2*(1-u_m/u_th)/(2*u_th**2)) as an approximation
111  // and then use the rejection method to correct it
112  // ( stop rejecting with probability exp(-u_m/(2*u_th**3)*(u-u_th)**2) )
113  // Note that this is the method that is used in the common case u_m=0
114  const amrex::Real approx_u_th = u_th/std::sqrt( 1._rt - u_m/u_th );
115  const amrex::Real reject_prefactor = (u_m/u_th)/(2._rt*u_th*u_th); // To save computation
116  bool reject = true;
117  while (reject) {
118  // Generates u according to u*exp(-u**2/(2*approx_u_th**2),
119  // using the method of the inverse cumulative function
120  amrex::Real xrand = 1._rt - amrex::Random(engine); // ensures urand > 0
121  u = approx_u_th * std::sqrt(2._rt*std::log(1._rt/xrand));
122  // Rejection method
123  xrand = amrex::Random(engine);
124  if (xrand < std::exp(-reject_prefactor*(u-u_th)*(u-u_th))) reject = false;
125  }
126  } else {
127  // Mean velocity is greater than thermal velocity
128  // Use the distribution exp(-(u-u_m-u_th**2/u_m)**2/(2*u_th**2)) as an approximation
129  // and then use the rejection method to correct it
130  // ( stop rejecting with probability (u/u_m)*exp(1-(u/u_m)) ; note
131  // that this number is always between 0 and 1 )
132  // Note that in the common case `u_m = 0`, this rejection method
133  // is not used, and the above rejection method is used instead.
134  bool reject = true;
135  const amrex::Real approx_u_m = u_m + u_th*u_th/u_m;
136  const amrex::Real inv_um = 1._rt/u_m; // To save computation
137  while (reject) {
138  // Approximate distribution: normal distribution, where we only retain positive u
139  u = -1._rt;
140  while (u < 0) {
141  u = amrex::RandomNormal(approx_u_m, u_th, engine);
142  }
143  // Rejection method
144  const amrex::Real xrand = amrex::Random(engine);
145  if (xrand < u*inv_um* std::exp(1._rt - u*inv_um)) reject = false;
146  }
147  }
148 
149  return u;
150  }
151 }
152 
153 // struct whose getMomentum returns momentum for 1 particle, from random
154 // gaussian flux distribution in the specified direction.
155 // Along the normal axis, the distribution is v*Gaussian,
156 // with the sign set by flux_direction.
158 {
159  InjectorMomentumGaussianFlux (amrex::Real a_ux_m, amrex::Real a_uy_m,
160  amrex::Real a_uz_m, amrex::Real a_ux_th,
161  amrex::Real a_uy_th, amrex::Real a_uz_th,
162  int a_flux_normal_axis, int a_flux_direction) noexcept
163  : m_ux_m(a_ux_m), m_uy_m(a_uy_m), m_uz_m(a_uz_m),
164  m_ux_th(a_ux_th), m_uy_th(a_uy_th), m_uz_th(a_uz_th),
165  m_flux_normal_axis(a_flux_normal_axis),
166  m_flux_direction(a_flux_direction)
167  {
168  // For now, do not allow negative `u_m` along the flux axis
169  bool raise_error = false;
170  if ((m_flux_normal_axis == 0) && (m_ux_m < 0)) raise_error = true;
171  if ((m_flux_normal_axis == 1) && (m_uy_m < 0)) raise_error = true;
172  if ((m_flux_normal_axis == 2) && (m_uz_m < 0)) raise_error = true;
173  WARPX_ALWAYS_ASSERT_WITH_MESSAGE( raise_error==false,
174  "When using the `gaussianflux` distribution, the central momentum along the flux axis must be positive or zero." );
175  }
176 
179  getMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/,
180  amrex::RandomEngine const& engine) const noexcept
181  {
182  using namespace amrex::literals;
183 
184  // Generate the distribution in the direction of the flux
185  amrex::Real u_m = 0, u_th = 0;
186  if (m_flux_normal_axis == 0) {
187  u_m = m_ux_m;
188  u_th = m_ux_th;
189  } else if (m_flux_normal_axis == 1) {
190  u_m = m_uy_m;
191  u_th = m_uy_th;
192  } else if (m_flux_normal_axis == 2) {
193  u_m = m_uz_m;
194  u_th = m_uz_th;
195  }
196  amrex::Real u = generateGaussianFluxDist(u_m, u_th, engine);
197  if (m_flux_direction < 0) u = -u;
198 
199  // Note: Here, in RZ geometry, the variables `ux` and `uy` actually
200  // correspond to the radial and azimuthal component of the momentum
201  // (and e.g.`m_flux_normal_axis==1` corresponds to v*Gaussian along theta)
202  amrex::Real const ux = (m_flux_normal_axis == 0 ? u : amrex::RandomNormal(m_ux_m, m_ux_th, engine));
203  amrex::Real const uy = (m_flux_normal_axis == 1 ? u : amrex::RandomNormal(m_uy_m, m_uy_th, engine));
204  amrex::Real const uz = (m_flux_normal_axis == 2 ? u : amrex::RandomNormal(m_uz_m, m_uz_th, engine));
205  return amrex::XDim3{ux, uy, uz};
206  }
207 
210  getBulkMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/) const noexcept
211  {
212  return amrex::XDim3{m_ux_m, m_uy_m, m_uz_m};
213  }
214 
215 private:
216  amrex::Real m_ux_m, m_uy_m, m_uz_m;
217  amrex::Real m_ux_th, m_uy_th, m_uz_th;
220 };
221 
222 
223 // struct whose getMomentum returns momentum for 1 particle, from random
224 // uniform distribution u_min < u < u_max
226 {
227  InjectorMomentumUniform (amrex::Real a_ux_min, amrex::Real a_uy_min,
228  amrex::Real a_uz_min, amrex::Real a_ux_max,
229  amrex::Real a_uy_max, amrex::Real a_uz_max) noexcept
230  : m_ux_min(a_ux_min), m_uy_min(a_uy_min), m_uz_min(a_uz_min),
231  m_ux_max(a_ux_max), m_uy_max(a_uy_max), m_uz_max(a_uz_max)
232  {
233  m_Dux = m_ux_max - m_ux_min;
234  m_Duy = m_uy_max - m_uy_min;
235  m_Duz = m_uz_max - m_uz_min;
236  m_ux_h = 0.5 * (m_ux_max + m_ux_min);
237  m_uy_h = 0.5 * (m_uy_max + m_uy_min);
238  m_uz_h = 0.5 * (m_uz_max + m_uz_min);
239  }
240 
243  getMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/,
244  amrex::RandomEngine const& engine) const noexcept
245  {
246  return amrex::XDim3{m_ux_min + amrex::Random(engine) * m_Dux,
247  m_uy_min + amrex::Random(engine) * m_Duy,
248  m_uz_min + amrex::Random(engine) * m_Duz};
249  }
250 
253  getBulkMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/) const noexcept
254  {
255  return amrex::XDim3{m_ux_h, m_uy_h, m_uz_h};
256  }
257 
258 private:
259  amrex::Real m_ux_min, m_uy_min, m_uz_min;
260  amrex::Real m_ux_max, m_uy_max, m_uz_max;
261  amrex::Real m_ux_h, m_uy_h, m_uz_h;
262  amrex::Real m_Dux, m_Duy, m_Duz;
263 };
264 
265 // struct whose getMomentum returns momentum for 1 particle with relativistic
266 // drift velocity beta, from the Maxwell-Boltzmann distribution.
268 {
269  // Constructor whose inputs are:
270  // a reference to the initial temperature container t,
271  // a reference to the initial velocity container b
273  : velocity(b), temperature(t)
274  {}
275 
278  getMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z,
279  amrex::RandomEngine const& engine) const noexcept
280  {
281  using namespace amrex::literals;
282 
283  // Calculate the local temperature and check if it's too
284  // high for Boltzmann or less than zero
285  amrex::Real const theta = temperature(x,y,z);
286  if (theta < 0._rt) {
287  amrex::Abort("Negative temperature parameter theta encountered, which is not allowed");
288  }
289  // Calculate local velocity and abort if |beta|>=1
290  amrex::Real const beta = velocity(x,y,z);
291  if (beta <= -1._rt || beta >= 1._rt) {
292  amrex::Abort("beta = v/c magnitude greater than or equal to 1");
293  }
294  // Calculate the value of vave from the local temperature
295  amrex::Real const vave = std::sqrt(theta);
296  int const dir = velocity.direction();
297 
298  amrex::Real u[3];
299  u[dir] = amrex::RandomNormal(0._rt, vave, engine);
300  u[(dir+1)%3] = amrex::RandomNormal(0._rt, vave, engine);
301  u[(dir+2)%3] = amrex::RandomNormal(0._rt, vave, engine);
302  amrex::Real const gamma = std::sqrt(1._rt + u[0]*u[0]+u[1]*u[1]+u[2]*u[2]);
303 
304  // The following condition is equation 32 in Zenitani 2015
305  // (Phys. Plasmas 22, 042116) , called the flipping method. It
306  // transforms the intergral: d3x' -> d3x where d3x' is the volume
307  // element for positions in the boosted frame. The particle positions
308  // and densities can be initialized in the simulation frame.
309  // The flipping method can transform any symmetric distribution from one
310  // reference frame to another moving at a relative velocity of beta.
311  // An equivalent alternative to this method native to WarpX would be to
312  // initialize the particle positions and densities in the frame moving
313  // at speed beta, and then perform a Lorentz transform on the positions
314  // and MB sampled velocities to the simulation frame.
315  if(-beta*u[dir]/gamma > amrex::Random(engine))
316  {
317  u[dir] = -u[dir];
318  }
319  // This Lorentz transform is equation 17 in Zenitani.
320  // It transforms the integral d3u' -> d3u
321  // where d3u' is the volume element for momentum in the boosted frame.
322  u[dir] = 1._rt/std::sqrt(1._rt-beta*beta)*(u[dir]+gamma*beta);
323  // Note that if beta = 0 then the flipping method and Lorentz transform
324  // have no effect on the u[dir] direction.
325  return amrex::XDim3 {u[0],u[1],u[2]};
326  }
327 
330  getBulkMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
331  {
332  using namespace amrex::literals;
333  amrex::Real u[3];
334  for (auto& el : u) el = 0.0_rt;
335  const amrex::Real beta = velocity(x,y,z);
336  int const dir = velocity.direction();
337  const amrex::Real gamma = static_cast<amrex::Real>(1._rt/sqrt(1._rt-beta*beta));
338  u[dir] = gamma*beta;
339  return amrex::XDim3 {u[0],u[1],u[2]};
340  }
341 
342 private:
345 };
346 
347 // struct whose getMomentum returns momentum for 1 particle with relativistc
348 // drift velocity beta, from the Maxwell-Juttner distribution. Method is from
349 // Zenitani 2015 (Phys. Plasmas 22, 042116).
351 {
352  // Constructor whose inputs are:
353  // a reference to the initial temperature container t,
354  // a reference to the initial velocity container b
356  : velocity(b), temperature(t)
357  {}
358 
361  getMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z,
362  amrex::RandomEngine const& engine) const noexcept
363  {
364  using namespace amrex::literals;
365  // Sobol method for sampling MJ Speeds,
366  // from Zenitani 2015 (Phys. Plasmas 22, 042116).
367  amrex::Real x1, x2, gamma;
368  amrex::Real u [3];
369  amrex::Real const theta = temperature(x,y,z);
370  // Check if temperature is too low to do sampling method. Abort for now,
371  // in future should implement an alternate method e.g. inverse transform
372  if (theta < 0.1_rt) {
373  amrex::Abort("Temeprature parameter theta is less than minimum 0.1 allowed for Maxwell-Juttner");
374  }
375  // Calculate local velocity and abort if |beta|>=1
376  amrex::Real const beta = velocity(x,y,z);
377  if (beta <= -1._rt || beta >= 1._rt) {
378  amrex::Abort("beta = v/c magnitude greater than or equal to 1");
379  }
380  int const dir = velocity.direction();
381  x1 = static_cast<amrex::Real>(0._rt);
382  gamma = static_cast<amrex::Real>(0._rt);
383  u[dir] = static_cast<amrex::Real>(0._rt);
384  // This condition is equation 10 in Zenitani,
385  // though x1 is defined differently.
386  while(u[dir]-gamma <= x1)
387  {
388  u[dir] = -theta*
389  std::log(amrex::Random(engine)*amrex::Random(engine)*amrex::Random(engine));
390  gamma = std::sqrt(1._rt+u[dir]*u[dir]);
391  x1 = theta*std::log(amrex::Random(engine));
392  }
393  // The following code samples a random unit vector
394  // and multiplies the result by speed u[dir].
395  x1 = amrex::Random(engine);
396  x2 = amrex::Random(engine);
397  // Direction dir is an input parameter that sets the boost direction:
398  // 'x' -> d = 0, 'y' -> d = 1, 'z' -> d = 2.
399  u[(dir+1)%3] = 2._rt*u[dir]*std::sqrt(x1*(1._rt-x1))*std::sin(2._rt*MathConst::pi*x2);
400  u[(dir+2)%3] = 2._rt*u[dir]*std::sqrt(x1*(1._rt-x1))*std::cos(2._rt*MathConst::pi*x2);
401  // The value of dir is the boost direction to be transformed.
402  u[dir] = u[dir]*(2._rt*x1-1._rt);
403  x1 = amrex::Random(engine);
404  // The following condition is equtaion 32 in Zenitani, called
405  // The flipping method. It transforms the intergral: d3x' -> d3x
406  // where d3x' is the volume element for positions in the boosted frame.
407  // The particle positions and densities can be initialized in the
408  // simulation frame with this method.
409  // The flipping method can similarly transform any
410  // symmetric distribution from one reference frame to another moving at
411  // a relative velocity of beta.
412  // An equivalent alternative to this method native to WarpX
413  // would be to initialize the particle positions and densities in the
414  // frame moving at speed beta, and then perform a Lorentz transform
415  // on their positions and MJ sampled velocities to the simulation frame.
416  if(-beta*u[dir]/gamma>x1)
417  {
418  u[dir] = -u[dir];
419  }
420  // This Lorentz transform is equation 17 in Zenitani.
421  // It transforms the integral d3u' -> d3u
422  // where d3u' is the volume element for momentum in the boosted frame.
423  u[dir] = 1._rt/std::sqrt(1._rt-beta*beta)*(u[dir]+gamma*beta);
424  // Note that if beta = 0 then the flipping method and Lorentz transform
425  // have no effect on the u[dir] direction.
426  return amrex::XDim3 {u[0],u[1],u[2]};
427  }
428 
431  getBulkMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
432  {
433  using namespace amrex::literals;
434  amrex::Real u[3];
435  for (auto& el : u) el = 0.0_rt;
436  amrex::Real const beta = velocity(x,y,z);
437  int const dir = velocity.direction();
438  amrex::Real const gamma = static_cast<amrex::Real>(1._rt/sqrt(1._rt-beta*beta));
439  u[dir] = gamma*beta;
440  return amrex::XDim3 {u[0],u[1],u[2]};
441  }
442 
443 private:
446 };
447 
456 {
457  InjectorMomentumRadialExpansion (amrex::Real a_u_over_r) noexcept
458  : u_over_r(a_u_over_r)
459  {}
460 
463  getMomentum (amrex::Real x, amrex::Real y, amrex::Real z,
464  amrex::RandomEngine const&) const noexcept
465  {
466  return {x*u_over_r, y*u_over_r, z*u_over_r};
467  }
468 
471  getBulkMomentum (amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
472  {
473  return {x*u_over_r, y*u_over_r, z*u_over_r};
474  }
475 
476 private:
477  amrex::Real u_over_r;
478 };
479 
480 // struct whose getMomentumm returns local momentum computed from parser.
482 {
484  amrex::ParserExecutor<3> const& a_uy_parser,
485  amrex::ParserExecutor<3> const& a_uz_parser) noexcept
486  : m_ux_parser(a_ux_parser), m_uy_parser(a_uy_parser),
487  m_uz_parser(a_uz_parser) {}
488 
491  getMomentum (amrex::Real x, amrex::Real y, amrex::Real z,
492  amrex::RandomEngine const&) const noexcept
493  {
494  return amrex::XDim3{m_ux_parser(x,y,z),m_uy_parser(x,y,z),m_uz_parser(x,y,z)};
495  }
496 
499  getBulkMomentum (amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
500  {
501  return amrex::XDim3{m_ux_parser(x,y,z),m_uy_parser(x,y,z),m_uz_parser(x,y,z)};
502  }
503 
504  amrex::ParserExecutor<3> m_ux_parser, m_uy_parser, m_uz_parser;
505 };
506 
507 // Base struct for momentum injector.
508 // InjectorMomentum contains a union (called Object) that holds any one
509 // instance of:
510 // - InjectorMomentumConstant : to generate constant density;
511 // - InjectorMomentumGaussian : to generate gaussian distribution;
512 // - InjectorMomentumGaussianFlux : to generate v*gaussian distribution;
513 // - InjectorMomentumRadialExpansion: to generate radial expansion;
514 // - InjectorMomentumParser : to generate momentum from parser;
515 // The choice is made at runtime, depending in the constructor called.
516 // This mimics virtual functions.
518 {
519  // This constructor stores a InjectorMomentumConstant in union object.
521  amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz)
522  : type(Type::constant),
523  object(t, a_ux, a_uy, a_uz)
524  { }
525 
526  // This constructor stores a InjectorMomentumParser in union object.
528  amrex::ParserExecutor<3> const& a_ux_parser,
529  amrex::ParserExecutor<3> const& a_uy_parser,
530  amrex::ParserExecutor<3> const& a_uz_parser)
531  : type(Type::parser),
532  object(t, a_ux_parser, a_uy_parser, a_uz_parser)
533  { }
534 
535  // This constructor stores a InjectorMomentumGaussian in union object.
537  amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m,
538  amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th)
539  : type(Type::gaussian),
540  object(t,a_ux_m,a_uy_m,a_uz_m,a_ux_th,a_uy_th,a_uz_th)
541  { }
542 
543  // This constructor stores a InjectorMomentumGaussianFlux in union object.
545  amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m,
546  amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th,
547  int a_flux_normal_axis, int a_flux_direction)
548  : type(Type::gaussianflux),
549  object(t,a_ux_m,a_uy_m,a_uz_m,a_ux_th,a_uy_th,a_uz_th,a_flux_normal_axis,a_flux_direction)
550  { }
551 
552  // This constructor stores a InjectorMomentumUniform in union object.
554  amrex::Real a_ux_min, amrex::Real a_uy_min, amrex::Real a_uz_min,
555  amrex::Real a_ux_max, amrex::Real a_uy_max, amrex::Real a_uz_max)
556  : type(Type::uniform),
557  object(t,a_ux_min,a_uy_min,a_uz_min,a_ux_max,a_uy_max,a_uz_max)
558  { }
559 
561  GetTemperature const& temperature, GetVelocity const& velocity)
562  : type(Type::boltzmann),
563  object(t, temperature, velocity)
564  { }
565 
566  // This constructor stores a InjectorMomentumJuttner in union object.
568  GetTemperature const& temperature, GetVelocity const& velocity)
569  : type(Type::juttner),
570  object(t, temperature, velocity)
571  { }
572 
573  // This constructor stores a InjectorMomentumRadialExpansion in union object.
575  amrex::Real u_over_r)
576  : type(Type::radial_expansion),
577  object(t, u_over_r)
578  { }
579 
580  // Explicitly prevent the compiler from generating copy constructors
581  // and copy assignment operators.
584  void operator= (InjectorMomentum const&) = delete;
585  void operator= (InjectorMomentum &&) = delete;
586 
587  void clear ();
588 
589  // call getMomentum from the object stored in the union
590  // (the union is called Object, and the instance is called object).
593  getMomentum (amrex::Real x, amrex::Real y, amrex::Real z,
594  amrex::RandomEngine const& engine) const noexcept
595  {
596  switch (type)
597  {
598  case Type::parser:
599  {
600  return object.parser.getMomentum(x,y,z,engine);
601  }
602  case Type::gaussian:
603  {
604  return object.gaussian.getMomentum(x,y,z,engine);
605  }
606  case Type::gaussianflux:
607  {
608  return object.gaussianflux.getMomentum(x,y,z,engine);
609  }
610  case Type::uniform:
611  {
612  return object.uniform.getMomentum(x,y,z,engine);
613  }
614  case Type::boltzmann:
615  {
616  return object.boltzmann.getMomentum(x,y,z,engine);
617  }
618  case Type::juttner:
619  {
620  return object.juttner.getMomentum(x,y,z,engine);
621  }
622  case Type::constant:
623  {
624  return object.constant.getMomentum(x,y,z,engine);
625  }
626  case Type::radial_expansion:
627  {
628  return object.radial_expansion.getMomentum(x,y,z,engine);
629  }
630  default:
631  {
632  amrex::Abort("InjectorMomentum: unknown type");
633  return {0.0,0.0,0.0};
634  }
635  }
636  }
637 
638  // call getBulkMomentum from the object stored in the union
639  // (the union is called Object, and the instance is called object).
642  getBulkMomentum (amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
643  {
644  switch (type)
645  {
646  case Type::parser:
647  {
648  return object.parser.getBulkMomentum(x,y,z);
649  }
650  case Type::gaussian:
651  {
652  return object.gaussian.getBulkMomentum(x,y,z);
653  }
654  case Type::gaussianflux:
655  {
656  return object.gaussianflux.getBulkMomentum(x,y,z);
657  }
658  case Type::uniform:
659  {
660  return object.uniform.getBulkMomentum(x,y,z);
661  }
662  case Type::boltzmann:
663  {
664  return object.boltzmann.getBulkMomentum(x,y,z);
665  }
666  case Type::juttner:
667  {
668  return object.juttner.getBulkMomentum(x,y,z);
669  }
670  case Type::constant:
671  {
672  return object.constant.getBulkMomentum(x,y,z);
673  }
674  case Type::radial_expansion:
675  {
676  return object.radial_expansion.getBulkMomentum(x,y,z);
677  }
678  default:
679  {
680  amrex::Abort("InjectorMomentum: unknown type");
681  return {0.0,0.0,0.0};
682  }
683  }
684  }
685 
686  enum struct Type { constant, gaussian, gaussianflux, uniform, boltzmann, juttner, radial_expansion, parser };
688 
689 private:
690 
691  // An instance of union Object constructs and stores any one of
692  // the objects declared (constant or gaussian or
693  // radial_expansion or parser).
694  union Object {
696  amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz) noexcept
697  : constant(a_ux,a_uy,a_uz) {}
699  amrex::Real a_ux_m, amrex::Real a_uy_m,
700  amrex::Real a_uz_m, amrex::Real a_ux_th,
701  amrex::Real a_uy_th, amrex::Real a_uz_th) noexcept
702  : gaussian(a_ux_m,a_uy_m,a_uz_m,a_ux_th,a_uy_th,a_uz_th) {}
704  amrex::Real a_ux_m, amrex::Real a_uy_m,
705  amrex::Real a_uz_m, amrex::Real a_ux_th,
706  amrex::Real a_uy_th, amrex::Real a_uz_th,
707  int a_flux_normal_axis, int a_flux_direction) noexcept
708  : gaussianflux(a_ux_m,a_uy_m,a_uz_m,a_ux_th,a_uy_th,a_uz_th,a_flux_normal_axis,a_flux_direction) {}
710  amrex::Real a_ux_min, amrex::Real a_uy_min,
711  amrex::Real a_uz_min, amrex::Real a_ux_max,
712  amrex::Real a_uy_max, amrex::Real a_uz_max) noexcept
713  : uniform(a_ux_min,a_uy_min,a_uz_min,a_ux_max,a_uy_max,a_uz_max) {}
715  GetTemperature const& t, GetVelocity const& b) noexcept
716  : boltzmann(t,b) {}
718  GetTemperature const& t, GetVelocity const& b) noexcept
719  : juttner(t,b) {}
721  amrex::Real u_over_r) noexcept
722  : radial_expansion(u_over_r) {}
724  amrex::ParserExecutor<3> const& a_ux_parser,
725  amrex::ParserExecutor<3> const& a_uy_parser,
726  amrex::ParserExecutor<3> const& a_uz_parser) noexcept
727  : parser(a_ux_parser, a_uy_parser, a_uz_parser) {}
736  };
738 };
739 
740 // In order for InjectorMomentum to be trivially copyable, its destructor
741 // must be trivial. So we have to rely on a custom deleter for unique_ptr.
743  void operator () (InjectorMomentum* p) const {
744  if (p) {
745  p->clear();
746  delete p;
747  }
748  }
749 };
750 
751 #endif
#define AMREX_GPU_HOST_DEVICE
#define WARPX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition: TextMsg.H:13
Real Random()
Real RandomNormal(Real mean, Real stddev)
void Abort(const std::string &msg)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
list x1
Definition: plot_particle_path.py:130
type
Definition: run_alltests_1node.py:72
beta
Definition: stencil.py:432
int gamma
boosted frame
Definition: stencil.py:429
parser
Definition: stencil.py:409
Get temperature at a point on the grid.
Definition: GetTemperature.H:23
Definition: GetVelocity.H:21
Definition: InjectorMomentum.H:268
GetTemperature temperature
Definition: InjectorMomentum.H:344
GetVelocity velocity
Definition: InjectorMomentum.H:343
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real const x, amrex::Real const y, amrex::Real const z, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:278
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
Definition: InjectorMomentum.H:330
InjectorMomentumBoltzmann(GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:272
Definition: InjectorMomentum.H:33
amrex::Real m_uy
Definition: InjectorMomentum.H:53
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:47
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real, amrex::Real, amrex::Real, amrex::RandomEngine const &) const noexcept
Definition: InjectorMomentum.H:39
amrex::Real m_ux
Definition: InjectorMomentum.H:53
InjectorMomentumConstant(amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz) noexcept
Definition: InjectorMomentum.H:34
amrex::Real m_uz
Definition: InjectorMomentum.H:53
Definition: InjectorMomentum.H:742
Definition: InjectorMomentum.H:158
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:210
amrex::Real m_uy_m
Definition: InjectorMomentum.H:216
int m_flux_normal_axis
Definition: InjectorMomentum.H:218
amrex::Real m_ux_m
Definition: InjectorMomentum.H:216
amrex::Real m_uz_th
Definition: InjectorMomentum.H:217
amrex::Real m_ux_th
Definition: InjectorMomentum.H:217
amrex::Real m_uy_th
Definition: InjectorMomentum.H:217
InjectorMomentumGaussianFlux(amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m, amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th, int a_flux_normal_axis, int a_flux_direction) noexcept
Definition: InjectorMomentum.H:159
amrex::Real m_uz_m
Definition: InjectorMomentum.H:216
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real, amrex::Real, amrex::Real, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:179
int m_flux_direction
Definition: InjectorMomentum.H:219
Definition: InjectorMomentum.H:59
amrex::Real m_uz_m
Definition: InjectorMomentum.H:85
amrex::Real m_ux_m
Definition: InjectorMomentum.H:85
amrex::Real m_ux_th
Definition: InjectorMomentum.H:86
amrex::Real m_uy_th
Definition: InjectorMomentum.H:86
amrex::Real m_uy_m
Definition: InjectorMomentum.H:85
InjectorMomentumGaussian(amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m, amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th) noexcept
Definition: InjectorMomentum.H:60
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real, amrex::Real, amrex::Real, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:69
amrex::Real m_uz_th
Definition: InjectorMomentum.H:86
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:79
Definition: InjectorMomentum.H:518
InjectorMomentum(InjectorMomentumRadialExpansion *t, amrex::Real u_over_r)
Definition: InjectorMomentum.H:574
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real x, amrex::Real y, amrex::Real z, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:593
Type type
Definition: InjectorMomentum.H:687
InjectorMomentum(InjectorMomentum &&)=delete
InjectorMomentum(InjectorMomentumParser *t, amrex::ParserExecutor< 3 > const &a_ux_parser, amrex::ParserExecutor< 3 > const &a_uy_parser, amrex::ParserExecutor< 3 > const &a_uz_parser)
Definition: InjectorMomentum.H:527
void clear()
Definition: InjectorMomentum.cpp:12
InjectorMomentum(InjectorMomentumConstant *t, amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz)
Definition: InjectorMomentum.H:520
InjectorMomentum(InjectorMomentum const &)=delete
InjectorMomentum(InjectorMomentumGaussian *t, amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m, amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th)
Definition: InjectorMomentum.H:536
InjectorMomentum(InjectorMomentumUniform *t, amrex::Real a_ux_min, amrex::Real a_uy_min, amrex::Real a_uz_min, amrex::Real a_ux_max, amrex::Real a_uy_max, amrex::Real a_uz_max)
Definition: InjectorMomentum.H:553
Type
Definition: InjectorMomentum.H:686
Object object
Definition: InjectorMomentum.H:737
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
Definition: InjectorMomentum.H:642
InjectorMomentum(InjectorMomentumGaussianFlux *t, amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m, amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th, int a_flux_normal_axis, int a_flux_direction)
Definition: InjectorMomentum.H:544
InjectorMomentum(InjectorMomentumBoltzmann *t, GetTemperature const &temperature, GetVelocity const &velocity)
Definition: InjectorMomentum.H:560
InjectorMomentum(InjectorMomentumJuttner *t, GetTemperature const &temperature, GetVelocity const &velocity)
Definition: InjectorMomentum.H:567
Definition: InjectorMomentum.H:351
GetVelocity velocity
Definition: InjectorMomentum.H:444
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
Definition: InjectorMomentum.H:431
GetTemperature temperature
Definition: InjectorMomentum.H:445
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real const x, amrex::Real const y, amrex::Real const z, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:361
InjectorMomentumJuttner(GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:355
Definition: InjectorMomentum.H:482
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real x, amrex::Real y, amrex::Real z, amrex::RandomEngine const &) const noexcept
Definition: InjectorMomentum.H:491
InjectorMomentumParser(amrex::ParserExecutor< 3 > const &a_ux_parser, amrex::ParserExecutor< 3 > const &a_uy_parser, amrex::ParserExecutor< 3 > const &a_uz_parser) noexcept
Definition: InjectorMomentum.H:483
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
Definition: InjectorMomentum.H:499
amrex::ParserExecutor< 3 > m_ux_parser
Definition: InjectorMomentum.H:504
struct whose getMomentum returns momentum for 1 particle, for radial expansion.
Definition: InjectorMomentum.H:456
InjectorMomentumRadialExpansion(amrex::Real a_u_over_r) noexcept
Definition: InjectorMomentum.H:457
amrex::Real u_over_r
Definition: InjectorMomentum.H:477
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real x, amrex::Real y, amrex::Real z, amrex::RandomEngine const &) const noexcept
Definition: InjectorMomentum.H:463
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
Definition: InjectorMomentum.H:471
Definition: InjectorMomentum.H:226
amrex::Real m_Dux
Definition: InjectorMomentum.H:262
amrex::Real m_ux_h
Definition: InjectorMomentum.H:261
amrex::Real m_ux_max
Definition: InjectorMomentum.H:260
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:253
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real, amrex::Real, amrex::Real, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:243
InjectorMomentumUniform(amrex::Real a_ux_min, amrex::Real a_uy_min, amrex::Real a_uz_min, amrex::Real a_ux_max, amrex::Real a_uy_max, amrex::Real a_uz_max) noexcept
Definition: InjectorMomentum.H:227
amrex::Real m_ux_min
Definition: InjectorMomentum.H:259
Definition: InjectorMomentum.H:694
InjectorMomentumGaussian gaussian
Definition: InjectorMomentum.H:729
InjectorMomentumUniform uniform
Definition: InjectorMomentum.H:731
Object(InjectorMomentumGaussianFlux *, amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m, amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th, int a_flux_normal_axis, int a_flux_direction) noexcept
Definition: InjectorMomentum.H:703
Object(InjectorMomentumBoltzmann *, GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:714
Object(InjectorMomentumParser *, amrex::ParserExecutor< 3 > const &a_ux_parser, amrex::ParserExecutor< 3 > const &a_uy_parser, amrex::ParserExecutor< 3 > const &a_uz_parser) noexcept
Definition: InjectorMomentum.H:723
InjectorMomentumJuttner juttner
Definition: InjectorMomentum.H:733
Object(InjectorMomentumUniform *, amrex::Real a_ux_min, amrex::Real a_uy_min, amrex::Real a_uz_min, amrex::Real a_ux_max, amrex::Real a_uy_max, amrex::Real a_uz_max) noexcept
Definition: InjectorMomentum.H:709
InjectorMomentumRadialExpansion radial_expansion
Definition: InjectorMomentum.H:734
InjectorMomentumBoltzmann boltzmann
Definition: InjectorMomentum.H:732
InjectorMomentumGaussianFlux gaussianflux
Definition: InjectorMomentum.H:730
Object(InjectorMomentumJuttner *, GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:717
Object(InjectorMomentumRadialExpansion *, amrex::Real u_over_r) noexcept
Definition: InjectorMomentum.H:720
Object(InjectorMomentumGaussian *, amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m, amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th) noexcept
Definition: InjectorMomentum.H:698
InjectorMomentumParser parser
Definition: InjectorMomentum.H:735
InjectorMomentumConstant constant
Definition: InjectorMomentum.H:728
Object(InjectorMomentumConstant *, amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz) noexcept
Definition: InjectorMomentum.H:695