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

Last change on this file since 892 was 831, checked in by garnier, 17 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.