Project
Loading...
Searching...
No Matches
VecGeomG4NavigatorBase.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include "G4VPhysicalVolume.hh"
15
16#include <VecGeom/management/BVHManager.h>
17#include <VecGeom/navigation/BVHNavigator.h>
18#include <VecGeom/navigation/BVHSafetyEstimator.h>
19#include <VecGeom/navigation/VSafetyEstimator.h>
20#include <VecGeom/volumes/LogicalVolume.h>
21#include <VecGeom/volumes/PlacedVolume.h>
22
23#include <fairlogger/Logger.h>
24
25#include <algorithm>
26
27namespace
28{
30constexpr std::size_t kMaxChain = 16;
32constexpr int kMaxDepth = 64;
33} // namespace
34
35namespace o2::simsetup
36{
37
38double VecGeomG4NavigatorBase::boundedSafety(vecgeom::NavigationState const& state, const G4ThreeVector& point,
39 double limit)
40{
41 auto const* pvol = state.Top();
42 auto const* lvol = pvol->GetLogicalVolume();
43 auto const* estimator = lvol->GetSafetyEstimator();
44 if (estimator == nullptr) {
45 return 0.;
46 }
47 if (limit < kInfinity && estimator == vecgeom::BVHSafetyEstimator::Instance() && lvol->GetDaughters().size() > 0) {
48 // The BVH estimator's own computation, with the search limited.
49 vecgeom::Transformation3D m;
50 state.TopMatrix(m);
51 const V3 local = m.Transform(toVG(point));
52 double safety = pvol->SafetyToOut(local);
53 if (safety > 0.) {
54 safety = vecgeom::BVHNavigator::ComputeBVHSafety<vecgeom::BVHSafetyEstimator>(
55 *vecgeom::BVHManager::GetBVH(lvol), local, safety, std::min(safety, limit * kG4ToVG));
56 }
57 return safety * kVGToG4;
58 }
59 return estimator->ComputeSafety(toVG(point), state) * kVGToG4;
60}
61
62G4VPhysicalVolume* VecGeomG4NavigatorBase::historyFromState(vecgeom::NavigationState const& state)
63{
64 // Collect the Geant4 volumes the state stands for, then keep the levels the history already has
65 // right and rebuild only from the first difference down: NewLevel composes a transform per level.
66 G4VPhysicalVolume* want[kMaxDepth];
67 int n = 0;
68 if (!state.IsOutside()) {
69 const int levels = state.GetCurrentLevel();
70 for (int l = 0; l < levels && n < kMaxDepth; ++l) {
71 auto const* placed = state.At(l);
72 if (placed == nullptr) {
73 break;
74 }
75 unsigned size = 0;
76 auto* const* chain = mMap.chain(placed->id(), size);
77 if (size == 0) {
78 LOG(fatal) << "VecGeom placement " << placed->GetLabel() << " (id " << placed->id() << ") at level " << l
79 << " has no Geant4 counterpart";
80 }
81 for (unsigned c = 0; c < size && n < kMaxDepth; ++c) {
82 want[n++] = chain[c];
83 }
84 }
85 }
86
87 if (n == 0) {
88 // Outside the world. A null first entry is how G4NavigationHistory says so.
89 fHistory.Reset();
90 fHistory.SetFirstEntry(nullptr);
91 return nullptr;
92 }
93
94 const int depth = static_cast<int>(fHistory.GetDepth());
95 int common = 0;
96 while (common <= depth && common < n && fHistory.GetVolume(common) == want[common]) {
97 ++common;
98 }
99 if (common == 0) {
100 fHistory.Reset();
101 fHistory.SetFirstEntry(want[0]);
102 common = 1;
103 } else if (depth >= common) {
104 fHistory.BackLevel(depth - common + 1);
105 }
106 for (int k = common; k < n; ++k) {
107 // The copy number is what TG4StepManager::CurrentVolID and CurrentVolOffID report, so it has to
108 // be filled exactly as the TGeo navigator fills it.
109 fHistory.NewLevel(want[k], kNormal, want[k]->GetCopyNo());
110 }
111 return fHistory.GetTopVolume();
112}
113
114bool VecGeomG4NavigatorBase::stateFromHistory(vecgeom::NavigationState& state) const
115{
116 // A run of levels that ends in a Geant4 volume several placements share is settled by comparing
117 // the run against the placements' recorded chains, which is exact.
118 state.Clear();
119 if (mMap.world() == nullptr || fHistory.GetVolume(0) == nullptr) {
120 return false;
121 }
122 state.Push(mMap.world());
123 const std::size_t depth = fHistory.GetDepth();
124 std::size_t l = mMap.chainSize(mMap.world()->id());
125 while (l <= depth) {
126 G4VPhysicalVolume* run[kMaxChain];
127 vecgeom::VPlacedVolume const* found = nullptr;
128 std::size_t n = 0;
129 for (std::size_t e = l; e <= depth && n < kMaxChain; ++e, ++n) {
130 run[n] = fHistory.GetVolume(e);
131 auto const* candidate = mMap.toVecGeom(run[n]->GetInstanceID());
132 if (candidate == nullptr) {
133 continue; // an assembly level; the chain reaches further down
134 }
135 if (candidate == VecGeomG4Map::ambiguous()) {
136 for (auto const* c : mMap.candidates(run[n]->GetInstanceID())) {
137 if (mMap.chainMatches(c, run, n + 1)) {
138 found = c;
139 break;
140 }
141 }
142 } else if (mMap.chainMatches(candidate, run, n + 1)) {
143 found = candidate;
144 }
145 if (found != nullptr) {
146 break;
147 }
148 }
149 if (found == nullptr) {
150 state.Clear();
151 return false;
152 }
153 state.Push(found);
154 l += mMap.chainSize(found->id());
155 }
156 return true;
157}
158
159} // namespace o2::simsetup
GPUChain * chain
SurfaceTrackState state
uint32_t c
Definition RawData.h:2
G4VPhysicalVolume *const * chain(int vgId, unsigned &size) const
static vecgeom::VPlacedVolume const * ambiguous()
Marks a Geant4 volume that several VecGeom placements reach.
std::vector< vecgeom::VPlacedVolume const * > const & candidates(int g4Id) const
The placements that share an ambiguous Geant4 volume, to be told apart by their chains.
unsigned chainSize(int vgId) const
How many Geant4 levels a VecGeom placement accounts for.
vecgeom::VPlacedVolume const * toVecGeom(int g4Id) const
bool chainMatches(vecgeom::VPlacedVolume const *pv, G4VPhysicalVolume *const *first, std::size_t n) const
Whether a placement's chain is exactly the given run of Geant4 volumes.
vecgeom::VPlacedVolume const * world() const
The outermost placement, standing for the Geant4 world volume.
G4VPhysicalVolume * historyFromState(vecgeom::NavigationState const &state)
static V3 toVG(const G4ThreeVector &p)
bool stateFromHistory(vecgeom::NavigationState &state) const
static double boundedSafety(vecgeom::NavigationState const &state, const G4ThreeVector &point, double limit)
GLdouble n
Definition glcorearb.h:1982
const GLfloat * m
Definition glcorearb.h:4066
GLsizeiptr size
Definition glcorearb.h:659
GLsizei levels
Definition glcorearb.h:2198
GLint GLint GLsizei GLsizei GLsizei depth
Definition glcorearb.h:470
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"