File indexing completed on 2026-11-07 10:11:39
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/random/distribution/BernoulliDistribution.hh"
0010 #include "celeritas/optical/CoreTrackView.hh"
0011
0012 #include "FresnelCalculator.hh"
0013 #include "ReflectionFormSampler.hh"
0014
0015 namespace celeritas
0016 {
0017 namespace optical
0018 {
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 class DielectricInteractor
0036 {
0037 public:
0038 struct Executor
0039 {
0040 NativeCRef<DielectricData> dielectric_data;
0041 NativeCRef<UnifiedReflectionData> unified_data;
0042
0043
0044 inline CELER_FUNCTION SurfaceInteraction operator()(
0045 CoreTrackView const&) const;
0046 };
0047
0048 public:
0049
0050 inline CELER_FUNCTION DielectricInteractor(
0051 ParticleTrackView const& particle,
0052 Real3 const& inc_direction,
0053 SurfacePhysicsTrackView const& surface_physics,
0054 MaterialView const& pre_material,
0055 MaterialView const& post_material,
0056 ReflectionModeSampler reflection_calc,
0057 DielectricInterface dielectric_interface);
0058
0059
0060 template<class Engine>
0061 inline CELER_FUNCTION SurfaceInteraction operator()(Engine&) const;
0062
0063 private:
0064 FresnelCalculator fresnel_;
0065 Real3 const& inc_direction_;
0066 ParticleTrackView const& inc_photon_;
0067 SurfacePhysicsTrackView const& surface_phys_;
0068 ReflectionModeSampler reflection_calc_;
0069 DielectricInterface dielectric_interface_;
0070 };
0071
0072
0073
0074
0075
0076
0077
0078 CELER_FUNCTION SurfaceInteraction DielectricInteractor::Executor::operator()(
0079 CoreTrackView const& track) const
0080 {
0081 auto s_phys = track.surface_physics();
0082
0083
0084 if (!s_phys.next_material())
0085 {
0086 return SurfaceInteraction::from_absorption();
0087 }
0088
0089
0090 if (s_phys.material() == s_phys.next_material())
0091 {
0092 return SurfaceInteraction::from_transmission();
0093 }
0094
0095 auto rng = track.rng();
0096 auto sub_model_id
0097 = s_phys.interface(SurfacePhysicsOrder::interaction).internal_surface_id();
0098 CELER_ASSERT(sub_model_id < dielectric_data.interface.size());
0099
0100 return DielectricInteractor{
0101 track.particle(),
0102 track.geometry().dir(),
0103 s_phys,
0104 track.material_record(s_phys.material()),
0105 track.material_record(s_phys.next_material()),
0106 ReflectionModeSampler{
0107 unified_data, sub_model_id, track.particle().energy()},
0108 dielectric_data.interface[sub_model_id]}(rng);
0109 }
0110
0111
0112
0113
0114
0115 CELER_FUNCTION DielectricInteractor::DielectricInteractor(
0116 ParticleTrackView const& particle,
0117 Real3 const& inc_direction,
0118 SurfacePhysicsTrackView const& surface_physics,
0119 MaterialView const& pre_material,
0120 MaterialView const& post_material,
0121 ReflectionModeSampler reflection_calc,
0122 DielectricInterface dielectric_interface)
0123 : fresnel_(inc_direction,
0124 particle,
0125 surface_physics.facet_normal(),
0126 pre_material,
0127 post_material)
0128 , inc_direction_(inc_direction)
0129 , inc_photon_(particle)
0130 , surface_phys_(surface_physics)
0131 , reflection_calc_(reflection_calc)
0132 , dielectric_interface_(dielectric_interface)
0133 {
0134 }
0135
0136
0137
0138
0139
0140 template<class Engine>
0141 CELER_FUNCTION SurfaceInteraction DielectricInteractor::operator()(
0142 Engine& rng) const
0143 {
0144 if (BernoulliDistribution{fresnel_.calc_reflectivity()}(rng))
0145 {
0146
0147 return ReflectionFormSampler{
0148 reflection_calc_,
0149 ReflectionFormCalculator{
0150 inc_direction_, inc_photon_, surface_phys_}}(rng);
0151 }
0152 else
0153 {
0154
0155 switch (dielectric_interface_)
0156 {
0157 case DielectricInterface::metal:
0158 return SurfaceInteraction::from_absorption();
0159 case DielectricInterface::dielectric:
0160 return fresnel_.refracted_interaction();
0161 default:
0162 CELER_ASSERT_UNREACHABLE();
0163 }
0164 }
0165 }
0166
0167
0168 }
0169 }