File indexing completed on 2026-10-29 09:07:49
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <type_traits>
0010
0011 #include "corecel/Assert.hh"
0012 #include "corecel/math/ArrayOperators.hh"
0013 #include "corecel/math/ArraySoftUnit.hh"
0014 #include "corecel/math/ArrayUtils.hh"
0015 #include "corecel/random/distribution/BernoulliDistribution.hh"
0016 #include "corecel/random/distribution/IsotropicDistribution.hh"
0017 #include "corecel/random/distribution/RejectionSampler.hh"
0018 #include "corecel/random/engine/RanluxppRngEngine.hh"
0019 #include "celeritas/optical/Interaction.hh"
0020 #include "celeritas/optical/ParticleTrackView.hh"
0021
0022 namespace celeritas
0023 {
0024 namespace optical
0025 {
0026
0027
0028
0029
0030
0031
0032
0033
0034 class RayleighInteractor
0035 {
0036 public:
0037
0038 inline CELER_FUNCTION RayleighInteractor(ParticleTrackView const& particle,
0039 Real3 const& direction);
0040
0041
0042 template<class Engine>
0043 inline CELER_FUNCTION Interaction operator()(Engine& rng);
0044
0045 private:
0046 Real3 const& inc_dir_;
0047 Real3 const& inc_pol_;
0048 IsotropicDistribution<real_type> sample_direction_{};
0049 RejectionSampler<real_type> reject_angle_{1};
0050 };
0051
0052
0053
0054
0055
0056
0057
0058 CELER_FUNCTION RayleighInteractor::RayleighInteractor(
0059 ParticleTrackView const& particle, Real3 const& direction)
0060 : inc_dir_(direction), inc_pol_(particle.polarization())
0061 {
0062 CELER_EXPECT(is_soft_unit_vector(inc_dir_));
0063 CELER_EXPECT(is_soft_unit_vector(inc_pol_));
0064 CELER_EXPECT(is_soft_orthogonal(inc_dir_, inc_pol_));
0065 }
0066
0067
0068
0069
0070
0071 template<class Engine>
0072 CELER_FUNCTION Interaction RayleighInteractor::operator()(Engine& rng)
0073 {
0074 if constexpr (std::is_same_v<Engine, RanluxppRngEngine>)
0075 {
0076
0077
0078 rng.advance();
0079 }
0080
0081 Real3 new_dir, new_pol;
0082 do
0083 {
0084 do
0085 {
0086 new_dir = sample_direction_(rng);
0087
0088
0089 new_pol = make_unit_vector(make_orthogonal(inc_pol_, new_dir));
0090
0091
0092
0093 } while (CELER_UNLIKELY(!is_soft_orthogonal(new_pol, new_dir)));
0094
0095 if (!BernoulliDistribution{0.5}(rng))
0096 {
0097
0098
0099 new_pol = -new_pol;
0100 }
0101
0102
0103 } while (reject_angle_(ipow<2>(dot_product(new_pol, inc_pol_)), rng));
0104
0105 CELER_ENSURE(is_soft_unit_vector(new_dir));
0106 CELER_ENSURE(is_soft_unit_vector(new_pol));
0107 Interaction result;
0108 result.direction = new_dir;
0109 result.polarization = new_pol;
0110 return result;
0111 }
0112
0113
0114 }
0115 }