ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4VAtomDeexcitation.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4VAtomDeexcitation.cc
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 // GEANT4 Class class file
30 //
31 //
32 // File name: G4VAtomDeexcitation
33 //
34 // Author: Alfonso Mantero & Vladimir Ivanchenko
35 //
36 // Creation date: 21.04.2010
37 //
38 // Modifications:
39 //
40 // Class Description:
41 //
42 // Abstract interface to energy loss models
43 
44 // -------------------------------------------------------------------
45 //
46 
47 #include "G4VAtomDeexcitation.hh"
48 #include "G4SystemOfUnits.hh"
49 #include "G4ParticleDefinition.hh"
50 #include "G4DynamicParticle.hh"
51 #include "G4Step.hh"
52 #include "G4Region.hh"
53 #include "G4RegionStore.hh"
54 #include "G4MaterialCutsCouple.hh"
55 #include "G4MaterialCutsCouple.hh"
56 #include "G4Material.hh"
57 #include "G4Element.hh"
58 #include "G4ElementVector.hh"
59 #include "Randomize.hh"
60 #include "G4VParticleChange.hh"
61 #include "G4PhysicsModelCatalog.hh"
62 #include "G4Gamma.hh"
63 
64 #ifdef G4MULTITHREADED
65  G4Mutex G4VAtomDeexcitation::atomDeexcitationMutex = G4MUTEX_INITIALIZER;
66 #endif
67 
68 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
69 
72 
74  : verbose(1), name(modname), isActive(false), flagAuger(false),
75  flagAugerCascade(false), flagPIXE(false), ignoreCuts(false),
76  isActiveLocked(false), isAugerLocked(false),
77  isAugerCascadeLocked(false), isPIXELocked(false)
78 {
80  vdyn.reserve(5);
81  theCoupleTable = nullptr;
82  G4String gg = "gammaPIXE";
83  G4String ee = "e-PIXE";
84  if(pixeIDg < 0) {
85 #ifdef G4MULTITHREADED
86  G4MUTEXLOCK(&atomDeexcitationMutex);
87  if(pixeIDg < 0) {
88 #endif
91 #ifdef G4MULTITHREADED
92  }
93  G4MUTEXUNLOCK(&atomDeexcitationMutex);
94 #endif
95  }
97 }
98 
99 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
100 
102 {}
103 
104 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
105 
107 {
109 
110  // Define list of couples
112  G4int numOfCouples = theCoupleTable->GetTableSize();
113 
114  // needed for unit tests
115  G4int nn = std::max(numOfCouples, 1);
116  activeDeexcitationMedia.resize(nn, false);
117  activeAugerMedia.resize(nn, false);
118  activePIXEMedia.resize(nn, false);
119  activeZ.resize(93, false);
120 
121  // initialisation of flags and options
122  // normally there is no locksed flags
126  if(!isPIXELocked) { flagPIXE = theParameters->Pixe(); }
128 
129  // Define list of regions
130  size_t nRegions = deRegions.size();
131  // check if deexcitation is active for the given run
132  if(!isActive && 0 == nRegions) { return; }
133 
134  // if no active regions add a world
135  if(0 == nRegions) {
137  nRegions = deRegions.size();
138  }
139 
140  if(0 < verbose) {
141  G4cout << G4endl;
142  G4cout << "### === Deexcitation model " << name
143  << " is activated for " << nRegions;
144  if(1 == nRegions) { G4cout << " region:" << G4endl; }
145  else { G4cout << " regions:" << G4endl;}
146  }
147 
148  // Identify active media
149  G4RegionStore* regionStore = G4RegionStore::GetInstance();
150  for(size_t j=0; j<nRegions; ++j) {
151  const G4Region* reg = regionStore->GetRegion(activeRegions[j], false);
152  if(reg && 0 < numOfCouples) {
153  const G4ProductionCuts* rpcuts = reg->GetProductionCuts();
154  if(0 < verbose) {
155  G4cout << " " << activeRegions[j]
156  << " " << deRegions[j] << " " << AugerRegions[j]
157  << " " << PIXERegions[j] << G4endl;
158  }
159  for(G4int i=0; i<numOfCouples; ++i) {
160  const G4MaterialCutsCouple* couple =
162  if (couple->GetProductionCuts() == rpcuts) {
166  }
167  }
168  }
169  }
171  //G4cout << nelm << G4endl;
172  for(G4int k=0; k<nelm; ++k) {
173  G4int Z = (*(G4Element::GetElementTable()))[k]->GetZasInt();
174  if(Z > 5 && Z < 93) {
175  activeZ[Z] = true;
176  //G4cout << "!!! Active de-excitation Z= " << Z << G4endl;
177  }
178  }
179 
180  // Initialise derived class
182 
183  if(0 < verbose && flagAuger) {
184  G4cout << "### === Auger cascade flag: " << flagAugerCascade
185  << G4endl;
186  }
187  if(0 < verbose) {
188  G4cout << "### === Ignore cuts flag: " << ignoreCuts
189  << G4endl;
190  }
191  if(0 < verbose && flagPIXE) {
192  G4cout << "### === PIXE model for hadrons: "
194  << G4endl;
195  G4cout << "### === PIXE model for e+-: "
197  << G4endl;
198  }
199 }
200 
201 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
202 
203 void
205  G4bool valDeexcitation,
206  G4bool valAuger,
207  G4bool valPIXE)
208 {
209  // no PIXE in parallel world
210  if(rname == "DefaultRegionForParallelWorld") { return; }
211 
212  G4String ss = rname;
213  /*
214  G4cout << "### G4VAtomDeexcitation::SetDeexcitationActiveRegion " << ss
215  << " " << valDeexcitation << " " << valAuger
216  << " " << valPIXE << G4endl;
217  */
218  if(ss == "world" || ss == "World" || ss == "WORLD") {
219  ss = "DefaultRegionForTheWorld";
220  }
221  size_t n = deRegions.size();
222  for(size_t i=0; i<n; ++i) {
223 
224  // Region already exist
225  if(ss == activeRegions[i]) {
226  deRegions[i] = valDeexcitation;
227  AugerRegions[i] = valAuger;
228  PIXERegions[i] = valPIXE;
229  return;
230  }
231  }
232  // New region
233  activeRegions.push_back(ss);
234  deRegions.push_back(valDeexcitation);
235  AugerRegions.push_back(valAuger);
236  PIXERegions.push_back(valPIXE);
237 
238  // if de-excitation defined for the world volume
239  // it should be active for all G4Regions
240  if(ss == "DefaultRegionForTheWorld") {
242  G4int nn = regions->size();
243  for(G4int i=0; i<nn; ++i) {
244  if(ss == (*regions)[i]->GetName()) { continue; }
245  SetDeexcitationActiveRegion((*regions)[i]->GetName(), valDeexcitation,
246  valAuger, valPIXE);
247 
248  }
249  }
250 }
251 
252 void G4VAtomDeexcitation::GenerateParticles(std::vector<G4DynamicParticle*>* v,
253  const G4AtomicShell* as,
254  G4int Z, G4int idx)
255 {
256  G4double gCut = DBL_MAX;
257  if(ignoreCuts) {
258  gCut = 0.0;
259  } else if (theCoupleTable) {
260  gCut = (*(theCoupleTable->GetEnergyCutsVector(0)))[idx];
261  }
262  if(gCut < as->BindingEnergy()) {
263  G4double eCut = DBL_MAX;
264  if(CheckAugerActiveRegion(idx)) {
265  if(ignoreCuts) {
266  eCut = 0.0;
267  } else if (theCoupleTable) {
268  eCut = (*(theCoupleTable->GetEnergyCutsVector(1)))[idx];
269  }
270  }
271  GenerateParticles(v, as, Z, gCut, eCut);
272  }
273 }
274 
275 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
276 
277 void
278 G4VAtomDeexcitation::AlongStepDeexcitation(std::vector<G4Track*>& tracks,
279  const G4Step& step,
280  G4double& eLossMax,
281  G4int coupleIndex)
282 {
283  G4double truelength = step.GetStepLength();
284  if(!flagPIXE && !activePIXEMedia[coupleIndex]) { return; }
285  if(eLossMax <= 0.0 || truelength <= 0.0) { return; }
286 
287  // step parameters
288  const G4StepPoint* preStep = step.GetPreStepPoint();
289  G4ThreeVector prePos = preStep->GetPosition();
290  G4ThreeVector delta = step.GetPostStepPoint()->GetPosition() - prePos;
291  G4double preTime = preStep->GetGlobalTime();
292  G4double dt = step.GetPostStepPoint()->GetGlobalTime() - preTime;
293 
294  // particle parameters
295  const G4Track* track = step.GetTrack();
296  const G4ParticleDefinition* part = track->GetDefinition();
297  G4double ekin = preStep->GetKineticEnergy();
298 
299  // media parameters
300  G4double gCut = (*theCoupleTable->GetEnergyCutsVector(0))[coupleIndex];
301  if(ignoreCuts) { gCut = 0.0; }
302  G4double eCut = DBL_MAX;
303  if(CheckAugerActiveRegion(coupleIndex)) {
304  eCut = (*theCoupleTable->GetEnergyCutsVector(1))[coupleIndex];
305  if(ignoreCuts) { eCut = 0.0; }
306  }
307 
308  //G4cout<<"!Sample PIXE gCut(MeV)= "<<gCut<<" eCut(MeV)= "<<eCut
309  // <<" Ekin(MeV)= " << ekin/MeV << G4endl;
310 
311  const G4Material* material = preStep->GetMaterial();
312  const G4ElementVector* theElementVector = material->GetElementVector();
313  const G4double* theAtomNumDensityVector =
314  material->GetVecNbOfAtomsPerVolume();
315  G4int nelm = material->GetNumberOfElements();
316 
317  // loop over deexcitations
318  for(G4int i=0; i<nelm; ++i) {
319  G4int Z = (*theElementVector)[i]->GetZasInt();
320  if(activeZ[Z] && Z < 93) {
321  G4int nshells =
322  std::min(9,(*theElementVector)[i]->GetNbOfAtomicShells());
323  G4double rho = truelength*theAtomNumDensityVector[i];
324  //G4cout<<" Z "<< Z <<" is active x(mm)= " << truelength/mm << G4endl;
325  for(G4int ii=0; ii<nshells; ++ii) {
327  const G4AtomicShell* shell = GetAtomicShell(Z, as);
329 
330  if(gCut > bindingEnergy) { break; }
331 
332  if(eLossMax > bindingEnergy) {
333  G4double sig = rho*
334  GetShellIonisationCrossSectionPerAtom(part, Z, as, ekin, material);
335 
336  // mfp is mean free path in units of step size
337  if(sig > 0.0) {
338  G4double mfp = 1.0/sig;
339  G4double stot = 0.0;
340  //G4cout << " Shell " << ii << " mfp(mm)= " << mfp/mm << G4endl;
341  // sample ionisation points
342  do {
343  stot -= mfp*std::log(G4UniformRand());
344  if( stot > 1.0 || eLossMax < bindingEnergy) { break; }
345  // sample deexcitation
346  vdyn.clear();
347  GenerateParticles(&vdyn, shell, Z, gCut, eCut);
348  G4int nsec = vdyn.size();
349  if(nsec > 0) {
350  G4ThreeVector r = prePos + stot*delta;
351  G4double time = preTime + stot*dt;
352  for(G4int j=0; j<nsec; ++j) {
353  G4DynamicParticle* dp = vdyn[j];
354  G4double e = dp->GetKineticEnergy();
355 
356  // save new secondary if there is enough energy
357  if(eLossMax >= e) {
358  eLossMax -= e;
359  G4Track* t = new G4Track(dp, time, r);
360 
361  // defined secondary type
362  if(dp->GetDefinition() == gamma) {
364  } else {
366  }
367 
368  tracks.push_back(t);
369  } else {
370  delete dp;
371  }
372  }
373  }
374  // Loop checking, 03-Aug-2015, Vladimir Ivanchenko
375  } while (stot < 1.0);
376  }
377  }
378  }
379  }
380  }
381  return;
382 }
383 
384 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....