Back to home page

EIC code displayed by LXR

 
 

    


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