|
||||
File indexing completed on 2025-01-18 10:05:59
0001 //----------------------------------*-C++-*----------------------------------// 0002 // Copyright 2021-2024 UT-Battelle, LLC, and other Celeritas developers. 0003 // See the top-level COPYRIGHT file for details. 0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0005 //---------------------------------------------------------------------------// 0006 //! \file orange/OrangeTypes.hh 0007 //! \brief Type definitions for ORANGE geometry. 0008 //---------------------------------------------------------------------------// 0009 #pragma once 0010 0011 #include <cstddef> 0012 #include <functional> 0013 #include <type_traits> 0014 #include <utility> 0015 0016 #include "corecel/Macros.hh" 0017 #include "corecel/OpaqueId.hh" 0018 #include "corecel/Types.hh" 0019 #include "corecel/cont/Array.hh" 0020 #include "corecel/math/NumericLimits.hh" 0021 #include "geocel/Types.hh" // IWYU pragma: export 0022 0023 namespace celeritas 0024 { 0025 //---------------------------------------------------------------------------// 0026 template<class T> 0027 class BoundingBox; 0028 0029 //---------------------------------------------------------------------------// 0030 // TYPE ALIASES 0031 //---------------------------------------------------------------------------// 0032 0033 //! Real type used for acceleration 0034 using fast_real_type = float; 0035 0036 //! Integer type for volume CSG tree representation 0037 using logic_int = size_type; 0038 0039 //! Helper class for some template dispatch functions 0040 template<Axis T> 0041 using AxisTag = std::integral_constant<Axis, T>; 0042 0043 //// ID TYPES //// 0044 0045 //! Identifier for a BIHNode objects 0046 using BIHNodeId = OpaqueId<struct BIHNode_>; 0047 0048 //! Identifier for a daughter universe 0049 using DaughterId = OpaqueId<struct Daughter>; 0050 0051 //! Identifier for a face within a volume 0052 using FaceId = OpaqueId<struct Face_, logic_int>; 0053 0054 //! Bounding box used for acceleration 0055 using FastBBox = BoundingBox<fast_real_type>; 0056 0057 //! Identifier for a bounding box used for acceleration 0058 using FastBBoxId = OpaqueId<FastBBox>; 0059 0060 //! Identifier for an array of length three of floating point values 0061 using FastReal3 = Array<float, 3>; 0062 0063 //! Identifier for the current "level", i.e., depth of embedded universe 0064 using LevelId = OpaqueId<struct Level_>; 0065 0066 //! Local identifier for a surface within a universe 0067 using LocalSurfaceId = OpaqueId<struct LocalSurface_>; 0068 0069 //! Local identifier for a geometry volume within a universe 0070 using LocalVolumeId = OpaqueId<struct LocalVolume_>; 0071 0072 //! Identifier for an OrientedBoundingZone 0073 using OrientedBoundingZoneId = OpaqueId<struct OrientedBoundingZoneRecord>; 0074 0075 //! Opaque index for "simple unit" data 0076 using SimpleUnitId = OpaqueId<struct SimpleUnitRecord>; 0077 0078 //! Opaque index for rectilinear array data 0079 using RectArrayId = OpaqueId<struct RectArrayRecord>; 0080 0081 //! Identifier for a translation of a single embedded universe 0082 using TransformId = OpaqueId<struct TransformRecord>; 0083 0084 //! Identifier for a relocatable set of volumes 0085 using UniverseId = OpaqueId<struct Universe_>; 0086 0087 //---------------------------------------------------------------------------// 0088 // ENUMERATIONS 0089 //---------------------------------------------------------------------------// 0090 /*! 0091 * Whether a position is logically "inside" or "outside" a surface. 0092 * 0093 * For a plane, "outside" (true) is the "positive" sense and equivalent to 0094 * \f[ 0095 \vec x \cdot \vec n >= 0 0096 * \f] 0097 * and "inside" is to the left of the plane's normal. Likewise, for a 0098 * sphere, "inside" is where the dot product of the position and outward normal 0099 * is negative. 0100 */ 0101 enum class Sense : bool 0102 { 0103 inside, //!< Quadric expression is less than zero 0104 outside, //!< Expression is greater than zero 0105 }; 0106 0107 //---------------------------------------------------------------------------// 0108 /*! 0109 * Enumeration for mapping surface classes to integers. 0110 * 0111 * These are ordered roughly by complexity. The storage requirement for 0112 * corresponding surfaces are: 0113 * - 1 for `p.|sc|c.c`, 0114 * - 3 for `c.`, 0115 * - 4 for `[ps]|k.`, 0116 * - 7 for `sq`, and 0117 * - 10 for `gq`. 0118 * 0119 * See \c orange/surf/SurfaceTypeTraits.hh for how these map to classes. 0120 */ 0121 enum class SurfaceType : unsigned char 0122 { 0123 px, //!< Plane aligned with X axis 0124 py, //!< Plane aligned with Y axis 0125 pz, //!< Plane aligned with Z axis 0126 cxc, //!< Cylinder centered on X axis 0127 cyc, //!< Cylinder centered on Y axis 0128 czc, //!< Cylinder centered on Z axis 0129 sc, //!< Sphere centered at the origin 0130 cx, //!< Cylinder parallel to X axis 0131 cy, //!< Cylinder parallel to Y axis 0132 cz, //!< Cylinder parallel to Z axis 0133 p, //!< General plane 0134 s, //!< Sphere 0135 kx, //!< Cone parallel to X axis 0136 ky, //!< Cone parallel to Y axis 0137 kz, //!< Cone parallel to Z axis 0138 sq, //!< Simple quadric 0139 gq, //!< General quadric 0140 inv, //!< Involute 0141 size_ //!< Sentinel value for number of surface types 0142 }; 0143 0144 //---------------------------------------------------------------------------// 0145 /*! 0146 * Enumeration for mapping transform implementations to integers. 0147 */ 0148 enum class TransformType : unsigned char 0149 { 0150 no_transformation, //!< Identity transform 0151 translation, //!< Translation only 0152 transformation, //!< Translation plus rotation 0153 size_ 0154 }; 0155 0156 //---------------------------------------------------------------------------// 0157 /*! 0158 * Enumeration for type-deleted universe storage. 0159 * 0160 * See \c orange/univ/UniverseTypeTraits.hh for how these map to data and 0161 * classes. 0162 */ 0163 enum class UniverseType : unsigned char 0164 { 0165 simple, 0166 rect_array, 0167 #if 0 0168 hex_array, 0169 dode_array, 0170 ... 0171 #endif 0172 size_ //!< Sentinel value for number of universe types 0173 }; 0174 0175 //---------------------------------------------------------------------------// 0176 /*! 0177 * Evaluated quadric expression allowing for distinct 'on surface' state. 0178 * 0179 * For a plane, "outside" is equivalent to 0180 * \f[ 0181 \vec x \cdot \vec n > 0 0182 * \f] 0183 * and "inside" is to the left of the plane's normal (a negative dot product). 0184 * The exact equality to zero is literally an "edge case" but it can happen 0185 * with inter-universe coincident surfaces as well as carefully placed 0186 * particle sources and ray tracing. 0187 * 0188 * As an implementataion detail, the "on" case is currently *exact*, but future 0189 * changes might increase the width of "on" to a finite but small range 0190 * ("fuzziness"). 0191 */ 0192 enum class SignedSense 0193 { 0194 inside = -1, 0195 on = 0, 0196 outside = 1 0197 }; 0198 0199 //---------------------------------------------------------------------------// 0200 /*! 0201 * When evaluating an intersection, whether the point is on the surface. 0202 * 0203 * This helps eliminate roundoff errors and other arithmetic issues. 0204 */ 0205 enum class SurfaceState : bool 0206 { 0207 off = false, 0208 on = true 0209 }; 0210 0211 //---------------------------------------------------------------------------// 0212 /*! 0213 * When crossing a boundary, whether the track exits the current volume. 0214 * 0215 * This is necessary due to changes in direction on the boundary due to 0216 * magnetic field and/or multiple scattering. We could extend this later to a 0217 * flag set of "volume changed" (internal non-reflective crossing), "direction 0218 * changed" (reflecting/periodic), "position changed" (bump/periodic). 0219 */ 0220 enum class BoundaryResult : bool 0221 { 0222 reentrant = false, 0223 exiting = true 0224 }; 0225 0226 //---------------------------------------------------------------------------// 0227 /*! 0228 * Chirality of a twirly object (currently only Involute). 0229 */ 0230 enum class Chirality : bool 0231 { 0232 left, //!< Sinistral, spiraling counterclockwise 0233 right, //!< Dextral, spiraling clockwise 0234 }; 0235 0236 //---------------------------------------------------------------------------// 0237 /*! 0238 * Volume logic encoding. 0239 * 0240 * This uses an *unscoped* enum inside a *namespace* so that its values can be 0241 * freely intermingled with other integers that represent face IDs. 0242 */ 0243 namespace logic 0244 { 0245 //! Special logical Evaluator tokens. 0246 // The enum values are set to the highest 6 values of logic_int. 0247 enum OperatorToken : logic_int 0248 { 0249 lbegin = logic_int(~logic_int(6)), 0250 lopen = lbegin, //!< Open parenthesis 0251 lclose, //!< Close parenthesis 0252 ltrue, //!< Push 'true' 0253 lor, //!< Binary logical OR 0254 land, //!< Binary logical AND 0255 lnot, //!< Unary negation 0256 lend 0257 }; 0258 } // namespace logic 0259 0260 //---------------------------------------------------------------------------// 0261 /*! 0262 * Masking priority. 0263 * 0264 * This is currently not implemented in GPU ORANGE except for the special 0265 * "background" cell and "exterior". 0266 */ 0267 enum class ZOrder : size_type 0268 { 0269 invalid = 0, //!< Invalid region 0270 background, //!< Implicit fill 0271 media, //!< Material-filled region or array 0272 array, //!< Lattice array of nested arrangement 0273 hole, //!< Another universe masking this one 0274 implicit_exterior = size_type(-2), //!< Exterior in lower universe 0275 exterior = size_type(-1), //!< The global problem boundary 0276 }; 0277 0278 //---------------------------------------------------------------------------// 0279 // STRUCTS 0280 //---------------------------------------------------------------------------// 0281 /*! 0282 * Data specifying a daughter universe embedded in a volume. 0283 */ 0284 struct Daughter 0285 { 0286 UniverseId universe_id; 0287 TransformId transform_id; 0288 }; 0289 0290 //---------------------------------------------------------------------------// 0291 /*! 0292 * Tolerance for construction and runtime bumping. 0293 * 0294 * The relative error is used for comparisons of magnitudes of values, and the 0295 * absolute error provides a lower bound for the comparison tolerance. In most 0296 * cases (see \c SoftEqual, \c BoundingBoxBumper , \c detail::BumpCalculator) 0297 * the tolerance used is a maximum of the absolute error and the 1- or 2-norm 0298 * of some spatial coordinate. In other cases (\c SurfaceSimplifier, \c 0299 * SoftSurfaceEqual) the similarity between surfaces is determined by solving 0300 * for a change in surface coefficients that results in no more than a change 0301 * in \f$ \epsilon \f$ of a particle intercept. A final special case (the \c 0302 * sqrt_quadratic static variable) is used to approximate the degenerate 0303 * condition \f$ a\sim 0\f$ for a particle traveling nearly parallel to a 0304 * quadric surface: see \c CylAligned for a discussion. 0305 * 0306 * The absolute error should typically be constructed from the relative error 0307 * (since computers use floating point precision) and a characteristic length 0308 * scale for the problem being used. For detector/reactor problems the length 0309 * might be ~1 cm, for microbiology it might be ~1 um, and for astronomy might 0310 * be ~1e6 m. 0311 * 0312 * \note For historical reasons, the absolute tolerance used by \c SoftEqual 0313 * defaults to 1/100 of the relative tolerance, whereas with \c Tolerance the 0314 * equivalent behavior is setting a length scale of 0.01. 0315 * 0316 * \todo Move this to a separate file. 0317 */ 0318 template<class T = ::celeritas::real_type> 0319 struct Tolerance 0320 { 0321 using real_type = T; 0322 0323 real_type rel{}; //!< Relative error for differences 0324 real_type abs{}; //!< Absolute error [native length] 0325 0326 //! Intercept tolerance for parallel-to-quadric cases 0327 static CELER_CONSTEXPR_FUNCTION real_type sqrt_quadratic() 0328 { 0329 if constexpr (std::is_same_v<real_type, double>) 0330 return 1e-5; 0331 else if constexpr (std::is_same_v<real_type, float>) 0332 return 5e-2f; 0333 } 0334 0335 //! True if tolerances are valid 0336 CELER_CONSTEXPR_FUNCTION operator bool() const 0337 { 0338 return rel > 0 && rel < 1 && abs > 0; 0339 } 0340 0341 // Construct from the default relative tolerance (sqrt(precision)) 0342 static Tolerance from_default(real_type length = 1); 0343 0344 // Construct from the default "soft equivalence" relative tolerance 0345 static Tolerance from_softequal(); 0346 0347 // Construct from a relative tolerance and a length scale 0348 static Tolerance from_relative(real_type rel, real_type length = 1); 0349 }; 0350 0351 extern template struct Tolerance<float>; 0352 extern template struct Tolerance<double>; 0353 0354 //---------------------------------------------------------------------------// 0355 // HELPER FUNCTIONS (HOST/DEVICE) 0356 //---------------------------------------------------------------------------// 0357 /*! 0358 * Convert a boolean value to a Sense enum. 0359 */ 0360 CELER_CONSTEXPR_FUNCTION Sense to_sense(bool s) 0361 { 0362 return static_cast<Sense>(s); 0363 } 0364 0365 //---------------------------------------------------------------------------// 0366 /*! 0367 * Change the sense across a surface. 0368 */ 0369 [[nodiscard]] CELER_CONSTEXPR_FUNCTION Sense flip_sense(Sense orig) 0370 { 0371 return static_cast<Sense>(!static_cast<bool>(orig)); 0372 } 0373 0374 //---------------------------------------------------------------------------// 0375 /*! 0376 * Change the sense across a surface. 0377 */ 0378 [[nodiscard]] CELER_CONSTEXPR_FUNCTION SignedSense flip_sense(SignedSense orig) 0379 { 0380 using IntT = std::underlying_type_t<SignedSense>; 0381 return static_cast<SignedSense>(-static_cast<IntT>(orig)); 0382 } 0383 0384 //---------------------------------------------------------------------------// 0385 /*! 0386 * Change whether a boundary crossing is reentrant or exiting. 0387 */ 0388 [[nodiscard]] CELER_CONSTEXPR_FUNCTION BoundaryResult 0389 flip_boundary(BoundaryResult orig) 0390 { 0391 return static_cast<BoundaryResult>(!static_cast<bool>(orig)); 0392 } 0393 0394 //---------------------------------------------------------------------------// 0395 /*! 0396 * Evaluate the sense based on the LHS expression of the quadric equation. 0397 * 0398 * This is an optimized jump-free version of: 0399 * \code 0400 return quadric == 0 ? SignedSense::on 0401 : quadric < 0 ? SignedSense::inside 0402 : SignedSense::outside; 0403 * \endcode 0404 * as 0405 * \code 0406 int gz = !(quadric <= 0) ? 1 : 0; 0407 int lz = quadric < 0 ? 1 : 0; 0408 return static_cast<SignedSense>(gz - lz); 0409 * \endcode 0410 * and compressed into a single line. 0411 * 0412 * NaN values are treated as "outside". 0413 */ 0414 [[nodiscard]] CELER_CONSTEXPR_FUNCTION SignedSense 0415 real_to_sense(real_type quadric) 0416 { 0417 return static_cast<SignedSense>(!(quadric <= 0) - (quadric < 0)); 0418 } 0419 0420 //---------------------------------------------------------------------------// 0421 /*! 0422 * Convert a signed sense to a Sense enum. 0423 */ 0424 CELER_CONSTEXPR_FUNCTION Sense to_sense(SignedSense s) 0425 { 0426 return Sense(static_cast<int>(s) >= 0); 0427 } 0428 0429 //---------------------------------------------------------------------------// 0430 /*! 0431 * Convert a signed sense to a surface state. 0432 */ 0433 CELER_CONSTEXPR_FUNCTION SurfaceState to_surface_state(SignedSense s) 0434 { 0435 return s == SignedSense::on ? SurfaceState::on : SurfaceState::off; 0436 } 0437 0438 //---------------------------------------------------------------------------// 0439 /*! 0440 * Sentinel value indicating "no intersection". 0441 * 0442 * \todo There is probably a better place to put this since it's not a "type". 0443 * \todo A value of zero might also work since zero-length steps are 0444 * prohibited. But we'll need custom `min` and `min_element` in that case. 0445 */ 0446 CELER_CONSTEXPR_FUNCTION real_type no_intersection() 0447 { 0448 return numeric_limits<real_type>::infinity(); 0449 } 0450 0451 //---------------------------------------------------------------------------// 0452 /*! 0453 * Return the UniverseId of the highest-level (i.e., root) universe. 0454 */ 0455 CELER_CONSTEXPR_FUNCTION UniverseId top_universe_id() 0456 { 0457 return UniverseId{0}; 0458 } 0459 0460 //---------------------------------------------------------------------------// 0461 namespace logic 0462 { 0463 //! Whether an integer is a special logic token. 0464 CELER_CONSTEXPR_FUNCTION bool is_operator_token(logic_int lv) 0465 { 0466 return (lv >= lbegin); 0467 } 0468 } // namespace logic 0469 0470 //---------------------------------------------------------------------------// 0471 // HELPER FUNCTIONS (HOST) 0472 //---------------------------------------------------------------------------// 0473 //! Get a printable character corresponding to a sense. 0474 inline constexpr char to_char(Sense s) 0475 { 0476 return s == Sense::inside ? '-' : '+'; 0477 } 0478 0479 // Get a string corresponding to a surface type 0480 char const* to_cstring(SurfaceType); 0481 0482 // Get a string corresponding to a transform type 0483 char const* to_cstring(TransformType); 0484 0485 // Get a string corresponding to a signed sense 0486 char const* to_cstring(SignedSense); 0487 0488 // Get a string corresponding to a surface state 0489 inline char const* to_cstring(SurfaceState s) 0490 { 0491 return s == SurfaceState::off ? "off" : "on"; 0492 } 0493 0494 //! Get a printable character corresponding to an operator. 0495 namespace logic 0496 { 0497 inline constexpr char to_char(OperatorToken tok) 0498 { 0499 return is_operator_token(tok) ? "()*|&~"[tok - lbegin] : '\a'; 0500 } 0501 } // namespace logic 0502 0503 // Get a string corresponding to a z ordering 0504 char const* to_cstring(ZOrder); 0505 0506 // Get a printable character corresponding to a z ordering 0507 char to_char(ZOrder z); 0508 0509 // Convert a printable character to a z ordering 0510 ZOrder to_zorder(char c); 0511 0512 //---------------------------------------------------------------------------// 0513 } // namespace celeritas 0514 0515 //---------------------------------------------------------------------------// 0516 // STD::HASH SPECIALIZATION FOR HOST CODE 0517 //---------------------------------------------------------------------------// 0518 //! \cond 0519 namespace std 0520 { 0521 //! Specialization for std::hash for unordered storage. 0522 template<> 0523 struct hash<celeritas::Sense> 0524 { 0525 using argument_type = celeritas::Sense; 0526 using result_type = std::size_t; 0527 result_type operator()(argument_type const& sense) const noexcept 0528 { 0529 return std::hash<bool>()(static_cast<bool>(sense)); 0530 } 0531 }; 0532 } // namespace std 0533 //! \endcond
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |