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/VolumeView.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "corecel/cont/Span.hh"
0011 #include "corecel/data/Collection.hh"
0012 #include "corecel/math/Algorithms.hh"
0013 #include "orange/OrangeData.hh"
0014 #include "orange/OrangeTypes.hh"
0015 
0016 namespace celeritas
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Access data about a single volume.
0021  *
0022  * A volume is a CSG tree of surfaces. The sorted, unique surface IDs
0023  * comprising the volume are "faces" and can be indexed as part of this volume
0024  * using the \c FaceId.
0025  *
0026  * Each surface defines an "inside" space and "outside" space that correspond
0027  * to "negative" and "positive" values of the quadric expression's evaluation.
0028  * Left of a plane is negative, for example, and evaluates to "false" or
0029  * "inside" or "negative". The CSG tree is encoded into a vector of Reverse
0030  * Polish Notation-type operations (push, negate, and, or) that is evaluated at
0031  * tracking time to determine whether a particle is inside the volume. The
0032  * encoded set of operations is the \c logic accessor.
0033  */
0034 class VolumeView
0035 {
0036   public:
0037     //@{
0038     //! Type aliases
0039     using ParamsRef = NativeCRef<OrangeParamsData>;
0040     //@}
0041 
0042   public:
0043     // Construct with reference to persistent data
0044     inline CELER_FUNCTION VolumeView(ParamsRef const& params,
0045                                      SimpleUnitRecord const& unit_record,
0046                                      LocalVolumeId id);
0047 
0048     //// ACCESSORS ////
0049 
0050     // Number of surfaces bounding this volume
0051     CELER_FORCEINLINE_FUNCTION FaceId::size_type num_faces() const;
0052 
0053     // Get surface ID for a single face
0054     inline CELER_FUNCTION LocalSurfaceId get_surface(FaceId id) const;
0055 
0056     // Get the face ID of a surface if present
0057     inline CELER_FUNCTION FaceId find_face(LocalSurfaceId id) const;
0058 
0059     // Get all surface IDs for the volume
0060     CELER_FORCEINLINE_FUNCTION LdgSpan<LocalSurfaceId const> faces() const;
0061 
0062     // Get logic definition
0063     CELER_FORCEINLINE_FUNCTION LdgSpan<logic_int const> logic() const;
0064 
0065     // Get the number of total intersections
0066     CELER_FORCEINLINE_FUNCTION logic_int max_intersections() const;
0067 
0068     // Whether the volume has internal surface crossings
0069     CELER_FORCEINLINE_FUNCTION bool internal_surfaces() const;
0070 
0071     // Whether the volume is an "implicit complement"
0072     CELER_FORCEINLINE_FUNCTION bool implicit_vol() const;
0073 
0074     // Whether the safety distance can be calculated with the simple algorithm
0075     CELER_FORCEINLINE_FUNCTION bool simple_safety() const;
0076 
0077     // Whether the intersection is the closest interior surface
0078     CELER_FORCEINLINE_FUNCTION bool simple_intersection() const;
0079 
0080   private:
0081     ParamsRef const& params_;
0082     VolumeRecord const& def_;
0083 
0084     static inline CELER_FUNCTION VolumeRecord const&
0085     volume_record(ParamsRef const&,
0086                   SimpleUnitRecord const& unit_record,
0087                   LocalVolumeId id);
0088 };
0089 
0090 //---------------------------------------------------------------------------//
0091 /*!
0092  * Construct with reference to persistent data.
0093  */
0094 CELER_FUNCTION
0095 VolumeView::VolumeView(ParamsRef const& params,
0096                        SimpleUnitRecord const& unit_record,
0097                        LocalVolumeId id)
0098     : params_(params), def_(VolumeView::volume_record(params, unit_record, id))
0099 {
0100 }
0101 
0102 //---------------------------------------------------------------------------//
0103 /*!
0104  * Number of surfaces bounding this volume.
0105  */
0106 CELER_FUNCTION FaceId::size_type VolumeView::num_faces() const
0107 {
0108     return def_.faces.size();
0109 }
0110 
0111 //---------------------------------------------------------------------------//
0112 /*!
0113  * Get the surface ID for a single face.
0114  *
0115  * This is an O(1) operation.
0116  */
0117 CELER_FUNCTION LocalSurfaceId VolumeView::get_surface(FaceId id) const
0118 {
0119     CELER_EXPECT(id < this->num_faces());
0120     auto offset = def_.faces.begin()->unchecked_get();
0121     offset += id.unchecked_get();
0122     return params_.local_surface_ids[ItemId<LocalSurfaceId>(offset)];
0123 }
0124 
0125 //---------------------------------------------------------------------------//
0126 /*!
0127  * Find the face ID of a surface.
0128  *
0129  * - A non-empty surface ID that's among the faces in this volume will return
0130  *   the face ID, which is just the index of the surface ID in the list of
0131  *   local faces.
0132  * - If the given surface is not present in the volume, the result will be
0133  * false.
0134  *
0135  * This is an O(log(num_faces)) operation.
0136  */
0137 CELER_FUNCTION FaceId VolumeView::find_face(LocalSurfaceId surface) const
0138 {
0139     CELER_EXPECT(surface);
0140     auto surface_list = this->faces();
0141     auto iter = lower_bound(surface_list.begin(), surface_list.end(), surface);
0142     if (iter == surface_list.end() || *iter != surface)
0143     {
0144         // Not found
0145         return {};
0146     }
0147 
0148     FaceId result(iter - surface_list.begin());
0149     CELER_ENSURE(result < this->num_faces());
0150     return result;
0151 }
0152 
0153 //---------------------------------------------------------------------------//
0154 /*!
0155  * Get all the surface IDs corresponding to the faces of this volume.
0156  */
0157 CELER_FUNCTION LdgSpan<LocalSurfaceId const> VolumeView::faces() const
0158 {
0159     return params_.local_surface_ids[def_.faces];
0160 }
0161 
0162 //---------------------------------------------------------------------------//
0163 /*!
0164  * Get logic definition.
0165  */
0166 CELER_FUNCTION LdgSpan<logic_int const> VolumeView::logic() const
0167 {
0168     return params_.logic_ints[def_.logic];
0169 }
0170 
0171 //---------------------------------------------------------------------------//
0172 /*!
0173  * Get the maximum number of surface intersections.
0174  */
0175 CELER_FUNCTION logic_int VolumeView::max_intersections() const
0176 {
0177     return def_.max_intersections;
0178 }
0179 
0180 //---------------------------------------------------------------------------//
0181 /*!
0182  * Whether the volume has internal surface crossings.
0183  */
0184 CELER_FUNCTION bool VolumeView::internal_surfaces() const
0185 {
0186     return def_.flags & VolumeRecord::internal_surfaces;
0187 }
0188 
0189 //---------------------------------------------------------------------------//
0190 /*!
0191  * Whether the volume is an "implicit complement".
0192  */
0193 CELER_FUNCTION bool VolumeView::implicit_vol() const
0194 {
0195     return def_.flags & VolumeRecord::implicit_vol;
0196 }
0197 
0198 //---------------------------------------------------------------------------//
0199 /*!
0200  * Whether the safety distance can be calculated with the simple algorithm.
0201  */
0202 CELER_FUNCTION bool VolumeView::simple_safety() const
0203 {
0204     return def_.flags & VolumeRecord::simple_safety;
0205 }
0206 
0207 //---------------------------------------------------------------------------//
0208 /*!
0209  * Whether the intersection is the closest interior surface.
0210  */
0211 CELER_FUNCTION bool VolumeView::simple_intersection() const
0212 {
0213     return !(def_.flags
0214              & (VolumeRecord::internal_surfaces | VolumeRecord::implicit_vol));
0215 }
0216 
0217 //---------------------------------------------------------------------------//
0218 /*!
0219  * Get the volume record data for the current volume.
0220  *
0221  * This is called during construction.
0222  */
0223 inline CELER_FUNCTION VolumeRecord const&
0224 VolumeView::volume_record(ParamsRef const& params,
0225                           SimpleUnitRecord const& unit,
0226                           LocalVolumeId local_vol_id)
0227 {
0228     CELER_EXPECT(local_vol_id < unit.volumes.size());
0229     return params.volume_records[unit.volumes[local_vol_id]];
0230 }
0231 
0232 //---------------------------------------------------------------------------//
0233 }  // namespace celeritas