14#include "G4Exception.hh"
15#include "G4TouchableHistory.hh"
16#include "G4VPhysicalVolume.hh"
18#include <VecGeom/base/Transformation3D.h>
19#include <VecGeom/management/GeoManager.h>
20#include <VecGeom/navigation/GlobalLocator.h>
21#include <VecGeom/navigation/VNavigator.h>
22#include <VecGeom/navigation/VSafetyEstimator.h>
23#include <VecGeom/volumes/LogicalVolume.h>
24#include <VecGeom/volumes/PlacedVolume.h>
26#include <fairlogger/Logger.h>
35const G4ThreeVector kNoPoint(-1e8, -1e8, -1e8);
37bool samePoint(
const G4ThreeVector&
a,
const G4ThreeVector&
b) {
return a.diff2(
b) < 1
e-20; }
39vecgeom::VPlacedVolume
const* topOf(vecgeom::NavigationState
const&
st)
41 return st.IsOutside() ? nullptr :
st.Top();
56 LOG(info) <<
"VecGeom navigation: zero steps " << mZeroStepCount <<
", stuck pushes " << mStuckPushCount
57 <<
", abandoned " << mAbandonCount <<
", negative safeties " << mNegativeSafetyCount
58 <<
", unmappable touchables " << mUnmappableHistoryCount <<
", relocated resumes "
59 << mRelocatedResumeCount <<
", missing exit normals " << mNoNormalCount;
62G4VPhysicalVolume* VecGeomG4Navigator::updateG4History()
65 if (mHistoryValid && mCurState.HasSamePathAsOther(mHistoryState)) {
66 return fHistory.GetTopVolume();
68 mHistoryState = mCurState;
73void VecGeomG4Navigator::locateFromWorld(
const V3& point)
76 vecgeom::GlobalLocator::LocateGlobalPoint(vecgeom::GeoManager::Instance().GetWorld(), point, mCurState,
true);
83double VecGeomG4Navigator::boundaryPush(
const V3& point,
const V3& dir)
85 constexpr double kMaxPush = 1.e-4;
86 const double big = std::max({std::abs(point.x()), std::abs(point.y()), std::abs(point.z())});
87 const double rounding = 1.e3 * big * std::numeric_limits<double>::epsilon();
90 vecgeom::NavigationState
const&
st = mWouldEnter ? mNextState : mCurState;
92 mPushNormalValid =
false;
93 if (!
st.IsOutside() &&
st.Top() !=
nullptr) {
94 vecgeom::Transformation3D
m;
97 st.Top()->GetUnplacedVolume()->Normal(
m.Transform(point),
n);
98 const double c = std::abs(
n.Dot(
m.TransformDirection(dir)));
99 if (
c > 0. &&
n.Mag2() > 0.5) {
102 if (
n.Mag2() > 0.5) {
103 mPushNormal =
m.InverseTransformDirection(
n);
104 mPushNormalValid =
true;
107 return std::max(rounding, std::min(mPushDepth / cosn, kMaxPush));
111 const G4double proposedStepLength, G4double& newSafety)
117 auto const*
top = topOf(mCurState);
118 if (
top ==
nullptr) {
121 auto const* navigator =
top->GetLogicalVolume()->GetNavigator();
125 bool calcSafety = !mZeroSafety && !(mLocatedOnBoundary && samePoint(globalPoint, mLastLocatedPoint));
126 if (calcSafety && samePoint(globalPoint, mSafetyOrig) && mLastSafety < mLastSafetyLimit) {
128 newSafety = mLastSafety;
135 mStepState = mCurState;
136 if (mExitBlockPending) {
137 const bool block = samePoint(globalPoint, mLastLocatedPoint) &&
141 mStepState.SetLastExited(mEmptyState.GetLastExitedState());
145 const double limit = std::min(proposedStepLength *
kG4ToVG,
static_cast<double>(vecgeom::kInfLength));
147 double vgStep = navigator->ComputeStepAndSafety(
toVG(globalPoint),
toDir(direction), limit, mStepState, calcSafety,
151 ++mNegativeSafetyCount;
155 mSafetyOrig = globalPoint;
156 mLastSafety = newSafety;
157 mLastSafetyLimit = kInfinity;
159 const bool boundaryLimited = vgStep < limit;
160 G4double step = std::max(vgStep, 0.) *
kVGToG4;
161 const bool entering = mStepState.GetCurrentLevel() > mCurState.GetCurrentLevel();
165 if (step < 0.05 * kCarTolerance) {
167 if (++mNzeroSteps >= kActionThresholdNoZeroSteps) {
169 step += 100. * kCarTolerance;
170 if (mNzeroSteps >= kAbandonThresholdNoZeroSteps) {
172 std::ostringstream
msg;
173 msg <<
"Track stuck or not moving: " << mNzeroSteps <<
" zero steps in " <<
top->GetLabel() <<
" at ("
174 << globalPoint.x() <<
", " << globalPoint.y() <<
", " << globalPoint.z() <<
") mm. Event aborted, as "
175 <<
"G4Navigator does.";
177 G4Exception(
"VecGeomG4Navigator::ComputeStep()",
"GeomNav0003", EventMustBeAborted,
msg.str().c_str());
184 if (boundaryLimited) {
185 mWouldEnter = entering;
186 mWouldExit = !entering;
187 mNextPoint = globalPoint + step * direction;
189 mNextState = mStepState;
192 mNormalState = entering ? mNextState : mCurState;
193 mNormalEnter = entering;
194 mNormalPoint = mNextPoint;
198 mNormalValid =
false;
210void VecGeomG4Navigator::leaveFlushVolumes(
const V3& point,
const V3& dir,
int minLevel,
211 vecgeom::VPlacedVolume
const* avoid)
213 for (
int round = 0; round < 4; ++round) {
214 vecgeom::VPlacedVolume
const*
left =
nullptr;
215 while (topOf(mCurState) !=
nullptr &&
static_cast<int>(mCurState.GetCurrentLevel()) > minLevel) {
216 vecgeom::Transformation3D
m;
217 mCurState.TopMatrix(
m);
218 if (mCurState.Top()->GetUnplacedVolume()->DistanceToOut(
m.Transform(point),
m.TransformDirection(dir)) > 0.) {
221 left = mCurState.Top();
222 mCurState.SetLastExited();
223 setExited(mCurState,
false);
224 if (mCurState.GetCurrentLevel() <= 1) {
230 if (
left ==
nullptr) {
233 auto const* mother = mCurState.Top();
234 vecgeom::Transformation3D
m;
235 mCurState.TopMatrix(
m);
236 const auto level = mCurState.GetCurrentLevel();
237 const auto blocked = mCurState.GetLastExitedState();
239 vecgeom::GlobalLocator::LocateGlobalPointExclVolume(mother,
left,
m.Transform(point), mCurState,
false);
240 mCurState.SetLastExited(blocked);
241 if (mCurState.GetCurrentLevel() ==
level) {
244 if (avoid !=
nullptr && mCurState.GetCurrentLevel() >
level) {
246 mPathScratch = mCurState;
247 while (mPathScratch.GetCurrentLevel() >
level && mPathScratch.Top() != avoid) {
250 if (mPathScratch.GetCurrentLevel() >
level) {
251 while (mCurState.GetCurrentLevel() >
level) {
263void VecGeomG4Navigator::updateCrossingFlags(
bool entering)
265 const int preLevel = mReloScratch.IsOutside() ? 0 :
static_cast<int>(mReloScratch.GetCurrentLevel());
266 const int curLevel = mCurState.IsOutside() ? 0 :
static_cast<int>(mCurState.GetCurrentLevel());
267 mPathScratch = mReloScratch;
268 mStepState = mCurState;
269 int la = preLevel, lb = curLevel;
278 while (la > 0 && !mPathScratch.HasSamePathAsOther(mStepState)) {
283 fExitedMother = !entering || la < preLevel;
284 fEnteredDaughter = entering || la < curLevel;
288 const G4ThreeVector* direction,
289 const G4bool relativeSearch,
const G4bool)
293 const bool onBoundary = relativeSearch && (fWasLimitedByGeometry || samePoint(point, mNextPoint));
294 const bool crossing = onBoundary && (mWouldEnter || mWouldExit) && direction !=
nullptr;
295 const bool entering = crossing && mWouldEnter;
297 const V3 dir = direction !=
nullptr ?
toDir(*direction) :
V3(0., 0., 0.);
298 const double push = (onBoundary && direction !=
nullptr) ? boundaryPush(p, dir) : 0.;
299 const V3 q = p + push * dir;
301 fWasLimitedByGeometry =
false;
302 fEnteredDaughter =
false;
303 fExitedMother =
false;
304 mLocatedOnBoundary =
false;
305 mLastLocatedPoint = point;
306 mSafetyOrig = kNoPoint;
309 if (!relativeSearch) {
312 }
else if (topOf(mCurState) ==
nullptr) {
314 }
else if (entering) {
316 mReloScratch = mCurState;
317 mCurState = mNextState;
320 mCurState.SetLastExited(mEmptyState.GetLastExitedState());
321 auto const* daughter = mCurState.Top();
323 vecgeom::Transformation3D
m;
324 mCurState.TopMatrix(
m);
325 vecgeom::GlobalLocator::LocateGlobalPoint(daughter, daughter->GetTransformation()->Transform(
m.Transform(q)),
327 mLocatedOnBoundary =
true;
328 }
else if (crossing) {
332 mReloScratch = mCurState;
333 if (mCurState.GetCurrentLevel() <= 1) {
336 vecgeom::Transformation3D
m;
337 mCurState.TopMatrix(
m);
338 vecgeom::GlobalLocator::RelocatePointFromPathForceDifferent(
m.Transform(q), mCurState);
339 mReloScratch.SetLastExited();
340 mCurState.SetLastExited(mReloScratch.GetLastExitedState());
341 setExited(mReloScratch,
true);
343 mLocatedOnBoundary =
true;
346 vecgeom::Transformation3D
m;
347 mCurState.TopMatrix(
m);
348 vecgeom::GlobalLocator::RelocatePointFromPath(
m.Transform(q), mCurState);
349 if (topOf(mCurState) ==
nullptr) {
352 mLocatedOnBoundary = onBoundary;
355 leaveFlushVolumes(q, dir, entering ?
static_cast<int>(mNextState.GetCurrentLevel()) : 0,
356 entering ? nullptr : topOf(mReloScratch));
357 updateCrossingFlags(entering);
361 return updateG4History();
365 const G4TouchableHistory& history)
369 fWasLimitedByGeometry =
false;
370 fEnteredDaughter =
false;
371 fExitedMother =
false;
374 mLocatedOnBoundary =
false;
375 mLastLocatedPoint = point;
376 mSafetyOrig = kNoPoint;
378 fHistory = *history.GetHistory();
382 vecgeom::Transformation3D
m;
383 mCurState.TopMatrix(
m);
384 if (mCurState.Top()->GetUnplacedVolume()->Contains(
m.Transform(p))) {
387 ++mRelocatedResumeCount;
388 vecgeom::GlobalLocator::RelocatePointFromPath(
m.Transform(p), mCurState);
389 if (topOf(mCurState) ==
nullptr) {
394 if (++mUnmappableHistoryCount <= 10) {
395 LOG(warning) <<
"VecGeom navigation: a touchable matches no VecGeom path; locating from the world";
402 mHistoryState = mCurState;
403 mHistoryValid =
true;
404 return fHistory.GetTopVolume();
406 mHistoryValid =
false;
407 return updateG4History();
415 mLocatedOnBoundary =
false;
418 fEnteredDaughter =
false;
419 fExitedMother =
false;
429 if (mLocatedOnBoundary && samePoint(globalPoint, mLastLocatedPoint)) {
432 if ((mWouldEnter || mWouldExit) && samePoint(globalPoint, mNextPoint)) {
435 if (samePoint(globalPoint, mSafetyOrig) && (mLastSafety < mLastSafetyLimit || mLastSafety >= proposedMaxLength)) {
438 if (topOf(mCurState) ==
nullptr) {
443 const double rest = mLastSafety - std::sqrt(globalPoint.diff2(mSafetyOrig));
444 if (rest >= proposedMaxLength) {
447 double safety =
boundedSafety(mCurState, globalPoint, proposedMaxLength);
449 ++mNegativeSafetyCount;
452 mSafetyOrig = globalPoint;
453 mLastSafety = safety;
454 mLastSafetyLimit = proposedMaxLength;
464bool VecGeomG4Navigator::computeExitNormal(
const G4ThreeVector& point,
V3& globalNormal)
const
466 if (!mNormalValid || topOf(mNormalState) ==
nullptr) {
469 vecgeom::Transformation3D
m;
470 mNormalState.TopMatrix(
m);
471 V3 localNormal(0., 0., 0.);
472 mNormalState.Top()->GetUnplacedVolume()->Normal(
m.Transform(
toVG(point)), localNormal);
473 globalNormal =
m.InverseTransformDirection(localNormal);
474 const double mag = globalNormal.Mag();
480 globalNormal = -globalNormal;
488 if (!computeExitNormal(mNormalPoint,
n) || topOf(mCurState) ==
nullptr) {
490 if (
valid !=
nullptr) {
493 return G4ThreeVector();
495 vecgeom::Transformation3D
m;
496 mCurState.TopMatrix(
m);
497 const auto local =
m.TransformDirection(
n);
498 if (
valid !=
nullptr) {
501 return G4ThreeVector(local[0], local[1], local[2]);
507 if (!computeExitNormal(point,
n)) {
509 if (
valid !=
nullptr) {
512 return G4ThreeVector();
514 if (
valid !=
nullptr) {
517 return G4ThreeVector(
n[0],
n[1],
n[2]);
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines kept
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
vecgeom::Vector3D< double > V3
static bool directionLeaves(const V3 &n, const V3 &dir)
static V3 toDir(const G4ThreeVector &d)
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)
static constexpr double kVGToG4
static constexpr double kG4ToVG
vecgeom::Vector3D< double > V3
G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid) override
G4double ComputeSafety(const G4ThreeVector &globalPoint, const G4double proposedMaxLength=DBL_MAX, const G4bool keepState=true) override
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &direction, const G4double proposedStepLength, G4double &newSafety) override
~VecGeomG4Navigator() override
VecGeomG4Navigator(VecGeomG4Map const &map, double pushDepth, bool zeroSafety)
G4VPhysicalVolume * ResetHierarchyAndLocate(const G4ThreeVector &point, const G4ThreeVector &direction, const G4TouchableHistory &history) override
G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=nullptr, const G4bool relativeSearch=true, const G4bool ignoreDirection=true) override
void LocateGlobalPointWithinVolume(const G4ThreeVector &position) override
G4ThreeVector GetLocalExitNormal(G4bool *valid) override
GLdouble GLdouble GLdouble GLdouble top
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
uint64_t const void const *restrict const msg