File indexing completed on 2025-09-18 09:24:48
0001
0002
0003
0004
0005
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
0024
0025
0026
0027 class UniverseIndexer
0028 {
0029 public:
0030
0031
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
0050 explicit inline CELER_FUNCTION
0051 UniverseIndexer(UniverseIndexerDataRef const& data);
0052
0053
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
0060 inline CELER_FUNCTION LocalSurface local_surface(SurfaceId id) const;
0061 inline CELER_FUNCTION LocalVolume local_volume(VolumeId id) const;
0062
0063
0064 CELER_FUNCTION size_type num_universes() const
0065 {
0066 return data_.surfaces.size() - 1;
0067 }
0068
0069
0070 CELER_FUNCTION size_type num_surfaces() const
0071 {
0072 return data_.surfaces[AllVals{}].back();
0073 }
0074
0075
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
0089 UniverseIndexerDataRef data_;
0090
0091
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
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
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
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
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
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
0173
0174
0175
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
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
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 }
0208 }