Skip to content

Commit 807b6b2

Browse files
committed
Add support for VecGeom v2
1 parent b593063 commit 807b6b2

1 file changed

Lines changed: 62 additions & 6 deletions

File tree

Detectors/Base/src/GeometryManager.cxx

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#ifdef O2_WITH_VECGEOM
3434
#include "TGeo2VecGeom/RootGeoManager.h"
35+
#include <VecGeom/base/Version.h>
3536
#include <VecGeom/management/GeoManager.h>
3637
#include <VecGeom/management/ABBoxManager.h>
3738
#include <VecGeom/management/BVHManager.h>
@@ -40,7 +41,11 @@
4041
#include <VecGeom/navigation/NewSimpleNavigator.h>
4142
#include <VecGeom/navigation/BVHNavigator.h>
4243
#include <VecGeom/navigation/SimpleLevelLocator.h>
44+
#if VECGEOM_VERSION >= 0x020000
45+
#include <VecGeom/navigation/SimpleABBoxLevelLocator.h>
46+
#else
4347
#include <VecGeom/navigation/BVHLevelLocator.h>
48+
#endif
4449
#include <VecGeom/navigation/VNavigator.h>
4550
#include <VecGeom/volumes/LogicalVolume.h>
4651
#include <mutex>
@@ -557,6 +562,14 @@ void GeometryManager::loadGeometry(std::string_view simPrefix, bool applyMisalig
557562

558563
namespace
559564
{
565+
/// Volumes with very few daughters are cheaper to brute-force than to accelerate. Defined once
566+
/// because two places must agree on it: where the navigators and locators are attached below,
567+
/// and where vecGeomMaterialBudget() decides how to take a step.
568+
bool usesBvhAcceleration(vecgeom::LogicalVolume const* vol)
569+
{
570+
return vol->GetDaughtersp()->size() > 2;
571+
}
572+
560573
/// Converts the currently loaded TGeo geometry to VecGeom and sets up navigators, once per
561574
/// process, the first time the VecGeom backend is requested. Not part of loadGeometry(),
562575
/// which every job calls regardless of whether it ever uses the VecGeom backend.
@@ -578,16 +591,35 @@ void ensureVecGeomWorldBuilt()
578591
vecgeom::BVHManager::Init();
579592

580593
// For each logical volume, set both a navigator (used for ComputeStep) and a matched
581-
// level locator (used for point relocation after a boundary crossing via GlobalLocator);
582-
// volumes with very few daughters are cheaper to brute-force than to accelerate.
594+
// level locator (used for point relocation after a boundary crossing via GlobalLocator).
583595
for (auto& lvol : vecgeom::GeoManager::Instance().GetLogicalVolumesMap()) {
584596
auto* vol = lvol.second;
585-
if (vol->GetDaughtersp()->size() <= 2) {
597+
if (!usesBvhAcceleration(vol)) {
586598
vol->SetNavigator(vecgeom::NewSimpleNavigator<>::Instance());
587599
vol->SetLevelLocator(vecgeom::SimpleLevelLocator::GetInstance());
588600
} else {
601+
#if VECGEOM_VERSION >= 0x020000
602+
// VecGeom 2 turned BVHNavigator into a plain class with static entry points instead of a
603+
// VNavigator singleton, so there is nothing to attach: vecGeomMaterialBudget() calls it
604+
// directly.
605+
//
606+
// The locator changes too, and not by choice. BVHLevelLocator does not compile in 2.1.0 or
607+
// 2.1.1 -- the header is byte-identical in both -- because its four LevelLocate() calls
608+
// have no match among the single templated BVH::LevelLocate(int exclude_item_id, ...) that
609+
// v2 ships. It survived two releases because nothing in VecGeom includes that header
610+
// except itself, so upstream CI never compiles it; O2 appears to be its only consumer.
611+
//
612+
// SimpleABBoxLevelLocator is the accelerated stand-in, using the ABBoxes built just above.
613+
// Three of the four methods could be rebuilt on the templated API (the idiom is in
614+
// BVHNavigator itself: bvh->LevelInside<BVHNavigator>(exclude_id, point, id, dlp)), but
615+
// the direction-aware LevelLocateExclVol has no v2 counterpart at all, so this stays a
616+
// fallback rather than a reimplementation. Revert to BVHLevelLocator once upstream fixes
617+
// or removes it, and measure: whether ABBox location costs anything real here is unknown.
618+
vol->SetLevelLocator(vecgeom::SimpleABBoxLevelLocator::GetInstance());
619+
#else
589620
vol->SetNavigator(vecgeom::BVHNavigator<>::Instance());
590621
vol->SetLevelLocator(vecgeom::BVHLevelLocator::GetInstance());
622+
#endif
591623
}
592624
}
593625
});
@@ -614,9 +646,24 @@ o2::base::MatBudget GeometryManager::vecGeomMaterialBudget(float x0, float y0, f
614646
dir[i] *= invlen;
615647
}
616648

649+
// Only the allocation differs between VecGeom versions; everything below works on pointers in
650+
// both, which also keeps the std::swap() at the end of the loop a pointer swap rather than a
651+
// copy of the state itself.
652+
//
653+
// VecGeom 1 builds NavigationState as NavStatePath, a variable-size object that must be told the
654+
// maximum depth at construction and can only be made through MakeInstance(). VecGeom 2 dropped
655+
// NavStatePath and MakeInstance with it: NavigationState is NavStateIndex or NavStateTuple, both
656+
// fixed-size value types, so a thread_local object is the direct equivalent.
657+
#if VECGEOM_VERSION >= 0x020000
658+
thread_local static vecgeom::NavigationState newnavstateStorage, currnavstateStorage, startCacheStorage;
659+
thread_local static vecgeom::NavigationState* newnavstate = &newnavstateStorage;
660+
thread_local static vecgeom::NavigationState* currnavstate = &currnavstateStorage;
661+
thread_local static vecgeom::NavigationState* startCache = &startCacheStorage;
662+
#else
617663
thread_local static vecgeom::NavigationState* newnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
618664
thread_local static vecgeom::NavigationState* currnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
619665
thread_local static vecgeom::NavigationState* startCache = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
666+
#endif
620667
thread_local static bool startCacheValid = false;
621668

622669
Vector3D currPoint(x0, y0, z0);
@@ -649,9 +696,18 @@ o2::base::MatBudget GeometryManager::vecGeomMaterialBudget(float x0, float y0, f
649696
Int_t nzero = 0;
650697
while (remainingDist > 1.E-10) {
651698
auto* lvol = currnavstate->Top()->GetLogicalVolume();
652-
accountMaterial(static_cast<TGeoMaterial*>(lvol->GetMaterialPtr()), budStep);
653-
vecgeom::VNavigator const* navigator = lvol->GetNavigator();
654-
double step = static_cast<double>(navigator->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate));
699+
// Not LogicalVolume::GetMaterialPtr(): VecGeom 2 dropped the material slot from the logical
700+
// volume. TGeo2VecGeom keeps what its conversion hook returned, indexed by logical volume id,
701+
// and serves it for both VecGeom versions.
702+
accountMaterial(static_cast<TGeoMaterial*>(tgeo2vecgeom::RootGeoManager::Instance().GetMaterialPtr(lvol)), budStep);
703+
#if VECGEOM_VERSION >= 0x020000
704+
const double step =
705+
usesBvhAcceleration(lvol)
706+
? static_cast<double>(vecgeom::BVHNavigator::ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate))
707+
: static_cast<double>(lvol->GetNavigator()->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate));
708+
#else
709+
const double step = static_cast<double>(lvol->GetNavigator()->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate));
710+
#endif
655711
if (step < 2.E-10) {
656712
nzero++;
657713
} else {

0 commit comments

Comments
 (0)