G4Root Version 6.6
Loading...
Searching...
No Matches
TG4RootNavigator.cxx
Go to the documentation of this file.
1// @(#)root/g4root:$Id$
2// Author: Andrei Gheata 07/08/06
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
16
17#include "TGeoManager.h"
18
20#include "TG4RootNavigator.h"
21
22#include "G4SystemOfUnits.hh"
23
24// ClassImp(TG4RootNavigator)
25// To get the current track in case to restore a geometry status
26#include "G4Track.hh"
27#include "G4TrackingManager.hh"
28
30static const double gCm = 1. / cm;
31static const double gZeroStepThr = 1.e-3; // >1.e-4 limit in G4PropagatorInField
32static const int gAbandonZeroSteps = 40; // <50 limit in G4PropagatorInField
33
34//______________________________________________________________________________
36 : G4Navigator(),
37 fGeometry(0),
38 fNavigator(0),
39 fDetConstruction(0),
40 fStepEntering(kFALSE),
41 fStepExiting(kFALSE),
42 fNextPoint(),
43 fSafetyOrig(),
44 fLastSafety(0),
45 fNzeroSteps(0),
46 fG4TrackingManager(nullptr),
47 fRestoreGeoStateFunction(nullptr)
48{
50}
51
52//______________________________________________________________________________
54 : G4Navigator(),
55 fGeometry(0),
56 fNavigator(0),
57 fDetConstruction(0),
58 fStepEntering(kFALSE),
59 fStepExiting(kFALSE),
60 fNextPoint(),
61 fSafetyOrig(),
62 fLastSafety(0),
63 fNzeroSteps(0),
64 fG4TrackingManager(nullptr),
65 fRestoreGeoStateFunction(nullptr)
66{
68 fSafetyOrig.set(kInfinity, kInfinity, kInfinity);
70 SetWorldVolume(dc->GetTopPV());
71}
72
73//______________________________________________________________________________
78
79//______________________________________________________________________________
81{
84 if (dc) fGeometry = dc->GetGeometryManager();
85 if (!fGeometry || !fGeometry->IsClosed()) {
86 G4Exception("TG4RootNavigator::SetDetectorConstruction", "G4Root_F001",
87 FatalException,
88 "Cannot create TG4RootNavigator without closed ROOT geometry !");
89 }
90 fNavigator = fGeometry->GetCurrentNavigator();
91 if (!fNavigator) fNavigator = fGeometry->AddNavigator();
92 // G4cout << "Navigator created: " << fNavigator << G4endl;
94}
95
96//______________________________________________________________________________
97G4double TG4RootNavigator::ComputeStep(const G4ThreeVector& pGlobalPoint,
98 const G4ThreeVector& pDirection, const G4double pCurrentProposedStepLength,
99 G4double& pNewSafety)
100{
113
114 // The following 2 lines are not needed if G4 calls first LocateGlobalPoint...
115 // fGeometry->ResetState();
116 static Long64_t istep = 0;
117 istep++;
118
119#ifdef G4ROOT_DEBUG
120 G4cout.precision(8);
121 G4cout << "*** ComputeStep #" << istep << ": ***"
122 << fHistory.GetTopVolume()->GetName()
123 << " entered: " << fEnteredDaughter << " exited: " << fExitedMother
124 << G4endl;
125#endif
126 Double_t tol = 0.;
127 Bool_t compute_safety = kTRUE;
128 Double_t pstep = pCurrentProposedStepLength;
129 if (pstep > TGeoShape::Big()) {
130 pstep = TGeoShape::Big();
131 compute_safety = kFALSE;
132 pNewSafety = 0.0;
133 }
134
135 Bool_t frombdr = fEnteredDaughter | fExitedMother;
136#ifdef G4ROOT_DEBUG
137 Bool_t oldpoint = kFALSE;
138#endif
139 if (frombdr) {
140 Double_t npt[3];
141 tol = TGeoShape::Tolerance();
142 npt[0] = pGlobalPoint.x() * gCm + tol * pDirection.x();
143 npt[1] = pGlobalPoint.y() * gCm + tol * pDirection.y();
144 npt[2] = pGlobalPoint.z() * gCm + tol * pDirection.z();
145 fNavigator->SetCurrentPoint(npt[0], npt[1], npt[2]);
146 compute_safety = kFALSE;
147 pNewSafety = 0.0;
148 }
149 else {
150 fNavigator->SetCurrentPoint(
151 pGlobalPoint.x() * gCm, pGlobalPoint.y() * gCm, pGlobalPoint.z() * gCm);
152 Double_t d2 = pGlobalPoint.diff2(fSafetyOrig);
153 if (d2 < 1.e-10) {
154#ifdef G4ROOT_DEBUG
155 oldpoint = kTRUE;
156#endif
157 compute_safety = kFALSE;
158 pNewSafety = fLastSafety;
159 }
160 fSafetyOrig = pGlobalPoint;
161 }
162 fNavigator->SetCurrentDirection(
163 pDirection.x(), pDirection.y(), pDirection.z());
164 fNavigator->FindNextBoundary(-(pstep * gCm - tol), "", !compute_safety);
165
166 if (compute_safety) {
167 pNewSafety = (fNavigator->GetSafeDistance() - tol) * cm;
168 if (pNewSafety < 0.) pNewSafety = 0.;
169 fLastSafety = pNewSafety;
170 }
171 G4double step = (fNavigator->GetStep() + tol) * cm;
172 // if (step >= pCurrentProposedStepLength) step = kInfinity;
173 if (step < 1.e3 * tol * cm) {
174 step = 0.;
175 fNzeroSteps++;
176 // Geant4 will abandon the track if the number of zero steps>50 just
177 // because it expects a non-zero distance inside the mother to the next
178 // daughter The way out is to generate an extra very small fake step in the
179 // mother, before this threshold is reached
181 }
182 else {
183 fNzeroSteps = 0;
184 }
185 fStepEntering = fNavigator->IsStepEntering();
186 fStepExiting = fNavigator->IsStepExiting();
188 fNextPoint = pGlobalPoint + step * pDirection;
189 }
190 else {
191 step = kInfinity;
192 }
193
194#ifdef G4ROOT_DEBUG
195 G4cout.precision(12);
196 G4cout << "ComputeStep: point=" << pGlobalPoint << " dir=" << pDirection
197 << G4endl;
198 G4cout << " pstep=" << pCurrentProposedStepLength
199 << " snext=" << step << G4endl;
200 G4cout << " safe =" << pNewSafety << " frombdr=" << frombdr
201 << " oldpoint=" << oldpoint << " entering=" << fStepEntering
202 << " exiting=" << fStepExiting << G4endl;
203 if (fStepEntering || fStepExiting && fNavigator->GetNextNode()) {
204 G4cout << " current: "
205 << fNavigator->GetCurrentNode()->GetName()
206 << " next: " << fNavigator->GetNextNode()->GetName() << G4endl;
207 }
208#endif
209 return step;
210}
211
212//______________________________________________________________________________
214 const G4ThreeVector& point, const G4ThreeVector& direction,
215 const G4TouchableHistory& h)
216{
229#ifdef G4ROOT_DEBUG
230 G4cout.precision(12);
231 G4cout << "ResetHierarchyAndLocate: POINT: " << point << " DIR: " << direction
232 << G4endl;
233#endif
234 ResetState();
235 fEnteredDaughter = kFALSE;
236 fExitedMother = kFALSE;
237 fStepEntering = kFALSE;
238 fStepExiting = kFALSE;
239 fHistory = *h.GetHistory();
241 fNavigator->InitTrack(point.x() * gCm, point.y() * gCm, point.z() * gCm,
242 direction.x(), direction.y(), direction.z());
243 G4VPhysicalVolume* pVol = SynchronizeHistory();
244 return pVol;
245}
246
247//______________________________________________________________________________
249{
253 Int_t geolevel = fNavigator->GetLevel();
254 Int_t depth = fHistory.GetDepth();
255 Int_t nodeIndex, level;
256 G4VPhysicalVolume* pvol;
257 TGeoNode *pnode, *newnode = 0;
258 for (level = 1; level <= depth; level++) {
259 pvol = fHistory.GetVolume(level);
260 newnode = fDetConstruction->GetNode(pvol);
261 if (level <= geolevel) {
262 // TGeo has also something at this level - check if it matches what is
263 // in fHistory
264 pnode = fNavigator->GetMother(geolevel - level);
265 // If the node at this level matches the one in the history, do nothing
266 if (pnode == newnode) continue;
267 // From this level down we need to update TGeo path.
268 while (geolevel >= level) {
269 fNavigator->CdUp();
270 geolevel--;
271 }
272 // Now TGeo is at level-1 and needs to update level
273 // this should be the index of the node to be used in CdDown(index)
274 nodeIndex = fNavigator->GetCurrentVolume()->GetIndex(newnode);
275 if (nodeIndex < 0) {
276 G4cerr << "SynchronizeGeoManager did not work (1)!!!" << G4endl;
277 return NULL;
278 }
279 // nodeIndex = fHistory.GetReplicaNo(level);
280 fNavigator->CdDown(nodeIndex);
281 geolevel++; // Should be equal to i now
282 }
283 else {
284 // This level has to be synchronized
285 nodeIndex = fNavigator->GetCurrentVolume()->GetIndex(newnode);
286 if (nodeIndex < 0) {
287 G4cerr << "SynchronizeGeoManager did not work (2)!!!" << G4endl;
288 return NULL;
289 }
290 // nodeIndex = fHistory.GetReplicaNo(level);
291 fNavigator->CdDown(nodeIndex);
292 geolevel++; // Should be equal to i now
293 }
294 }
295 return fNavigator->GetCurrentNode();
296}
297
298//______________________________________________________________________________
300{
304 Int_t depth = fHistory.GetDepth();
305 Int_t geolevel = fNavigator->GetLevel();
306 G4VPhysicalVolume *pvol, *pnewvol = 0;
307 TGeoNode* pnode;
308 Int_t level;
309 for (level = 0; level <= geolevel; level++) {
310 pnode = fNavigator->GetMother(geolevel - level);
311 pnewvol = fDetConstruction->GetG4VPhysicalVolume(pnode);
312 if (level <= depth) {
313 pvol = fHistory.GetVolume(level);
314 // If the phys. volume at this level matches the one in the history, do
315 // nothing
316 if (pvol == pnewvol) continue;
317 // From this level down we need to update G4 history.
318 if (level) {
319 fHistory.BackLevel(depth - level + 1);
320 // Now fHistory is at the level i-1 and needs to update level i
321 fHistory.NewLevel(pnewvol, kNormal, pnewvol->GetCopyNo());
322 }
323 else {
324 // We need to refresh top level
325 fHistory.BackLevel(depth);
326 fHistory.SetFirstEntry(pnewvol);
327 }
328 depth = level;
329 }
330 else {
331 // This level has to be added to the current history.
332 fHistory.NewLevel(pnewvol, kNormal, pnewvol->GetCopyNo());
333 depth++; // depth=level
334 }
335 }
336 if (depth > level - 1) fHistory.BackLevel(depth - level + 1);
337 if (fNavigator->IsOutside()) pnewvol = NULL;
338 return pnewvol;
339}
340
341//______________________________________________________________________________
343 const G4ThreeVector& globalPoint, const G4ThreeVector* pGlobalDirection,
344 const G4bool /*relativeSearch*/, const G4bool ignoreDirection)
345{
357
358 static Long64_t ilocate = 0;
359 ilocate++;
360
361 // Flag if geometry state was recovered.
362 Bool_t isGeoStateRestored = kFALSE;
363 // Try recstore geometry for those G4Tracks which are treated as primaries
364 // since they might have been transferred to GEANT4 from another engine
366 fG4TrackingManager->GetTrack()->GetParentID() == 0) {
367 Int_t currG4TrackId = fG4TrackingManager->GetTrack()->GetTrackID();
368 isGeoStateRestored = fRestoreGeoStateFunction(currG4TrackId);
369 }
370
371#ifdef G4ROOT_DEBUG
372 G4cout.precision(12);
373 G4cout << "LocateGlobalPointAndSetup #" << ilocate
374 << ": point: " << globalPoint << G4endl;
375#endif
376 fNavigator->SetCurrentPoint(
377 globalPoint.x() * gCm, globalPoint.y() * gCm, globalPoint.z() * gCm);
378 fEnteredDaughter = fExitedMother = kFALSE;
379 Bool_t onBoundary = kFALSE;
381 Double_t d2 = globalPoint.diff2(fNextPoint);
382 if (d2 < 1.e-16) {
383 // fNextPoint = globalPoint;
384 onBoundary = kTRUE;
385 }
386#ifdef G4ROOT_DEBUG
387 if (onBoundary)
388 G4cout << " ON BOUNDARY "
389 << "entering/exiting = " << fStepEntering << "/" << fStepExiting
390 << G4endl;
391 else
392 G4cout << " IN VOLUME "
393 << "entering/exiting = " << fStepEntering << "/" << fStepExiting
394 << G4endl;
395#endif
396 }
397 if ((!ignoreDirection || onBoundary) && pGlobalDirection) {
398 fNavigator->SetCurrentDirection(
399 pGlobalDirection->x(), pGlobalDirection->y(), pGlobalDirection->z());
400 }
401
402#ifdef G4ROOT_DEBUG
403 printf(" level %i: %s\n", fNavigator->GetLevel(), fNavigator->GetPath());
404 if (fNavigator->IsOutside()) G4cout << " outside" << G4endl;
405#endif
406 if (onBoundary) {
407 fEnteredDaughter = fStepEntering;
408 fExitedMother = fStepExiting;
409 TGeoNode* skip = fNavigator->GetCurrentNode();
410 if (fNavigator->IsOutside()) skip = NULL;
411 if (fStepExiting && !fNavigator->GetLevel()) {
412 fNavigator->SetOutside();
413 return NULL;
414 }
415 fNavigator->CdNext();
416 fNavigator->CrossBoundaryAndLocate(fStepEntering, skip);
417 }
418 else if (!isGeoStateRestored) {
419 // if (!relativeSearch) fNavigator->CdTop();
420 fNavigator->FindNode();
421 }
422 G4VPhysicalVolume* target = SynchronizeHistory();
423#ifdef G4ROOT_DEBUG
424 if (target)
425 G4cout << " POINT INSIDE: " << target->GetName()
426 << " entered=" << fEnteredDaughter << " exited=" << fExitedMother
427 << G4endl;
428#endif
429 return target;
430}
431
432//______________________________________________________________________________
434 const G4ThreeVector& pGlobalPoint)
435{
446#ifdef G4ROOT_DEBUG
447 G4cout.precision(12);
448 G4cout << "LocateGlobalPointWithinVolume " << pGlobalPoint << G4endl;
449#endif
450 fNavigator->SetCurrentPoint(
451 pGlobalPoint.x() * gCm, pGlobalPoint.y() * gCm, pGlobalPoint.z() * gCm);
452 fStepEntering = kFALSE;
453 fStepExiting = kFALSE;
454 fEnteredDaughter = kFALSE;
455 fExitedMother = kFALSE;
456}
457
458//______________________________________________________________________________
459G4double TG4RootNavigator::ComputeSafety(const G4ThreeVector& globalpoint,
460 const G4double pProposedMaxLength, const G4bool /*keepState*/)
461{
463 G4double saf = ComputeSafety(globalpoint, pProposedMaxLength);
464 return saf;
465}
466
467//______________________________________________________________________________
469 const G4ThreeVector& globalpoint, const G4double /*pProposedMaxLength*/)
470{
477
483 Double_t d2 = globalpoint.diff2(fNextPoint);
484 if (d2 < 1.e-10) {
485#ifdef G4ROOT_DEBUG
486 G4cout << "ComputeSafety: POINT on boundary: " << globalpoint
487 << " SKIPPED... oldsafe= 0.0" << G4endl;
488#endif
489 return 0.0;
490 }
491 d2 = globalpoint.diff2(fSafetyOrig);
492 if (d2 < 1.e-10) {
493#ifdef G4ROOT_DEBUG
494 G4cout << "ComputeSafety: POINT not changed: " << globalpoint
495 << " SKIPPED... oldsafe=" << fLastSafety << G4endl;
496#endif
497 return fLastSafety;
498 }
499 fNavigator->ResetState();
500 fNavigator->SetCurrentPoint(
501 globalpoint.x() * gCm, globalpoint.y() * gCm, globalpoint.z() * gCm);
502 G4double safety = fNavigator->Safety() * cm;
503 fSafetyOrig = globalpoint;
504 fLastSafety = safety;
505
506#ifdef G4ROOT_DEBUG
507 G4cout.precision(12);
508 G4cout << "ComputeSafety: POINT: " << globalpoint << " safe = " << safety
509 << G4endl;
510#endif
511 return safety;
512}
513
514//______________________________________________________________________________
516{
518 return G4Navigator::CreateTouchableHistoryHandle();
519}
520
521//______________________________________________________________________________
522G4ThreeVector TG4RootNavigator::GetLocalExitNormal(G4bool* valid)
523{
532 Double_t *norm, lnorm[3];
533 *valid = true;
534 norm = fNavigator->FindNormalFast();
535 G4ThreeVector normal(0., 0., 1.);
536 if (!norm) {
537 *valid = false;
538 return normal;
539 }
540 fNavigator->MasterToLocalVect(norm, lnorm);
541 normal.setX(lnorm[0]);
542 normal.setY(lnorm[1]);
543 normal.setZ(lnorm[2]);
544#ifdef G4ROOT_DEBUG
545 G4cout << "GetLocalExitNormal: " << normal << G4endl;
546#endif
547 return normal;
548}
549
550//______________________________________________________________________________
552 const G4ThreeVector& /*point*/, G4bool* valid)
553{
554 // Return Exit Surface Normal and validity too.
555 // Can only be called if the Navigator's last Step has crossed a
556 // volume geometrical boundary.
557 // It returns the Normal to the surface pointing out of the volume that
558 // was left behind and/or into the volume that was entered.
559 // Convention:
560 // The *local* normal is in the coordinate system of the *final* volume.
561 // Restriction:
562 // Normals are not available for replica volumes (returns valid= false)
563 // These methods takes full care about how to calculate this normal,
564 // but if the surfaces are not convex it will return valid=false.
565 Double_t* norm;
566 *valid = true;
567 norm = fNavigator->FindNormalFast();
568 G4ThreeVector normal(0., 0., 1.);
569 if (!norm) {
570 *valid = false;
571 return normal;
572 }
573 normal.setX(norm[0]);
574 normal.setY(norm[1]);
575 normal.setZ(norm[2]);
576#ifdef G4ROOT_DEBUG
577 G4cout << "GetGlobalExitNormal: " << normal << G4endl;
578#endif
579 return normal;
580}
581
582//______________________________________________________________________________
583void TG4RootNavigator::SetG4TrackingManager(G4TrackingManager* trackingManager)
584{
585 fG4TrackingManager = trackingManager;
586}
587
588//______________________________________________________________________________
590 std::function<Bool_t(Int_t)> restoreGeoStateFunction)
591{
592 fRestoreGeoStateFunction = restoreGeoStateFunction;
593}
Definition of the TG4RootDetectorConstruction and TVirtualUserPostDetConstruction classes.
static const double gCm
constant for conversion cm <-> mm
static const int gAbandonZeroSteps
static const double gZeroStepThr
Definition of the TG4RootNavigator class.
Builder creating a pseudo G4 geometry starting from a TGeo geometry.
G4VPhysicalVolume * GetG4VPhysicalVolume(const TGeoNode *node) const
TGeoManager * GetGeometryManager() const
Return TGeo geometry manager.
TGeoNode * GetNode(const G4VPhysicalVolume *g4vol) const
G4VPhysicalVolume * GetTopPV() const
Return the World G4 physical volume.
G4VPhysicalVolume * SynchronizeHistory()
G4double fLastSafety
Last computed safety.
void SetG4TrackingManager(G4TrackingManager *trackingManager)
Set current G4TrackingManager.
virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4double pProposedMaxLength)
TG4RootDetectorConstruction * fDetConstruction
virtual G4ThreeVector GetLocalExitNormal(G4bool *valid)
virtual G4TouchableHandle CreateTouchableHistoryHandle() const
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
TGeoNode * SynchronizeGeoManager()
TGeoManager * fGeometry
TGeo geometry manager.
TGeoNavigator * fNavigator
TGeo navigator.
void SetGeometryRestoreFunction(std::function< Bool_t(Int_t)> restoreGeoStateFunction)
Int_t fNzeroSteps
Number of zero steps in ComputeStep.
virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid)
virtual G4VPhysicalVolume * ResetHierarchyAndLocate(const G4ThreeVector &point, const G4ThreeVector &direction, const G4TouchableHistory &h)
G4ThreeVector fNextPoint
Crossing point with next boundary.
G4ThreeVector fSafetyOrig
Last computed safety origin.
virtual G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=0, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true)
G4TrackingManager * fG4TrackingManager
Store pointer to G4TrackingManager.
std::function< Bool_t(Int_t)> fRestoreGeoStateFunction
virtual G4double ComputeStep(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double pCurrentProposedStepLength, G4double &pNewSafety)
Bool_t fStepExiting
Next step is exiting current volume.
void SetDetectorConstruction(TG4RootDetectorConstruction *dc)
Bool_t fStepEntering
Next step is entering daughter.