Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:31:17

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2021-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file celeritas/em/interactor/detail/SBPositronXsCorrector.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <cmath>
0011 
0012 #include "corecel/Types.hh"
0013 #include "corecel/math/NumericLimits.hh"
0014 #include "celeritas/Constants.hh"
0015 #include "celeritas/Quantities.hh"
0016 #include "celeritas/mat/ElementView.hh"
0017 
0018 namespace celeritas
0019 {
0020 namespace detail
0021 {
0022 //---------------------------------------------------------------------------//
0023 /*!
0024  * Scale SB differential cross sections for positrons.
0025  *
0026  * This correction factor is the ratio of the positron to electron cross
0027  * sections. It appears in the bowels of \c
0028  * G4SeltzerBergerModel::SampleEnergyTransfer in Geant4 and scales the SB cross
0029  * section by a factor
0030  * \f[
0031    \frac{\sigma^+}{\sigma^-}
0032        = \exp( 2 \pi \alpha Z [ \beta^{-1}(E - k_c) - \beta^{-1}(E - k) ] )
0033  * \f]
0034  * where the inverse positron speed is : \f[
0035   \beta^{-1}(E) = \frac{c}{v} = \sqrt{1 - \left( \frac{m_e c^2}{E + m_e c^2}
0036   \right)^2}
0037   \,,
0038  * \f]
0039  * \f$ \alpha \f$ is the fine structure constant, \f$E\f$ is the
0040  * incident positron kinetic energy, \f$k_c\f$ is the gamma
0041  * production cutoff energy, and \f$ k \f$ is the provisionally sampled
0042  * energy of the emitted photon.
0043  *
0044  * \f$ \frac{\sigma^+}{\sigma^-} = 1 \f$ at the low end of the spectrum (where
0045  * \f$ k / E = 0 \f$) and is 0 at the tip of the spectrum where \f$ k / E \to 1
0046  * \f$.
0047  *
0048  * The correction factor is described in:
0049  *
0050  *   Kim, Longhuan, R. H. Pratt, S. M. Seltzer, and M. J. Berger. “Ratio of
0051  *   Positron to Electron Bremsstrahlung Energy Loss: An Approximate Scaling
0052  *   Law.” Physical Review A 33, no. 5 (May 1, 1986): 3002–9.
0053  *   https://doi.org/10.1103/PhysRevA.33.3002.
0054  */
0055 class SBPositronXsCorrector
0056 {
0057   public:
0058     //!@{
0059     using Energy = units::MevEnergy;
0060     using Mass = units::MevMass;
0061     using Xs = Quantity<SBElementTableData::XsUnits>;
0062     //!@}
0063 
0064   public:
0065     // Construct with positron data
0066     inline CELER_FUNCTION SBPositronXsCorrector(Mass positron_mass,
0067                                                 ElementView const& el,
0068                                                 Energy min_gamma_energy,
0069                                                 Energy inc_energy);
0070 
0071     // Calculate cross section scaling factor for the given exiting energy
0072     inline CELER_FUNCTION real_type operator()(Energy energy) const;
0073 
0074   private:
0075     //// DATA ////
0076 
0077     real_type const positron_mass_;
0078     real_type const alpha_z_;
0079     real_type const inc_energy_;
0080     real_type const cutoff_invbeta_;
0081 
0082     //// HELPER FUNCTIONS ////
0083 
0084     inline CELER_FUNCTION real_type calc_invbeta(real_type gamma_energy) const;
0085 };
0086 
0087 //---------------------------------------------------------------------------//
0088 // INLINE DEFINITIONS
0089 //---------------------------------------------------------------------------//
0090 /*!
0091  * Construct with positron data and energy range.
0092  */
0093 CELER_FUNCTION
0094 SBPositronXsCorrector::SBPositronXsCorrector(Mass positron_mass,
0095                                              ElementView const& el,
0096                                              Energy min_gamma_energy,
0097                                              Energy inc_energy)
0098     : positron_mass_{positron_mass.value()}
0099     , alpha_z_{2 * constants::pi * celeritas::constants::alpha_fine_structure
0100                * el.atomic_number().unchecked_get()}
0101     , inc_energy_(inc_energy.value())
0102     , cutoff_invbeta_{this->calc_invbeta(min_gamma_energy.value())}
0103 {
0104     CELER_EXPECT(inc_energy > min_gamma_energy);
0105 }
0106 
0107 //---------------------------------------------------------------------------//
0108 /*!
0109  * Calculate scaling factor for the given exiting gamma energy.
0110  *
0111  * Eq. 21 in Kim et al.
0112  */
0113 CELER_FUNCTION real_type SBPositronXsCorrector::operator()(Energy energy) const
0114 {
0115     CELER_EXPECT(energy > zero_quantity());
0116     CELER_EXPECT(energy.value() < inc_energy_);
0117     real_type delta = cutoff_invbeta_ - this->calc_invbeta(energy.value());
0118 
0119     // Avoid positive delta values due to floating point inaccuracies
0120     // See https://github.com/celeritas-project/celeritas/issues/617
0121     CELER_ASSERT(delta < 100 * numeric_limits<real_type>::epsilon());
0122     real_type result = std::exp(alpha_z_ * celeritas::min(delta, real_type{0}));
0123     CELER_ENSURE(result <= 1);
0124     return result;
0125 }
0126 
0127 //---------------------------------------------------------------------------//
0128 /*!
0129  * Calculate the inverse of the relativistic positron speed.
0130  *
0131  * The input here is the exiting gamma energy, so the positron energy is the
0132  * remainder from the incident energy. The relativistic speed \f$ \beta \f$
0133  * is:
0134  * \f[
0135   \beta^{-1}(K)
0136    = \frac{K + m c^2}{\sqrt{K (K + 2 m c^2)}}
0137    = \frac{K + mc^2}{\sqrt{K^2 + 2 K mc^2 + (mc^2)^2 - (mc^2)^2}}
0138    = \frac{K + mc^2}{\sqrt{(K + mc^2)^2 - mc^2}}
0139    = 1/\sqrt{1 - \left( \frac{mc^2}{K + mc^2} \right)^2}
0140    = 1 / \beta(K)
0141  * \f]
0142  */
0143 CELER_FUNCTION real_type
0144 SBPositronXsCorrector::calc_invbeta(real_type gamma_energy) const
0145 {
0146     CELER_EXPECT(gamma_energy > 0 && gamma_energy < inc_energy_);
0147     //! \todo Use local-data ParticleTrackView
0148     // Positron has all the energy except what it gave to the gamma
0149     real_type energy = inc_energy_ - gamma_energy;
0150     return (energy + positron_mass_)
0151            / std::sqrt(energy * (energy + 2 * positron_mass_));
0152 }
0153 
0154 //---------------------------------------------------------------------------//
0155 }  // namespace detail
0156 }  // namespace celeritas