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 the Geant4 Physics Reference Manual and
0029  * GEANT3 PHYS332 section 2.3.
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
0034  * follow a Gaussian distribution if \f$ \Delta E > \kappa T_{max} \f$,
0035  * where \f$ T_{max} \f$ is the maximum energy transfer (PHYS332 section
0036  * 2). For fluctuations of the \em restricted energy loss, the condition is
0037  * modified to \f$ \Delta E > \kappa T_{c} \f$ and \f$ T_{max} \le 2 T_c
0038  * \f$, where \f$ T_c \f$ is the delta ray cutoff energy (PRM Eq. 7.6-7.7).
0039  */
0040 class EnergyLossGaussianDistribution
0041 {
0042   public:
0043     //!@{
0044     //! \name Type aliases
0045     using Energy = units::MevEnergy;
0046     using EnergySq = RealQuantity<UnitProduct<units::Mev, units::Mev>>;
0047     //!@}
0048 
0049   public:
0050     // Construct from distribution parameters
0051     inline CELER_FUNCTION
0052     EnergyLossGaussianDistribution(Energy mean_loss, Energy bohr_stddev);
0053 
0054     // Construct from helper distribution parameters
0055     inline CELER_FUNCTION
0056     EnergyLossGaussianDistribution(Energy mean_loss, EnergySq bohr_var);
0057 
0058     // Construct from helper-calculated data
0059     explicit inline CELER_FUNCTION
0060     EnergyLossGaussianDistribution(EnergyLossHelper const& helper);
0061 
0062     // Sample energy loss according to the distribution
0063     template<class Generator>
0064     inline CELER_FUNCTION Energy operator()(Generator& rng);
0065 
0066   private:
0067     real_type const max_loss_;
0068     NormalDistribution<real_type> sample_normal_;
0069 };
0070 
0071 //---------------------------------------------------------------------------//
0072 // INLINE DEFINITIONS
0073 //---------------------------------------------------------------------------//
0074 /*!
0075  * Construct from mean/stddev.
0076  *
0077  * This formulation is used internally by the Urban distribution.
0078  */
0079 CELER_FUNCTION EnergyLossGaussianDistribution::EnergyLossGaussianDistribution(
0080     Energy mean_loss, Energy bohr_stddev)
0081     : max_loss_(2 * mean_loss.value())
0082     , sample_normal_(mean_loss.value(), bohr_stddev.value())
0083 
0084 {
0085     CELER_EXPECT(mean_loss > zero_quantity());
0086     CELER_EXPECT(bohr_stddev > zero_quantity());
0087 }
0088 
0089 //---------------------------------------------------------------------------//
0090 /*!
0091  * Construct from distribution parameters.
0092  *
0093  * The mean loss is the energy lost over the step, and the standard deviation
0094  * is the square root of Bohr's variance (PRM Eq. 7.8). For thick absorbers,
0095  * the straggling function approaches a Gaussian distribution with this
0096  * standard deviation.
0097  */
0098 CELER_FUNCTION EnergyLossGaussianDistribution::EnergyLossGaussianDistribution(
0099     Energy mean_loss, EnergySq bohr_var)
0100     : EnergyLossGaussianDistribution{mean_loss,
0101                                      Energy{std::sqrt(bohr_var.value())}}
0102 {
0103 }
0104 
0105 //---------------------------------------------------------------------------//
0106 /*!
0107  * Construct from helper-calculated data.
0108  */
0109 CELER_FUNCTION EnergyLossGaussianDistribution::EnergyLossGaussianDistribution(
0110     EnergyLossHelper const& helper)
0111     : EnergyLossGaussianDistribution{helper.mean_loss(), helper.bohr_variance()}
0112 {
0113 }
0114 
0115 //---------------------------------------------------------------------------//
0116 /*!
0117  * Sample energy loss according to the distribution.
0118  */
0119 template<class Generator>
0120 CELER_FUNCTION auto
0121 EnergyLossGaussianDistribution::operator()(Generator& rng) -> Energy
0122 {
0123     real_type result;
0124     do
0125     {
0126         result = sample_normal_(rng);
0127     } while (result <= 0 || result > max_loss_);
0128     return Energy{result};
0129 }
0130 
0131 //---------------------------------------------------------------------------//
0132 }  // namespace celeritas