Back to home page

EIC code displayed by LXR

 
 

    


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

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