![]() |
|
|||
File indexing completed on 2025-02-22 10:31:20
0001 //----------------------------------*-C++-*----------------------------------// 0002 // Copyright 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/xs/NuclearFormFactors.hh 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include <cmath> 0011 0012 #include "corecel/math/Algorithms.hh" 0013 #include "celeritas/Quantities.hh" 0014 #include "celeritas/phys/AtomicNumber.hh" 0015 0016 namespace celeritas 0017 { 0018 //---------------------------------------------------------------------------// 0019 //! Helper traits used in nuclear form factors 0020 struct NuclearFormFactorTraits 0021 { 0022 //!@{ 0023 //! \name Type aliases 0024 using AtomicMassNumber = AtomicNumber; 0025 using Momentum = units::MevMomentum; 0026 using MomentumSq = units::MevMomentumSq; 0027 using InvMomentum = Quantity<UnitInverse<Momentum::unit_type>>; 0028 using InvMomentumSq = Quantity<UnitInverse<MomentumSq::unit_type>>; 0029 using FFType = NuclearFormFactorType; 0030 //!@} 0031 0032 //! Momentum transfer prefactor: 1 fm / hbar 0033 static CELER_CONSTEXPR_FUNCTION InvMomentum fm_par_hbar() 0034 { 0035 return native_value_to<InvMomentum>(units::femtometer 0036 / constants::hbar_planck); 0037 } 0038 }; 0039 0040 //---------------------------------------------------------------------------// 0041 /*! 0042 * Exponential nuclear form factor. 0043 * 0044 * This nuclear form factor corresponds \c NuclearFormFactorType::exponential 0045 * and assumes the nuclear charge decays exponentially from its center. This 0046 * assumes a parameterization of the atomic nucleus valid for light and medium 0047 * atomic nuclei (Eq. 7 of [BKM2002]): \f[ 0048 * R_N = 1.27A^{0.27} \,\mathrm{fm} 0049 * \f] 0050 * with a special case for the proton radius, \f$ R_p = 0.85 \f$ fm. 0051 * 0052 * [BKM2002] A.V. Butkevich, R.P. Kokoulin, G.V. Matushko, S.P. Mikheyev, 0053 * Comments on multiple scattering of high-energy muons in thick layers, 0054 * Nuclear Instruments and Methods in Physics Research Section A: 0055 * Accelerators, Spectrometers, Detectors and Associated Equipment 488 0056 * (2002) 282–294. https://doi.org/10.1016/S0168-9002(02)00478-3. 0057 * 0058 * \todo Instead of using this coarse parameterization, we should add nuclear 0059 * radius to the isotope properties for a more accurate treatment, and 0060 * construct these classes directly from the atomic radius. 0061 */ 0062 class ExpNuclearFormFactor : public NuclearFormFactorTraits 0063 { 0064 public: 0065 //! Form factor type corresponding to this distribution 0066 static CELER_CONSTEXPR_FUNCTION FFType ff_type() 0067 { 0068 return FFType::exponential; 0069 } 0070 0071 // Construct with atomic mass number 0072 explicit inline CELER_FUNCTION 0073 ExpNuclearFormFactor(AtomicMassNumber a_mass); 0074 0075 // Construct with precalculated form factor 0076 explicit inline CELER_FUNCTION 0077 ExpNuclearFormFactor(InvMomentumSq prefactor); 0078 0079 // Calculate from square of target momentum 0080 inline CELER_FUNCTION real_type operator()(MomentumSq target_momsq) const; 0081 0082 // Calculate from target momentum 0083 inline CELER_FUNCTION real_type operator()(Momentum target_mom) const; 0084 0085 //! Nuclear form prefactor for the selected isotope 0086 CELER_FORCEINLINE_FUNCTION InvMomentumSq prefactor() const 0087 { 0088 return InvMomentumSq{prefactor_}; 0089 } 0090 0091 private: 0092 real_type prefactor_; // Function of nuclear radius [(MeV/c)^{-2}] 0093 }; 0094 0095 //---------------------------------------------------------------------------// 0096 /*! 0097 * Gaussian nuclear form factor. 0098 * 0099 * This nuclear form factor corresponds \c NuclearFormFactorType::gaussian and 0100 * assumes a Gaussian distribution of nuclear charge. Its 0101 * prefactor has the same value as the exponential. 0102 */ 0103 class GaussianNuclearFormFactor : public ExpNuclearFormFactor 0104 { 0105 public: 0106 //! Form factor type corresponding to this distribution 0107 static CELER_CONSTEXPR_FUNCTION FFType ff_type() 0108 { 0109 return FFType::gaussian; 0110 } 0111 0112 using ExpNuclearFormFactor::ExpNuclearFormFactor; 0113 0114 // Calculate from square of target momentum 0115 inline CELER_FUNCTION real_type operator()(MomentumSq target_momsq) const; 0116 0117 // Calculate from target momentum 0118 inline CELER_FUNCTION real_type operator()(Momentum target_mom) const; 0119 }; 0120 0121 //---------------------------------------------------------------------------// 0122 /*! 0123 * Uniform-uniform folded nuclear form factor. 0124 * 0125 * This nuclear form factor corresponds \c NuclearFormFactorType::flat and 0126 * assumes a uniform nuclear charge at the center with a smoothly decreasing 0127 * charge at the surface. This leads to a form factor: \f[ 0128 * F(q) = F'(x(R_0, q)) F'(x(R_1, q)) 0129 * \f] 0130 * where \f$ x \equiv q R / \hbar \f$ uses the effective nuclear radius \f$ 0131 * R_0 = 1.2 A^{1/3} \,\mathrm{fm} \f$ and nuclear surface skin \f$ R_1 = 2.0 0132 * \,\mathrm{fm} \f$, 0133 * and 0134 * \f[ 0135 * F'(x) = \frac{3}{x^3} ( \sin x - x \cos x) 0136 * \f] 0137 * is the form factor for a uniformly charged sphere. 0138 * 0139 * \warning This form factor suffers from catastrophic numerical cancellation 0140 * for small radii and momenta so should only be used for large nuclei or large 0141 * momentum transfers. 0142 * 0143 * [LR16] C. Leroy and P.G. Rancoita. Principles of Radiation Interaction in 0144 * Matter and Detection. World Scientific (Singapore), 4th edition, 0145 * 2016. 0146 * 0147 * [H56] R.H. Helm, Inelastic and Elastic Scattering of 187-Mev Electrons from 0148 * Selected Even-Even Nuclei, Phys. Rev. 104 (1956) 1466–1475. 0149 * https://doi.org/10.1103/PhysRev.104.1466. 0150 * 0151 * [FMS93] J.M. Fernández-Varea, R. Mayol, F. Salvat, Cross sections for 0152 * elastic scattering of fast electrons and positrons by atoms, Nuclear 0153 * Instruments and Methods in Physics Research Section B: Beam 0154 * Interactions with Materials and Atoms 82 (1993) 39–45. 0155 * https://doi.org/10.1016/0168-583X(93)95079-K. 0156 */ 0157 class UUNuclearFormFactor : public NuclearFormFactorTraits 0158 { 0159 public: 0160 //! Form factor type corresponding to this distribution 0161 static CELER_CONSTEXPR_FUNCTION FFType ff_type() { return FFType::flat; } 0162 0163 // Construct with atomic mass number 0164 explicit inline CELER_FUNCTION UUNuclearFormFactor(AtomicMassNumber a_mass); 0165 0166 // Calculate from square of target momentum 0167 inline CELER_FUNCTION real_type operator()(MomentumSq target_momsq) const; 0168 0169 // Calculate from target momentum 0170 inline CELER_FUNCTION real_type operator()(Momentum target_mom) const; 0171 0172 private: 0173 real_type nucl_radius_fm_; 0174 0175 // Effective nuclear skin radius: 2 fm 0176 static CELER_CONSTEXPR_FUNCTION real_type skin_radius_fm() { return 2; } 0177 }; 0178 0179 //---------------------------------------------------------------------------// 0180 // INLINE DEFINITIONS 0181 //---------------------------------------------------------------------------// 0182 /*! 0183 * Construct from atomic mass number. 0184 */ 0185 CELER_FUNCTION 0186 ExpNuclearFormFactor::ExpNuclearFormFactor(AtomicMassNumber a_mass) 0187 { 0188 CELER_EXPECT(a_mass); 0189 real_type nucl_radius_fm = [a_mass] { 0190 if (CELER_UNLIKELY(a_mass == AtomicMassNumber{1})) 0191 { 0192 // Special case for proton radius 0193 return real_type{0.85}; 0194 } 0195 return real_type{1.27} 0196 * fastpow(real_type(a_mass.get()), real_type{0.27}); 0197 }(); 0198 prefactor_ = ipow<2>(nucl_radius_fm * value_as<InvMomentum>(fm_par_hbar())) 0199 * (real_type{1} / 12); 0200 CELER_ENSURE(prefactor_ > 0); 0201 } 0202 0203 //---------------------------------------------------------------------------// 0204 /*! 0205 * Construct with precalculated form factor. 0206 */ 0207 CELER_FUNCTION 0208 ExpNuclearFormFactor::ExpNuclearFormFactor(InvMomentumSq prefactor) 0209 : prefactor_{prefactor.value()} 0210 { 0211 CELER_EXPECT(prefactor_ > 0); 0212 } 0213 0214 //---------------------------------------------------------------------------// 0215 /*! 0216 * Calculate the exponential folded form factor from the square momentum. 0217 */ 0218 CELER_FUNCTION real_type 0219 ExpNuclearFormFactor::operator()(MomentumSq target_momsq) const 0220 { 0221 CELER_EXPECT(target_momsq >= zero_quantity()); 0222 return 1 / ipow<2>(1 + prefactor_ * target_momsq.value()); 0223 } 0224 0225 //---------------------------------------------------------------------------// 0226 /*! 0227 * Calculate the exponential folded form factor. 0228 */ 0229 CELER_FUNCTION real_type ExpNuclearFormFactor::operator()(Momentum target_mom) const 0230 { 0231 return (*this)(MomentumSq{ipow<2>(target_mom.value())}); 0232 } 0233 0234 //---------------------------------------------------------------------------// 0235 /*! 0236 * Calculate the gaussian folded form factor. 0237 */ 0238 CELER_FUNCTION real_type 0239 GaussianNuclearFormFactor::operator()(MomentumSq target_momsq) const 0240 { 0241 CELER_EXPECT(target_momsq >= zero_quantity()); 0242 return std::exp(-2 * value_as<InvMomentumSq>(this->prefactor()) 0243 * target_momsq.value()); 0244 } 0245 0246 //---------------------------------------------------------------------------// 0247 /*! 0248 * Calculate the gaussian folded form factor by squaring the momentum. 0249 */ 0250 CELER_FUNCTION real_type 0251 GaussianNuclearFormFactor::operator()(Momentum target_mom) const 0252 { 0253 return (*this)(MomentumSq{ipow<2>(target_mom.value())}); 0254 } 0255 0256 //---------------------------------------------------------------------------// 0257 /*! 0258 * Construct from atomic mass number. 0259 */ 0260 CELER_FUNCTION UUNuclearFormFactor::UUNuclearFormFactor(AtomicMassNumber a_mass) 0261 { 0262 CELER_EXPECT(a_mass); 0263 nucl_radius_fm_ = real_type{1.2} 0264 * fastpow(real_type(a_mass.get()), real_type{1} / 3); 0265 } 0266 0267 //---------------------------------------------------------------------------// 0268 /*! 0269 * Calculate the uniform-uniform folded form factor by calculating momentum. 0270 */ 0271 CELER_FUNCTION real_type 0272 UUNuclearFormFactor::operator()(MomentumSq target_momsq) const 0273 { 0274 CELER_EXPECT(target_momsq >= zero_quantity()); 0275 return (*this)(Momentum{std::sqrt(target_momsq.value())}); 0276 } 0277 0278 //---------------------------------------------------------------------------// 0279 /*! 0280 * Calculate the uniform-uniform folded form factor. 0281 */ 0282 CELER_FUNCTION real_type UUNuclearFormFactor::operator()(Momentum target_mom) const 0283 { 0284 auto sphere_ff = [&target_mom](real_type r) { 0285 // x = q R / hbar 0286 // r units: fm 0287 real_type x = value_as<Momentum>(target_mom) 0288 * (r * value_as<InvMomentum>(fm_par_hbar())); 0289 return (3 / ipow<3>(x)) * std::fma(-x, std::cos(x), std::sin(x)); 0290 }; 0291 0292 // Due to catastrophic error for small x, clamp the result to 1 0293 return min(sphere_ff(nucl_radius_fm_) 0294 * sphere_ff(UUNuclearFormFactor::skin_radius_fm()), 0295 real_type{1}); 0296 } 0297 0298 //---------------------------------------------------------------------------// 0299 } // 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 |
![]() ![]() |