Geant4  10.02.p02
G4Navigator.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: G4Navigator.cc 2012-11-01 japost Exp $
28 // GEANT4 tag $ Name: $
29 //
30 // class G4Navigator Implementation
31 //
32 // Original author: Paul Kent, July 95/96
33 // Responsible 1996-present: John Apostolakis
34 // Co-maintainer: Gabriele Cosmo
35 // Additional revisions by: Pedro Arce, Vladimir Grichine
36 // --------------------------------------------------------------------
37 
38 #include <iomanip>
39 
40 #include "G4Navigator.hh"
41 #include "G4ios.hh"
42 #include "G4SystemOfUnits.hh"
43 #include "G4GeometryTolerance.hh"
44 #include "G4VPhysicalVolume.hh"
45 
46 #include "G4VoxelSafety.hh"
47 
48 // ********************************************************************
49 // Constructor
50 // ********************************************************************
51 //
53  : fWasLimitedByGeometry(false), fVerbose(0),
54  fTopPhysical(0), fCheck(false), fPushed(false), fWarnPush(true)
55 {
56  fActive= false;
58 
60  // Initialises also all
61  // - exit / entry flags
62  // - flags & variables for exit normals
63  // - zero step counters
64  // - blocked volume
65 
68 
70  fMinStep = 0.05*kCarTolerance;
72 
74 
77 
79 }
80 
81 // ********************************************************************
82 // Destructor
83 // ********************************************************************
84 //
86 {
87  delete fpVoxelSafety;
88 }
89 
90 // ********************************************************************
91 // ResetHierarchyAndLocate
92 // ********************************************************************
93 //
96  const G4ThreeVector &direction,
97  const G4TouchableHistory &h)
98 {
99  ResetState();
100  fHistory = *h.GetHistory();
101  SetupHierarchy();
102  fLastTriedStepComputation= false; // Redundant, but best
103  return LocateGlobalPointAndSetup(p, &direction, true, false);
104 }
105 
106 // ********************************************************************
107 // LocateGlobalPointAndSetup
108 //
109 // Locate the point in the hierarchy return 0 if outside
110 // The direction is required
111 // - if on an edge shared by more than two surfaces
112 // (to resolve likely looping in tracking)
113 // - at initial location of a particle
114 // (to resolve potential ambiguity at boundary)
115 //
116 // Flags on exit: (comments to be completed)
117 // fEntering - True if entering `daughter' volume (or replica)
118 // whether daughter of last mother directly
119 // or daughter of that volume's ancestor.
120 // fExiting - True if exited 'mother' volume
121 // (always ? - how about if going back down ? - tbc)
122 // ********************************************************************
123 //
126  const G4ThreeVector* pGlobalDirection,
127  const G4bool relativeSearch,
128  const G4bool ignoreDirection )
129 {
130  G4bool notKnownContained=true, noResult;
131  G4VPhysicalVolume *targetPhysical;
132  G4LogicalVolume *targetLogical;
133  G4VSolid *targetSolid=0;
134  G4ThreeVector localPoint, globalDirection;
135  EInside insideCode;
136 
137  G4bool considerDirection = (!ignoreDirection) || fLocatedOnEdge;
138 
140  fChangedGrandMotherRefFrame= false; // For local exit normal
141 
142  if( considerDirection && pGlobalDirection != 0 )
143  {
144  globalDirection=*pGlobalDirection;
145  }
146 
147 #ifdef G4VERBOSE
148  if( fVerbose > 2 )
149  {
150  G4int oldcoutPrec = G4cout.precision(8);
151  G4cout << "*** G4Navigator::LocateGlobalPointAndSetup: ***" << G4endl;
152  G4cout << " Called with arguments: " << G4endl
153  << " Globalpoint = " << globalPoint << G4endl
154  << " RelativeSearch = " << relativeSearch << G4endl;
155  if( fVerbose >= 4 )
156  {
157  G4cout << " ----- Upon entering:" << G4endl;
158  PrintState();
159  }
160  G4cout.precision(oldcoutPrec);
161  }
162 #endif
163 
164  G4int noLevelsExited=0 ;
165  G4int noLevelsEntered= 0;
166 
167  if ( !relativeSearch )
168  {
170  }
171  else
172  {
173  if ( fWasLimitedByGeometry )
174  {
175  fWasLimitedByGeometry = false;
176  fEnteredDaughter = fEntering; // Remember
177  fExitedMother = fExiting; // Remember
178  if ( fExiting )
179  {
180  noLevelsExited++; // count this first level entered too
181 
182  if ( fHistory.GetDepth() )
183  {
187  }
188  else
189  {
190  fLastLocatedPointLocal = localPoint;
191  fLocatedOutsideWorld = true;
192  fBlockedPhysicalVolume = 0; // to be sure
193  fBlockedReplicaNo = -1;
194  fEntering = false; // No longer
195  fEnteredDaughter = false;
196  fExitedMother = true; // ??
197 
198  return 0; // Have exited world volume
199  }
200  // A fix for the case where a volume is "entered" at an edge
201  // and a coincident surface exists outside it.
202  // - This stops it from exiting further volumes and cycling
203  // - However ReplicaNavigator treats this case itself
204  //
205  // assert( fBlockedPhysicalVolume!=0 );
206 
207  // Expect to be on edge => on surface
208  //
210  {
211  fExiting= false;
212  // Consider effect on Exit Normal !?
213  }
214  }
215  else
216  if ( fEntering )
217  {
218  // assert( fBlockedPhysicalVolume!=0 );
219 
220  noLevelsEntered++; // count the first level entered too
221 
223  {
224  case kNormal:
227  break;
228  case kReplica:
234  break;
235  case kParameterised:
237  {
238  G4VSolid *pSolid;
239  G4VPVParameterisation *pParam;
240  G4TouchableHistory parentTouchable( fHistory );
242  pSolid = pParam->ComputeSolid(fBlockedReplicaNo,
244  pSolid->ComputeDimensions(pParam, fBlockedReplicaNo,
251  //
252  // Set the correct solid and material in Logical Volume
253  //
254  G4LogicalVolume *pLogical;
256  pLogical->SetSolid( pSolid );
257  pLogical->UpdateMaterial(pParam ->
258  ComputeMaterial(fBlockedReplicaNo,
260  &parentTouchable));
261  }
262  break;
263  }
264  fEntering = false;
266  localPoint = fHistory.GetTopTransform().TransformPoint(globalPoint);
267  notKnownContained = false;
268  }
269  }
270  else
271  {
273  fEntering = false;
274  fEnteredDaughter = false; // Full Step was not taken, did not enter
275  fExiting = false;
276  fExitedMother = false; // Full Step was not taken, did not exit
277  }
278  }
279  //
280  // Search from top of history up through geometry until
281  // containing volume found:
282  // If on
283  // o OUTSIDE - Back up level, not/no longer exiting volumes
284  // o SURFACE and EXITING - Back up level, setting new blocking no.s
285  // else
286  // o containing volume found
287  //
288 
289  while (notKnownContained)
290  {
292  {
293  targetSolid = fHistory.GetTopVolume()->GetLogicalVolume()->GetSolid();
294  localPoint = fHistory.GetTopTransform().TransformPoint(globalPoint);
295  insideCode = targetSolid->Inside(localPoint);
296 #ifdef G4VERBOSE
297  if(( fVerbose == 1 ) && ( fCheck ))
298  {
299  G4String solidResponse = "-kInside-";
300  if (insideCode == kOutside)
301  solidResponse = "-kOutside-";
302  else if (insideCode == kSurface)
303  solidResponse = "-kSurface-";
304  G4cout << "*** G4Navigator::LocateGlobalPointAndSetup(): ***" << G4endl
305  << " Invoked Inside() for solid: " << targetSolid->GetName()
306  << ". Solid replied: " << solidResponse << G4endl
307  << " For local point p: " << localPoint << G4endl;
308  }
309 #endif
310  }
311  else
312  {
313  insideCode = freplicaNav.BackLocate(fHistory, globalPoint, localPoint,
314  fExiting, notKnownContained);
315  // !CARE! if notKnownContained returns false then the point is within
316  // the containing placement volume of the replica(s). If insidecode
317  // will result in the history being backed up one level, then the
318  // local point returned is the point in the system of this new level
319  }
320 
321 
322  if ( insideCode==kOutside )
323  {
324  noLevelsExited++;
325  if ( fHistory.GetDepth() )
326  {
330  fExiting = false;
331 
332  if( noLevelsExited > 1 )
333  {
334  // The first transformation was done by the sub-navigator
335  //
337  if( mRot )
338  {
339  fGrandMotherExitNormal *= (*mRot).inverse();
341  }
342  }
343  }
344  else
345  {
346  fLastLocatedPointLocal = localPoint;
347  fLocatedOutsideWorld = true;
348  // No extra transformation for ExitNormal - is in frame of Top Volume
349  return 0; // Have exited world volume
350  }
351  }
352  else
353  if ( insideCode==kSurface )
354  {
355  G4bool isExiting = fExiting;
356  if( (!fExiting)&&considerDirection )
357  {
358  // Figure out whether we are exiting this level's volume
359  // by using the direction
360  //
361  G4bool directionExiting = false;
362  G4ThreeVector localDirection =
363  fHistory.GetTopTransform().TransformAxis(globalDirection);
364 
365  // Make sure localPoint in correct reference frame
366  // ( Was it already correct ? How ? )
367  //
368  localPoint= fHistory.GetTopTransform().TransformPoint(globalPoint);
370  {
371  G4ThreeVector normal = targetSolid->SurfaceNormal(localPoint);
372  directionExiting = normal.dot(localDirection) > 0.0;
373  isExiting = isExiting || directionExiting;
374  }
375  }
376  if( isExiting )
377  {
378  noLevelsExited++;
379  if ( fHistory.GetDepth() )
380  {
384  //
385  // Still on surface but exited volume not necessarily convex
386  //
387  fValidExitNormal = false;
388 
389  if( noLevelsExited > 1 )
390  {
391  // The first transformation was done by the sub-navigator
392  //
393  const G4RotationMatrix* mRot =
395  if( mRot )
396  {
397  fGrandMotherExitNormal *= (*mRot).inverse();
399  }
400  }
401  }
402  else
403  {
404  fLastLocatedPointLocal = localPoint;
405  fLocatedOutsideWorld = true;
406  // No extra transformation for ExitNormal, is in frame of Top Vol
407  return 0; // Have exited world volume
408  }
409  }
410  else
411  {
412  notKnownContained=false;
413  }
414  }
415  else
416  {
417  notKnownContained=false;
418  }
419  } // END while (notKnownContained)
420  //
421  // Search downwards until deepest containing volume found,
422  // blocking fBlockedPhysicalVolume/BlockedReplicaNum
423  //
424  // 3 Cases:
425  //
426  // o Parameterised daughters
427  // =>Must be one G4PVParameterised daughter & voxels
428  // o Positioned daughters & voxels
429  // o Positioned daughters & no voxels
430 
431  noResult = true; // noResult should be renamed to
432  // something like enteredLevel, as that is its meaning.
433  do
434  {
435  // Determine `type' of current mother volume
436  //
437  targetPhysical = fHistory.GetTopVolume();
438  if (!targetPhysical) { break; }
439  targetLogical = targetPhysical->GetLogicalVolume();
440  switch( CharacteriseDaughters(targetLogical) )
441  {
442  case kNormal:
443  if ( targetLogical->GetVoxelHeader() ) // use optimised navigation
444  {
445  noResult = fvoxelNav.LevelLocate(fHistory,
448  globalPoint,
449  pGlobalDirection,
450  considerDirection,
451  localPoint);
452  }
453  else // do not use optimised navigation
454  {
455  noResult = fnormalNav.LevelLocate(fHistory,
458  globalPoint,
459  pGlobalDirection,
460  considerDirection,
461  localPoint);
462  }
463  break;
464  case kReplica:
465  noResult = freplicaNav.LevelLocate(fHistory,
468  globalPoint,
469  pGlobalDirection,
470  considerDirection,
471  localPoint);
472  break;
473  case kParameterised:
474  if( GetDaughtersRegularStructureId(targetLogical) != 1 )
475  {
476  noResult = fparamNav.LevelLocate(fHistory,
479  globalPoint,
480  pGlobalDirection,
481  considerDirection,
482  localPoint);
483  }
484  else // Regular structure
485  {
486  noResult = fregularNav.LevelLocate(fHistory,
489  globalPoint,
490  pGlobalDirection,
491  considerDirection,
492  localPoint);
493  }
494  break;
495  }
496 
497  // LevelLocate returns true if it finds a daughter volume
498  // in which globalPoint is inside (or on the surface).
499 
500  if ( noResult )
501  {
502  noLevelsEntered++;
503 
504  // Entering a daughter after ascending
505  //
506  // The blocked volume is no longer valid - it was for another level
507  //
509  fBlockedReplicaNo = -1;
510 
511  // fEntering should be false -- else blockedVolume is assumed good.
512  // fEnteredDaughter is used for ExitNormal
513  //
514  fEntering = false;
515  fEnteredDaughter = true;
516 
517  if( fExitedMother )
518  {
519  G4VPhysicalVolume* enteredPhysical = fHistory.GetTopVolume();
520  const G4RotationMatrix* mRot = enteredPhysical->GetRotation();
521  if( mRot )
522  {
523  // Go deeper, i.e. move 'down' in the hierarchy
524  // Apply direct rotation, not inverse
525  //
526  fGrandMotherExitNormal *= (*mRot);
528  }
529  }
530 
531 #ifdef G4DEBUG_NAVIGATION
532  if( fVerbose > 2 )
533  {
534  G4VPhysicalVolume* enteredPhysical = fHistory.GetTopVolume();
535  G4cout << "*** G4Navigator::LocateGlobalPointAndSetup() ***" << G4endl;
536  G4cout << " Entering volume: " << enteredPhysical->GetName()
537  << G4endl;
538  }
539 #endif
540  }
541  } while (noResult);
542 
543  fLastLocatedPointLocal = localPoint;
544 
545 #ifdef G4VERBOSE
546  if( fVerbose >= 4 )
547  {
548  G4int oldcoutPrec = G4cout.precision(8);
549  G4String curPhysVol_Name("None");
550  if (targetPhysical) { curPhysVol_Name = targetPhysical->GetName(); }
551  G4cout << " Return value = new volume = " << curPhysVol_Name << G4endl;
552  G4cout << " ----- Upon exiting:" << G4endl;
553  PrintState();
554  if( fVerbose >= 5 )
555  {
556  G4cout << "Upon exiting LocateGlobalPointAndSetup():" << G4endl;
557  G4cout << " History = " << G4endl << fHistory << G4endl << G4endl;
558  }
559  G4cout.precision(oldcoutPrec);
560  }
561 #endif
562 
563  fLocatedOutsideWorld= false;
564 
565  return targetPhysical;
566 }
567 
568 // ********************************************************************
569 // LocateGlobalPointWithinVolume
570 //
571 // -> the state information of this Navigator and its subNavigators
572 // is updated in order to start the next step at pGlobalpoint
573 // -> no check is performed whether pGlobalpoint is inside the
574 // original volume (this must be the case).
575 //
576 // Note: a direction could be added to the arguments, to aid in future
577 // optional checking (via the old code below, flagged by OLD_LOCATE).
578 // [ This would be done only in verbose mode ]
579 // ********************************************************************
580 //
581 void
583 {
584 #ifdef G4DEBUG_NAVIGATION
585  // Check: Either step was not limited by a boundary
586  // or else the full step is no longer being taken
587  assert( !fWasLimitedByGeometry );
588 #endif
589 
592  fChangedGrandMotherRefFrame= false; // Frame for Exit Normal
593 
594 #ifdef G4DEBUG_NAVIGATION
595  if( fVerbose > 2 )
596  {
597  G4cout << "Entering LocateGlobalWithinVolume(): History = " << G4endl;
598  G4cout << fHistory << G4endl;
599  }
600 #endif
601 
602  // For the case of Voxel (or Parameterised) volume the respective
603  // Navigator must be messaged to update its voxel information etc
604 
605  // Update the state of the Sub Navigators
606  // - in particular any voxel information they store/cache
607  //
608  G4VPhysicalVolume* motherPhysical = fHistory.GetTopVolume();
609  G4LogicalVolume* motherLogical = motherPhysical->GetLogicalVolume();
610  G4SmartVoxelHeader* pVoxelHeader = motherLogical->GetVoxelHeader();
611 
613  {
614  switch( CharacteriseDaughters(motherLogical) )
615  {
616  case kNormal:
617  if ( pVoxelHeader )
618  {
620  }
621  break;
622  case kParameterised:
623  if( GetDaughtersRegularStructureId(motherLogical) != 1 )
624  {
625  // Resets state & returns voxel node
626  //
628  }
629  break;
630  case kReplica:
631  G4Exception("G4Navigator::LocateGlobalPointWithinVolume()",
632  "GeomNav0001", FatalException,
633  "Not applicable for replicated volumes.");
634  break;
635  }
636  }
637 
638  // Reset the state variables
639  // - which would have been affected
640  // by the 'equivalent' call to LocateGlobalPointAndSetup
641  // - who's values have been invalidated by the 'move'.
642  //
644  fBlockedReplicaNo = -1;
645  fEntering = false;
646  fEnteredDaughter = false; // Boundary not encountered, did not enter
647  fExiting = false;
648  fExitedMother = false; // Boundary not encountered, did not exit
649 }
650 
651 // ********************************************************************
652 // SetSavedState
653 //
654 // Save the state, in case this is a parasitic call
655 // Save fValidExitNormal, fExitNormal, fExiting, fEntering,
656 // fBlockedPhysicalVolume, fBlockedReplicaNo, fLastStepWasZero;
657 // ********************************************************************
658 //
660 {
661  // Note: the state of dependent objects is not currently saved.
662  // ( This means that the full state is changed by calls between
663  // SetSavedState() and RestoreSavedState();
664 
669 
672 
674 
680 
681  // Even the safety sphere - if you want to change it do it explicitly!
682  //
685 }
686 
687 // ********************************************************************
688 // RestoreSavedState
689 //
690 // Restore the state (in Compute Step), in case this is a parasitic call
691 // ********************************************************************
692 //
694 {
699 
702 
704 
710 
711  // The 'expected' behaviour is to restore these too (fix 2014.05.26)
714 }
715 
716 // ********************************************************************
717 // ComputeStep
718 //
719 // Computes the next geometric Step: intersections with current
720 // mother and `daughter' volumes.
721 //
722 // NOTE:
723 //
724 // Flags on entry:
725 // --------------
726 // fValidExitNormal - Normal of exited volume is valid (convex, not a
727 // coincident boundary)
728 // fExitNormal - Surface normal of exited volume
729 // fExiting - True if have exited solid
730 //
731 // fBlockedPhysicalVolume - Ptr to exited volume (or 0)
732 // fBlockedReplicaNo - Replication no of exited volume
733 // fLastStepWasZero - True if last Step size was almost zero.
734 //
735 // Flags on exit:
736 // -------------
737 // fValidExitNormal - True if surface normal of exited volume is valid
738 // fExitNormal - Surface normal of exited volume rotated to mothers
739 // reference system
740 // fExiting - True if exiting mother
741 // fEntering - True if entering `daughter' volume (or replica)
742 // fBlockedPhysicalVolume - Ptr to candidate (entered) volume
743 // fBlockedReplicaNo - Replication no of candidate (entered) volume
744 // fLastStepWasZero - True if this Step size was almost zero.
745 // ********************************************************************
746 //
748  const G4ThreeVector &pDirection,
749  const G4double pCurrentProposedStepLength,
750  G4double &pNewSafety)
751 {
752  G4ThreeVector localDirection = ComputeLocalAxis(pDirection);
754  G4VPhysicalVolume *motherPhysical = fHistory.GetTopVolume();
755  G4LogicalVolume *motherLogical = motherPhysical->GetLogicalVolume();
756 
757  // All state relating to exiting normals must be reset
758  //
760  // Reset value - to erase its memory
762  // Reset - used for local exit normal
763  fGrandMotherExitNormal= G4ThreeVector( 0., 0., 0.);
764  fCalculatedExitNormal = false;
765  // Reset for new step
766 
767  static G4ThreadLocal G4int sNavCScalls=0;
768  sNavCScalls++;
769 
771 
772 #ifdef G4VERBOSE
773  if( fVerbose > 0 )
774  {
775  G4cout << "*** G4Navigator::ComputeStep: ***" << G4endl;
776  G4cout << " Volume = " << motherPhysical->GetName()
777  << " - Proposed step length = " << pCurrentProposedStepLength
778  << G4endl;
779 #ifdef G4DEBUG_NAVIGATION
780  if( fVerbose >= 2 )
781  {
782  G4cout << " Called with the arguments: " << G4endl
783  << " Globalpoint = " << std::setw(25) << pGlobalpoint << G4endl
784  << " Direction = " << std::setw(25) << pDirection << G4endl;
785  if( fVerbose >= 4 )
786  {
787  G4cout << " ---- Upon entering : State" << G4endl;
788  PrintState();
789  }
790  }
791 #endif
792  }
793 #endif
794 
795  G4ThreeVector newLocalPoint = ComputeLocalPoint(pGlobalpoint);
796  if( newLocalPoint != fLastLocatedPointLocal )
797  {
798  // Check whether the relocation is within safety
799  //
800  G4ThreeVector oldLocalPoint = fLastLocatedPointLocal;
801  G4double moveLenSq = (newLocalPoint-oldLocalPoint).mag2();
802 
803  if ( moveLenSq >= fSqTol )
804  {
805 #ifdef G4VERBOSE
806  ComputeStepLog(pGlobalpoint, moveLenSq);
807 #endif
808  // Relocate the point within the same volume
809  //
810  LocateGlobalPointWithinVolume( pGlobalpoint );
811  fLastTriedStepComputation= true; // Ensure that this is set again !!
812  }
813  }
815  {
816  switch( CharacteriseDaughters(motherLogical) )
817  {
818  case kNormal:
819  if ( motherLogical->GetVoxelHeader() )
820  {
822  localDirection,
823  pCurrentProposedStepLength,
824  pNewSafety,
825  fHistory,
827  fExitNormal,
828  fExiting,
829  fEntering,
832 
833  }
834  else
835  {
836  if( motherPhysical->GetRegularStructureId() == 0 )
837  {
839  localDirection,
840  pCurrentProposedStepLength,
841  pNewSafety,
842  fHistory,
844  fExitNormal,
845  fExiting,
846  fEntering,
849  }
850  else // Regular (non-voxelised) structure
851  {
852  LocateGlobalPointAndSetup( pGlobalpoint, &pDirection, true, true );
853  fLastTriedStepComputation= true; // Ensure that this is set again !!
854  //
855  // if physical process limits the step, the voxel will not be the
856  // one given by ComputeStepSkippingEqualMaterials() and the local
857  // point will be wrongly calculated.
858 
859  // There is a problem: when msc limits the step and the point is
860  // assigned wrongly to phantom in previous step (while it is out
861  // of the container volume). Then LocateGlobalPointAndSetup() has
862  // reset the history topvolume to world.
863  //
865  {
866  G4Exception("G4Navigator::ComputeStep()",
867  "GeomNav1001", JustWarning,
868  "Point is relocated in voxels, while it should be outside!");
870  localDirection,
871  pCurrentProposedStepLength,
872  pNewSafety,
873  fHistory,
875  fExitNormal,
876  fExiting,
877  fEntering,
880  }
881  else
882  {
883  Step = fregularNav.
884  ComputeStepSkippingEqualMaterials(fLastLocatedPointLocal,
885  localDirection,
886  pCurrentProposedStepLength,
887  pNewSafety,
888  fHistory,
890  fExitNormal,
891  fExiting,
892  fEntering,
895  motherPhysical);
896  }
897  }
898  }
899  break;
900  case kParameterised:
901  if( GetDaughtersRegularStructureId(motherLogical) != 1 )
902  {
904  localDirection,
905  pCurrentProposedStepLength,
906  pNewSafety,
907  fHistory,
909  fExitNormal,
910  fExiting,
911  fEntering,
914  }
915  else // Regular structure
916  {
918  localDirection,
919  pCurrentProposedStepLength,
920  pNewSafety,
921  fHistory,
923  fExitNormal,
924  fExiting,
925  fEntering,
928  }
929  break;
930  case kReplica:
931  G4Exception("G4Navigator::ComputeStep()", "GeomNav0001",
932  FatalException, "Not applicable for replicated volumes.");
933  break;
934  }
935  }
936  else
937  {
938  // In the case of a replica, it must handle the exiting
939  // edge/corner problem by itself
940  //
941  G4bool exitingReplica = fExitedMother;
942  G4bool calculatedExitNormal;
943  Step = freplicaNav.ComputeStep(pGlobalpoint,
944  pDirection,
946  localDirection,
947  pCurrentProposedStepLength,
948  pNewSafety,
949  fHistory,
951  calculatedExitNormal,
952  fExitNormal,
953  exitingReplica,
954  fEntering,
957  fExiting= exitingReplica;
958  fCalculatedExitNormal= calculatedExitNormal;
959  }
960 
961  // Remember last safety origin & value.
962  //
963  fPreviousSftOrigin = pGlobalpoint;
964  fPreviousSafety = pNewSafety;
965 
966  // Count zero steps - one can occur due to changing momentum at a boundary
967  // - one, two (or a few) can occur at common edges between
968  // volumes
969  // - more than two is likely a problem in the geometry
970  // description or the Navigation
971 
972  // Rule of thumb: likely at an Edge if two consecutive steps are zero,
973  // because at least two candidate volumes must have been
974  // checked
975  //
976  fLocatedOnEdge = fLastStepWasZero && (Step==0.0);
977  fLastStepWasZero = (Step<fMinStep);
978  if (fPushed) { fPushed = fLastStepWasZero; }
979 
980  // Handle large number of consecutive zero steps
981  //
982  if ( fLastStepWasZero )
983  {
985 #ifdef G4DEBUG_NAVIGATION
986  if( fNumberZeroSteps > 1 )
987  {
988  G4cout << "G4Navigator::ComputeStep(): another 'zero' step, # "
990  << ", at " << pGlobalpoint
991  << ", in volume " << motherPhysical->GetName()
992  << ", nav-comp-step calls # " << sNavCScalls
993  << ", Step= " << Step
994  << G4endl;
995  }
996 #endif
998  {
999  // Act to recover this stuck track. Pushing it along direction
1000  //
1001  Step += 100*kCarTolerance;
1002 #ifdef G4VERBOSE
1003  if ((!fPushed) && (fWarnPush))
1004  {
1005  std::ostringstream message;
1006  message << "Track stuck or not moving." << G4endl
1007  << " Track stuck, not moving for "
1008  << fNumberZeroSteps << " steps" << G4endl
1009  << " in volume -" << motherPhysical->GetName()
1010  << "- at point " << pGlobalpoint << G4endl
1011  << " direction: " << pDirection << "." << G4endl
1012  << " Potential geometry or navigation problem !"
1013  << G4endl
1014  << " Trying pushing it of " << Step << " mm ...";
1015  G4Exception("G4Navigator::ComputeStep()", "GeomNav1002",
1016  JustWarning, message, "Potential overlap in geometry!");
1017  }
1018 #endif
1019  fPushed = true;
1020  }
1022  {
1023  // Must kill this stuck track
1024  //
1025  std::ostringstream message;
1026  message << "Stuck Track: potential geometry or navigation problem."
1027  << G4endl
1028  << " Track stuck, not moving for "
1029  << fNumberZeroSteps << " steps" << G4endl
1030  << " in volume -" << motherPhysical->GetName()
1031  << "- at point " << pGlobalpoint << G4endl
1032  << " direction: " << pDirection << ".";
1033 #ifdef G4VERBOSE
1034  motherPhysical->CheckOverlaps(5000, false);
1035 #endif
1036  G4Exception("G4Navigator::ComputeStep()", "GeomNav0003",
1037  EventMustBeAborted, message);
1038  }
1039  }
1040  else
1041  {
1042  if (!fPushed) fNumberZeroSteps = 0;
1043  }
1044 
1045  fEnteredDaughter = fEntering; // I expect to enter a volume in this Step
1047 
1048  fStepEndPoint = pGlobalpoint
1049  + std::min(Step,pCurrentProposedStepLength) * pDirection;
1050  fLastStepEndPointLocal = fLastLocatedPointLocal + Step * localDirection;
1051 
1052  if( fExiting )
1053  {
1054 #ifdef G4DEBUG_NAVIGATION
1055  if( fVerbose > 2 )
1056  {
1057  G4cout << " At G4Nav CompStep End - if(exiting) - fExiting= " << fExiting
1058  << " fValidExitNormal = " << fValidExitNormal << G4endl;
1059  G4cout << " fExitNormal= " << fExitNormal << G4endl;
1060  }
1061 #endif
1062 
1064  {
1066  {
1067  // Convention: fExitNormal is in the 'grand-mother' coordinate system
1068  //
1070  fCalculatedExitNormal= true;
1071  }
1072  else
1073  {
1075  }
1076  }
1077  else
1078  {
1079  // We must calculate the normal anyway (in order to have it if requested)
1080  //
1081  G4ThreeVector finalLocalPoint =
1082  fLastLocatedPointLocal + localDirection*Step;
1083 
1085  {
1086  // Find normal in the 'mother' coordinate system
1087  //
1088  G4ThreeVector exitNormalMotherFrame=
1089  motherLogical->GetSolid()->SurfaceNormal(finalLocalPoint);
1090 
1091  // Transform it to the 'grand-mother' coordinate system
1092  //
1093  const G4RotationMatrix* mRot = motherPhysical->GetRotation();
1094  if( mRot )
1095  {
1097  fGrandMotherExitNormal = (*mRot).inverse() * exitNormalMotherFrame;
1098  }
1099  else
1100  {
1101  fGrandMotherExitNormal = exitNormalMotherFrame;
1102  }
1103 
1104  // Do not set fValidExitNormal -- this signifies
1105  // that the solid is convex!
1106  //
1107  fCalculatedExitNormal= true;
1108  }
1109  else
1110  {
1111  fCalculatedExitNormal = false;
1112  //
1113  // Nothing can be done at this stage currently - to solve this
1114  // Replica Navigation must have calculated the normal for this case
1115  // already.
1116  // Cases: mother is not convex, and exit is at previous replica level
1117 
1118 #ifdef G4DEBUG_NAVIGATION
1120 
1121  desc << "Problem in ComputeStep: Replica Navigation did not provide"
1122  << " valid exit Normal. " << G4endl;
1123  desc << " Do not know how calculate it in this case." << G4endl;
1124  desc << " Location = " << finalLocalPoint << G4endl;
1125  desc << " Volume name = " << motherPhysical->GetName()
1126  << " copy/replica No = " << motherPhysical->GetCopyNo() << G4endl;
1127  G4Exception("G4Navigator::ComputeStep()", "GeomNav0003",
1128  JustWarning, desc, "Normal not available for exiting.");
1129 #endif
1130  }
1131  }
1132 
1133  // Now transform it to the global reference frame !!
1134  //
1136  {
1137  G4int depth= fHistory.GetDepth();
1138  if( depth > 0 )
1139  {
1140  G4AffineTransform GrandMotherToGlobalTransf =
1141  fHistory.GetTransform(depth-1).Inverse();
1143  GrandMotherToGlobalTransf.TransformAxis( fGrandMotherExitNormal );
1144  }
1145  else
1146  {
1148  }
1149  }
1150  else
1151  {
1152  fExitNormalGlobalFrame= G4ThreeVector( 0., 0., 0.);
1153  }
1154  }
1155 
1156  if( (Step == pCurrentProposedStepLength) && (!fExiting) && (!fEntering) )
1157  {
1158  // This if Step is not really limited by the geometry.
1159  // The Navigator is obliged to return "infinity"
1160  //
1161  Step = kInfinity;
1162  }
1163 
1164 #ifdef G4VERBOSE
1165  if( fVerbose > 1 )
1166  {
1167  if( fVerbose >= 4 )
1168  {
1169  G4cout << " ----- Upon exiting :" << G4endl;
1170  PrintState();
1171  }
1172  G4cout << " Returned step= " << Step;
1173  if( fVerbose > 5 ) G4cout << G4endl;
1174  if( Step == kInfinity )
1175  {
1176  G4cout << " Requested step= " << pCurrentProposedStepLength ;
1177  if( fVerbose > 5) G4cout << G4endl;
1178  }
1179  G4cout << " Safety = " << pNewSafety << G4endl;
1180  }
1181 #endif
1182 
1183  return Step;
1184 }
1185 
1186 // ********************************************************************
1187 // CheckNextStep
1188 //
1189 // Compute the step without altering the navigator state
1190 // ********************************************************************
1191 //
1193  const G4ThreeVector& pDirection,
1194  const G4double pCurrentProposedStepLength,
1195  G4double& pNewSafety)
1196 {
1197  G4double step;
1198 
1199  // Save the state, for this parasitic call
1200  //
1201  SetSavedState();
1202 
1203  step = ComputeStep ( pGlobalpoint,
1204  pDirection,
1205  pCurrentProposedStepLength,
1206  pNewSafety );
1207 
1208  // It is a parasitic call, so attempt to restore the key parts of the state
1209  //
1210  RestoreSavedState();
1211  // NOTE: the state of the current subnavigator is NOT restored.
1212  // ***> TODO: restore subnavigator state
1213  // if( last_located) Need Position of last location
1214  // if( last_computed step) Need Endposition of last step
1215 
1216  return step;
1217 }
1218 
1219 // ********************************************************************
1220 // ResetState
1221 //
1222 // Resets stack and minimum of navigator state `machine'
1223 // ********************************************************************
1224 //
1226 {
1227  fWasLimitedByGeometry = false;
1228  fEntering = false;
1229  fExiting = false;
1230  fLocatedOnEdge = false;
1231  fLastStepWasZero = false;
1232  fEnteredDaughter = false;
1233  fExitedMother = false;
1234  fPushed = false;
1235 
1236  fValidExitNormal = false;
1238  fCalculatedExitNormal = false;
1239 
1240  fExitNormal = G4ThreeVector(0,0,0);
1243 
1245  fPreviousSafety = 0.0;
1246 
1247  fNumberZeroSteps = 0;
1248 
1250  fBlockedReplicaNo = -1;
1251 
1253  fLocatedOutsideWorld = false;
1254 }
1255 
1256 // ********************************************************************
1257 // SetupHierarchy
1258 //
1259 // Renavigates & resets hierarchy described by current history
1260 // o Reset volumes
1261 // o Recompute transforms and/or solids of replicated/parameterised volumes
1262 // ********************************************************************
1263 //
1265 {
1266  G4int i;
1267  const G4int cdepth = fHistory.GetDepth();
1268  G4VPhysicalVolume *current;
1269  G4VSolid *pSolid;
1270  G4VPVParameterisation *pParam;
1271 
1272  for ( i=1; i<=cdepth; i++ )
1273  {
1274  current = fHistory.GetVolume(i);
1275  switch ( fHistory.GetVolumeType(i) )
1276  {
1277  case kNormal:
1278  break;
1279  case kReplica:
1281  break;
1282  case kParameterised:
1283  G4int replicaNo;
1284  pParam = current->GetParameterisation();
1285  replicaNo = fHistory.GetReplicaNo(i);
1286  pSolid = pParam->ComputeSolid(replicaNo, current);
1287 
1288  // Set up dimensions & transform in solid/physical volume
1289  //
1290  pSolid->ComputeDimensions(pParam, replicaNo, current);
1291  pParam->ComputeTransformation(replicaNo, current);
1292 
1293  G4TouchableHistory *pTouchable= 0;
1294  if( pParam->IsNested() )
1295  {
1296  pTouchable= new G4TouchableHistory( fHistory );
1297  pTouchable->MoveUpHistory(); // Move up to the parent level
1298  // Adequate only if Nested at the Branch level (last)
1299  // To extend to other cases:
1300  // pTouchable->MoveUpHistory(cdepth-i-1);
1301  // Move to the parent level of *Current* level
1302  // Could replace this line and constructor with a revised
1303  // c-tor for History(levels to drop)
1304  }
1305  // Set up the correct solid and material in Logical Volume
1306  //
1307  G4LogicalVolume *pLogical = current->GetLogicalVolume();
1308  pLogical->SetSolid( pSolid );
1309  pLogical->UpdateMaterial( pParam ->
1310  ComputeMaterial(replicaNo, current, pTouchable) );
1311  delete pTouchable;
1312  break;
1313  }
1314  }
1315 }
1316 
1317 // ********************************************************************
1318 // GetLocalExitNormal
1319 //
1320 // Obtains the Normal vector to a surface (in local coordinates)
1321 // pointing out of previous volume and into current volume
1322 // ********************************************************************
1323 //
1325 {
1326  G4ThreeVector ExitNormal(0.,0.,0.);
1327  G4VSolid *currentSolid=0;
1328  G4LogicalVolume *candidateLogical;
1330  {
1331  // use fLastLocatedPointLocal and next candidate volume
1332  //
1333  G4ThreeVector nextSolidExitNormal(0.,0.,0.);
1334 
1335  if( fEntering && (fBlockedPhysicalVolume!=0) )
1336  {
1337  candidateLogical= fBlockedPhysicalVolume->GetLogicalVolume();
1338  if( candidateLogical )
1339  {
1340  // fLastStepEndPointLocal is in the coordinates of the mother
1341  // we need it in the daughter's coordinate system.
1342 
1343  // The following code should also work in case of Replica
1344  {
1345  // First transform fLastLocatedPointLocal to the new daughter
1346  // coordinates
1347  //
1348  G4AffineTransform MotherToDaughterTransform=
1352  G4ThreeVector daughterPointOwnLocal=
1353  MotherToDaughterTransform.TransformPoint( fLastStepEndPointLocal );
1354 
1355  // OK if it is a parameterised volume
1356  //
1357  EInside inSideIt;
1358  G4bool onSurface;
1359  G4double safety= -1.0;
1360  currentSolid= candidateLogical->GetSolid();
1361  inSideIt = currentSolid->Inside(daughterPointOwnLocal);
1362  onSurface = (inSideIt == kSurface);
1363  if( ! onSurface )
1364  {
1365  if( inSideIt == kOutside )
1366  {
1367  safety = (currentSolid->DistanceToIn(daughterPointOwnLocal));
1368  onSurface = safety < 100.0 * kCarTolerance;
1369  }
1370  else if (inSideIt == kInside )
1371  {
1372  safety = (currentSolid->DistanceToOut(daughterPointOwnLocal));
1373  onSurface = safety < 100.0 * kCarTolerance;
1374  }
1375  }
1376 
1377  if( onSurface )
1378  {
1379  nextSolidExitNormal =
1380  currentSolid->SurfaceNormal(daughterPointOwnLocal);
1381 
1382  // Entering the solid ==> opposite
1383  //
1384  ExitNormal = -nextSolidExitNormal;
1385  fCalculatedExitNormal= true;
1386  }
1387  else
1388  {
1389 #ifdef G4VERBOSE
1390  if(( fVerbose == 1 ) && ( fCheck ))
1391  {
1392  std::ostringstream message;
1393  message << "Point not on surface ! " << G4endl
1394  << " Point = "
1395  << daughterPointOwnLocal << G4endl
1396  << " Physical volume = "
1398  << " Logical volume = "
1399  << candidateLogical->GetName() << G4endl
1400  << " Solid = " << currentSolid->GetName()
1401  << " Type = "
1402  << currentSolid->GetEntityType() << G4endl
1403  << *currentSolid << G4endl;
1404  if( inSideIt == kOutside )
1405  {
1406  message << "Point is Outside. " << G4endl
1407  << " Safety (from outside) = " << safety << G4endl;
1408  }
1409  else // if( inSideIt == kInside )
1410  {
1411  message << "Point is Inside. " << G4endl
1412  << " Safety (from inside) = " << safety << G4endl;
1413  }
1414  G4Exception("G4Navigator::GetLocalExitNormal()", "GeomNav1001",
1415  JustWarning, message);
1416  }
1417 #endif
1418  }
1419  *valid = onSurface; // was =true;
1420  }
1421  }
1422  }
1423  else if ( fExiting )
1424  {
1425  ExitNormal = fGrandMotherExitNormal;
1426  *valid = true;
1427  fCalculatedExitNormal= true; // Should be true already
1428  }
1429  else // i.e. ( fBlockedPhysicalVolume == 0 )
1430  {
1431  *valid = false;
1432  G4Exception("G4Navigator::GetLocalExitNormal()",
1433  "GeomNav0003", JustWarning,
1434  "Incorrect call to GetLocalSurfaceNormal." );
1435  }
1436  }
1437  else // ( ! fLastTriedStepComputation ) ie. last call was to Locate
1438  {
1439  if ( EnteredDaughterVolume() )
1440  {
1441  G4VSolid* daughterSolid =fHistory.GetTopVolume()->GetLogicalVolume()
1442  ->GetSolid();
1443  ExitNormal= -(daughterSolid->SurfaceNormal(fLastLocatedPointLocal));
1444  if( std::fabs(ExitNormal.mag2()-1.0 ) > CLHEP::perMillion )
1445  {
1447  desc << " Parameters of solid: " << *daughterSolid
1448  << " Point for surface = " << fLastLocatedPointLocal << std::endl;
1449  G4Exception("G4Navigator::GetLocalExitNormal()",
1450  "GeomNav0003", FatalException, desc,
1451  "Surface Normal returned by Solid is not a Unit Vector." );
1452  }
1453  fCalculatedExitNormal= true;
1454  *valid = true;
1455  }
1456  else
1457  {
1458  if( fExitedMother )
1459  {
1460  ExitNormal = fGrandMotherExitNormal;
1461  *valid = true;
1462  fCalculatedExitNormal= true;
1463  }
1464  else // We are not at a boundary. ExitNormal remains (0,0,0)
1465  {
1466  *valid = false;
1467  fCalculatedExitNormal= false;
1468  G4ExceptionDescription message;
1469  message << "Function called when *NOT* at a Boundary." << G4endl;
1470  message << "Exit Normal not calculated." << G4endl;
1471  G4Exception("G4Navigator::GetLocalExitNormal()",
1472  "GeomNav0003", JustWarning, message);
1473  }
1474  }
1475  }
1476  return ExitNormal;
1477 }
1478 
1479 // ********************************************************************
1480 // GetMotherToDaughterTransform
1481 //
1482 // Obtains the mother to daughter affine transformation
1483 // ********************************************************************
1484 //
1487  G4int enteringReplicaNo,
1488  EVolume enteringVolumeType )
1489 {
1490  switch (enteringVolumeType)
1491  {
1492  case kNormal: // Nothing is needed to prepare the transformation
1493  break; // It is stored already in the physical volume (placement)
1494  case kReplica: // Sets the transform in the Replica - tbc
1495  G4Exception("G4Navigator::GetMotherToDaughterTransform()",
1496  "GeomNav0001", FatalException,
1497  "Method NOT Implemented yet for replica volumes.");
1498  break;
1499  case kParameterised:
1500  if( pEnteringPhysVol->GetRegularStructureId() == 0 )
1501  {
1502  G4VPVParameterisation *pParam =
1503  pEnteringPhysVol->GetParameterisation();
1504  G4VSolid* pSolid =
1505  pParam->ComputeSolid(enteringReplicaNo, pEnteringPhysVol);
1506  pSolid->ComputeDimensions(pParam, enteringReplicaNo, pEnteringPhysVol);
1507 
1508  // Sets the transform in the Parameterisation
1509  //
1510  pParam->ComputeTransformation(enteringReplicaNo, pEnteringPhysVol);
1511 
1512  // Set the correct solid and material in Logical Volume
1513  //
1514  G4LogicalVolume* pLogical = pEnteringPhysVol->GetLogicalVolume();
1515  pLogical->SetSolid( pSolid );
1516  }
1517  break;
1518  }
1519  return G4AffineTransform(pEnteringPhysVol->GetRotation(),
1520  pEnteringPhysVol->GetTranslation()).Invert();
1521 }
1522 
1523 
1524 // ********************************************************************
1525 // GetLocalExitNormalAndCheck
1526 //
1527 // Obtains the Normal vector to a surface (in local coordinates)
1528 // pointing out of previous volume and into current volume, and
1529 // checks the current point against expected 'local' value.
1530 // ********************************************************************
1531 //
1534 #ifdef G4DEBUG_NAVIGATION
1535  const G4ThreeVector& ExpectedBoundaryPointGlobal,
1536 #else
1537  const G4ThreeVector&,
1538 #endif
1539  G4bool* pValid)
1540 {
1541 #ifdef G4DEBUG_NAVIGATION
1542  // Check Current point against expected 'local' value
1543  //
1545  {
1546  G4ThreeVector ExpectedBoundaryPointLocal;
1547 
1548  const G4AffineTransform& GlobalToLocal= GetGlobalToLocalTransform();
1549  ExpectedBoundaryPointLocal =
1550  GlobalToLocal.TransformPoint( ExpectedBoundaryPointGlobal );
1551 
1552  // Add here: Comparison against expected position,
1553  // i.e. the endpoint of ComputeStep
1554  }
1555 #endif
1556 
1557  return GetLocalExitNormal( pValid);
1558 }
1559 
1560 
1561 // ********************************************************************
1562 // GetGlobalExitNormal
1563 //
1564 // Obtains the Normal vector to a surface (in global coordinates)
1565 // pointing out of previous volume and into current volume
1566 // ********************************************************************
1567 //
1570  G4bool* pNormalCalculated)
1571 {
1572  G4bool validNormal;
1573  G4ThreeVector localNormal, globalNormal;
1574 
1575  G4bool usingStored = fCalculatedExitNormal && (
1576  ( fLastTriedStepComputation && fExiting ) // Just calculated it
1577  || // No locate in between
1579  && (IntersectPointGlobal-fStepEndPoint).mag2() < 10.0*fSqTol ) );
1580  // Calculated it 'just' before & then called locate
1581  // but it did not move position
1582 
1583  if( usingStored )
1584  {
1585  // This was computed in last call to ComputeStep
1586  // and only if it arrived at boundary
1587  //
1588  globalNormal = fExitNormalGlobalFrame;
1589  G4double normMag2 = globalNormal.mag2();
1590  if( std::fabs ( normMag2 - 1.0 ) < perMillion ) // Value is good
1591  {
1592  *pNormalCalculated = true; // ComputeStep always computes it if Exiting
1593  // (fExiting==true)
1594  }
1595  else
1596  {
1597  G4ExceptionDescription message;
1598  message.precision(10);
1599  message << " WARNING> Expected normal-global-frame to be valid, "
1600  << " i.e. a unit vector!" << G4endl
1601  << " - but |normal| = " << std::sqrt(normMag2)
1602  << " - and |normal|^2 = " << normMag2 << G4endl
1603  << " which differs from 1.0 by " << normMag2 - 1.0 << G4endl
1604  << " n = " << fExitNormalGlobalFrame << G4endl
1605  << " Global point: " << IntersectPointGlobal << G4endl
1606  << " Volume: " << fHistory.GetTopVolume()->GetName() << G4endl;
1607 #ifdef G4VERBOSE
1609  if ( candLog )
1610  {
1611  message << " Solid: " << candLog->GetSolid()->GetName()
1612  << ", Type: " << candLog->GetSolid()->GetEntityType() << G4endl
1613  << *candLog->GetSolid() << G4endl;
1614  }
1615 #endif
1616  message << "============================================================"
1617  << G4endl;
1618  G4int oldVerbose = fVerbose;
1619  fVerbose=4;
1620  message << " State of Navigator: " << G4endl;
1621  message << *this << G4endl;
1622  fVerbose = oldVerbose;
1623  message << "============================================================"
1624  << G4endl;
1625 
1626  G4Exception("G4Navigator::GetGlobalExitNormal()",
1627  "GeomNav0003",JustWarning, message,
1628  "Value obtained from stored global-normal is not a unit vector.");
1629 
1630  // (Re)Compute it now -- as either it was not computed, or it is wrong.
1631  //
1632  localNormal = GetLocalExitNormalAndCheck(IntersectPointGlobal,
1633  &validNormal);
1634  *pNormalCalculated = fCalculatedExitNormal;
1635 
1636  G4AffineTransform localToGlobal = GetLocalToGlobalTransform();
1637  globalNormal = localToGlobal.TransformAxis( localNormal );
1638  }
1639  }
1640  else
1641  {
1642  localNormal = GetLocalExitNormalAndCheck(IntersectPointGlobal,&validNormal);
1643  *pNormalCalculated = fCalculatedExitNormal;
1644 
1645 #ifdef G4DEBUG_NAVIGATION
1646  usingStored= false;
1647 
1648  if( (!validNormal) && !fCalculatedExitNormal )
1649  {
1651  edN << " Calculated = " << fCalculatedExitNormal << G4endl;
1652  edN << " Entering= " << fEntering << G4endl;
1653  G4int oldVerbose= this->GetVerboseLevel();
1654  this->SetVerboseLevel(4);
1655  edN << " State of Navigator: " << G4endl;
1656  edN << *this << G4endl;
1657  this->SetVerboseLevel( oldVerbose );
1658 
1659  G4Exception("G4Navigator::GetGlobalExitNormal()",
1660  "GeomNav0003", JustWarning, edN,
1661  "LocalExitNormalAndCheck() did not calculate Normal.");
1662  }
1663 #endif
1664 
1665  G4double localMag2= localNormal.mag2();
1666  if( validNormal && (std::fabs(localMag2-1.0)) > CLHEP::perMillion )
1667  {
1669 
1670  edN << "G4Navigator::GetGlobalExitNormal: "
1671  << " Using Local Normal - from call to GetLocalExitNormalAndCheck. "
1672  << G4endl
1673  << " Local Exit Normal : " << " || = " << std::sqrt(localMag2)
1674  << " vec = " << localNormal << G4endl
1675  << " Global Exit Normal : " << " || = " << globalNormal.mag()
1676  << " vec = " << globalNormal << G4endl;
1677  edN << " Calculated It = " << fCalculatedExitNormal << G4endl;
1678 
1679  G4Exception("G4Navigator::GetGlobalExitNormal()",
1680  "GeomNav0003",JustWarning, edN,
1681  "Value obtained from new local *solid* is incorrect.");
1682  localNormal = localNormal.unit(); // Should we correct it ??
1683  }
1684  G4AffineTransform localToGlobal = GetLocalToGlobalTransform();
1685  globalNormal = localToGlobal.TransformAxis( localNormal );
1686  }
1687 
1688 #ifdef G4DEBUG_NAVIGATION
1689  if( usingStored )
1690  {
1691  G4ThreeVector globalNormAgn;
1692 
1693  localNormal= GetLocalExitNormalAndCheck(IntersectPointGlobal, &validNormal);
1694 
1695  G4AffineTransform localToGlobal = GetLocalToGlobalTransform();
1696  globalNormAgn = localToGlobal.TransformAxis( localNormal );
1697 
1698  // Check the value computed against fExitNormalGlobalFrame
1699  G4ThreeVector diffNorm = globalNormAgn - fExitNormalGlobalFrame;
1700  if( diffNorm.mag2() > perMillion*CLHEP::perMillion)
1701  {
1702  G4ExceptionDescription edDfn;
1703  edDfn << "Found difference in normals in case of exiting mother "
1704  << "- when Get is called after ComputingStep " << G4endl;
1705  edDfn << " Magnitude of diff = " << diffNorm.mag() << G4endl;
1706  edDfn << " Normal stored (Global) = " << fExitNormalGlobalFrame
1707  << G4endl;
1708  edDfn << " Global Computed from Local = " << globalNormAgn << G4endl;
1709  G4Exception("G4Navigator::GetGlobalExitNormal()", "GeomNav0003",
1710  JustWarning, edDfn);
1711  }
1712  }
1713 #endif
1714 
1715  return globalNormal;
1716 }
1717 
1718 // To make the new Voxel Safety the default, uncomment the next line
1719 #define G4NEW_SAFETY 1
1720 
1721 // ********************************************************************
1722 // ComputeSafety
1723 //
1724 // It assumes that it will be
1725 // i) called at the Point in the same volume as the EndPoint of the
1726 // ComputeStep.
1727 // ii) after (or at the end of) ComputeStep OR after the relocation.
1728 // ********************************************************************
1729 //
1731  const G4double pMaxLength,
1732  const G4bool keepState)
1733 {
1734  G4double newSafety = 0.0;
1735 
1736 #ifdef G4DEBUG_NAVIGATION
1737  G4int oldcoutPrec = G4cout.precision(8);
1738  if( fVerbose > 0 )
1739  {
1740  G4cout << "*** G4Navigator::ComputeSafety: ***" << G4endl
1741  << " Called at point: " << pGlobalpoint << G4endl;
1742 
1743  G4VPhysicalVolume *motherPhysical = fHistory.GetTopVolume();
1744  G4cout << " Volume = " << motherPhysical->GetName()
1745  << " - Maximum length = " << pMaxLength << G4endl;
1746  if( fVerbose >= 4 )
1747  {
1748  G4cout << " ----- Upon entering Compute Safety:" << G4endl;
1749  PrintState();
1750  }
1751  }
1752 #endif
1753 
1754  G4double distEndpointSq = (pGlobalpoint-fStepEndPoint).mag2();
1755  G4bool stayedOnEndpoint = distEndpointSq < kCarTolerance*kCarTolerance;
1756  G4bool endpointOnSurface = fEnteredDaughter || fExitedMother;
1757 
1758  if( endpointOnSurface && stayedOnEndpoint )
1759  {
1760 #ifdef G4DEBUG_NAVIGATION
1761  if( fVerbose >= 2 )
1762  {
1763  G4cout << " G4Navigator::ComputeSafety() finds that point - "
1764  << pGlobalpoint << " - is on surface " << G4endl;
1765  if( fEnteredDaughter ) { G4cout << " entered new daughter volume"; }
1766  if( fExitedMother ) { G4cout << " and exited previous volume."; }
1767  G4cout << G4endl;
1768  G4cout << " EndPoint was = " << fStepEndPoint << G4endl;
1769  }
1770 #endif
1771  newSafety = 0.0;
1772  // return newSafety;
1773  }
1774  else // if( !(endpointOnSurface && stayedOnEndpoint) )
1775  {
1776  if (keepState) { SetSavedState(); }
1777 
1778  // Pseudo-relocate to this point (updates voxel information only)
1779  //
1780  LocateGlobalPointWithinVolume( pGlobalpoint );
1781  // --->> DANGER: Side effects on sub-navigator voxel information <<---
1782  // Could be replaced again by 'granular' calls to sub-navigator
1783  // locates (similar side-effects, but faster.
1784  // Solutions:
1785  // 1) Re-locate (to where?)
1786  // 2) Insure that the methods using (G4ComputeStep?)
1787  // does a relocation (if information is disturbed only ?)
1788 
1789 #ifdef G4DEBUG_NAVIGATION
1790  if( fVerbose >= 2 )
1791  {
1792  G4cout << " G4Navigator::ComputeSafety() relocates-in-volume to point: "
1793  << pGlobalpoint << G4endl;
1794  }
1795 #endif
1796  G4VPhysicalVolume *motherPhysical = fHistory.GetTopVolume();
1797  G4LogicalVolume *motherLogical = motherPhysical->GetLogicalVolume();
1798  G4SmartVoxelHeader* pVoxelHeader = motherLogical->GetVoxelHeader();
1799  G4ThreeVector localPoint = ComputeLocalPoint(pGlobalpoint);
1800 
1802  {
1803  switch(CharacteriseDaughters(motherLogical))
1804  {
1805  case kNormal:
1806  if ( pVoxelHeader )
1807  {
1808 #ifdef G4NEW_SAFETY
1809  G4double safetyTwo = fpVoxelSafety->ComputeSafety(localPoint,
1810  *motherPhysical, pMaxLength);
1811  newSafety= safetyTwo; // Faster and best available
1812 #else
1813  G4double safetyOldVoxel;
1814  safetyOldVoxel =
1815  fvoxelNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1816  newSafety= safetyOldVoxel;
1817 #endif
1818  }
1819  else
1820  {
1821  newSafety=fnormalNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1822  }
1823  break;
1824  case kParameterised:
1825  if( GetDaughtersRegularStructureId(motherLogical) != 1 )
1826  {
1827  newSafety=fparamNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1828  }
1829  else // Regular structure
1830  {
1831  newSafety=fregularNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1832  }
1833  break;
1834  case kReplica:
1835  G4Exception("G4Navigator::ComputeSafety()", "GeomNav0001",
1836  FatalException, "Not applicable for replicated volumes.");
1837  break;
1838  }
1839  }
1840  else
1841  {
1842  newSafety = freplicaNav.ComputeSafety(pGlobalpoint, localPoint,
1843  fHistory, pMaxLength);
1844  }
1845 
1846  if (keepState)
1847  {
1849  // This now overwrites the values of the Safety 'sphere' (correction)
1850  }
1851 
1852  // Remember last safety origin & value
1853  //
1854  // We overwrite the Safety 'sphere' - keeping old behaviour
1855  fPreviousSftOrigin = pGlobalpoint;
1856  fPreviousSafety = newSafety;
1857  }
1858 
1859 #ifdef G4DEBUG_NAVIGATION
1860  if( fVerbose > 1 )
1861  {
1862  G4cout << " ---- Exiting ComputeSafety " << G4endl;
1863  if( fVerbose > 2 ) { PrintState(); }
1864  G4cout << " Returned value of Safety = " << newSafety << G4endl;
1865  }
1866  G4cout.precision(oldcoutPrec);
1867 #endif
1868 
1869  return newSafety;
1870 }
1871 
1872 
1873 // ********************************************************************
1874 // RecheckDistanceToCurrentBoundary
1875 //
1876 // Trial method for checking potential displacement for MS
1877 // Check position aDisplacedGlobalpoint, to see whether it is in the
1878 // current volume (mother).
1879 // If in mother, check distance to boundary along aNewDirection.
1880 // If in entering daughter, check distance back to boundary.
1881 // NOTE:
1882 // Can be called only after ComputeStep() is called - before ReLocation
1883 // Deals only with current volume (and potentially entered)
1884 // Caveats
1885 // First VERSION: Does not consider daughter volumes if it remained in mother
1886 // neither for checking whether it has exited current (mother) volume,
1887 // nor for determining distance to exit this (mother) volume.
1888 // ********************************************************************
1889 //
1891  const G4ThreeVector &aDisplacedGlobalPoint,
1892  const G4ThreeVector &aNewDirection,
1893  const G4double ProposedMove,
1894  G4double *prDistance,
1895  G4double *prNewSafety) const
1896 {
1897  G4ThreeVector localPosition = ComputeLocalPoint(aDisplacedGlobalPoint);
1898  G4ThreeVector localDirection = ComputeLocalAxis(aNewDirection);
1899  // G4double Step = kInfinity;
1900 
1901  G4bool validExitNormal;
1902  G4ThreeVector exitNormal;
1903  // Check against mother solid
1904  G4VPhysicalVolume *motherPhysical = fHistory.GetTopVolume();
1905  G4LogicalVolume *motherLogical = motherPhysical->GetLogicalVolume();
1906 
1907 #ifdef CHECK_ORDER_OF_METHODS
1909  {
1910  G4Exception("G4Navigator::RecheckDistanceToCurrentBoundary()",
1911  "GeomNav0001", FatalException,
1912  "Method must be called after ComputeStep(), before call to LocateMethod.");
1913  }
1914 #endif
1915 
1916  EInside locatedDaug; // = kUndefined;
1917  G4double daughterStep= DBL_MAX;
1918  G4double daughterSafety= DBL_MAX;
1919 
1920  if( fEnteredDaughter )
1921  {
1922  if( motherLogical->CharacteriseDaughters() == kReplica ) { return false; }
1923 
1924  // Track arrived at boundary of a daughter volume at
1925  // the last call of ComputeStep().
1926  // In case the proposed displaced point is inside this daughter,
1927  // it must backtrack at least to the entry point.
1928  // NOTE: No check is made against other daughter volumes. It is
1929  // assumed that the proposed displacement is small enough that
1930  // this is not needed.
1931 
1932  // Must check boundary of current daughter
1933  //
1934  G4VPhysicalVolume *candPhysical= fBlockedPhysicalVolume;
1935  G4LogicalVolume *candLogical= candPhysical->GetLogicalVolume();
1936  G4VSolid *candSolid= candLogical->GetSolid();
1937 
1938  G4AffineTransform nextLevelTrf(candPhysical->GetRotation(),
1939  candPhysical->GetTranslation());
1940 
1941  G4ThreeVector dgPosition= nextLevelTrf.TransformPoint(localPosition);
1942  G4ThreeVector dgDirection= nextLevelTrf.TransformAxis(localDirection);
1943  locatedDaug = candSolid->Inside(dgPosition);
1944 
1945  if( locatedDaug == kInside )
1946  {
1947  // Reverse direction - and find first exit. ( Is it valid?)
1948  // Must backtrack
1949  G4double distanceBackOut =
1950  candSolid->DistanceToOut(dgPosition,
1951  - dgDirection, // Reverse direction
1952  true, &validExitNormal, &exitNormal);
1953  daughterStep= - distanceBackOut;
1954  // No check is made whether the particle could have arrived at
1955  // at this location without encountering another volume or
1956  // a different psurface of the current volume
1957  if( prNewSafety )
1958  {
1959  daughterSafety= candSolid->DistanceToOut(dgPosition);
1960  }
1961  }
1962  else
1963  {
1964  if( locatedDaug == kOutside )
1965  {
1966  // See whether it still intersects it
1967  //
1968  daughterStep= candSolid->DistanceToIn(dgPosition,
1969  dgDirection);
1970  if( prNewSafety )
1971  {
1972  daughterSafety= candSolid->DistanceToIn(dgPosition);
1973  }
1974  }
1975  else
1976  {
1977  // The point remains on the surface of candidate solid
1978  //
1979  daughterStep= 0.0;
1980  daughterSafety= 0.0;
1981  }
1982  }
1983 
1984  // If trial point is in daughter (or on its surface) we have the
1985  // answer, the rest is not relevant
1986  //
1987  if( locatedDaug != kOutside )
1988  {
1989  *prDistance= daughterStep;
1990  if( prNewSafety ) { *prNewSafety= daughterSafety; }
1991  return true;
1992  }
1993  // If ever extended, so that some type of mother cut daughter,
1994  // this would change
1995  }
1996 
1997  G4VSolid *motherSolid= motherLogical->GetSolid();
1998 
1999  G4double motherStep= DBL_MAX, motherSafety= DBL_MAX;
2000 
2001  // Check distance to boundary of mother
2002  //
2004  {
2005  EInside locatedMoth = motherSolid->Inside(localPosition);
2006 
2007  if( locatedMoth == kInside )
2008  {
2009  motherSafety= motherSolid->DistanceToOut(localPosition);
2010  if( ProposedMove >= motherSafety )
2011  {
2012  motherStep= motherSolid->DistanceToOut(localPosition,
2013  localDirection,
2014  true, &validExitNormal, &exitNormal);
2015  }
2016  else
2017  {
2018  motherStep= ProposedMove;
2019  }
2020  }
2021  else if( locatedMoth == kOutside)
2022  {
2023  motherSafety= motherSolid->DistanceToIn(localPosition);
2024  if( ProposedMove >= motherSafety )
2025  {
2026  motherStep= - motherSolid->DistanceToIn(localPosition,
2027  -localDirection);
2028  }
2029  }
2030  else
2031  {
2032  motherSafety= 0.0;
2033  *prDistance= 0.0; // On surface - no move // motherStep;
2034  if( prNewSafety ) { *prNewSafety= motherSafety; }
2035  return false;
2036  }
2037  }
2038  else
2039  {
2040  return false;
2041  }
2042 
2043  *prDistance= std::min( motherStep, daughterStep );
2044  if( prNewSafety )
2045  {
2046  *prNewSafety= std::min( motherSafety, daughterSafety );
2047  }
2048  return true;
2049 }
2050 
2051 
2052 // ********************************************************************
2053 // CreateTouchableHistoryHandle
2054 // ********************************************************************
2055 //
2057 {
2059 }
2060 
2061 // ********************************************************************
2062 // PrintState
2063 // ********************************************************************
2064 //
2066 {
2067  G4int oldcoutPrec = G4cout.precision(4);
2068  if( fVerbose >= 4 )
2069  {
2070  G4cout << "The current state of G4Navigator is: " << G4endl;
2071  G4cout << " ValidExitNormal= " << fValidExitNormal // << G4endl
2072  << " ExitNormal = " << fExitNormal // << G4endl
2073  << " Exiting = " << fExiting // << G4endl
2074  << " Entering = " << fEntering // << G4endl
2075  << " BlockedPhysicalVolume= " ;
2076  if (fBlockedPhysicalVolume==0)
2077  {
2078  G4cout << "None";
2079  }
2080  else
2081  {
2083  }
2084  G4cout << G4endl
2085  << " BlockedReplicaNo = " << fBlockedReplicaNo // << G4endl
2086  << " LastStepWasZero = " << fLastStepWasZero // << G4endl
2087  << G4endl;
2088  }
2089  if( ( 1 < fVerbose) && (fVerbose < 4) )
2090  {
2091  G4cout << G4endl; // Make sure to line up
2092  G4cout << std::setw(30) << " ExitNormal " << " "
2093  << std::setw( 5) << " Valid " << " "
2094  << std::setw( 9) << " Exiting " << " "
2095  << std::setw( 9) << " Entering" << " "
2096  << std::setw(15) << " Blocked:Volume " << " "
2097  << std::setw( 9) << " ReplicaNo" << " "
2098  << std::setw( 8) << " LastStepZero " << " "
2099  << G4endl;
2100  G4cout << "( " << std::setw(7) << fExitNormal.x()
2101  << ", " << std::setw(7) << fExitNormal.y()
2102  << ", " << std::setw(7) << fExitNormal.z() << " ) "
2103  << std::setw( 5) << fValidExitNormal << " "
2104  << std::setw( 9) << fExiting << " "
2105  << std::setw( 9) << fEntering << " ";
2106  if ( fBlockedPhysicalVolume==0 )
2107  { G4cout << std::setw(15) << "None"; }
2108  else
2109  { G4cout << std::setw(15)<< fBlockedPhysicalVolume->GetName(); }
2110  G4cout << std::setw( 9) << fBlockedReplicaNo << " "
2111  << std::setw( 8) << fLastStepWasZero << " "
2112  << G4endl;
2113  }
2114  if( fVerbose > 2 )
2115  {
2116  G4cout.precision(8);
2117  G4cout << " Current Localpoint = " << fLastLocatedPointLocal << G4endl;
2118  G4cout << " PreviousSftOrigin = " << fPreviousSftOrigin << G4endl;
2119  G4cout << " PreviousSafety = " << fPreviousSafety << G4endl;
2120  }
2121  G4cout.precision(oldcoutPrec);
2122 }
2123 
2124 // ********************************************************************
2125 // ComputeStepLog
2126 // ********************************************************************
2127 //
2129  G4double moveLenSq) const
2130 {
2131  // The following checks only make sense if the move is larger
2132  // than the tolerance.
2133 
2134  const G4double fAccuracyForWarning = kCarTolerance,
2135  fAccuracyForException = 1000*kCarTolerance;
2136 
2137  G4ThreeVector OriginalGlobalpoint = fHistory.GetTopTransform().Inverse().
2138  TransformPoint(fLastLocatedPointLocal);
2139 
2140  G4double shiftOriginSafSq = (fPreviousSftOrigin-pGlobalpoint).mag2();
2141 
2142  // Check that the starting point of this step is
2143  // within the isotropic safety sphere of the last point
2144  // to a accuracy/precision given by fAccuracyForWarning.
2145  // If so give warning.
2146  // If it fails by more than fAccuracyForException exit with error.
2147  //
2148  if( shiftOriginSafSq >= sqr(fPreviousSafety) )
2149  {
2150  G4double shiftOrigin = std::sqrt(shiftOriginSafSq);
2151  G4double diffShiftSaf = shiftOrigin - fPreviousSafety;
2152 
2153  if( diffShiftSaf > fAccuracyForWarning )
2154  {
2155  G4int oldcoutPrec= G4cout.precision(8);
2156  G4int oldcerrPrec= G4cerr.precision(10);
2157  std::ostringstream message, suggestion;
2158  message << "Accuracy error or slightly inaccurate position shift."
2159  << G4endl
2160  << " The Step's starting point has moved "
2161  << std::sqrt(moveLenSq)/mm << " mm " << G4endl
2162  << " since the last call to a Locate method." << G4endl
2163  << " This has resulted in moving "
2164  << shiftOrigin/mm << " mm "
2165  << " from the last point at which the safety "
2166  << " was calculated " << G4endl
2167  << " which is more than the computed safety= "
2168  << fPreviousSafety/mm << " mm at that point." << G4endl
2169  << " This difference is "
2170  << diffShiftSaf/mm << " mm." << G4endl
2171  << " The tolerated accuracy is "
2172  << fAccuracyForException/mm << " mm.";
2173 
2174  suggestion << " ";
2175  static G4ThreadLocal G4int warnNow = 0;
2176  if( ((++warnNow % 100) == 1) )
2177  {
2178  message << G4endl
2179  << " This problem can be due to either " << G4endl
2180  << " - a process that has proposed a displacement"
2181  << " larger than the current safety , or" << G4endl
2182  << " - inaccuracy in the computation of the safety";
2183  suggestion << "We suggest that you " << G4endl
2184  << " - find i) what particle is being tracked, and "
2185  << " ii) through what part of your geometry " << G4endl
2186  << " for example by re-running this event with "
2187  << G4endl
2188  << " /tracking/verbose 1 " << G4endl
2189  << " - check which processes you declare for"
2190  << " this particle (and look at non-standard ones)"
2191  << G4endl
2192  << " - in case, create a detailed logfile"
2193  << " of this event using:" << G4endl
2194  << " /tracking/verbose 6 ";
2195  }
2196  G4Exception("G4Navigator::ComputeStep()",
2197  "GeomNav1002", JustWarning,
2198  message, G4String(suggestion.str()));
2199  G4cout.precision(oldcoutPrec);
2200  G4cerr.precision(oldcerrPrec);
2201  }
2202 #ifdef G4DEBUG_NAVIGATION
2203  else
2204  {
2205  G4cerr << "WARNING - G4Navigator::ComputeStep()" << G4endl
2206  << " The Step's starting point has moved "
2207  << std::sqrt(moveLenSq) << "," << G4endl
2208  << " which has taken it to the limit of"
2209  << " the current safety. " << G4endl;
2210  }
2211 #endif
2212  }
2213  G4double safetyPlus = fPreviousSafety + fAccuracyForException;
2214  if ( shiftOriginSafSq > sqr(safetyPlus) )
2215  {
2216  std::ostringstream message;
2217  message << "May lead to a crash or unreliable results." << G4endl
2218  << " Position has shifted considerably without"
2219  << " notifying the navigator !" << G4endl
2220  << " Tolerated safety: " << safetyPlus << G4endl
2221  << " Computed shift : " << shiftOriginSafSq;
2222  G4Exception("G4Navigator::ComputeStep()", "GeomNav1002",
2223  JustWarning, message);
2224  }
2225 }
2226 
2227 // ********************************************************************
2228 // Operator <<
2229 // ********************************************************************
2230 //
2231 std::ostream& operator << (std::ostream &os,const G4Navigator &n)
2232 {
2233  // Old version did only the following:
2234  // os << "Current History: " << G4endl << n.fHistory;
2235  // Old behaviour is recovered for fVerbose = 0
2236 
2237  // Adapted from G4Navigator::PrintState() const
2238 
2239  G4int oldcoutPrec = os.precision(4);
2240  if( n.fVerbose >= 4 )
2241  {
2242  os << "The current state of G4Navigator is: " << G4endl;
2243  os << " ValidExitNormal= " << n.fValidExitNormal << G4endl
2244  << " ExitNormal = " << n.fExitNormal << G4endl
2245  << " Exiting = " << n.fExiting << G4endl
2246  << " Entering = " << n.fEntering << G4endl
2247  << " BlockedPhysicalVolume= " ;
2248  if (n.fBlockedPhysicalVolume==0)
2249  os << "None";
2250  else
2251  os << n.fBlockedPhysicalVolume->GetName();
2252  os << G4endl
2253  << " BlockedReplicaNo = " << n.fBlockedReplicaNo << G4endl
2254  << " LastStepWasZero = " << n.fLastStepWasZero << G4endl
2255  << G4endl;
2256  }
2257  if( ( 1 < n.fVerbose) && (n.fVerbose < 4) )
2258  {
2259  os << G4endl; // Make sure to line up
2260  os << std::setw(30) << " ExitNormal " << " "
2261  << std::setw( 5) << " Valid " << " "
2262  << std::setw( 9) << " Exiting " << " "
2263  << std::setw( 9) << " Entering" << " "
2264  << std::setw(15) << " Blocked:Volume " << " "
2265  << std::setw( 9) << " ReplicaNo" << " "
2266  << std::setw( 8) << " LastStepZero " << " "
2267  << G4endl;
2268  os << "( " << std::setw(7) << n.fExitNormal.x()
2269  << ", " << std::setw(7) << n.fExitNormal.y()
2270  << ", " << std::setw(7) << n.fExitNormal.z() << " ) "
2271  << std::setw( 5) << n.fValidExitNormal << " "
2272  << std::setw( 9) << n.fExiting << " "
2273  << std::setw( 9) << n.fEntering << " ";
2274  if ( n.fBlockedPhysicalVolume==0 )
2275  { os << std::setw(15) << "None"; }
2276  else
2277  { os << std::setw(15)<< n.fBlockedPhysicalVolume->GetName(); }
2278  os << std::setw( 9) << n.fBlockedReplicaNo << " "
2279  << std::setw( 8) << n.fLastStepWasZero << " "
2280  << G4endl;
2281  }
2282  if( n.fVerbose > 2 )
2283  {
2284  os.precision(8);
2285  os << " Current Localpoint = " << n.fLastLocatedPointLocal << G4endl;
2286  os << " PreviousSftOrigin = " << n.fPreviousSftOrigin << G4endl;
2287  os << " PreviousSafety = " << n.fPreviousSafety << G4endl;
2288  }
2289  if( n.fVerbose > 3 || n.fVerbose == 0 )
2290  {
2291  os << "Current History: " << G4endl << n.fHistory;
2292  }
2293 
2294  os.precision(oldcoutPrec);
2295  return os;
2296 }
G4String GetName() const
G4ReplicaNavigation freplicaNav
Definition: G4Navigator.hh:503
G4bool fWarnPush
Definition: G4Navigator.hh:495
G4ParameterisedNavigation fparamNav
Definition: G4Navigator.hh:502
G4SmartVoxelHeader * GetVoxelHeader() const
G4bool fValidExitNormal
Definition: G4Navigator.hh:423
G4VPhysicalVolume * GetTopVolume() const
G4VoxelNavigation fvoxelNav
Definition: G4Navigator.hh:501
G4VPhysicalVolume * fBlockedPhysicalVolume
Definition: G4Navigator.hh:415
virtual void ResetState()
G4bool fLastTriedStepComputation
Definition: G4Navigator.hh:400
virtual G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
G4VoxelSafety * fpVoxelSafety
Definition: G4Navigator.hh:505
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4bool fCheck
Definition: G4Navigator.hh:493
const G4ThreeVector & GetTranslation() const
static const G4double kInfinity
Definition: geomdefs.hh:42
virtual G4bool IsNested() const
#define fWasLimitedByGeometry
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
void UpdateMaterial(G4Material *pMaterial)
CLHEP::Hep3Vector G4ThreeVector
CLHEP::HepRotation G4RotationMatrix
G4ThreeVector fLastStepEndPointLocal
Definition: G4Navigator.hh:388
virtual void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4VSolid.cc:137
G4AffineTransform Inverse() const
G4int GetVerboseLevel() const
G4ThreeVector fGrandMotherExitNormal
Definition: G4Navigator.hh:427
G4ThreeVector ComputeLocalAxis(const G4ThreeVector &pVec) const
G4bool fPushed
Definition: G4Navigator.hh:495
virtual G4TouchableHistoryHandle CreateTouchableHistoryHandle() const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
void ResetStackAndState()
G4int GetDepth() const
G4int fNumberZeroSteps
Definition: G4Navigator.hh:447
G4double GetSurfaceTolerance() const
G4VPhysicalVolume * spBlockedPhysicalVolume
Definition: G4Navigator.hh:471
virtual G4double ComputeStep(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double pCurrentProposedStepLength, G4double &pNewSafety)
Definition: G4Navigator.cc:747
G4int fVerbose
Definition: G4Navigator.hh:392
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4VPhysicalVolume &currentPhysical, G4double maxLength=DBL_MAX)
void PrintState() const
void SetSolid(G4VSolid *pSolid)
G4int fAbandonThreshold_NoZeroSteps
Definition: G4Navigator.hh:451
G4SmartVoxelNode * ParamVoxelLocate(G4SmartVoxelHeader *pHead, const G4ThreeVector &localPoint)
G4bool fEnteredDaughter
Definition: G4Navigator.hh:372
EVolume GetVolumeType(G4int n) const
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4bool &calculatedExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4bool fLocatedOnEdge
Definition: G4Navigator.hh:445
const G4AffineTransform GetLocalToGlobalTransform() const
virtual G4GeometryType GetEntityType() const =0
#define G4ThreadLocal
Definition: tls.hh:89
G4ReferenceCountedHandle< G4TouchableHistory > G4TouchableHistoryHandle
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
void ComputeTransformation(const G4int replicaNo, G4VPhysicalVolume *pVol, G4ThreeVector &point) const
int G4int
Definition: G4Types.hh:78
G4bool fLastStepWasZero
Definition: G4Navigator.hh:442
virtual G4VPhysicalVolume * ResetHierarchyAndLocate(const G4ThreeVector &point, const G4ThreeVector &direction, const G4TouchableHistory &h)
Definition: G4Navigator.cc:95
G4ThreeVector fExitNormalGlobalFrame
Definition: G4Navigator.hh:431
virtual G4ThreeVector GetLocalExitNormalAndCheck(const G4ThreeVector &point, G4bool *valid)
G4int GetTopReplicaNo() const
void SetVerboseLevel(G4int level)
#define fPushed
G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4NavigationHistory &history, const G4double pMaxLength=DBL_MAX)
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
G4bool fWasLimitedByGeometry
Definition: G4Navigator.hh:382
G4NormalNavigation fnormalNav
Definition: G4Navigator.hh:500
G4bool fEntering
Definition: G4Navigator.hh:406
void SetNormalNavigation(G4NormalNavigation *fnormnav)
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4NavigationHistory &history, const G4double pProposedMaxLength=DBL_MAX)
G4GLOB_DLL std::ostream G4cout
const G4String & GetName() const
virtual EInside Inside(const G4ThreeVector &p) const =0
virtual G4ThreeVector GetLocalExitNormal(G4bool *valid)
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4ThreeVector fPreviousSftOrigin
Definition: G4Navigator.hh:454
G4double fSqTol
Definition: G4Navigator.hh:361
G4double CheckNextStep(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double pCurrentProposedStepLength, G4double &pNewSafety)
bool G4bool
Definition: G4Types.hh:79
EVolume GetTopVolumeType() const
virtual G4int GetRegularStructureId() const =0
G4NavigationHistory fHistory
Definition: G4Navigator.hh:368
virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4NavigationHistory &history, const G4double pMaxLength=DBL_MAX)
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
virtual G4VPVParameterisation * GetParameterisation() const =0
virtual void SetCopyNo(G4int CopyNo)=0
G4int GetReplicaNo(G4int n) const
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
G4bool fExitedMother
Definition: G4Navigator.hh:378
EVolume CharacteriseDaughters() const
virtual G4bool RecheckDistanceToCurrentBoundary(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double CurrentProposedStepLength, G4double *prDistance, G4double *prNewSafety=0) const
G4bool EnteredDaughterVolume() const
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
G4int fBlockedReplicaNo
Definition: G4Navigator.hh:416
#define G4DEBUG_NAVIGATION
const G4int n
EVolume CharacteriseDaughters(const G4LogicalVolume *pLog) const
G4ThreeVector fLastLocatedPointLocal
Definition: G4Navigator.hh:418
G4double fPreviousSafety
Definition: G4Navigator.hh:455
G4bool fLocatedOutsideWorld
Definition: G4Navigator.hh:420
void SetSavedState()
Definition: G4Navigator.cc:659
G4bool fActive
Definition: G4Navigator.hh:397
G4ThreeVector ComputeLocalPoint(const G4ThreeVector &rGlobPoint) const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4double kCarTolerance
Definition: G4Navigator.hh:361
static const double perMillion
Definition: G4SIunits.hh:331
void NewLevel(G4VPhysicalVolume *pNewMother, EVolume vType=kNormal, G4int nReplica=-1)
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4TouchableHistory * CreateTouchableHistory() const
G4double ComputeStep(const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4AffineTransform GetMotherToDaughterTransform(G4VPhysicalVolume *dVolume, G4int dReplicaNo, EVolume dVolumeType)
G4LogicalVolume * GetLogicalVolume() const
const G4AffineTransform & GetTransform(G4int n) const
virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid)
G4bool fExiting
Definition: G4Navigator.hh:406
EInside
Definition: geomdefs.hh:58
G4int GetDaughtersRegularStructureId(const G4LogicalVolume *pLog) const
virtual void ComputeTransformation(const G4int, G4VPhysicalVolume *) const =0
G4ThreeVector TransformAxis(const G4ThreeVector &axis) const
virtual G4int GetCopyNo() const =0
const G4AffineTransform & GetGlobalToLocalTransform() const
virtual G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=0, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true)
Definition: G4Navigator.cc:125
struct G4Navigator::G4SaveNavigatorState fSaveState
const G4RotationMatrix * GetRotation() const
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
Definition: Step.hh:41
G4SmartVoxelNode * VoxelLocate(G4SmartVoxelHeader *pHead, const G4ThreeVector &localPoint)
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4NavigationHistory &history, const G4double pProposedMaxLength=DBL_MAX)
#define G4endl
Definition: G4ios.hh:61
const G4AffineTransform & GetTopTransform() const
std::ostream & operator<<(std::ostream &os, const G4Navigator &n)
G4bool fCalculatedExitNormal
Definition: G4Navigator.hh:433
G4ThreeVector fStepEndPoint
Definition: G4Navigator.hh:385
const G4NavigationHistory * GetHistory() const
G4ThreeVector fExitNormal
Definition: G4Navigator.hh:424
G4int fActionThreshold_NoZeroSteps
Definition: G4Navigator.hh:449
T sqr(const T &x)
Definition: templates.hh:145
G4bool fChangedGrandMotherRefFrame
Definition: G4Navigator.hh:429
EVolume
Definition: geomdefs.hh:68
G4int MoveUpHistory(G4int num_levels=1)
const G4String & GetName() const
G4double ComputeSafety(const G4ThreeVector &globalPoint, const G4ThreeVector &localPoint, G4NavigationHistory &history, const G4double pProposedMaxLength=DBL_MAX)
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
double G4double
Definition: G4Types.hh:76
G4VPhysicalVolume * GetVolume(G4int n) const
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4double pProposedMaxLength=DBL_MAX, const G4bool keepState=true)
virtual G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4RegularNavigation fregularNav
Definition: G4Navigator.hh:504
EInside BackLocate(G4NavigationHistory &history, const G4ThreeVector &globalPoint, G4ThreeVector &localPoint, const G4bool &exiting, G4bool &notKnownInside) const
#define DBL_MAX
Definition: templates.hh:83
virtual void SetupHierarchy()
static const double mm
Definition: G4SIunits.hh:114
virtual G4bool CheckOverlaps(G4int res=1000, G4double tol=0., G4bool verbose=true, G4int errMax=1)
EVolume VolumeType(const G4VPhysicalVolume *pVol) const
static G4GeometryTolerance * GetInstance()
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
Definition: G4Navigator.cc:582
G4VSolid * GetSolid() const
void ComputeStepLog(const G4ThreeVector &pGlobalpoint, G4double moveLenSq) const
void RestoreSavedState()
Definition: G4Navigator.cc:693
virtual ~G4Navigator()
Definition: G4Navigator.cc:85
G4GLOB_DLL std::ostream G4cerr
G4double fMinStep
Definition: G4Navigator.hh:361