![]() |
|
|||
File indexing completed on 2025-02-22 10:31:16
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/distribution/SBEnergyDistribution.hh 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include "corecel/grid/TwodSubgridCalculator.hh" 0011 #include "corecel/math/Algorithms.hh" 0012 #include "celeritas/Quantities.hh" 0013 #include "celeritas/em/data/SeltzerBergerData.hh" 0014 #include "celeritas/random/distribution/RejectionSampler.hh" 0015 0016 #include "SBEnergyDistHelper.hh" 0017 0018 namespace celeritas 0019 { 0020 //---------------------------------------------------------------------------// 0021 /*! 0022 * Default scaling for SB cross sections. 0023 */ 0024 struct SBElectronXsCorrector 0025 { 0026 using Xs = Quantity<SBElementTableData::XsUnits>; 0027 0028 //! No cross section scaling for any exiting energy 0029 CELER_FUNCTION real_type operator()(units::MevEnergy) const { return 1; } 0030 }; 0031 0032 //---------------------------------------------------------------------------// 0033 /*! 0034 * Sample exiting photon energy from Bremsstrahlung. 0035 * 0036 * The SB energy distribution uses tabulated Seltzer-Berger differential cross 0037 * section data from G4EMLOW, which stores scaled cross sections as a function 0038 * of incident particle energy and exiting gamma energy (see SeltzerBergerModel 0039 * for details). The sampling procedure is roughly laid out in section 0040 * [PHYS341] of the GEANT3 physics reference manual, although like Geant4 we 0041 * use raw tabulated SB data rather than a parameter fit. Also like Geant4 we 0042 * include the extra density correction factor. 0043 * 0044 * Once an element and incident energy have been selected, the exiting energy 0045 * distribution is the differential cross section, which is stored as a scaled 0046 * tabulated value. The reconstructed cross section gives the pdf 0047 * \f[ 0048 * p(\kappa) \propto \difd{\sigma}{k} s 0049 \propto \frac{1}{\kappa} \chi_Z(E, \kappa) 0050 * \f] 0051 * where \f$ \kappa = k / E \f$ is the ratio of the emitted photon energy to 0052 * the incident charged particle energy, and the domain of \em p is 0053 * nominally restricted by the allowable energy range \f$ \kappa_c < \kappa < 1 0054 * \f$, where \f$ \kappa_c \f$ is from the cutoff energy \f$ E_c \f$ for 0055 * secondary gamma production. This distribution is sampled by decomposing it 0056 * into an analytic sampling of \f$ 1/\kappa \f$ and a rejection sample on 0057 * the scaled cross section \f$ \chi \f$. 0058 * The analytic sample over the domain is from \f[ 0059 p_1(\kappa) \frac{1}{\ln 1/\kappa_c} \frac{1}{\kappa} 0060 * \f] 0061 * by sampling 0062 * \f[ 0063 \kappa = \exp( \xi \ln \kappa_c ) \,, 0064 \f] 0065 * and the rejection sample is the ratio of the scaled differential cross 0066 * section at the exiting energy to the maximum across all exiting energies. 0067 * \f[ 0068 p_2(\kappa) = \frac{\chi_Z(E, \kappa)}{\max_\kappa \chi_Z(E, \kappa)} 0069 \f] 0070 * Since the tabulated data is bilinearly interpolated in incident and exiting 0071 * energy, we can calculate a bounding maximum by precalculating (at 0072 * setup time) the index of the maximum value of \f$ \chi \f$ and 0073 * linearly interpolating those maximum values based on the incident energy. 0074 * 0075 * The above algorithm is idealized; in practice, the minimum and maximum 0076 * values are adjusted for a constant factor \f$d_\rho\f$, which depends on the 0077 * incident particle mass + energy and the material's electron density: 0078 * \f[ 0079 \kappa_\mathrm{min} = \ln (E_c^2 + d_\rho E^2) 0080 * \f] 0081 * and 0082 * \f[ 0083 \kappa_\mathrm{max} = \ln (E^2 + d_\rho E^2) \, . 0084 * \f] 0085 * With this correction, the sample of the exiting gamma energy 0086 * \f$ k = \kappa / E \f$ is transformed from the simple exponential above to: 0087 * \f[ 0088 * k = \sqrt{ \exp(\kappa_\mathrm{min} + \xi [\kappa_\mathrm{max} - 0089 \kappa_\mathrm{min}]) - d_\rho E^2} 0090 * \f] 0091 * 0092 * Most of the mechanics of the sampling are in the template-free 0093 * \c SBEnergyDistHelper, which is passed as a construction argument to this 0094 * sampler. The separate class exists here to minimize duplication of templated 0095 * code, which is required to provide for an on-the-fly correction of the cross 0096 * section sampling. 0097 */ 0098 template<class XSCorrector> 0099 class SBEnergyDistribution 0100 { 0101 public: 0102 //!@{ 0103 //! \name Type aliases 0104 using SBData = NativeCRef<SeltzerBergerData>; 0105 using Energy = units::MevEnergy; 0106 using EnergySq = Quantity<UnitProduct<units::Mev, units::Mev>>; 0107 //!@} 0108 0109 public: 0110 // Construct from data 0111 inline CELER_FUNCTION SBEnergyDistribution(SBEnergyDistHelper const& helper, 0112 XSCorrector scale_xs); 0113 0114 template<class Engine> 0115 inline CELER_FUNCTION Energy operator()(Engine& rng); 0116 0117 private: 0118 //// IMPLEMENTATION DATA //// 0119 SBEnergyDistHelper const& helper_; 0120 XSCorrector scale_xs_; 0121 }; 0122 0123 //---------------------------------------------------------------------------// 0124 // INLINE DEFINITIONS 0125 //---------------------------------------------------------------------------// 0126 /*! 0127 * Construct from incident particle and energy. 0128 * 0129 * The incident energy *must* be within the bounds of the SB table data, so the 0130 * Model's applicability must be consistent with the table data. 0131 */ 0132 template<class X> 0133 CELER_FUNCTION 0134 SBEnergyDistribution<X>::SBEnergyDistribution(SBEnergyDistHelper const& helper, 0135 X scale_xs) 0136 : helper_(helper), scale_xs_(::celeritas::move(scale_xs)) 0137 { 0138 } 0139 0140 //---------------------------------------------------------------------------// 0141 /*! 0142 * Sample the exiting energy by doing a table lookup and rejection. 0143 */ 0144 template<class X> 0145 template<class Engine> 0146 CELER_FUNCTION auto SBEnergyDistribution<X>::operator()(Engine& rng) -> Energy 0147 { 0148 // Sampled energy 0149 Energy exit_energy; 0150 // Calculated cross section used inside rejection sampling 0151 real_type xs{}; 0152 do 0153 { 0154 // Sample scaled energy and subtract correction factor 0155 exit_energy = helper_.sample_exit_energy(rng); 0156 0157 // Interpolate the differential cross setion at the sampled exit energy 0158 xs = helper_.calc_xs(exit_energy).value() * scale_xs_(exit_energy); 0159 } while (RejectionSampler<>(xs, helper_.max_xs().value())(rng)); 0160 return exit_energy; 0161 } 0162 0163 //---------------------------------------------------------------------------// 0164 } // namespace celeritas
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |