Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/celeritas/em/distribution/EnergyLossGaussianDistribution.hh was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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/EnergyLossGaussianDistribution.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <cmath>
0010 
0011 #include "corecel/Assert.hh"
0012 #include "corecel/Macros.hh"
0013 #include "corecel/Types.hh"
0014 #include "corecel/math/Algorithms.hh"
0015 #include "corecel/random/distribution/NormalDistribution.hh"
0016 
0017 #include "EnergyLossHelper.hh"
0018 
0019 namespace celeritas
0020 {
0021 //---------------------------------------------------------------------------//
0022 /*!
0023  * Sample energy loss from a Gaussian distribution.
0024  *
0025  * In a thick absorber, the total energy transfer is a result of many small
0026  * energy losses from a large number of collisions. The central limit theorem
0027  * applies, and the energy loss fluctuations can be described by a Gaussian
0028  * distribution. See section 7.3.1 of \cite{g4prm} and
0029  * PHYS332 section 2.3 of \cite{geant3-1993} .
0030  *
0031  * The Gaussian approximation is valid for heavy particles and in the
0032  * regime \f$ \kappa = \xi / T_\textrm{max} > 10 \f$.
0033  * Fluctuations of the unrestricted energy loss follow a Gaussian distribution
0034  * if \f$ \Delta E > \kappa T_\textrm{max} \f$, where \f$ T_\textrm{max} \f$
0035  * is the maximum energy transfer (PHYS332 section 2 of \cite{geant3-1993} ).
0036  * For fluctuations of the \em restricted energy loss, the condition is
0037  * modified to \f$ \Delta E > \kappa T_c \f$ and
0038  * \f$ T_\textrm{max} \le 2 T_c \f$,
0039  * where \f$ T_c \f$ is the delta ray cutoff energy (Eq. 7.6--7.7 from
0040  * \cite{g4prm} ).
0041  */
0042 class EnergyLossGaussianDistribution
0043 {
0044   public:
0045     //!@{
0046     //! \name Type aliases
0047     using Energy = units::MevEnergy;
0048     using EnergySq = RealQuantity<UnitProduct<units::Mev, units::Mev>>;
0049     //!@}
0050 
0051   public:
0052     // Construct from distribution parameters
0053     inline CELER_FUNCTION
0054     EnergyLossGaussianDistribution(Energy mean_loss, Energy bohr_stddev);
0055 
0056     // Construct from helper distribution parameters
0057     inline CELER_FUNCTION
0058     EnergyLossGaussianDistribution(Energy mean_loss, EnergySq bohr_var);
0059 
0060     // Construct from helper-calculated data
0061     explicit inline CELER_FUNCTION
0062     EnergyLossGaussianDistribution(EnergyLossHelper const& helper);
0063 
0064     // Sample energy loss according to the distribution
0065     template<class Generator>
0066     inline CELER_FUNCTION Energy operator()(Generator& rng);
0067 
0068   private:
0069     real_type const max_loss_;
0070     NormalDistribution<real_type> sample_normal_;
0071 };
0072 
0073 //---------------------------------------------------------------------------//
0074 // INLINE DEFINITIONS
0075 //---------------------------------------------------------------------------//
0076 /*!
0077  * Construct from mean/stddev.
0078  *
0079  * This formulation is used internally by the Urban distribution.
0080  */
0081 CELER_FUNCTION EnergyLossGaussianDistribution::EnergyLossGaussianDistribution(
0082     Energy mean_loss, Energy bohr_stddev)
0083     : max_loss_(2 * mean_loss.value())
0084     , sample_normal_(mean_loss.value(), bohr_stddev.value())
0085 
0086 {
0087     CELER_EXPECT(mean_loss > zero_quantity());
0088     CELER_EXPECT(bohr_stddev > zero_quantity());
0089 }
0090 
0091 //---------------------------------------------------------------------------//
0092 /*!
0093  * Construct from distribution parameters.
0094  *
0095  * The mean loss is the energy lost over the step, and the standard deviation
0096  * is the square root of Bohr's variance (PRM Eq. 7.8). For thick absorbers,
0097  * the straggling function approaches a Gaussian distribution with this
0098  * standard deviation.
0099  */
0100 CELER_FUNCTION EnergyLossGaussianDistribution::EnergyLossGaussianDistribution(
0101     Energy mean_loss, EnergySq bohr_var)
0102     : EnergyLossGaussianDistribution{mean_loss,
0103                                      Energy{std::sqrt(bohr_var.value())}}
0104 {
0105 }
0106 
0107 //---------------------------------------------------------------------------//
0108 /*!
0109  * Construct from helper-calculated data.
0110  */
0111 CELER_FUNCTION EnergyLossGaussianDistribution::EnergyLossGaussianDistribution(
0112     EnergyLossHelper const& helper)
0113     : EnergyLossGaussianDistribution{helper.mean_loss(), helper.bohr_variance()}
0114 {
0115 }
0116 
0117 //---------------------------------------------------------------------------//
0118 /*!
0119  * Sample energy loss according to the distribution.
0120  */
0121 template<class Generator>
0122 CELER_FUNCTION auto EnergyLossGaussianDistribution::operator()(Generator& rng)
0123     -> Energy
0124 {
0125     real_type result;
0126     do
0127     {
0128         result = sample_normal_(rng);
0129     } while (result <= 0 || result > max_loss_);
0130     return Energy{result};
0131 }
0132 
0133 //---------------------------------------------------------------------------//
0134 }  // namespace celeritas