Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-10 10:11:50

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 geocel/VolumeSurfaceView.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Assert.hh"
0010 #include "corecel/Macros.hh"
0011 #include "corecel/Types.hh"
0012 #include "corecel/data/Collection.hh"
0013 #include "corecel/math/Algorithms.hh"
0014 #include "geocel/Types.hh"
0015 
0016 #include "SurfaceData.hh"
0017 
0018 namespace celeritas
0019 {
0020 //---------------------------------------------------------------------------//
0021 /*!
0022  * Access surface properties attached to a volume.
0023  *
0024  * This class provides a view into surface data for a specific volume, usually
0025  * an exiting volume, allowing access to its optional boundary surfaces
0026  * (surrounding the entire volume) and optional interface surfaces to an
0027  * adjacent volume.
0028  */
0029 class VolumeSurfaceView
0030 {
0031   public:
0032     //!@{
0033     //! \name Type aliases
0034     using SurfaceParamsRef = NativeCRef<SurfaceParamsData>;
0035     //!@}
0036 
0037   public:
0038     // Construct from params and pre-step volume ID
0039     inline CELER_FUNCTION
0040     VolumeSurfaceView(SurfaceParamsRef const& params, VolumeId id);
0041 
0042     // ID of the Volume
0043     CELER_FORCEINLINE_FUNCTION VolumeId volume_id() const;
0044 
0045     // ID of the boundary surface for this volume, if any
0046     CELER_FORCEINLINE_FUNCTION SurfaceId boundary_id() const;
0047 
0048     // Check if this volume has least one interface surface
0049     CELER_FORCEINLINE_FUNCTION bool has_interface() const;
0050 
0051     // Find surface ID for a transition to another volume instance
0052     inline CELER_FUNCTION SurfaceId
0053     find_interface(VolumeInstanceId pre_id, VolumeInstanceId post_id) const;
0054 
0055   private:
0056     SurfaceParamsRef const& params_;
0057     VolumeId volume_;
0058 
0059     // HELPER FUNCTIONS
0060 
0061     CELER_FORCEINLINE_FUNCTION VolumeSurfaceRecord const& volume_record() const;
0062 };
0063 
0064 //---------------------------------------------------------------------------//
0065 // INLINE DEFINITIONS
0066 //---------------------------------------------------------------------------//
0067 /*!
0068  * Construct from surface parameters and volume ID.
0069  */
0070 CELER_FUNCTION
0071 VolumeSurfaceView::VolumeSurfaceView(SurfaceParamsRef const& params,
0072                                      VolumeId id)
0073     : params_(params), volume_(id)
0074 {
0075     CELER_EXPECT(id < params.volume_surfaces.size());
0076 }
0077 
0078 //---------------------------------------------------------------------------//
0079 /*!
0080  * Get the volume ID being viewed.
0081  */
0082 CELER_FUNCTION auto VolumeSurfaceView::volume_id() const -> VolumeId
0083 {
0084     return volume_;
0085 }
0086 
0087 //---------------------------------------------------------------------------//
0088 /*!
0089  * Get the optional boundary surface ID for this volume.
0090 
0091  * If the result is null, no boundary surface is present.
0092  */
0093 CELER_FUNCTION SurfaceId VolumeSurfaceView::boundary_id() const
0094 {
0095     return this->volume_record().boundary;
0096 }
0097 
0098 //---------------------------------------------------------------------------//
0099 /*!
0100  * Check if this volume has at least one interface surface.
0101  */
0102 CELER_FUNCTION bool VolumeSurfaceView::has_interface() const
0103 {
0104     return !this->volume_record().surface.empty();
0105 }
0106 
0107 //---------------------------------------------------------------------------//
0108 /*!
0109  * Find the surface ID for a transition between volume instances.
0110  *
0111  * This searches for the surface ID associated with a pre->post
0112  * volume instance transition.
0113  *
0114  * \todo The current implementation uses linear search, which is unsuitable for
0115  * complex detectors such as LHCB's RICH, whose pvRichGrandPMTQuartz has 770
0116  * specific interfaces. We should either implement an \c equal_range function
0117  * for searching these sorted arrays, or (better) use a hash lookup for {pre,
0118  * post} -> surface.
0119  *
0120  * \return The surface ID if found, or an invalid ID if not found.
0121  */
0122 CELER_FUNCTION SurfaceId VolumeSurfaceView::find_interface(
0123     VolumeInstanceId pre_id, VolumeInstanceId post_id) const
0124 {
0125     auto const& record = this->volume_record();
0126     auto get_volinst_id
0127         = [this](auto item) { return params_.volume_instance_ids[item]; };
0128     for (size_type index = 0; index < record.interface_pre.size(); ++index)
0129     {
0130         {
0131             VolumeInstanceId cur_pre_id
0132                 = get_volinst_id(record.interface_pre[index]);
0133             if (pre_id < cur_pre_id)
0134             {
0135                 // Past range of pre-step IDs: volume isn't in array
0136                 break;
0137             }
0138             else if (cur_pre_id < pre_id)
0139             {
0140                 // Before range; keep going
0141                 continue;
0142             }
0143         }
0144         {
0145             VolumeInstanceId cur_post_id
0146                 = get_volinst_id(record.interface_post[index]);
0147             if (post_id < cur_post_id)
0148             {
0149                 // Past range of post-step IDs
0150                 break;
0151             }
0152             else if (cur_post_id < post_id)
0153             {
0154                 // Before range; keep going
0155                 continue;
0156             }
0157         }
0158         // Pre and post now match
0159         CELER_ASSERT(index < record.surface.size());
0160         auto surf_id_offset = record.surface[index];
0161         CELER_ASSERT(surf_id_offset < params_.surface_ids.size());
0162         auto result = params_.surface_ids[surf_id_offset];
0163         CELER_ENSURE(result);
0164         return result;
0165     }
0166     return {};
0167 }
0168 
0169 //---------------------------------------------------------------------------//
0170 // PRIVATE METHODS
0171 //---------------------------------------------------------------------------//
0172 /*!
0173  * Get the volume surface record for the current volume.
0174  */
0175 CELER_FUNCTION VolumeSurfaceRecord const&
0176 VolumeSurfaceView::volume_record() const
0177 {
0178     return params_.volume_surfaces[volume_];
0179 }
0180 
0181 //---------------------------------------------------------------------------//
0182 }  // namespace celeritas