Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-13 10:48:10

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