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 
37  [[nodiscard]]
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 
46  [[nodiscard]]
49  getBulkMomentum (amrex::Real, amrex::Real, amrex::Real) const noexcept
50  {
51  return amrex::XDim3{m_ux,m_uy,m_uz};
52  }
53 
54 private:
55  amrex::Real m_ux, m_uy, m_uz;
56 };
57 
58 // struct whose getMomentum returns momentum for 1 particle, from random
59 // gaussian distribution.
61 {
62  InjectorMomentumGaussian (amrex::Real a_ux_m, amrex::Real a_uy_m,
63  amrex::Real a_uz_m, amrex::Real a_ux_th,
64  amrex::Real a_uy_th, amrex::Real a_uz_th) noexcept
65  : m_ux_m(a_ux_m), m_uy_m(a_uy_m), m_uz_m(a_uz_m),
66  m_ux_th(a_ux_th), m_uy_th(a_uy_th), m_uz_th(a_uz_th)
67  {}
68 
69  [[nodiscard]]
72  getMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/,
73  amrex::RandomEngine const& engine) const noexcept
74  {
78  }
79 
80  [[nodiscard]]
83  getBulkMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/) const noexcept
84  {
85  return amrex::XDim3{m_ux_m, m_uy_m, m_uz_m};
86  }
87 
88 private:
89  amrex::Real m_ux_m, m_uy_m, m_uz_m;
90  amrex::Real m_ux_th, m_uy_th, m_uz_th;
91 };
92 
93 namespace {
101  [[nodiscard]]
104  amrex::Real
105  generateGaussianFluxDist( amrex::Real u_m, amrex::Real u_th, amrex::RandomEngine const& engine ) {
106 
107  using namespace amrex::literals;
108 
109  // Momentum to be returned at the end of this function
110  amrex::Real u = 0._rt;
111 
112  const amrex::Real abs_u_m = std::abs(u_m);
113 
114  if (u_th == 0._rt) {
115  u = u_m; // Trivial case ; avoids division by 0 in the rest of the code below
116  } else if (abs_u_m < 0.6*u_th) {
117  // Mean velocity magnitude is less than thermal velocity
118  // Use the distribution u*exp(-u**2*(1-abs(u_m)/u_th)/(2*u_th**2)) as an approximation
119  // and then use the rejection method to correct it
120  // ( stop rejecting with probability exp(-abs(u_m)/(2*u_th**3)*(u-sign(u_m)*u_th)**2) )
121  // Note that this is the method that is used in the common case u_m=0
122  const amrex::Real umsign = std::copysign(1._rt, u_m);
123  const amrex::Real approx_u_th = u_th/std::sqrt( 1._rt - abs_u_m/u_th );
124  const amrex::Real reject_prefactor = (abs_u_m/u_th)/(2._rt*u_th*u_th); // To save computation
125  bool reject = true;
126  while (reject) {
127  // Generates u according to u*exp(-u**2/(2*approx_u_th**2)),
128  // using the method of the inverse cumulative function
129  amrex::Real xrand = 1._rt - amrex::Random(engine); // ensures urand > 0
130  u = approx_u_th * std::sqrt(2._rt*std::log(1._rt/xrand));
131  // Rejection method
132  xrand = amrex::Random(engine);
133  if (xrand < std::exp(-reject_prefactor*(u - umsign*u_th)*(u - umsign*u_th))) { reject = false; }
134  }
135  } else {
136  // Mean velocity magnitude is greater than thermal velocity
137  // Use the distribution exp(-(u-u_m-u_th**2/abs(u_m))**2/(2*u_th**2)) as an approximation
138  // and then use the rejection method to correct it
139  // ( stop rejecting with probability (u/abs(u_m))*exp(1-(u/abs(u_m))) ; note
140  // that this number is always between 0 and 1 )
141  // Note that in the common case `u_m = 0`, this rejection method
142  // is not used, and the above rejection method is used instead.
143  bool reject = true;
144  const amrex::Real approx_u_m = u_m + u_th*u_th/abs_u_m;
145  const amrex::Real inv_um = 1._rt/abs_u_m; // To save computation
146  while (reject) {
147  // Approximate distribution: normal distribution, where we only retain positive u
148  u = -1._rt;
149  while (u < 0) {
150  u = amrex::RandomNormal(approx_u_m, u_th, engine);
151  }
152  // Rejection method
153  const amrex::Real xrand = amrex::Random(engine);
154  if (xrand < u*inv_um* std::exp(1._rt - u*inv_um)) { reject = false; }
155  }
156  }
157 
158  return u;
159  }
160 }
161 
162 // struct whose getMomentum returns momentum for 1 particle, from random
163 // gaussian flux distribution in the specified direction.
164 // Along the normal axis, the distribution is v*Gaussian,
165 // with the sign set by flux_direction.
167 {
168  InjectorMomentumGaussianFlux (amrex::Real a_ux_m, amrex::Real a_uy_m,
169  amrex::Real a_uz_m, amrex::Real a_ux_th,
170  amrex::Real a_uy_th, amrex::Real a_uz_th,
171  int a_flux_normal_axis, int a_flux_direction) noexcept
172  : m_ux_m(a_ux_m), m_uy_m(a_uy_m), m_uz_m(a_uz_m),
173  m_ux_th(a_ux_th), m_uy_th(a_uy_th), m_uz_th(a_uz_th),
174  m_flux_normal_axis(a_flux_normal_axis),
175  m_flux_direction(a_flux_direction)
176  {
177  }
178 
179  [[nodiscard]]
182  getMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/,
183  amrex::RandomEngine const& engine) const noexcept
184  {
185  using namespace amrex::literals;
186 
187  // Generate the distribution in the direction of the flux
188  amrex::Real u_m = 0, u_th = 0;
189  if (m_flux_normal_axis == 0) {
190  u_m = m_ux_m;
191  u_th = m_ux_th;
192  } else if (m_flux_normal_axis == 1) {
193  u_m = m_uy_m;
194  u_th = m_uy_th;
195  } else if (m_flux_normal_axis == 2) {
196  u_m = m_uz_m;
197  u_th = m_uz_th;
198  }
199  amrex::Real u = generateGaussianFluxDist(u_m, u_th, engine);
200  if (m_flux_direction < 0) { u = -u; }
201 
202  // Note: Here, in RZ geometry, the variables `ux` and `uy` actually
203  // correspond to the radial and azimuthal component of the momentum
204  // (and e.g.`m_flux_normal_axis==1` corresponds to v*Gaussian along theta)
205  amrex::Real const ux = (m_flux_normal_axis == 0 ? u : amrex::RandomNormal(m_ux_m, m_ux_th, engine));
206  amrex::Real const uy = (m_flux_normal_axis == 1 ? u : amrex::RandomNormal(m_uy_m, m_uy_th, engine));
207  amrex::Real const uz = (m_flux_normal_axis == 2 ? u : amrex::RandomNormal(m_uz_m, m_uz_th, engine));
208  return amrex::XDim3{ux, uy, uz};
209  }
210 
211  [[nodiscard]]
214  getBulkMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/) const noexcept
215  {
216  return amrex::XDim3{m_ux_m, m_uy_m, m_uz_m};
217  }
218 
219 private:
220  amrex::Real m_ux_m, m_uy_m, m_uz_m;
221  amrex::Real m_ux_th, m_uy_th, m_uz_th;
224 };
225 
226 
227 // struct whose getMomentum returns momentum for 1 particle, from random
228 // uniform distribution u_min < u < u_max
230 {
231  InjectorMomentumUniform (amrex::Real a_ux_min, amrex::Real a_uy_min,
232  amrex::Real a_uz_min, amrex::Real a_ux_max,
233  amrex::Real a_uy_max, amrex::Real a_uz_max) noexcept
234  : m_ux_min(a_ux_min), m_uy_min(a_uy_min), m_uz_min(a_uz_min),
235  m_ux_max(a_ux_max), m_uy_max(a_uy_max), m_uz_max(a_uz_max),
236  m_Dux(m_ux_max - m_ux_min),
237  m_Duy(m_uy_max - m_uy_min),
238  m_Duz(m_uz_max - m_uz_min),
239  m_ux_h(amrex::Real(0.5) * (m_ux_max + m_ux_min)),
240  m_uy_h(amrex::Real(0.5) * (m_uy_max + m_uy_min)),
241  m_uz_h(amrex::Real(0.5) * (m_uz_max + m_uz_min))
242  {}
243 
244  [[nodiscard]]
247  getMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/,
248  amrex::RandomEngine const& engine) const noexcept
249  {
250  return amrex::XDim3{m_ux_min + amrex::Random(engine) * m_Dux,
251  m_uy_min + amrex::Random(engine) * m_Duy,
252  m_uz_min + amrex::Random(engine) * m_Duz};
253  }
254 
255  [[nodiscard]]
258  getBulkMomentum (amrex::Real /*x*/, amrex::Real /*y*/, amrex::Real /*z*/) const noexcept
259  {
260  return amrex::XDim3{m_ux_h, m_uy_h, m_uz_h};
261  }
262 
263 private:
264  amrex::Real m_ux_min, m_uy_min, m_uz_min;
265  amrex::Real m_ux_max, m_uy_max, m_uz_max;
266  amrex::Real m_Dux, m_Duy, m_Duz;
267  amrex::Real m_ux_h, m_uy_h, m_uz_h;
268 };
269 
270 // struct whose getMomentum returns momentum for 1 particle with relativistic
271 // drift velocity beta, from the Maxwell-Boltzmann distribution.
273 {
274  // Constructor whose inputs are:
275  // a reference to the initial temperature container t,
276  // a reference to the initial velocity container b
278  : velocity(b), temperature(t)
279  {}
280 
281  [[nodiscard]]
284  getMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z,
285  amrex::RandomEngine const& engine) const noexcept
286  {
287  using namespace amrex::literals;
288 
289  // Calculate the local temperature and check if it's too
290  // high for Boltzmann or less than zero
291  amrex::Real const theta = temperature(x,y,z);
292  if (theta < 0._rt) {
293  amrex::Abort("Negative temperature parameter theta encountered, which is not allowed");
294  }
295  // Calculate local velocity and abort if |beta|>=1
296  amrex::Real const beta = velocity(x,y,z);
297  if (beta <= -1._rt || beta >= 1._rt) {
298  amrex::Abort("beta = v/c magnitude greater than or equal to 1");
299  }
300  // Calculate the value of vave from the local temperature
301  amrex::Real const vave = std::sqrt(theta);
302  int const dir = velocity.direction();
303 
304  amrex::Real u[3];
305  u[dir] = amrex::RandomNormal(0._rt, vave, engine);
306  u[(dir+1)%3] = amrex::RandomNormal(0._rt, vave, engine);
307  u[(dir+2)%3] = amrex::RandomNormal(0._rt, vave, engine);
308  amrex::Real const gamma = std::sqrt(1._rt + u[0]*u[0]+u[1]*u[1]+u[2]*u[2]);
309 
310  // The following condition is equation 32 in Zenitani 2015
311  // (Phys. Plasmas 22, 042116) , called the flipping method. It
312  // transforms the integral: d3x' -> d3x where d3x' is the volume
313  // element for positions in the boosted frame. The particle positions
314  // and densities can be initialized in the simulation frame.
315  // The flipping method can transform any symmetric distribution from one
316  // reference frame to another moving at a relative velocity of beta.
317  // An equivalent alternative to this method native to WarpX would be to
318  // initialize the particle positions and densities in the frame moving
319  // at speed beta, and then perform a Lorentz transform on the positions
320  // and MB sampled velocities to the simulation frame.
321  if(-beta*u[dir]/gamma > amrex::Random(engine))
322  {
323  u[dir] = -u[dir];
324  }
325  // This Lorentz transform is equation 17 in Zenitani.
326  // It transforms the integral d3u' -> d3u
327  // where d3u' is the volume element for momentum in the boosted frame.
328  u[dir] = 1._rt/std::sqrt(1._rt-beta*beta)*(u[dir]+gamma*beta);
329  // Note that if beta = 0 then the flipping method and Lorentz transform
330  // have no effect on the u[dir] direction.
331  return amrex::XDim3 {u[0],u[1],u[2]};
332  }
333 
334  [[nodiscard]]
337  getBulkMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
338  {
339  using namespace amrex::literals;
340  amrex::Real u[3];
341  for (auto& el : u) { el = 0.0_rt; }
342  const amrex::Real beta = velocity(x,y,z);
343  int const dir = velocity.direction();
344  const auto gamma = 1._rt/std::sqrt(1._rt-beta*beta);
345  u[dir] = gamma*beta;
346  return amrex::XDim3 {u[0],u[1],u[2]};
347  }
348 
349 private:
352 };
353 
354 // struct whose getMomentum returns momentum for 1 particle with relativistic
355 // drift velocity beta, from the Maxwell-Juttner distribution. Method is from
356 // Zenitani 2015 (Phys. Plasmas 22, 042116).
358 {
359  // Constructor whose inputs are:
360  // a reference to the initial temperature container t,
361  // a reference to the initial velocity container b
363  : velocity(b), temperature(t)
364  {}
365 
366  [[nodiscard]]
369  getMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z,
370  amrex::RandomEngine const& engine) const noexcept
371  {
372  using namespace amrex::literals;
373  // Sobol method for sampling MJ Speeds,
374  // from Zenitani 2015 (Phys. Plasmas 22, 042116).
375  amrex::Real x1, x2, gamma;
376  amrex::Real u [3];
377  amrex::Real const theta = temperature(x,y,z);
378  // Check if temperature is too low to do sampling method. Abort for now,
379  // in future should implement an alternate method e.g. inverse transform
380  if (theta < 0.1_rt) {
381  amrex::Abort("Temeprature parameter theta is less than minimum 0.1 allowed for Maxwell-Juttner");
382  }
383  // Calculate local velocity and abort if |beta|>=1
384  amrex::Real const beta = velocity(x,y,z);
385  if (beta <= -1._rt || beta >= 1._rt) {
386  amrex::Abort("beta = v/c magnitude greater than or equal to 1");
387  }
388  int const dir = velocity.direction();
389  x1 = static_cast<amrex::Real>(0._rt);
390  gamma = static_cast<amrex::Real>(0._rt);
391  u[dir] = static_cast<amrex::Real>(0._rt);
392  // This condition is equation 10 in Zenitani,
393  // though x1 is defined differently.
394  while(u[dir]-gamma <= x1)
395  {
396  u[dir] = -theta*
397  std::log(amrex::Random(engine)*amrex::Random(engine)*amrex::Random(engine));
398  gamma = std::sqrt(1._rt+u[dir]*u[dir]);
399  x1 = theta*std::log(amrex::Random(engine));
400  }
401  // The following code samples a random unit vector
402  // and multiplies the result by speed u[dir].
403  x1 = amrex::Random(engine);
404  x2 = amrex::Random(engine);
405  // Direction dir is an input parameter that sets the boost direction:
406  // 'x' -> d = 0, 'y' -> d = 1, 'z' -> d = 2.
407  u[(dir+1)%3] = 2._rt*u[dir]*std::sqrt(x1*(1._rt-x1))*std::sin(2._rt*MathConst::pi*x2);
408  u[(dir+2)%3] = 2._rt*u[dir]*std::sqrt(x1*(1._rt-x1))*std::cos(2._rt*MathConst::pi*x2);
409  // The value of dir is the boost direction to be transformed.
410  u[dir] = u[dir]*(2._rt*x1-1._rt);
411  x1 = amrex::Random(engine);
412  // The following condition is equation 32 in Zenitani, called
413  // The flipping method. It transforms the integral: d3x' -> d3x
414  // where d3x' is the volume element for positions in the boosted frame.
415  // The particle positions and densities can be initialized in the
416  // simulation frame with this method.
417  // The flipping method can similarly transform any
418  // symmetric distribution from one reference frame to another moving at
419  // a relative velocity of beta.
420  // An equivalent alternative to this method native to WarpX
421  // would be to initialize the particle positions and densities in the
422  // frame moving at speed beta, and then perform a Lorentz transform
423  // on their positions and MJ sampled velocities to the simulation frame.
424  if(-beta*u[dir]/gamma>x1)
425  {
426  u[dir] = -u[dir];
427  }
428  // This Lorentz transform is equation 17 in Zenitani.
429  // It transforms the integral d3u' -> d3u
430  // where d3u' is the volume element for momentum in the boosted frame.
431  u[dir] = 1._rt/std::sqrt(1._rt-beta*beta)*(u[dir]+gamma*beta);
432  // Note that if beta = 0 then the flipping method and Lorentz transform
433  // have no effect on the u[dir] direction.
434  return amrex::XDim3 {u[0],u[1],u[2]};
435  }
436 
437  [[nodiscard]]
440  getBulkMomentum (amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
441  {
442  using namespace amrex::literals;
443  amrex::Real u[3];
444  for (auto& el : u) { el = 0.0_rt; }
445  amrex::Real const beta = velocity(x,y,z);
446  int const dir = velocity.direction();
447  auto const gamma = 1._rt/std::sqrt(1._rt-beta*beta);
448  u[dir] = gamma*beta;
449  return amrex::XDim3 {u[0],u[1],u[2]};
450  }
451 
452 private:
455 };
456 
465 {
466  InjectorMomentumRadialExpansion (amrex::Real a_u_over_r) noexcept
467  : u_over_r(a_u_over_r)
468  {}
469 
470  [[nodiscard]]
473  getMomentum (amrex::Real x, amrex::Real y, amrex::Real z,
474  amrex::RandomEngine const&) const noexcept
475  {
476  return {x*u_over_r, y*u_over_r, z*u_over_r};
477  }
478 
479  [[nodiscard]]
482  getBulkMomentum (amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
483  {
484  return {x*u_over_r, y*u_over_r, z*u_over_r};
485  }
486 
487 private:
488  amrex::Real u_over_r;
489 };
490 
491 // struct whose getMomentum returns local momentum computed from parser.
493 {
495  amrex::ParserExecutor<3> const& a_uy_parser,
496  amrex::ParserExecutor<3> const& a_uz_parser) noexcept
497  : m_ux_parser(a_ux_parser), m_uy_parser(a_uy_parser),
498  m_uz_parser(a_uz_parser) {}
499 
500  [[nodiscard]]
503  getMomentum (amrex::Real x, amrex::Real y, amrex::Real z,
504  amrex::RandomEngine const&) const noexcept
505  {
506  return amrex::XDim3{m_ux_parser(x,y,z),m_uy_parser(x,y,z),m_uz_parser(x,y,z)};
507  }
508 
509  [[nodiscard]]
512  getBulkMomentum (amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
513  {
514  return amrex::XDim3{m_ux_parser(x,y,z),m_uy_parser(x,y,z),m_uz_parser(x,y,z)};
515  }
516 
517  amrex::ParserExecutor<3> m_ux_parser, m_uy_parser, m_uz_parser;
518 };
519 
520 // struct whose getMomentum returns local momentum and thermal spread computed from parser.
522 {
524  amrex::ParserExecutor<3> const& a_uy_m_parser,
525  amrex::ParserExecutor<3> const& a_uz_m_parser,
526  amrex::ParserExecutor<3> const& a_ux_th_parser,
527  amrex::ParserExecutor<3> const& a_uy_th_parser,
528  amrex::ParserExecutor<3> const& a_uz_th_parser) noexcept
529  : m_ux_m_parser(a_ux_m_parser), m_uy_m_parser(a_uy_m_parser), m_uz_m_parser(a_uz_m_parser),
530  m_ux_th_parser(a_ux_th_parser), m_uy_th_parser(a_uy_th_parser), m_uz_th_parser(a_uz_th_parser) {}
531 
532  [[nodiscard]]
535  getMomentum (amrex::Real x, amrex::Real y, amrex::Real z,
536  amrex::RandomEngine const& engine) const noexcept
537  {
538  amrex::Real const ux_m = m_ux_m_parser(x,y,z);
539  amrex::Real const uy_m = m_uy_m_parser(x,y,z);
540  amrex::Real const uz_m = m_uz_m_parser(x,y,z);
541  amrex::Real const ux_th = m_ux_th_parser(x,y,z);
542  amrex::Real const uy_th = m_uy_th_parser(x,y,z);
543  amrex::Real const uz_th = m_uz_th_parser(x,y,z);
544  return amrex::XDim3{amrex::RandomNormal(ux_m, ux_th, engine),
545  amrex::RandomNormal(uy_m, uy_th, engine),
546  amrex::RandomNormal(uz_m, uz_th, engine)};
547  }
548 
549  [[nodiscard]]
552  getBulkMomentum (amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
553  {
554  return amrex::XDim3{m_ux_m_parser(x,y,z), m_uy_m_parser(x,y,z), m_uz_m_parser(x,y,z)};
555  }
556 
557  amrex::ParserExecutor<3> m_ux_m_parser, m_uy_m_parser, m_uz_m_parser;
558  amrex::ParserExecutor<3> m_ux_th_parser, m_uy_th_parser, m_uz_th_parser;
559 };
560 
561 // Base struct for momentum injector.
562 // InjectorMomentum contains a union (called Object) that holds any one
563 // instance of:
564 // - InjectorMomentumConstant : to generate constant density;
565 // - InjectorMomentumGaussian : to generate gaussian distribution;
566 // - InjectorMomentumGaussianFlux : to generate v*gaussian distribution;
567 // - InjectorMomentumRadialExpansion: to generate radial expansion;
568 // - InjectorMomentumParser : to generate momentum from parser;
569 // - InjectorMomentumGaussianParser : to generate momentum and thermal spread from parser;
570 // The choice is made at runtime, depending in the constructor called.
571 // This mimics virtual functions.
573 {
574  // This constructor stores a InjectorMomentumConstant in union object.
576  amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz)
577  : type(Type::constant),
578  object(t, a_ux, a_uy, a_uz)
579  { }
580 
581  // This constructor stores a InjectorMomentumParser in union object.
583  amrex::ParserExecutor<3> const& a_ux_parser,
584  amrex::ParserExecutor<3> const& a_uy_parser,
585  amrex::ParserExecutor<3> const& a_uz_parser)
586  : type(Type::parser),
587  object(t, a_ux_parser, a_uy_parser, a_uz_parser)
588  { }
589 
590  // This constructor stores a InjectorMomentumGaussianParser in union object.
592  amrex::ParserExecutor<3> const& a_ux_m_parser,
593  amrex::ParserExecutor<3> const& a_uy_m_parser,
594  amrex::ParserExecutor<3> const& a_uz_m_parser,
595  amrex::ParserExecutor<3> const& a_ux_th_parser,
596  amrex::ParserExecutor<3> const& a_uy_th_parser,
597  amrex::ParserExecutor<3> const& a_uz_th_parser)
598  : type(Type::gaussianparser),
599  object(t, a_ux_m_parser, a_uy_m_parser, a_uz_m_parser,
600  a_ux_th_parser, a_uy_th_parser, a_uz_th_parser)
601  { }
602 
603  // This constructor stores a InjectorMomentumGaussian in union object.
605  amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m,
606  amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th)
607  : type(Type::gaussian),
608  object(t,a_ux_m,a_uy_m,a_uz_m,a_ux_th,a_uy_th,a_uz_th)
609  { }
610 
611  // This constructor stores a InjectorMomentumGaussianFlux in union object.
613  amrex::Real a_ux_m, amrex::Real a_uy_m, amrex::Real a_uz_m,
614  amrex::Real a_ux_th, amrex::Real a_uy_th, amrex::Real a_uz_th,
615  int a_flux_normal_axis, int a_flux_direction)
616  : type(Type::gaussianflux),
617  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)
618  { }
619 
620  // This constructor stores a InjectorMomentumUniform in union object.
622  amrex::Real a_ux_min, amrex::Real a_uy_min, amrex::Real a_uz_min,
623  amrex::Real a_ux_max, amrex::Real a_uy_max, amrex::Real a_uz_max)
624  : type(Type::uniform),
625  object(t,a_ux_min,a_uy_min,a_uz_min,a_ux_max,a_uy_max,a_uz_max)
626  { }
627 
629  GetTemperature const& temperature, GetVelocity const& velocity)
630  : type(Type::boltzmann),
631  object(t, temperature, velocity)
632  { }
633 
634  // This constructor stores a InjectorMomentumJuttner in union object.
636  GetTemperature const& temperature, GetVelocity const& velocity)
637  : type(Type::juttner),
638  object(t, temperature, velocity)
639  { }
640 
641  // This constructor stores a InjectorMomentumRadialExpansion in union object.
643  amrex::Real u_over_r)
644  : type(Type::radial_expansion),
645  object(t, u_over_r)
646  { }
647 
648  // Explicitly prevent the compiler from generating copy constructors
649  // and copy assignment operators.
652  void operator= (InjectorMomentum const&) = delete;
653  void operator= (InjectorMomentum &&) = delete;
654 
655  // Default destructor
656  ~InjectorMomentum() = default;
657 
658  void clear ();
659 
660  // call getMomentum from the object stored in the union
661  // (the union is called Object, and the instance is called object).
662  [[nodiscard]]
665  getMomentum (amrex::Real x, amrex::Real y, amrex::Real z,
666  amrex::RandomEngine const& engine) const noexcept
667  {
668  switch (type)
669  {
670  case Type::parser:
671  {
672  return object.parser.getMomentum(x,y,z,engine);
673  }
674  case Type::gaussian:
675  {
676  return object.gaussian.getMomentum(x,y,z,engine);
677  }
678  case Type::gaussianparser:
679  {
680  return object.gaussianparser.getMomentum(x,y,z,engine);
681  }
682  case Type::gaussianflux:
683  {
684  return object.gaussianflux.getMomentum(x,y,z,engine);
685  }
686  case Type::uniform:
687  {
688  return object.uniform.getMomentum(x,y,z,engine);
689  }
690  case Type::boltzmann:
691  {
692  return object.boltzmann.getMomentum(x,y,z,engine);
693  }
694  case Type::juttner:
695  {
696  return object.juttner.getMomentum(x,y,z,engine);
697  }
698  case Type::constant:
699  {
700  return object.constant.getMomentum(x,y,z,engine);
701  }
702  case Type::radial_expansion:
703  {
704  return object.radial_expansion.getMomentum(x,y,z,engine);
705  }
706  default:
707  {
708  amrex::Abort("InjectorMomentum: unknown type");
709  return {0.0,0.0,0.0};
710  }
711  }
712  }
713 
714  // call getBulkMomentum from the object stored in the union
715  // (the union is called Object, and the instance is called object).
716  [[nodiscard]]
719  getBulkMomentum (amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
720  {
721  switch (type)
722  {
723  case Type::parser:
724  {
725  return object.parser.getBulkMomentum(x,y,z);
726  }
727  case Type::gaussian:
728  {
729  return object.gaussian.getBulkMomentum(x,y,z);
730  }
731  case Type::gaussianparser:
732  {
733  return object.gaussianparser.getBulkMomentum(x,y,z);
734  }
735  case Type::gaussianflux:
736  {
737  return object.gaussianflux.getBulkMomentum(x,y,z);
738  }
739  case Type::uniform:
740  {
741  return object.uniform.getBulkMomentum(x,y,z);
742  }
743  case Type::boltzmann:
744  {
745  return object.boltzmann.getBulkMomentum(x,y,z);
746  }
747  case Type::juttner:
748  {
749  return object.juttner.getBulkMomentum(x,y,z);
750  }
751  case Type::constant:
752  {
753  return object.constant.getBulkMomentum(x,y,z);
754  }
755  case Type::radial_expansion:
756  {
757  return object.radial_expansion.getBulkMomentum(x,y,z);
758  }
759  default:
760  {
761  amrex::Abort("InjectorMomentum: unknown type");
762  return {0.0,0.0,0.0};
763  }
764  }
765  }
766 
767  enum struct Type { constant, gaussian, gaussianflux, uniform, boltzmann, juttner, radial_expansion, parser, gaussianparser };
769 
770 private:
771 
772  // An instance of union Object constructs and stores any one of
773  // the objects declared (constant or gaussian or
774  // radial_expansion or parser).
775  union Object {
777  amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz) noexcept
778  : constant(a_ux,a_uy,a_uz) {}
780  amrex::Real a_ux_m, amrex::Real a_uy_m,
781  amrex::Real a_uz_m, amrex::Real a_ux_th,
782  amrex::Real a_uy_th, amrex::Real a_uz_th) noexcept
783  : gaussian(a_ux_m,a_uy_m,a_uz_m,a_ux_th,a_uy_th,a_uz_th) {}
785  amrex::Real a_ux_m, amrex::Real a_uy_m,
786  amrex::Real a_uz_m, amrex::Real a_ux_th,
787  amrex::Real a_uy_th, amrex::Real a_uz_th,
788  int a_flux_normal_axis, int a_flux_direction) noexcept
789  : 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) {}
791  amrex::Real a_ux_min, amrex::Real a_uy_min,
792  amrex::Real a_uz_min, amrex::Real a_ux_max,
793  amrex::Real a_uy_max, amrex::Real a_uz_max) noexcept
794  : uniform(a_ux_min,a_uy_min,a_uz_min,a_ux_max,a_uy_max,a_uz_max) {}
796  GetTemperature const& t, GetVelocity const& b) noexcept
797  : boltzmann(t,b) {}
799  GetTemperature const& t, GetVelocity const& b) noexcept
800  : juttner(t,b) {}
802  amrex::Real u_over_r) noexcept
803  : radial_expansion(u_over_r) {}
805  amrex::ParserExecutor<3> const& a_ux_parser,
806  amrex::ParserExecutor<3> const& a_uy_parser,
807  amrex::ParserExecutor<3> const& a_uz_parser) noexcept
808  : parser(a_ux_parser, a_uy_parser, a_uz_parser) {}
810  amrex::ParserExecutor<3> const& a_ux_m_parser,
811  amrex::ParserExecutor<3> const& a_uy_m_parser,
812  amrex::ParserExecutor<3> const& a_uz_m_parser,
813  amrex::ParserExecutor<3> const& a_ux_th_parser,
814  amrex::ParserExecutor<3> const& a_uy_th_parser,
815  amrex::ParserExecutor<3> const& a_uz_th_parser) noexcept
816  : gaussianparser(a_ux_m_parser, a_uy_m_parser, a_uz_m_parser,
817  a_ux_th_parser, a_uy_th_parser, a_uz_th_parser) {}
827  };
829 };
830 
831 // In order for InjectorMomentum to be trivially copyable, its destructor
832 // must be trivial. So we have to rely on a custom deleter for unique_ptr.
834  void operator () (InjectorMomentum* p) const {
835  if (p) {
836  p->clear();
837  delete p;
838  }
839  }
840 };
841 
842 #endif
#define AMREX_FORCE_INLINE
#define AMREX_GPU_HOST_DEVICE
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
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:273
GetTemperature temperature
Definition: InjectorMomentum.H:351
GetVelocity velocity
Definition: InjectorMomentum.H:350
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:284
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
Definition: InjectorMomentum.H:337
InjectorMomentumBoltzmann(GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:277
Definition: InjectorMomentum.H:33
amrex::Real m_uy
Definition: InjectorMomentum.H:55
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:49
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:55
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:55
Definition: InjectorMomentum.H:833
Definition: InjectorMomentum.H:167
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:214
amrex::Real m_uy_m
Definition: InjectorMomentum.H:220
int m_flux_normal_axis
Definition: InjectorMomentum.H:222
amrex::Real m_ux_m
Definition: InjectorMomentum.H:220
amrex::Real m_uz_th
Definition: InjectorMomentum.H:221
amrex::Real m_ux_th
Definition: InjectorMomentum.H:221
amrex::Real m_uy_th
Definition: InjectorMomentum.H:221
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:168
amrex::Real m_uz_m
Definition: InjectorMomentum.H:220
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real, amrex::Real, amrex::Real, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:182
int m_flux_direction
Definition: InjectorMomentum.H:223
Definition: InjectorMomentum.H:61
amrex::Real m_uz_m
Definition: InjectorMomentum.H:89
amrex::Real m_ux_m
Definition: InjectorMomentum.H:89
amrex::Real m_ux_th
Definition: InjectorMomentum.H:90
amrex::Real m_uy_th
Definition: InjectorMomentum.H:90
amrex::Real m_uy_m
Definition: InjectorMomentum.H:89
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:62
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real, amrex::Real, amrex::Real, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:72
amrex::Real m_uz_th
Definition: InjectorMomentum.H:90
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:83
Definition: InjectorMomentum.H:522
InjectorMomentumGaussianParser(amrex::ParserExecutor< 3 > const &a_ux_m_parser, amrex::ParserExecutor< 3 > const &a_uy_m_parser, amrex::ParserExecutor< 3 > const &a_uz_m_parser, amrex::ParserExecutor< 3 > const &a_ux_th_parser, amrex::ParserExecutor< 3 > const &a_uy_th_parser, amrex::ParserExecutor< 3 > const &a_uz_th_parser) noexcept
Definition: InjectorMomentum.H:523
amrex::ParserExecutor< 3 > m_ux_th_parser
Definition: InjectorMomentum.H:558
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
Definition: InjectorMomentum.H:552
amrex::ParserExecutor< 3 > m_ux_m_parser
Definition: InjectorMomentum.H:557
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:535
Definition: InjectorMomentum.H:573
InjectorMomentum(InjectorMomentumRadialExpansion *t, amrex::Real u_over_r)
Definition: InjectorMomentum.H:642
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:665
Type type
Definition: InjectorMomentum.H:768
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:582
void clear()
Definition: InjectorMomentum.cpp:12
InjectorMomentum(InjectorMomentumConstant *t, amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz)
Definition: InjectorMomentum.H:575
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:604
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:621
Type
Definition: InjectorMomentum.H:767
Object object
Definition: InjectorMomentum.H:828
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
Definition: InjectorMomentum.H:719
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:612
InjectorMomentum(InjectorMomentumBoltzmann *t, GetTemperature const &temperature, GetVelocity const &velocity)
Definition: InjectorMomentum.H:628
InjectorMomentum(InjectorMomentumJuttner *t, GetTemperature const &temperature, GetVelocity const &velocity)
Definition: InjectorMomentum.H:635
InjectorMomentum(InjectorMomentumGaussianParser *t, amrex::ParserExecutor< 3 > const &a_ux_m_parser, amrex::ParserExecutor< 3 > const &a_uy_m_parser, amrex::ParserExecutor< 3 > const &a_uz_m_parser, amrex::ParserExecutor< 3 > const &a_ux_th_parser, amrex::ParserExecutor< 3 > const &a_uy_th_parser, amrex::ParserExecutor< 3 > const &a_uz_th_parser)
Definition: InjectorMomentum.H:591
Definition: InjectorMomentum.H:358
GetVelocity velocity
Definition: InjectorMomentum.H:453
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real const x, amrex::Real const y, amrex::Real const z) const noexcept
Definition: InjectorMomentum.H:440
GetTemperature temperature
Definition: InjectorMomentum.H:454
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:369
InjectorMomentumJuttner(GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:362
Definition: InjectorMomentum.H:493
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real x, amrex::Real y, amrex::Real z, amrex::RandomEngine const &) const noexcept
Definition: InjectorMomentum.H:503
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:494
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
Definition: InjectorMomentum.H:512
amrex::ParserExecutor< 3 > m_ux_parser
Definition: InjectorMomentum.H:517
struct whose getMomentum returns momentum for 1 particle, for radial expansion.
Definition: InjectorMomentum.H:465
InjectorMomentumRadialExpansion(amrex::Real a_u_over_r) noexcept
Definition: InjectorMomentum.H:466
amrex::Real u_over_r
Definition: InjectorMomentum.H:488
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real x, amrex::Real y, amrex::Real z, amrex::RandomEngine const &) const noexcept
Definition: InjectorMomentum.H:473
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real x, amrex::Real y, amrex::Real z) const noexcept
Definition: InjectorMomentum.H:482
Definition: InjectorMomentum.H:230
amrex::Real m_Dux
Definition: InjectorMomentum.H:266
amrex::Real m_ux_h
Definition: InjectorMomentum.H:267
amrex::Real m_ux_max
Definition: InjectorMomentum.H:265
AMREX_GPU_HOST_DEVICE amrex::XDim3 getBulkMomentum(amrex::Real, amrex::Real, amrex::Real) const noexcept
Definition: InjectorMomentum.H:258
AMREX_GPU_HOST_DEVICE amrex::XDim3 getMomentum(amrex::Real, amrex::Real, amrex::Real, amrex::RandomEngine const &engine) const noexcept
Definition: InjectorMomentum.H:247
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:231
amrex::Real m_ux_min
Definition: InjectorMomentum.H:264
Definition: InjectorMomentum.H:775
InjectorMomentumGaussian gaussian
Definition: InjectorMomentum.H:819
InjectorMomentumUniform uniform
Definition: InjectorMomentum.H:821
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:784
Object(InjectorMomentumBoltzmann *, GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:795
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:804
InjectorMomentumGaussianParser gaussianparser
Definition: InjectorMomentum.H:826
InjectorMomentumJuttner juttner
Definition: InjectorMomentum.H:823
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:790
InjectorMomentumRadialExpansion radial_expansion
Definition: InjectorMomentum.H:824
InjectorMomentumBoltzmann boltzmann
Definition: InjectorMomentum.H:822
InjectorMomentumGaussianFlux gaussianflux
Definition: InjectorMomentum.H:820
Object(InjectorMomentumJuttner *, GetTemperature const &t, GetVelocity const &b) noexcept
Definition: InjectorMomentum.H:798
Object(InjectorMomentumRadialExpansion *, amrex::Real u_over_r) noexcept
Definition: InjectorMomentum.H:801
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:779
InjectorMomentumParser parser
Definition: InjectorMomentum.H:825
InjectorMomentumConstant constant
Definition: InjectorMomentum.H:818
Object(InjectorMomentumGaussianParser *, amrex::ParserExecutor< 3 > const &a_ux_m_parser, amrex::ParserExecutor< 3 > const &a_uy_m_parser, amrex::ParserExecutor< 3 > const &a_uz_m_parser, amrex::ParserExecutor< 3 > const &a_ux_th_parser, amrex::ParserExecutor< 3 > const &a_uy_th_parser, amrex::ParserExecutor< 3 > const &a_uz_th_parser) noexcept
Definition: InjectorMomentum.H:809
Object(InjectorMomentumConstant *, amrex::Real a_ux, amrex::Real a_uy, amrex::Real a_uz) noexcept
Definition: InjectorMomentum.H:776