Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ITNavigator1.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// class G4ITNavigator1 Implementation
28//
29// Original author: Paul Kent, July 95/96
30//
31// G4ITNavigator1 is a duplicate version of G4Navigator starting from Geant4.9.5
32// initially written by Paul Kent and colleagues.
33// The only difference resides in the way the information is saved and managed
34//
35// History:
36// - Created. Paul Kent, Jul 95/96
37// - Zero step protections J.A. / G.C., Nov 2004
38// - Added check mode G. Cosmo, Mar 2004
39// - Made Navigator Abstract G. Cosmo, Nov 2003
40// - G4ITNavigator1 created M.K., Nov 2012
41// --------------------------------------------------------------------
42
43#include <iomanip>
44
45#include "G4ITNavigator1.hh"
46//#include "G4ITNavigator.hh"
47#include "G4ios.hh"
48#include "G4SystemOfUnits.hh"
50#include "G4VPhysicalVolume.hh"
51
52#define G4DEBUG_NAVIGATION 1
53#include "G4VoxelSafety.hh"
54
55// ********************************************************************
56// Constructor
57// ********************************************************************
58//
60 : fWasLimitedByGeometry(false), fVerbose(0),
61 fTopPhysical(0), fCheck(false), fPushed(false), fWarnPush(true)
62{
63 fActive= false;
64 fLastTriedStepComputation= false;
65
67 // Initialises also all
68 // - exit / entry flags
69 // - flags & variables for exit normals
70 // - zero step counters
71 // - blocked volume
72
73 fActionThreshold_NoZeroSteps = 10;
74 fAbandonThreshold_NoZeroSteps = 25;
75
77 fregularNav.SetNormalNavigation( &fnormalNav );
78
79 fStepEndPoint = G4ThreeVector( kInfinity, kInfinity, kInfinity );
80 fLastStepEndPointLocal = G4ThreeVector( kInfinity, kInfinity, kInfinity );
81
82 fpVoxelSafety= new G4VoxelSafety();
83 fpSaveState = 0;
84
85 // this->SetVerboseLevel(3);
86 // this->CheckMode(true);
87}
88
89// !>
90
91G4ITNavigator1::G4SaveNavigatorState::G4SaveNavigatorState() : G4ITNavigatorState_Lock1()
92{
93 sWasLimitedByGeometry = false;
94 sEntering = false;
95 sExiting = false;
96 sLocatedOnEdge = false;
97 sLastStepWasZero = false;
98 sEnteredDaughter = false;
99 sExitedMother = false;
100 sPushed = false;
101
102 sValidExitNormal = false;
103 sExitNormal = G4ThreeVector(0,0,0);
104
105 sPreviousSftOrigin = G4ThreeVector(0,0,0);
106 sPreviousSafety = 0.0;
107
108 sNumberZeroSteps = 0;
109
110 spBlockedPhysicalVolume = 0;
111 sBlockedReplicaNo = -1;
112
113 sLastLocatedPointLocal = G4ThreeVector( kInfinity, -kInfinity, 0.0 );
114 sLocatedOutsideWorld = false;
115}
116
117// <!
118
119// ********************************************************************
120// Destructor
121// ********************************************************************
122//
124{ delete fpVoxelSafety; }
125
126// ********************************************************************
127// ResetHierarchyAndLocate
128// ********************************************************************
129//
132 const G4ThreeVector &direction,
133 const G4TouchableHistory &h)
134{
135 ResetState();
136 fHistory = *h.GetHistory();
138 fLastTriedStepComputation= false; // Redundant, but best
139 return LocateGlobalPointAndSetup(p, &direction, true, false);
140}
141
142// ********************************************************************
143// LocateGlobalPointAndSetup
144//
145// Locate the point in the hierarchy return 0 if outside
146// The direction is required
147// - if on an edge shared by more than two surfaces
148// (to resolve likely looping in tracking)
149// - at initial location of a particle
150// (to resolve potential ambiguity at boundary)
151//
152// Flags on exit: (comments to be completed)
153// fEntering - True if entering `daughter' volume (or replica)
154// whether daughter of last mother directly
155// or daughter of that volume's ancestor.
156// ********************************************************************
157//
160 const G4ThreeVector* pGlobalDirection,
161 const G4bool relativeSearch,
162 const G4bool ignoreDirection )
163{
164 G4bool notKnownContained=true, noResult;
165 G4VPhysicalVolume *targetPhysical;
166 G4LogicalVolume *targetLogical;
167 G4VSolid *targetSolid=0;
168 G4ThreeVector localPoint, globalDirection;
169 EInside insideCode;
170
171 G4bool considerDirection = (!ignoreDirection) || fLocatedOnEdge;
172
173 fLastTriedStepComputation= false;
174 fChangedGrandMotherRefFrame= false; // For local exit normal
175
176 if( considerDirection && pGlobalDirection != 0 )
177 {
178 globalDirection=*pGlobalDirection;
179 }
180
181
182#ifdef G4VERBOSE
183 if( fVerbose > 2 )
184 {
185 G4long oldcoutPrec = G4cout.precision(8);
186 G4cout << "*** G4ITNavigator1::LocateGlobalPointAndSetup: ***" << G4endl;
187 G4cout << " Called with arguments: " << G4endl
188 << " Globalpoint = " << globalPoint << G4endl
189 << " RelativeSearch = " << relativeSearch << G4endl;
190 if( fVerbose == 4 )
191 {
192 G4cout << " ----- Upon entering:" << G4endl;
193 PrintState();
194 }
195 G4cout.precision(oldcoutPrec);
196 }
197#endif
198
199 if ( !relativeSearch )
200 {
202 }
203 else
204 {
206 {
207 fWasLimitedByGeometry = false;
208 fEnteredDaughter = fEntering; // Remember
209 fExitedMother = fExiting; // Remember
210 if ( fExiting )
211 {
212 if ( fHistory.GetDepth() )
213 {
214 fBlockedPhysicalVolume = fHistory.GetTopVolume();
215 fBlockedReplicaNo = fHistory.GetTopReplicaNo();
217 }
218 else
219 {
220 fLastLocatedPointLocal = localPoint;
221 fLocatedOutsideWorld = true;
222 return 0; // Have exited world volume
223 }
224 // A fix for the case where a volume is "entered" at an edge
225 // and a coincident surface exists outside it.
226 // - This stops it from exiting further volumes and cycling
227 // - However ReplicaNavigator treats this case itself
228 //
229 if ( fLocatedOnEdge && (VolumeType(fBlockedPhysicalVolume)!=kReplica ))
230 {
231 fExiting= false;
232 }
233 }
234 else
235 if ( fEntering )
236 {
237 switch (VolumeType(fBlockedPhysicalVolume))
238 {
239 case kNormal:
240 fHistory.NewLevel(fBlockedPhysicalVolume, kNormal,
241 fBlockedPhysicalVolume->GetCopyNo());
242 break;
243 case kReplica:
244 freplicaNav.ComputeTransformation(fBlockedReplicaNo,
245 fBlockedPhysicalVolume);
246 fHistory.NewLevel(fBlockedPhysicalVolume, kReplica,
247 fBlockedReplicaNo);
248 fBlockedPhysicalVolume->SetCopyNo(fBlockedReplicaNo);
249 break;
250 case kParameterised:
251 if( fBlockedPhysicalVolume->GetRegularStructureId() == 0 )
252 {
253 G4VSolid *pSolid;
254 G4VPVParameterisation *pParam;
255 G4TouchableHistory parentTouchable( fHistory );
256 pParam = fBlockedPhysicalVolume->GetParameterisation();
257 pSolid = pParam->ComputeSolid(fBlockedReplicaNo,
258 fBlockedPhysicalVolume);
259 pSolid->ComputeDimensions(pParam, fBlockedReplicaNo,
260 fBlockedPhysicalVolume);
261 pParam->ComputeTransformation(fBlockedReplicaNo,
262 fBlockedPhysicalVolume);
263 fHistory.NewLevel(fBlockedPhysicalVolume, kParameterised,
264 fBlockedReplicaNo);
265 fBlockedPhysicalVolume->SetCopyNo(fBlockedReplicaNo);
266 //
267 // Set the correct solid and material in Logical Volume
268 //
269 G4LogicalVolume *pLogical;
270 pLogical = fBlockedPhysicalVolume->GetLogicalVolume();
271 pLogical->SetSolid( pSolid );
272 pLogical->UpdateMaterial(pParam ->
273 ComputeMaterial(fBlockedReplicaNo,
274 fBlockedPhysicalVolume,
275 &parentTouchable));
276 }
277 break;
278 case kExternal:
279 G4Exception("G4ITNavigator1::LocateGlobalPointAndSetup()",
280 "GeomNav0001", FatalException,
281 "Not applicable for external volumes.");
282 break;
283 }
284 fEntering = false;
285 fBlockedPhysicalVolume = 0;
286 localPoint = fHistory.GetTopTransform().TransformPoint(globalPoint);
287 notKnownContained = false;
288 }
289 }
290 else
291 {
292 fBlockedPhysicalVolume = 0;
293 fEntering = false;
294 fEnteredDaughter = false; // Full Step was not taken, did not enter
295 fExiting = false;
296 fExitedMother = false; // Full Step was not taken, did not exit
297 }
298 }
299 //
300 // Search from top of history up through geometry until
301 // containing volume found:
302 // If on
303 // o OUTSIDE - Back up level, not/no longer exiting volumes
304 // o SURFACE and EXITING - Back up level, setting new blocking no.s
305 // else
306 // o containing volume found
307 //
308 G4int noLevelsExited=0 ;
309
310 while (notKnownContained)
311 {
313 {
314 targetSolid = fHistory.GetTopVolume()->GetLogicalVolume()->GetSolid();
315 localPoint = fHistory.GetTopTransform().TransformPoint(globalPoint);
316 insideCode = targetSolid->Inside(localPoint);
317#ifdef G4VERBOSE
318 if(( fVerbose == 1 ) && ( fCheck ))
319 {
320 G4String solidResponse = "-kInside-";
321 if (insideCode == kOutside)
322 solidResponse = "-kOutside-";
323 else if (insideCode == kSurface)
324 solidResponse = "-kSurface-";
325 G4cout << "*** G4ITNavigator1::LocateGlobalPointAndSetup(): ***" << G4endl
326 << " Invoked Inside() for solid: " << targetSolid->GetName()
327 << ". Solid replied: " << solidResponse << G4endl
328 << " For local point p: " << localPoint << G4endl;
329 }
330#endif
331 }
332 else
333 {
334 insideCode = freplicaNav.BackLocate(fHistory, globalPoint, localPoint,
335 fExiting, notKnownContained);
336 // !CARE! if notKnownContained returns false then the point is within
337 // the containing placement volume of the replica(s). If insidecode
338 // will result in the history being backed up one level, then the
339 // local point returned is the point in the system of this new level
340 }
341
342
343 if ( insideCode==kOutside )
344 {
345 noLevelsExited++;
346 if ( fHistory.GetDepth() )
347 {
348 fBlockedPhysicalVolume = fHistory.GetTopVolume();
349 fBlockedReplicaNo = fHistory.GetTopReplicaNo();
351 fExiting = false;
352
353 if( noLevelsExited > 1 )
354 {
355 // The first transformation was done by the sub-navigator
356 //
357 const G4RotationMatrix* mRot = fBlockedPhysicalVolume->GetRotation();
358 if( mRot )
359 {
360 fGrandMotherExitNormal *= (*mRot).inverse();
361 fChangedGrandMotherRefFrame= true;
362 }
363 }
364 }
365 else
366 {
367 fLastLocatedPointLocal = localPoint;
368 fLocatedOutsideWorld = true;
369 // No extra transformation for ExitNormal - is in frame of Top Volume
370 return 0; // Have exited world volume
371 }
372 }
373 else
374 if ( insideCode==kSurface )
375 {
376 G4bool isExiting = fExiting;
377 if( (!fExiting)&&considerDirection )
378 {
379 // Figure out whether we are exiting this level's volume
380 // by using the direction
381 //
382 G4bool directionExiting = false;
383 G4ThreeVector localDirection =
384 fHistory.GetTopTransform().TransformAxis(globalDirection);
385
386 // Make sure localPoint in correct reference frame
387 // ( Was it already correct ? How ? )
388 //
389 localPoint= fHistory.GetTopTransform().TransformPoint(globalPoint);
391 {
392 G4ThreeVector normal = targetSolid->SurfaceNormal(localPoint);
393 directionExiting = normal.dot(localDirection) > 0.0;
394 isExiting = isExiting || directionExiting;
395 }
396 }
397 if( isExiting )
398 {
399 noLevelsExited++;
400 if ( fHistory.GetDepth() )
401 {
402 fBlockedPhysicalVolume = fHistory.GetTopVolume();
403 fBlockedReplicaNo = fHistory.GetTopReplicaNo();
405 //
406 // Still on surface but exited volume not necessarily convex
407 //
408 fValidExitNormal = false;
409
410 if( noLevelsExited > 1 )
411 {
412 // The first transformation was done by the sub-navigator
413 //
414 const G4RotationMatrix* mRot=fBlockedPhysicalVolume->GetRotation();
415 if( mRot )
416 {
417 fGrandMotherExitNormal *= (*mRot).inverse();
418 fChangedGrandMotherRefFrame= true;
419 }
420 }
421 }
422 else
423 {
424 fLastLocatedPointLocal = localPoint;
425 fLocatedOutsideWorld = true;
426 // No extra transformation for ExitNormal, is in frame of Top Vol
427 return 0; // Have exited world volume
428 }
429 }
430 else
431 {
432 notKnownContained=false;
433 }
434 }
435 else
436 {
437 notKnownContained=false;
438 }
439 } // END while (notKnownContained)
440 //
441 // Search downwards until deepest containing volume found,
442 // blocking fBlockedPhysicalVolume/BlockedReplicaNum
443 //
444 // 3 Cases:
445 //
446 // o Parameterised daughters
447 // =>Must be one G4PVParameterised daughter & voxels
448 // o Positioned daughters & voxels
449 // o Positioned daughters & no voxels
450
451 noResult = true; // noResult should be renamed to
452 // something like enteredLevel, as that is its meaning.
453 do
454 {
455 // Determine `type' of current mother volume
456 //
457 targetPhysical = fHistory.GetTopVolume();
458 if (!targetPhysical) { break; }
459 targetLogical = targetPhysical->GetLogicalVolume();
460 switch( CharacteriseDaughters(targetLogical) )
461 {
462 case kNormal:
463 if ( targetLogical->GetVoxelHeader() ) // use optimised navigation
464 {
465 noResult = fvoxelNav.LevelLocate(fHistory,
466 fBlockedPhysicalVolume,
467 fBlockedReplicaNo,
468 globalPoint,
469 pGlobalDirection,
470 considerDirection,
471 localPoint);
472 }
473 else // do not use optimised navigation
474 {
475 noResult = fnormalNav.LevelLocate(fHistory,
476 fBlockedPhysicalVolume,
477 fBlockedReplicaNo,
478 globalPoint,
479 pGlobalDirection,
480 considerDirection,
481 localPoint);
482 }
483 break;
484 case kReplica:
485 noResult = freplicaNav.LevelLocate(fHistory,
486 fBlockedPhysicalVolume,
487 fBlockedReplicaNo,
488 globalPoint,
489 pGlobalDirection,
490 considerDirection,
491 localPoint);
492 break;
493 case kParameterised:
494 if( GetDaughtersRegularStructureId(targetLogical) != 1 )
495 {
496 noResult = fparamNav.LevelLocate(fHistory,
497 fBlockedPhysicalVolume,
498 fBlockedReplicaNo,
499 globalPoint,
500 pGlobalDirection,
501 considerDirection,
502 localPoint);
503 }
504 else // Regular structure
505 {
506 noResult = fregularNav.LevelLocate(fHistory,
507 fBlockedPhysicalVolume,
508 fBlockedReplicaNo,
509 globalPoint,
510 pGlobalDirection,
511 considerDirection,
512 localPoint);
513 }
514 break;
515 case kExternal:
516 G4Exception("G4ITNavigator1::LocateGlobalPointAndSetup()",
517 "GeomNav0001", FatalException,
518 "Not applicable for external volumes.");
519 break;
520 }
521
522 // LevelLocate returns true if it finds a daughter volume
523 // in which globalPoint is inside (or on the surface).
524
525 if ( noResult )
526 {
527 // Entering a daughter after ascending
528 //
529 // The blocked volume is no longer valid - it was for another level
530 //
531 fBlockedPhysicalVolume = 0;
532 fBlockedReplicaNo = -1;
533
534 // fEntering should be false -- else blockedVolume is assumed good.
535 // fEnteredDaughter is used for ExitNormal
536 //
537 fEntering = false;
538 fEnteredDaughter = true;
539
540 if( fExitedMother )
541 {
542 G4VPhysicalVolume* enteredPhysical = fHistory.GetTopVolume();
543 const G4RotationMatrix* mRot = enteredPhysical->GetRotation();
544 if( mRot )
545 {
546 fGrandMotherExitNormal *= (*mRot).inverse();
547 }
548 }
549
550#ifdef G4DEBUG_NAVIGATION
551 if( fVerbose > 2 )
552 {
553 G4VPhysicalVolume* enteredPhysical = fHistory.GetTopVolume();
554 G4cout << "*** G4ITNavigator1::LocateGlobalPointAndSetup() ***" << G4endl;
555 G4cout << " Entering volume: " << enteredPhysical->GetName()
556 << G4endl;
557 }
558#endif
559 }
560 } while (noResult);
561
562 fLastLocatedPointLocal = localPoint;
563
564#ifdef G4VERBOSE
565 if( fVerbose >= 4 )
566 {
567 G4long oldcoutPrec = G4cout.precision(8);
568 G4String curPhysVol_Name("None");
569 if (targetPhysical) { curPhysVol_Name = targetPhysical->GetName(); }
570 G4cout << " Return value = new volume = " << curPhysVol_Name << G4endl;
571 G4cout << " ----- Upon exiting:" << G4endl;
572 PrintState();
573 if( fVerbose == 5 )
574 {
575 G4cout << "Upon exiting LocateGlobalPointAndSetup():" << G4endl;
576 G4cout << " History = " << G4endl << fHistory << G4endl << G4endl;
577 }
578 G4cout.precision(oldcoutPrec);
579 }
580#endif
581
582 fLocatedOutsideWorld= false;
583
584 return targetPhysical;
585}
586
587// ********************************************************************
588// LocateGlobalPointWithinVolume
589//
590// -> the state information of this Navigator and its subNavigators
591// is updated in order to start the next step at pGlobalpoint
592// -> no check is performed whether pGlobalpoint is inside the
593// original volume (this must be the case).
594//
595// Note: a direction could be added to the arguments, to aid in future
596// optional checking (via the old code below, flagged by OLD_LOCATE).
597// [ This would be done only in verbose mode ]
598// ********************************************************************
599//
600void
602{
603 fLastLocatedPointLocal = ComputeLocalPoint(pGlobalpoint);
604 fLastTriedStepComputation= false;
605 fChangedGrandMotherRefFrame= false; // Frame for Exit Normal
606
607#ifdef G4DEBUG_NAVIGATION
608 if( fVerbose > 2 )
609 {
610 G4cout << "Entering LocateGlobalWithinVolume(): History = " << G4endl;
611 G4cout << fHistory << G4endl;
612 }
613#endif
614
615 // For the case of Voxel (or Parameterised) volume the respective
616 // Navigator must be messaged to update its voxel information etc
617
618 // Update the state of the Sub Navigators
619 // - in particular any voxel information they store/cache
620 //
621 G4VPhysicalVolume* motherPhysical = fHistory.GetTopVolume();
622 G4LogicalVolume* motherLogical = motherPhysical->GetLogicalVolume();
623 G4SmartVoxelHeader* pVoxelHeader = motherLogical->GetVoxelHeader();
624
626 {
627 switch( CharacteriseDaughters(motherLogical) )
628 {
629 case kNormal:
630 if ( pVoxelHeader )
631 {
632 fvoxelNav.VoxelLocate( pVoxelHeader, fLastLocatedPointLocal );
633 }
634 break;
635 case kParameterised:
636 if( GetDaughtersRegularStructureId(motherLogical) != 1 )
637 {
638 // Resets state & returns voxel node
639 //
640 fparamNav.ParamVoxelLocate( pVoxelHeader, fLastLocatedPointLocal );
641 }
642 break;
643 case kReplica:
644 G4Exception("G4ITNavigator1::LocateGlobalPointWithinVolume()",
645 "GeomNav0001", FatalException,
646 "Not applicable for replicated volumes.");
647 break;
648 case kExternal:
649 G4Exception("G4ITNavigator1::LocateGlobalPointWithinVolume()",
650 "GeomNav0001", FatalException,
651 "Not applicable for external volumes.");
652 break;
653 }
654 }
655
656 // Reset the state variables
657 // - which would have been affected
658 // by the 'equivalent' call to LocateGlobalPointAndSetup
659 // - who's values have been invalidated by the 'move'.
660 //
661 fBlockedPhysicalVolume = 0;
662 fBlockedReplicaNo = -1;
663 fEntering = false;
664 fEnteredDaughter = false; // Boundary not encountered, did not enter
665 fExiting = false;
666 fExitedMother = false; // Boundary not encountered, did not exit
667}
668
669// !>
671{
673 return fpSaveState;
674}
675
677{
678 fpSaveState = (G4SaveNavigatorState*) navState;
679 if(navState) RestoreSavedState();
680}
681
683{
684 fpSaveState = new G4SaveNavigatorState();
685 ResetState();
686}
687
688
689// ********************************************************************
690// SetSavedState
691//
692// Save the state, in case this is a parasitic call
693// Save fValidExitNormal, fExitNormal, fExiting, fEntering,
694// fBlockedPhysicalVolume, fBlockedReplicaNo, fLastStepWasZero;
695// ********************************************************************
696//
698{
699 // !>
700 // This check can be avoid if instead, at every first step of a track,
701 // the IT tracking uses NewNavigatorSate
702 // The normal tracking would just call once NewNavigatorState() before tracking
703
704// if(fpSaveState == 0)
705// fpSaveState = new G4SaveNavigatorState;
706 // <!
707
708 // fSaveExitNormal = fExitNormal;
709 fpSaveState->sExitNormal = fExitNormal;
710 fpSaveState->sValidExitNormal = fValidExitNormal;
711 fpSaveState->sExiting = fExiting;
712 fpSaveState->sEntering = fEntering;
713
714 fpSaveState->spBlockedPhysicalVolume = fBlockedPhysicalVolume;
715 fpSaveState->sBlockedReplicaNo = fBlockedReplicaNo,
716
717 fpSaveState->sLastStepWasZero = fLastStepWasZero;
718
719 // !>
720 fpSaveState->sPreviousSftOrigin = fPreviousSftOrigin;
721 fpSaveState->sPreviousSafety = fPreviousSafety;
722 fpSaveState->sNumberZeroSteps = fNumberZeroSteps;
723 fpSaveState->sLocatedOnEdge = fLocatedOnEdge;
724 fpSaveState->sWasLimitedByGeometry= fWasLimitedByGeometry;
725 fpSaveState->sPushed=fPushed;
726 fpSaveState->sNumberZeroSteps=fNumberZeroSteps;
727 fpSaveState->sEnteredDaughter = fEnteredDaughter;
728 fpSaveState->sExitedMother = fExitedMother;
729
730 fpSaveState->sLastLocatedPointLocal = fLastLocatedPointLocal;
731 fpSaveState->sLocatedOutsideWorld = fLocatedOutsideWorld;
732 // <!
733}
734
735// ********************************************************************
736// RestoreSavedState
737//
738// Restore the state (in Compute Step), in case this is a parasitic call
739// ********************************************************************
740//
742{
743 fExitNormal = fpSaveState->sExitNormal;
744 fValidExitNormal = fpSaveState->sValidExitNormal;
745 fExiting = fpSaveState->sExiting;
746 fEntering = fpSaveState->sEntering;
747
748 fBlockedPhysicalVolume = fpSaveState->spBlockedPhysicalVolume;
749 fBlockedReplicaNo = fpSaveState->sBlockedReplicaNo,
750
751 fLastStepWasZero = fpSaveState->sLastStepWasZero;
752
753 // !>
754 fPreviousSftOrigin = fpSaveState->sPreviousSftOrigin ;
755 fPreviousSafety = fpSaveState->sPreviousSafety ;
756 fNumberZeroSteps = fpSaveState->sNumberZeroSteps ;
757 fLocatedOnEdge = fpSaveState->sLocatedOnEdge ;
758 fWasLimitedByGeometry = fpSaveState->sWasLimitedByGeometry;
759 fPushed = fpSaveState->sPushed;
760 fNumberZeroSteps = fpSaveState->sNumberZeroSteps;
761 fEnteredDaughter= fpSaveState->sEnteredDaughter ;
762 fExitedMother = fpSaveState->sExitedMother ;
763
764 fLastLocatedPointLocal = fpSaveState->sLastLocatedPointLocal ;
765 fLocatedOutsideWorld = fpSaveState->sLocatedOutsideWorld;
766 // <!
767}
768// <!
769
770// ********************************************************************
771// ComputeStep
772//
773// Computes the next geometric Step: intersections with current
774// mother and `daughter' volumes.
775//
776// NOTE:
777//
778// Flags on entry:
779// --------------
780// fValidExitNormal - Normal of exited volume is valid (convex, not a
781// coincident boundary)
782// fExitNormal - Surface normal of exited volume
783// fExiting - True if have exited solid
784//
785// fBlockedPhysicalVolume - Ptr to exited volume (or 0)
786// fBlockedReplicaNo - Replication no of exited volume
787// fLastStepWasZero - True if last Step size was zero.
788//
789// Flags on exit:
790// -------------
791// fValidExitNormal - True if surface normal of exited volume is valid
792// fExitNormal - Surface normal of exited volume rotated to mothers
793// reference system
794// fExiting - True if exiting mother
795// fEntering - True if entering `daughter' volume (or replica)
796// fBlockedPhysicalVolume - Ptr to candidate (entered) volume
797// fBlockedReplicaNo - Replication no of candidate (entered) volume
798// fLastStepWasZero - True if this Step size was zero.
799// ********************************************************************
800//
802 const G4ThreeVector &pDirection,
803 const G4double pCurrentProposedStepLength,
804 G4double &pNewSafety)
805{
806 G4ThreeVector localDirection = ComputeLocalAxis(pDirection);
807 G4double Step = kInfinity;
808 G4VPhysicalVolume *motherPhysical = fHistory.GetTopVolume();
809 G4LogicalVolume *motherLogical = motherPhysical->GetLogicalVolume();
810
811 // All state relating to exiting normals must be reset
812 //
813 fExitNormalGlobalFrame= G4ThreeVector( 0., 0., 0.);
814 // Reset value - to erase its memory
815 fChangedGrandMotherRefFrame= false;
816 // Reset - used for local exit normal
817 fGrandMotherExitNormal= G4ThreeVector( 0., 0., 0.);
818 fCalculatedExitNormal = false;
819 // Reset for new step
820
821 static G4ThreadLocal G4int sNavCScalls=0;
822 sNavCScalls++;
823
824 fLastTriedStepComputation= true;
825
826#ifdef G4VERBOSE
827 if( fVerbose > 0 )
828 {
829 G4cout << "*** G4ITNavigator1::ComputeStep: ***" << G4endl;
830 G4cout << " Volume = " << motherPhysical->GetName()
831 << " - Proposed step length = " << pCurrentProposedStepLength
832 << G4endl;
833#ifdef G4DEBUG_NAVIGATION
834 if( fVerbose >= 2 )
835 {
836 G4cout << " Called with the arguments: " << G4endl
837 << " Globalpoint = " << std::setw(25) << pGlobalpoint << G4endl
838 << " Direction = " << std::setw(25) << pDirection << G4endl;
839 if( fVerbose >= 4 )
840 {
841 G4cout << " ---- Upon entering : State" << G4endl;
842 PrintState();
843 }
844 }
845#endif
846 }
847#endif
848
849 G4ThreeVector newLocalPoint = ComputeLocalPoint(pGlobalpoint);
850 if( newLocalPoint != fLastLocatedPointLocal )
851 {
852 // Check whether the relocation is within safety
853 //
854 G4ThreeVector oldLocalPoint = fLastLocatedPointLocal;
855 G4double moveLenSq = (newLocalPoint-oldLocalPoint).mag2();
856
857 if ( moveLenSq >= kCarTolerance*kCarTolerance )
858 {
859#ifdef G4VERBOSE
860 ComputeStepLog(pGlobalpoint, moveLenSq);
861#endif
862 // Relocate the point within the same volume
863 //
864 LocateGlobalPointWithinVolume( pGlobalpoint );
865 fLastTriedStepComputation= true; // Ensure that this is set again !!
866 }
867 }
869 {
870 switch( CharacteriseDaughters(motherLogical) )
871 {
872 case kNormal:
873 if ( motherLogical->GetVoxelHeader() )
874 {
875 Step = fvoxelNav.ComputeStep(fLastLocatedPointLocal,
876 localDirection,
877 pCurrentProposedStepLength,
878 pNewSafety,
879 fHistory,
880 fValidExitNormal,
881 fExitNormal,
882 fExiting,
883 fEntering,
884 &fBlockedPhysicalVolume,
885 fBlockedReplicaNo);
886
887 }
888 else
889 {
890 if( motherPhysical->GetRegularStructureId() == 0 )
891 {
892 Step = fnormalNav.ComputeStep(fLastLocatedPointLocal,
893 localDirection,
894 pCurrentProposedStepLength,
895 pNewSafety,
896 fHistory,
897 fValidExitNormal,
898 fExitNormal,
899 fExiting,
900 fEntering,
901 &fBlockedPhysicalVolume,
902 fBlockedReplicaNo);
903 }
904 else // Regular (non-voxelised) structure
905 {
906 LocateGlobalPointAndSetup( pGlobalpoint, &pDirection, true, true );
907 fLastTriedStepComputation= true; // Ensure that this is set again !!
908 //
909 // if physical process limits the step, the voxel will not be the
910 // one given by ComputeStepSkippingEqualMaterials() and the local
911 // point will be wrongly calculated.
912
913 // There is a problem: when msc limits the step and the point is
914 // assigned wrongly to phantom in previous step (while it is out
915 // of the container volume). Then LocateGlobalPointAndSetup() has
916 // reset the history topvolume to world.
917 //
919 {
920 G4Exception("G4ITNavigator1::ComputeStep()",
921 "GeomNav1001", JustWarning,
922 "Point is relocated in voxels, while it should be outside!");
923 Step = fnormalNav.ComputeStep(fLastLocatedPointLocal,
924 localDirection,
925 pCurrentProposedStepLength,
926 pNewSafety,
927 fHistory,
928 fValidExitNormal,
929 fExitNormal,
930 fExiting,
931 fEntering,
932 &fBlockedPhysicalVolume,
933 fBlockedReplicaNo);
934 }
935 else
936 {
937 Step = fregularNav.
938 ComputeStepSkippingEqualMaterials(fLastLocatedPointLocal,
939 localDirection,
940 pCurrentProposedStepLength,
941 pNewSafety,
942 fHistory,
943 fValidExitNormal,
944 fExitNormal,
945 fExiting,
946 fEntering,
947 &fBlockedPhysicalVolume,
948 fBlockedReplicaNo,
949 motherPhysical);
950 }
951 }
952 }
953 break;
954 case kParameterised:
955 if( GetDaughtersRegularStructureId(motherLogical) != 1 )
956 {
957 Step = fparamNav.ComputeStep(fLastLocatedPointLocal,
958 localDirection,
959 pCurrentProposedStepLength,
960 pNewSafety,
961 fHistory,
962 fValidExitNormal,
963 fExitNormal,
964 fExiting,
965 fEntering,
966 &fBlockedPhysicalVolume,
967 fBlockedReplicaNo);
968 }
969 else // Regular structure
970 {
971 Step = fregularNav.ComputeStep(fLastLocatedPointLocal,
972 localDirection,
973 pCurrentProposedStepLength,
974 pNewSafety,
975 fHistory,
976 fValidExitNormal,
977 fExitNormal,
978 fExiting,
979 fEntering,
980 &fBlockedPhysicalVolume,
981 fBlockedReplicaNo);
982 }
983 break;
984 case kReplica:
985 G4Exception("G4ITNavigator1::ComputeStep()", "GeomNav0001",
986 FatalException, "Not applicable for replicated volumes.");
987 break;
988 case kExternal:
989 G4Exception("G4ITNavigator1::ComputeStep()", "GeomNav0001",
990 FatalException, "Not applicable for external volumes.");
991 break;
992 }
993 }
994 else
995 {
996 // In the case of a replica, it must handle the exiting
997 // edge/corner problem by itself
998 //
999 G4bool exitingReplica = fExitedMother;
1000 G4bool calculatedExitNormal= false;
1001
1002 Step = freplicaNav.ComputeStep(pGlobalpoint,
1003 pDirection,
1004 fLastLocatedPointLocal,
1005 localDirection,
1006 pCurrentProposedStepLength,
1007 pNewSafety,
1008 fHistory,
1009 fValidExitNormal,
1010 calculatedExitNormal,
1011 fExitNormal,
1012 exitingReplica,
1013 fEntering,
1014 &fBlockedPhysicalVolume,
1015 fBlockedReplicaNo);
1016 fExiting= exitingReplica;
1017 fCalculatedExitNormal= calculatedExitNormal;
1018 }
1019
1020 // Remember last safety origin & value.
1021 //
1022 fPreviousSftOrigin = pGlobalpoint;
1023 fPreviousSafety = pNewSafety;
1024
1025 // Count zero steps - one can occur due to changing momentum at a boundary
1026 // - one, two (or a few) can occur at common edges between
1027 // volumes
1028 // - more than two is likely a problem in the geometry
1029 // description or the Navigation
1030
1031 // Rule of thumb: likely at an Edge if two consecutive steps are zero,
1032 // because at least two candidate volumes must have been
1033 // checked
1034 //
1035 fLocatedOnEdge = fLastStepWasZero && (Step==0.0);
1036 fLastStepWasZero = (Step==0.0);
1037 if (fPushed) { fPushed = fLastStepWasZero; }
1038
1039 // Handle large number of consecutive zero steps
1040 //
1041 if ( fLastStepWasZero )
1042 {
1043 fNumberZeroSteps++;
1044#ifdef G4DEBUG_NAVIGATION
1045 if( fNumberZeroSteps > 1 )
1046 {
1047 G4cout << "G4ITNavigator1::ComputeStep(): another zero step, # "
1048 << fNumberZeroSteps
1049 << " at " << pGlobalpoint
1050 << " in volume " << motherPhysical->GetName()
1051 << " nav-comp-step calls # " << sNavCScalls
1052 << G4endl;
1053 }
1054#endif
1055 if( fNumberZeroSteps > fActionThreshold_NoZeroSteps-1 )
1056 {
1057 // Act to recover this stuck track. Pushing it along direction
1058 //
1059 Step += 100*kCarTolerance;
1060#ifdef G4VERBOSE
1061 if ((!fPushed) && (fWarnPush))
1062 {
1063 std::ostringstream message;
1064 message << "Track stuck or not moving." << G4endl
1065 << " Track stuck, not moving for "
1066 << fNumberZeroSteps << " steps" << G4endl
1067 << " in volume -" << motherPhysical->GetName()
1068 << "- at point " << pGlobalpoint << G4endl
1069 << " direction: " << pDirection << "." << G4endl
1070 << " Potential geometry or navigation problem !"
1071 << G4endl
1072 << " Trying pushing it of " << Step << " mm ...";
1073 G4Exception("G4ITNavigator1::ComputeStep()", "GeomNav1002",
1074 JustWarning, message, "Potential overlap in geometry!");
1075 }
1076#endif
1077 fPushed = true;
1078 }
1079 if( fNumberZeroSteps > fAbandonThreshold_NoZeroSteps-1 )
1080 {
1081 // Must kill this stuck track
1082 //
1083 std::ostringstream message;
1084 message << "Stuck Track: potential geometry or navigation problem."
1085 << G4endl
1086 << " Track stuck, not moving for "
1087 << fNumberZeroSteps << " steps" << G4endl
1088 << " in volume -" << motherPhysical->GetName()
1089 << "- at point " << pGlobalpoint << G4endl
1090 << " direction: " << pDirection << ".";
1091 motherPhysical->CheckOverlaps(5000, false);
1092 G4Exception("G4ITNavigator1::ComputeStep()", "GeomNav0003",
1093 EventMustBeAborted, message);
1094 }
1095 }
1096 else
1097 {
1098 if (!fPushed) fNumberZeroSteps = 0;
1099 }
1100
1101 fEnteredDaughter = fEntering; // I expect to enter a volume in this Step
1102 fExitedMother = fExiting;
1103
1104 fStepEndPoint = pGlobalpoint + Step * pDirection;
1105 fLastStepEndPointLocal = fLastLocatedPointLocal + Step * localDirection;
1106
1107 if( fExiting )
1108 {
1109#ifdef G4DEBUG_NAVIGATION
1110 if( fVerbose > 2 )
1111 {
1112 G4cout << " At G4Nav CompStep End - if(exiting) - fExiting= " << fExiting
1113 << " fValidExitNormal = " << fValidExitNormal << G4endl;
1114 G4cout << " fExitNormal= " << fExitNormal << G4endl;
1115 }
1116#endif
1117
1118 if(fValidExitNormal || fCalculatedExitNormal)
1119 {
1121 {
1122 // Convention: fExitNormal is in the 'grand-mother' coordinate system
1123 //
1124 fGrandMotherExitNormal= fExitNormal;
1125 fCalculatedExitNormal= true;
1126 }
1127 else
1128 {
1129 fGrandMotherExitNormal = fExitNormal;
1130 }
1131 }
1132 else
1133 {
1134 // We must calculate the normal anyway (in order to have it if requested)
1135 //
1136 G4ThreeVector finalLocalPoint =
1137 fLastLocatedPointLocal + localDirection*Step;
1138
1140 {
1141 // Find normal in the 'mother' coordinate system
1142 //
1143 G4ThreeVector exitNormalMotherFrame=
1144 motherLogical->GetSolid()->SurfaceNormal(finalLocalPoint);
1145
1146 // Transform it to the 'grand-mother' coordinate system
1147 //
1148 const G4RotationMatrix* mRot = motherPhysical->GetRotation();
1149 if( mRot )
1150 {
1151 fChangedGrandMotherRefFrame= true;
1152 fGrandMotherExitNormal = (*mRot).inverse() * exitNormalMotherFrame;
1153 }
1154 else
1155 {
1156 fGrandMotherExitNormal = exitNormalMotherFrame;
1157 }
1158
1159 // Do not set fValidExitNormal -- this signifies
1160 // that the solid is convex!
1161 //
1162 fCalculatedExitNormal= true;
1163 }
1164 else
1165 {
1166 fCalculatedExitNormal = false;
1167 //
1168 // Nothing can be done at this stage currently - to solve this
1169 // Replica Navigation must have calculated the normal for this case
1170 // already.
1171 // Cases: mother is not convex, and exit is at previous replica level
1172
1173#ifdef G4DEBUG_NAVIGATION
1175
1176 desc << "Problem in ComputeStep: Replica Navigation did not provide"
1177 << " valid exit Normal. " << G4endl;
1178 desc << " Do not know how calculate it in this case." << G4endl;
1179 desc << " Location = " << finalLocalPoint << G4endl;
1180 desc << " Volume name = " << motherPhysical->GetName()
1181 << " copy/replica No = " << motherPhysical->GetCopyNo() << G4endl;
1182 G4Exception("G4ITNavigator1::ComputeStep()", "GeomNav0003",
1183 JustWarning, desc, "Normal not available for exiting.");
1184#endif
1185 }
1186 }
1187
1188 // Now transform it to the global reference frame !!
1189 //
1190 if( fValidExitNormal || fCalculatedExitNormal )
1191 {
1192 G4int depth = (G4int)fHistory.GetDepth();
1193 if( depth > 0 )
1194 {
1195 G4AffineTransform GrandMotherToGlobalTransf =
1196 fHistory.GetTransform(depth-1).Inverse();
1197 fExitNormalGlobalFrame =
1198 GrandMotherToGlobalTransf.TransformAxis( fGrandMotherExitNormal );
1199 }
1200 else
1201 {
1202 fExitNormalGlobalFrame= fGrandMotherExitNormal;
1203 }
1204 }
1205 else
1206 {
1207 fExitNormalGlobalFrame= G4ThreeVector( 0., 0., 0.);
1208 }
1209 }
1210 fStepEndPoint= pGlobalpoint+Step*pDirection;
1211
1212 if( (Step == pCurrentProposedStepLength) && (!fExiting) && (!fEntering) )
1213 {
1214 // This if Step is not really limited by the geometry.
1215 // The Navigator is obliged to return "infinity"
1216 //
1217 Step = kInfinity;
1218 }
1219
1220#ifdef G4VERBOSE
1221 if( fVerbose > 1 )
1222 {
1223 if( fVerbose >= 4 )
1224 {
1225 G4cout << " ----- Upon exiting :" << G4endl;
1226 PrintState();
1227 }
1228 G4cout << " Returned step= " << Step;
1229 if( fVerbose > 5 ) G4cout << G4endl;
1230 if( Step == kInfinity )
1231 {
1232 G4cout << " Requested step= " << pCurrentProposedStepLength ;
1233 if( fVerbose > 5) G4cout << G4endl;
1234 }
1235 G4cout << " Safety = " << pNewSafety << G4endl;
1236 }
1237#endif
1238
1239 return Step;
1240}
1241
1242// ********************************************************************
1243// CheckNextStep
1244//
1245// Compute the step without altering the navigator state
1246// ********************************************************************
1247//
1249 const G4ThreeVector& pDirection,
1250 const G4double pCurrentProposedStepLength,
1251 G4double& pNewSafety)
1252{
1253 G4double step;
1254
1255 // Save the state, for this parasitic call
1256 //
1257 SetSavedState();
1258
1259 step = ComputeStep ( pGlobalpoint,
1260 pDirection,
1261 pCurrentProposedStepLength,
1262 pNewSafety );
1263
1264 // If a parasitic call, then attempt to restore the key parts of the state
1265 //
1267
1268 return step;
1269}
1270
1271// ********************************************************************
1272// ResetState
1273//
1274// Resets stack and minimum of navigator state `machine'
1275// ********************************************************************
1276//
1278{
1279 fWasLimitedByGeometry = false;
1280 fEntering = false;
1281 fExiting = false;
1282 fLocatedOnEdge = false;
1283 fLastStepWasZero = false;
1284 fEnteredDaughter = false;
1285 fExitedMother = false;
1286 fPushed = false;
1287
1288 fValidExitNormal = false;
1289 fChangedGrandMotherRefFrame= false;
1290 fCalculatedExitNormal = false;
1291
1292 fExitNormal = G4ThreeVector(0,0,0);
1293 fGrandMotherExitNormal = G4ThreeVector(0,0,0);
1294 fExitNormalGlobalFrame = G4ThreeVector(0,0,0);
1295
1296 fPreviousSftOrigin = G4ThreeVector(0,0,0);
1297 fPreviousSafety = 0.0;
1298
1299 fNumberZeroSteps = 0;
1300
1301 fBlockedPhysicalVolume = 0;
1302 fBlockedReplicaNo = -1;
1303
1304 fLastLocatedPointLocal = G4ThreeVector( kInfinity, -kInfinity, 0.0 );
1305 fLocatedOutsideWorld = false;
1306}
1307
1308// ********************************************************************
1309// SetupHierarchy
1310//
1311// Renavigates & resets hierarchy described by current history
1312// o Reset volumes
1313// o Recompute transforms and/or solids of replicated/parameterised volumes
1314// ********************************************************************
1315//
1317{
1318 G4int i;
1319 const G4int cdepth = (G4int)fHistory.GetDepth();
1320 G4VPhysicalVolume *current;
1321 G4VSolid *pSolid;
1322 G4VPVParameterisation *pParam;
1323
1324 for ( i=1; i<=cdepth; i++ )
1325 {
1326 current = fHistory.GetVolume(i);
1327 switch ( fHistory.GetVolumeType(i) )
1328 {
1329 case kNormal:
1330 break;
1331 case kReplica:
1332 freplicaNav.ComputeTransformation(fHistory.GetReplicaNo(i), current);
1333 break;
1334 case kParameterised: {
1335 G4int replicaNo;
1336 pParam = current->GetParameterisation();
1337 replicaNo = fHistory.GetReplicaNo(i);
1338 pSolid = pParam->ComputeSolid(replicaNo, current);
1339
1340 // Set up dimensions & transform in solid/physical volume
1341 //
1342 pSolid->ComputeDimensions(pParam, replicaNo, current);
1343 pParam->ComputeTransformation(replicaNo, current);
1344
1345 G4TouchableHistory touchable( fHistory );
1346 touchable.MoveUpHistory(); // move up to the parent level
1347
1348 // Set up the correct solid and material in Logical Volume
1349 //
1350 G4LogicalVolume *pLogical = current->GetLogicalVolume();
1351 pLogical->SetSolid( pSolid );
1352 pLogical->UpdateMaterial( pParam ->
1353 ComputeMaterial(replicaNo, current, &touchable) );
1354 break;
1355 }
1356 case kExternal:
1357 G4Exception("G4ITNavigator1::SetupHierarchy()",
1358 "GeomNav0001", FatalException,
1359 "Not applicable for external volumes.");
1360 break;
1361 }
1362 }
1363}
1364
1365// ********************************************************************
1366// GetLocalExitNormal
1367//
1368// Obtains the Normal vector to a surface (in local coordinates)
1369// pointing out of previous volume and into current volume
1370// ********************************************************************
1371//
1373{
1374 G4ThreeVector ExitNormal(0.,0.,0.);
1375 G4VSolid *currentSolid=0;
1376 G4LogicalVolume *candidateLogical;
1377 if ( fLastTriedStepComputation )
1378 {
1379 // use fLastLocatedPointLocal and next candidate volume
1380 //
1381 G4ThreeVector nextSolidExitNormal(0.,0.,0.);
1382
1383 if( fEntering && (fBlockedPhysicalVolume!=0) )
1384 {
1385 candidateLogical= fBlockedPhysicalVolume->GetLogicalVolume();
1386 if( candidateLogical )
1387 {
1388 // fLastStepEndPointLocal is in the coordinates of the mother
1389 // we need it in the daughter's coordinate system.
1390
1391 // The following code should also work in case of Replica
1392 {
1393 // First transform fLastLocatedPointLocal to the new daughter
1394 // coordinates
1395 //
1396 G4AffineTransform MotherToDaughterTransform=
1397 GetMotherToDaughterTransform( fBlockedPhysicalVolume,
1398 fBlockedReplicaNo,
1399 VolumeType(fBlockedPhysicalVolume) );
1400 G4ThreeVector daughterPointOwnLocal=
1401 MotherToDaughterTransform.TransformPoint( fLastStepEndPointLocal );
1402
1403 // OK if it is a parameterised volume
1404 //
1405 EInside inSideIt;
1406 G4bool onSurface;
1407 G4double safety= -1.0;
1408 currentSolid= candidateLogical->GetSolid();
1409 inSideIt = currentSolid->Inside(daughterPointOwnLocal);
1410 onSurface = (inSideIt == kSurface);
1411 if( ! onSurface )
1412 {
1413 if( inSideIt == kOutside )
1414 {
1415 safety = (currentSolid->DistanceToIn(daughterPointOwnLocal));
1416 onSurface = safety < 100.0 * kCarTolerance;
1417 }
1418 else if (inSideIt == kInside )
1419 {
1420 safety = (currentSolid->DistanceToOut(daughterPointOwnLocal));
1421 onSurface = safety < 100.0 * kCarTolerance;
1422 }
1423 }
1424
1425 if( onSurface )
1426 {
1427 nextSolidExitNormal =
1428 currentSolid->SurfaceNormal(daughterPointOwnLocal);
1429
1430 // Entering the solid ==> opposite
1431 //
1432 ExitNormal = -nextSolidExitNormal;
1433 fCalculatedExitNormal= true;
1434 }
1435 else
1436 {
1437#ifdef G4VERBOSE
1438 if(( fVerbose == 1 ) && ( fCheck ))
1439 {
1440 std::ostringstream message;
1441 message << "Point not on surface ! " << G4endl
1442 << " Point = "
1443 << daughterPointOwnLocal << G4endl
1444 << " Physical volume = "
1445 << fBlockedPhysicalVolume->GetName() << G4endl
1446 << " Logical volume = "
1447 << candidateLogical->GetName() << G4endl
1448 << " Solid = " << currentSolid->GetName()
1449 << " Type = "
1450 << currentSolid->GetEntityType() << G4endl
1451 << *currentSolid << G4endl;
1452 if( inSideIt == kOutside )
1453 {
1454 message << "Point is Outside. " << G4endl
1455 << " Safety (from outside) = " << safety << G4endl;
1456 }
1457 else // if( inSideIt == kInside )
1458 {
1459 message << "Point is Inside. " << G4endl
1460 << " Safety (from inside) = " << safety << G4endl;
1461 }
1462 G4Exception("G4ITNavigator1::GetLocalExitNormal()", "GeomNav1001",
1463 JustWarning, message);
1464 }
1465#endif
1466 }
1467 *valid = onSurface; // was =true;
1468 }
1469 }
1470 }
1471 else if ( fExiting )
1472 {
1473 ExitNormal = fGrandMotherExitNormal;
1474 *valid = true;
1475 fCalculatedExitNormal= true; // Should be true already
1476 }
1477 else // i.e. ( fBlockedPhysicalVolume == 0 )
1478 {
1479 *valid = false;
1480 G4Exception("G4ITNavigator1::GetLocalExitNormal()",
1481 "GeomNav0003", JustWarning,
1482 "Incorrect call to GetLocalSurfaceNormal." );
1483 }
1484 }
1485 else // ( ! fLastTriedStepComputation ) ie. last call was to Locate
1486 {
1487 if ( EnteredDaughterVolume() )
1488 {
1489 G4VSolid* daughterSolid =fHistory.GetTopVolume()->GetLogicalVolume()
1490 ->GetSolid();
1491 ExitNormal= -(daughterSolid->SurfaceNormal(fLastLocatedPointLocal));
1492 if( std::fabs(ExitNormal.mag2()-1.0 ) > CLHEP::perMillion )
1493 {
1495 desc << " Parameters of solid: " << *daughterSolid
1496 << " Point for surface = " << fLastLocatedPointLocal << std::endl;
1497 G4Exception("G4ITNavigator1::GetLocalExitNormal()",
1498 "GeomNav0003", FatalException, desc,
1499 "Surface Normal returned by Solid is not a Unit Vector." );
1500 }
1501 fCalculatedExitNormal= true;
1502 *valid = true;
1503 }
1504 else
1505 {
1506 if( fExitedMother )
1507 {
1508 ExitNormal = fGrandMotherExitNormal;
1509 *valid = true;
1510 fCalculatedExitNormal= true;
1511 }
1512 else // We are not at a boundary. ExitNormal remains (0,0,0)
1513 {
1514 *valid = false;
1515 fCalculatedExitNormal= false;
1516 G4ExceptionDescription message;
1517 message << "Function called when *NOT* at a Boundary." << G4endl;
1518 G4Exception("G4ITNavigator1::GetLocalExitNormal()",
1519 "GeomNav0003", JustWarning, message);
1520 }
1521 }
1522 }
1523 return ExitNormal;
1524}
1525
1526// ********************************************************************
1527// GetMotherToDaughterTransform
1528//
1529// Obtains the mother to daughter affine transformation
1530// ********************************************************************
1531//
1534 G4int enteringReplicaNo,
1535 EVolume enteringVolumeType )
1536{
1537 switch (enteringVolumeType)
1538 {
1539 case kNormal: // Nothing is needed to prepare the transformation
1540 break; // It is stored already in the physical volume (placement)
1541 case kReplica: // Sets the transform in the Replica - tbc
1542 G4Exception("G4ITNavigator1::GetMotherToDaughterTransform()",
1543 "GeomNav0001", FatalException,
1544 "Method NOT Implemented yet for replica volumes.");
1545 break;
1546 case kParameterised:
1547 if( pEnteringPhysVol->GetRegularStructureId() == 0 )
1548 {
1549 G4VPVParameterisation *pParam =
1550 pEnteringPhysVol->GetParameterisation();
1551 G4VSolid* pSolid =
1552 pParam->ComputeSolid(enteringReplicaNo, pEnteringPhysVol);
1553 pSolid->ComputeDimensions(pParam, enteringReplicaNo, pEnteringPhysVol);
1554
1555 // Sets the transform in the Parameterisation
1556 //
1557 pParam->ComputeTransformation(enteringReplicaNo, pEnteringPhysVol);
1558
1559 // Set the correct solid and material in Logical Volume
1560 //
1561 G4LogicalVolume* pLogical = pEnteringPhysVol->GetLogicalVolume();
1562 pLogical->SetSolid( pSolid );
1563 }
1564 break;
1565 case kExternal:
1566 G4Exception("G4ITNavigator1::GetMotherToDaughterTransform()",
1567 "GeomNav0001", FatalException,
1568 "Not applicable for external volumes.");
1569 break;
1570 }
1571 return G4AffineTransform(pEnteringPhysVol->GetRotation(),
1572 pEnteringPhysVol->GetTranslation()).Invert();
1573}
1574
1575// ********************************************************************
1576// GetLocalExitNormalAndCheck
1577//
1578// Obtains the Normal vector to a surface (in local coordinates)
1579// pointing out of previous volume and into current volume, and
1580// checks the current point against expected 'local' value.
1581// ********************************************************************
1582//
1585#ifdef G4DEBUG_NAVIGATION
1586 const G4ThreeVector& ExpectedBoundaryPointGlobal,
1587#else
1588 const G4ThreeVector&,
1589#endif
1590 G4bool* pValid)
1591{
1592#ifdef G4DEBUG_NAVIGATION
1593 // Check Current point against expected 'local' value
1594 //
1595 if ( fLastTriedStepComputation )
1596 {
1597 G4ThreeVector ExpectedBoundaryPointLocal;
1598
1599 const G4AffineTransform& GlobalToLocal= GetGlobalToLocalTransform();
1600 ExpectedBoundaryPointLocal =
1601 GlobalToLocal.TransformPoint( ExpectedBoundaryPointGlobal );
1602
1603 // Add here: Comparison against expected position,
1604 // i.e. the endpoint of ComputeStep
1605 }
1606#endif
1607
1608 return GetLocalExitNormal( pValid);
1609}
1610
1611// ********************************************************************
1612// GetGlobalExitNormal
1613//
1614// Obtains the Normal vector to a surface (in global coordinates)
1615// pointing out of previous volume and into current volume
1616// ********************************************************************
1617//
1620 G4bool* pNormalCalculated)
1621{
1622 G4bool validNormal;
1623 G4ThreeVector localNormal, globalNormal;
1624
1625 if( fLastTriedStepComputation && fExiting )
1626 {
1627 // This was computed in ComputeStep -- and only on arrival at boundary
1628 //
1629 globalNormal = fExitNormalGlobalFrame;
1630 *pNormalCalculated = true; // ComputeStep always computes it if Exiting
1631 // (fExiting==true)
1632 }
1633 else
1634 {
1635 localNormal = GetLocalExitNormalAndCheck(IntersectPointGlobal,&validNormal);
1636 *pNormalCalculated = fCalculatedExitNormal;
1637
1638#ifdef G4DEBUG_NAVIGATION
1639 if( (!validNormal) && !fCalculatedExitNormal)
1640 {
1642 edN << " Calculated = " << fCalculatedExitNormal << G4endl;
1643 edN << " Entering= " << fEntering << G4endl;
1644 G4int oldVerbose= this->GetVerboseLevel();
1645 this->SetVerboseLevel(4);
1646 edN << " State of Navigator: " << G4endl;
1647 edN << *this << G4endl;
1648 this->SetVerboseLevel( oldVerbose );
1649
1650 G4Exception("G4ITNavigator1::GetGlobalExitNormal()",
1651 "GeomNav0003", JustWarning, edN,
1652 "LocalExitNormalAndCheck() did not calculate Normal.");
1653 }
1654#endif
1655
1656 G4double localMag2= localNormal.mag2();
1657 if( validNormal && (std::fabs(localMag2-1.0)) > CLHEP::perMillion )
1658 {
1660
1661 edN << "G4ITNavigator1::GetGlobalExitNormal: "
1662 << " Using Local Normal - from call to GetLocalExitNormalAndCheck. "
1663 << G4endl
1664 << " Local Exit Normal = " << localNormal << " || = "
1665 << std::sqrt(localMag2) << G4endl
1666 << " Global Exit Normal = " << globalNormal << " || = "
1667 << globalNormal.mag() << G4endl;
1668 edN << " Calculated It = " << fCalculatedExitNormal << G4endl;
1669
1670 G4Exception("G4ITNavigator1::GetGlobalExitNormal()",
1671 "GeomNav0003",JustWarning, edN,
1672 "Value obtained from new local *solid* is incorrect.");
1673 localNormal = localNormal.unit(); // Should we correct it ??
1674 }
1676 globalNormal = localToGlobal.TransformAxis( localNormal );
1677 }
1678
1679#ifdef G4DEBUG_NAVIGATION
1680 // Temporary extra checks
1681 if( fLastTriedStepComputation && fExiting)
1682 {
1683 localNormal = GetLocalExitNormalAndCheck( IntersectPointGlobal, &validNormal);
1684 *pNormalCalculated = fCalculatedExitNormal;
1685
1687 globalNormal = localToGlobal.TransformAxis( localNormal );
1688
1689 // Check the value computed against fExitNormalGlobalFrame
1690 G4ThreeVector diffNorm = globalNormal - fExitNormalGlobalFrame;
1691 if( diffNorm.mag2() > perMillion*CLHEP::perMillion)
1692 {
1694 edDfn << "Found difference in normals in case of exiting mother "
1695 << "- when Get is called after ComputingStep " << G4endl;
1696 edDfn << " Magnitude of diff = " << diffNorm.mag() << G4endl;
1697 edDfn << " Normal stored (Global) = " << fExitNormalGlobalFrame
1698 << G4endl;
1699 edDfn << " Global Computed from Local = " << globalNormal << G4endl;
1700 G4Exception("G4ITNavigator1::GetGlobalExitNormal()", "GeomNav0003",
1701 JustWarning, edDfn);
1702 }
1703 }
1704#endif
1705
1706 return globalNormal;
1707}
1708
1709// To make the new Voxel Safety the default, uncomment the next line
1710#define G4NEW_SAFETY 1
1711
1712// ********************************************************************
1713// ComputeSafety
1714//
1715// It assumes that it will be
1716// i) called at the Point in the same volume as the EndPoint of the
1717// ComputeStep.
1718// ii) after (or at the end of) ComputeStep OR after the relocation.
1719// ********************************************************************
1720//
1722 const G4double pMaxLength,
1723 const G4bool keepState)
1724{
1725 G4double newSafety = 0.0;
1726
1727#ifdef G4DEBUG_NAVIGATION
1728 G4long oldcoutPrec = G4cout.precision(8);
1729 if( fVerbose > 0 )
1730 {
1731 G4cout << "*** G4ITNavigator1::ComputeSafety: ***" << G4endl
1732 << " Called at point: " << pGlobalpoint << G4endl;
1733
1734 G4VPhysicalVolume *motherPhysical = fHistory.GetTopVolume();
1735 G4cout << " Volume = " << motherPhysical->GetName()
1736 << " - Maximum length = " << pMaxLength << G4endl;
1737 if( fVerbose >= 4 )
1738 {
1739 G4cout << " ----- Upon entering Compute Safety:" << G4endl;
1740 PrintState();
1741 }
1742 }
1743#endif
1744
1745 if (keepState) { SetSavedState(); }
1746
1747 G4double distEndpointSq = (pGlobalpoint-fStepEndPoint).mag2();
1748 G4bool stayedOnEndpoint = distEndpointSq < kCarTolerance*kCarTolerance;
1749 G4bool endpointOnSurface = fEnteredDaughter || fExitedMother;
1750
1751 if( !(endpointOnSurface && stayedOnEndpoint) )
1752 {
1753 // Pseudo-relocate to this point (updates voxel information only)
1754 //
1755 LocateGlobalPointWithinVolume( pGlobalpoint );
1756 // --->> DANGER: Side effects on sub-navigator voxel information <<---
1757 // Could be replaced again by 'granular' calls to sub-navigator
1758 // locates (similar side-effects, but faster.
1759 // Solutions:
1760 // 1) Re-locate (to where?)
1761 // 2) Insure that the methods using (G4ComputeStep?)
1762 // does a relocation (if information is disturbed only ?)
1763
1764#ifdef G4DEBUG_NAVIGATION
1765 if( fVerbose >= 2 )
1766 {
1767 G4cout << " G4ITNavigator1::ComputeSafety() relocates-in-volume to point: "
1768 << pGlobalpoint << G4endl;
1769 }
1770#endif
1771 G4VPhysicalVolume *motherPhysical = fHistory.GetTopVolume();
1772 G4LogicalVolume *motherLogical = motherPhysical->GetLogicalVolume();
1773 G4SmartVoxelHeader* pVoxelHeader = motherLogical->GetVoxelHeader();
1774 G4ThreeVector localPoint = ComputeLocalPoint(pGlobalpoint);
1775
1777 {
1778 switch(CharacteriseDaughters(motherLogical))
1779 {
1780 case kNormal:
1781 if ( pVoxelHeader )
1782 {
1783#ifdef G4NEW_SAFETY
1784 G4double safetyTwo = fpVoxelSafety->ComputeSafety(localPoint,
1785 *motherPhysical, pMaxLength);
1786 newSafety= safetyTwo; // Faster and best available
1787#else
1788 G4double safetyOldVoxel;
1789 safetyOldVoxel =
1790 fvoxelNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1791 newSafety= safetyOldVoxel;
1792#endif
1793 }
1794 else
1795 {
1796 newSafety=fnormalNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1797 }
1798 break;
1799 case kParameterised:
1800 if( GetDaughtersRegularStructureId(motherLogical) != 1 )
1801 {
1802 newSafety=fparamNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1803 }
1804 else // Regular structure
1805 {
1806 newSafety=fregularNav.ComputeSafety(localPoint,fHistory,pMaxLength);
1807 }
1808 break;
1809 case kReplica:
1810 G4Exception("G4ITNavigator1::ComputeSafety()", "GeomNav0001",
1811 FatalException, "Not applicable for replicated volumes.");
1812 break;
1813 case kExternal:
1814 G4Exception("G4ITNavigator1::ComputeSafety()",
1815 "GeomNav0001", FatalException,
1816 "Not applicable for external volumes.");
1817 break;
1818 }
1819 }
1820 else
1821 {
1822 newSafety = freplicaNav.ComputeSafety(pGlobalpoint, localPoint,
1823 fHistory, pMaxLength);
1824 }
1825 }
1826 else // if( endpointOnSurface && stayedOnEndpoint )
1827 {
1828#ifdef G4DEBUG_NAVIGATION
1829 if( fVerbose >= 2 )
1830 {
1831 G4cout << " G4ITNavigator1::ComputeSafety() finds that point - "
1832 << pGlobalpoint << " - is on surface " << G4endl;
1833 if( fEnteredDaughter ) { G4cout << " entered new daughter volume"; }
1834 if( fExitedMother ) { G4cout << " and exited previous volume."; }
1835 G4cout << G4endl;
1836 G4cout << " EndPoint was = " << fStepEndPoint << G4endl;
1837 }
1838#endif
1839 newSafety = 0.0;
1840 }
1841
1842 // Remember last safety origin & value
1843 //
1844 fPreviousSftOrigin = pGlobalpoint;
1845 fPreviousSafety = newSafety;
1846
1847 if (keepState) { RestoreSavedState(); }
1848
1849#ifdef G4DEBUG_NAVIGATION
1850 if( fVerbose > 1 )
1851 {
1852 G4cout << " ---- Exiting ComputeSafety " << G4endl;
1853 if( fVerbose > 2 ) { PrintState(); }
1854 G4cout << " Returned value of Safety = " << newSafety << G4endl;
1855 }
1856 G4cout.precision(oldcoutPrec);
1857#endif
1858
1859 return newSafety;
1860}
1861
1862// ********************************************************************
1863// CreateTouchableHistoryHandle
1864// ********************************************************************
1865//
1867{
1869}
1870
1871// ********************************************************************
1872// PrintState
1873// ********************************************************************
1874//
1876{
1877 G4long oldcoutPrec = G4cout.precision(4);
1878 if( fVerbose == 4 )
1879 {
1880 G4cout << "The current state of G4ITNavigator1 is: " << G4endl;
1881 G4cout << " ValidExitNormal= " << fValidExitNormal << G4endl
1882 << " ExitNormal = " << fExitNormal << G4endl
1883 << " Exiting = " << fExiting << G4endl
1884 << " Entering = " << fEntering << G4endl
1885 << " BlockedPhysicalVolume= " ;
1886 if (fBlockedPhysicalVolume==0)
1887 G4cout << "None";
1888 else
1889 G4cout << fBlockedPhysicalVolume->GetName();
1890 G4cout << G4endl
1891 << " BlockedReplicaNo = " << fBlockedReplicaNo << G4endl
1892 << " LastStepWasZero = " << fLastStepWasZero << G4endl
1893 << G4endl;
1894 }
1895 if( ( 1 < fVerbose) && (fVerbose < 4) )
1896 {
1897 G4cout << G4endl; // Make sure to line up
1898 G4cout << std::setw(30) << " ExitNormal " << " "
1899 << std::setw( 5) << " Valid " << " "
1900 << std::setw( 9) << " Exiting " << " "
1901 << std::setw( 9) << " Entering" << " "
1902 << std::setw(15) << " Blocked:Volume " << " "
1903 << std::setw( 9) << " ReplicaNo" << " "
1904 << std::setw( 8) << " LastStepZero " << " "
1905 << G4endl;
1906 G4cout << "( " << std::setw(7) << fExitNormal.x()
1907 << ", " << std::setw(7) << fExitNormal.y()
1908 << ", " << std::setw(7) << fExitNormal.z() << " ) "
1909 << std::setw( 5) << fValidExitNormal << " "
1910 << std::setw( 9) << fExiting << " "
1911 << std::setw( 9) << fEntering << " ";
1912 if ( fBlockedPhysicalVolume==0 )
1913 {
1914 G4cout << std::setw(15) << "None";
1915 }
1916 else
1917 {
1918 G4cout << std::setw(15)<< fBlockedPhysicalVolume->GetName();
1919 }
1920 G4cout << std::setw( 9) << fBlockedReplicaNo << " "
1921 << std::setw( 8) << fLastStepWasZero << " "
1922 << G4endl;
1923 }
1924 if( fVerbose > 2 )
1925 {
1926 G4cout.precision(8);
1927 G4cout << " Current Localpoint = " << fLastLocatedPointLocal << G4endl;
1928 G4cout << " PreviousSftOrigin = " << fPreviousSftOrigin << G4endl;
1929 G4cout << " PreviousSafety = " << fPreviousSafety << G4endl;
1930 }
1931 G4cout.precision(oldcoutPrec);
1932}
1933
1934// ********************************************************************
1935// ComputeStepLog
1936// ********************************************************************
1937//
1938void G4ITNavigator1::ComputeStepLog(const G4ThreeVector& pGlobalpoint,
1939 G4double moveLenSq) const
1940{
1941 // The following checks only make sense if the move is larger
1942 // than the tolerance.
1943
1944 static const G4double fAccuracyForWarning = kCarTolerance,
1945 fAccuracyForException = 1000*kCarTolerance;
1946
1947 G4ThreeVector OriginalGlobalpoint = fHistory.GetTopTransform().Inverse().
1948 TransformPoint(fLastLocatedPointLocal);
1949
1950 G4double shiftOriginSafSq = (fPreviousSftOrigin-pGlobalpoint).mag2();
1951
1952 // Check that the starting point of this step is
1953 // within the isotropic safety sphere of the last point
1954 // to a accuracy/precision given by fAccuracyForWarning.
1955 // If so give warning.
1956 // If it fails by more than fAccuracyForException exit with error.
1957 //
1958 if( shiftOriginSafSq >= sqr(fPreviousSafety) )
1959 {
1960 G4double shiftOrigin = std::sqrt(shiftOriginSafSq);
1961 G4double diffShiftSaf = shiftOrigin - fPreviousSafety;
1962
1963 if( diffShiftSaf > fAccuracyForWarning )
1964 {
1965 G4long oldcoutPrec= G4cout.precision(8);
1966 G4long oldcerrPrec= G4cerr.precision(10);
1967 std::ostringstream message, suggestion;
1968 message << "Accuracy error or slightly inaccurate position shift."
1969 << G4endl
1970 << " The Step's starting point has moved "
1971 << std::sqrt(moveLenSq)/mm << " mm " << G4endl
1972 << " since the last call to a Locate method." << G4endl
1973 << " This has resulted in moving "
1974 << shiftOrigin/mm << " mm "
1975 << " from the last point at which the safety "
1976 << " was calculated " << G4endl
1977 << " which is more than the computed safety= "
1978 << fPreviousSafety/mm << " mm at that point." << G4endl
1979 << " This difference is "
1980 << diffShiftSaf/mm << " mm." << G4endl
1981 << " The tolerated accuracy is "
1982 << fAccuracyForException/mm << " mm.";
1983
1984 suggestion << " ";
1985 static G4ThreadLocal G4int warnNow = 0;
1986 if( ((++warnNow % 100) == 1) )
1987 {
1988 message << G4endl
1989 << " This problem can be due to either " << G4endl
1990 << " - a process that has proposed a displacement"
1991 << " larger than the current safety , or" << G4endl
1992 << " - inaccuracy in the computation of the safety";
1993 suggestion << "We suggest that you " << G4endl
1994 << " - find i) what particle is being tracked, and "
1995 << " ii) through what part of your geometry " << G4endl
1996 << " for example by re-running this event with "
1997 << G4endl
1998 << " /tracking/verbose 1 " << G4endl
1999 << " - check which processes you declare for"
2000 << " this particle (and look at non-standard ones)"
2001 << G4endl
2002 << " - in case, create a detailed logfile"
2003 << " of this event using:" << G4endl
2004 << " /tracking/verbose 6 ";
2005 }
2006 G4Exception("G4ITNavigator1::ComputeStep()",
2007 "GeomNav1002", JustWarning,
2008 message, G4String(suggestion.str()));
2009 G4cout.precision(oldcoutPrec);
2010 G4cerr.precision(oldcerrPrec);
2011 }
2012#ifdef G4DEBUG_NAVIGATION
2013 else
2014 {
2015 G4cerr << "WARNING - G4ITNavigator1::ComputeStep()" << G4endl
2016 << " The Step's starting point has moved "
2017 << std::sqrt(moveLenSq) << "," << G4endl
2018 << " which has taken it to the limit of"
2019 << " the current safety. " << G4endl;
2020 }
2021#endif
2022 }
2023 G4double safetyPlus = fPreviousSafety + fAccuracyForException;
2024 if ( shiftOriginSafSq > sqr(safetyPlus) )
2025 {
2026 std::ostringstream message;
2027 message << "May lead to a crash or unreliable results." << G4endl
2028 << " Position has shifted considerably without"
2029 << " notifying the navigator !" << G4endl
2030 << " Tolerated safety: " << safetyPlus << G4endl
2031 << " Computed shift : " << shiftOriginSafSq;
2032 G4Exception("G4ITNavigator1::ComputeStep()", "GeomNav1002",
2033 JustWarning, message);
2034 }
2035}
2036
2037// ********************************************************************
2038// Operator <<
2039// ********************************************************************
2040//
2041std::ostream& operator << (std::ostream &os,const G4ITNavigator1 &n)
2042{
2043 // Old version did only the following:
2044 // os << "Current History: " << G4endl << n.fHistory;
2045 // Old behaviour is recovered for fVerbose = 0
2046
2047 // Adapted from G4ITNavigator1::PrintState() const
2048
2049 G4long oldcoutPrec = os.precision(4);
2050 if( n.fVerbose >= 4 )
2051 {
2052 os << "The current state of G4ITNavigator1 is: " << G4endl;
2053 os << " ValidExitNormal= " << n.fValidExitNormal << G4endl
2054 << " ExitNormal = " << n.fExitNormal << G4endl
2055 << " Exiting = " << n.fExiting << G4endl
2056 << " Entering = " << n.fEntering << G4endl
2057 << " BlockedPhysicalVolume= " ;
2058 if (n.fBlockedPhysicalVolume==0)
2059 os << "None";
2060 else
2061 os << n.fBlockedPhysicalVolume->GetName();
2062 os << G4endl
2063 << " BlockedReplicaNo = " << n.fBlockedReplicaNo << G4endl
2064 << " LastStepWasZero = " << n.fLastStepWasZero << G4endl
2065 << G4endl;
2066 }
2067 if( ( 1 < n.fVerbose) && (n.fVerbose < 4) )
2068 {
2069 os << G4endl; // Make sure to line up
2070 os << std::setw(30) << " ExitNormal " << " "
2071 << std::setw( 5) << " Valid " << " "
2072 << std::setw( 9) << " Exiting " << " "
2073 << std::setw( 9) << " Entering" << " "
2074 << std::setw(15) << " Blocked:Volume " << " "
2075 << std::setw( 9) << " ReplicaNo" << " "
2076 << std::setw( 8) << " LastStepZero " << " "
2077 << G4endl;
2078 os << "( " << std::setw(7) << n.fExitNormal.x()
2079 << ", " << std::setw(7) << n.fExitNormal.y()
2080 << ", " << std::setw(7) << n.fExitNormal.z() << " ) "
2081 << std::setw( 5) << n.fValidExitNormal << " "
2082 << std::setw( 9) << n.fExiting << " "
2083 << std::setw( 9) << n.fEntering << " ";
2084 if ( n.fBlockedPhysicalVolume==0 )
2085 { os << std::setw(15) << "None"; }
2086 else
2087 { os << std::setw(15)<< n.fBlockedPhysicalVolume->GetName(); }
2088 os << std::setw( 9) << n.fBlockedReplicaNo << " "
2089 << std::setw( 8) << n.fLastStepWasZero << " "
2090 << G4endl;
2091 }
2092 if( n.fVerbose > 2 )
2093 {
2094 os.precision(8);
2095 os << " Current Localpoint = " << n.fLastLocatedPointLocal << G4endl;
2096 os << " PreviousSftOrigin = " << n.fPreviousSftOrigin << G4endl;
2097 os << " PreviousSafety = " << n.fPreviousSafety << G4endl;
2098 }
2099 if( n.fVerbose > 3 || n.fVerbose == 0 )
2100 {
2101 os << "Current History: " << G4endl << n.fHistory;
2102 }
2103
2104 os.precision(oldcoutPrec);
2105 return os;
2106}
@ JustWarning
@ FatalException
@ EventMustBeAborted
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
#define fWasLimitedByGeometry
#define G4DEBUG_NAVIGATION
std::ostream & operator<<(std::ostream &os, const G4ITNavigator1 &n)
#define fExitNormalGlobalFrame
#define fPushed
#define fLastStepWasZero
#define fPreviousSafety
CLHEP::Hep3Vector G4ThreeVector
G4ReferenceCountedHandle< G4TouchableHistory > G4TouchableHistoryHandle
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector unit() const
double x() const
double mag2() const
double y() const
double dot(const Hep3Vector &) const
double mag() const
G4AffineTransform Inverse() const
G4AffineTransform & Invert()
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4ThreeVector TransformAxis(const G4ThreeVector &axis) const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
G4TouchableHistory * CreateTouchableHistory() const
virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid)
virtual G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=0, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true)
const G4AffineTransform GetLocalToGlobalTransform() const
void RestoreSavedState()
G4int GetVerboseLevel() const
G4ThreeVector fStepEndPoint
G4double CheckNextStep(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double pCurrentProposedStepLength, G4double &pNewSafety)
G4ThreeVector ComputeLocalAxis(const G4ThreeVector &pVec) const
virtual G4VPhysicalVolume * ResetHierarchyAndLocate(const G4ThreeVector &point, const G4ThreeVector &direction, const G4TouchableHistory &h)
void ResetStackAndState()
G4int GetDaughtersRegularStructureId(const G4LogicalVolume *pLog) const
const G4AffineTransform & GetGlobalToLocalTransform() const
G4bool EnteredDaughterVolume() const
virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4double pProposedMaxLength=DBL_MAX, const G4bool keepState=true)
void PrintState() const
EVolume CharacteriseDaughters(const G4LogicalVolume *pLog) const
G4NavigationHistory fHistory
virtual G4ThreeVector GetLocalExitNormalAndCheck(const G4ThreeVector &point, G4bool *valid)
G4ThreeVector fLastStepEndPointLocal
void SetNavigatorState(G4ITNavigatorState_Lock1 *)
virtual void SetupHierarchy()
G4AffineTransform GetMotherToDaughterTransform(G4VPhysicalVolume *dVolume, G4int dReplicaNo, EVolume dVolumeType)
EVolume VolumeType(const G4VPhysicalVolume *pVol) const
virtual G4double ComputeStep(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double pCurrentProposedStepLength, G4double &pNewSafety)
G4bool fWasLimitedByGeometry
virtual G4ThreeVector GetLocalExitNormal(G4bool *valid)
G4ITNavigatorState_Lock1 * GetNavigatorState()
G4double kCarTolerance
void NewNavigatorState()
virtual ~G4ITNavigator1()
virtual G4TouchableHistoryHandle CreateTouchableHistoryHandle() const
void SetVerboseLevel(G4int level)
G4ThreeVector ComputeLocalPoint(const G4ThreeVector &rGlobPoint) const
virtual void ResetState()
G4VSolid * GetSolid() const
const G4String & GetName() const
void SetSolid(G4VSolid *pSolid)
G4SmartVoxelHeader * GetVoxelHeader() const
void UpdateMaterial(G4Material *pMaterial)
EVolume GetTopVolumeType() const
void NewLevel(G4VPhysicalVolume *pNewMother, EVolume vType=kNormal, G4int nReplica=-1)
G4int GetReplicaNo(G4int n) const
const G4AffineTransform & GetTopTransform() const
G4int GetTopReplicaNo() const
G4VPhysicalVolume * GetVolume(G4int n) const
std::size_t GetDepth() const
G4VPhysicalVolume * GetTopVolume() const
EVolume GetVolumeType(G4int n) const
const G4AffineTransform & GetTransform(G4int n) const
G4double ComputeStep(const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4NavigationHistory &history, const G4double pMaxLength=DBL_MAX)
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4SmartVoxelNode * ParamVoxelLocate(G4SmartVoxelHeader *pHead, const G4ThreeVector &localPoint)
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4NavigationHistory &history, const G4double pProposedMaxLength=DBL_MAX)
void SetNormalNavigation(G4NormalNavigation *fnormnav)
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4NavigationHistory &history, const G4double pProposedMaxLength=DBL_MAX)
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4bool &calculatedExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4double ComputeSafety(const G4ThreeVector &globalPoint, const G4ThreeVector &localPoint, G4NavigationHistory &history, const G4double pProposedMaxLength=DBL_MAX)
void ComputeTransformation(const G4int replicaNo, G4VPhysicalVolume *pVol, G4ThreeVector &point) const
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
EInside BackLocate(G4NavigationHistory &history, const G4ThreeVector &globalPoint, G4ThreeVector &localPoint, const G4bool &exiting, G4bool &notKnownInside) const
const G4NavigationHistory * GetHistory() const
G4int MoveUpHistory(G4int num_levels=1)
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
virtual void ComputeTransformation(const G4int, G4VPhysicalVolume *) const =0
const G4RotationMatrix * GetRotation() const
virtual void SetCopyNo(G4int CopyNo)=0
const G4ThreeVector GetTranslation() const
virtual G4bool CheckOverlaps(G4int res=1000, G4double tol=0., G4bool verbose=true, G4int errMax=1)
G4LogicalVolume * GetLogicalVolume() const
virtual G4int GetCopyNo() const =0
const G4String & GetName() const
virtual G4int GetRegularStructureId() const =0
virtual G4VPVParameterisation * GetParameterisation() const =0
G4String GetName() const
virtual EInside Inside(const G4ThreeVector &p) const =0
virtual void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4VSolid.cc:137
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const =0
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
virtual G4GeometryType GetEntityType() const =0
virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4NavigationHistory &history, const G4double pMaxLength=DBL_MAX)
virtual G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
G4SmartVoxelNode * VoxelLocate(G4SmartVoxelHeader *pHead, const G4ThreeVector &localPoint)
virtual G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint)
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4VPhysicalVolume &currentPhysical, G4double maxLength=DBL_MAX)
EInside
Definition: geomdefs.hh:67
@ kInside
Definition: geomdefs.hh:70
@ kOutside
Definition: geomdefs.hh:68
@ kSurface
Definition: geomdefs.hh:69
EVolume
Definition: geomdefs.hh:83
@ kNormal
Definition: geomdefs.hh:84
@ kParameterised
Definition: geomdefs.hh:86
@ kExternal
Definition: geomdefs.hh:87
@ kReplica
Definition: geomdefs.hh:85
T sqr(const T &x)
Definition: templates.hh:128
#define G4ThreadLocal
Definition: tls.hh:77