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