WarpX
Loading...
Searching...
No Matches
TwoProductUtil.H
Go to the documentation of this file.
1/* Copyright 2022 Remi Lehe
2 *
3 * This file is part of WarpX.
4 *
5 * License: BSD-3-Clause-LBNL
6 */
7
8#ifndef WARPX_TWO_PRODUCT_UTIL_H
9#define WARPX_TWO_PRODUCT_UTIL_H
10
11#include "Utils/ParticleUtils.H"
13#include "Utils/WarpXConst.H"
14
15#include <AMReX_Math.H>
16#include <AMReX_Random.H>
17#include <AMReX_REAL.H>
18
19#include <cmath>
20#include <limits>
21
22namespace {
50 void TwoProductComputeProductMomenta (
51 const amrex::ParticleReal& u1x_in,
52 const amrex::ParticleReal& u1y_in,
53 const amrex::ParticleReal& u1z_in,
54 const amrex::ParticleReal& m1_in,
55 const amrex::ParticleReal& u2x_in,
56 const amrex::ParticleReal& u2y_in,
57 const amrex::ParticleReal& u2z_in,
58 const amrex::ParticleReal& m2_in,
59 amrex::ParticleReal& u1x_out,
60 amrex::ParticleReal& u1y_out,
61 amrex::ParticleReal& u1z_out,
62 const amrex::ParticleReal& m1_out,
63 amrex::ParticleReal& u2x_out,
64 amrex::ParticleReal& u2y_out,
65 amrex::ParticleReal& u2z_out,
66 const amrex::ParticleReal& m2_out,
67 const amrex::ParticleReal& E_reaction,
68 ScatteringAngleModel scattering_angle_model,
69 const amrex::RandomEngine& engine )
70 {
71 using namespace amrex::literals;
72 using namespace amrex::Math;
73
76 // Rest energy of incident particles
77 const amrex::ParticleReal E_rest_in = (m1_in + m2_in)*c2;
78 // Rest energy of products
79 const amrex::ParticleReal E_rest_out = (m1_out + m2_out)*c2;
80
81 // Compute momenta
82 // Note: for massless particles, the momentum is normalized to the electron mass
84 const amrex::ParticleReal p1x_in = (m1_in == 0) ? me*u1x_in : m1_in*u1x_in;
85 const amrex::ParticleReal p1y_in = (m1_in == 0) ? me*u1y_in : m1_in*u1y_in;
86 const amrex::ParticleReal p1z_in = (m1_in == 0) ? me*u1z_in : m1_in*u1z_in;
87 const amrex::ParticleReal p2x_in = (m2_in == 0) ? me*u2x_in : m2_in*u2x_in;
88 const amrex::ParticleReal p2y_in = (m2_in == 0) ? me*u2y_in : m2_in*u2y_in;
89 const amrex::ParticleReal p2z_in = (m2_in == 0) ? me*u2z_in : m2_in*u2z_in;
90
91 // Compute 0th component of the 4-momentum of the incident particles
92 const amrex::ParticleReal p1t_in = std::sqrt(
93 m1_in*m1_in*c2 + p1x_in*p1x_in + p1y_in*p1y_in + p1z_in*p1z_in);
94 const amrex::ParticleReal p2t_in = std::sqrt(
95 m2_in*m2_in*c2 + p2x_in*p2x_in + p2y_in*p2y_in + p2z_in*p2z_in);
96
97 // Square norm of the total (sum between the two particles) momenta in the lab frame
98 const amrex::ParticleReal p_total_sq = powi<2>(p1x_in+p2x_in) +
99 powi<2>(p1y_in+p2y_in) +
100 powi<2>(p1z_in+p2z_in);
101
102 // Total energy of incident macroparticles in the lab frame
103 const amrex::ParticleReal E_lab = (p1t_in + p2t_in) * PhysConst::c;
104 // Total energy squared of the reactants in the center of mass frame, calculated using the
105 // Lorentz invariance of the four-momentum norm
106 const amrex::ParticleReal E_star_sq = E_lab*E_lab - c2*p_total_sq;
107 // Total energy squared of the products in the center of mass frame
108 // In principle, the term - E_rest_in + E_rest_out + E_reaction is not needed and equal to
109 // zero (i.e. the energy liberated during the reaction is equal to the mass difference). However,
110 // due to possible inconsistencies in how the mass is defined in the code, it is
111 // probably more robust to subtract the rest masses and to add the reaction energy to the
112 // total kinetic energy.
113 const amrex::ParticleReal E_star_f_sq = powi<2>(std::sqrt(E_star_sq)
114 - E_rest_in + E_rest_out + E_reaction);
115
116 // Square of the norm of the momentum of the products in the center of mass frame
117 // Formula obtained by inverting E^2 = p^2*c^2 + m^2*c^4 in the COM frame for each particle
118 // The expression below is specifically written in a form that avoids returning
119 // small negative numbers due to machine precision errors, for low-energy particles
120 const amrex::ParticleReal E_ratio = std::sqrt(E_star_f_sq)/((m1_out + m2_out)*c2);
121 const amrex::ParticleReal p_star_f_sq = m1_out*m2_out*c2 * ( powi<2>(E_ratio) - 1._prt )
122 + powi<2>(m1_out - m2_out)*c2*0.25_prt * powi<2>( E_ratio - 1._prt/E_ratio );
123
124 // Preliminary calculation: compute center of mass velocity
125 const amrex::ParticleReal pt = p1t_in + p2t_in;
126 const amrex::ParticleReal vcx = (p1x_in+p2x_in) * PhysConst::c / pt;
127 const amrex::ParticleReal vcy = (p1y_in+p2y_in) * PhysConst::c / pt;
128 const amrex::ParticleReal vcz = (p1z_in+p2z_in) * PhysConst::c / pt;
129 const amrex::ParticleReal vc_sq = vcx*vcx + vcy*vcy + vcz*vcz;
130 const amrex::ParticleReal gc = 1._prt / std::sqrt( 1._prt - vc_sq*inv_c2 );
131
132 // Compute momentum of first product in the center of mass frame
133 amrex::ParticleReal px_star_out = 0.0_prt;
134 amrex::ParticleReal py_star_out = 0.0_prt;
135 amrex::ParticleReal pz_star_out = 0.0_prt;
136 if (scattering_angle_model == ScatteringAngleModel::Isotropic) {
137 // Isotropic scattering: the angle of emission of the products in the center of mass frame is random
138 ParticleUtils::RandomizeVelocity(px_star_out, py_star_out, pz_star_out, std::sqrt(p_star_f_sq),
139 engine);
140 }
141 else if (scattering_angle_model == ScatteringAngleModel::Forward) {
142 // Forward scattering: the products have the same direction as the incident particle in the center of mass frame
143 amrex::ParticleReal p1x_star_in, p1y_star_in, p1z_star_in;
144 if ( vc_sq > std::numeric_limits<amrex::ParticleReal>::min() )
145 {
146 // Convert momentum of first incident particle to lab frame, using equation (2)
147 // of F. Perez et al., Phys.Plasmas.19.083104 (2012)
148 const amrex::ParticleReal vcDps = vcx*p1x_in + vcy*p1y_in + vcz*p1z_in;
149 const amrex::ParticleReal factor0 = (gc-1._prt)/vc_sq;
150 const amrex::ParticleReal factor = factor0*vcDps - p1t_in*gc/PhysConst::c;
151 p1x_star_in = p1x_in + vcx * factor;
152 p1y_star_in = p1y_in + vcy * factor;
153 p1z_star_in = p1z_in + vcz * factor;
154 }
155 else // If center of mass velocity is zero, we are already in the lab frame
156 {
157 p1x_star_in = p1x_in;
158 p1y_star_in = p1y_in;
159 p1z_star_in = p1z_in;
160 }
161 const amrex::ParticleReal p1_star_in = std::sqrt(p1x_star_in*p1x_star_in + p1y_star_in*p1y_star_in + p1z_star_in*p1z_star_in);
162
163 // Momentum of the first product in the center of mass frame:
164 // same direction as the incident, but scaled to have the magnitude sqrt(p_star_f_sq)
165 const amrex::ParticleReal scaling = std::sqrt(p_star_f_sq)/p1_star_in;
166 px_star_out = p1x_star_in * scaling;
167 py_star_out = p1y_star_in * scaling;
168 pz_star_out = p1z_star_in * scaling;
169 }
170
171 // Next step is to convert momenta to lab frame
172 amrex::ParticleReal p1x_out, p1y_out, p1z_out;
173 // Convert momentum of first product to lab frame, using equation (13)
174 // of F. Perez et al., Phys.Plasmas.19.083104 (2012)
175 if ( vc_sq > std::numeric_limits<amrex::ParticleReal>::min() )
176 {
177 const amrex::ParticleReal p1t_out = std::sqrt(m1_out*m1_out*c2 + p_star_f_sq);
178 const amrex::ParticleReal vcDps = vcx*px_star_out + vcy*py_star_out + vcz*pz_star_out;
179 const amrex::ParticleReal factor0 = (gc-1._prt)/vc_sq;
180 const amrex::ParticleReal factor = factor0*vcDps + p1t_out*gc/PhysConst::c;
181 p1x_out = px_star_out + vcx * factor;
182 p1y_out = py_star_out + vcy * factor;
183 p1z_out = pz_star_out + vcz * factor;
184 }
185 else // If center of mass velocity is zero, we are already in the lab frame
186 {
187 p1x_out = px_star_out;
188 p1y_out = py_star_out;
189 p1z_out = pz_star_out;
190 }
191
192 // Compute momentum of the second product in lab frame, using total momentum conservation
193 const amrex::ParticleReal p2x_out = p1x_in + p2x_in - p1x_out;
194 const amrex::ParticleReal p2y_out = p1y_in + p2y_in - p1y_out;
195 const amrex::ParticleReal p2z_out = p1z_in + p2z_in - p1z_out;
196
197 // Compute the momentum of the product macroparticles
198 // Note: for massless particles, the momentum is normalized to the electron mass
199 u1x_out = (m1_out == 0) ? p1x_out/me : p1x_out/m1_out;
200 u1y_out = (m1_out == 0) ? p1y_out/me : p1y_out/m1_out;
201 u1z_out = (m1_out == 0) ? p1z_out/me : p1z_out/m1_out;
202 u2x_out = (m2_out == 0) ? p2x_out/me : p2x_out/m2_out;
203 u2y_out = (m2_out == 0) ? p2y_out/me : p2y_out/m2_out;
204 u2z_out = (m2_out == 0) ? p2z_out/me : p2z_out/m2_out;
205 }
206}
207
208#endif // WARPX_TWO_PRODUCT_UTIL_H
#define AMREX_INLINE
#define AMREX_GPU_HOST_DEVICE
ScatteringAngleModel
For binary collision algorithms, the strategy to determine the scattering angle in the center of mass...
Definition WarpXAlgorithmSelection.H:198
@ Isotropic
Definition WarpXAlgorithmSelection.H:198
@ Forward
Definition WarpXAlgorithmSelection.H:198
amrex_particle_real ParticleReal
AMREX_GPU_HOST_DEVICE AMREX_INLINE void RandomizeVelocity(amrex::ParticleReal &ux, amrex::ParticleReal &uy, amrex::ParticleReal &uz, const amrex::ParticleReal vp, amrex::RandomEngine const &engine)
Function to perform scattering of a particle that results in a random velocity vector with given magn...
Definition ParticleUtils.H:217
constexpr auto c
vacuum speed of light [m/s]
Definition constant.H:153
constexpr auto c2
square of the vacuum speed of light [m^2/s^2]
Definition constant.H:214
constexpr auto inv_c2_v
inverse of the square of the vacuum speed of light [s^2/m^2] (variable template)
Definition constant.H:146
constexpr auto m_e
electron mass [kg]
Definition constant.H:165
constexpr auto c2_v
square of the vacuum speed of light [m^2/s^2] (variable template)
Definition constant.H:138
constexpr auto inv_c2
inverse of the square of the vacuum speed of light [s^2/m^2]
Definition constant.H:220
constexpr T powi(T x) noexcept