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