Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:53:33

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file celeritas/em/distribution/MuAngularDistribution.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Macros.hh"
0010 #include "corecel/Types.hh"
0011 #include "corecel/math/Algorithms.hh"
0012 #include "corecel/random/distribution/UniformRealDistribution.hh"
0013 #include "celeritas/Constants.hh"
0014 #include "celeritas/Quantities.hh"
0015 
0016 namespace celeritas
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Sample the polar angle for muon bremsstrahlung and pair production.
0021  *
0022  * The polar angle is sampled according to a simplified PDF
0023  * \f[
0024    f(r) \sim \frac{r}{(1 + r^2)^2}, \ r = frac{E\theta}{m}
0025  * \f]
0026  * by sampling
0027  * \f[
0028    \theta = r\frac{m}{E}
0029  * \f]
0030  * with
0031  * \f[
0032    r = \sqrt{frac{a}{1 - a}},
0033    a = \xi \frac{r^2_{\text{max}}}{1 + r^2_{\text{max}}},
0034    r_{\text{max}} = frac{\pi}{2} E' / m \min(1, E' / \epsilon),
0035  * \f]
0036  * and where \f$ m \f$ is the incident muon mass, \f$ E \f$ is incident energy,
0037  * \f$ \epsilon \f$ is the emitted energy,
0038  * \f$ E' = E - \epsilon \f$, and \f$ \xi \sim U(0,1) \f$.
0039  *
0040  * \note This performs the same sampling routine as in Geant4's \c
0041  * G4ModifiedMephi class and documented in section 11.2.4 of the Geant4 Physics
0042  * Reference (release 11.2).
0043  */
0044 class MuAngularDistribution
0045 {
0046   public:
0047     //!@{
0048     //! \name Type aliases
0049     using Energy = units::MevEnergy;
0050     using Mass = units::MevMass;
0051     //!@}
0052 
0053   public:
0054     // Construct with incident and secondary particle quantities
0055     inline CELER_FUNCTION
0056     MuAngularDistribution(Energy inc_energy, Mass inc_mass, Energy energy);
0057 
0058     // Sample the cosine of the polar angle of the secondary
0059     template<class Engine>
0060     inline CELER_FUNCTION real_type operator()(Engine& rng);
0061 
0062   private:
0063     // Incident particle Lorentz factor
0064     real_type gamma_;
0065     // r_max^2 / (1 + r_max^2)
0066     UniformRealDistribution<real_type> sample_a_;
0067 };
0068 
0069 //---------------------------------------------------------------------------//
0070 // INLINE DEFINITIONS
0071 //---------------------------------------------------------------------------//
0072 /*!
0073  * Construct with incident and secondary particle.
0074  */
0075 CELER_FUNCTION
0076 MuAngularDistribution::MuAngularDistribution(Energy inc_energy,
0077                                              Mass inc_mass,
0078                                              Energy energy)
0079     : gamma_(1 + value_as<Energy>(inc_energy) / value_as<Mass>(inc_mass))
0080 {
0081     real_type r_max_sq = ipow<2>(
0082         real_type(0.5) * constants::pi * gamma_
0083         * min(real_type(1),
0084               gamma_ * value_as<Mass>(inc_mass) / value_as<Energy>(energy) - 1));
0085     sample_a_ = {0, r_max_sq / (1 + r_max_sq)};
0086 }
0087 
0088 //---------------------------------------------------------------------------//
0089 /*!
0090  * Sample the cosine of the polar angle of the secondary.
0091  */
0092 template<class Engine>
0093 CELER_FUNCTION real_type MuAngularDistribution::operator()(Engine& rng)
0094 {
0095     real_type a = sample_a_(rng);
0096     return std::cos(std::sqrt(a / (1 - a)) / gamma_);
0097 }
0098 
0099 //---------------------------------------------------------------------------//
0100 }  // namespace celeritas