File indexing completed on 2025-02-22 10:31:15
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "corecel/Macros.hh"
0011 #include "corecel/Types.hh"
0012 #include "corecel/math/Algorithms.hh"
0013 #include "celeritas/Quantities.hh"
0014 #include "celeritas/random/distribution/RejectionSampler.hh"
0015 #include "celeritas/random/distribution/UniformRealDistribution.hh"
0016
0017 namespace celeritas
0018 {
0019
0020
0021
0022
0023
0024
0025 class BhabhaEnergyDistribution
0026 {
0027 public:
0028
0029
0030 using Mass = units::MevMass;
0031 using Energy = units::MevEnergy;
0032
0033
0034 public:
0035
0036 inline CELER_FUNCTION BhabhaEnergyDistribution(Mass electron_mass,
0037 Energy min_valid_energy,
0038 Energy inc_energy);
0039
0040
0041 template<class Engine>
0042 inline CELER_FUNCTION real_type operator()(Engine& rng);
0043
0044 private:
0045
0046
0047
0048 real_type min_energy_fraction_;
0049
0050 real_type gamma_;
0051
0052
0053
0054
0055 inline CELER_FUNCTION real_type calc_g_fraction(real_type epsilon_min,
0056 real_type epsilon_max);
0057
0058
0059 static CELER_CONSTEXPR_FUNCTION real_type max_energy_fraction()
0060 {
0061 return 1;
0062 }
0063
0064 };
0065
0066
0067
0068
0069
0070
0071
0072 CELER_FUNCTION
0073 BhabhaEnergyDistribution::BhabhaEnergyDistribution(Mass electron_mass,
0074 Energy min_valid_energy,
0075 Energy inc_energy)
0076 : min_energy_fraction_(value_as<Energy>(min_valid_energy)
0077 / value_as<Energy>(inc_energy))
0078 , gamma_(1 + value_as<Energy>(inc_energy) / value_as<Mass>(electron_mass))
0079 {
0080 CELER_EXPECT(electron_mass > zero_quantity()
0081 && inc_energy > zero_quantity());
0082 }
0083
0084
0085
0086
0087
0088 template<class Engine>
0089 CELER_FUNCTION real_type BhabhaEnergyDistribution::operator()(Engine& rng)
0090 {
0091 real_type const g_denominator = this->calc_g_fraction(
0092 min_energy_fraction_, this->max_energy_fraction());
0093
0094 UniformRealDistribution<> sample_inverse_epsilon(
0095 1 / this->max_energy_fraction(), 1 / min_energy_fraction_);
0096
0097
0098 real_type epsilon;
0099 do
0100 {
0101 epsilon = 1 / sample_inverse_epsilon(rng);
0102 } while (RejectionSampler<>(this->calc_g_fraction(epsilon, epsilon),
0103 g_denominator)(rng));
0104
0105 return epsilon;
0106 }
0107
0108
0109
0110
0111
0112 CELER_FUNCTION real_type BhabhaEnergyDistribution::calc_g_fraction(
0113 real_type epsilon_min, real_type epsilon_max)
0114 {
0115 real_type const y = 1 / (1 + gamma_);
0116 real_type const y_sq = ipow<2>(y);
0117 real_type const one_minus_2y = 1 - 2 * y;
0118
0119 real_type const b1 = 2 - y_sq;
0120 real_type const b2 = one_minus_2y * (3 + y_sq);
0121 real_type const b4 = ipow<3>(one_minus_2y);
0122 real_type const b3 = ipow<2>(one_minus_2y) + b4;
0123 real_type const beta_sq = 1 - (1 / ipow<2>(gamma_));
0124
0125 return 1
0126 + (ipow<4>(epsilon_max) * b4 - ipow<3>(epsilon_min) * b3
0127 + ipow<2>(epsilon_max) * b2 - epsilon_min * b1)
0128 * beta_sq;
0129 }
0130
0131
0132 }