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/Types.hh"
0011 #include "corecel/data/StackAllocator.hh"
0012 #include "corecel/math/ArrayUtils.hh"
0013 #include "corecel/random/distribution/ReciprocalDistribution.hh"
0014 #include "corecel/random/distribution/RejectionSampler.hh"
0015 #include "celeritas/Constants.hh"
0016 #include "celeritas/Quantities.hh"
0017 #include "celeritas/em/data/MuBremsstrahlungData.hh"
0018 #include "celeritas/em/distribution/MuAngularDistribution.hh"
0019 #include "celeritas/em/xs/MuBremsDiffXsCalculator.hh"
0020 #include "celeritas/mat/ElementView.hh"
0021 #include "celeritas/mat/MaterialView.hh"
0022 #include "celeritas/phys/CutoffView.hh"
0023 #include "celeritas/phys/Interaction.hh"
0024 #include "celeritas/phys/InteractionUtils.hh"
0025 #include "celeritas/phys/ParticleTrackView.hh"
0026 #include "celeritas/phys/Secondary.hh"
0027
0028 #include "detail/BremFinalStateHelper.hh"
0029
0030 namespace celeritas
0031 {
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 class MuBremsstrahlungInteractor
0045 {
0046
0047
0048 using Energy = units::MevEnergy;
0049 using Mass = units::MevMass;
0050 using Momentum = units::MevMomentum;
0051
0052
0053 public:
0054
0055 inline CELER_FUNCTION
0056 MuBremsstrahlungInteractor(MuBremsstrahlungData const& shared,
0057 ParticleTrackView const& particle,
0058 Real3 const& inc_direction,
0059 CutoffView const& cutoffs,
0060 StackAllocator<Secondary>& allocate,
0061 MaterialView const& material,
0062 ElementComponentId elcomp_id);
0063
0064
0065 template<class Engine>
0066 inline CELER_FUNCTION Interaction operator()(Engine& rng);
0067
0068 private:
0069
0070
0071
0072 MuBremsstrahlungData const& shared_;
0073
0074 Real3 const& inc_direction_;
0075
0076 StackAllocator<Secondary>& allocate_;
0077
0078 ElementView const element_;
0079
0080 ParticleTrackView const& particle_;
0081
0082 MuBremsDiffXsCalculator calc_dcs_;
0083
0084 ReciprocalDistribution<> sample_energy_;
0085
0086 real_type envelope_;
0087 };
0088
0089
0090
0091
0092
0093
0094
0095 CELER_FUNCTION MuBremsstrahlungInteractor::MuBremsstrahlungInteractor(
0096 MuBremsstrahlungData const& shared,
0097 ParticleTrackView const& particle,
0098 Real3 const& inc_direction,
0099 CutoffView const& cutoffs,
0100 StackAllocator<Secondary>& allocate,
0101 MaterialView const& material,
0102 ElementComponentId elcomp_id)
0103 : shared_(shared)
0104 , inc_direction_(inc_direction)
0105 , allocate_(allocate)
0106 , element_(material.element_record(elcomp_id))
0107 , particle_(particle)
0108 , calc_dcs_(
0109 element_, particle.energy(), particle.mass(), shared.electron_mass)
0110 , sample_energy_{value_as<Energy>(cutoffs.energy(shared.gamma)),
0111 value_as<Energy>(particle_.energy())}
0112 {
0113 CELER_EXPECT(particle.particle_id() == shared_.mu_minus
0114 || particle.particle_id() == shared_.mu_plus);
0115 CELER_EXPECT(particle_.energy() > cutoffs.energy(shared.gamma));
0116
0117
0118
0119 real_type gamma_cutoff = value_as<Energy>(cutoffs.energy(shared.gamma));
0120 envelope_ = gamma_cutoff * calc_dcs_(Energy{gamma_cutoff});
0121 }
0122
0123
0124
0125
0126
0127 template<class Engine>
0128 CELER_FUNCTION Interaction MuBremsstrahlungInteractor::operator()(Engine& rng)
0129 {
0130
0131 Secondary* secondary = allocate_(1);
0132 if (secondary == nullptr)
0133 {
0134
0135 return Interaction::from_failure();
0136 }
0137
0138
0139 real_type gamma_energy;
0140 do
0141 {
0142 gamma_energy = sample_energy_(rng);
0143 } while (RejectionSampler{gamma_energy * calc_dcs_(Energy{gamma_energy}),
0144 envelope_}(rng));
0145
0146 MuAngularDistribution sample_costheta(
0147 particle_.energy(), particle_.mass(), Energy{gamma_energy});
0148
0149
0150 return detail::BremFinalStateHelper(particle_.energy(),
0151 inc_direction_,
0152 particle_.momentum(),
0153 shared_.gamma,
0154 Energy{gamma_energy},
0155 sample_costheta(rng),
0156 secondary)(rng);
0157 }
0158
0159
0160 }