File indexing completed on 2026-08-25 09:25:28
0001
0002
0003
0004
0005 #ifndef VECGEOM_NAVIGATION_NAVSTATEPATH_H_
0006 #define VECGEOM_NAVIGATION_NAVSTATEPATH_H_
0007
0008 #include "VecGeom/base/Config.h"
0009
0010 #include "VecGeom/base/VariableSizeObj.h"
0011 #include "VecGeom/base/Transformation3D.h"
0012 #include "VecGeom/volumes/PlacedVolume.h"
0013 #include "VecGeom/management/GeoManager.h"
0014 #ifdef VECGEOM_ENABLE_CUDA
0015 #include "VecGeom/management/CudaManager.h"
0016 #endif
0017 #include "VecGeom/base/Global.h"
0018
0019 #include <iostream>
0020 #include <string>
0021
0022 class TGeoBranchArray;
0023
0024
0025
0026
0027 #if __GNUC__ < 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)
0028
0029 #pragma GCC diagnostic push
0030 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
0031 #pragma GCC diagnostic ignored "-Weffc++"
0032 #define GCC_DIAG_POP_NEEDED
0033 #endif
0034
0035 namespace vecgeom {
0036 inline namespace VECGEOM_IMPL_NAMESPACE {
0037
0038
0039
0040
0041
0042
0043 #ifdef VECGEOM_USE_INDEXEDNAVSTATES
0044
0045 typedef unsigned long NavStateIndex_t;
0046 #else
0047 typedef VPlacedVolume const *NavStateIndex_t;
0048 #endif
0049
0050
0051
0052
0053
0054 template <typename T>
0055 struct Index2PVolumeConverter {
0056 VECCORE_ATT_HOST_DEVICE
0057 VECGEOM_FORCE_INLINE
0058 static VPlacedVolume const *ToPlacedVolume(T index)
0059 {
0060 #ifdef VECCORE_CUDA_DEVICE_COMPILATION
0061
0062
0063 VECGEOM_ASSERT(vecgeom::globaldevicegeomdata::gCompactPlacedVolBuffer != nullptr);
0064 return &vecgeom::globaldevicegeomdata::gCompactPlacedVolBuffer[index];
0065 #else
0066 #ifndef VECCORE_CUDA
0067 VECGEOM_ASSERT(vecgeom::GeoManager::gCompactPlacedVolBuffer == nullptr ||
0068 vecgeom::GeoManager::gCompactPlacedVolBuffer[index].id() == index);
0069 return &vecgeom::GeoManager::gCompactPlacedVolBuffer[index];
0070 #else
0071
0072
0073 VECGEOM_VALIDATE(false, << "reached unimplement code");
0074 (void)index;
0075 return nullptr;
0076 #endif
0077 #endif
0078 }
0079
0080 VECCORE_ATT_HOST_DEVICE
0081 VECGEOM_FORCE_INLINE
0082 static T ToIndex(VPlacedVolume const *pvol) { return pvol->id(); }
0083 };
0084
0085
0086 template <>
0087 struct Index2PVolumeConverter<VPlacedVolume const *> {
0088 VECCORE_ATT_HOST_DEVICE
0089 VECGEOM_FORCE_INLINE
0090 static VPlacedVolume const *ToPlacedVolume(VPlacedVolume const *pvol) { return pvol; }
0091 VECCORE_ATT_HOST_DEVICE
0092 VECGEOM_FORCE_INLINE
0093 static VPlacedVolume const *ToIndex(VPlacedVolume const *pvol) { return pvol; }
0094 };
0095
0096
0097
0098
0099
0100 class NavStatePath : protected VariableSizeObjectInterface<NavStatePath, NavStateIndex_t>,
0101 private Index2PVolumeConverter<NavStateIndex_t> {
0102 public:
0103 using Value_t = NavStateIndex_t;
0104 using Base_t = VariableSizeObjectInterface<NavStatePath, Value_t>;
0105 using VariableData_t = VariableSizeObj<Value_t>;
0106
0107 private:
0108 friend Base_t;
0109
0110
0111 VECCORE_ATT_HOST_DEVICE
0112 VariableData_t &GetVariableData() { return fPath; }
0113 VECCORE_ATT_HOST_DEVICE
0114 const VariableData_t &GetVariableData() const { return fPath; }
0115
0116 unsigned char
0117 fCurrentLevel;
0118
0119
0120
0121
0122
0123 short fCache;
0124
0125 bool fOnBoundary;
0126
0127 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0128
0129 bool fCacheM = true;
0130 Transformation3D fTopTrans;
0131 #endif
0132
0133
0134 VariableSizeObj<Value_t> fPath;
0135
0136
0137
0138 VECGEOM_FORCE_INLINE
0139 VECCORE_ATT_HOST_DEVICE
0140 NavStatePath(size_t nvalues);
0141
0142 VECGEOM_FORCE_INLINE
0143 VECCORE_ATT_HOST_DEVICE
0144 NavStatePath(size_t new_size, NavStatePath &other)
0145 : fCurrentLevel(other.fCurrentLevel), fCache(-1), fOnBoundary(other.fOnBoundary),
0146 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0147 fCacheM(other.fCacheM), fTopTrans(other.fTopTrans),
0148 #endif
0149 fPath(new_size, other.fPath)
0150 {
0151
0152
0153
0154
0155
0156 if (new_size > other.fPath.fN) {
0157 memset(fPath.GetValues() + other.fPath.fN, 0, new_size - other.fPath.fN);
0158 }
0159 }
0160
0161
0162 VECGEOM_FORCE_INLINE
0163 VECCORE_ATT_HOST_DEVICE
0164 void InitInternalStorage();
0165
0166 private:
0167
0168
0169
0170 const void *DataStart() const { return (const void *)&fCurrentLevel; }
0171 const void *ObjectStart() const { return (const void *)this; }
0172 void *DataStart() { return (void *)&fCurrentLevel; }
0173 void *ObjectStart() { return (void *)this; }
0174
0175
0176 size_t DataSize() const { return SizeOf() + (size_t)ObjectStart() - (size_t)DataStart(); }
0177
0178 public:
0179
0180
0181
0182 void ConvertToGPUPointers();
0183
0184
0185
0186
0187 void ConvertToCPUPointers();
0188
0189
0190 using Base_t::MakeCopy;
0191 using Base_t::MakeCopyAt;
0192 using Base_t::ReleaseInstance;
0193 using Base_t::SizeOf;
0194 using Base_t::SizeOfAlignAware;
0195
0196
0197
0198 using Index2PVolumeConverter<NavStateIndex_t>::ToIndex;
0199 using Index2PVolumeConverter<NavStateIndex_t>::ToPlacedVolume;
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 VECCORE_ATT_HOST_DEVICE
0211 static NavStatePath *MakeInstance(int maxlevel)
0212 {
0213
0214 return Base_t::MakeInstance(maxlevel + 1);
0215 }
0216
0217 VECCORE_ATT_HOST_DEVICE
0218 static NavStatePath *MakeInstanceAt(int maxlevel, void *addr)
0219 {
0220
0221 return Base_t::MakeInstanceAt(maxlevel + 1, addr);
0222 }
0223
0224
0225
0226 VECCORE_ATT_HOST_DEVICE
0227 static size_t SizeOfInstance(int maxlevel)
0228 {
0229
0230 return VariableSizeObjectInterface::SizeOf(maxlevel + 1);
0231 }
0232
0233
0234
0235
0236 VECCORE_ATT_HOST_DEVICE
0237 static size_t SizeOfInstanceAlignAware(int maxlevel)
0238 {
0239
0240 return VariableSizeObjectInterface::SizeOfAlignAware(maxlevel + 1);
0241 }
0242
0243 VECCORE_ATT_HOST_DEVICE
0244 int GetObjectSize() const { return SizeOf(GetMaxLevel()); }
0245
0246 VECCORE_ATT_HOST_DEVICE
0247 int SizeOf() const { return NavStatePath::SizeOfInstance(GetMaxLevel()); }
0248
0249 VECGEOM_FORCE_INLINE
0250 VECCORE_ATT_HOST_DEVICE
0251 NavStatePath &operator=(NavStatePath const &rhs);
0252
0253
0254
0255
0256 void GetPathAsListOfIndices(std::list<uint> &indices) const;
0257 void ResetPathFromListOfIndices(VPlacedVolume const *world, std::list<uint> const &indices);
0258
0259 VECCORE_ATT_HOST_DEVICE
0260 void CopyTo(NavStatePath *other) const
0261 {
0262
0263
0264
0265
0266 bool alloc = other->fPath.fSelfAlloc;
0267
0268
0269
0270
0271
0272 std::memcpy(static_cast<void *>(other), this, NavStatePath::SizeOfInstance(this->GetCurrentLevel()));
0273
0274 other->fPath.fSelfAlloc = alloc;
0275 }
0276
0277
0278
0279
0280 template <size_t N>
0281 void CopyToFixedSize(NavStatePath *other) const
0282 {
0283 bool alloc = other->fPath.fSelfAlloc;
0284 for (size_t i = 0; i < N; ++i) {
0285 ((char *)other)[i] = ((char *)this)[i];
0286 }
0287 other->fPath.fSelfAlloc = alloc;
0288 }
0289
0290 VECGEOM_FORCE_INLINE
0291 VECCORE_ATT_HOST_DEVICE
0292 ~NavStatePath();
0293
0294
0295
0296 VECGEOM_FORCE_INLINE
0297 VECCORE_ATT_HOST_DEVICE
0298 unsigned char GetMaxLevel() const { return fPath.fN - 1; }
0299
0300 VECGEOM_FORCE_INLINE
0301 VECCORE_ATT_HOST_DEVICE
0302 unsigned char GetCurrentLevel() const { return fCurrentLevel; }
0303
0304 VECGEOM_FORCE_INLINE
0305 VECCORE_ATT_HOST_DEVICE
0306 VPlacedVolume const *GetLastExited() const
0307 {
0308
0309
0310
0311
0312 return nullptr;
0313 }
0314
0315 VECGEOM_FORCE_INLINE
0316 VECCORE_ATT_HOST_DEVICE
0317 void SetLastExited() {}
0318
0319
0320 VECGEOM_FORCE_INLINE
0321 VECCORE_ATT_HOST_DEVICE
0322 void Push(VPlacedVolume const *);
0323
0324
0325 VECGEOM_FORCE_INLINE
0326 VECCORE_ATT_HOST_DEVICE
0327 void Push(unsigned short);
0328
0329
0330 VECGEOM_FORCE_INLINE
0331 VECCORE_ATT_HOST_DEVICE
0332 void PushIndexType(NavStateIndex_t);
0333
0334 VECGEOM_FORCE_INLINE
0335 VECCORE_ATT_HOST_DEVICE
0336 VPlacedVolume const *Top() const;
0337
0338 VECGEOM_FORCE_INLINE
0339 VECCORE_ATT_HOST_DEVICE
0340 VPlacedVolume const *At(int level) const { return ToPlacedVolume(fPath[level]); }
0341
0342 VECGEOM_FORCE_INLINE
0343 VECCORE_ATT_HOST_DEVICE
0344 Value_t ValueAt(int level) const { return fPath[level]; }
0345
0346
0347
0348
0349 VECGEOM_FORCE_INLINE
0350 VECCORE_ATT_HOST_DEVICE
0351 void SetValueAt(int level, Value_t v) { fPath[level] = v; }
0352
0353 VECGEOM_FORCE_INLINE
0354 VECCORE_ATT_HOST_DEVICE
0355 void TopMatrix(Transformation3D &) const;
0356
0357 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0358
0359 VECGEOM_FORCE_INLINE
0360 VECCORE_ATT_HOST_DEVICE
0361 void UpdateTopMatrix(Transformation3D *top_matrix = nullptr);
0362 #endif
0363
0364
0365
0366
0367 VECCORE_ATT_HOST_DEVICE
0368 void DeltaTransformation(NavStatePath const &other, Transformation3D & ) const;
0369
0370
0371 VECCORE_ATT_HOST_DEVICE
0372 Vector3D<Precision> GlobalToLocal(Vector3D<Precision> const &) const;
0373
0374 VECCORE_ATT_HOST_DEVICE
0375 Vector3D<Precision> GlobalToLocal(Vector3D<Precision> const &, int tolevel) const;
0376
0377 VECCORE_ATT_HOST_DEVICE
0378 void TopMatrix(int tolevel, Transformation3D &) const;
0379
0380 VECGEOM_FORCE_INLINE
0381 VECCORE_ATT_HOST_DEVICE
0382 void Pop();
0383
0384 VECGEOM_FORCE_INLINE
0385 VECCORE_ATT_HOST_DEVICE
0386 int Distance(NavStatePath const &) const;
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400 std::string RelativePath(NavStatePath const & ) const;
0401
0402
0403 VECGEOM_FORCE_INLINE
0404 VECCORE_ATT_HOST_DEVICE
0405 void Clear();
0406
0407 VECCORE_ATT_HOST_DEVICE
0408 void Print() const;
0409
0410 VECGEOM_FORCE_INLINE
0411 VECCORE_ATT_HOST_DEVICE
0412 void Dump() const;
0413
0414 VECGEOM_FORCE_INLINE
0415 VECCORE_ATT_HOST_DEVICE
0416 bool HasSamePathAsOther(NavStatePath const &other) const
0417 {
0418 if (other.fCurrentLevel != fCurrentLevel) return false;
0419 for (int i = fCurrentLevel - 1; i >= 0; --i) {
0420 if (fPath[i] != other.fPath[i]) return false;
0421 }
0422 return true;
0423 }
0424
0425 void printValueSequence(std::ostream & = std::cerr) const;
0426
0427
0428
0429 unsigned long getCheckSum() const
0430 {
0431 unsigned long s = 0;
0432 for (int i = 0; i < fCurrentLevel; ++i) {
0433 s += (unsigned long)(ValueAt(i) + 1);
0434 }
0435 return s;
0436 }
0437
0438
0439
0440
0441
0442 VECGEOM_FORCE_INLINE
0443 VECCORE_ATT_HOST_DEVICE
0444 unsigned char GetLevel() const { return fCurrentLevel - 1; }
0445
0446
0447
0448
0449 VECGEOM_FORCE_INLINE
0450 VECCORE_ATT_HOST_DEVICE
0451 bool IsOutside() const { return !(fCurrentLevel > 0); }
0452
0453 VECGEOM_FORCE_INLINE
0454 VECCORE_ATT_HOST_DEVICE
0455 bool IsOnBoundary() const { return fOnBoundary; }
0456
0457 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0458 VECGEOM_FORCE_INLINE
0459 VECCORE_ATT_HOST_DEVICE
0460 bool IsMatrixCached() const { return fCacheM; }
0461 #endif
0462
0463 VECGEOM_FORCE_INLINE
0464 VECCORE_ATT_HOST_DEVICE
0465 void SetBoundaryState(bool b) { fOnBoundary = b; }
0466
0467 VECGEOM_FORCE_INLINE
0468 VECCORE_ATT_HOST_DEVICE
0469 short GetCacheValue() const { return fCache; }
0470
0471 VECGEOM_FORCE_INLINE
0472 VECCORE_ATT_HOST_DEVICE
0473 void SetCacheValue(short v) { fCache = v; }
0474
0475 };
0476
0477 VECCORE_ATT_HOST_DEVICE
0478 NavStatePath &NavStatePath::operator=(NavStatePath const &rhs)
0479 {
0480 if (this != &rhs) {
0481 fCurrentLevel = rhs.fCurrentLevel;
0482 fCache = rhs.fCache;
0483 fOnBoundary = rhs.fOnBoundary;
0484 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0485 fCacheM = rhs.fCacheM;
0486 fTopTrans = rhs.fTopTrans;
0487 #endif
0488
0489 fPath = rhs.fPath;
0490 }
0491 return *this;
0492 }
0493
0494
0495 VECCORE_ATT_HOST_DEVICE
0496 NavStatePath::NavStatePath(size_t nvalues) : fCurrentLevel(0), fCache(-1), fOnBoundary(false), fPath(nvalues)
0497 {
0498
0499 std::memset(fPath.GetValues(), 0, nvalues * sizeof(NavStateIndex_t));
0500 }
0501
0502 VECCORE_ATT_HOST_DEVICE
0503 NavStatePath::~NavStatePath() {}
0504
0505 VECCORE_ATT_HOST_DEVICE
0506 void NavStatePath::Pop()
0507 {
0508 if (fCurrentLevel > 0) {
0509 fCurrentLevel--;
0510
0511
0512 fCache = -1;
0513 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0514 fCacheM = false;
0515 #endif
0516 }
0517 }
0518
0519 VECCORE_ATT_HOST_DEVICE
0520 void NavStatePath::Clear()
0521 {
0522 fCurrentLevel = 0;
0523 fOnBoundary = false;
0524 fCache = -1;
0525 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0526 fCacheM = true;
0527 #endif
0528 }
0529
0530 VECCORE_ATT_HOST_DEVICE
0531 void NavStatePath::Push(VPlacedVolume const *v)
0532 {
0533 #ifdef DEBUG
0534 VECGEOM_ASSERT(fCurrentLevel < GetMaxLevel());
0535 #endif
0536 fPath[fCurrentLevel++] = ToIndex(v);
0537 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0538 fCacheM = false;
0539 #endif
0540 }
0541
0542
0543 VECCORE_ATT_HOST_DEVICE
0544 void NavStatePath::Push(unsigned short child)
0545 {
0546 if (fCurrentLevel > 0) {
0547 auto top = ToPlacedVolume(fPath[fCurrentLevel - 1]);
0548 #ifdef DEBUG
0549 VECGEOM_ASSERT(child < top->GetDaughters().size());
0550 #endif
0551 fPath[fCurrentLevel++] = ToIndex(top->GetDaughters().operator[](child));
0552 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0553 fCacheM = false;
0554 #endif
0555 }
0556 }
0557
0558 VECCORE_ATT_HOST_DEVICE
0559 void NavStatePath::PushIndexType(NavStateIndex_t v)
0560 {
0561 #ifdef DEBUG
0562 VECGEOM_ASSERT(fCurrentLevel < GetMaxLevel());
0563 #endif
0564 fPath[fCurrentLevel++] = v;
0565 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0566 fCacheM = false;
0567 #endif
0568 }
0569
0570 VECCORE_ATT_HOST_DEVICE
0571 VPlacedVolume const *NavStatePath::Top() const
0572 {
0573 return (fCurrentLevel > 0) ? ToPlacedVolume(fPath[fCurrentLevel - 1]) : nullptr;
0574 }
0575
0576
0577
0578
0579 VECGEOM_FORCE_INLINE
0580 VECCORE_ATT_HOST_DEVICE
0581 void NavStatePath::TopMatrix(Transformation3D &global_matrix) const
0582 {
0583
0584 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0585 if (fCacheM) {
0586 global_matrix = fTopTrans;
0587 return;
0588 }
0589 #endif
0590 for (int i = fCurrentLevel - 1; i > 0; --i) {
0591 global_matrix *= *(ToPlacedVolume(fPath[i])->GetTransformation());
0592 }
0593 }
0594
0595 #ifdef VECGEOM_USE_CACHED_TRANSFORMATIONS
0596
0597 VECGEOM_FORCE_INLINE
0598 VECCORE_ATT_HOST_DEVICE
0599 void NavStatePath::UpdateTopMatrix(Transformation3D *top_matrix)
0600 {
0601
0602 if (fCacheM) return;
0603 if (top_matrix) {
0604 fTopTrans = *top_matrix;
0605 } else {
0606
0607 fTopTrans.Clear();
0608 TopMatrix(fTopTrans);
0609 }
0610
0611 fCacheM = true;
0612 }
0613 #endif
0614
0615 VECGEOM_FORCE_INLINE
0616 VECCORE_ATT_HOST_DEVICE
0617 void NavStatePath::Dump() const
0618 {
0619 const unsigned int *ptr = (const unsigned int *)this;
0620 #pragma GCC diagnostic push
0621 #pragma GCC diagnostic ignored "-Wcast-qual"
0622 printf("NavState::Dump(): data: %p(%zu) : %p(%zu) : %p(%zu)\n", (void *)&fCurrentLevel, sizeof(fCurrentLevel),
0623 (void *)&fOnBoundary, sizeof(fOnBoundary), (void *)&fPath, sizeof(fPath));
0624 for (unsigned int i = 0; i < 20; ++i) {
0625 printf("%p: ", (void *)ptr);
0626 for (unsigned int j = 0; j < 8; ++j) {
0627 printf(" %08x ", *ptr);
0628 ptr++;
0629 }
0630 printf("\n");
0631 }
0632 #pragma GCC diagnostic pop
0633 }
0634
0635
0636
0637
0638 inline void NavStatePath::printValueSequence(std::ostream &stream) const
0639 {
0640 for (int i = 0; i < fCurrentLevel; ++i) {
0641 stream << "/" << fPath[i] << "(" << At(i)->GetLabel() << ")";
0642 }
0643 }
0644
0645
0646
0647
0648
0649 VECGEOM_FORCE_INLINE
0650 VECCORE_ATT_HOST_DEVICE
0651 int NavStatePath::Distance(NavStatePath const &other) const
0652 {
0653 int lastcommonlevel = -1;
0654 int maxlevel = Min(GetCurrentLevel(), other.GetCurrentLevel());
0655
0656
0657 for (int i = 0; i < maxlevel; i++) {
0658 if (this->At(i) == other.At(i)) {
0659 lastcommonlevel = i;
0660 } else {
0661 break;
0662 }
0663 }
0664
0665 return (GetCurrentLevel() - lastcommonlevel) + (other.GetCurrentLevel() - lastcommonlevel) - 2;
0666 }
0667
0668 inline void NavStatePath::ConvertToGPUPointers()
0669 {
0670 #if !defined(VECCORE_CUDA) && defined(VECGEOM_ENABLE_CUDA) && !defined(VECGEOM_USE_INDEXEDNAVSTATES)
0671 for (int i = 0; i < fCurrentLevel; ++i) {
0672 auto *pvol = vecgeom::CudaManager::Instance().LookupPlaced(ToPlacedVolume(fPath[i])).GetPtr();
0673 fPath[i] = ToIndex(pvol);
0674 }
0675 #endif
0676 }
0677
0678 inline void NavStatePath::ConvertToCPUPointers()
0679 {
0680 #if !defined(VECCORE_CUDA) && defined(VECGEOM_ENABLE_CUDA) && !defined(VECGEOM_USE_INDEXEDNAVSTATES)
0681 for (int i = 0; i < fCurrentLevel; ++i)
0682 fPath[i] = ToIndex(vecgeom::CudaManager::Instance().LookupPlacedCPUPtr((const void *)ToPlacedVolume(fPath[i])));
0683 #endif
0684 }
0685 }
0686 }
0687
0688 #if defined(GCC_DIAG_POP_NEEDED)
0689 #pragma GCC diagnostic pop
0690 #undef GCC_DIAG_POP_NEEDED
0691 #endif
0692
0693 #endif