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