Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:05:58

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/univ/detail/Types.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "corecel/OpaqueId.hh"
0011 #include "corecel/cont/Span.hh"
0012 #include "orange/OrangeTypes.hh"
0013 
0014 namespace celeritas
0015 {
0016 namespace detail
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Signed surface.
0021  *
0022  * Particles are never allowed to be logically "on" a surface: they must be
0023  * logically on one side or another so that they are in a particular volume.
0024  *
0025  * This class encapsulates the storage of the sense/value: we could try using a
0026  * bit field to compress the ID and sense at the cost of reducing the max
0027  * number of surfaces/faces by a factor of two.
0028  */
0029 template<class IdT>
0030 class OnTface
0031 {
0032   public:
0033     //! Not on a surface
0034     constexpr OnTface() = default;
0035 
0036     //! On a particular side of the given surface (id may be null)
0037     CELER_CONSTEXPR_FUNCTION OnTface(IdT id, Sense sense) noexcept
0038         : id_{id}, sense_{sense}
0039     {
0040     }
0041 
0042     //! Whether we're on a surface
0043     explicit CELER_CONSTEXPR_FUNCTION operator bool() const noexcept
0044     {
0045         return static_cast<bool>(id_);
0046     }
0047 
0048     //! Get the ID of the surface/face (or "null" if not on a face)
0049     CELER_CONSTEXPR_FUNCTION IdT id() const noexcept { return id_; }
0050 
0051     //! Get the sense if we're on a face
0052     CELER_FUNCTION Sense sense() const
0053     {
0054         CELER_EXPECT(*this);
0055         return sense_;
0056     }
0057 
0058     //! Get the sense (unspecified if not on a face, to allow passthrough)
0059     CELER_CONSTEXPR_FUNCTION Sense unchecked_sense() const noexcept
0060     {
0061         return sense_;
0062     }
0063 
0064     //! Reverse the current sense, moving from one side to the other
0065     CELER_FUNCTION void flip_sense()
0066     {
0067         CELER_EXPECT(*this);
0068         sense_ = ::celeritas::flip_sense(sense_);
0069     }
0070 
0071   private:
0072     IdT id_{};
0073     Sense sense_{Sense::inside};
0074 };
0075 
0076 using OnLocalSurface = OnTface<LocalSurfaceId>;
0077 using OnFace = OnTface<FaceId>;
0078 
0079 //---------------------------------------------------------------------------//
0080 /*!
0081  * Distance and next-surface information.
0082  *
0083  * The resulting sense is *before* crossing the boundary (on the current side
0084  * of it).
0085  */
0086 struct Intersection
0087 {
0088     OnLocalSurface surface;
0089     real_type distance = no_intersection();
0090 
0091     //! Whether a next surface has been found
0092     explicit CELER_FUNCTION operator bool() const
0093     {
0094         return static_cast<bool>(surface);
0095     }
0096 };
0097 
0098 //---------------------------------------------------------------------------//
0099 /*!
0100  * Volume ID and surface ID after initialization.
0101  *
0102  * Possible configurations for the initialization result ('X' means 'has
0103  * a valid ID', i.e. evaluates to true):
0104  *
0105  *  Vol   | Surface | Description
0106  * :----: | :-----: | :-------------------------------
0107  *        |         | Failed to find new volume
0108  *        |   X     | Initialized on a surface (reject)
0109  *   X    |         | Initialized
0110  *   X    |   X     | Crossed surface into new volume
0111  */
0112 struct Initialization
0113 {
0114     LocalVolumeId volume;
0115     OnLocalSurface surface;
0116 
0117     //! Whether initialization succeeded
0118     explicit CELER_FUNCTION operator bool() const
0119     {
0120         return static_cast<bool>(volume);
0121     }
0122 };
0123 
0124 //---------------------------------------------------------------------------//
0125 /*!
0126  * Local face IDs, distances, and ordering.
0127  *
0128  * This is temporary space for calculating the distance-to-intersection within
0129  * a volume. The faces and distances are effectively pairs, up to index \c
0130  * size.
0131  *
0132  * The index vector \c isect is initialized with the sequence `[0, size)` to
0133  * allow indirect sorting of the intersections stored in the face/distance
0134  * pairs.
0135  */
0136 struct TempNextFace
0137 {
0138     FaceId* face{nullptr};
0139     real_type* distance{nullptr};
0140     size_type* isect{nullptr};
0141 
0142     size_type size{0};  //!< Maximum number of intersections
0143 
0144     explicit CELER_FORCEINLINE_FUNCTION operator bool() const
0145     {
0146         return static_cast<bool>(face);
0147     }
0148 };
0149 
0150 //---------------------------------------------------------------------------//
0151 /*!
0152  * Access to the local state.
0153  *
0154  * All variables (IDs, position, direction) are *local* to the given tracker.
0155  * Since this is passed by \em value, it is *not* expected to be modified,
0156  * except for the temporary storage references.
0157  *
0158  * The temporary vectors should be sufficient to store all the senses and
0159  * intersections in any volume.
0160  */
0161 struct LocalState
0162 {
0163     Real3 pos;
0164     Real3 dir;
0165     LocalVolumeId volume;
0166     OnLocalSurface surface;
0167     Span<Sense> temp_sense;
0168     TempNextFace temp_next;
0169 };
0170 
0171 //---------------------------------------------------------------------------//
0172 }  // namespace detail
0173 }  // namespace celeritas