File indexing completed on 2025-09-17 08:53:35
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Macros.hh"
0010 #include "corecel/data/StackAllocator.hh"
0011 #include "corecel/math/ArrayUtils.hh"
0012 #include "celeritas/Constants.hh"
0013 #include "celeritas/Quantities.hh"
0014 #include "celeritas/Types.hh"
0015 #include "celeritas/em/data/SeltzerBergerData.hh"
0016 #include "celeritas/em/distribution/TsaiUrbanDistribution.hh"
0017 #include "celeritas/mat/ElementView.hh"
0018 #include "celeritas/mat/MaterialView.hh"
0019 #include "celeritas/phys/CutoffView.hh"
0020 #include "celeritas/phys/Interaction.hh"
0021 #include "celeritas/phys/ParticleTrackView.hh"
0022 #include "celeritas/phys/Secondary.hh"
0023
0024 #include "detail/BremFinalStateHelper.hh"
0025 #include "detail/PhysicsConstants.hh"
0026 #include "detail/SBEnergySampler.hh"
0027
0028 namespace celeritas
0029 {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 class SeltzerBergerInteractor
0048 {
0049 public:
0050
0051
0052 using Energy = units::MevEnergy;
0053 using Momentum = units::MevMomentum;
0054
0055
0056 public:
0057
0058 inline CELER_FUNCTION
0059 SeltzerBergerInteractor(SeltzerBergerRef const& shared,
0060 ParticleTrackView const& particle,
0061 Real3 const& inc_direction,
0062 CutoffView const& cutoffs,
0063 StackAllocator<Secondary>& allocate,
0064 MaterialView const& material,
0065 ElementComponentId const& elcomp_id);
0066
0067
0068 template<class Engine>
0069 inline CELER_FUNCTION Interaction operator()(Engine& rng);
0070
0071 private:
0072
0073
0074 SeltzerBergerRef const& shared_;
0075
0076 Energy const inc_energy_;
0077
0078 Momentum const inc_momentum_;
0079
0080 Real3 const& inc_direction_;
0081
0082 Energy const gamma_cutoff_;
0083
0084 StackAllocator<Secondary>& allocate_;
0085
0086 ElementComponentId const elcomp_id_;
0087
0088
0089
0090 detail::SBEnergySampler sample_photon_energy_;
0091
0092 TsaiUrbanDistribution sample_costheta_;
0093 };
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 CELER_FUNCTION SeltzerBergerInteractor::SeltzerBergerInteractor(
0105 SeltzerBergerRef const& shared,
0106 ParticleTrackView const& particle,
0107 Real3 const& inc_direction,
0108 CutoffView const& cutoffs,
0109 StackAllocator<Secondary>& allocate,
0110 MaterialView const& material,
0111 ElementComponentId const& elcomp_id)
0112 : shared_(shared)
0113 , inc_energy_(particle.energy())
0114 , inc_momentum_(particle.momentum())
0115 , inc_direction_(inc_direction)
0116 , gamma_cutoff_(cutoffs.energy(shared.ids.gamma))
0117 , allocate_(allocate)
0118 , elcomp_id_(elcomp_id)
0119 , sample_photon_energy_(shared.differential_xs,
0120 particle,
0121 gamma_cutoff_,
0122 material,
0123 elcomp_id,
0124 particle.particle_id() == shared_.ids.electron)
0125 , sample_costheta_(inc_energy_, particle.mass())
0126 {
0127 CELER_EXPECT(particle.particle_id() == shared_.ids.electron
0128 || particle.particle_id() == shared_.ids.positron);
0129 CELER_EXPECT(gamma_cutoff_ > zero_quantity());
0130 CELER_EXPECT(inc_energy_ < shared_.high_energy_limit);
0131 }
0132
0133
0134
0135
0136
0137
0138
0139 template<class Engine>
0140 CELER_FUNCTION Interaction SeltzerBergerInteractor::operator()(Engine& rng)
0141 {
0142 if (inc_energy_ <= gamma_cutoff_)
0143 {
0144
0145
0146
0147
0148 return Interaction::from_unchanged();
0149 }
0150
0151
0152 Secondary* secondaries = allocate_(1);
0153 if (secondaries == nullptr)
0154 {
0155
0156 return Interaction::from_failure();
0157 }
0158
0159
0160 return detail::BremFinalStateHelper{inc_energy_,
0161 inc_direction_,
0162 inc_momentum_,
0163 shared_.ids.gamma,
0164 sample_photon_energy_(rng),
0165 sample_costheta_(rng),
0166 secondaries}(rng);
0167 }
0168
0169
0170 }