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