Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/runAndEvent/RE07/src/EmStandardPhysicsTrackingManager.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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