|
|
|||
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/SurfacePhysicsView.hh 0006 //! \sa celeritas/optical/SurfacePhysics.test.cc 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include "celeritas/Types.hh" 0011 #include "celeritas/optical/Types.hh" 0012 0013 #include "SurfacePhysicsData.hh" 0014 #include "SurfacePhysicsUtils.hh" 0015 0016 namespace celeritas 0017 { 0018 namespace optical 0019 { 0020 //---------------------------------------------------------------------------// 0021 /*! 0022 * Access physics data for a local surface based on traversal orientation. 0023 * 0024 * "Local" surfaces, which are boundaries between layers on a geometric 0025 * surface, are ordered in storage between two volumes based on user input. 0026 * These layers can be traversed based on the \c orientation, whether the track 0027 * entered the surface crossing in \c forward order (e.g., \em out of the 0028 * volume defining a boundary surface) or \c reverse (e.g., \em into that 0029 * volume). 0030 * 0031 * The surface physics record only stores the behavior on the surfaces and 0032 * interstitial materials. Because one geometric surface can be surrounded by 0033 * different pairs of pre/post materials (due to the physical volume 0034 * adjacency), it \em cannot store the pre- and post-crossing materials. 0035 * Those are managed by the \c SurfacePhysicsTrackView which has extra state. 0036 * 0037 * A single geometric surface with \em N interstitial layers will have 0038 * \f$ N + 2 \f$ "local materials" and \f$ N + 1 \f$ "local surfaces". 0039 * Most geometric surfaces have no interstial layers, just a pre- and post- 0040 * volume material with a single surface, and therefore have two local material 0041 * regions surrounding a single local surface. 0042 * 0043 * During crossing \c LocalSurfaceId{0} separates the pre-volume material (\c 0044 * LocalPositionId{0} ) and the next. 0045 * Physics surface IDs are contiguous <em>by construction</em> 0046 * in the surface physics loader and optical physics input. 0047 * 0048 * \par Example traversal 0049 * 0050 * This surface record has two interstitial materials, implying three surfaces 0051 * and a total of four materials during the crossing. 0052 * The IDs and corresponding physics data, when traversing in the forward 0053 * direction, are: 0054 * \verbatim 0055 local surface ID : LS0 LS1 LS2 0056 local material ID : LM0 | LM1 | LM2 | LM3 0057 interstitial materials : (pre) | IM0 | IM1 | (post) 0058 optical materials : ---- | A | B | ---- 0059 physics surfaces : | X | X+1 | 0060 \endverbatim 0061 * Only the two interstitial materials' optical material IDs can be accessed by 0062 * the view. 0063 * The orientation of the local surfaces and interstitial materials align 0064 * with the \c SurfacePhysicsRecord storage \em only in the \c forward 0065 * orientation. 0066 * When traversing in \c reverse orientation, the data layout stays the same 0067 * but the IDs are still relative to the pre/post volumes: 0068 * \verbatim 0069 local surface ID : LS2 LS1 LS0 0070 local material ID : LM3 | LM2 | LM1 | LM0 0071 interstitial materials : (post) | IM1 | IM0 | (pre) 0072 optical materials : ---- | A | B | ---- 0073 physics surfaces : | X | X+1 | 0074 \endverbatim 0075 * 0076 */ 0077 class SurfacePhysicsView 0078 { 0079 public: 0080 //!@{ 0081 //! \name Type aliases 0082 using SurfaceParamsRef = NativeCRef<SurfacePhysicsParamsData>; 0083 //!@} 0084 0085 public: 0086 // Construct view from data and state 0087 inline CELER_FUNCTION SurfacePhysicsView( 0088 SurfaceParamsRef const&, SurfaceId, LocalDirection); 0089 0090 //! Get geometric surface ID the track is currently on 0091 CELER_FIF SurfaceId surface() const { return surface_; } 0092 0093 //! Get traversal orientation on the current surface 0094 CELER_FIF LocalDirection orientation() const { return orientation_; } 0095 0096 // Get optical pre/interstitial/post material at the given track position 0097 inline CELER_FUNCTION OptMatId interstitial_material(LocalPositionId) const; 0098 0099 // Get the physics surface at the given position and direction 0100 inline CELER_FUNCTION PhysSurfaceId interface(LocalPositionId, 0101 LocalDirection) const; 0102 0103 private: 0104 SurfaceParamsRef const& params_; 0105 SurfaceId surface_; 0106 LocalDirection orientation_; 0107 0108 // Get record data for the current surface 0109 inline CELER_FUNCTION SurfacePhysicsRecord const& surface_record() const; 0110 }; 0111 0112 //---------------------------------------------------------------------------// 0113 // INLINE DEFINITIONS 0114 //---------------------------------------------------------------------------// 0115 /*! 0116 * Construct from data, states, and a given track ID. 0117 */ 0118 CELER_FUNCTION SurfacePhysicsView::SurfacePhysicsView( 0119 SurfaceParamsRef const& params, 0120 SurfaceId surface, 0121 LocalDirection orientation) 0122 : params_(params), surface_(surface), orientation_(orientation) 0123 { 0124 CELER_EXPECT(surface_ < params_.surfaces.size()); 0125 } 0126 0127 //---------------------------------------------------------------------------// 0128 /*! 0129 * Return the interstitial material ID at the given track position. 0130 * 0131 * Position should be in the range [1,N] where N is the number of subsurface 0132 * materials. 0133 */ 0134 CELER_FUNCTION OptMatId SurfacePhysicsView::interstitial_material( 0135 LocalPositionId pos) const 0136 { 0137 auto const& ids = this->surface_record().interstitial_mat_ids; 0138 CELER_EXPECT(pos > LocalPositionId{0} && pos <= ids.size()); 0139 0140 // Position 0 is pre-volume material, and N+1 is post-volume material. 0141 // Offset position so it maps to the interstitial material range. 0142 LocalPositionId::size_type interstit_idx = pos.unchecked_get(); 0143 if (orientation_ == LocalDirection::reverse) 0144 { 0145 interstit_idx = ids.size() - interstit_idx; 0146 } 0147 else 0148 { 0149 --interstit_idx; 0150 } 0151 0152 ItemId<OptMatId> opt_mat_id_id = ids[interstit_idx]; 0153 CELER_ASSERT(opt_mat_id_id < params_.opt_mat_ids.size()); 0154 return params_.opt_mat_ids[opt_mat_id_id]; 0155 } 0156 0157 //---------------------------------------------------------------------------// 0158 /*! 0159 * Return the next physics surface at the given position along the direction. 0160 */ 0161 CELER_FUNCTION PhysSurfaceId SurfacePhysicsView::interface( 0162 LocalPositionId pos, LocalDirection dir) const 0163 { 0164 auto const& ids = this->surface_record().local_surface_ids; 0165 CELER_EXPECT(pos >= LocalPositionId{0} && pos <= ids.size()); 0166 0167 auto local_surf = local_surf_id(pos, dir); 0168 if (orientation_ == LocalDirection::reverse) 0169 { 0170 // Reverse index in ids: 0 -> N-1; 1 -> N-2; ... 0171 local_surf = id_cast<LocalSurfaceId>( 0172 ids.size() - 1 - local_surf.unchecked_get()); 0173 } 0174 0175 CELER_ENSURE(local_surf < ids.size()); 0176 return ids[local_surf]; 0177 } 0178 0179 //---------------------------------------------------------------------------// 0180 /*! 0181 * Get surface record of current geometric surface. 0182 */ 0183 CELER_FUNCTION SurfacePhysicsRecord const& 0184 SurfacePhysicsView::surface_record() const 0185 { 0186 return params_.surfaces[this->surface()]; 0187 } 0188 0189 //---------------------------------------------------------------------------// 0190 } // namespace optical 0191 } // namespace celeritas
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|