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