Back to home page

EIC code displayed by LXR

 
 

    


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

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/detail/UniverseIndexer.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <vector>
0010 
0011 #include "corecel/data/Collection.hh"
0012 #include "corecel/math/Algorithms.hh"
0013 
0014 #include "../OrangeData.hh"
0015 #include "../OrangeTypes.hh"
0016 
0017 namespace celeritas
0018 {
0019 namespace detail
0020 {
0021 //---------------------------------------------------------------------------//
0022 /*!
0023  * Convert a unit input to params data.
0024  *
0025  * Linearize the data in a UnitInput and add it to the host.
0026  */
0027 class UniverseIndexer
0028 {
0029   public:
0030     //!@{
0031     //! \name Type aliases
0032     using UniverseIndexerDataRef
0033         = UniverseIndexerData<Ownership::const_reference, MemSpace::native>;
0034 
0035     struct LocalSurface
0036     {
0037         UniverseId universe;
0038         LocalSurfaceId surface;
0039     };
0040 
0041     struct LocalVolume
0042     {
0043         UniverseId universe;
0044         LocalVolumeId volume;
0045     };
0046     //!@}
0047 
0048   public:
0049     // Construct from UniverseIndexerData
0050     explicit inline CELER_FUNCTION
0051     UniverseIndexer(UniverseIndexerDataRef const& data);
0052 
0053     // Local-to-global
0054     inline CELER_FUNCTION SurfaceId global_surface(UniverseId uni,
0055                                                    LocalSurfaceId surface) const;
0056     inline CELER_FUNCTION VolumeId global_volume(UniverseId uni,
0057                                                  LocalVolumeId volume) const;
0058 
0059     // Global-to-local
0060     inline CELER_FUNCTION LocalSurface local_surface(SurfaceId id) const;
0061     inline CELER_FUNCTION LocalVolume local_volume(VolumeId id) const;
0062 
0063     //! Total number of universes
0064     CELER_FUNCTION size_type num_universes() const
0065     {
0066         return data_.surfaces.size() - 1;
0067     }
0068 
0069     //! Total number of surfaces
0070     CELER_FUNCTION size_type num_surfaces() const
0071     {
0072         return data_.surfaces[AllVals{}].back();
0073     }
0074 
0075     //! Total number of cells
0076     CELER_FUNCTION size_type num_volumes() const
0077     {
0078         return data_.volumes[AllVals{}].back();
0079     }
0080 
0081   private:
0082     using DataRef
0083         = Collection<size_type, Ownership::const_reference, MemSpace::native>;
0084     using AllVals = AllItems<size_type, MemSpace::native>;
0085     using SizeId = OpaqueId<size_type>;
0086     using SpanIter = typename DataRef::SpanConstT::const_iterator;
0087 
0088     //// DATA ////
0089     UniverseIndexerDataRef data_;
0090 
0091     //// IMPLEMENTATION METHODS ////
0092     static inline CELER_FUNCTION SpanIter find_local(DataRef offsets,
0093                                                      size_type id);
0094     static inline CELER_FUNCTION size_type local_size(DataRef offsets,
0095                                                       UniverseId uni);
0096 };
0097 
0098 //---------------------------------------------------------------------------//
0099 /*!
0100  * Construct from UniverseIndexerData.
0101  */
0102 CELER_FUNCTION
0103 UniverseIndexer::UniverseIndexer(UniverseIndexerDataRef const& data)
0104     : data_(data)
0105 {
0106     CELER_EXPECT(data_.surfaces.size() == data_.volumes.size());
0107     CELER_EXPECT(data_.surfaces[AllVals{}].front() == 0);
0108     CELER_EXPECT(data_.volumes[AllVals{}].front() == 0);
0109 }
0110 
0111 //---------------------------------------------------------------------------//
0112 /*!
0113  * Transform local to global surface ID.
0114  */
0115 CELER_FUNCTION SurfaceId
0116 UniverseIndexer::global_surface(UniverseId uni, LocalSurfaceId surf) const
0117 {
0118     CELER_EXPECT(uni < this->num_universes());
0119     CELER_EXPECT(surf < this->local_size(data_.surfaces, uni));
0120 
0121     return SurfaceId(data_.surfaces[SizeId{uni.unchecked_get()}]
0122                      + surf.unchecked_get());
0123 }
0124 
0125 //---------------------------------------------------------------------------//
0126 /*!
0127  * Transform local to global volume ID.
0128  */
0129 CELER_FUNCTION VolumeId UniverseIndexer::global_volume(UniverseId uni,
0130                                                        LocalVolumeId volume) const
0131 {
0132     CELER_EXPECT(uni < this->num_universes());
0133     CELER_EXPECT(volume < this->local_size(data_.volumes, uni));
0134 
0135     return VolumeId(data_.volumes[SizeId{uni.unchecked_get()}]
0136                     + volume.unchecked_get());
0137 }
0138 
0139 //---------------------------------------------------------------------------//
0140 /*!
0141  * Transform global to local surface ID.
0142  */
0143 CELER_FUNCTION UniverseIndexer::LocalSurface
0144 UniverseIndexer::local_surface(SurfaceId id) const
0145 {
0146     CELER_EXPECT(id < this->num_surfaces());
0147     auto iter = this->find_local(data_.surfaces, id.unchecked_get());
0148 
0149     UniverseId uni(iter - data_.surfaces[AllVals{}].begin());
0150     LocalSurfaceId surface((id - *iter).unchecked_get());
0151     CELER_ENSURE(uni < this->num_universes());
0152     return {uni, surface};
0153 }
0154 
0155 //---------------------------------------------------------------------------//
0156 /*!
0157  * Transform global to local volume ID.
0158  */
0159 CELER_FUNCTION UniverseIndexer::LocalVolume
0160 UniverseIndexer::local_volume(VolumeId id) const
0161 {
0162     CELER_EXPECT(id < this->num_volumes());
0163     auto iter = this->find_local(data_.volumes, id.unchecked_get());
0164 
0165     UniverseId uni(iter - data_.volumes[AllVals{}].begin());
0166     LocalVolumeId volume((id - *iter).unchecked_get());
0167     CELER_ENSURE(uni.get() < this->num_universes());
0168     return {uni, volume};
0169 }
0170 
0171 //---------------------------------------------------------------------------//
0172 // IMPLEMENTATION METHODS
0173 //---------------------------------------------------------------------------//
0174 /*!
0175  * Locate the given ID in the list of offsets.
0176  */
0177 CELER_FUNCTION UniverseIndexer::SpanIter
0178 UniverseIndexer::find_local(DataRef offsets, size_type id)
0179 {
0180     CELER_EXPECT(id < offsets[SizeId{offsets.size() - 1}]);
0181 
0182     // Use upper bound to skip past universes with zero surfaces.
0183     auto iter = upper_bound(
0184         offsets[AllVals{}].begin(), offsets[AllVals{}].end(), id);
0185 
0186     CELER_ASSERT(iter != offsets[AllVals{}].end());
0187     --iter;
0188 
0189     CELER_ENSURE(*iter <= id);
0190     CELER_ENSURE(id < *(iter + 1));
0191     return iter;
0192 }
0193 
0194 //---------------------------------------------------------------------------//
0195 /*!
0196  * Get the number of elements in the given universe.
0197  */
0198 CELER_FUNCTION size_type UniverseIndexer::local_size(DataRef offsets,
0199                                                      UniverseId uni)
0200 {
0201     CELER_EXPECT(uni && uni.unchecked_get() + 1 < offsets.size());
0202     return offsets[SizeId{uni.unchecked_get() + 1}]
0203            - offsets[SizeId{uni.unchecked_get()}];
0204 }
0205 
0206 //---------------------------------------------------------------------------//
0207 }  // namespace detail
0208 }  // namespace celeritas