Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-25 09:32:01

0001 /// \file NavStateIndex
0002 /// \author Andrei Gheata (andrei.gheata@cern.ch)
0003 /// \date 12.03.2014
0004 
0005 #ifndef VECGEOM_NAVIGATION_NAVSTATEINDEX_H_
0006 #define VECGEOM_NAVIGATION_NAVSTATEINDEX_H_
0007 
0008 #include "VecGeom/base/Config.h"
0009 #include "VecGeom/base/Global.h"
0010 #include "VecGeom/base/Transformation3D.h"
0011 #include "VecGeom/base/Transformation3DMP.h"
0012 #include "VecGeom/volumes/PlacedVolume.h"
0013 #include "VecGeom/management/GeoManager.h"
0014 #include "VecGeom/volumes/VolumeTree.h"
0015 #include "VecGeom/management/DeviceGlobals.h"
0016 
0017 #include <iostream>
0018 #include <string>
0019 
0020 class TGeoBranchArray;
0021 
0022 namespace vecgeom {
0023 inline namespace VECGEOM_IMPL_NAMESPACE {
0024 
0025 /**
0026  * A class describing a current geometry state based on a single index
0027  * likely there will be such an object for each particle/track currently treated.
0028  */
0029 class NavStateIndex {
0030 public:
0031   using Value_t = unsigned int;
0032 
0033 private:
0034   NavIndex_t fNavInd     = 0;     ///< Navigation state index
0035   NavIndex_t fLastExited = 0;     ///< Navigation state index of the last exited state
0036   bool fOnBoundary       = false; ///< flag indicating whether track is on boundary of the "Top()" placed volume
0037 
0038 public:
0039   VECCORE_ATT_HOST_DEVICE
0040   NavStateIndex(NavIndex_t nav_ind = 0) { fNavInd = nav_ind; }
0041 
0042   template <typename Container>
0043   VECCORE_ATT_HOST_DEVICE NavStateIndex(Container const *cont)
0044   {
0045     VECGEOM_ASSERT(cont->size() == 1);
0046     fNavInd = (*cont)[0];
0047   }
0048 
0049   VECGEOM_FORCE_INLINE
0050   VECCORE_ATT_HOST_DEVICE
0051   static unsigned char GetMaxLevel()
0052   {
0053 #ifdef VECCORE_CUDA_DEVICE_COMPILATION
0054     return vecgeom::globaldevicegeomdata::gMaxDepth;
0055 #else
0056     return (unsigned char)GeoManager::Instance().getMaxDepth();
0057 #endif
0058   }
0059 
0060   // Static accessors
0061   VECCORE_ATT_HOST_DEVICE
0062   static NavStateIndex *MakeInstance(int)
0063   {
0064     // MaxLevel is 'zero' based (i.e. maxlevel==0 requires one value)
0065     return new NavStateIndex();
0066   }
0067 
0068   VECCORE_ATT_HOST_DEVICE
0069   static NavStateIndex *MakeCopy(NavStateIndex const &other) { return new NavStateIndex(other); }
0070 
0071   VECCORE_ATT_HOST_DEVICE
0072   static NavStateIndex *MakeInstanceAt(int, void *addr) { return new (addr) NavStateIndex(); }
0073 
0074   VECCORE_ATT_HOST_DEVICE
0075   static NavStateIndex *MakeCopy(NavStateIndex const &other, void *addr) { return new (addr) NavStateIndex(other); }
0076 
0077   VECCORE_ATT_HOST_DEVICE
0078   static void ReleaseInstance(NavStateIndex *state)
0079   {
0080     // MaxLevel is 'zero' based (i.e. maxlevel==0 requires one value)
0081     delete state;
0082   }
0083 
0084   // returns the size in bytes of a NavStateIndex object with internal
0085   // path depth maxlevel
0086   VECCORE_ATT_HOST_DEVICE
0087   static size_t SizeOfInstance(int)
0088   {
0089     // MaxLevel is 'zero' based (i.e. maxlevel==0 requires one value)
0090     return sizeof(NavStateIndex);
0091   }
0092 
0093   // returns the size in bytes of a NavStateIndex object with internal
0094   // path depth maxlevel -- including space needed for padding to next aligned object
0095   // of same kind
0096   VECCORE_ATT_HOST_DEVICE
0097   static size_t SizeOfInstanceAlignAware(int)
0098   {
0099     // MaxLevel is 'zero' based (i.e. maxlevel==0 requires one value)
0100     return sizeof(NavStateIndex);
0101   }
0102 
0103   VECCORE_ATT_HOST_DEVICE
0104   VECGEOM_FORCE_INLINE
0105   NavIndex_t GetNavIndex() const { return fNavInd; }
0106 
0107   VECCORE_ATT_HOST_DEVICE
0108   VECGEOM_FORCE_INLINE
0109   NavIndex_t GetState() const { return fNavInd; }
0110 
0111   VECCORE_ATT_HOST_DEVICE
0112   int GetObjectSize() const { return (int)sizeof(NavStateIndex); }
0113 
0114   VECCORE_ATT_HOST_DEVICE
0115   static size_t SizeOf(size_t) { return sizeof(NavStateIndex); }
0116 
0117   VECCORE_ATT_HOST_DEVICE
0118   void CopyTo(NavStateIndex *other) const { *other = *this; }
0119 
0120   // copies a fixed and predetermined number of bytes
0121   // might be useful for specialized navigators which know the depth + SizeOf in advance
0122   // N is number of bytes to be copied and can be obtained by a prior call to constexpr NavStateIndex::SizeOf( ... );
0123   template <size_t N>
0124   void CopyToFixedSize(NavStateIndex *other) const
0125   {
0126     *other = *this;
0127   }
0128 
0129   VECCORE_ATT_HOST_DEVICE
0130   VECGEOM_FORCE_INLINE
0131   static NavIndex_t const *NavIndAddr(NavIndex_t nav_ind)
0132   {
0133 #ifdef VECCORE_CUDA_DEVICE_COMPILATION
0134     // checking here for NVCC_DEVICE since the global variable globaldevicegeomgata::gCompact...
0135     // is marked __device__ and can only be compiled within device compiler passes
0136     VECGEOM_ASSERT(vecgeom::globaldevicegeomdata::gNavIndex != nullptr);
0137     return &vecgeom::globaldevicegeomdata::gNavIndex[nav_ind];
0138 #else
0139     VECGEOM_ASSERT(vecgeom::GeoManager::gNavIndex != nullptr);
0140     return &vecgeom::GeoManager::gNavIndex[nav_ind];
0141 #endif
0142   }
0143 
0144   VECCORE_ATT_HOST_DEVICE
0145   VECGEOM_FORCE_INLINE
0146   static NavIndex_t NavInd(NavIndex_t nav_ind) { return *NavIndAddr(nav_ind); }
0147 
0148   VECCORE_ATT_HOST_DEVICE
0149   VECGEOM_FORCE_INLINE
0150   static VPlacedVolume const *ToPlacedVolume(size_t index)
0151   {
0152 #ifdef VECCORE_CUDA_DEVICE_COMPILATION
0153     // checking here for NVCC_DEVICE since the global variable globaldevicegeomgata::gCompact...
0154     // is marked __device__ and can only be compiled within device compiler passes
0155     VECGEOM_ASSERT(vecgeom::globaldevicegeomdata::gCompactPlacedVolBuffer != nullptr);
0156     return &vecgeom::globaldevicegeomdata::gCompactPlacedVolBuffer[index];
0157 #else
0158     VECGEOM_ASSERT(vecgeom::GeoManager::gCompactPlacedVolBuffer == nullptr ||
0159                    vecgeom::GeoManager::gCompactPlacedVolBuffer[index].id() == index);
0160     return &vecgeom::GeoManager::gCompactPlacedVolBuffer[index];
0161 #endif
0162   }
0163 
0164   VECCORE_ATT_HOST_DEVICE
0165   VECGEOM_FORCE_INLINE
0166   static int WorldId() { return NavInd(3); }
0167 
0168   VECCORE_ATT_HOST_DEVICE
0169   VECGEOM_FORCE_INLINE
0170   static vecgeom::PlacedId const &ToPlacedId(size_t iplaced)
0171   {
0172     return vecgeom::VolumeTree::Instance().fPlaced[iplaced];
0173   }
0174 
0175   VECCORE_ATT_HOST_DEVICE
0176   VECGEOM_FORCE_INLINE
0177   static unsigned short GetNdaughtersImpl(NavIndex_t nav_ind)
0178   {
0179     constexpr unsigned int kOffsetNd = 5 * sizeof(NavIndex_t) + 2;
0180     auto content_nd                  = (unsigned short *)((unsigned char *)(NavIndAddr(nav_ind)) + kOffsetNd);
0181     return *content_nd;
0182   }
0183 
0184   VECGEOM_FORCE_INLINE
0185   VECCORE_ATT_HOST_DEVICE
0186   static unsigned char GetLevelImpl(NavIndex_t nav_ind)
0187   {
0188     constexpr unsigned int kOffsetLevel = 5 * sizeof(NavIndex_t);
0189     auto content_level                  = (unsigned char *)(NavIndAddr(nav_ind)) + kOffsetLevel;
0190     return *content_level;
0191   }
0192 
0193   /// @brief Implementation for getting the scene id for a given navigation index
0194   VECCORE_ATT_HOST_DEVICE
0195   VECGEOM_FORCE_INLINE
0196   static bool GetSceneIdImpl(NavIndex_t const & /*nav_ind*/, unsigned short &scene_id, unsigned short &newscene_id)
0197   {
0198     scene_id = newscene_id = 0;
0199     return false;
0200   }
0201 
0202   VECCORE_ATT_HOST_DEVICE
0203   VECGEOM_FORCE_INLINE
0204   static NavIndex_t GetNavIndexImpl(NavIndex_t nav_ind, int level)
0205   {
0206     int up            = GetLevelImpl(nav_ind) - level;
0207     NavIndex_t mother = nav_ind;
0208     while (mother && up--)
0209       mother = NavInd(mother);
0210     return mother;
0211   }
0212 
0213   VECGEOM_FORCE_INLINE
0214   VECCORE_ATT_HOST_DEVICE
0215   static NavIndex_t GetIdImpl(NavIndex_t nav_ind) { return (nav_ind > 0) ? NavInd(nav_ind + 1) : 0; }
0216 
0217   VECGEOM_FORCE_INLINE
0218   VECCORE_ATT_HOST_DEVICE
0219   static bool IsDescendentImpl(NavIndex_t child_ind, NavIndex_t parent_ind)
0220   {
0221     NavIndex_t ind = child_ind;
0222     while (ind > parent_ind) {
0223       ind = NavInd(ind);
0224       if (ind == parent_ind) return true;
0225     }
0226     return false;
0227   }
0228 
0229   VECGEOM_FORCE_INLINE
0230   VECCORE_ATT_HOST_DEVICE
0231   static unsigned int GetLogicalIdImpl(NavIndex_t nav_ind) { return nav_ind ? NavInd(nav_ind + 4) : 0; }
0232 
0233   /// @brief Implementation for getting the child id for a given navigation index
0234   VECGEOM_FORCE_INLINE
0235   VECCORE_ATT_HOST_DEVICE
0236   static int GetChildIdImpl(NavIndex_t const &nav_index)
0237   {
0238     auto content_ichild = reinterpret_cast<const int *>(NavIndAddr(nav_index + 3));
0239     return *content_ichild;
0240   }
0241 
0242   VECGEOM_FORCE_INLINE
0243   VECCORE_ATT_HOST_DEVICE
0244   static bool IsSceneImpl(NavIndex_t nav_ind) { return nav_ind == 0; }
0245 
0246   VECGEOM_FORCE_INLINE
0247   VECCORE_ATT_HOST_DEVICE
0248   static void PopImpl(NavIndex_t &nav_ind) { nav_ind = (nav_ind > 0) ? NavInd(nav_ind) : 0; }
0249 
0250   VECGEOM_FORCE_INLINE
0251   VECCORE_ATT_HOST_DEVICE
0252   static void PushImpl(NavIndex_t &nav_ind, VPlacedVolume const *v)
0253   {
0254     nav_ind = (nav_ind > 0) ? NavInd(nav_ind + 6 + v->GetChildId()) : 1;
0255   }
0256 
0257   VECGEOM_FORCE_INLINE
0258   VECCORE_ATT_HOST_DEVICE
0259   static NavIndex_t GetChildNavInd(NavIndex_t nav_ind, int ichild)
0260   {
0261     return (nav_ind > 0) ? NavInd(nav_ind + 6 + ichild) : 0;
0262   }
0263 
0264   VECGEOM_FORCE_INLINE
0265   VECCORE_ATT_HOST_DEVICE
0266   static void PushDaughterImpl(NavIndex_t &nav_ind, int idaughter)
0267   {
0268     nav_ind = (nav_ind > 0) ? NavInd(nav_ind + 6 + idaughter) : 1;
0269   }
0270 
0271   VECGEOM_FORCE_INLINE
0272   VECCORE_ATT_HOST_DEVICE
0273   static void PushImpl(NavIndex_t &nav_ind, int iplaced)
0274   {
0275     auto const &pv_ind = ToPlacedId(iplaced);
0276     PushDaughterImpl(nav_ind, pv_ind.fChildId);
0277   }
0278 
0279   VECGEOM_FORCE_INLINE
0280   VECCORE_ATT_HOST_DEVICE
0281   static VPlacedVolume const *TopImpl(NavIndex_t nav_ind)
0282   {
0283     return (nav_ind > 0) ? ToPlacedVolume(NavInd(nav_ind + 2)) : nullptr;
0284   }
0285 
0286   VECGEOM_FORCE_INLINE
0287   VECCORE_ATT_HOST_DEVICE
0288   static VPlacedVolume const *World() { return ToPlacedVolume(NavInd(3)); }
0289 
0290   VECGEOM_FORCE_INLINE
0291   VECCORE_ATT_HOST_DEVICE
0292   static int TopIdImpl(NavIndex_t const &nav_ind) { return (nav_ind > 0) ? int(NavInd(nav_ind + 2)) : -1; }
0293 
0294   template <typename Real_t>
0295   VECCORE_ATT_HOST_DEVICE static void TopMatrixImpl(NavIndex_t nav_ind, Transformation3DMP<Real_t> &trans)
0296   {
0297     constexpr unsigned int kOffsetHasm = 5 * sizeof(NavIndex_t) + 1;
0298 
0299     unsigned char hasm;
0300     while (true) {
0301       if (nav_ind == 0) return;
0302       hasm            = *((unsigned char *)(NavIndAddr(nav_ind)) + kOffsetHasm);
0303       bool has_matrix = (hasm & 0x04) > 0;
0304       if (has_matrix) break;
0305       // note that the surface model should always have a matrix and never do the following multiplication
0306       auto const &t = *TopImpl(nav_ind)->GetTransformation();
0307       trans *= t;
0308       nav_ind = NavInd(nav_ind);
0309     }
0310 
0311     if ((hasm & 0x03) == 0) return;
0312     bool has_trans = (hasm & 0x02) > 0;
0313     bool has_rot   = (hasm & 0x01) > 0;
0314     auto nd        = GetNdaughtersImpl(nav_ind);
0315 
0316     // Potentially skip one NavIndex_t to ensure alignment of transformation data
0317     auto transformationDataIndex     = nav_ind + 6 + nd + ((nd + 1) & 1);
0318     const bool padTransformationData = (transformationDataIndex * sizeof(NavIndex_t)) % sizeof(Precision) != 0;
0319     transformationDataIndex += unsigned{padTransformationData};
0320 
0321     const auto address = reinterpret_cast<const Precision *>(NavIndAddr(transformationDataIndex));
0322     VECGEOM_ASSERT(reinterpret_cast<uintptr_t>(address) % sizeof(Precision) == 0);
0323 
0324     Transformation3DMP<Real_t> t;
0325     t.Set(address, address + 3, has_trans, has_rot);
0326     trans *= t;
0327   }
0328 
0329   VECCORE_ATT_HOST_DEVICE
0330   static void TopMatrixImpl(NavIndex_t nav_ind, Transformation3D &trans)
0331   {
0332     constexpr unsigned int kOffsetHasm = 5 * sizeof(NavIndex_t) + 1;
0333 
0334     unsigned char hasm;
0335     while (true) {
0336       if (nav_ind == 0) return;
0337       hasm            = *((unsigned char *)(NavIndAddr(nav_ind)) + kOffsetHasm);
0338       bool has_matrix = (hasm & 0x04) > 0;
0339       if (has_matrix) break;
0340       auto const &t = *TopImpl(nav_ind)->GetTransformation();
0341       trans *= t;
0342       nav_ind = NavInd(nav_ind);
0343     }
0344 
0345     if ((hasm & 0x03) == 0) return;
0346     bool has_trans = (hasm & 0x02) > 0;
0347     bool has_rot   = (hasm & 0x01) > 0;
0348     auto nd        = GetNdaughtersImpl(nav_ind);
0349 
0350     // Potentially skip one NavIndex_t to ensure alignment of transformation data
0351     auto transformationDataIndex     = nav_ind + 6 + nd + ((nd + 1) & 1);
0352     const bool padTransformationData = (transformationDataIndex * sizeof(NavIndex_t)) % sizeof(Precision) != 0;
0353     transformationDataIndex += unsigned{padTransformationData};
0354 
0355     const auto address = reinterpret_cast<const Precision *>(NavIndAddr(transformationDataIndex));
0356     VECGEOM_ASSERT(reinterpret_cast<uintptr_t>(address) % sizeof(Precision) == 0);
0357 
0358     Transformation3D t;
0359     t.Set(address, address + 3, has_trans, has_rot);
0360     trans *= t;
0361   }
0362 
0363   template <typename Real_t>
0364   VECCORE_ATT_HOST_DEVICE static void TopInSceneMatrixImpl(NavIndex_t nav_ind, Transformation3DMP<Real_t> &trans)
0365   {
0366     // Get transformation of the node in the top scene
0367     TopMatrixImpl(nav_ind, trans);
0368   }
0369 
0370   VECCORE_ATT_HOST_DEVICE
0371   static void TopInSceneMatrixImpl(NavIndex_t nav_ind, Transformation3D &trans)
0372   {
0373     // Get transformation of the node in the top scene
0374     TopMatrixImpl(nav_ind, trans);
0375   }
0376 
0377   template <typename Real_t>
0378   VECCORE_ATT_HOST_DEVICE static void SceneMatrixImpl(NavIndex_t const & /*nav_tuple*/,
0379                                                       Transformation3DMP<Real_t> & /*trans*/)
0380   {
0381   }
0382 
0383   VECCORE_ATT_HOST_DEVICE
0384   static void SceneMatrixImpl(NavIndex_t const & /*nav_tuple*/, Transformation3D & /*trans*/) {}
0385 
0386   template <typename Real_t>
0387   VECCORE_ATT_HOST_DEVICE static Vector3D<Real_t> GlobalToLocalImpl(NavIndex_t nav_ind,
0388                                                                     Vector3D<Real_t> const &globalpoint)
0389   {
0390     Transformation3DMP<Real_t> trans;
0391     TopMatrixImpl(nav_ind, trans);
0392     Vector3D<Real_t> local = trans.Transform(globalpoint);
0393     return local;
0394   }
0395 
0396   VECCORE_ATT_HOST_DEVICE
0397   static Vector3D<Precision> GlobalToLocalImpl(NavIndex_t nav_ind, Vector3D<Precision> const &globalpoint)
0398   {
0399     Transformation3D trans;
0400     TopMatrixImpl(nav_ind, trans);
0401     Vector3D<Precision> local = trans.Transform(globalpoint);
0402     return local;
0403   }
0404 
0405   // Intrerface methods
0406   VECGEOM_FORCE_INLINE
0407   VECCORE_ATT_HOST_DEVICE
0408   VPlacedVolume const *GetLastExited() const { return TopImpl(fLastExited); }
0409 
0410   VECGEOM_FORCE_INLINE
0411   VECCORE_ATT_HOST_DEVICE
0412   NavIndex_t GetLastExitedState() const { return fLastExited; }
0413 
0414   VECGEOM_FORCE_INLINE
0415   VECCORE_ATT_HOST_DEVICE
0416   int GetLastIdExited() const { return TopIdImpl(fLastExited); }
0417 
0418   VECGEOM_FORCE_INLINE
0419   VECCORE_ATT_HOST_DEVICE
0420   void SetLastExited() { fLastExited = fNavInd; }
0421 
0422   VECGEOM_FORCE_INLINE
0423   VECCORE_ATT_HOST_DEVICE
0424   void SetLastExited(NavIndex_t const &navind) { fLastExited = navind; }
0425 
0426   VECGEOM_FORCE_INLINE
0427   VECCORE_ATT_HOST_DEVICE
0428   void SetNavIndex(NavIndex_t navind) { fNavInd = navind; }
0429 
0430   VECCORE_ATT_HOST_DEVICE
0431   VECGEOM_FORCE_INLINE
0432   unsigned short GetNdaughters() const { return GetNdaughtersImpl(fNavInd); }
0433 
0434   VECGEOM_FORCE_INLINE
0435   VECCORE_ATT_HOST_DEVICE
0436   NavIndex_t GetId() const { return GetIdImpl(fNavInd); }
0437 
0438   VECGEOM_FORCE_INLINE
0439   VECCORE_ATT_HOST_DEVICE
0440   NavIndex_t GetParentSceneTopId() const { return 0; }
0441 
0442   VECCORE_ATT_HOST_DEVICE
0443   VECGEOM_FORCE_INLINE
0444   bool GetSceneId(unsigned short &scene_id, unsigned short &newscene_id) const
0445   {
0446     scene_id = newscene_id = 0;
0447     return false;
0448   }
0449 
0450   VECCORE_ATT_HOST_DEVICE
0451   VECGEOM_FORCE_INLINE
0452   unsigned int GetSceneLevel() const { return 0; }
0453 
0454   /// @brief Implementation for getting the parent scene id
0455   VECCORE_ATT_HOST_DEVICE
0456   VECGEOM_FORCE_INLINE
0457   unsigned short GetParentScene() const { return 0; }
0458 
0459   VECCORE_ATT_HOST_DEVICE
0460   VECGEOM_FORCE_INLINE
0461   unsigned int GetLogicalId() const { return GetLogicalIdImpl(fNavInd); }
0462 
0463   VECCORE_ATT_HOST_DEVICE
0464   VECGEOM_FORCE_INLINE
0465   int GetChildId() const { return GetChildIdImpl(fNavInd); }
0466 
0467   VECCORE_ATT_HOST_DEVICE
0468   VECGEOM_FORCE_INLINE
0469   bool IsScene() const { return false; }
0470 
0471   VECGEOM_FORCE_INLINE
0472   VECCORE_ATT_HOST_DEVICE
0473   bool IsDescendent(NavIndex_t parent) const { return IsDescendentImpl(fNavInd, parent); }
0474 
0475   VECGEOM_FORCE_INLINE
0476   VECCORE_ATT_HOST_DEVICE
0477   void Push(VPlacedVolume const *v) { PushImpl(fNavInd, v); }
0478 
0479   VECGEOM_FORCE_INLINE
0480   VECCORE_ATT_HOST_DEVICE
0481   void Push(int iplaced) { PushImpl(fNavInd, iplaced); }
0482 
0483   VECGEOM_FORCE_INLINE
0484   VECCORE_ATT_HOST_DEVICE
0485   void PushDaughter(int idaughter) { PushDaughterImpl(fNavInd, idaughter); }
0486 
0487   VECGEOM_FORCE_INLINE
0488   VECCORE_ATT_HOST_DEVICE
0489   void PushScene(NavIndex_t) {}
0490 
0491   VECGEOM_FORCE_INLINE
0492   VECCORE_ATT_HOST_DEVICE
0493   void Pop() { PopImpl(fNavInd); }
0494 
0495   VECGEOM_FORCE_INLINE
0496   VECCORE_ATT_HOST_DEVICE
0497   void PopScene() { fNavInd = 0; }
0498 
0499   VECGEOM_FORCE_INLINE
0500   VECCORE_ATT_HOST_DEVICE
0501   VPlacedVolume const *Top() const { return TopImpl(fNavInd); }
0502 
0503   VECGEOM_FORCE_INLINE
0504   VECCORE_ATT_HOST_DEVICE
0505   int TopId() const { return TopIdImpl(fNavInd); }
0506 
0507   /**
0508    * returns the number of FILLED LEVELS such that
0509    * state.GetNode( state.GetLevel() ) == state.Top()
0510    */
0511   VECGEOM_FORCE_INLINE
0512   VECCORE_ATT_HOST_DEVICE
0513   unsigned char GetLevel() const { return GetLevelImpl(fNavInd); }
0514 
0515   /** Compatibility getter for NavigationState interface */
0516   VECGEOM_FORCE_INLINE
0517   VECCORE_ATT_HOST_DEVICE
0518   unsigned char GetCurrentLevel() const { return GetLevel() + 1; }
0519 
0520   /**
0521    * Returns the navigation index for a level smaller/equal than the current level.
0522    */
0523   VECCORE_ATT_HOST_DEVICE
0524   VECGEOM_FORCE_INLINE
0525   NavIndex_t GetNavIndex(int level) const { return GetNavIndexImpl(fNavInd, level); }
0526 
0527   /**
0528    * Returns the placed volume at a evel smaller/equal than the current level.
0529    */
0530   VECGEOM_FORCE_INLINE
0531   VECCORE_ATT_HOST_DEVICE
0532   VPlacedVolume const *At(int level) const
0533   {
0534     auto parent = GetNavIndexImpl(fNavInd, level);
0535     return (parent > 0) ? ToPlacedVolume(NavInd(parent + 2)) : nullptr;
0536   }
0537 
0538   /**
0539    * Returns the index of a placed volume at a evel smaller/equal than the current level.
0540    */
0541   VECGEOM_FORCE_INLINE
0542   VECCORE_ATT_HOST_DEVICE
0543   size_t ValueAt(int level) const
0544   {
0545     auto parent = GetNavIndexImpl(fNavInd, level);
0546     return (parent > 0) ? (size_t)NavInd(parent + 2) : 0;
0547   }
0548 
0549   template <typename Real_t>
0550   VECCORE_ATT_HOST_DEVICE void TopMatrix(Transformation3DMP<Real_t> &trans) const
0551   {
0552     TopMatrixImpl(fNavInd, trans);
0553   }
0554 
0555   VECCORE_ATT_HOST_DEVICE
0556   void TopMatrix(Transformation3D &trans) const { TopMatrixImpl(fNavInd, trans); }
0557 
0558   template <typename Real_t>
0559   VECCORE_ATT_HOST_DEVICE void TopMatrix(int tolevel, Transformation3DMP<Real_t> &trans) const
0560   {
0561     TopMatrixImpl(GetNavIndexImpl(fNavInd, tolevel), trans);
0562   }
0563 
0564   VECCORE_ATT_HOST_DEVICE
0565   void TopMatrix(int tolevel, Transformation3D &trans) const
0566   {
0567     TopMatrixImpl(GetNavIndexImpl(fNavInd, tolevel), trans);
0568   }
0569 
0570   template <typename Real_t>
0571   VECCORE_ATT_HOST_DEVICE void TopInSceneMatrix(Transformation3DMP<Real_t> &trans) const
0572   {
0573     TopInSceneMatrixImpl(fNavInd, trans);
0574   }
0575 
0576   VECCORE_ATT_HOST_DEVICE
0577   void TopInSceneMatrix(Transformation3D &trans) const { TopInSceneMatrixImpl(fNavInd, trans); }
0578 
0579   template <typename Real_t>
0580   VECCORE_ATT_HOST_DEVICE void SceneMatrix(Transformation3DMP<Real_t> & /*trans*/) const
0581   {
0582   }
0583 
0584   VECCORE_ATT_HOST_DEVICE
0585   void SceneMatrix(Transformation3D & /*trans*/) const {}
0586 
0587   // returning a "delta" transformation that can transform
0588   // coordinates given in reference frame of this->Top() to the reference frame of other->Top()
0589   // simply with otherlocalcoordinate = delta.Transform( thislocalcoordinate )
0590   template <typename Real_t>
0591   VECCORE_ATT_HOST_DEVICE void DeltaTransformation(NavStateIndex const &other, Transformation3DMP<Real_t> &delta) const;
0592 
0593   VECCORE_ATT_HOST_DEVICE
0594   void DeltaTransformation(NavStateIndex const &other, Transformation3D &delta) const;
0595 
0596   // VECGEOM_FORCE_INLINE
0597   VECCORE_ATT_HOST_DEVICE
0598   Vector3D<Precision> GlobalToLocal(Vector3D<Precision> const &localpoint) const
0599   {
0600     return GlobalToLocalImpl(fNavInd, localpoint);
0601   }
0602 
0603   VECCORE_ATT_HOST_DEVICE
0604   Vector3D<Precision> GlobalToLocal(Vector3D<Precision> const &localpoint, int tolevel) const
0605   {
0606     return GlobalToLocalImpl(GetNavIndexImpl(fNavInd, tolevel), localpoint);
0607   }
0608 
0609   /**
0610    * calculates if other navigation state takes a different branch in geometry path or is on same branch
0611    * ( two states are on same branch if one can connect the states just by going upwards or downwards ( or do nothing ))
0612    */
0613   VECCORE_ATT_HOST_DEVICE
0614   int Distance(NavStateIndex const &) const;
0615 
0616   // returns a string representation of a (relative) sequence of operations/moves
0617   // that transforms this navigation state into the other navigation state
0618   // example:
0619   // state1 = /0/1/1/
0620   // state2 = /0/2/2/3
0621   // results in string
0622   // "/up/horiz/1/down/2/down/3" with 4 operations "up", "horiz", "down", "down"
0623   // the sequence of moves is the following
0624   // up: /0/1/1 --> /0/1/
0625   // horiz/1 : 0/1 --> /0/2 ( == /0/(1+1) )   "we are hopping from daughter 1 to 2 (which corresponds to a step of 1)"
0626   // down/2 : /0/2 --> /0/2/2   "going further down 2nd daughter"
0627   // down/3 : /0/2/2/3 --> /0/2/2/3  "going further down 2nd daughter"
0628   std::string RelativePath(NavStateIndex const & /*other*/) const;
0629 
0630   // functions useful to "serialize" navigationstate
0631   // the Vector-of-Indices basically describes the path on the tree taken from top to bottom
0632   // an index corresponds to a daughter
0633 
0634   void GetPathAsListOfIndices(std::list<uint> &indices) const;
0635   void ResetPathFromListOfIndices(VPlacedVolume const *world, std::list<uint> const &indices);
0636 
0637   // N/A: only for NavStatePath
0638   void ConvertToGPUPointers() {}
0639 
0640   // N/A: only for NavStatePath
0641   void ConvertToCPUPointers() {}
0642 
0643   // clear all information
0644   VECGEOM_FORCE_INLINE
0645   VECCORE_ATT_HOST_DEVICE
0646   void Clear()
0647   {
0648     fNavInd     = 0;
0649     fLastExited = 0;
0650     fOnBoundary = false;
0651   }
0652 
0653   VECCORE_ATT_HOST_DEVICE
0654   static void PrintRecord(NavIndex_t nav_ind);
0655 
0656   VECCORE_ATT_HOST_DEVICE void Print(bool print_names = false) const;
0657 
0658   VECCORE_ATT_HOST_DEVICE
0659   static void PrintTopImpl(NavIndex_t nav_ind) { NavStateIndex(nav_ind).Print(); }
0660 
0661   VECCORE_ATT_HOST_DEVICE
0662   void PrintTop() const { Print(); }
0663 
0664   VECCORE_ATT_HOST_DEVICE
0665   static bool IsValid(NavIndex_t nav_ind, int nprint = 0)
0666   {
0667     int nd      = GetNdaughtersImpl(nav_ind);
0668     auto parent = NavInd(nav_ind);
0669     if (nprint) printf("state %d: parent %d | %d daughters: ", nav_ind, parent, nd);
0670     bool valid = nav_ind == 1 || parent > 0;
0671     for (auto i = 0; i < nd; ++i) {
0672       auto nav_ind_child = GetChildNavInd(nav_ind, i);
0673       if (i < nprint) printf(" %d", nav_ind_child);
0674       valid &= NavInd(nav_ind_child) == nav_ind;
0675     }
0676     if (nprint) printf(" valid = %d\n", valid);
0677     return valid;
0678   }
0679 
0680   VECCORE_ATT_HOST_DEVICE
0681   void Dump() const { Print(); }
0682 
0683   VECGEOM_FORCE_INLINE
0684   VECCORE_ATT_HOST_DEVICE
0685   bool HasSamePathAsOther(NavStateIndex const &other) const { return (fNavInd == other.fNavInd); }
0686 
0687   void printValueSequence(std::ostream & = std::cerr) const;
0688 
0689   // calculates a checksum along the path
0690   // can be used (as a quick criterion) to see whether 2 states are same
0691   unsigned long getCheckSum() const { return (unsigned long)fNavInd; }
0692 
0693   /**
0694     function returning whether the point (current navigation state) is outside the detector setup
0695   */
0696   VECGEOM_FORCE_INLINE
0697   VECCORE_ATT_HOST_DEVICE
0698   bool IsOutside() const { return (fNavInd == 0); }
0699 
0700   VECGEOM_FORCE_INLINE
0701   VECCORE_ATT_HOST_DEVICE
0702   bool IsOnBoundary() const { return fOnBoundary; }
0703 
0704   VECGEOM_FORCE_INLINE
0705   VECCORE_ATT_HOST_DEVICE
0706   void SetBoundaryState(bool b) { fOnBoundary = b; }
0707 };
0708 
0709 /**
0710  * encodes the geometry path as a concatenated string of ( Value_t ) present in fPath
0711  */
0712 inline void NavStateIndex::printValueSequence(std::ostream &stream) const
0713 {
0714   auto level = GetLevel();
0715   for (int i = 0; i < level + 1; ++i) {
0716     auto pvol = At(i);
0717     if (pvol) stream << "/" << ValueAt(i) << "(" << pvol->GetLabel() << ")";
0718   }
0719 }
0720 
0721 } // namespace VECGEOM_IMPL_NAMESPACE
0722 } // namespace vecgeom
0723 
0724 #endif // VECGEOM_NAVIGATION_NAVSTATEINDEX_H_