|
|
|||
File indexing completed on 2026-10-29 09:13:54
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 geocel/GeoTrackInterface.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <functional> 0010 0011 #include "corecel/Config.hh" 0012 0013 #include "corecel/Macros.hh" 0014 #include "corecel/cont/Array.hh" 0015 #include "corecel/cont/Span.hh" 0016 #include "corecel/math/ArrayUtils.hh" 0017 0018 #include "Types.hh" 0019 0020 namespace celeritas 0021 { 0022 //---------------------------------------------------------------------------// 0023 /*! 0024 * Standard interface to geometry navigation for a track for testing on CPU. 0025 * \tparam RealType Floating point precision 0026 * 0027 * \note This class is for illustrative and testing purposes \b only 0028 * (see celeritas::test::WrappedGeoTrackView) and is 0029 * \b not used during the main Celeritas execution. The geometry there is 0030 * determined by the \c CELERITAS_CORE_GEO configuration variable and defined 0031 * as a type alias \c celeritas::CoreGeoTrackView . 0032 * 0033 * Initialization is performed via the assignment operator using a \c 0034 * GeoTrackInitializer. 0035 * 0036 * - Initialization may fail, leaving the track with an "error" status. 0037 * - Some implementations allow initialization on a boundary, leaving the track 0038 * in an "outgoing from boundary" state (i.e., the next step is into the 0039 * volume the track initializes inside). 0040 * - Some implementations allow initialization to succeed but be in an 0041 * unphysical part of the geometry (e.g., ORANGE exterior volume). In this 0042 * case, the canonical volume ID will be null, indicating no 0043 * corresponding user-defined geometry region. 0044 * 0045 * Tracking to and across volumes along a straight line requires a specific 0046 * sequence of calls. 0047 * 0048 * - Locate the boundary crossing along the current direction with \c 0049 * find_next_step. 0050 * - Move within the current volume, not crossing a boundary, via \c 0051 * move_internal or \c move_to_boundary. 0052 * - If on a boundary, \c normal can be used to calculate the current surface 0053 * normal, but its dot product with the track direction may not be 0054 * meaningful. Use \c geo_status to determine whether the track is incident 0055 * to or outgoing from the boundary. 0056 * - If incident into the boundary, change volumes ("relocate") with \c 0057 * cross_boundary. The post-crossing status can be \c error, \c 0058 * boundary_out, or \c invalid. Some geometries represent the exterior as a 0059 * null canonical VolumeId, and some as an invalid state. 0060 * 0061 * \note The free function \c is_on_boundary will be true of the geo status 0062 * both before \em and after the call to \c cross_boundary, and the surface 0063 * normal can be calculated in both cases. 0064 * 0065 * Movement to a nearby but arbitrary point can be done inside a 0066 * "safety" distance: 0067 * 0068 * - Locate the closest point on the boundary in any direction with \c 0069 * find_safety. 0070 * - Change the direction with \c set_dir. (Note that this will always 0071 * invalidate the linear "next step".) 0072 * - Move to a point with \c move_internal. 0073 * 0074 * Neither accessors nor mutators should be called in an \c invalid state. 0075 * It is allowable but potentially dangerous to call accessors in an \c error 0076 * state. 0077 */ 0078 template<class RealType = ::celeritas::real_type> 0079 class GeoTrackInterface 0080 { 0081 public: 0082 //!@{ 0083 //! \name Type aliases 0084 using Initializer_t = GeoTrackInitializer; 0085 using real_type = RealType; 0086 using Real3 = Array<real_type, 3>; 0087 using VolPathVisitor = std::function<void(VolumeLevelId, VolumeInstanceId)>; 0088 //!@} 0089 0090 public: 0091 // Anchor virtual destructor in GeoInterface.cc 0092 virtual ~GeoTrackInterface() = 0; 0093 0094 /*! 0095 * Initialize the state. 0096 * 0097 * Takes a \c GeoTrackInitializer object to locate the point in the 0098 * geometry hierarchy. 0099 * 0100 * \post \c geo_status() is never \c GeoStatus::boundary_inc : the 0101 * result is \c interior (placed inside a volume), \c boundary_out 0102 * (placed on a boundary with direction heading away from it), or \c 0103 * error (volume not found). 0104 */ 0105 virtual GeoTrackInterface& operator=(Initializer_t const& init) = 0; 0106 0107 //!@{ 0108 //! \name Physical state 0109 0110 //! Return the physical position in the global coordinate system 0111 virtual Real3 const& pos() const = 0; 0112 //! Return the direction in the global coordinate system 0113 virtual Real3 const& dir() const = 0; 0114 0115 //!@} 0116 //!@{ 0117 //! \name Canonical volume state 0118 //! \pre The geo status cannot be \c GeoStatus::invalid 0119 0120 //! Get the canonical volume ID in the current impl volume 0121 virtual VolumeId volume_id() const = 0; 0122 //! Get the physical volume ID in the current cell 0123 virtual VolumeInstanceId volume_instance_id() const = 0; 0124 //! Get the distance from root volume in the geometry hierarchy 0125 virtual VolumeLevelId volume_level() const = 0; 0126 //! Get the volume instance ID for all levels 0127 virtual void volume_instance_id(Span<VolumeInstanceId> levels) const = 0; 0128 //! Visit each volume level in the path 0129 virtual void foreach_volume_path(VolPathVisitor visit) const = 0; 0130 0131 /*! 0132 * Whether the track is outside the valid geometry region. 0133 * 0134 * Returns true if the track has left the world (or started outside the 0135 * outermost known volume). 0136 * 0137 * \deprecated Check \c geo.geo_status() is not \c invalid and evaluate \c 0138 * is_outside(geo.volume_id()) 0139 */ 0140 virtual bool is_outside() const = 0; 0141 //!@} 0142 0143 //! Get the implementation volume ID 0144 virtual ImplVolumeId impl_volume_id() const = 0; 0145 0146 /*! 0147 * Whether the last operation resulted in an error. 0148 * 0149 * \deprecated check \c geo_status for \c GeoStatus::error instead. 0150 */ 0151 virtual bool failed() const = 0; 0152 0153 //!@{ 0154 //! \name Surface state 0155 0156 /*! 0157 * Whether the track is exactly on a surface. 0158 * 0159 * Returns true if a track is exactly on the boundary of a volume, capable 0160 * of changing to another volume without altering the physical position. 0161 * 0162 * \deprecated use \c is_on_boundary(geo.geo_status()) 0163 */ 0164 virtual bool is_on_boundary() const = 0; 0165 0166 /*! 0167 * Calculate the normal vector on the current surface. 0168 * 0169 * Returns a global-coordinate direction perpendicular to the volume at 0170 * the local point when on a boundary. The sign of the surface normal is 0171 * implementation-dependent; it may change based on the track state 0172 * (previous volume, direction, surface sign) or geometry construction. 0173 * 0174 * \pre \c is_on_boundary(geo.geo_status()) must be true 0175 */ 0176 virtual Real3 normal() const = 0; 0177 0178 /*! 0179 * Derive the geometry state from the existing state flags. 0180 * 0181 * This is a shim for geometry implementations that do not natively track 0182 * the full \c GeoStatus. When on a boundary, it \b assumes the normal 0183 * vector is oriented "outward" from the current volume. 0184 * The dot product of the track direction and the surface normal determines 0185 * whether the track is incident to the boundary (positive: headed outward 0186 * from the volume) or incident (negative: headed into the volume). 0187 */ 0188 virtual GeoStatus geo_status() const 0189 { 0190 if (this->failed()) 0191 return GeoStatus::error; 0192 if (this->is_on_boundary()) 0193 { 0194 return dot_product(this->dir(), this->normal()) >= 0 0195 ? GeoStatus::boundary_inc 0196 : GeoStatus::boundary_out; 0197 } 0198 return GeoStatus::interior; 0199 } 0200 0201 //!@} 0202 //!@{ 0203 //! \name Straight-line movement and boundary crossing 0204 0205 /*! 0206 * Find the distance to the next boundary, up to and including a step. 0207 * 0208 * Determines the distance to the next boundary along the track's current 0209 * direction, up to a given distance. Queries may be more efficient for 0210 * small distances. 0211 * 0212 * \todo Revisit whether to allow \c geo_status() to be 0213 * \c GeoStatus::boundary_inc , or to reconsider \c geo_status entirely 0214 * 0215 * \post The returned distance is in the range \c [0, max_step] . 0216 * A zero distance must indicate a boundary hit, e.g. within the geometry's 0217 * surface tolerance. Call move_to_boundary followed by cross_boundary to 0218 * resolve the hit even when no physical displacement is needed. 0219 */ 0220 virtual Propagation find_next_step(real_type max_step) = 0; 0221 0222 /*! 0223 * Move within the volume along a straight line. 0224 * 0225 * Changes the physical position of the geometry state without altering 0226 * the logical state (i.e., it must remain within the current volume). 0227 * 0228 * \pre The given \c step must be less than or equal to the previous \c 0229 * find_next_step result and can only be equal if the endpoint is not on a 0230 * boundary. 0231 */ 0232 virtual void move_internal(real_type step) = 0; 0233 0234 /*! 0235 * Move to the boundary in preparation for crossing it. 0236 * 0237 * Moves the track to the boundary of the current volume along the current 0238 * direction, updating its logical state to indicate that it is on the 0239 * boundary of the current volume. 0240 * 0241 * \pre \c geo_status() is not \c GeoStatus::boundary_inc . 0242 * \post \c geo_status() is \c GeoStatus::boundary_inc . 0243 */ 0244 virtual void move_to_boundary() = 0; 0245 0246 /*! 0247 * Cross from one side of the current surface to the other. 0248 * 0249 * Changes the logical state when on the boundary, updating to the next 0250 * volume. 0251 * 0252 * \pre \c geo_status() is \c GeoStatus::boundary_inc . 0253 * \post \c geo_status() is \c GeoStatus::boundary_out , or \c 0254 * GeoStatus::error if the new volume could not be found. 0255 */ 0256 virtual void cross_boundary() = 0; 0257 //!@} 0258 //!@{ 0259 //! \name Locally bounded movement 0260 0261 /*! 0262 * Find the safety distance at the current position. 0263 * 0264 * Determines the distance to the nearest boundary in any direction (i.e., 0265 * the radius of the maximally inscribed sphere). 0266 * 0267 * \c deprecated: use \c find_safety(inf) (REMOVE in v0.8) 0268 */ 0269 virtual real_type find_safety() = 0; 0270 0271 /*! 0272 * Find the safety at the current position, up to a maximum step distance. 0273 * 0274 * The resulting safety should be no larger than the maximum step. 0275 * 0276 * \pre \c is_on_boundary(geo.geo_status()) must be false 0277 */ 0278 virtual real_type find_safety(real_type max_step) = 0; 0279 0280 /*! 0281 * Change direction. 0282 * 0283 * Changes the direction of the track (in global coordinate system). 0284 */ 0285 virtual void set_dir(Real3 const& newdir) = 0; 0286 0287 /*! 0288 * Move within the volume to a specific point. 0289 * 0290 * Changes the physical position of the geometry state without altering 0291 * the logical state (i.e., it must remain within the current volume). 0292 * The original and updated points \em must be path-connected: a line can 0293 * be drawn between them entirely within the current volume. 0294 */ 0295 virtual void move_internal(Real3 const& pos) = 0; 0296 //!@} 0297 0298 protected: 0299 GeoTrackInterface() = default; 0300 CELER_DEFAULT_COPY_MOVE(GeoTrackInterface); 0301 }; 0302 0303 //---------------------------------------------------------------------------// 0304 #if CELERITAS_REAL_TYPE == CELERITAS_REAL_TYPE_FLOAT 0305 extern template class GeoTrackInterface<float>; 0306 #endif 0307 extern template class GeoTrackInterface<double>; 0308 0309 //---------------------------------------------------------------------------// 0310 } // 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 |
|