00001 // 00002 // ******************************************************************** 00003 // * License and Disclaimer * 00004 // * * 00005 // * The Geant4 software is copyright of the Copyright Holders of * 00006 // * the Geant4 Collaboration. It is provided under the terms and * 00007 // * conditions of the Geant4 Software License, included in the file * 00008 // * LICENSE and available at http://cern.ch/geant4/license . These * 00009 // * include a list of copyright holders. * 00010 // * * 00011 // * Neither the authors of this software system, nor their employing * 00012 // * institutes,nor the agencies providing financial support for this * 00013 // * work make any representation or warranty, express or implied, * 00014 // * regarding this software system or assume any liability for its * 00015 // * use. Please see the license in the file LICENSE and URL above * 00016 // * for the full disclaimer and the limitation of liability. * 00017 // * * 00018 // * This code implementation is the result of the scientific and * 00019 // * technical work of the GEANT4 collaboration. * 00020 // * By using, copying, modifying or distributing the software (or * 00021 // * any work based on the software) you agree to acknowledge its * 00022 // * use in resulting scientific publications, and indicate your * 00023 // * acceptance of all terms of the Geant4 Software license. * 00024 // ******************************************************************** 00025 // 00026 // 00027 // $Id$ 00028 // 00029 // 00030 // class G4Navigator 00031 // 00032 // Class description: 00033 // 00034 // A class for use by the tracking management, able to obtain/calculate 00035 // dynamic tracking time information such as the distance to the next volume, 00036 // or to find the physical volume containing a given point in the world 00037 // reference system. The navigator maintains a transformation history and 00038 // other information to optimise the tracking time performance. 00039 00040 // History: 00041 // - Created. Paul Kent, Jul 95/96 00042 // - Zero step protections J.A. / G.C., Nov 2004 00043 // - Added check mode G. Cosmo, Mar 2004 00044 // - Made Navigator Abstract G. Cosmo, Nov 2003 00045 // ********************************************************************* 00046 00047 #ifndef G4NAVIGATOR_HH 00048 #define G4NAVIGATOR_HH 00049 00050 #include "geomdefs.hh" 00051 00052 #include "G4ThreeVector.hh" 00053 #include "G4AffineTransform.hh" 00054 #include "G4RotationMatrix.hh" 00055 00056 #include "G4LogicalVolume.hh" // Used in inline methods 00057 #include "G4GRSVolume.hh" // " " 00058 #include "G4GRSSolid.hh" // " " 00059 #include "G4TouchableHandle.hh" // " " 00060 #include "G4TouchableHistoryHandle.hh" 00061 00062 #include "G4NavigationHistory.hh" 00063 #include "G4NormalNavigation.hh" 00064 #include "G4VoxelNavigation.hh" 00065 #include "G4ParameterisedNavigation.hh" 00066 #include "G4ReplicaNavigation.hh" 00067 #include "G4RegularNavigation.hh" 00068 00069 #include <iostream> 00070 00071 class G4VPhysicalVolume; 00072 00073 class G4Navigator 00074 { 00075 public: // with description 00076 00077 friend std::ostream& operator << (std::ostream &os, const G4Navigator &n); 00078 00079 G4Navigator(); 00080 // Constructor - initialisers and setup. 00081 00082 virtual ~G4Navigator(); 00083 // Destructor. No actions. 00084 00085 virtual G4double ComputeStep(const G4ThreeVector &pGlobalPoint, 00086 const G4ThreeVector &pDirection, 00087 const G4double pCurrentProposedStepLength, 00088 G4double &pNewSafety); 00089 // Calculate the distance to the next boundary intersected 00090 // along the specified NORMALISED vector direction and 00091 // from the specified point in the global coordinate 00092 // system. LocateGlobalPointAndSetup or LocateGlobalPointWithinVolume 00093 // must have been called with the same global point prior to this call. 00094 // The isotropic distance to the nearest boundary is also 00095 // calculated (usually an underestimate). The current 00096 // proposed Step length is used to avoid intersection 00097 // calculations: if it can be determined that the nearest 00098 // boundary is >pCurrentProposedStepLength away, kInfinity 00099 // is returned together with the computed isotropic safety 00100 // distance. Geometry must be closed. 00101 00102 G4double CheckNextStep(const G4ThreeVector &pGlobalPoint, 00103 const G4ThreeVector &pDirection, 00104 const G4double pCurrentProposedStepLength, 00105 G4double &pNewSafety); 00106 // Same as above, but do not disturb the state of the Navigator. 00107 00108 virtual 00109 G4VPhysicalVolume* ResetHierarchyAndLocate(const G4ThreeVector &point, 00110 const G4ThreeVector &direction, 00111 const G4TouchableHistory &h); 00112 00113 // Resets the geometrical hierarchy and search for the volumes deepest 00114 // in the hierarchy containing the point in the global coordinate space. 00115 // The direction is used to check if a volume is entered. 00116 // The search begin is the geometrical hierarchy at the location of the 00117 // last located point, or the endpoint of the previous Step if 00118 // SetGeometricallyLimitedStep() has been called immediately before. 00119 // 00120 // Important Note: In order to call this the geometry MUST be closed. 00121 00122 virtual 00123 G4VPhysicalVolume* LocateGlobalPointAndSetup(const G4ThreeVector& point, 00124 const G4ThreeVector* direction=0, 00125 const G4bool pRelativeSearch=true, 00126 const G4bool ignoreDirection=true); 00127 // Search the geometrical hierarchy for the volumes deepest in the hierarchy 00128 // containing the point in the global coordinate space. Two main cases are: 00129 // i) If pRelativeSearch=false it makes use of no previous/state 00130 // information. Returns the physical volume containing the point, 00131 // with all previous mothers correctly set up. 00132 // ii) If pRelativeSearch is set to true, the search begin is the 00133 // geometrical hierarchy at the location of the last located point, 00134 // or the endpoint of the previous Step if SetGeometricallyLimitedStep() 00135 // has been called immediately before. 00136 // The direction is used (to check if a volume is entered) if either 00137 // - the argument ignoreDirection is false, or 00138 // - the Navigator has determined that it is on an edge shared by two or 00139 // more volumes. (This is state information.) 00140 // 00141 // Important Note: In order to call this the geometry MUST be closed. 00142 00143 virtual 00144 void LocateGlobalPointWithinVolume(const G4ThreeVector& position); 00145 // Notify the Navigator that a track has moved to the new Global point 00146 // 'position', that is known to be within the current safety. 00147 // No check is performed to ensure that it is within the volume. 00148 // This method can be called instead of LocateGlobalPointAndSetup ONLY if 00149 // the caller is certain that the new global point (position) is inside the 00150 // same volume as the previous position. Usually this can be guaranteed 00151 // only if the point is within safety. 00152 00153 inline void LocateGlobalPointAndUpdateTouchableHandle( 00154 const G4ThreeVector& position, 00155 const G4ThreeVector& direction, 00156 G4TouchableHandle& oldTouchableToUpdate, 00157 const G4bool RelativeSearch = true); 00158 // First, search the geometrical hierarchy like the above method 00159 // LocateGlobalPointAndSetup(). Then use the volume found and its 00160 // navigation history to update the touchable. 00161 00162 inline void LocateGlobalPointAndUpdateTouchable( 00163 const G4ThreeVector& position, 00164 const G4ThreeVector& direction, 00165 G4VTouchable* touchableToUpdate, 00166 const G4bool RelativeSearch = true); 00167 // First, search the geometrical hierarchy like the above method 00168 // LocateGlobalPointAndSetup(). Then use the volume found and its 00169 // navigation history to update the touchable. 00170 00171 inline void LocateGlobalPointAndUpdateTouchable( 00172 const G4ThreeVector& position, 00173 G4VTouchable* touchableToUpdate, 00174 const G4bool RelativeSearch = true); 00175 // Same as the method above but missing direction. 00176 00177 inline void SetGeometricallyLimitedStep(); 00178 // Inform the navigator that the previous Step calculated 00179 // by the geometry was taken in its entirety. 00180 00181 virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, 00182 const G4double pProposedMaxLength = DBL_MAX, 00183 const G4bool keepState = true); 00184 // Calculate the isotropic distance to the nearest boundary from the 00185 // specified point in the global coordinate system. 00186 // The globalpoint utilised must be within the current volume. 00187 // The value returned is usually an underestimate. 00188 // The proposed maximum length is used to avoid volume safety 00189 // calculations. The geometry must be closed. 00190 // To ensure minimum side effects from the call, keepState 00191 // must be true. 00192 00193 inline G4VPhysicalVolume* GetWorldVolume() const; 00194 // Return the current world (`topmost') volume. 00195 00196 inline void SetWorldVolume(G4VPhysicalVolume* pWorld); 00197 // Set the world (`topmost') volume. This must be positioned at 00198 // origin (0,0,0) and unrotated. 00199 00200 inline G4GRSVolume* CreateGRSVolume() const; 00201 inline G4GRSSolid* CreateGRSSolid() const; 00202 inline G4TouchableHistory* CreateTouchableHistory() const; 00203 inline G4TouchableHistory* CreateTouchableHistory(const G4NavigationHistory*) const; 00204 // `Touchable' creation methods: caller has deletion responsibility. 00205 00206 virtual G4TouchableHistoryHandle CreateTouchableHistoryHandle() const; 00207 // Returns a reference counted handle to a touchable history. 00208 00209 virtual G4ThreeVector GetLocalExitNormal(G4bool* valid); 00210 virtual G4ThreeVector GetLocalExitNormalAndCheck(const G4ThreeVector& point, 00211 G4bool* valid); 00212 virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector& point, 00213 G4bool* valid); 00214 // Return Exit Surface Normal and validity too. 00215 // Can only be called if the Navigator's last Step has crossed a 00216 // volume geometrical boundary. 00217 // It returns the Normal to the surface pointing out of the volume that 00218 // was left behind and/or into the volume that was entered. 00219 // Convention: 00220 // The *local* normal is in the coordinate system of the *final* volume. 00221 // Restriction: 00222 // Normals are not available for replica volumes (returns valid= false) 00223 // These methods takes full care about how to calculate this normal, 00224 // but if the surfaces are not convex it will return valid=false. 00225 00226 inline G4int GetVerboseLevel() const; 00227 inline void SetVerboseLevel(G4int level); 00228 // Get/Set Verbose(ness) level. 00229 // [if level>0 && G4VERBOSE, printout can occur] 00230 00231 inline G4bool IsActive() const; 00232 // Verify if the navigator is active. 00233 inline void Activate(G4bool flag); 00234 // Activate/inactivate the navigator. 00235 00236 inline G4bool EnteredDaughterVolume() const; 00237 // The purpose of this function is to inform the caller if the track is 00238 // entering a daughter volume while exiting from the current volume. 00239 // This method returns 00240 // - True only in case 1) above, that is when the Step has caused 00241 // the track to arrive at a boundary of a daughter. 00242 // - False in cases 2), 3) and 4), i.e. in all other cases. 00243 // This function is not guaranteed to work if SetGeometricallyLimitedStep() 00244 // was not called when it should have been called. 00245 inline G4bool ExitedMotherVolume() const; 00246 // Verify if the step has exited the mother volume. 00247 00248 inline void CheckMode(G4bool mode); 00249 // Run navigation in "check-mode", therefore using additional 00250 // verifications and more strict correctness conditions. 00251 // Is effective only with G4VERBOSE set. 00252 inline G4bool IsCheckModeActive() const; 00253 inline void SetPushVerbosity(G4bool mode); 00254 // Set/unset verbosity for pushed tracks (default is true). 00255 00256 void PrintState() const; 00257 // Print the internal state of the Navigator (for debugging). 00258 // The level of detail is according to the verbosity. 00259 00260 inline const G4AffineTransform& GetGlobalToLocalTransform() const; 00261 inline const G4AffineTransform GetLocalToGlobalTransform() const; 00262 // Obtain the transformations Global/Local (and inverse). 00263 // Clients of these methods must copy the data if they need to keep it. 00264 00265 G4AffineTransform GetMotherToDaughterTransform(G4VPhysicalVolume* dVolume, 00266 G4int dReplicaNo, 00267 EVolume dVolumeType ); 00268 // Obtain mother to daughter transformation 00269 00270 inline void ResetStackAndState(); 00271 // Reset stack and minimum or navigator state machine necessary for reset 00272 // as needed by LocalGlobalPointAndSetup. 00273 // [Does not perform clears, resizes, or reset fLastLocatedPointLocal] 00274 00275 inline G4int SeverityOfZeroStepping( G4int* noZeroSteps ) const; 00276 // Report on severity of error and number of zero steps, 00277 // in case Navigator is stuck and is returning zero steps. 00278 // Values: 1 (small problem), 5 (correcting), 00279 // 9 (ready to abandon), 10 (abandoned) 00280 00281 inline G4ThreeVector GetCurrentLocalCoordinate() const; 00282 // Return the local coordinate of the point in the reference system 00283 // of its containing volume that was found by LocalGlobalPointAndSetup. 00284 // The local coordinate of the last located track. 00285 00286 inline G4ThreeVector NetTranslation() const; 00287 inline G4RotationMatrix NetRotation() const; 00288 // Compute+return the local->global translation/rotation of current volume. 00289 00290 inline void EnableBestSafety( G4bool value= false ); 00291 // Enable best-possible evaluation of isotropic safety 00292 00293 protected: // with description 00294 00295 void SetSavedState(); 00296 // ( fValidExitNormal, fExitNormal, fExiting, fEntering, 00297 // fBlockedPhysicalVolume, fBlockedReplicaNo, fLastStepWasZero); 00298 // Extended to include: 00299 // ( fLastLocatedPointLocal, fLocatedOutsideWorld; 00300 // fEnteredDaughter, fExitedMother 00301 // fPreviousSftOrigin, sPreviousSafety) Safety Sphere. 00302 00303 void RestoreSavedState(); 00304 // Copy aspects of the state, to enable a non-state changing 00305 // call to ComputeStep(). 00306 00307 virtual void ResetState(); 00308 // Utility method to reset the navigator state machine. 00309 00310 inline G4ThreeVector ComputeLocalPoint(const G4ThreeVector& rGlobPoint) const; 00311 // Return position vector in local coordinate system, given a position 00312 // vector in world coordinate system. 00313 00314 inline G4ThreeVector ComputeLocalAxis(const G4ThreeVector& pVec) const; 00315 // Return the local direction of the specified vector in the reference 00316 // system of the volume that was found by LocalGlobalPointAndSetup. 00317 // The Local Coordinates of point in world coordinate system. 00318 00319 inline EVolume VolumeType(const G4VPhysicalVolume *pVol) const; 00320 // Characterise `type' of volume - normal/replicated/parameterised. 00321 00322 inline EVolume CharacteriseDaughters(const G4LogicalVolume *pLog) const; 00323 // Characterise daughter of logical volume. 00324 00325 inline G4int GetDaughtersRegularStructureId(const G4LogicalVolume *pLog) const; 00326 // Get regular structure ID of first daughter 00327 00328 virtual void SetupHierarchy(); 00329 // Renavigate & reset hierarchy described by current history 00330 // o Reset volumes 00331 // o Recompute transforms and/or solids of replicated/parameterised 00332 // volumes. 00333 00334 private: 00335 00336 void ComputeStepLog(const G4ThreeVector& pGlobalpoint, 00337 G4double moveLenSq) const; 00338 // Log and checks for steps larger than the tolerance 00339 00340 protected: // without description 00341 00342 G4double kCarTolerance; 00343 // Geometrical tolerance for surface thickness of shapes. 00344 00345 // 00346 // BEGIN State information 00347 // 00348 00349 G4NavigationHistory fHistory; 00350 // Transformation and history of the current path 00351 // through the geometrical hierarchy. 00352 00353 G4bool fEnteredDaughter; 00354 // A memory of whether in this Step a daughter volume is entered 00355 // (set in Compute & Locate). 00356 // After Compute: it expects to enter a daughter 00357 // After Locate: it has entered a daughter 00358 00359 G4bool fExitedMother; 00360 // A similar memory whether the Step exited current "mother" volume 00361 // completely, not entering daughter. 00362 00363 G4bool fWasLimitedByGeometry; 00364 // Set true if last Step was limited by geometry. 00365 00366 G4ThreeVector fStepEndPoint; 00367 // Endpoint of last ComputeStep 00368 // can be used for optimisation (e.g. when computing safety). 00369 G4ThreeVector fLastStepEndPointLocal; 00370 // Position of the end-point of the last call to ComputeStep 00371 // in last Local coordinates. 00372 00373 G4int fVerbose; 00374 // Verbose(ness) level [if > 0, printout can occur]. 00375 00376 private: 00377 00378 G4bool fActive; 00379 // States if the navigator is activated or not. 00380 00381 G4bool fLastTriedStepComputation; 00382 // Whether ComputeStep was called since the last call to a Locate method 00383 // Uses: - distinguish parts of state which differ before/after calls 00384 // to ComputeStep or one of the Locate methods; 00385 // - avoid two consecutive calls to compute-step (illegal). 00386 00387 G4bool fEntering,fExiting; 00388 // Entering/Exiting volumes blocking/setup 00389 // o If exiting 00390 // volume ptr & replica number (set & used by Locate..()) 00391 // used for blocking on redescent of geometry 00392 // o If entering 00393 // volume ptr & replica number (set by ComputeStep(),used by 00394 // Locate..()) of volume for `automatic' entry 00395 00396 G4VPhysicalVolume *fBlockedPhysicalVolume; 00397 G4int fBlockedReplicaNo; 00398 00399 G4ThreeVector fLastLocatedPointLocal; 00400 // Position of the last located point relative to its containing volume. 00401 G4bool fLocatedOutsideWorld; 00402 // Whether the last call to Locate methods left the world 00403 00404 G4bool fValidExitNormal; // Set true if have leaving volume normal 00405 G4ThreeVector fExitNormal; // Leaving volume normal, in the 00406 // volume containing the exited 00407 // volume's coordinate system 00408 G4ThreeVector fGrandMotherExitNormal; // Leaving volume normal, in its 00409 // own coordinate system 00410 G4bool fChangedGrandMotherRefFrame; // Whether frame is changed 00411 00412 G4ThreeVector fExitNormalGlobalFrame; // Leaving volume normal, in the 00413 // global coordinate system 00414 G4bool fCalculatedExitNormal; // Has it been computed since 00415 // the last call to ComputeStep 00416 // Covers both Global and GrandMother 00417 00418 // Count zero steps - as one or two can occur due to changing momentum at 00419 // a boundary or at an edge common between volumes 00420 // - several are likely a problem in the geometry 00421 // description or in the navigation 00422 // 00423 G4bool fLastStepWasZero; 00424 // Whether the last ComputeStep moved Zero. Used to check for edges. 00425 00426 G4bool fLocatedOnEdge; 00427 // Whether the Navigator has detected an edge 00428 G4int fNumberZeroSteps; 00429 // Number of preceding moves that were Zero. Reset to 0 after finite step 00430 G4int fActionThreshold_NoZeroSteps; 00431 // After this many failed/zero steps, act (push etc) 00432 G4int fAbandonThreshold_NoZeroSteps; 00433 // After this many failed/zero steps, abandon track 00434 00435 G4ThreeVector fPreviousSftOrigin; 00436 G4double fPreviousSafety; 00437 // Memory of last safety origin & value. Used in ComputeStep to ensure 00438 // that origin of current Step is in the same volume as the point of the 00439 // last relocation 00440 00441 // 00442 // END State information 00443 // 00444 00445 // Save key state information (NOT the navigation history stack) 00446 // 00447 struct G4SaveNavigatorState 00448 { 00449 G4ThreeVector sExitNormal; 00450 G4bool sValidExitNormal; 00451 G4bool sEntering, sExiting; 00452 G4VPhysicalVolume* spBlockedPhysicalVolume; 00453 G4int sBlockedReplicaNo; 00454 G4int sLastStepWasZero; 00455 00456 // Potentially relevant 00457 // 00458 G4bool sLocatedOutsideWorld; 00459 G4ThreeVector sLastLocatedPointLocal; 00460 G4bool sEnteredDaughter, sExitedMother; 00461 G4ThreeVector sPreviousSftOrigin; 00462 G4double sPreviousSafety; 00463 } fSaveState; 00464 00465 // Tracking Invariants 00466 // 00467 G4VPhysicalVolume *fTopPhysical; 00468 // A link to the topmost physical volume in the detector. 00469 // Must be positioned at the origin and unrotated. 00470 00471 // Utility information 00472 // 00473 G4bool fCheck; 00474 // Check-mode flag [if true, more strict checks are performed]. 00475 G4bool fPushed, fWarnPush; 00476 // Push flags [if true, means a stuck particle has been pushed]. 00477 00478 // Helpers/Utility classes 00479 // 00480 G4NormalNavigation fnormalNav; 00481 G4VoxelNavigation fvoxelNav; 00482 G4ParameterisedNavigation fparamNav; 00483 G4ReplicaNavigation freplicaNav; 00484 G4RegularNavigation fregularNav; 00485 }; 00486 00487 #include "G4Navigator.icc" 00488 00489 #endif 00490 00491 00492 // NOTES: 00493 // 00494 // The following methods provide detailed information when a Step has 00495 // arrived at a geometrical boundary. They distinguish between the different 00496 // causes that can result in the track leaving its current volume. 00497 // 00498 // Four cases are possible: 00499 // 00500 // 1) The particle has reached a boundary of a daughter of the current volume: 00501 // (this could cause the relocation to enter the daughter itself 00502 // or a potential granddaughter or further descendant) 00503 // 00504 // 2) The particle has reached a boundary of the current 00505 // volume, exiting into a mother (regardless the level 00506 // at which it is located in the tree): 00507 // 00508 // 3) The particle has reached a boundary of the current 00509 // volume, exiting into a volume which is not in its 00510 // parental hierarchy: 00511 // 00512 // 4) The particle is not on a boundary between volumes: 00513 // the function returns an exception, and the caller is 00514 // reccomended to compare the G4touchables associated 00515 // to the preStepPoint and postStepPoint to handle this case. 00516 // 00517 // G4bool EnteredDaughterVolume() 00518 // G4bool IsExitNormalValid() 00519 // G4ThreeVector GetLocalExitNormal() 00520 // 00521 // The expected usefulness of these methods is to allow the caller to 00522 // determine how to compute the surface normal at the volume boundary. The two 00523 // possibilities are to obtain the normal from: 00524 // 00525 // i) the solid associated with the volume of the initial point of the Step. 00526 // This is valid for cases 2 and 3. 00527 // (Note that the initial point is generally the PreStepPoint of a Step). 00528 // or 00529 // 00530 // ii) the solid of the final point, ie of the volume after the relocation. 00531 // This is valid for case 1. 00532 // (Note that the final point is generally the PreStepPoint of a Step). 00533 // 00534 // This way the caller can always get a valid normal, pointing outside 00535 // the solid for which it is computed, that can be used at his own 00536 // discretion.