Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:24:53

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