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