WarpX
Loading...
Searching...
No Matches
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
28
36
37namespace BinaryCollisionUtils{
38
39 NuclearFusionType get_nuclear_fusion_type (const std::string& collision_name,
40 MultiParticleContainer const * mypc);
41
42 void CheckFusionEnergy (NuclearFusionType fusion_type,
43 amrex::ParticleReal mass_before,
44 amrex::ParticleReal mass_after);
45
46 CollisionType get_collision_type (const std::string& collision_name,
47 MultiParticleContainer const * mypc);
48
51 {
55 }
58 }
61 }
64 }
65 else if (fusion_type == NuclearFusionType::ProtonBoronToAlphas) {
67 }
68 else {
70 WARPX_ABORT_WITH_MESSAGE("Invalid nuclear fusion type");
71 ))
72 }
73 return collision_type;
74 }
75
84
87 {
88 const CollisionType collision_type = nuclear_fusion_type_to_collision_type(fusion_type);
89 return is_two_product_fusion_type(collision_type);
90 }
91
99 const amrex::ParticleReal& p1x, const amrex::ParticleReal& p1y,
100 const amrex::ParticleReal& p1z, const amrex::ParticleReal& p2x,
101 const amrex::ParticleReal& p2y, const amrex::ParticleReal& p2z,
102 const amrex::ParticleReal& m1, const amrex::ParticleReal& m2,
103 amrex::ParticleReal& E_kin_COM, amrex::ParticleReal& v_rel_COM,
104 amrex::ParticleReal& lab_to_COM_lorentz_factor )
105 {
106 // General notations in this function:
107 // x_sq denotes the square of x
108 // x_star denotes the value of x in the center of mass frame
109
110 using namespace amrex::literals;
111 using namespace amrex::Math;
112
113 constexpr double c = PhysConst::c;
114 constexpr auto c2 = PhysConst::c2_v<double>;
115 constexpr double inv_c = 1./PhysConst::c;
116
117 // Cast input parameters to double before computing collision properties
118 // This is needed to avoid errors when using single-precision particles
119 const auto m1_dbl = static_cast<double>(m1);
120 const auto m2_dbl = static_cast<double>(m2);
121 const auto p1x_dbl = static_cast<double>(p1x);
122 const auto p1y_dbl = static_cast<double>(p1y);
123 const auto p1z_dbl = static_cast<double>(p1z);
124 const auto p2x_dbl = static_cast<double>(p2x);
125 const auto p2y_dbl = static_cast<double>(p2y);
126 const auto p2z_dbl = static_cast<double>(p2z);
127
128 const double m1_sq = m1_dbl*m1_dbl;
129 const double m2_sq = m2_dbl*m2_dbl;
130
131 // Square norm of the total (sum between the two particles) momenta in the lab frame
132 const double p_total_sq = powi<2>(p1x_dbl + p2x_dbl) + powi<2>(p1y_dbl + p2y_dbl) + powi<2>(p1z_dbl + p2z_dbl);
133
134 // Total energy in the lab frame
135 // Note the use of `double` for energy since this calculation is prone to error with single precision.
136 const double E1_lab = std::sqrt( m1_sq * c2 + p1x_dbl*p1x_dbl + p1y_dbl*p1y_dbl + p1z_dbl*p1z_dbl ) * c;
137 const double E2_lab = std::sqrt( m2_sq * c2 + p2x_dbl*p2x_dbl + p2y_dbl*p2y_dbl + p2z_dbl*p2z_dbl ) * c;
138 const double E_lab = E1_lab + E2_lab;
139 // Total energy squared in the center of mass frame, calculated using the Lorentz invariance
140 // of the four-momentum norm
141 const double E_star_sq = E_lab*E_lab - c2*p_total_sq;
142
143 // Kinetic energy in the center of mass frame
144 const double E_star = std::sqrt(E_star_sq);
145
146 // Cast back to chosen precision for output
147 E_kin_COM = static_cast<amrex::ParticleReal>(E_star - (m1_dbl + m2_dbl)*c2);
148
149 // Find the norm of the momentum of each particles in the center of mass frame
150 // This is done by solving the following system (in the COM frame)
151 // E_1^2 = p^2 c^2 + m_1^2 c^4 (for the first particle)
152 // E_2^2 = p^2 c^2 + m_2^2 c^4 (for the second particle ; same p since we are in the COM frame)
153 // to find the expression of the p as a function of E = E_1 + E_2.
154 // Here is an abbreviation derivation:
155 // - By summing the above equations
156 // E^2 = E_1^2 + E_2^2 + 2 E_1 E_2 = 2 p^2 c^2 + (m_1^2 + m_2^2) c^4 + 2 E_1 E_2
157 // - Rearranging and squaring
158 // ( E^2 - 2 p^2 c^2 - (m_1^2 + m_2^2) c^4 )^2 = 4 E_1^2 E_2^2 = 4 (p^2 c^2 + m_1^2 c^4) (p^2 c^2 + m_2^2 c^4)
159 // - By rearranging, we get:
160 // p^2 = E^2/4c^2 - (m_1^2 + m_2^2)c^2/2 + (m_1^2-m_2^2)^2 c^6/4E^2
161 double p_star_sq;
162 if (m1_dbl + m2_dbl == 0) {
163 p_star_sq = powi<2>( 0.5 * E_star * inv_c );
164 } else {
165 // The expression below is specifically written in a form that avoids returning
166 // small negative numbers due to machine precision errors, for low-energy particles
167 const double E_ratio = E_star/((m1_dbl + m2_dbl)*c2);
168 p_star_sq = m1_dbl*m2_dbl*c2 * ( powi<2>(E_ratio) - 1.0 )
169 + powi<2>(m1_dbl - m2_dbl)*c2/4.0 * powi<2>( E_ratio - 1.0/E_ratio);
170 }
171
172 // Energy of each particle in the center of mass frame
173 const double E1_star = std::sqrt(m1_sq*c2 + p_star_sq) * c;
174 const double E2_star = std::sqrt(m2_sq*c2 + p_star_sq) * c;
175
176 // relative velocity in the center of mass frame, cast back to chosen precision
177 v_rel_COM = PhysConst::c * static_cast<amrex::ParticleReal>(std::sqrt(p_star_sq) * c * (1.0/E1_star + 1.0/E2_star));
178
179 // Cross sections and relative velocity are computed in the center of mass frame.
180 // On the other hand, the particle densities (weight over volume) in the lab frame are used.
181 // To take this discrepancy into account, it is needed to multiply the
182 // collision probability by the ratio between the Lorentz factors in the
183 // COM frame and the Lorentz factors in the lab frame (see Perez et al.,
184 // Phys.Plasmas.19.083104 (2012)). The correction factor is calculated here.
185 lab_to_COM_lorentz_factor = static_cast<amrex::ParticleReal>(E1_star*E2_star/(E1_lab*E2_lab));
186 }
187
194 amrex::ParticleReal& weight, uint64_t& idcpu,
195 const amrex::ParticleReal reaction_weight )
196 {
197 // Remove weight from given particle
198 amrex::Gpu::Atomic::AddNoRet(&weight, -reaction_weight);
199
200 // If the colliding particle weight decreases to zero, remove particle by
201 // setting its id to invalid
202 if (weight <= std::numeric_limits<amrex::ParticleReal>::min())
203 {
204#if defined(AMREX_USE_OMP)
205#pragma omp atomic write
207#else
209 (unsigned long long *)&idcpu,
210 (unsigned long long)amrex::ParticleIdCpus::Invalid
211 );
212#endif
213 }
214 }
215}
216
217#endif // WARPX_BINARY_COLLISION_UTILS_H_
#define AMREX_INLINE
#define AMREX_IF_ON_HOST(CODE)
#define AMREX_GPU_HOST_DEVICE
CollisionType
Definition BinaryCollisionUtils.H:17
@ LinearBreitWheeler
Definition BinaryCollisionUtils.H:25
@ ProtonBoronToAlphasFusion
Definition BinaryCollisionUtils.H:21
@ Bremsstrahlung
Definition BinaryCollisionUtils.H:22
@ PairwiseCoulomb
Definition BinaryCollisionUtils.H:24
@ DSMC
Definition BinaryCollisionUtils.H:23
@ DeuteriumDeuteriumToProtonTritiumFusion
Definition BinaryCollisionUtils.H:18
@ DeuteriumDeuteriumToNeutronHeliumFusion
Definition BinaryCollisionUtils.H:19
@ DeuteriumTritiumToNeutronHeliumFusion
Definition BinaryCollisionUtils.H:17
@ LinearCompton
Definition BinaryCollisionUtils.H:26
@ DeuteriumHeliumToProtonHeliumFusion
Definition BinaryCollisionUtils.H:20
@ Undefined
Definition BinaryCollisionUtils.H:27
NuclearFusionType
Definition BinaryCollisionUtils.H:29
@ DeuteriumHeliumToProtonHelium
Definition BinaryCollisionUtils.H:33
@ ProtonBoronToAlphas
Definition BinaryCollisionUtils.H:34
@ DeuteriumDeuteriumToProtonTritium
Definition BinaryCollisionUtils.H:31
@ DeuteriumDeuteriumToNeutronHelium
Definition BinaryCollisionUtils.H:32
@ DeuteriumTritiumToNeutronHelium
Definition BinaryCollisionUtils.H:30
#define WARPX_ABORT_WITH_MESSAGE(MSG)
Definition TextMsg.H:15
amrex_particle_real ParticleReal
Definition BinaryCollisionUtils.cpp:23
void CheckFusionEnergy(const NuclearFusionType fusion_type, const amrex::ParticleReal mass_before, const amrex::ParticleReal mass_after)
Definition BinaryCollisionUtils.cpp:206
CollisionType get_collision_type(const std::string &collision_name, MultiParticleContainer const *const mypc)
Definition BinaryCollisionUtils.cpp:25
AMREX_GPU_HOST_DEVICE AMREX_INLINE CollisionType nuclear_fusion_type_to_collision_type(NuclearFusionType fusion_type)
Definition BinaryCollisionUtils.H:50
AMREX_GPU_HOST_DEVICE AMREX_INLINE bool is_two_product_fusion_type(const CollisionType collision_type)
Definition BinaryCollisionUtils.H:77
AMREX_GPU_HOST_DEVICE AMREX_INLINE void get_collision_parameters(const amrex::ParticleReal &p1x, const amrex::ParticleReal &p1y, const amrex::ParticleReal &p1z, const amrex::ParticleReal &p2x, const amrex::ParticleReal &p2y, const amrex::ParticleReal &p2z, 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:98
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:193
NuclearFusionType get_nuclear_fusion_type(const std::string &collision_name, MultiParticleContainer const *const mypc)
Definition BinaryCollisionUtils.cpp:104
constexpr auto c
vacuum speed of light [m/s]
Definition constant.H:153
constexpr auto c2_v
square of the vacuum speed of light [m^2/s^2] (variable template)
Definition constant.H:138
__host__ __device__ AMREX_FORCE_INLINE T Exch(T *address, T val) noexcept
__host__ __device__ AMREX_FORCE_INLINE void AddNoRet(T *sum, T value) noexcept
constexpr T powi(T x) noexcept
constexpr std::uint64_t Invalid