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 // 28 // 29 //--------------------------------------------------------------- 30 // 31 // G4FastSimulationProcess.cc 32 // 33 // Description: 34 // The process that triggers the parameterised simulations, 35 // if any. 36 // 37 // History: 38 // August 97: First implementation. Verderi && MoraDeFreitas. 39 // October 06: move to parallel geometry scheme, M. Verderi 40 //--------------------------------------------------------------- 41 42 #include "G4FastSimulationManagerProcess.hh" 43 44 #include "G4FieldTrackUpdator.hh" 45 #include "G4GlobalFastSimulationManager.hh" 46 #include "G4ParticleChange.hh" 47 #include "G4PathFinder.hh" 48 #include "G4TransportationManager.hh" 49 #include "G4ios.hh" 50 51 G4FastSimulationManagerProcess::G4FastSimulationManagerProcess(const G4String& processName, 52 G4ProcessType theType) 53 : G4VProcess(processName, theType), 54 fWorldVolume(nullptr), 55 fIsTrackingTime(false), 56 fIsFirstStep(false), 57 fGhostNavigator(nullptr), 58 fGhostNavigatorIndex(-1), 59 fIsGhostGeometry(false), 60 fGhostSafety(-1.0), 61 fFieldTrack('0'), 62 fFastSimulationManager(nullptr), 63 fFastSimulationTrigger(false) 64 { 65 // -- set Process Sub Type 66 SetProcessSubType(static_cast<int>(FASTSIM_ManagerProcess)); 67 68 fPathFinder = G4PathFinder::GetInstance(); 69 fTransportationManager = G4TransportationManager::GetTransportationManager(); 70 71 SetWorldVolume(fTransportationManager->GetNavigatorForTracking()->GetWorldVolume()->GetName()); 72 if (verboseLevel > 0) 73 G4cout << "G4FastSimulationManagerProcess `" << GetProcessName() 74 << "' is created, and will message geometry with world volume `" 75 << fWorldVolume->GetName() << "'." << G4endl; 76 G4GlobalFastSimulationManager::GetGlobalFastSimulationManager()->AddFSMP(this); 77 } 78 79 G4FastSimulationManagerProcess::G4FastSimulationManagerProcess(const G4String& processName, 80 const G4String& worldVolumeName, 81 G4ProcessType theType) 82 : G4VProcess(processName, theType), 83 fWorldVolume(nullptr), 84 fIsTrackingTime(false), 85 fIsFirstStep(false), 86 fGhostNavigator(nullptr), 87 fGhostNavigatorIndex(-1), 88 fIsGhostGeometry(false), 89 fGhostSafety(-1.0), 90 fFieldTrack('0'), 91 fFastSimulationManager(nullptr), 92 fFastSimulationTrigger(false) 93 { 94 // -- set Process Sub Type 95 SetProcessSubType(static_cast<int>(FASTSIM_ManagerProcess)); 96 97 fPathFinder = G4PathFinder::GetInstance(); 98 fTransportationManager = G4TransportationManager::GetTransportationManager(); 99 100 SetWorldVolume(worldVolumeName); 101 if (verboseLevel > 0) 102 G4cout << "G4FastSimulationManagerProcess `" << GetProcessName() 103 << "' is created, and will message geometry with world volume `" 104 << fWorldVolume->GetName() << "'." << G4endl; 105 G4GlobalFastSimulationManager::GetGlobalFastSimulationManager()->AddFSMP(this); 106 } 107 108 G4FastSimulationManagerProcess::G4FastSimulationManagerProcess(const G4String& processName, 109 G4VPhysicalVolume* worldVolume, 110 G4ProcessType theType) 111 : G4VProcess(processName, theType), 112 fWorldVolume(nullptr), 113 fIsTrackingTime(false), 114 fIsFirstStep(false), 115 fGhostNavigator(nullptr), 116 fGhostNavigatorIndex(-1), 117 fIsGhostGeometry(false), 118 fGhostSafety(-1.0), 119 fFieldTrack('0'), 120 fFastSimulationManager(nullptr), 121 fFastSimulationTrigger(false) 122 { 123 // -- set Process Sub Type 124 SetProcessSubType(static_cast<int>(FASTSIM_ManagerProcess)); 125 126 fPathFinder = G4PathFinder::GetInstance(); 127 fTransportationManager = G4TransportationManager::GetTransportationManager(); 128 129 SetWorldVolume(worldVolume); 130 if (verboseLevel > 0) 131 G4cout << "G4FastSimulationManagerProcess `" << GetProcessName() 132 << "' is created, and will message geometry with world volume `" 133 << fWorldVolume->GetName() << "'." << G4endl; 134 G4GlobalFastSimulationManager::GetGlobalFastSimulationManager()->AddFSMP(this); 135 } 136 137 G4FastSimulationManagerProcess::~G4FastSimulationManagerProcess() 138 { 139 G4GlobalFastSimulationManager::GetGlobalFastSimulationManager()->RemoveFSMP(this); 140 } 141 142 // ----------------------- 143 // User access methods: 144 // ----------------------- 145 void G4FastSimulationManagerProcess::SetWorldVolume(G4String newWorldName) 146 { 147 if (fIsTrackingTime) { 148 G4ExceptionDescription ed; 149 ed << "G4FastSimulationManagerProcess `" << GetProcessName() 150 << "': changing of world volume at tracking time is not allowed." << G4endl; 151 G4Exception("G4FastSimulationManagerProcess::SetWorldVolume(const G4String)", "FastSim002", 152 JustWarning, ed, "Call ignored."); 153 } 154 else { 155 G4VPhysicalVolume* newWorld = fTransportationManager->IsWorldExisting(newWorldName); 156 if (newWorld == nullptr) { 157 G4ExceptionDescription tellWhatIsWrong; 158 tellWhatIsWrong << "Volume newWorldName = `" << newWorldName 159 << "' is not a parallel world nor the mass world volume." << G4endl; 160 G4Exception("G4FastSimulationManagerProcess::SetWorldVolume(const G4String)", "FastSim003", 161 FatalException, tellWhatIsWrong); 162 } 163 if (verboseLevel > 0) { 164 if (fWorldVolume != nullptr) 165 G4cout << "G4FastSimulationManagerProcess `" << GetProcessName() 166 << "': changing world volume from '" << fWorldVolume->GetName() << "' to `" 167 << newWorld << "'." << G4endl; 168 else 169 G4cout << "G4FastSimulationManagerProcess `" << GetProcessName() 170 << "': setting world volume from to `" << newWorld->GetName() << "'." << G4endl; 171 } 172 fWorldVolume = newWorld; 173 } 174 } 175 176 void G4FastSimulationManagerProcess::SetWorldVolume(G4VPhysicalVolume* newWorld) 177 { 178 if (newWorld != nullptr) 179 SetWorldVolume(newWorld->GetName()); 180 else { 181 G4ExceptionDescription tellWhatIsWrong; 182 tellWhatIsWrong << "Null pointer passed for world volume." << G4endl; 183 G4Exception("G4FastSimulationManagerProcess::SetWorldVolume(const G4VPhysicalVolume* newWorld)", 184 "FastSim004", FatalException, tellWhatIsWrong); 185 } 186 } 187 188 // -------------------- 189 // Start/End tracking: 190 // -------------------- 191 void G4FastSimulationManagerProcess::StartTracking(G4Track* track) 192 { 193 fIsTrackingTime = true; 194 fIsFirstStep = true; 195 196 // -- fetch the navigator (and its index) and activate it: 197 G4TransportationManager* transportationManager = 198 G4TransportationManager::GetTransportationManager(); 199 fGhostNavigator = transportationManager->GetNavigator(fWorldVolume); 200 fIsGhostGeometry = (fGhostNavigator != transportationManager->GetNavigatorForTracking()); 201 if (fIsGhostGeometry) 202 fGhostNavigatorIndex = transportationManager->ActivateNavigator(fGhostNavigator); 203 else 204 fGhostNavigatorIndex = -1; 205 206 fPathFinder->PrepareNewTrack(track->GetPosition(), track->GetMomentumDirection()); 207 } 208 209 void G4FastSimulationManagerProcess::EndTracking() 210 { 211 fIsTrackingTime = false; 212 if (fIsGhostGeometry) fTransportationManager->DeActivateNavigator(fGhostNavigator); 213 } 214 215 // ------------------------------------------ 216 // PostStepGetPhysicalInteractionLength(): 217 // ------------------------------------------ 218 G4double 219 G4FastSimulationManagerProcess::PostStepGetPhysicalInteractionLength(const G4Track& track, G4double, 220 G4ForceCondition* condition) 221 { 222 // -- Get current volume, and check for presence of fast simulation manager. 223 // -- For the case of the navigator for tracking (fGhostNavigatorIndex == 0) 224 // -- we use the track volume. This allows the code to be valid for both 225 // -- cases where the PathFinder is used (G4CoupledTranportation) or not 226 // -- (G4Transportation). 227 const G4VPhysicalVolume* currentVolume(nullptr); 228 if (fIsGhostGeometry) 229 currentVolume = fPathFinder->GetLocatedVolume(fGhostNavigatorIndex); 230 else 231 currentVolume = track.GetVolume(); 232 233 if (currentVolume != nullptr) { 234 fFastSimulationManager = currentVolume->GetLogicalVolume()->GetFastSimulationManager(); 235 if (fFastSimulationManager != nullptr) { 236 // Ask for trigger: 237 fFastSimulationTrigger = 238 fFastSimulationManager->PostStepGetFastSimulationManagerTrigger(track, fGhostNavigator); 239 if (fFastSimulationTrigger) { 240 // Take control over stepping: 241 *condition = ExclusivelyForced; 242 return 0.0; 243 } 244 } 245 } 246 247 // -- no fast simulation occuring there: 248 *condition = NotForced; 249 return DBL_MAX; 250 } 251 252 //------------------------------------ 253 // PostStepDoIt() 254 //------------------------------------ 255 G4VParticleChange* G4FastSimulationManagerProcess::PostStepDoIt(const G4Track&, const G4Step&) 256 { 257 G4VParticleChange* finalState = fFastSimulationManager->InvokePostStepDoIt(); 258 259 // If the particle is still alive, suspend it to force physics re-initialisation: 260 if (finalState->GetTrackStatus() != fStopAndKill) finalState->ProposeTrackStatus(fSuspend); 261 262 return finalState; 263 } 264 265 G4double G4FastSimulationManagerProcess::AlongStepGetPhysicalInteractionLength( 266 const G4Track& track, G4double previousStepSize, G4double currentMinimumStep, 267 G4double& proposedSafety, G4GPILSelection* selection) 268 { 269 *selection = NotCandidateForSelection; 270 G4double returnedStep = DBL_MAX; 271 272 // --------------------------------------------------- 273 // -- Below code valid for ghost geometry, otherwise 274 // -- useless for fast simulation attached to mass 275 // -- geometry. Warn user in case along used for 276 // -- mass geometry ? 277 // -------------------------------------------------- 278 if (fIsGhostGeometry) { 279 static G4ThreadLocal G4FieldTrack* endTrack_G4MT_TLS_ = nullptr; 280 if (endTrack_G4MT_TLS_ == nullptr) endTrack_G4MT_TLS_ = new G4FieldTrack('0'); 281 G4FieldTrack& endTrack = *endTrack_G4MT_TLS_; 282 283 static G4ThreadLocal ELimited* eLimited_G4MT_TLS_ = nullptr; 284 if (eLimited_G4MT_TLS_ == nullptr) eLimited_G4MT_TLS_ = new ELimited; 285 ELimited& eLimited = *eLimited_G4MT_TLS_; 286 287 if (previousStepSize > 0.) fGhostSafety -= previousStepSize; 288 if (fGhostSafety < 0.) fGhostSafety = 0.0; 289 290 // ------------------------------------------ 291 // Determination of the proposed step length: 292 // ------------------------------------------ 293 if (currentMinimumStep <= fGhostSafety && currentMinimumStep > 0.) { 294 // -- No chance to limit the step, as proposed move inside safety 295 returnedStep = currentMinimumStep; 296 proposedSafety = fGhostSafety - currentMinimumStep; 297 } 298 else { 299 // -- Proposed move exceeds safety, need to state 300 G4FieldTrackUpdator::Update(&fFieldTrack, &track); 301 returnedStep = fPathFinder->ComputeStep(fFieldTrack, currentMinimumStep, fGhostNavigatorIndex, 302 track.GetCurrentStepNumber(), fGhostSafety, eLimited, 303 endTrack, track.GetVolume()); 304 305 if (eLimited == kDoNot) 306 fGhostSafety = 307 fGhostNavigator->ComputeSafety(endTrack.GetPosition()); // -- step no limited by ghost 308 proposedSafety = fGhostSafety; 309 if (eLimited == kUnique || eLimited == kSharedOther) 310 *selection = CandidateForSelection; 311 else if (eLimited == kSharedTransport) 312 returnedStep *= 313 (1.0 + 1.0e-9); // -- Expand to disable its selection in Step Manager comparison 314 } 315 } 316 317 // ---------------------------------------------- 318 // Returns the fGhostSafety as the proposedSafety 319 // The SteppingManager will take care of keeping 320 // the smallest one. 321 // ---------------------------------------------- 322 return returnedStep; 323 } 324 325 G4VParticleChange* G4FastSimulationManagerProcess::AlongStepDoIt(const G4Track& track, 326 const G4Step&) 327 { 328 fDummyParticleChange.Initialize(track); 329 return &fDummyParticleChange; 330 } 331 332 //-------------------------------------------- 333 // At Rest parameterisation: 334 //-------------------------------------------- 335 // AtRestGetPhysiscalInteractionLength: 336 //-------------------------------------------- 337 G4double 338 G4FastSimulationManagerProcess::AtRestGetPhysicalInteractionLength(const G4Track& track, 339 G4ForceCondition* condition) 340 { 341 const G4VPhysicalVolume* currentVolume(nullptr); 342 if (fIsGhostGeometry) 343 currentVolume = fPathFinder->GetLocatedVolume(fGhostNavigatorIndex); 344 else 345 currentVolume = track.GetVolume(); 346 fFastSimulationManager = currentVolume->GetLogicalVolume()->GetFastSimulationManager(); 347 if (fFastSimulationManager != nullptr) { 348 // Ask for trigger: 349 fFastSimulationTrigger = 350 fFastSimulationManager->AtRestGetFastSimulationManagerTrigger(track, fGhostNavigator); 351 if (fFastSimulationTrigger) { 352 // Dirty trick to take control over stepping. Does anyone will ever use that ? 353 *condition = NotForced; 354 return -1.0; 355 } 356 } 357 358 // -- no fast simulation occuring there: 359 *condition = NotForced; 360 return DBL_MAX; 361 } 362 363 //----------------------------------------------- 364 // AtRestDoIt: 365 //----------------------------------------------- 366 G4VParticleChange* G4FastSimulationManagerProcess::AtRestDoIt(const G4Track&, const G4Step&) 367 { 368 return fFastSimulationManager->InvokeAtRestDoIt(); 369 } 370