WarpX
BinaryCollisionUtils.H
Go to the documentation of this file.
1 /* Copyright 2021 Neil Zaim
2  *
3  * This file is part of WarpX.
4  *
5  * License: BSD-3-Clause-LBNL
6  */
7 
8 #ifndef WARPX_BINARY_COLLISION_UTILS_H_
9 #define WARPX_BINARY_COLLISION_UTILS_H_
10 
11 #include <string>
12 
14 
15 #include <AMReX_Math.H>
16 
22  DSMC,
24  Undefined };
25 
26 enum struct NuclearFusionType {
32  Undefined };
33 
34 namespace BinaryCollisionUtils{
35 
36  NuclearFusionType get_nuclear_fusion_type (const std::string& collision_name,
37  MultiParticleContainer const * mypc);
38 
39  CollisionType get_collision_type (const std::string& collision_name,
40  MultiParticleContainer const * mypc);
41 
43 
51  const amrex::ParticleReal& u1x, const amrex::ParticleReal& u1y,
52  const amrex::ParticleReal& u1z, const amrex::ParticleReal& u2x,
53  const amrex::ParticleReal& u2y, const amrex::ParticleReal& u2z,
54  const amrex::ParticleReal& m1, const amrex::ParticleReal& m2,
55  amrex::ParticleReal& E_kin_COM, amrex::ParticleReal& v_rel_COM,
56  amrex::ParticleReal& lab_to_COM_lorentz_factor )
57  {
58  // General notations in this function:
59  // x_sq denotes the square of x
60  // x_star denotes the value of x in the center of mass frame
61 
62  using namespace amrex::literals;
63  using namespace amrex::Math;
64 
65  constexpr double c_sq = PhysConst::c * PhysConst::c;
66  constexpr double inv_csq = 1.0 / c_sq;
67 
68  // Cast input parameters to double before computing collision properties
69  // This is needed to avoid errors when using single-precision particles
70  const auto m1_dbl = static_cast<double>(m1);
71  const auto m2_dbl = static_cast<double>(m2);
72  const auto u1x_dbl = static_cast<double>(u1x);
73  const auto u1y_dbl = static_cast<double>(u1y);
74  const auto u1z_dbl = static_cast<double>(u1z);
75  const auto u2x_dbl = static_cast<double>(u2x);
76  const auto u2y_dbl = static_cast<double>(u2y);
77  const auto u2z_dbl = static_cast<double>(u2z);
78 
79  const double m1_sq = m1_dbl*m1_dbl;
80  const double m2_sq = m2_dbl*m2_dbl;
81 
82  // Compute Lorentz factor gamma in the lab frame
83  const double g1 = std::sqrt( 1.0 + (u1x_dbl*u1x_dbl + u1y_dbl*u1y_dbl + u1z_dbl*u1z_dbl)*inv_csq );
84  const double g2 = std::sqrt( 1.0 + (u2x_dbl*u2x_dbl + u2y_dbl*u2y_dbl + u2z_dbl*u2z_dbl)*inv_csq );
85 
86  // Compute momenta
87  const double p1x = u1x_dbl * m1_dbl;
88  const double p1y = u1y_dbl * m1_dbl;
89  const double p1z = u1z_dbl * m1_dbl;
90  const double p2x = u2x_dbl * m2_dbl;
91  const double p2y = u2y_dbl * m2_dbl;
92  const double p2z = u2z_dbl * m2_dbl;
93 
94  // Square norm of the total (sum between the two particles) momenta in the lab frame
95  const double p_total_sq = powi<2>(p1x + p2x) + powi<2>(p1y + p2y) + powi<2>(p1z + p2z);
96 
97  // Total energy in the lab frame
98  // Note the use of `double` for energy since this calculation is
99  // prone to error with single precision.
100  const double E_lab = (m1_dbl*g1 + m2_dbl*g2) * c_sq;
101  // Total energy squared in the center of mass frame, calculated using the Lorentz invariance
102  // of the four-momentum norm
103  const double E_star_sq = E_lab*E_lab - c_sq*p_total_sq;
104 
105  // Kinetic energy in the center of mass frame
106  const double E_star = std::sqrt(E_star_sq);
107 
108  // Cast back to chosen precision for output
109  E_kin_COM = static_cast<amrex::ParticleReal>(E_star - (m1_dbl + m2_dbl)*c_sq);
110 
111  // Square of the norm of the momentum of one of the particles in the center of mass frame
112  // Formula obtained by inverting E^2 = p^2*c^2 + m^2*c^4 in the COM frame for each particle
113  // The expression below is specifically written in a form that avoids returning
114  // small negative numbers due to machine precision errors, for low-energy particles
115  const double E_ratio = E_star/((m1_dbl + m2_dbl)*c_sq);
116  const double p_star_sq = m1_dbl*m2_dbl*c_sq * ( powi<2>(E_ratio) - 1.0 )
117  + powi<2>(m1_dbl - m2_dbl)*c_sq/4.0 * powi<2>( E_ratio - 1.0/E_ratio);
118 
119  // Lorentz factors in the center of mass frame
120  const double g1_star = std::sqrt(1.0 + p_star_sq / (m1_sq*c_sq));
121  const double g2_star = std::sqrt(1.0 + p_star_sq / (m2_sq*c_sq));
122 
123  // relative velocity in the center of mass frame, cast back to chosen precision
124  v_rel_COM = static_cast<amrex::ParticleReal>(std::sqrt(p_star_sq) * (1.0/(m1_dbl*g1_star) + 1.0/(m2_dbl*g2_star)));
125 
126  // Cross sections and relative velocity are computed in the center of mass frame.
127  // On the other hand, the particle densities (weight over volume) in the lab frame are used.
128  // To take this disrepancy into account, it is needed to multiply the
129  // collision probability by the ratio between the Lorentz factors in the
130  // COM frame and the Lorentz factors in the lab frame (see
131  // Perez et al., Phys.Plasmas.19.083104 (2012)). The correction factor
132  // is calculated here.
133  lab_to_COM_lorentz_factor = static_cast<amrex::ParticleReal>(g1_star*g2_star/(g1*g2));
134  }
135 
142  amrex::ParticleReal& weight, uint64_t& idcpu,
143  const amrex::ParticleReal reaction_weight )
144  {
145  // Remove weight from given particle
146  amrex::Gpu::Atomic::AddNoRet(&weight, -reaction_weight);
147 
148  // If the colliding particle weight decreases to zero, remove particle by
149  // setting its id to invalid
150  if (weight <= std::numeric_limits<amrex::ParticleReal>::min())
151  {
152 #if defined(AMREX_USE_OMP)
153 #pragma omp atomic write
155 #else
157  (unsigned long long *)&idcpu,
158  (unsigned long long)amrex::ParticleIdCpus::Invalid
159  );
160 #endif
161  }
162  }
163 }
164 
165 #endif // WARPX_BINARY_COLLISION_UTILS_H_
#define AMREX_INLINE
#define AMREX_GPU_HOST_DEVICE
CollisionType
Definition: BinaryCollisionUtils.H:17
@ ProtonBoronToAlphasFusion
@ DeuteriumDeuteriumToProtonTritiumFusion
@ DeuteriumDeuteriumToNeutronHeliumFusion
@ DeuteriumTritiumToNeutronHeliumFusion
@ DeuteriumHeliumToProtonHeliumFusion
NuclearFusionType
Definition: BinaryCollisionUtils.H:26
@ DeuteriumDeuteriumToProtonTritium
@ DeuteriumDeuteriumToNeutronHelium
Definition: MultiParticleContainer.H:66
Definition: BinaryCollisionUtils.cpp:18
CollisionType get_collision_type(const std::string &collision_name, MultiParticleContainer const *const mypc)
Definition: BinaryCollisionUtils.cpp:20
CollisionType nuclear_fusion_type_to_collision_type(const NuclearFusionType fusion_type)
Definition: BinaryCollisionUtils.cpp:125
AMREX_GPU_HOST_DEVICE AMREX_INLINE void remove_weight_from_colliding_particle(amrex::ParticleReal &weight, uint64_t &idcpu, const amrex::ParticleReal reaction_weight)
Subtract given weight from particle and set its ID to invalid if the weight reaches zero.
Definition: BinaryCollisionUtils.H:141
NuclearFusionType get_nuclear_fusion_type(const std::string &collision_name, MultiParticleContainer const *const mypc)
Definition: BinaryCollisionUtils.cpp:40
AMREX_GPU_HOST_DEVICE AMREX_INLINE void get_collision_parameters(const amrex::ParticleReal &u1x, const amrex::ParticleReal &u1y, const amrex::ParticleReal &u1z, const amrex::ParticleReal &u2x, const amrex::ParticleReal &u2y, const amrex::ParticleReal &u2z, const amrex::ParticleReal &m1, const amrex::ParticleReal &m2, amrex::ParticleReal &E_kin_COM, amrex::ParticleReal &v_rel_COM, amrex::ParticleReal &lab_to_COM_lorentz_factor)
Return (relativistic) collision energy, collision speed and Lorentz factor for transforming between t...
Definition: BinaryCollisionUtils.H:50
static constexpr auto c
vacuum speed of light [m/s]
Definition: constant.H:44
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T Exch(T *address, T val) noexcept
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void AddNoRet(T *sum, T value) noexcept
constexpr std::uint64_t Invalid