Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:22:47

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // Implementation of a custom tracking manager for e-/e+ and gamma, using
0027 // the same processes as defined in G4EmStandardPhysics.
0028 //
0029 // Original author: Jonas Hahnfeld, 2021
0030 
0031 #include "EmStandardPhysicsTrackingManager.hh"
0032 
0033 #include "TrackingManagerHelper.hh"
0034 
0035 #include "G4ComptonScattering.hh"
0036 #include "G4CoulombScattering.hh"
0037 #include "G4Electron.hh"
0038 #include "G4EmParameters.hh"
0039 #include "G4Gamma.hh"
0040 #include "G4GammaConversion.hh"
0041 #include "G4KleinNishinaModel.hh"
0042 #include "G4LivermorePhotoElectricModel.hh"
0043 #include "G4LivermorePolarizedRayleighModel.hh"
0044 #include "G4PhotoElectricAngularGeneratorPolarized.hh"
0045 #include "G4PhotoElectricEffect.hh"
0046 #include "G4Positron.hh"
0047 #include "G4RayleighScattering.hh"
0048 #include "G4SystemOfUnits.hh"
0049 #include "G4UrbanMscModel.hh"
0050 #include "G4WentzelVIModel.hh"
0051 #include "G4eBremsstrahlung.hh"
0052 #include "G4eCoulombScatteringModel.hh"
0053 #include "G4eIonisation.hh"
0054 #include "G4eMultipleScattering.hh"
0055 #include "G4eplusAnnihilation.hh"
0056 
0057 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0058 
0059 EmStandardPhysicsTrackingManager* EmStandardPhysicsTrackingManager::fMasterTrackingManager =
0060   nullptr;
0061 
0062 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0063 
0064 EmStandardPhysicsTrackingManager::EmStandardPhysicsTrackingManager()
0065 {
0066   G4EmParameters* param = G4EmParameters::Instance();
0067   G4double highEnergyLimit = param->MscEnergyLimit();
0068   G4bool polar = param->EnablePolarisation();
0069 
0070   // e-
0071   {
0072     G4eMultipleScattering* msc = new G4eMultipleScattering;
0073     G4UrbanMscModel* msc1 = new G4UrbanMscModel;
0074     G4WentzelVIModel* msc2 = new G4WentzelVIModel;
0075     msc1->SetHighEnergyLimit(highEnergyLimit);
0076     msc2->SetLowEnergyLimit(highEnergyLimit);
0077     msc->SetEmModel(msc1);
0078     msc->SetEmModel(msc2);
0079     fElectronProcs.msc = msc;
0080 
0081     fElectronProcs.ioni = new G4eIonisation;
0082     fElectronProcs.brems = new G4eBremsstrahlung;
0083 
0084     G4CoulombScattering* ss = new G4CoulombScattering;
0085     G4eCoulombScatteringModel* ssm = new G4eCoulombScatteringModel;
0086     ssm->SetLowEnergyLimit(highEnergyLimit);
0087     ssm->SetActivationLowEnergyLimit(highEnergyLimit);
0088     ss->SetEmModel(ssm);
0089     ss->SetMinKinEnergy(highEnergyLimit);
0090     fElectronProcs.ss = ss;
0091   }
0092 
0093   // e+
0094   {
0095     G4eMultipleScattering* msc = new G4eMultipleScattering;
0096     G4UrbanMscModel* msc1 = new G4UrbanMscModel;
0097     G4WentzelVIModel* msc2 = new G4WentzelVIModel;
0098     msc1->SetHighEnergyLimit(highEnergyLimit);
0099     msc2->SetLowEnergyLimit(highEnergyLimit);
0100     msc->SetEmModel(msc1);
0101     msc->SetEmModel(msc2);
0102     fPositronProcs.msc = msc;
0103 
0104     fPositronProcs.ioni = new G4eIonisation;
0105     fPositronProcs.brems = new G4eBremsstrahlung;
0106     fPositronProcs.annihilation = new G4eplusAnnihilation;
0107 
0108     G4CoulombScattering* ss = new G4CoulombScattering;
0109     G4eCoulombScatteringModel* ssm = new G4eCoulombScatteringModel;
0110     ssm->SetLowEnergyLimit(highEnergyLimit);
0111     ssm->SetActivationLowEnergyLimit(highEnergyLimit);
0112     ss->SetEmModel(ssm);
0113     ss->SetMinKinEnergy(highEnergyLimit);
0114     fPositronProcs.ss = ss;
0115   }
0116 
0117   {
0118     G4PhotoElectricEffect* pe = new G4PhotoElectricEffect;
0119     G4VEmModel* peModel = new G4LivermorePhotoElectricModel;
0120     if (polar) {
0121       peModel->SetAngularDistribution(new G4PhotoElectricAngularGeneratorPolarized);
0122     }
0123     pe->SetEmModel(peModel);
0124     fGammaProcs.pe = pe;
0125 
0126     G4ComptonScattering* cs = new G4ComptonScattering;
0127     if (polar) {
0128       cs->SetEmModel(new G4KleinNishinaModel);
0129     }
0130     fGammaProcs.compton = cs;
0131 
0132     fGammaProcs.conversion = new G4GammaConversion;
0133 
0134     G4RayleighScattering* rl = new G4RayleighScattering;
0135     if (polar) {
0136       rl->SetEmModel(new G4LivermorePolarizedRayleighModel);
0137     }
0138     fGammaProcs.rayleigh = rl;
0139   }
0140 
0141   if (fMasterTrackingManager == nullptr) {
0142     fMasterTrackingManager = this;
0143   }
0144   else {
0145     fElectronProcs.msc->SetMasterProcess(fMasterTrackingManager->fElectronProcs.msc);
0146     fElectronProcs.ss->SetMasterProcess(fMasterTrackingManager->fElectronProcs.ss);
0147     fElectronProcs.ioni->SetMasterProcess(fMasterTrackingManager->fElectronProcs.ioni);
0148     fElectronProcs.brems->SetMasterProcess(fMasterTrackingManager->fElectronProcs.brems);
0149 
0150     fPositronProcs.msc->SetMasterProcess(fMasterTrackingManager->fPositronProcs.msc);
0151     fPositronProcs.ss->SetMasterProcess(fMasterTrackingManager->fPositronProcs.ss);
0152     fPositronProcs.ioni->SetMasterProcess(fMasterTrackingManager->fPositronProcs.ioni);
0153     fPositronProcs.brems->SetMasterProcess(fMasterTrackingManager->fPositronProcs.brems);
0154     fPositronProcs.annihilation->SetMasterProcess(
0155       fMasterTrackingManager->fPositronProcs.annihilation);
0156 
0157     fGammaProcs.pe->SetMasterProcess(fMasterTrackingManager->fGammaProcs.pe);
0158     fGammaProcs.compton->SetMasterProcess(fMasterTrackingManager->fGammaProcs.compton);
0159     fGammaProcs.conversion->SetMasterProcess(fMasterTrackingManager->fGammaProcs.conversion);
0160     fGammaProcs.rayleigh->SetMasterProcess(fMasterTrackingManager->fGammaProcs.rayleigh);
0161   }
0162 }
0163 
0164 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0165 
0166 EmStandardPhysicsTrackingManager::~EmStandardPhysicsTrackingManager()
0167 {
0168   if (fMasterTrackingManager == this) {
0169     fMasterTrackingManager = nullptr;
0170   }
0171 }
0172 
0173 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0174 
0175 void EmStandardPhysicsTrackingManager::BuildPhysicsTable(const G4ParticleDefinition& part)
0176 {
0177   if (&part == G4Electron::Definition()) {
0178     fElectronProcs.msc->BuildPhysicsTable(part);
0179     fElectronProcs.ioni->BuildPhysicsTable(part);
0180     fElectronProcs.brems->BuildPhysicsTable(part);
0181     fElectronProcs.ss->BuildPhysicsTable(part);
0182   }
0183   else if (&part == G4Positron::Definition()) {
0184     fPositronProcs.msc->BuildPhysicsTable(part);
0185     fPositronProcs.ioni->BuildPhysicsTable(part);
0186     fPositronProcs.brems->BuildPhysicsTable(part);
0187     fPositronProcs.annihilation->BuildPhysicsTable(part);
0188     fPositronProcs.ss->BuildPhysicsTable(part);
0189   }
0190   else if (&part == G4Gamma::Definition()) {
0191     fGammaProcs.pe->BuildPhysicsTable(part);
0192     fGammaProcs.compton->BuildPhysicsTable(part);
0193     fGammaProcs.conversion->BuildPhysicsTable(part);
0194     fGammaProcs.rayleigh->BuildPhysicsTable(part);
0195   }
0196 }
0197 
0198 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0199 
0200 void EmStandardPhysicsTrackingManager::PreparePhysicsTable(const G4ParticleDefinition& part)
0201 {
0202   if (&part == G4Electron::Definition()) {
0203     fElectronProcs.msc->PreparePhysicsTable(part);
0204     fElectronProcs.ioni->PreparePhysicsTable(part);
0205     fElectronProcs.brems->PreparePhysicsTable(part);
0206     fElectronProcs.ss->PreparePhysicsTable(part);
0207   }
0208   else if (&part == G4Positron::Definition()) {
0209     fPositronProcs.msc->PreparePhysicsTable(part);
0210     fPositronProcs.ioni->PreparePhysicsTable(part);
0211     fPositronProcs.brems->PreparePhysicsTable(part);
0212     fPositronProcs.annihilation->PreparePhysicsTable(part);
0213     fPositronProcs.ss->PreparePhysicsTable(part);
0214   }
0215   else if (&part == G4Gamma::Definition()) {
0216     fGammaProcs.pe->PreparePhysicsTable(part);
0217     fGammaProcs.compton->PreparePhysicsTable(part);
0218     fGammaProcs.conversion->PreparePhysicsTable(part);
0219     fGammaProcs.rayleigh->PreparePhysicsTable(part);
0220   }
0221 }
0222 
0223 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0224 
0225 void EmStandardPhysicsTrackingManager::TrackElectron(G4Track* aTrack)
0226 {
0227   class ElectronPhysics final : public TrackingManagerHelper::Physics
0228   {
0229     public:
0230       ElectronPhysics(EmStandardPhysicsTrackingManager& mgr) : fMgr(mgr) {}
0231 
0232       void StartTracking(G4Track* aTrack) override
0233       {
0234         auto& electronProcs = fMgr.fElectronProcs;
0235 
0236         electronProcs.msc->StartTracking(aTrack);
0237         electronProcs.ioni->StartTracking(aTrack);
0238         electronProcs.brems->StartTracking(aTrack);
0239         electronProcs.ss->StartTracking(aTrack);
0240 
0241         fPreviousStepLength = 0;
0242       }
0243       void EndTracking() override
0244       {
0245         auto& electronProcs = fMgr.fElectronProcs;
0246 
0247         electronProcs.msc->EndTracking();
0248         electronProcs.ioni->EndTracking();
0249         electronProcs.brems->EndTracking();
0250         electronProcs.ss->EndTracking();
0251       }
0252 
0253       G4double GetPhysicalInteractionLength(const G4Track& track) override
0254       {
0255         auto& electronProcs = fMgr.fElectronProcs;
0256         G4double physIntLength, proposedSafety = DBL_MAX;
0257         G4ForceCondition condition;
0258         G4GPILSelection selection;
0259 
0260         fProposedStep = DBL_MAX;
0261         fSelected = -1;
0262 
0263         physIntLength = electronProcs.ss->PostStepGPIL(track, fPreviousStepLength, &condition);
0264         if (physIntLength < fProposedStep) {
0265           fProposedStep = physIntLength;
0266           fSelected = 0;
0267         }
0268 
0269         physIntLength = electronProcs.brems->PostStepGPIL(track, fPreviousStepLength, &condition);
0270         if (physIntLength < fProposedStep) {
0271           fProposedStep = physIntLength;
0272           fSelected = 1;
0273         }
0274 
0275         physIntLength = electronProcs.ioni->PostStepGPIL(track, fPreviousStepLength, &condition);
0276         if (physIntLength < fProposedStep) {
0277           fProposedStep = physIntLength;
0278           fSelected = 2;
0279         }
0280 
0281         physIntLength = electronProcs.ioni->AlongStepGPIL(track, fPreviousStepLength, fProposedStep,
0282                                                           proposedSafety, &selection);
0283         if (physIntLength < fProposedStep) {
0284           fProposedStep = physIntLength;
0285           fSelected = -1;
0286         }
0287 
0288         physIntLength = electronProcs.msc->AlongStepGPIL(track, fPreviousStepLength, fProposedStep,
0289                                                          proposedSafety, &selection);
0290         if (physIntLength < fProposedStep) {
0291           fProposedStep = physIntLength;
0292           // Check if MSC actually wants to win, in most cases it only limits the
0293           // step size.
0294           if (selection == CandidateForSelection) {
0295             fSelected = -1;
0296           }
0297         }
0298 
0299         return fProposedStep;
0300       }
0301 
0302       void AlongStepDoIt(G4Track& track, G4Step& step, G4TrackVector&) override
0303       {
0304         if (step.GetStepLength() == fProposedStep) {
0305           step.GetPostStepPoint()->SetStepStatus(fAlongStepDoItProc);
0306         }
0307         else {
0308           // Remember that the step was limited by geometry.
0309           fSelected = -1;
0310         }
0311         auto& electronProcs = fMgr.fElectronProcs;
0312         G4VParticleChange* particleChange;
0313 
0314         particleChange = electronProcs.msc->AlongStepDoIt(track, step);
0315         particleChange->UpdateStepForAlongStep(&step);
0316         track.SetTrackStatus(particleChange->GetTrackStatus());
0317         particleChange->Clear();
0318 
0319         particleChange = electronProcs.ioni->AlongStepDoIt(track, step);
0320         particleChange->UpdateStepForAlongStep(&step);
0321         track.SetTrackStatus(particleChange->GetTrackStatus());
0322         particleChange->Clear();
0323 
0324         fPreviousStepLength = step.GetStepLength();
0325       }
0326 
0327       void PostStepDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override
0328       {
0329         if (fSelected < 0) {
0330           return;
0331         }
0332         step.GetPostStepPoint()->SetStepStatus(fPostStepDoItProc);
0333 
0334         auto& electronProcs = fMgr.fElectronProcs;
0335         G4VProcess* process = nullptr;
0336         G4VParticleChange* particleChange = nullptr;
0337 
0338         switch (fSelected) {
0339           case 0:
0340             process = electronProcs.ss;
0341             particleChange = electronProcs.ss->PostStepDoIt(track, step);
0342             break;
0343           case 1:
0344             process = electronProcs.brems;
0345             particleChange = electronProcs.brems->PostStepDoIt(track, step);
0346             break;
0347           case 2:
0348             process = electronProcs.ioni;
0349             particleChange = electronProcs.ioni->PostStepDoIt(track, step);
0350             break;
0351         }
0352 
0353         particleChange->UpdateStepForPostStep(&step);
0354         step.UpdateTrack();
0355 
0356         G4int numSecondaries = particleChange->GetNumberOfSecondaries();
0357         for (G4int i = 0; i < numSecondaries; ++i) {
0358           G4Track* secondary = particleChange->GetSecondary(i);
0359           secondary->SetParentID(track.GetTrackID());
0360           secondary->SetCreatorProcess(process);
0361           secondaries.push_back(secondary);
0362         }
0363 
0364         track.SetTrackStatus(particleChange->GetTrackStatus());
0365         particleChange->Clear();
0366       }
0367 
0368     private:
0369       EmStandardPhysicsTrackingManager& fMgr;
0370       G4double fPreviousStepLength;
0371       G4double fProposedStep;
0372       G4int fSelected;
0373   };
0374 
0375   ElectronPhysics physics(*this);
0376   TrackingManagerHelper::TrackChargedParticle(aTrack, physics);
0377 }
0378 
0379 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0380 
0381 void EmStandardPhysicsTrackingManager::TrackPositron(G4Track* aTrack)
0382 {
0383   class PositronPhysics final : public TrackingManagerHelper::Physics
0384   {
0385     public:
0386       PositronPhysics(EmStandardPhysicsTrackingManager& mgr) : fMgr(mgr) {}
0387 
0388       void StartTracking(G4Track* aTrack) override
0389       {
0390         auto& positronProcs = fMgr.fPositronProcs;
0391 
0392         positronProcs.msc->StartTracking(aTrack);
0393         positronProcs.ioni->StartTracking(aTrack);
0394         positronProcs.brems->StartTracking(aTrack);
0395         positronProcs.annihilation->StartTracking(aTrack);
0396         positronProcs.ss->StartTracking(aTrack);
0397 
0398         fPreviousStepLength = 0;
0399       }
0400       void EndTracking() override
0401       {
0402         auto& positronProcs = fMgr.fPositronProcs;
0403 
0404         positronProcs.msc->EndTracking();
0405         positronProcs.ioni->EndTracking();
0406         positronProcs.brems->EndTracking();
0407         positronProcs.annihilation->EndTracking();
0408         positronProcs.ss->EndTracking();
0409       }
0410 
0411       G4double GetPhysicalInteractionLength(const G4Track& track) override
0412       {
0413         auto& positronProcs = fMgr.fPositronProcs;
0414         G4double physIntLength, proposedSafety = DBL_MAX;
0415         G4ForceCondition condition;
0416         G4GPILSelection selection;
0417 
0418         fProposedStep = DBL_MAX;
0419         fSelected = -1;
0420 
0421         physIntLength = positronProcs.ss->PostStepGPIL(track, fPreviousStepLength, &condition);
0422         if (physIntLength < fProposedStep) {
0423           fProposedStep = physIntLength;
0424           fSelected = 0;
0425         }
0426 
0427         physIntLength =
0428           positronProcs.annihilation->PostStepGPIL(track, fPreviousStepLength, &condition);
0429         if (physIntLength < fProposedStep) {
0430           fProposedStep = physIntLength;
0431           fSelected = 1;
0432         }
0433 
0434         physIntLength = positronProcs.brems->PostStepGPIL(track, fPreviousStepLength, &condition);
0435         if (physIntLength < fProposedStep) {
0436           fProposedStep = physIntLength;
0437           fSelected = 2;
0438         }
0439 
0440         physIntLength = positronProcs.ioni->PostStepGPIL(track, fPreviousStepLength, &condition);
0441         if (physIntLength < fProposedStep) {
0442           fProposedStep = physIntLength;
0443           fSelected = 3;
0444         }
0445 
0446         physIntLength = positronProcs.ioni->AlongStepGPIL(track, fPreviousStepLength, fProposedStep,
0447                                                           proposedSafety, &selection);
0448         if (physIntLength < fProposedStep) {
0449           fProposedStep = physIntLength;
0450           fSelected = -1;
0451         }
0452 
0453         physIntLength = positronProcs.msc->AlongStepGPIL(track, fPreviousStepLength, fProposedStep,
0454                                                          proposedSafety, &selection);
0455         if (physIntLength < fProposedStep) {
0456           fProposedStep = physIntLength;
0457           // Check if MSC actually wants to win, in most cases it only limits the
0458           // step size.
0459           if (selection == CandidateForSelection) {
0460             fSelected = -1;
0461           }
0462         }
0463 
0464         return fProposedStep;
0465       }
0466 
0467       void AlongStepDoIt(G4Track& track, G4Step& step, G4TrackVector&) override
0468       {
0469         if (step.GetStepLength() == fProposedStep) {
0470           step.GetPostStepPoint()->SetStepStatus(fAlongStepDoItProc);
0471         }
0472         else {
0473           // Remember that the step was limited by geometry.
0474           fSelected = -1;
0475         }
0476         auto& positronProcs = fMgr.fPositronProcs;
0477         G4VParticleChange* particleChange;
0478 
0479         particleChange = positronProcs.msc->AlongStepDoIt(track, step);
0480         particleChange->UpdateStepForAlongStep(&step);
0481         track.SetTrackStatus(particleChange->GetTrackStatus());
0482         particleChange->Clear();
0483 
0484         particleChange = positronProcs.ioni->AlongStepDoIt(track, step);
0485         particleChange->UpdateStepForAlongStep(&step);
0486         track.SetTrackStatus(particleChange->GetTrackStatus());
0487         particleChange->Clear();
0488 
0489         fPreviousStepLength = step.GetStepLength();
0490       }
0491 
0492       void PostStepDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override
0493       {
0494         if (fSelected < 0) {
0495           return;
0496         }
0497         step.GetPostStepPoint()->SetStepStatus(fPostStepDoItProc);
0498 
0499         auto& positronProcs = fMgr.fPositronProcs;
0500         G4VProcess* process = nullptr;
0501         G4VParticleChange* particleChange = nullptr;
0502 
0503         switch (fSelected) {
0504           case 0:
0505             process = positronProcs.ss;
0506             particleChange = positronProcs.ss->PostStepDoIt(track, step);
0507             break;
0508           case 1:
0509             process = positronProcs.annihilation;
0510             particleChange = positronProcs.annihilation->PostStepDoIt(track, step);
0511             break;
0512           case 2:
0513             process = positronProcs.brems;
0514             particleChange = positronProcs.brems->PostStepDoIt(track, step);
0515             break;
0516           case 3:
0517             process = positronProcs.ioni;
0518             particleChange = positronProcs.ioni->PostStepDoIt(track, step);
0519             break;
0520         }
0521 
0522         particleChange->UpdateStepForPostStep(&step);
0523         step.UpdateTrack();
0524 
0525         G4int numSecondaries = particleChange->GetNumberOfSecondaries();
0526         for (G4int i = 0; i < numSecondaries; ++i) {
0527           G4Track* secondary = particleChange->GetSecondary(i);
0528           secondary->SetParentID(track.GetTrackID());
0529           secondary->SetCreatorProcess(process);
0530           secondaries.push_back(secondary);
0531         }
0532 
0533         track.SetTrackStatus(particleChange->GetTrackStatus());
0534         particleChange->Clear();
0535       }
0536 
0537       G4bool HasAtRestProcesses() override { return true; }
0538 
0539       void AtRestDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override
0540       {
0541         auto& positronProcs = fMgr.fPositronProcs;
0542         // Annihilate the positron at rest.
0543         G4VParticleChange* particleChange = positronProcs.annihilation->AtRestDoIt(track, step);
0544         particleChange->UpdateStepForAtRest(&step);
0545         step.UpdateTrack();
0546 
0547         G4int numSecondaries = particleChange->GetNumberOfSecondaries();
0548         for (G4int i = 0; i < numSecondaries; ++i) {
0549           G4Track* secondary = particleChange->GetSecondary(i);
0550           secondary->SetParentID(track.GetTrackID());
0551           secondary->SetCreatorProcess(positronProcs.annihilation);
0552           secondaries.push_back(secondary);
0553         }
0554 
0555         track.SetTrackStatus(particleChange->GetTrackStatus());
0556         particleChange->Clear();
0557       }
0558 
0559     private:
0560       EmStandardPhysicsTrackingManager& fMgr;
0561       G4double fPreviousStepLength;
0562       G4double fProposedStep;
0563       G4int fSelected;
0564   };
0565 
0566   PositronPhysics physics(*this);
0567   TrackingManagerHelper::TrackChargedParticle(aTrack, physics);
0568 }
0569 
0570 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0571 
0572 void EmStandardPhysicsTrackingManager::TrackGamma(G4Track* aTrack)
0573 {
0574   class GammaPhysics final : public TrackingManagerHelper::Physics
0575   {
0576     public:
0577       GammaPhysics(EmStandardPhysicsTrackingManager& mgr) : fMgr(mgr) {}
0578 
0579       void StartTracking(G4Track* aTrack) override
0580       {
0581         auto& gammaProcs = fMgr.fGammaProcs;
0582 
0583         gammaProcs.pe->StartTracking(aTrack);
0584         gammaProcs.compton->StartTracking(aTrack);
0585         gammaProcs.conversion->StartTracking(aTrack);
0586         gammaProcs.rayleigh->StartTracking(aTrack);
0587 
0588         fPreviousStepLength = 0;
0589       }
0590       void EndTracking() override
0591       {
0592         auto& gammaProcs = fMgr.fGammaProcs;
0593 
0594         gammaProcs.pe->EndTracking();
0595         gammaProcs.compton->EndTracking();
0596         gammaProcs.conversion->EndTracking();
0597         gammaProcs.rayleigh->EndTracking();
0598       }
0599 
0600       G4double GetPhysicalInteractionLength(const G4Track& track) override
0601       {
0602         auto& gammaProcs = fMgr.fGammaProcs;
0603         G4double physIntLength;
0604         G4ForceCondition condition;
0605 
0606         fProposedStep = DBL_MAX;
0607         fSelected = -1;
0608 
0609         physIntLength = gammaProcs.rayleigh->PostStepGPIL(track, fPreviousStepLength, &condition);
0610         if (physIntLength < fProposedStep) {
0611           fProposedStep = physIntLength;
0612           fSelected = 0;
0613         }
0614 
0615         physIntLength = gammaProcs.conversion->PostStepGPIL(track, fPreviousStepLength, &condition);
0616         if (physIntLength < fProposedStep) {
0617           fProposedStep = physIntLength;
0618           fSelected = 1;
0619         }
0620 
0621         physIntLength = gammaProcs.compton->PostStepGPIL(track, fPreviousStepLength, &condition);
0622         if (physIntLength < fProposedStep) {
0623           fProposedStep = physIntLength;
0624           fSelected = 2;
0625         }
0626 
0627         physIntLength = gammaProcs.pe->PostStepGPIL(track, fPreviousStepLength, &condition);
0628         if (physIntLength < fProposedStep) {
0629           fProposedStep = physIntLength;
0630           fSelected = 3;
0631         }
0632 
0633         return fProposedStep;
0634       }
0635 
0636       void AlongStepDoIt(G4Track&, G4Step& step, G4TrackVector&) override
0637       {
0638         if (step.GetStepLength() == fProposedStep) {
0639           step.GetPostStepPoint()->SetStepStatus(fAlongStepDoItProc);
0640         }
0641         else {
0642           // Remember that the step was limited by geometry.
0643           fSelected = -1;
0644         }
0645         fPreviousStepLength = step.GetStepLength();
0646       }
0647 
0648       void PostStepDoIt(G4Track& track, G4Step& step, G4TrackVector& secondaries) override
0649       {
0650         if (fSelected < 0) {
0651           return;
0652         }
0653         step.GetPostStepPoint()->SetStepStatus(fPostStepDoItProc);
0654 
0655         auto& gammaProcs = fMgr.fGammaProcs;
0656         G4VProcess* process = nullptr;
0657         G4VParticleChange* particleChange = nullptr;
0658 
0659         switch (fSelected) {
0660           case 0:
0661             process = gammaProcs.rayleigh;
0662             particleChange = gammaProcs.rayleigh->PostStepDoIt(track, step);
0663             break;
0664           case 1:
0665             process = gammaProcs.conversion;
0666             particleChange = gammaProcs.conversion->PostStepDoIt(track, step);
0667             break;
0668           case 2:
0669             process = gammaProcs.compton;
0670             particleChange = gammaProcs.compton->PostStepDoIt(track, step);
0671             break;
0672           case 3:
0673             process = gammaProcs.pe;
0674             particleChange = gammaProcs.pe->PostStepDoIt(track, step);
0675             break;
0676         }
0677 
0678         particleChange->UpdateStepForPostStep(&step);
0679         step.UpdateTrack();
0680 
0681         G4int numSecondaries = particleChange->GetNumberOfSecondaries();
0682         for (G4int i = 0; i < numSecondaries; ++i) {
0683           G4Track* secondary = particleChange->GetSecondary(i);
0684           secondary->SetParentID(track.GetTrackID());
0685           secondary->SetCreatorProcess(process);
0686           secondaries.push_back(secondary);
0687         }
0688 
0689         track.SetTrackStatus(particleChange->GetTrackStatus());
0690         particleChange->Clear();
0691       }
0692 
0693     private:
0694       EmStandardPhysicsTrackingManager& fMgr;
0695       G4double fPreviousStepLength;
0696       G4double fProposedStep;
0697       G4int fSelected;
0698   };
0699 
0700   GammaPhysics physics(*this);
0701   TrackingManagerHelper::TrackNeutralParticle(aTrack, physics);
0702 }
0703 
0704 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0705 
0706 void EmStandardPhysicsTrackingManager::HandOverOneTrack(G4Track* aTrack)
0707 {
0708   const G4ParticleDefinition* part = aTrack->GetParticleDefinition();
0709 
0710   if (part == G4Electron::Definition()) {
0711     TrackElectron(aTrack);
0712   }
0713   else if (part == G4Positron::Definition()) {
0714     TrackPositron(aTrack);
0715   }
0716   else if (part == G4Gamma::Definition()) {
0717     TrackGamma(aTrack);
0718   }
0719 
0720   aTrack->SetTrackStatus(fStopAndKill);
0721   delete aTrack;
0722 }
0723 
0724 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......