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