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