File indexing completed on 2025-02-22 10:31:18
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 "corecel/math/ArrayUtils.hh"
0014 #include "celeritas/Quantities.hh"
0015 #include "celeritas/Types.hh"
0016 #include "celeritas/em/data/UrbanMscData.hh"
0017 #include "celeritas/grid/EnergyLossCalculator.hh"
0018 #include "celeritas/grid/InverseRangeCalculator.hh"
0019 #include "celeritas/grid/RangeCalculator.hh"
0020 #include "celeritas/grid/ValueGridType.hh"
0021 #include "celeritas/grid/XsCalculator.hh"
0022 #include "celeritas/phys/ParticleTrackView.hh"
0023 #include "celeritas/phys/PhysicsTrackView.hh"
0024
0025 namespace celeritas
0026 {
0027 namespace detail
0028 {
0029
0030
0031
0032
0033
0034
0035
0036
0037 class UrbanMscHelper
0038 {
0039 public:
0040
0041
0042 using Energy = units::MevEnergy;
0043 using MaterialData = UrbanMscMaterialData;
0044 using UrbanMscRef = NativeCRef<UrbanMscData>;
0045
0046
0047 public:
0048
0049 inline CELER_FUNCTION UrbanMscHelper(UrbanMscRef const& shared,
0050 ParticleTrackView const& particle,
0051 PhysicsTrackView const& physics);
0052
0053
0054
0055
0056
0057 CELER_FUNCTION real_type msc_mfp() const { return lambda_; }
0058
0059
0060 inline CELER_FUNCTION real_type calc_msc_mfp(Energy energy) const;
0061
0062
0063
0064
0065 inline CELER_FUNCTION Energy calc_inverse_range(real_type step) const;
0066
0067
0068 CELER_FUNCTION real_type scaled_zeff() const
0069 {
0070 return this->pmdata().scaled_zeff;
0071 }
0072
0073
0074 inline CELER_FUNCTION real_type max_step() const;
0075
0076
0077 inline CELER_FUNCTION Energy calc_end_energy(real_type step) const;
0078
0079 private:
0080
0081
0082
0083 UrbanMscRef const& shared_;
0084 ParticleTrackView const& particle_;
0085 PhysicsTrackView const& physics_;
0086
0087
0088 real_type lambda_;
0089
0090
0091 CELER_FUNCTION UrbanMscParMatData const& pmdata() const
0092 {
0093 return shared_.par_mat_data[shared_.at<UrbanMscParMatData>(
0094 physics_.material_id(), particle_.particle_id())];
0095 }
0096
0097
0098 CELER_FUNCTION XsGridData const& xs() const
0099 {
0100 return shared_.xs[shared_.at<XsGridData>(physics_.material_id(),
0101 particle_.particle_id())];
0102 }
0103 };
0104
0105
0106
0107
0108
0109
0110
0111 CELER_FUNCTION
0112 UrbanMscHelper::UrbanMscHelper(UrbanMscRef const& shared,
0113 ParticleTrackView const& particle,
0114 PhysicsTrackView const& physics)
0115 : shared_(shared)
0116 , particle_(particle)
0117 , physics_(physics)
0118 , lambda_(this->calc_msc_mfp(particle_.energy()))
0119 {
0120 CELER_EXPECT(particle.particle_id() == shared_.ids.electron
0121 || particle.particle_id() == shared_.ids.positron);
0122 }
0123
0124
0125
0126
0127
0128 CELER_FUNCTION real_type UrbanMscHelper::calc_msc_mfp(Energy energy) const
0129 {
0130 CELER_EXPECT(energy > zero_quantity());
0131 XsCalculator calc_scaled_xs(this->xs(), shared_.reals);
0132
0133 real_type xsec = calc_scaled_xs(energy) / ipow<2>(energy.value());
0134 CELER_ENSURE(xsec >= 0 && 1 / xsec > 0);
0135 return 1 / xsec;
0136 }
0137
0138
0139
0140
0141
0142
0143
0144
0145 CELER_FUNCTION auto
0146 UrbanMscHelper::calc_inverse_range(real_type step) const -> Energy
0147 {
0148 auto range_gid
0149 = physics_.value_grid(ValueGridType::range, physics_.eloss_ppid());
0150 auto range_to_energy
0151 = physics_.make_calculator<InverseRangeCalculator>(range_gid);
0152 return range_to_energy(step);
0153 }
0154
0155
0156
0157
0158
0159 CELER_FUNCTION real_type UrbanMscHelper::max_step() const
0160 {
0161 return physics_.dedx_range() * this->pmdata().d_over_r;
0162 }
0163
0164
0165
0166
0167
0168 CELER_FUNCTION auto
0169 UrbanMscHelper::calc_end_energy(real_type step) const -> Energy
0170 {
0171 CELER_EXPECT(step <= physics_.dedx_range());
0172 real_type range = physics_.dedx_range();
0173 if (step <= range * shared_.params.dtrl())
0174 {
0175 auto eloss_gid = physics_.value_grid(ValueGridType::energy_loss,
0176 physics_.eloss_ppid());
0177
0178 real_type dedx = physics_.make_calculator<EnergyLossCalculator>(
0179 eloss_gid)(particle_.energy());
0180
0181 return particle_.energy() - Energy{step * dedx};
0182 }
0183 else
0184 {
0185
0186 return this->calc_inverse_range(range - step);
0187 }
0188 }
0189
0190
0191 }
0192 }