Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:11:40

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file celeritas/optical/surface/SurfacePhysicsTrackView.hh
0006 //! \sa celeritas/optical/SurfacePhysics.test.cc
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "corecel/math/ArrayOperators.hh"
0011 #include "celeritas/optical/Types.hh"
0012 #include "celeritas/phys/SurfacePhysicsMapView.hh"
0013 
0014 #include "SurfacePhysicsData.hh"
0015 #include "SurfacePhysicsUtils.hh"
0016 #include "SurfacePhysicsView.hh"
0017 #include "SurfaceTraversalView.hh"
0018 
0019 namespace celeritas
0020 {
0021 namespace optical
0022 {
0023 //---------------------------------------------------------------------------//
0024 /*!
0025  * Optical surface physics data for a track.
0026  *
0027  * Tracks maintain a position while traversing the interstitial materials of an
0028  * optical surface.
0029  * This class provides transformations from this position based on the surface
0030  * orientation (pre/post volume when the crossing began) and traversal
0031  * direction (current state) to access relevant material and interface data in
0032  * storage.
0033  *
0034  * See \c SurfacePhysicsView, \c SurfaceTraversalView .
0035  */
0036 class SurfacePhysicsTrackView
0037 {
0038   public:
0039     //!@{
0040     //! \name Type aliases
0041     using SurfaceParamsRef = NativeCRef<SurfacePhysicsParamsData>;
0042     using SurfaceStateRef = NativeRef<SurfacePhysicsStateData>;
0043     //!@}
0044 
0045     struct Initializer
0046     {
0047         SurfaceId surface{};
0048         LocalDirection orientation;
0049         Real3 global_normal{0, 0, 0};
0050         OptMatId pre_volume_material{};
0051         OptMatId post_volume_material{};
0052     };
0053 
0054   public:
0055     // Create view from surface physics data and state
0056     inline CELER_FUNCTION SurfacePhysicsTrackView(
0057         SurfaceParamsRef const&, SurfaceStateRef const&, TrackSlotId);
0058 
0059     // Initialize track state
0060     inline CELER_FUNCTION SurfacePhysicsTrackView& operator=(
0061         Initializer const&);
0062 
0063     // Reset surface physics state of the track
0064     inline CELER_FUNCTION void reset();
0065 
0066     // Whether track is undergoing boundary crossing
0067     inline CELER_FUNCTION bool is_crossing_boundary() const;
0068 
0069     // Get current subsurface material
0070     inline CELER_FUNCTION OptMatId material() const;
0071 
0072     // Get next subsurface material
0073     inline CELER_FUNCTION OptMatId next_material() const;
0074 
0075     // Get surface physics map for next surface
0076     inline CELER_FUNCTION SurfacePhysicsMapView interface(
0077         SurfacePhysicsOrder) const;
0078 
0079     // Calculate and update traversal direction from track momentum
0080     inline CELER_FUNCTION void update_traversal_direction(Real3 const&);
0081 
0082     // Get global surface normal
0083     inline CELER_FUNCTION Real3 global_normal() const;
0084 
0085     // Get local facet normal
0086     inline CELER_FUNCTION Real3 const& facet_normal() const;
0087 
0088     // Assign local facet normal
0089     inline CELER_FUNCTION void facet_normal(Real3 const&);
0090 
0091     // Get reflectivity action for this step
0092     inline CELER_FUNCTION ReflectivityAction reflectivity_action() const;
0093 
0094     // Assign reflectivity action for this step
0095     inline CELER_FUNCTION void reflectivity_action(ReflectivityAction);
0096 
0097     // Construct a traversal view for this track
0098     inline CELER_FUNCTION SurfaceTraversalView traversal() const;
0099 
0100     // Construct a constant physics view
0101     inline CELER_FUNCTION SurfacePhysicsView surface() const;
0102 
0103     // Access scalar data for surface physics
0104     inline CELER_FUNCTION SurfacePhysicsParamsScalars const& scalars() const;
0105 
0106   private:
0107     SurfaceParamsRef const& params_;
0108     SurfaceStateRef const& states_;
0109     TrackSlotId const track_id_;
0110 
0111     // Get material at the given track position
0112     inline CELER_FUNCTION OptMatId material(LocalPositionId) const;
0113 };
0114 
0115 //---------------------------------------------------------------------------//
0116 // INLINE DEFINITIONS
0117 //---------------------------------------------------------------------------//
0118 /*!
0119  * Initialize view from surface physics data and state for a given track.
0120  */
0121 CELER_FUNCTION SurfacePhysicsTrackView::SurfacePhysicsTrackView(
0122     SurfaceParamsRef const& params,
0123     SurfaceStateRef const& states,
0124     TrackSlotId track)
0125     : params_(params), states_(states), track_id_(track)
0126 {
0127     CELER_EXPECT(track_id_ < states_.size());
0128 }
0129 
0130 //---------------------------------------------------------------------------//
0131 /*!
0132  * Initialize track state with given initializer data.
0133  */
0134 CELER_FUNCTION SurfacePhysicsTrackView& SurfacePhysicsTrackView::operator=(
0135     Initializer const& init)
0136 {
0137     CELER_EXPECT(init.surface < params_.surfaces.size());
0138     CELER_EXPECT(is_soft_unit_vector(init.global_normal));
0139     states_.surface[track_id_] = init.surface;
0140     states_.surface_orientation[track_id_] = init.orientation;
0141     states_.global_normal[track_id_] = init.global_normal;
0142     states_.facet_normal[track_id_] = init.global_normal;
0143     states_.pre_volume_material[track_id_] = init.pre_volume_material;
0144     states_.post_volume_material[track_id_] = init.post_volume_material;
0145     states_.reflectivity_action[track_id_] = ReflectivityAction::interact;
0146     this->traversal() = SurfaceTraversalView::Initializer{};
0147     return *this;
0148 }
0149 
0150 //---------------------------------------------------------------------------//
0151 /*!
0152  * Reset the state of a track.
0153  *
0154  * Invalidates the surface ID, indicating the track is no longer undergoing
0155  * boundary crossing.
0156  */
0157 CELER_FUNCTION void SurfacePhysicsTrackView::reset()
0158 {
0159     states_.surface[track_id_] = {};
0160     CELER_ENSURE(!states_.surface[track_id_]);
0161 }
0162 
0163 //---------------------------------------------------------------------------//
0164 /*!
0165  * Whether the track is undergoing boundary crossing.
0166  *
0167  * Returns true if there's a valid surface ID, otherwise false.
0168  */
0169 CELER_FUNCTION bool SurfacePhysicsTrackView::is_crossing_boundary() const
0170 {
0171     return states_.surface[track_id_] < params_.surfaces.size();
0172 }
0173 
0174 //---------------------------------------------------------------------------//
0175 /*!
0176  * Get current subsurface material.
0177  */
0178 CELER_FUNCTION OptMatId SurfacePhysicsTrackView::material() const
0179 {
0180     return this->material(this->traversal().pos());
0181 }
0182 
0183 //---------------------------------------------------------------------------//
0184 /*!
0185  * Get next subsurface material.
0186  */
0187 CELER_FUNCTION OptMatId SurfacePhysicsTrackView::next_material() const
0188 {
0189     return this->material(this->traversal().next_pos());
0190 }
0191 
0192 //---------------------------------------------------------------------------//
0193 /*!
0194  * Get surface physics map for next surface.
0195  */
0196 CELER_FUNCTION SurfacePhysicsMapView SurfacePhysicsTrackView::interface(
0197     SurfacePhysicsOrder step) const
0198 {
0199     auto traverse = this->traversal();
0200     return SurfacePhysicsMapView{
0201         params_.model_maps[step],
0202         this->surface().interface(traverse.pos(), traverse.dir())};
0203 }
0204 
0205 //---------------------------------------------------------------------------//
0206 /*!
0207  * Calculate and update traversal direction from track momentum.
0208  */
0209 CELER_FUNCTION void SurfacePhysicsTrackView::update_traversal_direction(
0210     Real3 const& dir)
0211 {
0212     CELER_EXPECT(is_soft_unit_vector(dir));
0213     this->traversal().dir(
0214         calc_subsurface_direction(dir, states_.global_normal[track_id_]));
0215     CELER_ENSURE(is_entering_surface(dir, this->global_normal()));
0216 }
0217 
0218 //---------------------------------------------------------------------------//
0219 /*!
0220  * Get global surface normal.
0221  *
0222  * The global surface normal is the normal defined by the geometry and does not
0223  * include any roughness effects. By convention it points from the post-volume
0224  * into the pre-volume.
0225  */
0226 CELER_FUNCTION Real3 SurfacePhysicsTrackView::global_normal() const
0227 {
0228     CELER_EXPECT(this->is_crossing_boundary());
0229     return to_signed_offset(this->traversal().dir())
0230            * states_.global_normal[track_id_];
0231 }
0232 
0233 //---------------------------------------------------------------------------//
0234 /*!
0235  * Get local facet normal after roughness sampling.
0236  */
0237 CELER_FUNCTION Real3 const& SurfacePhysicsTrackView::facet_normal() const
0238 {
0239     CELER_EXPECT(this->is_crossing_boundary());
0240     return states_.facet_normal[track_id_];
0241 }
0242 
0243 //---------------------------------------------------------------------------//
0244 /*!
0245  * Assign local facet normal from roughness sampling.
0246  */
0247 CELER_FUNCTION void SurfacePhysicsTrackView::facet_normal(Real3 const& normal)
0248 {
0249     CELER_EXPECT(this->is_crossing_boundary());
0250     CELER_EXPECT(is_soft_unit_vector(normal));
0251     CELER_EXPECT(dot_product(normal, this->global_normal()) >= 0);
0252     states_.facet_normal[track_id_] = normal;
0253 }
0254 
0255 //---------------------------------------------------------------------------//
0256 /*!
0257  * Get the reflectivity action for this step.
0258  */
0259 CELER_FUNCTION ReflectivityAction
0260 SurfacePhysicsTrackView::reflectivity_action() const
0261 {
0262     return states_.reflectivity_action[track_id_];
0263 }
0264 
0265 //---------------------------------------------------------------------------//
0266 /*!
0267  * Assign the reflectivity action for this step.
0268  */
0269 CELER_FUNCTION void SurfacePhysicsTrackView::reflectivity_action(
0270     ReflectivityAction action)
0271 {
0272     states_.reflectivity_action[track_id_] = action;
0273 }
0274 
0275 //---------------------------------------------------------------------------//
0276 /*!
0277  * Construct a traversal view for this track.
0278  */
0279 CELER_FUNCTION SurfaceTraversalView SurfacePhysicsTrackView::traversal() const
0280 {
0281     return SurfaceTraversalView{params_, states_, track_id_};
0282 }
0283 
0284 //---------------------------------------------------------------------------//
0285 /*!
0286  * Construct a surface physics view, whose orientation is based on this track.
0287  */
0288 CELER_FUNCTION SurfacePhysicsView SurfacePhysicsTrackView::surface() const
0289 {
0290     return SurfacePhysicsView{params_,
0291                               states_.surface[track_id_],
0292                               states_.surface_orientation[track_id_]};
0293 }
0294 
0295 //---------------------------------------------------------------------------//
0296 /*!
0297  * Access scalar data for surface physics.
0298  */
0299 CELER_FUNCTION SurfacePhysicsParamsScalars const&
0300 SurfacePhysicsTrackView::scalars() const
0301 {
0302     return params_.scalars;
0303 }
0304 
0305 //---------------------------------------------------------------------------//
0306 /*!
0307  * Get material at given track position.
0308  */
0309 CELER_FUNCTION OptMatId SurfacePhysicsTrackView::material(
0310     LocalPositionId pos) const
0311 {
0312     auto pos_range = range(LocalPositionId{this->traversal().num_local_pos()});
0313     CELER_EXPECT(pos < pos_range.size());
0314 
0315     if (pos == pos_range.front())
0316     {
0317         // Pre-volume material
0318         return states_.pre_volume_material[track_id_];
0319     }
0320     else if (pos == pos_range.back())
0321     {
0322         // Post-volume material
0323         return states_.post_volume_material[track_id_];
0324     }
0325 
0326     return this->surface().interstitial_material(pos);
0327 }
0328 
0329 //---------------------------------------------------------------------------//
0330 }  // namespace optical
0331 }  // namespace celeritas