File indexing completed on 2026-01-06 10:05:26
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/random/distribution/ExponentialDistribution.hh"
0013 #include "corecel/random/distribution/UniformRealDistribution.hh"
0014 #include "geocel/random/IsotropicDistribution.hh"
0015 #include "celeritas/Types.hh"
0016 #include "celeritas/grid/NonuniformGridCalculator.hh"
0017 #include "celeritas/optical/Interaction.hh"
0018 #include "celeritas/optical/ParticleTrackView.hh"
0019 #include "celeritas/optical/TrackInitializer.hh"
0020 #include "celeritas/optical/WavelengthShiftData.hh"
0021 #include "celeritas/phys/InteractionUtils.hh"
0022
0023 namespace celeritas
0024 {
0025 namespace optical
0026 {
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 class WavelengthShiftGenerator
0045 {
0046 public:
0047
0048 inline CELER_FUNCTION
0049 WavelengthShiftGenerator(NativeCRef<WavelengthShiftData> const& shared,
0050 WlsDistributionData const& distribution);
0051
0052
0053 template<class Engine>
0054 inline CELER_FUNCTION TrackInitializer operator()(Engine& rng);
0055
0056 private:
0057
0058
0059 using Energy = units::MevEnergy;
0060
0061
0062
0063 WlsDistributionData const& distribution_;
0064 real_type time_constant_;
0065 WlsTimeProfile time_profile_;
0066 NonuniformGridCalculator calc_cdf_;
0067 };
0068
0069
0070
0071
0072
0073
0074
0075 CELER_FUNCTION
0076 WavelengthShiftGenerator::WavelengthShiftGenerator(
0077 NativeCRef<WavelengthShiftData> const& shared,
0078 WlsDistributionData const& distribution)
0079 : distribution_(distribution)
0080 , time_constant_(shared.wls_record[distribution_.material].time_constant)
0081 , time_profile_(shared.time_profile)
0082 , calc_cdf_(shared.energy_cdf[distribution_.material], shared.reals)
0083 {
0084 CELER_EXPECT(distribution_);
0085 CELER_EXPECT(distribution_.energy.value() > calc_cdf_.grid().front());
0086 }
0087
0088
0089
0090
0091
0092
0093
0094 template<class Engine>
0095 CELER_FUNCTION TrackInitializer WavelengthShiftGenerator::operator()(Engine& rng)
0096 {
0097
0098 TrackInitializer result;
0099
0100
0101
0102
0103 NonuniformGridCalculator calc_energy = calc_cdf_.make_inverse();
0104 real_type energy = calc_energy(generate_canonical(rng));
0105 if (CELER_UNLIKELY(energy > value_as<Energy>(distribution_.energy)))
0106 {
0107
0108 real_type cdf_max = calc_cdf_(value_as<Energy>(distribution_.energy));
0109 UniformRealDistribution<real_type> sample_cdf(0, cdf_max);
0110 energy = calc_energy(sample_cdf(rng));
0111 }
0112 CELER_ENSURE(energy < value_as<Energy>(distribution_.energy));
0113 result.energy = Energy{energy};
0114
0115
0116 result.position = distribution_.position;
0117
0118
0119 result.direction = IsotropicDistribution()(rng);
0120 result.polarization = ExitingDirectionSampler{0, result.direction}(rng);
0121
0122
0123 result.time
0124 = distribution_.time
0125 + (time_profile_ == WlsTimeProfile::delta
0126 ? time_constant_
0127 : ExponentialDistribution(real_type{1} / time_constant_)(rng));
0128
0129 CELER_ENSURE(is_soft_unit_vector(result.polarization));
0130 CELER_ENSURE(soft_zero(dot_product(result.direction, result.polarization)));
0131 return result;
0132 }
0133
0134
0135 }
0136 }