|
|
|||
File indexing completed on 2026-01-07 10:01:42
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/optical/gen/CherenkovDndxCalculator.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/grid/VectorUtils.hh" 0015 #include "celeritas/Quantities.hh" 0016 #include "celeritas/grid/NonuniformGridCalculator.hh" 0017 0018 #include "CherenkovData.hh" 0019 #include "../MaterialView.hh" 0020 0021 namespace celeritas 0022 { 0023 //---------------------------------------------------------------------------// 0024 /*! 0025 * Calculate the mean number of Cherenkov photons produced per unit length. 0026 * 0027 * The average number of photons produced is given by 0028 * \f[ 0029 \dif N = \frac{\alpha z^2}{\hbar c}\sin^2\theta \dif\epsilon \dif x = 0030 \frac{\alpha z^2}{\hbar c}\left(1 - \frac{1}{n^2\beta^2}\right) \dif\epsilon 0031 \dif x, 0032 * \f] 0033 * where \f$ n \f$ is the refractive index of the material, \f$ \epsilon \f$ 0034 * is the photon energy, and \f$ \theta \f$ is the angle of the emitted photons 0035 * with respect to the incident particle direction, given by \f$ \cos\theta = 1 0036 * / (\beta n) \f$. Note that in a dispersive medium, the index of refraction 0037 * is an inreasing function of photon energy. The mean number of photons per 0038 * unit length is given by 0039 * \f[ 0040 \difd{N}{x} = \frac{\alpha z^2}{\hbar c} 0041 \int_{\epsilon_\text{min}}^{\epsilon_\text{max}} \left(1 - 0042 \frac{1}{n^2\beta^2} \right) \dif\epsilon 0043 = \frac{\alpha z^2}{\hbar c} 0044 \left[\epsilon_\text{max} - \epsilon_\text{min} - \frac{1}{\beta^2} 0045 \int_{\epsilon_\text{min}}^{\epsilon_\text{max}} 0046 \frac{1}{n^2(\epsilon)}\dif\epsilon \right]. 0047 * \f] 0048 */ 0049 class CherenkovDndxCalculator 0050 { 0051 public: 0052 // Construct from optical materials and Cherenkov angle integrals 0053 inline CELER_FUNCTION 0054 CherenkovDndxCalculator(optical::MaterialView const& material, 0055 NativeCRef<CherenkovData> const& shared, 0056 units::ElementaryCharge charge); 0057 0058 // Calculate the mean number of Cherenkov photons produced per unit length 0059 inline CELER_FUNCTION real_type operator()(units::LightSpeed beta); 0060 0061 private: 0062 // Calculate refractive index [MeV -> unitless] 0063 NonuniformGridCalculator calc_refractive_index_; 0064 0065 // Calculate the Cherenkov angle integral [MeV -> unitless] 0066 NonuniformGridCalculator calc_integral_; 0067 0068 // Square of particle charge 0069 real_type zsq_; 0070 }; 0071 0072 //---------------------------------------------------------------------------// 0073 // INLINE DEFINITIONS 0074 //---------------------------------------------------------------------------// 0075 /*! 0076 * Construct from optical materials and Cherenkov angle integrals. 0077 */ 0078 CELER_FUNCTION 0079 CherenkovDndxCalculator::CherenkovDndxCalculator( 0080 optical::MaterialView const& material, 0081 NativeCRef<CherenkovData> const& shared, 0082 units::ElementaryCharge charge) 0083 : calc_refractive_index_(material.make_refractive_index_calculator()) 0084 , calc_integral_{shared.angle_integral[material.material_id()], 0085 shared.reals} 0086 , zsq_(ipow<2>(charge.value())) 0087 { 0088 CELER_EXPECT(charge != zero_quantity()); 0089 } 0090 0091 //---------------------------------------------------------------------------// 0092 /*! 0093 * Calculate the mean number of Cherenkov photons produced per unit length. 0094 * 0095 * \todo define a "generic grid extents" class for finding the lower/upper x/y 0096 * coordinates on grid data. In the future we could cache these if the memory 0097 * lookups result in too much indirection. 0098 */ 0099 CELER_FUNCTION real_type 0100 CherenkovDndxCalculator::operator()(units::LightSpeed beta) 0101 { 0102 CELER_EXPECT(beta.value() > 0 && beta.value() <= 1); 0103 0104 real_type inv_beta = 1 / beta.value(); 0105 real_type energy_max = calc_refractive_index_.grid().back(); 0106 if (inv_beta > calc_refractive_index_(energy_max)) 0107 { 0108 // Incident particle energy is below the threshold for Cherenkov 0109 // emission (i.e., beta < 1 / n_max) 0110 return 0; 0111 } 0112 0113 // Calculate \f$ \int_{\epsilon_\text{min}}^{\epsilon_\text{max}} 0114 // \dif\epsilon \left(1 - \frac{1}{n^2\beta^2}\right) \f$ 0115 real_type energy; 0116 if (inv_beta < calc_refractive_index_[0]) 0117 { 0118 energy = energy_max - calc_refractive_index_.grid().front() 0119 - calc_integral_(energy_max) * ipow<2>(inv_beta); 0120 } 0121 else 0122 { 0123 // Find the energy where the refractive index is equal to 1 / beta. 0124 // Both energy and refractive index are monotonically increasing, so 0125 // the grid and values can be swapped and the energy can be calculated 0126 // from a given index of refraction 0127 real_type energy_min = calc_refractive_index_.make_inverse()(inv_beta); 0128 energy = energy_max - energy_min 0129 - (calc_integral_(energy_max) - calc_integral_(energy_min)) 0130 * ipow<2>(inv_beta); 0131 } 0132 0133 // Calculate number of photons. This may be negative if the incident 0134 // particle energy is very close to (just above) the Cherenkov production 0135 // threshold 0136 return clamp_to_nonneg(zsq_ 0137 * (constants::alpha_fine_structure 0138 / (constants::hbar_planck * constants::c_light)) 0139 * native_value_from(units::MevEnergy(energy))); 0140 } 0141 0142 //---------------------------------------------------------------------------// 0143 } // 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 |
|