Skip to content

Commit 2a4eeae

Browse files
authoredMar 24, 2025··
Use KineticEnergy instead of getEnergy (#5786)
We currently have two functions in the code that do almost exactly the same thing: ``` /** * \brief Return (relativistic) particle energy given velocity and mass. * Note the use of `double` since this calculation is prone to error with * single precision. * * @param[in] u2 square of particle speed (i.e. u dot u where u = gamma*v) * @param[in] mass particle mass * @param[out] energy particle energy in eV */ AMREX_GPU_HOST_DEVICE AMREX_INLINE void getEnergy ( amrex::ParticleReal const u2, double const mass, double& energy ) { using std::sqrt; using namespace amrex::literals; constexpr auto c2 = PhysConst::c * PhysConst::c; energy = mass * u2 / (sqrt(1.0_rt + u2 / c2) + 1.0_rt) / PhysConst::q_e; } ``` and ``` AMREX_GPU_HOST_DEVICE AMREX_INLINE amrex::ParticleReal KineticEnergy( const amrex::ParticleReal ux, const amrex::ParticleReal uy, const amrex::ParticleReal uz, const amrex::ParticleReal mass) { using namespace amrex; constexpr auto inv_c2 = 1.0_prt/(PhysConst::c * PhysConst::c); // The expression used is derived by reducing the expression // (gamma - 1)*(gamma + 1)/(gamma + 1) const auto u2 = ux*ux + uy*uy + uz*uz; const auto gamma = std::sqrt(1.0_prt + u2*inv_c2); return 1.0_prt/(1.0_prt + gamma)*mass*u2; } ``` The only differences are that `getEnergy` forces the use of double precision and returns an energy in `eV`. I think that it would be better if we could use only one function for clarity. Therefore, in this PR I replaced `getEnergy` with `KineticEnergy`. The units of the output are easy to deal with (we can just divide by 1eV the result). The precision is trickier. @roelof-groenewald , do you think that we really need to force `double` precision here? If it is the case, I think that it could be preferable to make `getEnergy` a template function and force double precision with something like `KineticEnergy<double>(...)`. What do you think? ---------
1 parent 5c7ac49 commit 2a4eeae

File tree

4 files changed

+20
-34
lines changed

4 files changed

+20
-34
lines changed
 

‎Source/Particles/Algorithms/KineticEnergy.H

+10-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "AMReX_Extension.H"
1414
#include "AMReX_GpuQualifiers.H"
15+
#include "AMReX_Math.H"
1516
#include "AMReX_REAL.H"
1617

1718
#include <cmath>
@@ -22,28 +23,30 @@ namespace Algorithms{
2223
* \brief Computes the kinetic energy of a particle.
2324
* This method should not be used with photons.
2425
*
26+
* @tparam T floating-point type to be used in internal calculations (by default equal to amrex::ParticleReal)
2527
* @param[in] ux x component of the particle momentum (code units)
2628
* @param[in] uy y component of the particle momentum (code units)
2729
* @param[in] uz z component of the particle momentum (code units)
2830
* @param[in] mass mass of the particle (in S.I. units)
2931
*
3032
* @return the kinetic energy of the particle (in S.I. units)
3133
*/
34+
template <typename T = amrex::ParticleReal>
3235
AMREX_GPU_HOST_DEVICE AMREX_INLINE
33-
amrex::ParticleReal KineticEnergy(
34-
const amrex::ParticleReal ux, const amrex::ParticleReal uy, const amrex::ParticleReal uz,
35-
const amrex::ParticleReal mass)
36+
T KineticEnergy(
37+
const amrex::ParticleReal ux, const amrex::ParticleReal uy, const amrex::ParticleReal uz, const amrex::ParticleReal mass)
3638
{
3739
using namespace amrex;
3840

39-
constexpr auto inv_c2 = 1.0_prt/(PhysConst::c * PhysConst::c);
41+
constexpr auto one = static_cast<T>(1.0);
42+
constexpr auto inv_c2 = one/Math::powi<2>(static_cast<T>(PhysConst::c));
4043

4144
// The expression used is derived by reducing the expression
4245
// (gamma - 1)*(gamma + 1)/(gamma + 1)
4346

44-
const auto u2 = ux*ux + uy*uy + uz*uz;
45-
const auto gamma = std::sqrt(1.0_prt + u2*inv_c2);
46-
return 1.0_prt/(1.0_prt + gamma)*mass*u2;
47+
const auto u2 = static_cast<T>(ux*ux + uy*uy + uz*uz);
48+
const auto gamma = std::sqrt(one + u2*inv_c2);
49+
return one/(one + gamma)*static_cast<T>(mass)*u2;
4750
}
4851

4952
/**

‎Source/Particles/Collision/BackgroundMCC/BackgroundMCCCollision.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "BackgroundMCCCollision.H"
88

99
#include "ImpactIonization.H"
10+
#include "Particles/Algorithms/KineticEnergy.H"
1011
#include "Particles/ParticleCreation/FilterCopyTransform.H"
1112
#include "Particles/ParticleCreation/SmartCopy.H"
1213
#include "Utils/Parser/ParserUtils.H"
@@ -435,8 +436,8 @@ void BackgroundMCCCollision::doBackgroundCollisionsWithinTile
435436
// subtract any energy penalty of the collision from the
436437
// projectile energy
437438
if (scattering_process.m_energy_penalty > 0.0_prt) {
438-
ParticleUtils::getEnergy(v_coll2, m, E_coll);
439-
E_coll = (E_coll - scattering_process.m_energy_penalty) * PhysConst::q_e;
439+
constexpr auto eV = PhysConst::q_e;
440+
E_coll = (Algorithms::KineticEnergy<double>(vx, vy, vz, m) - scattering_process.m_energy_penalty*eV);
440441
const auto scale_fac = static_cast<amrex::ParticleReal>(
441442
std::sqrt(E_coll * (E_coll + 2.0_prt*mc2) / c2) / m / v_coll);
442443
vx *= scale_fac;

‎Source/Particles/Collision/BackgroundMCC/ImpactIonization.H

+7-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "Particles/Collision/ScatteringProcess.H"
1111

12+
#include "Particles/Algorithms/KineticEnergy.H"
1213
#include "Utils/ParticleUtils.H"
1314
#include "Utils/WarpXConst.H"
1415

@@ -94,13 +95,14 @@ public:
9495
const ParticleReal uz = ptd.m_rdata[PIdx::uz][i];
9596

9697
// calculate kinetic energy
97-
const ParticleReal u_coll2 = ux*ux + uy*uy + uz*uz;
98-
ParticleUtils::getEnergy(u_coll2, m_mass, E_coll);
98+
constexpr auto eV = PhysConst::q_e;
99+
E_coll = Algorithms::KineticEnergy<double>(ux, uy, uz, m_mass)/eV;
99100

100101
// get collision cross-section
101102
const ParticleReal sigma_E = m_mcc_process.getCrossSection(static_cast<amrex::ParticleReal>(E_coll));
102103

103104
// calculate normalized collision frequency
105+
const ParticleReal u_coll2 = ux*ux + uy*uy + uz*uz;
104106
const ParticleReal nu_i = n_a * sigma_E * sqrt(u_coll2) / m_nu_max;
105107

106108
// check if this collision should be performed
@@ -198,11 +200,11 @@ public:
198200
auto& i_uz = dst2.m_rdata[PIdx::uz][i_dst2];
199201

200202
// calculate kinetic energy
201-
const ParticleReal u_coll2 = ux*ux + uy*uy + uz*uz;
202-
ParticleUtils::getEnergy(u_coll2, m_mass1, E_coll);
203+
constexpr auto eV = PhysConst::q_e;
204+
E_coll = Algorithms::KineticEnergy<double>(ux, uy, uz, m_mass1)/eV;
203205

204206
// each electron gets half the energy (could change this later)
205-
const auto E_out = static_cast<amrex::ParticleReal>((E_coll - m_energy_cost) / 2.0_prt * PhysConst::q_e);
207+
const auto E_out = static_cast<amrex::ParticleReal>((E_coll - m_energy_cost) / 2.0_prt * eV);
206208

207209
// precalculate often used value
208210
constexpr auto c2 = PhysConst::c * PhysConst::c;

‎Source/Utils/ParticleUtils.H

-20
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,6 @@ namespace ParticleUtils {
3333
amrex::MFIter const & mfi,
3434
WarpXParticleContainer::ParticleTileType & ptile);
3535

36-
/**
37-
* \brief Return (relativistic) particle energy given velocity and mass.
38-
* Note the use of `double` since this calculation is prone to error with
39-
* single precision.
40-
*
41-
* @param[in] u2 square of particle speed (i.e. u dot u where u = gamma*v)
42-
* @param[in] mass particle mass
43-
* @param[out] energy particle energy in eV
44-
*/
45-
AMREX_GPU_HOST_DEVICE AMREX_INLINE
46-
void getEnergy ( amrex::ParticleReal const u2, double const mass,
47-
double& energy )
48-
{
49-
using std::sqrt;
50-
using namespace amrex::literals;
51-
52-
constexpr auto c2 = PhysConst::c * PhysConst::c;
53-
energy = mass * u2 / (sqrt(1.0_rt + u2 / c2) + 1.0_rt) / PhysConst::q_e;
54-
}
55-
5636
/**
5737
* \brief Return (relativistic) collision energy assuming the target (with
5838
* mass M) is stationary and the projectile is approaching with the

0 commit comments

Comments
 (0)