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 // Implementation of a custom tracking manager for e-/e+ and gamma, using 27 // the same processes as defined in G4EmStandardPhysics. 28 // 29 // Original author: Jonas Hahnfeld, 2021 30 31 #include "EmStandardPhysicsTrackingManager.hh" 32 33 #include "TrackingManagerHelper.hh" 34 35 #include "G4ComptonScattering.hh" 36 #include "G4CoulombScattering.hh" 37 #include "G4Electron.hh" 38 #include "G4EmParameters.hh" 39 #include "G4Gamma.hh" 40 #include "G4GammaConversion.hh" 41 #include "G4KleinNishinaModel.hh" 42 #include "G4LivermorePhotoElectricModel.hh" 43 #include "G4LivermorePolarizedRayleighModel.hh" 44 #include "G4PhotoElectricAngularGeneratorPolarized.hh" 45 #include "G4PhotoElectricEffect.hh" 46 #include "G4Positron.hh" 47 #include "G4RayleighScattering.hh" 48 #include "G4SystemOfUnits.hh" 49 #include "G4UrbanMscModel.hh" 50 #include "G4WentzelVIModel.hh" 51 #include "G4eBremsstrahlung.hh" 52 #include "G4eCoulombScatteringModel.hh" 53 #include "G4eIonisation.hh" 54 #include "G4eMultipleScattering.hh" 55 #include "G4eplusAnnihilation.hh" 56 57 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 58 59 EmStandardPhysicsTrackingManager* EmStandardPhysicsTrackingManager::fMasterTrackingManager = 60 nullptr; 61 62 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 63 64 EmStandardPhysicsTrackingManager::EmStandardPhysicsTrackingManager() 65 { 66 G4EmParameters* param = G4EmParameters::Instance(); 67 G4double highEnergyLimit = param->MscEnergyLimit(); 68 G4bool polar = param->EnablePolarisation(); 69 70 // e- 71 { 72 G4eMultipleScattering* msc = new G4eMultipleScattering; 73 G4UrbanMscModel* msc1 = new G4UrbanMscModel; 74 G4WentzelVIModel* msc2 = new G4WentzelVIModel; 75 msc1->SetHighEnergyLimit(highEnergyLimit); 76 msc2->SetLowEnergyLimit(highEnergyLimit); 77 msc->SetEmModel(msc1); 78 msc->SetEmModel(msc2); 79 fElectronProcs.msc = msc; 80 81 fElectronProcs.ioni = new G4eIonisation; 82 fElectronProcs.brems = new G4eBremsstrahlung; 83 84 G4CoulombScattering* ss = new G4CoulombScattering; 85 G4eCoulombScatteringModel* ssm = new G4eCoulombScatteringModel; 86 ssm->SetLowEnergyLimit(highEnergyLimit); 87 ssm->SetActivationLowEnergyLimit(highEnergyLimit); 88 ss->SetEmModel(ssm); 89 ss->SetMinKinEnergy(highEnergyLimit); 90 fElectronProcs.ss = ss; 91 } 92 93 // e+ 94 { 95 G4eMultipleScattering* msc = new G4eMultipleScattering; 96 G4UrbanMscModel* msc1 = new G4UrbanMscModel; 97 G4WentzelVIModel* msc2 = new G4WentzelVIModel; 98 msc1->SetHighEnergyLimit(highEnergyLimit); 99 msc2->SetLowEnergyLimit(highEnergyLimit); 100 msc->SetEmModel(msc1); 101 msc->SetEmModel(msc2); 102 fPositronProcs.msc = msc; 103 104 fPositronProcs.ioni = new G4eIonisation; 105 fPositronProcs.brems = new G4eBremsstrahlung; 106 fPositronProcs.annihilation = new G4eplusAnnihilation; 107 108 G4CoulombScattering* ss = new G4CoulombScattering; 109 G4eCoulombScatteringModel* ssm = new G4eCoulombScatteringModel; 110 ssm->SetLowEnergyLimit(highEnergyLimit); 111 ssm->SetActivationLowEnergyLimit(highEnergyLimit); 112 ss->SetEmModel(ssm); 113 ss->SetMinKinEnergy(highEnergyLimit); 114 fPositronProcs.ss = ss; 115 } 116 117 { 118 G4PhotoElectricEffect* pe = new G4PhotoElectricEffect; 119 G4VEmModel* peModel = new G4LivermorePhotoElectricModel; 120 if (polar) { 121 peModel->SetAngularDistribution(new G4PhotoElectricAngularGeneratorPolarized); 122 } 123 pe->SetEmModel(peModel); 124 fGammaProcs.pe = pe; 125 126 G4ComptonScattering* cs = new G4ComptonScattering; 127 if (polar) { 128 cs->SetEmModel(new G4KleinNishinaModel); 129 } 130 fGammaProcs.compton = cs; 131 132 fGammaProcs.conversion = new G4GammaConversion; 133 134 G4RayleighScattering* rl = new G4RayleighScattering; 135 if (polar) { 136 rl->SetEmModel(new G4LivermorePolarizedRayleighModel); 137 } 138 fGammaProcs.rayleigh = rl; 139 } 140 141 if (fMasterTrackingManager == nullptr) { 142 fMasterTrackingManager = this; 143 } 144 else { 145 fElectronProcs.msc->SetMasterProcess(fMasterTrackingManager->fElectronProcs.msc); 146 fElectronProcs.ss->SetMasterProcess(fMasterTrackingManager->fElectronProcs.ss); 147 fElectronProcs.ioni->SetMasterProcess(fMasterTrackingManager->fElectronProcs.ioni); 148 fElectronProcs.brems->SetMasterProcess(fMasterTrackingManager->fElectronProcs.brems); 149 150 fPositronProcs.msc->SetMasterProcess(fMasterTrackingManager->fPositronProcs.msc); 151 fPositronProcs.ss->SetMasterProcess(fMasterTrackingManager->fPositronProcs.ss); 152 fPositronProcs.ioni->SetMasterProcess(fMasterTrackingManager->fPositronProcs.ioni); 153 fPositronProcs.brems->SetMasterProcess(fMasterTrackingManager->fPositronProcs.brems); 154 fPositronProcs.annihilation->SetMasterProcess( 155 fMasterTrackingManager->fPositronProcs.annihilation); 156 157 fGammaProcs.pe->SetMasterProcess(fMasterTrackingManager->fGammaProcs.pe); 158 fGammaProcs.compton->SetMasterProcess(fMasterTrackingManager->fGammaProcs.compton); 159 fGammaProcs.conversion->SetMasterProcess(fMasterTrackingManager->fGammaProcs.conversion); 160 fGammaProcs.rayleigh->SetMasterProcess(fMasterTrackingManager->fGammaProcs.rayleigh); 161 } 162 } 163 164 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 165 166 EmStandardPhysicsTrackingManager::~EmStandardPhysicsTrackingManager() 167 { 168 if (fMasterTrackingManager == this) { 169 fMasterTrackingManager = nullptr; 170 } 171 } 172 173 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 174 175 void EmStandardPhysicsTrackingManager::BuildPhysicsTable(const G4ParticleDefinition& part) 176 { 177 if (&part == G4Electron::Definition()) { 178 fElectronProcs.msc->BuildPhysicsTable(part); 179 fElectronProcs.ioni->BuildPhysicsTable(part); 180 fElectronProcs.brems->BuildPhysicsTable(part); 181 fElectronProcs.ss->BuildPhysicsTable(part); 182 } 183 else if (&part == G4Positron::Definition()) { 184 fPositronProcs.msc->BuildPhysicsTable(part); 185 fPositronProcs.ioni->BuildPhysicsTable(part); 186 fPositronProcs.brems->BuildPhysicsTable(part); 187 fPositronProcs.annihilation->BuildPhysicsTable(part); 188 fPositronProcs.ss->BuildPhysicsTable(part); 189 } 190 else if (&part == G4Gamma::Definition()) { 191 fGammaProcs.pe->BuildPhysicsTable(part); 192 fGammaProcs.compton->BuildPhysicsTable(part); 193 fGammaProcs.conversion->BuildPhysicsTable(part); 194 fGammaProcs.rayleigh->BuildPhysicsTable(part); 195 } 196 } 197 198 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 199 200 void EmStandardPhysicsTrackingManager::PreparePhysicsTable(const G4ParticleDefinition& part) 201 { 202 if (&part == G4Electron::Definition()) { 203 fElectronProcs.msc->PreparePhysicsTable(part); 204 fElectronProcs.ioni->PreparePhysicsTable(part); 205 fElectronProcs.brems->PreparePhysicsTable(part); 206 fElectronProcs.ss->PreparePhysicsTable(part); 207 } 208 else if (&part == G4Positron::Definition()) { 209 fPositronProcs.msc->PreparePhysicsTable(part); 210 fPositronProcs.ioni->PreparePhysicsTable(part); 211 fPositronProcs.brems->PreparePhysicsTable(part); 212 fPositronProcs.annihilation->PreparePhysicsTable(part); 213 fPositronProcs.ss->PreparePhysicsTable(part); 214 } 215 else if (&part == G4Gamma::Definition()) { 216 fGammaProcs.pe->PreparePhysicsTable(part); 217 fGammaProcs.compton->PreparePhysicsTable(part); 218 fGammaProcs.conversion->PreparePhysicsTable(part); 219 fGammaProcs.rayleigh->PreparePhysicsTable(part); 220 } 221 } 222 223 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 224 225 void EmStandardPhysicsTrackingManager::TrackElectron(G4Track* aTrack) 226 { 227 class ElectronPhysics final : public TrackingManagerHelper::Physics 228 { 229 public: 230 ElectronPhysics(EmStandardPhysicsTrackingManager& mgr) : fMgr(mgr) {} 231 232 void StartTracking(G4Track* aTrack) override 233 { 234 auto& electronProcs = fMgr.fElectronProcs; 235 236 electronProcs.msc->StartTracking(aTrack); 237 electronProcs.ioni->StartTracking(aTrack); 238 electronProcs.brems->StartTracking(aTrack); 239 electronProcs.ss->StartTracking(aTrack); 240 241 fPreviousStepLength = 0; 242 } 243 void EndTracking() override 244 { 245 auto& electronProcs = fMgr.fElectronProcs; 246 247 electronProcs.msc->EndTracking(); 248 electronProcs.ioni->EndTracking(); 249 electronProcs.brems->EndTracking(); 250 electronProcs.ss->EndTracking(); 251 } 252 253 G4double GetPhysicalInteractionLength(const G4Track& track) override 254 { 255 auto& electronProcs = fMgr.fElectronProcs; 256 G4double physIntLength, proposedSafety = DBL_MAX; 257 G4ForceCondition condition; 258 G4GPILSelection selection; 259 260 fProposedStep = DBL_MAX; 261 fSelected = -1; 262 263 physIntLength = electronProcs.ss->PostStepGPIL(track, fPreviousStepLength, &condition); 264 if (physIntLength < fProposedStep) { 265 fProposedStep = physIntLength; 266 fSelected = 0; 267 } 268 269 physIntLength = electronProcs.brems->PostStepGPIL(track, fPreviousStepLength, &condition); 270 if (physIntLength < fProposedStep) { 271 fProposedStep = physIntLength; 272 fSelected = 1; 273 } 274 275 physIntLength = electronProcs.ioni->PostStepGPIL(track, fPreviousStepLength, &condition); 276 if (physIntLength < fProposedStep) { 277 fProposedStep = physIntLength; 278 fSelected = 2; 279 } 280 281 physIntLength = electronProcs.ioni->AlongStepGPIL(track, fPreviousStepLength, fProposedStep, 282 proposedSafety, &selection); 283 if (physIntLength < fProposedStep) { 284 fProposedStep = physIntLength; 285 fSelected = -1; 286 } 287 288 physIntLength = electronProcs.msc->AlongStepGPIL(track, fPreviousStepLength, fProposedStep, 289 proposedSafety, &selection); 290 if (physIntLength < fProposedStep) { 291 fProposedStep = physIntLength; 292 // Check if MSC actually wants to win, in most cases it only limits the 293 // step size. 294 if (selection == CandidateForSelection) { 295 fSelected = -1; 296 } 297 } 298 299 return fProposedStep; 300 } 301 302 void AlongStepDoIt(G4Track& track, G4Step& step, G4TrackVector&) override 303 { 304 if (step.GetStepLength() == fProposedStep) { 305 step.GetPostStepPoint()->SetStepStatus(fAlongStepDoItProc); 306 } 307 else { 308 // Remember that the step was limited by geometry. 309 fSelected = -1; 310 } 311 auto& electronProcs = fMgr.fElectronProcs; 312 G4VParticleChange* particleChange; 313 314 particleChange = electronProcs.msc->AlongStepDoIt(track, step); 315 particleChange->UpdateStepForAlongStep(&step); 316 track.SetTrackStatus(particleChange->GetTrackStatus()); 317 particleChange->Clear(); 318 319 particleChange = electronProcs.ioni->AlongStepDoIt(track, step); 320 particleChange->UpdateStepForAlongStep(&step); 321 track.SetTrackStatus(particleChange->GetTrackStatus()); 322 particleChange->Clear(); 323 324 fPreviousStepLength = step.GetStepLength(); 325 } 326 327 void PostStepDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override 328 { 329 if (fSelected < 0) { 330 return; 331 } 332 step.GetPostStepPoint()->SetStepStatus(fPostStepDoItProc); 333 334 auto& electronProcs = fMgr.fElectronProcs; 335 G4VProcess* process = nullptr; 336 G4VParticleChange* particleChange = nullptr; 337 338 switch (fSelected) { 339 case 0: 340 process = electronProcs.ss; 341 particleChange = electronProcs.ss->PostStepDoIt(track, step); 342 break; 343 case 1: 344 process = electronProcs.brems; 345 particleChange = electronProcs.brems->PostStepDoIt(track, step); 346 break; 347 case 2: 348 process = electronProcs.ioni; 349 particleChange = electronProcs.ioni->PostStepDoIt(track, step); 350 break; 351 } 352 353 particleChange->UpdateStepForPostStep(&step); 354 step.UpdateTrack(); 355 356 G4int numSecondaries = particleChange->GetNumberOfSecondaries(); 357 for (G4int i = 0; i < numSecondaries; ++i) { 358 G4Track* secondary = particleChange->GetSecondary(i); 359 secondary->SetParentID(track.GetTrackID()); 360 secondary->SetCreatorProcess(process); 361 secondaries.push_back(secondary); 362 } 363 364 track.SetTrackStatus(particleChange->GetTrackStatus()); 365 particleChange->Clear(); 366 } 367 368 private: 369 EmStandardPhysicsTrackingManager& fMgr; 370 G4double fPreviousStepLength; 371 G4double fProposedStep; 372 G4int fSelected; 373 }; 374 375 ElectronPhysics physics(*this); 376 TrackingManagerHelper::TrackChargedParticle(aTrack, physics); 377 } 378 379 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 380 381 void EmStandardPhysicsTrackingManager::TrackPositron(G4Track* aTrack) 382 { 383 class PositronPhysics final : public TrackingManagerHelper::Physics 384 { 385 public: 386 PositronPhysics(EmStandardPhysicsTrackingManager& mgr) : fMgr(mgr) {} 387 388 void StartTracking(G4Track* aTrack) override 389 { 390 auto& positronProcs = fMgr.fPositronProcs; 391 392 positronProcs.msc->StartTracking(aTrack); 393 positronProcs.ioni->StartTracking(aTrack); 394 positronProcs.brems->StartTracking(aTrack); 395 positronProcs.annihilation->StartTracking(aTrack); 396 positronProcs.ss->StartTracking(aTrack); 397 398 fPreviousStepLength = 0; 399 } 400 void EndTracking() override 401 { 402 auto& positronProcs = fMgr.fPositronProcs; 403 404 positronProcs.msc->EndTracking(); 405 positronProcs.ioni->EndTracking(); 406 positronProcs.brems->EndTracking(); 407 positronProcs.annihilation->EndTracking(); 408 positronProcs.ss->EndTracking(); 409 } 410 411 G4double GetPhysicalInteractionLength(const G4Track& track) override 412 { 413 auto& positronProcs = fMgr.fPositronProcs; 414 G4double physIntLength, proposedSafety = DBL_MAX; 415 G4ForceCondition condition; 416 G4GPILSelection selection; 417 418 fProposedStep = DBL_MAX; 419 fSelected = -1; 420 421 physIntLength = positronProcs.ss->PostStepGPIL(track, fPreviousStepLength, &condition); 422 if (physIntLength < fProposedStep) { 423 fProposedStep = physIntLength; 424 fSelected = 0; 425 } 426 427 physIntLength = 428 positronProcs.annihilation->PostStepGPIL(track, fPreviousStepLength, &condition); 429 if (physIntLength < fProposedStep) { 430 fProposedStep = physIntLength; 431 fSelected = 1; 432 } 433 434 physIntLength = positronProcs.brems->PostStepGPIL(track, fPreviousStepLength, &condition); 435 if (physIntLength < fProposedStep) { 436 fProposedStep = physIntLength; 437 fSelected = 2; 438 } 439 440 physIntLength = positronProcs.ioni->PostStepGPIL(track, fPreviousStepLength, &condition); 441 if (physIntLength < fProposedStep) { 442 fProposedStep = physIntLength; 443 fSelected = 3; 444 } 445 446 physIntLength = positronProcs.ioni->AlongStepGPIL(track, fPreviousStepLength, fProposedStep, 447 proposedSafety, &selection); 448 if (physIntLength < fProposedStep) { 449 fProposedStep = physIntLength; 450 fSelected = -1; 451 } 452 453 physIntLength = positronProcs.msc->AlongStepGPIL(track, fPreviousStepLength, fProposedStep, 454 proposedSafety, &selection); 455 if (physIntLength < fProposedStep) { 456 fProposedStep = physIntLength; 457 // Check if MSC actually wants to win, in most cases it only limits the 458 // step size. 459 if (selection == CandidateForSelection) { 460 fSelected = -1; 461 } 462 } 463 464 return fProposedStep; 465 } 466 467 void AlongStepDoIt(G4Track& track, G4Step& step, G4TrackVector&) override 468 { 469 if (step.GetStepLength() == fProposedStep) { 470 step.GetPostStepPoint()->SetStepStatus(fAlongStepDoItProc); 471 } 472 else { 473 // Remember that the step was limited by geometry. 474 fSelected = -1; 475 } 476 auto& positronProcs = fMgr.fPositronProcs; 477 G4VParticleChange* particleChange; 478 479 particleChange = positronProcs.msc->AlongStepDoIt(track, step); 480 particleChange->UpdateStepForAlongStep(&step); 481 track.SetTrackStatus(particleChange->GetTrackStatus()); 482 particleChange->Clear(); 483 484 particleChange = positronProcs.ioni->AlongStepDoIt(track, step); 485 particleChange->UpdateStepForAlongStep(&step); 486 track.SetTrackStatus(particleChange->GetTrackStatus()); 487 particleChange->Clear(); 488 489 fPreviousStepLength = step.GetStepLength(); 490 } 491 492 void PostStepDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override 493 { 494 if (fSelected < 0) { 495 return; 496 } 497 step.GetPostStepPoint()->SetStepStatus(fPostStepDoItProc); 498 499 auto& positronProcs = fMgr.fPositronProcs; 500 G4VProcess* process = nullptr; 501 G4VParticleChange* particleChange = nullptr; 502 503 switch (fSelected) { 504 case 0: 505 process = positronProcs.ss; 506 particleChange = positronProcs.ss->PostStepDoIt(track, step); 507 break; 508 case 1: 509 process = positronProcs.annihilation; 510 particleChange = positronProcs.annihilation->PostStepDoIt(track, step); 511 break; 512 case 2: 513 process = positronProcs.brems; 514 particleChange = positronProcs.brems->PostStepDoIt(track, step); 515 break; 516 case 3: 517 process = positronProcs.ioni; 518 particleChange = positronProcs.ioni->PostStepDoIt(track, step); 519 break; 520 } 521 522 particleChange->UpdateStepForPostStep(&step); 523 step.UpdateTrack(); 524 525 G4int numSecondaries = particleChange->GetNumberOfSecondaries(); 526 for (G4int i = 0; i < numSecondaries; ++i) { 527 G4Track* secondary = particleChange->GetSecondary(i); 528 secondary->SetParentID(track.GetTrackID()); 529 secondary->SetCreatorProcess(process); 530 secondaries.push_back(secondary); 531 } 532 533 track.SetTrackStatus(particleChange->GetTrackStatus()); 534 particleChange->Clear(); 535 } 536 537 G4bool HasAtRestProcesses() override { return true; } 538 539 void AtRestDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override 540 { 541 auto& positronProcs = fMgr.fPositronProcs; 542 // Annihilate the positron at rest. 543 G4VParticleChange* particleChange = positronProcs.annihilation->AtRestDoIt(track, step); 544 particleChange->UpdateStepForAtRest(&step); 545 step.UpdateTrack(); 546 547 G4int numSecondaries = particleChange->GetNumberOfSecondaries(); 548 for (G4int i = 0; i < numSecondaries; ++i) { 549 G4Track* secondary = particleChange->GetSecondary(i); 550 secondary->SetParentID(track.GetTrackID()); 551 secondary->SetCreatorProcess(positronProcs.annihilation); 552 secondaries.push_back(secondary); 553 } 554 555 track.SetTrackStatus(particleChange->GetTrackStatus()); 556 particleChange->Clear(); 557 } 558 559 private: 560 EmStandardPhysicsTrackingManager& fMgr; 561 G4double fPreviousStepLength; 562 G4double fProposedStep; 563 G4int fSelected; 564 }; 565 566 PositronPhysics physics(*this); 567 TrackingManagerHelper::TrackChargedParticle(aTrack, physics); 568 } 569 570 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 571 572 void EmStandardPhysicsTrackingManager::TrackGamma(G4Track* aTrack) 573 { 574 class GammaPhysics final : public TrackingManagerHelper::Physics 575 { 576 public: 577 GammaPhysics(EmStandardPhysicsTrackingManager& mgr) : fMgr(mgr) {} 578 579 void StartTracking(G4Track* aTrack) override 580 { 581 auto& gammaProcs = fMgr.fGammaProcs; 582 583 gammaProcs.pe->StartTracking(aTrack); 584 gammaProcs.compton->StartTracking(aTrack); 585 gammaProcs.conversion->StartTracking(aTrack); 586 gammaProcs.rayleigh->StartTracking(aTrack); 587 588 fPreviousStepLength = 0; 589 } 590 void EndTracking() override 591 { 592 auto& gammaProcs = fMgr.fGammaProcs; 593 594 gammaProcs.pe->EndTracking(); 595 gammaProcs.compton->EndTracking(); 596 gammaProcs.conversion->EndTracking(); 597 gammaProcs.rayleigh->EndTracking(); 598 } 599 600 G4double GetPhysicalInteractionLength(const G4Track& track) override 601 { 602 auto& gammaProcs = fMgr.fGammaProcs; 603 G4double physIntLength; 604 G4ForceCondition condition; 605 606 fProposedStep = DBL_MAX; 607 fSelected = -1; 608 609 physIntLength = gammaProcs.rayleigh->PostStepGPIL(track, fPreviousStepLength, &condition); 610 if (physIntLength < fProposedStep) { 611 fProposedStep = physIntLength; 612 fSelected = 0; 613 } 614 615 physIntLength = gammaProcs.conversion->PostStepGPIL(track, fPreviousStepLength, &condition); 616 if (physIntLength < fProposedStep) { 617 fProposedStep = physIntLength; 618 fSelected = 1; 619 } 620 621 physIntLength = gammaProcs.compton->PostStepGPIL(track, fPreviousStepLength, &condition); 622 if (physIntLength < fProposedStep) { 623 fProposedStep = physIntLength; 624 fSelected = 2; 625 } 626 627 physIntLength = gammaProcs.pe->PostStepGPIL(track, fPreviousStepLength, &condition); 628 if (physIntLength < fProposedStep) { 629 fProposedStep = physIntLength; 630 fSelected = 3; 631 } 632 633 return fProposedStep; 634 } 635 636 void AlongStepDoIt(G4Track&, G4Step& step, G4TrackVector&) override 637 { 638 if (step.GetStepLength() == fProposedStep) { 639 step.GetPostStepPoint()->SetStepStatus(fAlongStepDoItProc); 640 } 641 else { 642 // Remember that the step was limited by geometry. 643 fSelected = -1; 644 } 645 fPreviousStepLength = step.GetStepLength(); 646 } 647 648 void PostStepDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override 649 { 650 if (fSelected < 0) { 651 return; 652 } 653 step.GetPostStepPoint()->SetStepStatus(fPostStepDoItProc); 654 655 auto& gammaProcs = fMgr.fGammaProcs; 656 G4VProcess* process = nullptr; 657 G4VParticleChange* particleChange = nullptr; 658 659 switch (fSelected) { 660 case 0: 661 process = gammaProcs.rayleigh; 662 particleChange = gammaProcs.rayleigh->PostStepDoIt(track, step); 663 break; 664 case 1: 665 process = gammaProcs.conversion; 666 particleChange = gammaProcs.conversion->PostStepDoIt(track, step); 667 break; 668 case 2: 669 process = gammaProcs.compton; 670 particleChange = gammaProcs.compton->PostStepDoIt(track, step); 671 break; 672 case 3: 673 process = gammaProcs.pe; 674 particleChange = gammaProcs.pe->PostStepDoIt(track, step); 675 break; 676 } 677 678 particleChange->UpdateStepForPostStep(&step); 679 step.UpdateTrack(); 680 681 G4int numSecondaries = particleChange->GetNumberOfSecondaries(); 682 for (G4int i = 0; i < numSecondaries; ++i) { 683 G4Track* secondary = particleChange->GetSecondary(i); 684 secondary->SetParentID(track.GetTrackID()); 685 secondary->SetCreatorProcess(process); 686 secondaries.push_back(secondary); 687 } 688 689 track.SetTrackStatus(particleChange->GetTrackStatus()); 690 particleChange->Clear(); 691 } 692 693 private: 694 EmStandardPhysicsTrackingManager& fMgr; 695 G4double fPreviousStepLength; 696 G4double fProposedStep; 697 G4int fSelected; 698 }; 699 700 GammaPhysics physics(*this); 701 TrackingManagerHelper::TrackNeutralParticle(aTrack, physics); 702 } 703 704 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 705 706 void EmStandardPhysicsTrackingManager::HandOverOneTrack(G4Track* aTrack) 707 { 708 const G4ParticleDefinition* part = aTrack->GetParticleDefinition(); 709 710 if (part == G4Electron::Definition()) { 711 TrackElectron(aTrack); 712 } 713 else if (part == G4Positron::Definition()) { 714 TrackPositron(aTrack); 715 } 716 else if (part == G4Gamma::Definition()) { 717 TrackGamma(aTrack); 718 } 719 720 aTrack->SetTrackStatus(fStopAndKill); 721 delete aTrack; 722 } 723 724 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 725