source: trunk/source/geometry/navigation/src/G4MultiNavigator.cc @ 836

Last change on this file since 836 was 831, checked in by garnier, 16 years ago

import all except CVS

File size: 21.0 KB
Line 
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: G4MultiNavigator.cc,v 1.7 2007/11/02 13:48:43 japost Exp $
28// GEANT4 tag $ Name:  $
29//
30// class G4PathFinder Implementation
31//
32// Author:  John Apostolakis, November 2006
33// --------------------------------------------------------------------
34
35#include "G4MultiNavigator.hh"
36
37class G4FieldManager;
38
39#include "G4Navigator.hh"
40#include "G4PropagatorInField.hh"
41#include "G4TransportationManager.hh"
42
43#include <iomanip>
44
45// ********************************************************************
46// Constructor
47// ********************************************************************
48//
49G4MultiNavigator::G4MultiNavigator() 
50  : G4Navigator()
51{
52  fNoActiveNavigators= 0; 
53  G4ThreeVector Big3Vector( DBL_MAX, DBL_MAX, DBL_MAX ); 
54  fLastLocatedPosition = Big3Vector;
55  fSafetyLocation  = Big3Vector;
56  fPreStepLocation = Big3Vector;
57
58  fMinSafety_PreStepPt=  -1.0; 
59  fMinSafety_atSafLocation= -1.0; 
60  fMinSafety= -DBL_MAX; 
61  fMinStep=   -DBL_MAX; 
62
63  for(register int num=0; num<= fMaxNav; ++num )
64  {
65    fpNavigator[num] =  0;   
66    fLimitTruth[num] = false;
67    fLimitedStep[num] = kUndefLimited;
68    fCurrentStepSize[num] = -1.0; 
69    fLocatedVolume[num] = 0; 
70  }
71
72  pTransportManager= G4TransportationManager::GetTransportationManager();
73
74  G4Navigator* massNav= pTransportManager->GetNavigatorForTracking();
75  if( massNav )
76  { 
77    G4VPhysicalVolume* pWorld= massNav->GetWorldVolume(); 
78    if( pWorld )
79    { 
80      SetWorldVolume( pWorld ); 
81      fLastMassWorld = pWorld; 
82    }
83  }
84}
85
86G4MultiNavigator::~G4MultiNavigator() 
87{
88}
89
90G4double G4MultiNavigator::ComputeStep(const G4ThreeVector &pGlobalPoint,
91                                       const G4ThreeVector &pDirection,
92                                       const G4double       proposedStepLength,
93                                             G4double      &pNewSafety)
94{
95  G4double safety= 0.0, step=0.0;
96  G4double minSafety= DBL_MAX, minStep= DBL_MAX;
97
98#ifdef G4DEBUG_NAVIGATION
99  if( fVerbose > 2 )
100  {
101    G4cout << " G4MultiNavigator::ComputeStep : entered " << G4endl;
102    G4cout << "   Input position= " << pGlobalPoint
103           << "   direction= "      << pDirection         << G4endl;
104    G4cout << "   Requested step= " << proposedStepLength << G4endl;
105  }
106#endif
107
108  std::vector<G4Navigator*>::iterator pNavigatorIter;
109
110  pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
111
112  G4ThreeVector initialPosition = pGlobalPoint;
113  G4ThreeVector initialDirection= pDirection;
114
115  for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
116  {
117     safety= DBL_MAX;
118
119     step= (*pNavigatorIter)->ComputeStep( initialPosition, 
120                                           initialDirection,
121                                           proposedStepLength,
122                                           safety ); 
123     if( safety < minSafety ){ minSafety = safety; } 
124     if( step < minStep )    { minStep= step; } 
125
126     fCurrentStepSize[num] = step; 
127     fNewSafety[num]= safety; 
128      // This is currently the safety from the last sub-step
129
130#ifdef G4DEBUG_NAVIGATION
131     if( fVerbose > 2 )
132     {
133       G4cout << "G4MultiNavigator::ComputeStep : Navigator ["
134              << num << "] -- step size " << step
135              << " safety= " << safety << G4endl;
136     }
137#endif
138  } 
139
140  // Save safety value, related position
141  //
142  fPreStepLocation     = initialPosition; 
143  fMinSafety_PreStepPt = minSafety;
144  fMinStep = minStep; 
145
146  if( fMinStep == kInfinity )
147  {
148     fTrueMinStep = proposedStepLength;   //  Use this below for endpoint !!
149  }
150  else
151  {
152     fTrueMinStep = minStep;
153  }
154
155#ifdef G4DEBUG_NAVIGATION
156  if( fVerbose > 1 )
157  {
158    G4ThreeVector endPosition = initialPosition+fTrueMinStep*initialDirection;
159
160    G4int oldPrec = G4cout.precision(8); 
161    G4cout << "G4MultiNavigator::ComputeStep : "
162           << " initialPosition = " << initialPosition
163           << " and endPosition = " << endPosition << G4endl;
164    G4cout.precision( oldPrec );
165  }
166#endif
167
168  pNewSafety = minSafety; 
169
170  this->WhichLimited(); 
171
172#ifdef G4DEBUG_NAVIGATION
173  if( fVerbose > 2 )
174  {
175    G4cout << " G4MultiNavigator::ComputeStep : exits returning "
176           << minStep << G4endl;
177  }
178#endif
179
180  return minStep;  // must return kInfinity if do not limit step
181}
182
183// ----------------------------------------------------------------------
184
185G4double
186G4MultiNavigator::ObtainFinalStep( G4int     navigatorId, 
187                                   G4double &pNewSafety,  // for this geometry
188                                   G4double &minStep,
189                                   ELimited &limitedStep) 
190{
191  G4int navigatorNo=-1; 
192
193  if( navigatorId <= fNoActiveNavigators )
194  {
195     navigatorNo= navigatorId;
196  }
197  else
198  { 
199     G4cerr << "ERROR - G4MultiNavigator::ObtainFinalStep()"
200            << "        Navigator Id = " << navigatorId
201            << "        No Active = " << fNoActiveNavigators << " . "
202            << G4endl;
203     G4Exception("G4MultiNavigator::ObtainFinalStep()", "InvalidSetup",
204                 FatalException, "Bad Navigator Id" ); 
205  }
206
207  // Prepare the information to return
208  pNewSafety  = fNewSafety[ navigatorNo ]; 
209  limitedStep = fLimitedStep[ navigatorNo ];
210  minStep= fMinStep; 
211
212  // if( (minStep==kInfinity) || (fVerbose > 1) ){
213#ifdef G4DEBUG_NAVIGATION
214  if( fVerbose > 1 ){ 
215     G4cout << " G4MultiNavigator::ComputeStep returns " << fCurrentStepSize[ navigatorNo ]
216            << " for Navigator " << navigatorNo << " Limited step = " << limitedStep
217            << " Safety(mm) = " << pNewSafety / mm << G4endl; 
218  }
219#endif
220
221  return fCurrentStepSize[ navigatorNo ];
222}
223
224// ----------------------------------------------------------------------
225
226void G4MultiNavigator::PrepareNewTrack( const G4ThreeVector position, 
227                                        const G4ThreeVector direction )
228{
229#ifdef G4DEBUG_NAVIGATION
230  if( fVerbose > 1 )
231  {
232    G4cout << " Entered G4MultiNavigator::PrepareNewTrack() " << G4endl;
233  }
234#endif
235
236  G4MultiNavigator::PrepareNavigators(); 
237
238  LocateGlobalPointAndSetup( position, &direction, false, false );   
239  //
240  // The first location for each Navigator must be non-relative
241  // or else call ResetStackAndState() for each Navigator
242  // Use direction to get correct side of boundary (ignore dir= false)
243}
244
245// ----------------------------------------------------------------------
246
247void G4MultiNavigator::PrepareNavigators()
248{
249  // Key purposes:
250  //   - Check and cache set of active navigators
251  //   - Reset state for new track
252
253#ifdef G4DEBUG_NAVIGATION
254  if( fVerbose > 1 )
255  {
256    G4cout << " Entered G4MultiNavigator::PrepareNavigators() " << G4endl;
257  }
258#endif
259
260  // Message the transportation-manager to find active navigators
261
262  std::vector<G4Navigator*>::iterator pNavigatorIter; 
263  fNoActiveNavigators=  pTransportManager-> GetNoActiveNavigators();
264
265  if( fNoActiveNavigators > fMaxNav )
266  {
267    G4cerr << "ERROR - G4MultiNavigator::PrepareNavigators()"
268           << "        Too many active Navigators (worlds): "
269           << fNoActiveNavigators << G4endl
270           << "        which is more than the number allowed: "
271           << fMaxNav << " !" << G4endl;
272    G4Exception("G4MultiNavigator::PrepareNavigators()", "InvalidSetup", 
273                FatalException, "Too many active Navigators / worlds !"); 
274  }
275
276  pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
277  for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
278  {
279     fpNavigator[num] =  *pNavigatorIter;   
280     fLimitTruth[num] = false;
281     fLimitedStep[num] = kDoNot;
282     fCurrentStepSize[num] = 0.0; 
283     fLocatedVolume[num] = 0; 
284  }
285  fWasLimitedByGeometry = false; 
286
287  // Check the world volume of the mass navigator
288  // in case a call to SetWorldVolume() changed it
289
290  G4VPhysicalVolume* massWorld = GetWorldVolume();
291
292  if( (massWorld != fLastMassWorld) && (massWorld!=0) )
293  { 
294     // Pass along change to Mass Navigator
295     fpNavigator[0] -> SetWorldVolume( massWorld );
296
297#ifdef G4DEBUG_NAVIGATION
298     if( fVerbose > 0 )
299     { 
300       G4cout << " G4MultiNavigator::PrepareNavigators() changed world volume " 
301              << " for mass geometry to " << massWorld->GetName() << G4endl; 
302     }
303#endif
304
305     fLastMassWorld = massWorld;
306  }
307}
308
309// ----------------------------------------------------------------------
310
311G4VPhysicalVolume* 
312G4MultiNavigator::LocateGlobalPointAndSetup(const G4ThreeVector& position,
313                                            const G4ThreeVector* pDirection,
314                                            const G4bool pRelativeSearch,
315                                            const G4bool ignoreDirection )
316{
317  // Locate the point in each geometry
318
319  G4ThreeVector direction(0.0, 0.0, 0.0);
320  G4bool relative = pRelativeSearch; 
321  std::vector<G4Navigator*>::iterator pNavIter
322    = pTransportManager->GetActiveNavigatorsIterator(); 
323
324  if( pDirection ) { direction = *pDirection; }
325
326#ifdef G4DEBUG_NAVIGATION
327  if( fVerbose > 2 )
328  {
329    G4cout << " Entered G4MultiNavigator::LocateGlobalPointAndSetup() "
330           << G4endl;
331    G4cout << "   Locating at position: " << position
332           << ", with direction: " << direction << G4endl
333           << "   Relative: " << relative
334           << ", ignore direction: " << ignoreDirection << G4endl;
335    G4cout << "   Number of active navigators: " << fNoActiveNavigators
336           << G4endl;
337  }
338#endif
339
340  for ( register int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
341  {
342     if( fWasLimitedByGeometry && fLimitTruth[num] )
343     { 
344        (*pNavIter)->SetGeometricallyLimitedStep(); 
345     }
346
347     G4VPhysicalVolume *pLocated
348       = (*pNavIter)->LocateGlobalPointAndSetup( position, &direction,
349                                                 relative, ignoreDirection );   
350     // Set the state related to the location
351     //
352     fLocatedVolume[num] = pLocated; 
353
354     // Clear state related to the step
355     //
356     fLimitedStep[num]   = kDoNot; 
357     fCurrentStepSize[num] = 0.0;     
358     fLimitTruth[ num ] = false;   // Always clear on locating (see Navigator)
359   
360#ifdef G4DEBUG_NAVIGATION
361     if( fVerbose > 2 )
362     {
363       G4cout << " Located in world: " << num << ", at: " << position << G4endl
364              << " Used geomLimStp: " << fLimitTruth[num]
365              << ", found in volume: " << pLocated << G4endl; 
366       G4cout << " Name = '" ;       
367       if( pLocated )
368       { 
369         G4cout << pLocated->GetName() << "'"; 
370         G4cout << " - CopyNo= " << pLocated->GetCopyNo(); 
371       }
372       else
373       { 
374         G4cout <<  "Null'   Id: Not-Set "; 
375       }
376       G4cout << G4endl; 
377     }
378#endif
379  }
380
381  fWasLimitedByGeometry = false;   // Clear on locating
382  G4VPhysicalVolume* volMassLocated= fLocatedVolume[0]; 
383
384  return volMassLocated;
385}
386
387// ----------------------------------------------------------------------
388
389void
390G4MultiNavigator::LocateGlobalPointWithinVolume(const G4ThreeVector& position)
391{
392  // Relocate the point in each geometry
393
394  std::vector<G4Navigator*>::iterator pNavIter
395    = pTransportManager->GetActiveNavigatorsIterator(); 
396
397#ifdef G4DEBUG_NAVIGATION
398  if( fVerbose > 2 )
399  {
400    G4cout << " Entered G4MultiNavigator::ReLocate() " << G4endl
401           << "  Re-locating at position: " << position  << G4endl; 
402  }
403#endif
404
405  for ( register int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
406  {
407     //  ... none limited the step
408
409     (*pNavIter)->LocateGlobalPointWithinVolume( position ); 
410
411     // Clear state related to the step
412     //
413     fLimitedStep[num]     = kDoNot; 
414     fCurrentStepSize[num] = 0.0;     
415
416     fLimitTruth[ num ] = false;   // Always clear on locating (see Navigator)
417  }
418  fWasLimitedByGeometry = false;   // Clear on locating
419  fLastLocatedPosition  = position; 
420}
421
422// ----------------------------------------------------------------------
423
424G4double G4MultiNavigator::ComputeSafety( const G4ThreeVector& position,
425                                                G4double       maxDistance)
426{
427    // Recompute safety for the relevant point
428
429    G4double minSafety = DBL_MAX, safety = DBL_MAX;
430 
431    std::vector<G4Navigator*>::iterator pNavigatorIter;
432    pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
433
434    for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
435    {
436       safety = (*pNavigatorIter)->ComputeSafety( position, maxDistance );
437       if( safety < minSafety ) { minSafety = safety; } 
438    } 
439
440    fSafetyLocation = position;
441    fMinSafety_atSafLocation = minSafety;
442
443#ifdef G4DEBUG_NAVIGATION
444    if( fVerbose > 1 )
445    { 
446      G4cout << " G4MultiNavigator::ComputeSafety - returns: " 
447             << minSafety << ", at location: " << position << G4endl;
448    }
449#endif
450    return minSafety; 
451}
452
453// -----------------------------------------------------------------------
454
455G4TouchableHistoryHandle
456G4MultiNavigator::CreateTouchableHistoryHandle() const
457{
458  G4Exception( "G4MultiNavigator::CreateTouchableHistoryHandle()", 
459               "215-TouchableFromWrongNavigator", FatalException, 
460               "Getting a touchable from G4MultiNavigator is not defined."); 
461
462  G4TouchableHistory* touchHist;
463  touchHist= fpNavigator[0] -> CreateTouchableHistory(); 
464
465  G4VPhysicalVolume* locatedVolume= fLocatedVolume[0]; 
466  if( locatedVolume == 0 )
467  {
468    // Workaround to ensure that the touchable is fixed !! // TODO: fix
469    //
470    touchHist->UpdateYourself( locatedVolume, touchHist->GetHistory() );
471  }
472   
473  return G4TouchableHistoryHandle(touchHist); 
474}
475
476// -----------------------------------------------------------------------
477
478void G4MultiNavigator::WhichLimited()
479{
480  // Flag which processes limited the step
481
482  G4int last=-1; 
483  const G4int IdTransport= 0;  // Id of Mass Navigator !!
484  G4int noLimited=0; 
485  ELimited shared= kSharedOther; 
486
487#ifdef G4DEBUG_NAVIGATION
488  if( fVerbose > 2 )
489  {
490    G4cout << " Entered G4MultiNavigator::WhichLimited() " << G4endl;
491  }
492#endif
493
494  // Assume that [IdTransport] is Mass / Transport
495  //
496  G4bool transportLimited = (fCurrentStepSize[IdTransport] == fMinStep)
497                         && ( fMinStep!= kInfinity); 
498  if( transportLimited )
499  { 
500     shared= kSharedTransport;
501  }
502
503  for ( register int num= 0; num < fNoActiveNavigators; num++ )
504  { 
505    G4bool limitedStep;
506
507    G4double step= fCurrentStepSize[num]; 
508
509    limitedStep = ( step == fMinStep ) && ( step != kInfinity); 
510   
511    fLimitTruth[ num ] = limitedStep; 
512    if( limitedStep )
513    {
514      noLimited++; 
515      fLimitedStep[num] = shared;
516      last= num; 
517    }
518    else
519    {
520      fLimitedStep[num] = kDoNot;
521    }
522  }
523  if( (last > -1) && (noLimited == 1 ) )
524  {
525    fLimitedStep[ last ] = kUnique; 
526  }
527}
528
529// -----------------------------------------------------------------------
530
531void
532G4MultiNavigator::PrintLimited()
533{
534  // Report results -- for checking   
535
536  static G4String StrDoNot("DoNot"), StrUnique("Unique"),
537                  StrUndefined("Undefined"),
538                  StrSharedTransport("SharedTransport"),
539                  StrSharedOther("SharedOther");
540  G4cout << "### G4MultiNavigator::PrintLimited() reports: " << G4endl;
541  G4cout << "    Minimum step (true): " << fTrueMinStep
542         << ", reported min: " << fMinStep << G4endl; 
543
544#ifdef G4DEBUG_NAVIGATION
545  if(fVerbose>=2)
546  {
547    G4cout << std::setw(5) << " NavId"  << " "
548           << std::setw(12) << " step-size " << " "
549           << std::setw(12) << " raw-size "  << " "
550           << std::setw(12) << " pre-safety " << " " 
551           << std::setw(15) << " Limited / flag"  << " "
552           << std::setw(15) << "  World "  << " "
553           << G4endl; 
554  }
555#endif
556
557  for ( register int num= 0; num < fNoActiveNavigators; num++ )
558  { 
559    G4double rawStep = fCurrentStepSize[num]; 
560    G4double stepLen = fCurrentStepSize[num]; 
561    if( stepLen > fTrueMinStep )
562    { 
563      stepLen = fTrueMinStep;     // did not limit (went as far as asked)
564    }
565    G4int oldPrec= G4cout.precision(9); 
566
567    G4cout << std::setw(5) << num  << " "
568           << std::setw(12) << stepLen << " "
569           << std::setw(12) << rawStep << " "
570           << std::setw(12) << fNewSafety[num] << " "
571           << std::setw(5) << (fLimitTruth[num] ? "YES" : " NO") << " ";
572    G4String limitedStr;
573    switch ( fLimitedStep[num] )
574    {
575      case kDoNot          : limitedStr= StrDoNot; break;
576      case kUnique         : limitedStr = StrUnique; break; 
577      case kSharedTransport: limitedStr= StrSharedTransport; break; 
578      case kSharedOther    : limitedStr = StrSharedOther; break;
579      default              : limitedStr = StrUndefined; break;
580    }
581    G4cout << " " << std::setw(15) << limitedStr << " "; 
582    G4cout.precision(oldPrec); 
583
584    G4Navigator *pNav= fpNavigator[ num ]; 
585    G4String  WorldName( "Not-Set" ); 
586    if (pNav)
587    {
588       G4VPhysicalVolume *pWorld= pNav->GetWorldVolume(); 
589       if( pWorld )
590       {
591           WorldName = pWorld->GetName(); 
592       }
593    }
594    G4cout << " " << WorldName ; 
595    G4cout << G4endl;
596  }
597}
598 
599
600// -----------------------------------------------------------------------
601
602void G4MultiNavigator::ResetState()
603{
604   fWasLimitedByGeometry= false; 
605
606   G4Exception("G4MultiNavigator::ResetState()", "217-NotImplemented", 
607               FatalException, 
608               "Cannot call ResetState() for navigators of G4MultiNavigator.");
609   
610   std::vector<G4Navigator*>::iterator pNavigatorIter;
611   pNavigatorIter= pTransportManager-> GetActiveNavigatorsIterator();
612   for( register int num=0; num< fNoActiveNavigators; ++pNavigatorIter,++num )
613   {
614       //  (*pNavigatorIter)->ResetState();  // KEEP THIS comment !!!
615   } 
616}
617
618// -----------------------------------------------------------------------
619
620void G4MultiNavigator::SetupHierarchy()
621{
622  G4Exception( "G4MultiNavigator::SetupHierarchy()", 
623               "217-NotImplemented", FatalException, 
624           "Cannot call SetupHierarchy() for navigators of G4MultiNavigator."); 
625}
626
627// -----------------------------------------------------------------------
628
629void G4MultiNavigator::CheckMassWorld()
630{
631   G4VPhysicalVolume* navTrackWorld=
632     pTransportManager->GetNavigatorForTracking()->GetWorldVolume();
633
634   if( navTrackWorld != fLastMassWorld )
635   { 
636      G4Exception( "G4MultiNavigator::CheckMassWorld()",
637                   "220-InvalidSetup", FatalException, 
638                   "Mass world pointer has been changed." ); 
639   }
640}
641
642// -----------------------------------------------------------------------
643
644G4VPhysicalVolume*
645G4MultiNavigator::ResetHierarchyAndLocate(const G4ThreeVector &point,
646                                          const G4ThreeVector &direction,
647                                          const G4TouchableHistory &MassHistory)
648{
649   // Reset geometry for all -- and use the touchable for the mass history
650
651   G4VPhysicalVolume* massVolume=0; 
652   G4Navigator* pMassNavigator= fpNavigator[0]; 
653
654   if( pMassNavigator )
655   {
656      massVolume= pMassNavigator->ResetHierarchyAndLocate( point, direction,
657                                                           MassHistory); 
658   }
659   else
660   {
661      G4Exception("G4MultiNavigator::ResetHierarchyAndLocate()",
662                  "218-TooEarlyToReset", FatalException,
663                  "Cannot reset hierarchy before navigators are initialised.");
664   }
665
666   std::vector<G4Navigator*>::iterator pNavIter= 
667       pTransportManager->GetActiveNavigatorsIterator(); 
668
669   for ( register int num=0; num< fNoActiveNavigators ; ++pNavIter,++num )
670   {
671      G4bool relativeSearch, ignoreDirection; 
672
673      (*pNavIter)-> LocateGlobalPointAndSetup( point, 
674                                               &direction, 
675                                               relativeSearch=false,
676                                               ignoreDirection=false);
677   }
678   return massVolume; 
679}
Note: See TracBrowser for help on using the repository browser.