ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4ITMultiNavigator.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4ITMultiNavigator.cc
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 // GEANT4 tag $ Name: $
28 //
29 // class G4PathFinder Implementation
30 //
31 // Author: John Apostolakis, November 2006
32 // --------------------------------------------------------------------
33 
34 #include <iomanip>
35 
36 #include "G4ITMultiNavigator.hh"
37 
38 class G4FieldManager;
39 
40 #include "G4SystemOfUnits.hh"
41 #include "G4ITNavigator.hh"
42 #include "G4PropagatorInField.hh"
44 
45 #define State(X) fpTrackState->X
46 #define fLimitedStep State(fLimitedStep)
47 #define fLimitTruth State(fLimitTruth)
48 #define fCurrentStepSize State(fCurrentStepSize)
49 #define fNewSafety State(fNewSafety)
50 #define fNoLimitingStep State(fNoLimitingStep)
51 #define fIdNavLimiting State(fIdNavLimiting)
52 #define fMinStep State(fMinStep)
53 #define fMinSafety State(fMinSafety)
54 #define fTrueMinStep State(fTrueMinStep)
55 #define fLocatedVolume State(fLocatedVolume)
56 #define fLastLocatedPosition State(fLastLocatedPosition)
57 #define fSafetyLocation State(fSafetyLocation)
58 #define fMinSafety_atSafLocation State(fMinSafety_atSafLocation)
59 #define fPreStepLocation State(fPreStepLocation)
60 #define fMinSafety_PreStepPt State(fMinSafety_PreStepPt)
61 #define fWasLimitedByGeometry State(fWasLimitedByGeometry)
62 
63 // ********************************************************************
64 // Constructor
65 // ********************************************************************
66 //
68  : G4ITNavigator(), fLastMassWorld(0)
69 {
71 
72  for(G4int num=0; num< fMaxNav; ++num )
73  {
74  fpNavigator[num] = 0;
75  }
76 
78 
79  G4ITNavigator* massNav= pTransportManager->GetNavigatorForTracking();
80  if( massNav )
81  {
82  G4VPhysicalVolume* pWorld= massNav->GetWorldVolume();
83  if( pWorld )
84  {
85  SetWorldVolume( pWorld );
86  fLastMassWorld = pWorld;
87  }
88  }
89 }
90 
92 {
93 }
94 
96  const G4ThreeVector &pDirection,
97  const G4double proposedStepLength,
98  G4double &pNewSafety)
99 {
100  G4double safety= 0.0, step=0.0;
101  G4double minSafety= kInfinity, minStep= kInfinity;
102 
103  fNoLimitingStep= -1;
104  fIdNavLimiting= -1; // Reset for new step
105 
106 #ifdef G4DEBUG_NAVIGATION
107  if( fVerbose > 2 )
108  {
109  G4cout << " G4ITMultiNavigator::ComputeStep : entered " << G4endl;
110  G4cout << " Input position= " << pGlobalPoint
111  << " direction= " << pDirection << G4endl;
112  G4cout << " Requested step= " << proposedStepLength << G4endl;
113  }
114 #endif
115 
116  std::vector<G4ITNavigator*>::iterator pNavigatorIter;
117 
118  pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
119 
120  G4ThreeVector initialPosition = pGlobalPoint;
121  G4ThreeVector initialDirection= pDirection;
122 
123  for( G4int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
124  {
125  safety= kInfinity;
126 
127  step= (*pNavigatorIter)->ComputeStep( initialPosition,
128  initialDirection,
129  proposedStepLength,
130  safety );
131  if( safety < minSafety ){ minSafety = safety; }
132  if( step < minStep ) { minStep= step; }
133 
135  fNewSafety[num]= safety;
136  // This is currently the safety from the last sub-step
137 
138 #ifdef G4DEBUG_NAVIGATION
139  if( fVerbose > 2 )
140  {
141  G4cout << "G4ITMultiNavigator::ComputeStep : Navigator ["
142  << num << "] -- step size " << step
143  << " safety= " << safety << G4endl;
144  }
145 #endif
146  }
147 
148  // Save safety value, related position
149  //
150  fPreStepLocation = initialPosition;
151  fMinSafety_PreStepPt = minSafety;
152  fMinStep = minStep;
153 
154  if( fMinStep == kInfinity )
155  {
156  fTrueMinStep = proposedStepLength; // Use this below for endpoint !!
157  }
158  else
159  {
160  fTrueMinStep = minStep;
161  }
162 
163 #ifdef G4DEBUG_NAVIGATION
164  if( fVerbose > 1 )
165  {
166  G4ThreeVector endPosition = initialPosition+fTrueMinStep*initialDirection;
167 
168  G4int oldPrec = G4cout.precision(8);
169  G4cout << "G4ITMultiNavigator::ComputeStep : "
170  << " initialPosition = " << initialPosition
171  << " and endPosition = " << endPosition << G4endl;
172  G4cout.precision( oldPrec );
173  }
174 #endif
175 
176  pNewSafety = minSafety;
177 
178  this->WhichLimited();
179 
180 #ifdef G4DEBUG_NAVIGATION
181  if( fVerbose > 2 )
182  {
183  G4cout << " G4ITMultiNavigator::ComputeStep : exits returning "
184  << minStep << G4endl;
185  }
186 #endif
187 
188  return minStep; // must return kInfinity if do not limit step
189 }
190 
191 // ----------------------------------------------------------------------
192 
193 G4double
195  G4double &pNewSafety, // for this geometry
196  G4double &minStep,
197  ELimited &limitedStep)
198 {
199  if( navigatorId > fNoActiveNavigators )
200  {
201  std::ostringstream message;
202  message << "Bad Navigator Id!" << G4endl
203  << " Navigator Id = " << navigatorId
204  << " No Active = " << fNoActiveNavigators << ".";
205  G4Exception("G4ITMultiNavigator::ObtainFinalStep()", "GeomNav0002",
206  FatalException, message);
207  }
208 
209  // Prepare the information to return
210  //
211  pNewSafety = fNewSafety[ navigatorId ];
212  limitedStep = fLimitedStep[ navigatorId ];
213  minStep= fMinStep;
214 
215 #ifdef G4DEBUG_NAVIGATION
216  if( fVerbose > 1 )
217  {
218  G4cout << " G4ITMultiNavigator::ComputeStep returns "
219  << fCurrentStepSize[ navigatorId ]
220  << " for Navigator " << navigatorId
221  << " Limited step = " << limitedStep
222  << " Safety(mm) = " << pNewSafety / mm << G4endl;
223  }
224 #endif
225 
226  return fCurrentStepSize[ navigatorId ];
227 }
228 
229 // ----------------------------------------------------------------------
230 
232  const G4ThreeVector direction )
233 {
234 #ifdef G4DEBUG_NAVIGATION
235  if( fVerbose > 1 )
236  {
237  G4cout << " Entered G4ITMultiNavigator::PrepareNewTrack() " << G4endl;
238  }
239 #endif
240 
242 
243  LocateGlobalPointAndSetup( position, &direction, false, false );
244  //
245  // The first location for each Navigator must be non-relative
246  // or else call ResetStackAndState() for each Navigator
247  // Use direction to get correct side of boundary (ignore dir= false)
248 }
249 
250 // ----------------------------------------------------------------------
251 
253 {
254  // Key purposes:
255  // - Check and cache set of active navigators
256  // - Reset state for new track
257 
258 #ifdef G4DEBUG_NAVIGATION
259  if( fVerbose > 1 )
260  {
261  G4cout << " Entered G4ITMultiNavigator::PrepareNavigators() " << G4endl;
262  }
263 #endif
264 
265  // Message the transportation-manager to find active navigators
266 
267  std::vector<G4ITNavigator*>::iterator pNavigatorIter;
268  fNoActiveNavigators= pTransportManager-> GetNoActiveNavigators();
269 
270  if( fNoActiveNavigators > fMaxNav )
271  {
272  std::ostringstream message;
273  message << "Too many active Navigators / worlds !" << G4endl
274  << " Active Navigators (worlds): "
276  << " which is more than the number allowed: "
277  << fMaxNav << " !";
278  G4Exception("G4ITMultiNavigator::PrepareNavigators()", "GeomNav0002",
279  FatalException, message);
280  }
281 
282  pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
283  for( G4int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
284  {
285  fpNavigator[num] = *pNavigatorIter;
286  fLimitTruth[num] = false;
288  fCurrentStepSize[num] = 0.0;
289  fLocatedVolume[num] = 0;
290  }
291  fWasLimitedByGeometry = false;
292 
293  // Check the world volume of the mass navigator
294  // in case a call to SetWorldVolume() changed it
295 
296  G4VPhysicalVolume* massWorld = GetWorldVolume();
297 
298  if( (massWorld != fLastMassWorld) && (massWorld!=0) )
299  {
300  // Pass along change to Mass Navigator
301  fpNavigator[0] -> SetWorldVolume( massWorld );
302 
303 #ifdef G4DEBUG_NAVIGATION
304  if( fVerbose > 0 )
305  {
306  G4cout << " G4ITMultiNavigator::PrepareNavigators() changed world volume "
307  << " for mass geometry to " << massWorld->GetName() << G4endl;
308  }
309 #endif
310 
311  fLastMassWorld = massWorld;
312  }
313 }
314 
315 // ----------------------------------------------------------------------
316 
319  const G4ThreeVector* pDirection,
320  const G4bool pRelativeSearch,
321  const G4bool ignoreDirection )
322 {
323  // Locate the point in each geometry
324 
325  G4ThreeVector direction(0.0, 0.0, 0.0);
326  G4bool relative = pRelativeSearch;
327  std::vector<G4ITNavigator*>::iterator pNavIter
329 
330  if( pDirection ) { direction = *pDirection; }
331 
332 #ifdef G4DEBUG_NAVIGATION
333  if( fVerbose > 2 )
334  {
335  G4cout << " Entered G4ITMultiNavigator::LocateGlobalPointAndSetup() "
336  << G4endl;
337  G4cout << " Locating at position: " << position
338  << ", with direction: " << direction << G4endl
339  << " Relative: " << relative
340  << ", ignore direction: " << ignoreDirection << G4endl;
341  G4cout << " Number of active navigators: " << fNoActiveNavigators
342  << G4endl;
343  }
344 #endif
345 
346  for ( G4int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
347  {
349  {
350  (*pNavIter)->SetGeometricallyLimitedStep();
351  }
352 
353  G4VPhysicalVolume *pLocated
354  = (*pNavIter)->LocateGlobalPointAndSetup( position, &direction,
355  relative, ignoreDirection );
356  // Set the state related to the location
357  //
358  fLocatedVolume[num] = pLocated;
359 
360  // Clear state related to the step
361  //
362  fLimitedStep[num] = kDoNot;
363  fCurrentStepSize[num] = 0.0;
364  fLimitTruth[ num ] = false; // Always clear on locating (see Navigator)
365 
366 #ifdef G4DEBUG_NAVIGATION
367  if( fVerbose > 2 )
368  {
369  G4cout << " Located in world: " << num << ", at: " << position << G4endl
370  << " Used geomLimStp: " << fLimitTruth[num]
371  << ", found in volume: " << pLocated << G4endl;
372  G4cout << " Name = '" ;
373  if( pLocated )
374  {
375  G4cout << pLocated->GetName() << "'";
376  G4cout << " - CopyNo= " << pLocated->GetCopyNo();
377  }
378  else
379  {
380  G4cout << "Null' Id: Not-Set ";
381  }
382  G4cout << G4endl;
383  }
384 #endif
385  }
386 
387  fWasLimitedByGeometry = false; // Clear on locating
388  G4VPhysicalVolume* volMassLocated= fLocatedVolume[0];
389 
390  return volMassLocated;
391 }
392 
393 // ----------------------------------------------------------------------
394 
395 void
397 {
398  // Relocate the point in each geometry
399 
400  std::vector<G4ITNavigator*>::iterator pNavIter
402 
403 #ifdef G4DEBUG_NAVIGATION
404  if( fVerbose > 2 )
405  {
406  G4cout << " Entered G4ITMultiNavigator::ReLocate() " << G4endl
407  << " Re-locating at position: " << position << G4endl;
408  }
409 #endif
410 
411  for ( G4int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
412  {
413  // ... none limited the step
414 
415  (*pNavIter)->LocateGlobalPointWithinVolume( position );
416 
417  // Clear state related to the step
418  //
419  fLimitedStep[num] = kDoNot;
420  fCurrentStepSize[num] = 0.0;
421 
422  fLimitTruth[ num ] = false; // Always clear on locating (see Navigator)
423  }
424  fWasLimitedByGeometry = false; // Clear on locating
426 }
427 
428 // ----------------------------------------------------------------------
429 
431  const G4double maxDistance,
432  const G4bool state)
433 {
434  // Recompute safety for the relevant point
435 
436  G4double minSafety = kInfinity, safety = kInfinity;
437 
438  std::vector<G4ITNavigator*>::iterator pNavigatorIter;
439  pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
440 
441  for( G4int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
442  {
443  safety = (*pNavigatorIter)->ComputeSafety( position, maxDistance, state);
444  if( safety < minSafety ) { minSafety = safety; }
445  }
446 
448  fMinSafety_atSafLocation = minSafety;
449 
450 #ifdef G4DEBUG_NAVIGATION
451  if( fVerbose > 1 )
452  {
453  G4cout << " G4ITMultiNavigator::ComputeSafety - returns: "
454  << minSafety << ", at location: " << position << G4endl;
455  }
456 #endif
457  return minSafety;
458 }
459 
460 // -----------------------------------------------------------------------
461 
464 {
465  G4Exception( "G4ITMultiNavigator::CreateTouchableHistoryHandle()",
466  "GeomNav0001", FatalException,
467  "Getting a touchable from G4ITMultiNavigator is not defined.");
468 
469  G4TouchableHistory* touchHist;
470  touchHist= fpNavigator[0] -> CreateTouchableHistory();
471 
472  G4VPhysicalVolume* locatedVolume= fLocatedVolume[0];
473  if( locatedVolume == 0 )
474  {
475  // Workaround to ensure that the touchable is fixed !! // TODO: fix
476  //
477  touchHist->UpdateYourself( locatedVolume, touchHist->GetHistory() );
478  }
479 
480  return G4TouchableHistoryHandle(touchHist);
481 }
482 
483 // -----------------------------------------------------------------------
484 
486 {
487  // Flag which processes limited the step
488 
489  G4int last=-1;
490  const G4int IdTransport= 0; // Id of Mass Navigator !!
491  G4int noLimited=0;
492  ELimited shared= kSharedOther;
493 
494 #ifdef G4DEBUG_NAVIGATION
495  if( fVerbose > 2 )
496  {
497  G4cout << " Entered G4ITMultiNavigator::WhichLimited() " << G4endl;
498  }
499 #endif
500 
501  // Assume that [IdTransport] is Mass / Transport
502  //
503  G4bool transportLimited = (fCurrentStepSize[IdTransport] == fMinStep)
504  && ( fMinStep!= kInfinity);
505  if( transportLimited )
506  {
507  shared= kSharedTransport;
508  }
509 
510  for ( G4int num= 0; num < fNoActiveNavigators; num++ )
511  {
512  G4bool limitedStep;
513 
515 
516  limitedStep = ( step == fMinStep ) && ( step != kInfinity);
517 
518  fLimitTruth[ num ] = limitedStep;
519  if( limitedStep )
520  {
521  noLimited++;
522  fLimitedStep[num] = shared;
523  last= num;
524  }
525  else
526  {
528  }
529  }
530  if( (last > -1) && (noLimited == 1 ) )
531  {
532  fLimitedStep[ last ] = kUnique;
533  }
534 
535  fNoLimitingStep= noLimited;
536 
537  return;
538 }
539 
540 // -----------------------------------------------------------------------
541 
542 void
544 {
545  // Report results -- for checking
546 
547  static const G4String StrDoNot("DoNot"), StrUnique("Unique"),
548  StrUndefined("Undefined"),
549  StrSharedTransport("SharedTransport"),
550  StrSharedOther("SharedOther");
551  G4cout << "### G4ITMultiNavigator::PrintLimited() reports: " << G4endl;
552  G4cout << " Minimum step (true): " << fTrueMinStep
553  << ", reported min: " << fMinStep << G4endl;
554 
555 #ifdef G4DEBUG_NAVIGATION
556  if(fVerbose>=2)
557  {
558  G4cout << std::setw(5) << " NavId" << " "
559  << std::setw(12) << " step-size " << " "
560  << std::setw(12) << " raw-size " << " "
561  << std::setw(12) << " pre-safety " << " "
562  << std::setw(15) << " Limited / flag" << " "
563  << std::setw(15) << " World " << " "
564  << G4endl;
565  }
566 #endif
567 
568  for ( G4int num= 0; num < fNoActiveNavigators; num++ )
569  {
570  G4double rawStep = fCurrentStepSize[num];
571  G4double stepLen = fCurrentStepSize[num];
572  if( stepLen > fTrueMinStep )
573  {
574  stepLen = fTrueMinStep; // did not limit (went as far as asked)
575  }
576  G4int oldPrec= G4cout.precision(9);
577 
578  G4cout << std::setw(5) << num << " "
579  << std::setw(12) << stepLen << " "
580  << std::setw(12) << rawStep << " "
581  << std::setw(12) << fNewSafety[num] << " "
582  << std::setw(5) << (fLimitTruth[num] ? "YES" : " NO") << " ";
583  G4String limitedStr;
584  switch ( fLimitedStep[num] )
585  {
586  case kDoNot : limitedStr= StrDoNot; break;
587  case kUnique : limitedStr = StrUnique; break;
588  case kSharedTransport: limitedStr= StrSharedTransport; break;
589  case kSharedOther : limitedStr = StrSharedOther; break;
590  default : limitedStr = StrUndefined; break;
591  }
592  G4cout << " " << std::setw(15) << limitedStr << " ";
593  G4cout.precision(oldPrec);
594 
595  G4ITNavigator *pNav= fpNavigator[ num ];
596  G4String WorldName( "Not-Set" );
597  if (pNav)
598  {
599  G4VPhysicalVolume *pWorld= pNav->GetWorldVolume();
600  if( pWorld )
601  {
602  WorldName = pWorld->GetName();
603  }
604  }
605  G4cout << " " << WorldName ;
606  G4cout << G4endl;
607  }
608 }
609 
610 
611 // -----------------------------------------------------------------------
612 
614 {
615  fWasLimitedByGeometry= false;
616 
617  G4Exception("G4ITMultiNavigator::ResetState()", "GeomNav0001",
619  "Cannot reset state for navigators of G4ITMultiNavigator.");
620 
621  std::vector<G4ITNavigator*>::iterator pNavigatorIter;
622  pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
623  for( G4int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
624  {
625  // (*pNavigatorIter)->ResetState(); // KEEP THIS comment !!!
626  }
627 }
628 
629 // -----------------------------------------------------------------------
630 
632 {
633  G4Exception( "G4ITMultiNavigator::SetupHierarchy()",
634  "GeomNav0001", FatalException,
635  "Cannot setup hierarchy for navigators of G4ITMultiNavigator.");
636 }
637 
638 // -----------------------------------------------------------------------
639 
641 {
642  G4VPhysicalVolume* navTrackWorld=
643  pTransportManager->GetNavigatorForTracking()->GetWorldVolume();
644 
645  if( navTrackWorld != fLastMassWorld )
646  {
647  G4Exception( "G4ITMultiNavigator::CheckMassWorld()",
648  "GeomNav0003", FatalException,
649  "Mass world pointer has been changed." );
650  }
651 }
652 
653 // -----------------------------------------------------------------------
654 
657  const G4ThreeVector &direction,
658  const G4TouchableHistory &MassHistory)
659 {
660  // Reset geometry for all -- and use the touchable for the mass history
661 
662  G4VPhysicalVolume* massVolume=0;
663  G4ITNavigator* pMassNavigator= fpNavigator[0];
664 
665  if( pMassNavigator )
666  {
667  massVolume= pMassNavigator->ResetHierarchyAndLocate( point, direction,
668  MassHistory);
669  }
670  else
671  {
672  G4Exception("G4ITMultiNavigator::ResetHierarchyAndLocate()",
673  "GeomNav0002", FatalException,
674  "Cannot reset hierarchy before navigators are initialised.");
675  }
676 
677  std::vector<G4ITNavigator*>::iterator pNavIter=
679 
680  for ( G4int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
681  {
682  G4bool relativeSearch, ignoreDirection;
683 
684  (*pNavIter)-> LocateGlobalPointAndSetup( point,
685  &direction,
686  relativeSearch=false,
687  ignoreDirection=false);
688  }
689  return massVolume;
690 }
691 
692 // ----------------- ooooooOOOOOOOOOOOOOOOoooooo -------------------------------------
693 
696  G4bool* argpObtained) // obtained valid
697 {
698  G4ThreeVector normalGlobalCrd(0.0, 0.0, 0.0);
699  G4bool isObtained= false;
700  // These default values will be used if fNoLimitingStep== 0
701  G4int firstNavigatorId= -1;
702  G4bool oneObtained= false;
703 
704  if( fNoLimitingStep==1 )
705  {
706  // Only message the Navigator which limited the step!
707  normalGlobalCrd= fpNavigator[ fIdNavLimiting ]->GetGlobalExitNormal( argPoint, &isObtained);
708  *argpObtained= isObtained;
709  }
710  else
711  {
712  if( fNoLimitingStep > 1 )
713  {
714  std::vector<G4ITNavigator*>::iterator pNavIter=
716 
717  for ( G4int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
718  {
719  G4ThreeVector oneNormal;
720  if( fLimitTruth[ num ] ) // Did this geometry limit the step ?
721  {
722  G4ThreeVector newNormal= (*pNavIter)-> GetGlobalExitNormal( argPoint, &oneObtained );
723  if( oneObtained )
724  {
725  // Keep first one - only if it is valid (ie not null)
726  if( !isObtained && (newNormal.mag2() != 0.0) )
727  {
728  normalGlobalCrd= newNormal;
729  isObtained = oneObtained;
730  firstNavigatorId= num;
731  }else{
732  // Check for clash
733  G4double dotNewPrevious= newNormal.dot( normalGlobalCrd );
734  G4double productMagSq= normalGlobalCrd.mag2() * newNormal.mag2();
735  if( productMagSq > 0.0 )
736  {
737  G4double productMag= std::sqrt( productMagSq );
738  dotNewPrevious /= productMag; // Normalise
739  if( dotNewPrevious < (1 - perThousand) )
740  {
741  *argpObtained= false;
742 
743  if( fVerbose > 2 ) // dotNewPrevious <= 0.0 )
744  {
745  std::ostringstream message;
746  message << "Clash of Normal from different Navigators!" << G4endl
747  << " Previous Navigator Id = " << firstNavigatorId << G4endl
748  << " Current Navigator Id = " << num << G4endl;
749  message << " Dot product of 2 normals = " << dotNewPrevious << G4endl;
750  message << " Normal (previous) = " << normalGlobalCrd << G4endl;
751  message << " Normal (current) = " << newNormal << G4endl;
752  G4Exception("G4ITMultiNavigator::GetGlobalExitNormal()", "GeomNav0002",
753  JustWarning, message);
754  }
755  }
756  else
757  {
758  // Close agreement - Do not change
759  }
760  }
761  }
762  }
763  }
764  } // end for over the Navigators
765 
766  // Report if no Normal was obtained
767  if( !oneObtained )
768  {
769  std::ostringstream message;
770  message << "No Normal obtained despite having " << fNoLimitingStep
771  << " candidate Navigators limiting the step!" << G4endl;
772  G4Exception("G4ITMultiNavigator::GetGlobalExitNormal()", "GeomNav0002",
773  JustWarning, message);
774  }
775 
776  } // end if ( fNoLimiting > 1 )
777  } // end else
778 
779  *argpObtained= isObtained;
780  return normalGlobalCrd;
781 }
782 
783 // ----------------- ooooooOOOOOOOOOOOOOOOoooooo -------------------------------------
784 
787 {
788  // If it is the mass navigator, then expect
789  G4ThreeVector normalGlobalCrd(0.0, 0.0, 0.0);
790  G4bool isObtained= false;
791  // These default values will be used if fNoLimitingStep== 0
792 
793  if( fNoLimitingStep==1 )
794  {
795  // Only message the Navigator which limited the step!
796  normalGlobalCrd= fpNavigator[ fIdNavLimiting ]->GetLocalExitNormal( &isObtained);
797  *argpObtained= isObtained;
798 
799  static G4ThreadLocal G4int numberWarnings= 0;
800  G4int noWarningsStart= 10, noModuloWarnings=100;
801  numberWarnings++;
802  if( (numberWarnings < noWarningsStart ) || (numberWarnings%noModuloWarnings==0) )
803  {
804  std::ostringstream message;
805  message << "Cannot obtain normal in local coordinates of two or more coordinate systems." << G4endl;
806  G4Exception("G4ITMultiNavigator::GetGlobalExitNormal()", "GeomNav0002",
807  JustWarning, message);
808  }
809  }
810  else
811  {
812  if( fNoLimitingStep > 1 )
813  {
814  // Does not make sense - cannot obtain *local* normal in several coordinate systems
815  std::ostringstream message;
816  message << "Cannot obtain normal in local coordinates of two or more coordinate systems." << G4endl;
817  G4Exception("G4ITMultiNavigator::GetGlobalExitNormal()", "GeomNav0002",
818  FatalException, message);
819  }
820  }
821 
822  *argpObtained= isObtained;
823  return normalGlobalCrd;
824 }
825 
826 
827 // ----------------- ooooooOOOOOOOOOOOOOOOoooooo -------------------------------------
828 
831  G4bool* obtained)
832 {
833  return G4ITMultiNavigator::GetLocalExitNormal( obtained);
834 }