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/SurfaceTraversalView.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/math/ArrayUtils.hh"
0010 #include "celeritas/optical/Types.hh"
0011 
0012 #include "SurfacePhysicsData.hh"
0013 #include "SurfacePhysicsUtils.hh"
0014 
0015 namespace celeritas
0016 {
0017 namespace optical
0018 {
0019 //---------------------------------------------------------------------------//
0020 /*!
0021  * Manage one-dimensional logic for traversing an optical surface.
0022  *
0023  * During surface crossing, tracks maintain a "within-surface state" that
0024  * stores the current layer and direction, decoupling the geometry state from
0025  * the material state.
0026  *
0027  * See \c SurfacePhysicsView for documentation.
0028  */
0029 class SurfaceTraversalView
0030 {
0031   public:
0032     //!@{
0033     //! \name Type aliases
0034     using SurfaceParamsRef = NativeCRef<SurfacePhysicsParamsData>;
0035     using SurfaceStateRef = NativeRef<SurfacePhysicsStateData>;
0036     //!@}
0037 
0038     struct Initializer
0039     {
0040     };
0041 
0042   public:
0043     // Create view from surface physics data and state
0044     inline CELER_FUNCTION SurfaceTraversalView(
0045         SurfaceParamsRef const&, SurfaceStateRef const&, TrackSlotId);
0046 
0047     // Initialize track state
0048     inline CELER_FUNCTION SurfaceTraversalView& operator=(Initializer const&);
0049 
0050     // Whether the track is in the pre-volume
0051     inline CELER_FUNCTION bool in_pre_volume() const;
0052 
0053     // Whether the track is in the post-volume
0054     inline CELER_FUNCTION bool in_post_volume() const;
0055 
0056     // Whether track is currently moving off the surface
0057     inline CELER_FUNCTION bool is_exiting() const;
0058 
0059     // Whether track is in pre-/post-volume and direction is off the surface
0060     inline CELER_FUNCTION bool is_exiting(LocalDirection) const;
0061 
0062     // Position of the track in the surface crossing
0063     inline CELER_FUNCTION LocalPositionId pos() const;
0064 
0065     // Next pos of the track in the given direction
0066     inline CELER_FUNCTION LocalPositionId next_pos() const;
0067 
0068     // Set position of the track in the surface crossing
0069     inline CELER_FUNCTION void pos(LocalPositionId);
0070 
0071     // Number of valid positions of the track in the surface crossing
0072     inline CELER_FUNCTION LocalSurfaceId::size_type num_local_pos() const;
0073 
0074     // Current track traversal direction
0075     inline CELER_FUNCTION LocalDirection dir() const;
0076 
0077     // Set track traversal direction
0078     inline CELER_FUNCTION void dir(LocalDirection);
0079 
0080     // Cross subsurface interface in the given direction
0081     inline CELER_FUNCTION void cross_interface(LocalDirection);
0082 
0083   private:
0084     SurfaceParamsRef const& params_;
0085     SurfaceStateRef const& states_;
0086     TrackSlotId const track_id_;
0087 };
0088 
0089 //---------------------------------------------------------------------------//
0090 // INLINE DEFINITIONS
0091 //---------------------------------------------------------------------------//
0092 /*!
0093  * Create view from surface physics data and state for a given track.
0094  */
0095 CELER_FUNCTION SurfaceTraversalView::SurfaceTraversalView(
0096     SurfaceParamsRef const& params,
0097     SurfaceStateRef const& states,
0098     TrackSlotId track)
0099     : params_(params), states_(states), track_id_(track)
0100 {
0101     CELER_EXPECT(track_id_ < states_.size());
0102     CELER_EXPECT(states_.surface[track_id_] < params_.surfaces.size());
0103 }
0104 
0105 //---------------------------------------------------------------------------//
0106 /*!
0107  * Initialize track state with given initializer data.
0108  */
0109 CELER_FUNCTION SurfaceTraversalView& SurfaceTraversalView::operator=(
0110     Initializer const&)
0111 {
0112     states_.local_position[track_id_] = LocalPositionId{0};
0113     states_.local_direction[track_id_] = LocalDirection::forward;
0114     return *this;
0115 }
0116 
0117 //---------------------------------------------------------------------------//
0118 /*!
0119  * Whether the track is in the pre-volume.
0120  */
0121 CELER_FUNCTION bool SurfaceTraversalView::in_pre_volume() const
0122 {
0123     return this->pos().get() == 0;
0124 }
0125 
0126 //---------------------------------------------------------------------------//
0127 /*!
0128  * Whether the track is in the post-volume.
0129  */
0130 CELER_FUNCTION bool SurfaceTraversalView::in_post_volume() const
0131 {
0132     return this->pos().get() + 1 == this->num_local_pos();
0133 }
0134 
0135 //---------------------------------------------------------------------------//
0136 /*!
0137  * Whether the current track direction is exiting the surface.
0138  */
0139 CELER_FUNCTION bool SurfaceTraversalView::is_exiting() const
0140 {
0141     return this->is_exiting(this->dir());
0142 }
0143 
0144 //---------------------------------------------------------------------------//
0145 /*!
0146  * Whether the direction is exiting the surface.
0147  */
0148 CELER_FUNCTION bool SurfaceTraversalView::is_exiting(LocalDirection d) const
0149 {
0150     // Use unsigned underflow when moving reverse (-1) on the pre-surface
0151     // (position 0) to wrap to an invalid position value
0152     return next_local_pos_id(this->pos(), d).unchecked_get()
0153            >= this->num_local_pos();
0154 }
0155 
0156 //---------------------------------------------------------------------------//
0157 /*!
0158  * Current position of the track in the sub-surfaces, in track-local
0159  * coordinates.
0160  *
0161  * Tracks traverse a surface in track-local coordinates where 0 is the
0162  * pre-volume and N is the post-volume. Depending on the surface orientation,
0163  * this will be mapped to the appropriate sub-surface material and interface.
0164  */
0165 CELER_FUNCTION LocalPositionId SurfaceTraversalView::pos() const
0166 {
0167     return states_.local_position[track_id_];
0168 }
0169 
0170 //---------------------------------------------------------------------------//
0171 /*!
0172  */
0173 CELER_FUNCTION LocalPositionId SurfaceTraversalView::next_pos() const
0174 {
0175     return next_local_pos_id(this->pos(), this->dir());
0176 }
0177 
0178 //---------------------------------------------------------------------------//
0179 /*!
0180  * Set current position of the track in the sub-surfaces, in track-local
0181  * coordinates.
0182  */
0183 CELER_FUNCTION void SurfaceTraversalView::pos(LocalPositionId pos)
0184 {
0185     CELER_EXPECT(pos < this->num_local_pos());
0186     states_.local_position[track_id_] = pos;
0187 }
0188 
0189 //---------------------------------------------------------------------------//
0190 /*!
0191  * Get number of valid track positions in the surface.
0192  *
0193  * This is equivalent to the number of interstitial sub-surface materials, plus
0194  * the pre-volume and post-volumes.
0195  *
0196  * \todo Check if caching this would improve performance over redirections.
0197  */
0198 CELER_FUNCTION LocalSurfaceId::size_type
0199 SurfaceTraversalView::num_local_pos() const
0200 {
0201     auto const& surface = params_.surfaces[states_.surface[track_id_]];
0202     return surface.interstitial_mat_ids.size() + 2;
0203 }
0204 
0205 //---------------------------------------------------------------------------//
0206 /*!
0207  * Get current track traversal direction.
0208  *
0209  * This quantity is cached for a single loop of surface boundary crossing to
0210  * avoid repeated queries of the geometry. The traversal direction should be
0211  * updated when the geometry direction is updated after an interaction.
0212  */
0213 CELER_FUNCTION LocalDirection SurfaceTraversalView::dir() const
0214 {
0215     return states_.local_direction[track_id_];
0216 }
0217 
0218 //---------------------------------------------------------------------------//
0219 /*!
0220  * Set current track traversal direction.
0221  */
0222 CELER_FUNCTION void SurfaceTraversalView::dir(LocalDirection dir)
0223 {
0224     states_.local_direction[track_id_] = dir;
0225 }
0226 
0227 //---------------------------------------------------------------------------//
0228 /*!
0229  * Cross the subsurface interface in the given direction.
0230  */
0231 CELER_FUNCTION void SurfaceTraversalView::cross_interface(LocalDirection d)
0232 {
0233     CELER_EXPECT(!this->is_exiting(d));
0234     this->pos(next_local_pos_id(this->pos(), d));
0235 }
0236 
0237 //---------------------------------------------------------------------------//
0238 }  // namespace optical
0239 }  // namespace celeritas