Skip to content

Commit 5466462

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

1 file changed

Lines changed: 67 additions & 18 deletions

File tree

Detectors/Base/src/GeometryManager.cxx

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <cassert>
2424
#include <cstddef> // for NULL
2525
#include <numeric>
26+
#include <type_traits> // for the NavigationState static_assert below
2627

2728
#include "DetectorsBase/GeometryManager.h"
2829
#include "DetectorsBase/GeometryManagerParam.h"
@@ -32,6 +33,7 @@
3233

3334
#ifdef O2_WITH_VECGEOM
3435
#include "TGeo2VecGeom/RootGeoManager.h"
36+
#include <VecGeom/base/Version.h>
3537
#include <VecGeom/management/GeoManager.h>
3638
#include <VecGeom/management/ABBoxManager.h>
3739
#include <VecGeom/management/BVHManager.h>
@@ -40,7 +42,11 @@
4042
#include <VecGeom/navigation/NewSimpleNavigator.h>
4143
#include <VecGeom/navigation/BVHNavigator.h>
4244
#include <VecGeom/navigation/SimpleLevelLocator.h>
45+
#if VECGEOM_VERSION >= 0x020000
46+
#include <VecGeom/navigation/SimpleABBoxLevelLocator.h>
47+
#else
4348
#include <VecGeom/navigation/BVHLevelLocator.h>
49+
#endif
4450
#include <VecGeom/navigation/VNavigator.h>
4551
#include <VecGeom/volumes/LogicalVolume.h>
4652
#include <mutex>
@@ -557,6 +563,14 @@ void GeometryManager::loadGeometry(std::string_view simPrefix, bool applyMisalig
557563

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

580594
// 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.
595+
// level locator (used for point relocation after a boundary crossing via GlobalLocator).
583596
for (auto& lvol : vecgeom::GeoManager::Instance().GetLogicalVolumesMap()) {
584597
auto* vol = lvol.second;
585-
if (vol->GetDaughtersp()->size() <= 2) {
598+
if (!usesBvhAcceleration(vol)) {
586599
vol->SetNavigator(vecgeom::NewSimpleNavigator<>::Instance());
587600
vol->SetLevelLocator(vecgeom::SimpleLevelLocator::GetInstance());
588601
} else {
602+
#if VECGEOM_VERSION >= 0x020000
603+
// VecGeom 2 turned BVHNavigator into a plain class with static entry points instead of a
604+
// VNavigator singleton, so there is nothing to attach: vecGeomMaterialBudget() calls it
605+
// directly.
606+
//
607+
// The locator changes too, and not by choice. BVHLevelLocator does not compile in 2.1.0 or
608+
// 2.1.1 -- the header is byte-identical in both -- because its four LevelLocate() calls
609+
// have no match among the single templated BVH::LevelLocate(int exclude_item_id, ...) that
610+
// v2 ships. It survived two releases because nothing in VecGeom includes that header
611+
// except itself, so upstream CI never compiles it; O2 appears to be its only consumer.
612+
//
613+
// SimpleABBoxLevelLocator is the accelerated stand-in, using the ABBoxes built just above.
614+
// Three of the four methods could be rebuilt on the templated API (the idiom is in
615+
// BVHNavigator itself: bvh->LevelInside<BVHNavigator>(exclude_id, point, id, dlp)), but
616+
// the direction-aware LevelLocateExclVol has no v2 counterpart at all, so this stays a
617+
// fallback rather than a reimplementation. Revert to BVHLevelLocator once upstream fixes
618+
// or removes it, and measure: whether ABBox location costs anything real here is unknown.
619+
vol->SetLevelLocator(vecgeom::SimpleABBoxLevelLocator::GetInstance());
620+
#else
589621
vol->SetNavigator(vecgeom::BVHNavigator<>::Instance());
590622
vol->SetLevelLocator(vecgeom::BVHLevelLocator::GetInstance());
623+
#endif
591624
}
592625
}
593626
});
@@ -614,9 +647,16 @@ o2::base::MatBudget GeometryManager::vecGeomMaterialBudget(float x0, float y0, f
614647
dir[i] *= invlen;
615648
}
616649

617-
thread_local static vecgeom::NavigationState* newnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
618-
thread_local static vecgeom::NavigationState* currnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
619-
thread_local static vecgeom::NavigationState* startCache = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
650+
// Held by value rather than through NavigationState::MakeInstance(): VecGeom 2 removed
651+
// MakeInstance, and in VecGeom 1 it only ever did `new NavStateIndex()` with the depth argument
652+
// ignored. By value it is also one fewer per-thread allocation that was never freed.
653+
static_assert(std::is_default_constructible_v<vecgeom::NavigationState>,
654+
"NavigationState must be an index or tuple state. A variable-depth NavStatePath "
655+
"build (VecGeom 1 without VECGEOM_USE_INDEXEDNAVSTATES) needs the depth at "
656+
"construction and is not supported here.");
657+
thread_local static vecgeom::NavigationState newnavstate;
658+
thread_local static vecgeom::NavigationState currnavstate;
659+
thread_local static vecgeom::NavigationState startCache;
620660
thread_local static bool startCacheValid = false;
621661

622662
Vector3D currPoint(x0, y0, z0);
@@ -627,31 +667,40 @@ o2::base::MatBudget GeometryManager::vecGeomMaterialBudget(float x0, float y0, f
627667
budStep.length = length;
628668

629669
// Locate the starting volume, reusing the path from the previous call when still valid.
630-
if (startCacheValid && !startCache->IsOutside()) {
631-
startCache->CopyTo(currnavstate);
670+
if (startCacheValid && !startCache.IsOutside()) {
671+
startCache.CopyTo(&currnavstate);
632672
vecgeom::Transformation3D m;
633-
currnavstate->TopMatrix(m);
634-
vecgeom::GlobalLocator::RelocatePointFromPath(m.Transform(currPoint), *currnavstate);
673+
currnavstate.TopMatrix(m);
674+
vecgeom::GlobalLocator::RelocatePointFromPath(m.Transform(currPoint), currnavstate);
635675
} else {
636-
currnavstate->Clear();
637-
vecgeom::GlobalLocator::LocateGlobalPoint(world, currPoint, *currnavstate, true);
676+
currnavstate.Clear();
677+
vecgeom::GlobalLocator::LocateGlobalPoint(world, currPoint, currnavstate, true);
638678
}
639-
if (currnavstate->IsOutside() || currnavstate->Top() == nullptr) {
679+
if (currnavstate.IsOutside() || currnavstate.Top() == nullptr) {
640680
LOG(error) << "start point out of geometry: " << x0 << ':' << y0 << ':' << z0;
641681
startCacheValid = false;
642682
return o2::base::MatBudget();
643683
}
644-
currnavstate->CopyTo(startCache);
684+
currnavstate.CopyTo(&startCache);
645685
startCacheValid = true;
646686

647687
double stepTot = 0.;
648688
double remainingDist = length;
649689
Int_t nzero = 0;
650690
while (remainingDist > 1.E-10) {
651-
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));
691+
auto* lvol = currnavstate.Top()->GetLogicalVolume();
692+
// Not LogicalVolume::GetMaterialPtr(): VecGeom 2 dropped the material slot from the logical
693+
// volume. TGeo2VecGeom keeps what its conversion hook returned, indexed by logical volume id,
694+
// and serves it for both VecGeom versions.
695+
accountMaterial(static_cast<TGeoMaterial*>(tgeo2vecgeom::RootGeoManager::Instance().GetMaterialPtr(lvol)), budStep);
696+
#if VECGEOM_VERSION >= 0x020000
697+
const double step =
698+
usesBvhAcceleration(lvol)
699+
? static_cast<double>(vecgeom::BVHNavigator::ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, currnavstate, newnavstate))
700+
: static_cast<double>(lvol->GetNavigator()->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, currnavstate, newnavstate));
701+
#else
702+
const double step = static_cast<double>(lvol->GetNavigator()->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, currnavstate, newnavstate));
703+
#endif
655704
if (step < 2.E-10) {
656705
nzero++;
657706
} else {

0 commit comments

Comments
 (0)