Geant4 Cross Reference |
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 // G4Navigator 27 // 28 // Class description: 29 // 30 // A class for use by the tracking management, able to obtain/calculate 31 // dynamic tracking time information such as the distance to the next volume, 32 // or to find the physical volume containing a given point in the world 33 // reference system. The navigator maintains a transformation history and 34 // other information to optimise the tracking time performance. 35 36 // - Created. Paul Kent, Jul 95/96 37 // - Made Navigator Abstract G. Cosmo, Nov 2003 38 // - Added check mode G. Cosmo, Mar 2004 39 // - Zero step protections J.A. / G.C., Nov 2004 40 // -------------------------------------------------------------------- 41 #ifndef G4NAVIGATOR_HH 42 #define G4NAVIGATOR_HH 1 43 44 #include "geomdefs.hh" 45 46 #include "G4ThreeVector.hh" 47 #include "G4AffineTransform.hh" 48 #include "G4RotationMatrix.hh" 49 50 #include "G4LogicalVolume.hh" // Used in inline methods 51 #include "G4TouchableHandle.hh" // " " 52 53 #include "G4NavigationHistory.hh" 54 #include "G4NormalNavigation.hh" 55 #include "G4VoxelNavigation.hh" 56 #include "G4ParameterisedNavigation.hh" 57 #include "G4ReplicaNavigation.hh" 58 #include "G4RegularNavigation.hh" 59 #include "G4VExternalNavigation.hh" 60 61 #include <iostream> 62 63 class G4VPhysicalVolume; 64 class G4SafetyCalculator; 65 66 class G4Navigator 67 { 68 public: 69 70 friend std::ostream& operator << (std::ostream &os, const G4Navigator &n); 71 72 G4Navigator(); 73 // Constructor - initialisers and setup. 74 75 G4Navigator(const G4Navigator&) = delete; 76 G4Navigator& operator=(const G4Navigator&) = delete; 77 // Copy constructor & assignment operator not allowed. 78 79 virtual ~G4Navigator(); 80 // Destructor. No actions. 81 82 virtual G4double ComputeStep(const G4ThreeVector& pGlobalPoint, 83 const G4ThreeVector& pDirection, 84 const G4double pCurrentProposedStepLength, 85 G4double& pNewSafety); 86 // Calculate the distance to the next boundary intersected 87 // along the specified NORMALISED vector direction and 88 // from the specified point in the global coordinate 89 // system. LocateGlobalPointAndSetup or LocateGlobalPointWithinVolume 90 // must have been called with the same global point prior to this call. 91 // The isotropic distance to the nearest boundary is also 92 // calculated (usually an underestimate). The current 93 // proposed Step length is used to avoid intersection 94 // calculations: if it can be determined that the nearest 95 // boundary is >pCurrentProposedStepLength away, kInfinity 96 // is returned together with the computed isotropic safety 97 // distance. Geometry must be closed. 98 99 G4double CheckNextStep(const G4ThreeVector& pGlobalPoint, 100 const G4ThreeVector& pDirection, 101 const G4double pCurrentProposedStepLength, 102 G4double& pNewSafety); 103 // Same as above, but do not disturb the state of the Navigator. 104 105 virtual 106 G4VPhysicalVolume* ResetHierarchyAndLocate(const G4ThreeVector& point, 107 const G4ThreeVector& direction, 108 const G4TouchableHistory& h); 109 110 // Resets the geometrical hierarchy and search for the volumes deepest 111 // in the hierarchy containing the point in the global coordinate space. 112 // The direction is used to check if a volume is entered. 113 // The search begin is the geometrical hierarchy at the location of the 114 // last located point, or the endpoint of the previous Step if 115 // SetGeometricallyLimitedStep() has been called immediately before. 116 // 117 // Important Note: In order to call this the geometry MUST be closed. 118 119 virtual 120 G4VPhysicalVolume* LocateGlobalPointAndSetup(const G4ThreeVector& point, 121 const G4ThreeVector* direction = nullptr, 122 const G4bool pRelativeSearch = true, 123 const G4bool ignoreDirection = true); 124 // Search the geometrical hierarchy for the volumes deepest in hierarchy 125 // containing the point in the global coordinate space. Two main cases 126 // are: 127 // i) If pRelativeSearch=false it makes use of no previous/state 128 // information. Returns the physical volume containing the point, 129 // with all previous mothers correctly set up. 130 // ii) If pRelativeSearch is set to true, the search begin is the 131 // geometrical hierarchy at the location of the last located point, 132 // or the endpoint of previous Step if SetGeometricallyLimitedStep() 133 // has been called immediately before. 134 // The direction is used (to check if a volume is entered) if either 135 // - the argument ignoreDirection is false, or 136 // - the Navigator has determined that it is on an edge shared by two 137 // or more volumes. (This is state information.) 138 // 139 // Important Note: In order to call this the geometry MUST be closed. 140 141 virtual 142 void LocateGlobalPointWithinVolume(const G4ThreeVector& position); 143 // Notify the Navigator that a track has moved to the new Global point 144 // 'position', that is known to be within the current safety. 145 // No check is performed to ensure that it is within the volume. 146 // This method can be called instead of LocateGlobalPointAndSetup ONLY if 147 // the caller is certain that the new global point (position) is inside 148 // the same volume as the previous position. 149 // Usually this can be guaranteed only if the point is within safety. 150 151 inline void LocateGlobalPointAndUpdateTouchableHandle( 152 const G4ThreeVector& position, 153 const G4ThreeVector& direction, 154 G4TouchableHandle& oldTouchableToUpdate, 155 const G4bool RelativeSearch = true); 156 // First, search the geometrical hierarchy like the above method 157 // LocateGlobalPointAndSetup(). Then use the volume found and its 158 // navigation history to update the touchable. 159 160 inline void LocateGlobalPointAndUpdateTouchable( 161 const G4ThreeVector& position, 162 const G4ThreeVector& direction, 163 G4VTouchable* touchableToUpdate, 164 const G4bool RelativeSearch = true); 165 // First, search the geometrical hierarchy like the above method 166 // LocateGlobalPointAndSetup(). Then use the volume found and its 167 // navigation history to update the touchable. 168 169 inline void LocateGlobalPointAndUpdateTouchable( 170 const G4ThreeVector& position, 171 G4VTouchable* touchableToUpdate, 172 const G4bool RelativeSearch = true); 173 // Same as the method above but missing direction. 174 175 inline void SetGeometricallyLimitedStep(); 176 // Inform the navigator that the previous Step calculated 177 // by the geometry was taken in its entirety. 178 179 virtual G4double ComputeSafety(const G4ThreeVector& globalpoint, 180 const G4double pProposedMaxLength = DBL_MAX, 181 const G4bool keepState = true); 182 // Calculate the isotropic distance to the nearest boundary from the 183 // specified point in the global coordinate system. 184 // The globalpoint utilised must be within the current volume. 185 // The value returned is usually an underestimate. 186 // The proposed maximum length is used to avoid volume safety 187 // calculations. The geometry must be closed. 188 // To ensure minimum side effects from the call, keepState must be true. 189 190 inline G4VPhysicalVolume* GetWorldVolume() const; 191 // Return the current world (`topmost') volume. 192 193 inline void SetWorldVolume(G4VPhysicalVolume* pWorld); 194 // Set the world (`topmost') volume. This must be positioned at 195 // origin (0,0,0) and unrotated. 196 197 inline G4TouchableHistory* CreateTouchableHistory() const; 198 inline G4TouchableHistory* CreateTouchableHistory(const G4NavigationHistory*) const; 199 // `Touchable' creation methods: caller has deletion responsibility. 200 201 virtual G4TouchableHandle CreateTouchableHistoryHandle() const; 202 // Returns a reference counted handle to a touchable history. 203 204 virtual G4ThreeVector GetLocalExitNormal(G4bool* valid); 205 virtual G4ThreeVector GetLocalExitNormalAndCheck(const G4ThreeVector& point, 206 G4bool* valid); 207 virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector& point, 208 G4bool* valid); 209 // Return Exit Surface Normal and validity too. 210 // Can only be called if the Navigator's last Step has crossed a 211 // volume geometrical boundary. 212 // It returns the Normal to the surface pointing out of the volume that 213 // was left behind and/or into the volume that was entered. 214 // Convention: 215 // The *local* normal is in the coordinate system of the *final* volume. 216 // Restriction: 217 // Normals are not available for replica volumes (returns valid= false) 218 // These methods takes full care about how to calculate this normal, 219 // but if the surfaces are not convex it will return valid=false. 220 221 inline G4int GetVerboseLevel() const; 222 inline void SetVerboseLevel(G4int level); 223 // Get/Set Verbose(ness) level. 224 // [if level>0 && G4VERBOSE, printout can occur] 225 226 inline G4bool IsActive() const; 227 // Verify if the navigator is active. 228 inline void Activate(G4bool flag); 229 // Activate/inactivate the navigator. 230 231 inline G4bool EnteredDaughterVolume() const; 232 // The purpose of this function is to inform the caller if the track is 233 // entering a daughter volume while exiting from the current volume. 234 // This method returns 235 // - True only in case 1) above, that is when the Step has caused 236 // the track to arrive at a boundary of a daughter. 237 // - False in cases 2), 3) and 4), i.e. in all other cases. 238 // This function is not guaranteed to work if SetGeometricallyLimitedStep() 239 // was not called when it should have been called. 240 inline G4bool ExitedMotherVolume() const; 241 // Verify if the step has exited the mother volume. 242 243 inline void CheckMode(G4bool mode); 244 // Run navigation in "check-mode", therefore using additional 245 // verifications and more strict correctness conditions. 246 // Is effective only with G4VERBOSE set. 247 inline G4bool IsCheckModeActive() const; 248 inline void SetPushVerbosity(G4bool mode); 249 // Set/unset verbosity for pushed tracks (default is true). 250 251 void PrintState() const; 252 // Print the internal state of the Navigator (for debugging). 253 // The level of detail is according to the verbosity. 254 255 inline const G4AffineTransform& GetGlobalToLocalTransform() const; 256 inline const G4AffineTransform GetLocalToGlobalTransform() const; 257 // Obtain the transformations Global/Local (and inverse). 258 // Clients of these methods must copy the data if they need to keep it. 259 260 G4AffineTransform GetMotherToDaughterTransform(G4VPhysicalVolume* dVolume, 261 G4int dReplicaNo, 262 EVolume dVolumeType ); 263 // Obtain mother to daughter transformation. 264 265 inline void ResetStackAndState(); 266 // Reset stack and minimum or navigator state machine necessary for reset 267 // as needed by LocalGlobalPointAndSetup. 268 // Does not perform clears, resizes, or reset fLastLocatedPointLocal. 269 270 inline G4int SeverityOfZeroStepping( G4int* noZeroSteps ) const; 271 // Report on severity of error and number of zero steps, 272 // in case Navigator is stuck and is returning zero steps. 273 // Values: 1 (small problem), 5 (correcting), 274 // 9 (ready to abandon), 10 (abandoned) 275 276 inline G4ThreeVector GetCurrentLocalCoordinate() const; 277 // Return the local coordinate of the point in the reference system 278 // of its containing volume that was found by LocalGlobalPointAndSetup. 279 // The local coordinate of the last located track. 280 281 inline G4ThreeVector NetTranslation() const; 282 inline G4RotationMatrix NetRotation() const; 283 // Compute+return the local->global translation/rotation of current volume. 284 285 inline void EnableBestSafety( G4bool value = false ); 286 // Enable best-possible evaluation of isotropic safety. 287 288 inline G4VExternalNavigation* GetExternalNavigation() const; 289 void SetExternalNavigation(G4VExternalNavigation* externalNav); 290 // Accessor & modifier for custom external navigation. 291 292 inline G4VoxelNavigation& GetVoxelNavigator(); 293 void SetVoxelNavigation(G4VoxelNavigation* voxelNav); 294 // Alternative navigator for voxel volumes. 295 296 inline G4Navigator* Clone() const; 297 // Cloning feature for use in MT applications to clone 298 // navigator, including external sub-navigator. 299 // Client has responsibility for ownership of returned allocated pointer. 300 301 inline G4ThreeVector GetLastStepEndPoint() const { return fStepEndPoint;} 302 // Get endpoint of last step. 303 304 void InformLastStep(G4double lastStep, 305 G4bool entersDaughtVol, 306 G4bool exitsMotherVol ); 307 // Derived navigators which rely on LocateGlobalPointAndSetup() need to 308 // inform size of step, to maintain logic about arriving on boundary 309 // for challenging cases. 310 // Required in order to cope with multiple trials at boundaries 311 // => Locate with use direction rather than simple, fast logic. 312 313 protected: 314 315 void SetSavedState(); 316 // ( fValidExitNormal, fExitNormal, fExiting, fEntering, 317 // fBlockedPhysicalVolume, fBlockedReplicaNo, fLastStepWasZero); 318 // Extended to include: 319 // ( fLastLocatedPointLocal, fLocatedOutsideWorld; 320 // fEnteredDaughter, fExitedMother 321 // fPreviousSftOrigin, sPreviousSafety) Safety Sphere. 322 323 void RestoreSavedState(); 324 // Copy aspects of the state, to enable a non-state changing 325 // call to ComputeStep(). 326 327 virtual void ResetState(); 328 // Utility method to reset the navigator state machine. 329 330 inline G4ThreeVector ComputeLocalPoint(const G4ThreeVector& rGlobPoint) const; 331 // Return position vector in local coordinate system, given a position 332 // vector in world coordinate system. 333 334 inline G4ThreeVector ComputeLocalAxis(const G4ThreeVector& pVec) const; 335 // Return the local direction of the specified vector in the reference 336 // system of the volume that was found by LocalGlobalPointAndSetup. 337 // The Local Coordinates of point in world coordinate system. 338 339 inline EVolume VolumeType(const G4VPhysicalVolume *pVol) const; 340 // Characterise `type' of volume - normal/replicated/parameterised. 341 342 inline EVolume CharacteriseDaughters(const G4LogicalVolume *pLog) const; 343 // Characterise daughter of logical volume. 344 345 inline G4int GetDaughtersRegularStructureId(const G4LogicalVolume *pLv) const; 346 // Get regular structure ID of first daughter. 347 348 virtual void SetupHierarchy(); 349 // Renavigate & reset hierarchy described by current history: 350 // o Reset volumes and recompute transforms and/or solids of 351 // replicated/parameterised volumes. 352 353 G4bool CheckOverlapsIterative(G4VPhysicalVolume* vol); 354 // Utility method to trigger overlaps check on a volume with reported 355 // overlaps ordered by relevance. Used in ComputeStep() when loopings 356 // with zero step are detected. 357 358 private: 359 360 void ComputeStepLog(const G4ThreeVector& pGlobalpoint, 361 G4double moveLenSq) const; 362 // Log and checks for steps larger than the tolerance. 363 364 protected: 365 366 G4double kCarTolerance, fMinStep, fSqTol; 367 // Cached tolerances. 368 369 // 370 // BEGIN State information 371 // 372 373 G4NavigationHistory fHistory; 374 // Transformation and history of the current path 375 // through the geometrical hierarchy. 376 377 G4ThreeVector fStepEndPoint; 378 // Endpoint of last ComputeStep 379 // can be used for optimisation (e.g. when computing safety). 380 G4ThreeVector fLastStepEndPointLocal; 381 // Position of the end-point of the last call to ComputeStep 382 // in last Local coordinates. 383 384 G4int fVerbose = 0; 385 // Verbose(ness) level [if > 0, printout can occur]. 386 387 G4bool fEnteredDaughter; 388 // A memory of whether in this Step a daughter volume is entered 389 // (set in Compute & Locate). 390 // After Compute: it expects to enter a daughter 391 // After Locate: it has entered a daughter. 392 393 G4bool fExitedMother; 394 // A similar memory whether the Step exited current "mother" volume 395 // completely, not entering daughter. 396 397 G4bool fWasLimitedByGeometry = false; 398 // Set true if last Step was limited by geometry. 399 400 private: 401 402 G4ThreeVector fLastLocatedPointLocal; 403 // Position of the last located point relative to its containing volume. 404 // This is coupled with the bool member fLocatedOutsideWorld; 405 406 G4ThreeVector fExitNormal; 407 // Leaving volume normal, in the volume containing the exited 408 // volume's coordinate system. 409 // This is closely coupled with fValidExitNormal, which signals whether 410 // we have a (valid) normal for volume we're leaving. 411 412 G4ThreeVector fGrandMotherExitNormal; 413 // Leaving volume normal, in its own coordinate system. 414 G4ThreeVector fExitNormalGlobalFrame; 415 // Leaving volume normal, in the global coordinate system. 416 417 G4ThreeVector fPreviousSftOrigin; 418 G4double fPreviousSafety; 419 // Memory of last safety origin & value. Used in ComputeStep() to ensure 420 // that origin of current Step is in the same volume as the point of the 421 // last relocation. 422 423 G4VPhysicalVolume* fLastMotherPhys = nullptr; 424 // Memory of the mother volume during previous step. 425 // Intended use: inform user in case of stuck track. 426 427 G4VPhysicalVolume* fBlockedPhysicalVolume; 428 G4int fBlockedReplicaNo; 429 // Identifies the volume and copy / replica number that is blocked 430 // (after exiting -- because the exit direction is along the exit normal) 431 // or a candidate for entry (after compute step). 432 433 G4int fNumberZeroSteps; 434 // Count zero steps, as one or two can occur due to changing momentum at 435 // a boundary or at an edge common between volumes; several zero steps 436 // are likely a problem in the geometry description or in the navigation. 437 // Number of preceding moves that were Zero. Reset to 0 after finite step. 438 G4int fActionThreshold_NoZeroSteps = 10; 439 // After this many failed/zero steps, act (push etc). 440 G4int fAbandonThreshold_NoZeroSteps = 25; 441 // After this many failed/zero steps, abandon track. 442 443 G4bool fActive = false; 444 // States if the navigator is activated or not. 445 446 G4bool fLastTriedStepComputation = false; 447 // Whether ComputeStep() was called since the last call to a Locate(). 448 // Uses: distinguish parts of state which differ before/after calls 449 // to ComputeStep() or one of the Locate() methods; avoid two consecutive 450 // calls to compute-step (illegal). 451 452 G4bool fEntering, fExiting; 453 // Entering/Exiting volumes blocking/setup. 454 // o If exiting, volume ptr & replica number (set & used by Locate..()) 455 // used for blocking on redescent of geometry; 456 // o If entering, volume ptr & replica number (set by ComputeStep(), 457 // used by Locate..()) of volume for 'automatic' entry. 458 459 G4bool fValidExitNormal; 460 // Set true if have leaving volume normal. 461 G4bool fLastStepWasZero; 462 // Whether the last ComputeStep moved Zero. Used to check for edges. 463 G4bool fLocatedOnEdge; 464 // Whether the Navigator has detected an edge. 465 G4bool fLocatedOutsideWorld; 466 // Whether the last call to Locate methods left the world. 467 468 G4bool fChangedGrandMotherRefFrame; 469 // Whether frame is changed. 470 G4bool fCalculatedExitNormal; 471 // Has it been computed since the last call to ComputeStep(). 472 // Covers both Global and GrandMother. 473 474 // END State information 475 // 476 477 // Optional State information (created/used as needed) 478 // 479 480 // Save key state information (NOT the navigation history stack) 481 // 482 struct G4SaveNavigatorState 483 { 484 G4ThreeVector sExitNormal; 485 G4bool sValidExitNormal; 486 G4bool sEntering, sExiting; 487 G4VPhysicalVolume* spBlockedPhysicalVolume; 488 G4int sBlockedReplicaNo; 489 G4int sLastStepWasZero; 490 G4bool sWasLimitedByGeometry; 491 492 // Potentially relevant 493 // 494 G4bool sLocatedOutsideWorld; 495 G4ThreeVector sLastLocatedPointLocal; 496 G4bool sEnteredDaughter, sExitedMother; 497 G4ThreeVector sPreviousSftOrigin; 498 G4double sPreviousSafety; 499 } fSaveState; 500 501 // BEGIN -- Tracking Invariants 502 // =========================================== 503 504 G4VPhysicalVolume* fTopPhysical = nullptr; 505 // A link to the topmost physical volume in the detector. 506 // Must be positioned at the origin and unrotated. 507 508 // Helpers/Utility classes 509 // 510 G4NormalNavigation fnormalNav; 511 G4VoxelNavigation* fpvoxelNav; 512 G4ParameterisedNavigation fparamNav; 513 G4ReplicaNavigation freplicaNav; 514 G4RegularNavigation fregularNav; 515 G4VExternalNavigation* fpExternalNav = nullptr; 516 G4VoxelSafety* fpVoxelSafety; 517 G4SafetyCalculator* fpSafetyCalculator = nullptr; 518 519 // Utility information 520 // 521 G4bool fCheck = false; 522 // Check-mode flag [if true, more strict checks are performed]. 523 G4bool fPushed = false, fWarnPush = true; 524 // Push flags [if true, means a stuck particle has been pushed]. 525 526 // End -- Tracking Invariants 527 }; 528 529 #include "G4Navigator.icc" 530 531 #endif 532 533 534 // NOTES: 535 // 536 // The following methods provide detailed information when a Step has 537 // arrived at a geometrical boundary. They distinguish between the different 538 // causes that can result in the track leaving its current volume. 539 // 540 // Four cases are possible: 541 // 542 // 1) The particle has reached a boundary of a daughter of the current volume: 543 // (this could cause the relocation to enter the daughter itself 544 // or a potential granddaughter or further descendant) 545 // 546 // 2) The particle has reached a boundary of the current 547 // volume, exiting into a mother (regardless the level 548 // at which it is located in the tree): 549 // 550 // 3) The particle has reached a boundary of the current 551 // volume, exiting into a volume which is not in its 552 // parental hierarchy: 553 // 554 // 4) The particle is not on a boundary between volumes: 555 // the function returns an exception, and the caller is 556 // reccomended to compare the G4touchables associated 557 // to the preStepPoint and postStepPoint to handle this case. 558 // 559 // G4bool EnteredDaughterVolume() 560 // G4bool IsExitNormalValid() 561 // G4ThreeVector GetLocalExitNormal() 562 // 563 // The expected usefulness of these methods is to allow the caller to 564 // determine how to compute the surface normal at the volume boundary. The two 565 // possibilities are to obtain the normal from: 566 // 567 // i) the solid associated with the volume of the initial point of the Step. 568 // This is valid for cases 2 and 3. 569 // (Note that the initial point is generally the PreStepPoint of a Step). 570 // or 571 // 572 // ii) the solid of the final point, ie of the volume after the relocation. 573 // This is valid for case 1. 574 // (Note that the final point is generally the PreStepPoint of a Step). 575 // 576 // This way the caller can always get a valid normal, pointing outside 577 // the solid for which it is computed, that can be used at his own 578 // discretion. 579