File indexing completed on 2026-09-21 09:29:04
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef VECGEOM_MANAGEMENT_NAVINDEXTABLE_H_
0010 #define VECGEOM_MANAGEMENT_NAVINDEXTABLE_H_
0011
0012 #include "VecGeom/management/GeoVisitor.h"
0013 #include "VecGeom/navigation/NavigationState.h"
0014
0015 #include <new>
0016
0017 namespace vecgeom {
0018 inline namespace VECGEOM_IMPL_NAMESPACE {
0019
0020 class NavIndexTable;
0021
0022
0023 class BuildNavIndexVisitor : public GeoVisitorNavIndex {
0024 private:
0025 size_t fTableSize = sizeof(NavIndex_t);
0026 NavIndex_t *fNavInd = nullptr;
0027 int fLimitDepth = 0;
0028 int fError = 0;
0029 NavIndex_t fCurrent = 1;
0030 bool fDoCount = true;
0031 bool fValidate = false;
0032 std::vector<NavIndex_t> fSelectedVolumes;
0033 std::vector<int> fSceneId;
0034 public:
0035 BuildNavIndexVisitor(int depth_limit, bool do_count)
0036 : GeoVisitorNavIndex(), fLimitDepth(depth_limit), fDoCount(do_count)
0037 {
0038 int ntot = GeoManager::Instance().GetRegisteredVolumesCount();
0039 fSelectedVolumes = std::vector<NavIndex_t>(ntot, 0);
0040 fSceneId = std::vector<int>(ntot, 0);
0041 }
0042 int GetError() const { return fError; }
0043 std::vector<NavIndex_t> &GetSelectedVolumes() { return fSelectedVolumes; }
0044 size_t GetTableSize() const { return fTableSize; }
0045 int GetSceneId(int ivol) const { return fSceneId[ivol]; }
0046 void SetSceneId(int ivol, int id) { fSceneId[ivol] = id; }
0047 bool IsSelected(int ivol) const { return fSelectedVolumes[ivol] > 0; }
0048 bool IsVisited(int ivol) const { return fSelectedVolumes[ivol] > 1; }
0049 void SetVisited(int ivol)
0050 {
0051 if (fSelectedVolumes[ivol] == 1) fSelectedVolumes[ivol] = 2;
0052 }
0053
0054 void ResetVisited()
0055 {
0056 std::for_each(fSelectedVolumes.begin(), fSelectedVolumes.end(), [](NavIndex_t &i) {
0057 if (i > 1) i = 1;
0058 });
0059 }
0060
0061 void SetSceneIndex(int ivol, NavIndex_t address) { fSelectedVolumes[ivol] = address; }
0062 NavIndex_t GetSceneIndex(int ivol)
0063 {
0064 auto scene_index = fSelectedVolumes[ivol];
0065 return (scene_index > 2) ? scene_index : 0;
0066 }
0067 void SetTable(NavIndex_t *table) { fNavInd = table; }
0068 void SetDoCount(bool flag) { fDoCount = flag; }
0069 void SetValidate(bool flag) { fValidate = flag; }
0070 std::vector<NavIndex_t> &SelectedVolumes() { return fSelectedVolumes; }
0071
0072
0073
0074
0075
0076
0077
0078
0079 NavIndex_t apply(NavStatePath *state, int level, NavIndex_t mother, int dind, NavIndex_t &id);
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 NavIndex_t apply_tuple(NavStatePath *state, int level, NavIndex_t mother, int dind, NavIndex_t &id, int scene_id,
0091 int new_scene_id);
0092
0093
0094
0095
0096
0097
0098 void NodeReduction(int min_per_scene = 1000);
0099 };
0100
0101 class NavIndexTable {
0102 private:
0103 NavIndex_t *fNavInd = nullptr;
0104 VPlacedVolume *fVolBuffer = nullptr;
0105 NavIndex_t fWorld = 1;
0106 size_t fTableSize = 0;
0107 size_t fDepthLimit = 0;
0108
0109 NavIndexTable(NavIndex_t *table, size_t table_size) : fNavInd(table), fTableSize(table_size) {}
0110
0111 public:
0112 ~NavIndexTable() { CleanTable(); }
0113
0114
0115
0116
0117 static NavIndexTable *Instance(NavIndex_t *nav_table = nullptr, size_t table_size = 0)
0118 {
0119 static NavIndexTable instance(nav_table, table_size);
0120 return &instance;
0121 }
0122
0123
0124 void CleanTable()
0125 {
0126 delete[] fNavInd;
0127 fNavInd = nullptr;
0128 }
0129
0130
0131 VECCORE_ATT_HOST_DEVICE
0132 VECGEOM_FORCE_INLINE
0133 size_t GetTableSize() const { return fTableSize; }
0134
0135
0136 VECCORE_ATT_HOST_DEVICE
0137 VECGEOM_FORCE_INLINE
0138 NavIndex_t *GetTable() const { return fNavInd; }
0139
0140
0141 VECCORE_ATT_HOST_DEVICE
0142 VECGEOM_FORCE_INLINE
0143 void SetVolumeBuffer(VPlacedVolume *buffer) { fVolBuffer = buffer; }
0144
0145
0146 VECCORE_ATT_HOST_DEVICE
0147 VECGEOM_FORCE_INLINE
0148 NavIndex_t GetWorld() const { return fWorld; }
0149
0150
0151
0152
0153 bool AllocateTable(size_t bytes);
0154
0155
0156
0157
0158
0159
0160
0161 bool CreateTable(VPlacedVolume const *top, int maxdepth, int depth_limit, int min_per_scene = 1000);
0162
0163
0164
0165
0166
0167 bool Validate(VPlacedVolume const *top, int maxdepth) const;
0168
0169
0170
0171
0172
0173 NavIndex_t ValidateState(NavStatePath *state, int &error);
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 template <typename Visitor>
0186 static int visitAllPlacedVolumesNavIndex(VPlacedVolume const *currentvolume, Visitor *visitor, NavStatePath *state,
0187 NavIndex_t &id, int level = 0, NavIndex_t mother = 0, int dind = 0)
0188 {
0189 if (currentvolume != NULL) {
0190 state->Push(currentvolume);
0191 NavIndex_t new_mother = visitor->apply(state, level, mother, dind, id);
0192 auto ierr = visitor->GetError();
0193 if (ierr) return ierr;
0194 int size = currentvolume->GetDaughters().size();
0195 for (int i = 0; i < size; ++i) {
0196 ierr = visitAllPlacedVolumesNavIndex(currentvolume->GetDaughters().operator[](i), visitor, state, id, level + 1,
0197 new_mother, i);
0198 if (ierr) return ierr;
0199 }
0200 state->Pop();
0201 }
0202 return 0;
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 template <typename Visitor>
0218 static int visitAllPlacedVolumesNavTuple(VPlacedVolume const *currentvolume, Visitor *visitor, NavStatePath *state,
0219 NavIndex_t &id, int &iscene, int scene_id, int level = 0,
0220 NavIndex_t mother = 0, int dind = 0, bool new_scene = false)
0221 {
0222 if (currentvolume != NULL) {
0223 auto lvol = currentvolume->GetLogicalVolume();
0224 int ivol = lvol->id();
0225 state->Push(currentvolume);
0226 bool selected = visitor->IsSelected(ivol);
0227 bool visited = visitor->IsVisited(ivol);
0228 int new_scene_id = scene_id;
0229
0230 if (selected) {
0231 if (!visited) {
0232 new_scene_id = ++iscene;
0233 visitor->SetSceneId(ivol, new_scene_id);
0234 } else {
0235 new_scene_id = visitor->GetSceneId(ivol);
0236 }
0237 }
0238 NavIndex_t id_bak = id;
0239 NavIndex_t new_mother = visitor->apply_tuple(state, level, mother, dind, id, scene_id, new_scene_id);
0240 auto ierr = visitor->GetError();
0241 if (ierr) return ierr;
0242 if (!visited) {
0243 int size = currentvolume->GetDaughters().size();
0244 NavStatePath *scene_state = nullptr;
0245 if (selected) {
0246 scene_state = NavStatePath::MakeInstance(GeoManager::Instance().getMaxDepth());
0247 scene_state->Push(GeoManager::Instance().GetWorld());
0248 VECGEOM_ASSERT(visitor->IsVisited(ivol));
0249 id = 1;
0250 level = 0;
0251 }
0252 for (int i = 0; i < size; ++i) {
0253 ierr = visitAllPlacedVolumesNavTuple(currentvolume->GetDaughters().operator[](i), visitor,
0254 scene_state ? scene_state : state, id, iscene, new_scene_id, level + 1,
0255 new_mother, i, selected);
0256 if (ierr) return ierr;
0257 }
0258 if (selected) {
0259 NavStatePath::ReleaseInstance(scene_state);
0260 id = ++id_bak;
0261 }
0262 }
0263 state->Pop();
0264 }
0265 return 0;
0266 }
0267 };
0268
0269 }
0270 }
0271
0272 #endif