Geant4  10.02.p01
G4AtomicDeexcitation.cc
Go to the documentation of this file.
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 // Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
29 // Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
30 //
31 // History:
32 // -----------
33 //
34 // 16 Sept 2001 First committed to cvs
35 // 12 Sep 2003 Bug in auger production fixed
36 //
37 // -------------------------------------------------------------------
38 
39 #include "G4AtomicDeexcitation.hh"
40 #include "Randomize.hh"
41 #include "G4PhysicalConstants.hh"
42 #include "G4SystemOfUnits.hh"
43 #include "G4Gamma.hh"
44 #include "G4Electron.hh"
46 #include "G4FluoTransition.hh"
47 
49  minGammaEnergy(100.*eV),
50  minElectronEnergy(100.*eV),
51  fAuger(false)
52 {
53 
54  G4cout << " ********************************************************** " << G4endl;
55  G4cout << " * W A R N I N G ! ! ! * " << G4endl;
56  G4cout << " ********************************************************** " << G4endl;
57  G4cout << " * * " << G4endl;
58  G4cout << " * Class G4AtomicDeexcitation is obsolete. It has been * " << G4endl;
59  G4cout << " * discontinued and is going to be removed by next Geant4 * " << G4endl;
60  G4cout << " * release please migrate to G4UAtomDeexcitation. * " << G4endl;
61  G4cout << " * * " << G4endl;
62  G4cout << " ********************************************************** " << G4endl;
63 
65  newShellId=0;
66 }
67 
69 {}
70 
71 std::vector<G4DynamicParticle*>* G4AtomicDeexcitation::GenerateParticles(G4int Z,G4int givenShellId)
72 {
73 
74  std::vector<G4DynamicParticle*>* vectorOfParticles;
75  vectorOfParticles = new std::vector<G4DynamicParticle*>;
76 
77  G4DynamicParticle* aParticle;
78  G4int provShellId = 0;
79  G4int counter = 0;
80 
81  // The aim of this loop is to generate more than one fluorecence photon
82  // from the same ionizing event
83  do
84  {
85  if (counter == 0)
86  // First call to GenerateParticles(...):
87  // givenShellId is given by the process
88  {
89  provShellId = SelectTypeOfTransition(Z, givenShellId);
90 
91  if ( provShellId >0)
92  {
93  aParticle = GenerateFluorescence(Z,givenShellId,provShellId);
94  }
95  else if ( provShellId == -1)
96  {
97  aParticle = GenerateAuger(Z, givenShellId);
98  }
99  else
100  {
101  G4Exception("G4AtomicDeexcitation::Constructor", "de0002", JustWarning, "Transition selection invalid, energy local deposited");
102  }
103  }
104  else
105  // Following calls to GenerateParticles(...):
106  // newShellId is given by GenerateFluorescence(...)
107  {
108  provShellId = SelectTypeOfTransition(Z,newShellId);
109  if (provShellId >0)
110  {
111  aParticle = GenerateFluorescence(Z,newShellId,provShellId);
112  }
113  else if ( provShellId == -1)
114  {
115  aParticle = GenerateAuger(Z, newShellId);
116  }
117  else
118  {
119  G4Exception("G4AtomicDeexcitation::constructor", "de0002", JustWarning, "Transition selection invalid, energy local deposited" );
120  }
121  }
122  counter++;
123  if (aParticle != 0) {vectorOfParticles->push_back(aParticle);}
124  else {provShellId = -2;}
125  }
126 
127  // Look this in a particular way: only one auger emitted! // ????
128  while (provShellId > -2);
129 
130  // debug
131  // if (vectorOfParticles->size() > 0) {
132  // G4cout << " DEEXCITATION!" << G4endl;
133  // }
134 
135  return vectorOfParticles;
136 }
137 
139 {
140  if (shellId <=0 )
141  {G4Exception("G4AtomicDeexcitation::SelectTypeOfTransition()","de0002", JustWarning ,"zero or negative shellId");}
142 
143  //G4bool fluoTransitionFoundFlag = false;
144 
145  const G4AtomicTransitionManager* transitionManager =
147  G4int provShellId = -1;
148  G4int shellNum = 0;
149  G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);
150 
151  const G4FluoTransition* refShell = transitionManager->ReachableShell(Z,maxNumOfShells-1);
152 
153  // This loop gives shellNum the value of the index of shellId
154  // in the vector storing the list of the shells reachable through
155  // a radiative transition
156  if ( shellId <= refShell->FinalShellId())
157  {
158  while (shellId != transitionManager->ReachableShell(Z,shellNum)->FinalShellId())
159  {
160  if(shellNum ==maxNumOfShells-1)
161  {
162  break;
163  }
164  shellNum++;
165  }
166  G4int transProb = 0; //AM change 29/6/07 was 1
167 
168  G4double partialProb = G4UniformRand();
169  G4double partSum = 0;
170  const G4FluoTransition* aShell = transitionManager->ReachableShell(Z,shellNum);
171  G4int trSize = (aShell->TransitionProbabilities()).size();
172 
173  // Loop over the shells wich can provide an electron for a
174  // radiative transition towards shellId:
175  // in every loop the partial sum of the first transProb shells
176  // is calculated and compared with a random number [0,1].
177  // If the partial sum is greater, the shell whose index is transProb
178  // is chosen as the starting shell for a radiative transition
179  // and its identity is returned
180  // Else, terminateded the loop, -1 is returned
181  while(transProb < trSize){
182 
183  partSum += aShell->TransitionProbability(transProb);
184 
185  if(partialProb <= partSum)
186  {
187  provShellId = aShell->OriginatingShellId(transProb);
188  //fluoTransitionFoundFlag = true;
189 
190  break;
191  }
192  transProb++;
193  }
194 
195  // here provShellId is the right one or is -1.
196  // if -1, the control is passed to the Auger generation part of the package
197  }
198 
199 
200 
201  else
202  {
203 
204  provShellId = -1;
205 
206  }
207  return provShellId;
208 }
209 
211  G4int shellId,
212  G4int provShellId )
213 {
214 
215 
217  // G4int provenienceShell = provShellId;
218 
219  //isotropic angular distribution for the outcoming photon
220  G4double newcosTh = 1.-2.*G4UniformRand();
221  G4double newsinTh = std::sqrt(1.-newcosTh*newcosTh);
222  G4double newPhi = twopi*G4UniformRand();
223 
224  G4double xDir = newsinTh*std::sin(newPhi);
225  G4double yDir = newsinTh*std::cos(newPhi);
226  G4double zDir = newcosTh;
227 
228  G4ThreeVector newGammaDirection(xDir,yDir,zDir);
229 
230  G4int shellNum = 0;
231  G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);
232 
233  // find the index of the shell named shellId
234  while (shellId != transitionManager->
235  ReachableShell(Z,shellNum)->FinalShellId())
236  {
237  if(shellNum == maxNumOfShells-1)
238  {
239  break;
240  }
241  shellNum++;
242  }
243  // number of shell from wich an electron can reach shellId
244  size_t transitionSize = transitionManager->
245  ReachableShell(Z,shellNum)->OriginatingShellIds().size();
246 
247  size_t index = 0;
248 
249  // find the index of the shell named provShellId in the vector
250  // storing the shells from which shellId can be reached
251  while (provShellId != transitionManager->
252  ReachableShell(Z,shellNum)->OriginatingShellId(index))
253  {
254  if(index == transitionSize-1)
255  {
256  break;
257  }
258  index++;
259  }
260  // energy of the gamma leaving provShellId for shellId
261  G4double transitionEnergy = transitionManager->
262  ReachableShell(Z,shellNum)->TransitionEnergy(index);
263 
264  // This is the shell where the new vacancy is: it is the same
265  // shell where the electron came from
266  newShellId = transitionManager->
267  ReachableShell(Z,shellNum)->OriginatingShellId(index);
268 
269 
271  newGammaDirection,
272  transitionEnergy);
273  return newPart;
274 }
275 
277 {
278  if(!fAuger) return 0;
279 
280 
281  const G4AtomicTransitionManager* transitionManager =
283 
284 
285 
286  if (shellId <=0 )
287  {G4Exception("G4AtomicDeexcitation::GenerateAuger()","de0002", JustWarning ,"zero or negative shellId");}
288 
289  // G4int provShellId = -1;
290  G4int maxNumOfShells = transitionManager->NumberOfReachableAugerShells(Z);
291 
292  const G4AugerTransition* refAugerTransition =
293  transitionManager->ReachableAugerShell(Z,maxNumOfShells-1);
294 
295 
296  // This loop gives to shellNum the value of the index of shellId
297  // in the vector storing the list of the vacancies in the variuos shells
298  // that can originate a NON-radiative transition
299 
300  // ---- MGP ---- Next line commented out to remove compilation warning
301  // G4int p = refAugerTransition->FinalShellId();
302 
303  G4int shellNum = 0;
304 
305 
306  if ( shellId <= refAugerTransition->FinalShellId() )
307  //"FinalShellId" is final from the point of view of the elctron who makes the transition,
308  // being the Id of the shell in which there is a vacancy
309  {
310  G4int pippo = transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId();
311  if (shellId != pippo ) {
312  do {
313  shellNum++;
314  if(shellNum == maxNumOfShells)
315  {
316 
317  //G4Exception("G4AtomicDeexcitation: No Auger transition found");
318  return 0;
319  }
320  }
321  while (shellId != (transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId()) ) ;
322  }
323 
324 
325  // Now we have that shellnum is the shellIndex of the shell named ShellId
326 
327  // G4cout << " the index of the shell is: "<<shellNum<<G4endl;
328 
329  // But we have now to select two shells: one for the transition,
330  // and another for the auger emission.
331 
332  G4int transitionLoopShellIndex = 0;
333  G4double partSum = 0;
334  const G4AugerTransition* anAugerTransition =
335  transitionManager->ReachableAugerShell(Z,shellNum);
336 
337  // G4cout << " corresponding to the ID: "<< anAugerTransition->FinalShellId() << G4endl;
338 
339 
340  G4int transitionSize =
341  (anAugerTransition->TransitionOriginatingShellIds())->size();
342  while (transitionLoopShellIndex < transitionSize) {
343 
344  std::vector<G4int>::const_iterator pos =
345  anAugerTransition->TransitionOriginatingShellIds()->begin();
346 
347  G4int transitionLoopShellId = *(pos+transitionLoopShellIndex);
348  G4int numberOfPossibleAuger =
349  (anAugerTransition->AugerTransitionProbabilities(transitionLoopShellId))->size();
350  G4int augerIndex = 0;
351  // G4int partSum2 = 0;
352 
353 
354  if (augerIndex < numberOfPossibleAuger) {
355 
356  do
357  {
358  G4double thisProb = anAugerTransition->AugerTransitionProbability(augerIndex,
359  transitionLoopShellId);
360  partSum += thisProb;
361  augerIndex++;
362 
363  } while (augerIndex < numberOfPossibleAuger);
364  }
365  transitionLoopShellIndex++;
366  }
367 
368 
369 
370  // Now we have the entire probability of an auger transition for the vacancy
371  // located in shellNum (index of shellId)
372 
373  // AM *********************** F I X E D **************************** AM
374  // Here we duplicate the previous loop, this time looking to the sum of the probabilities
375  // to be under the random number shoot by G4 UniformRdandom. This could have been done in the
376  // previuos loop, while integrating the probabilities. There is a bug that will be fixed
377  // 5 minutes from now: a line:
378  // G4int numberOfPossibleAuger = (anAugerTransition->
379  // AugerTransitionProbabilities(transitionLoopShellId))->size();
380  // to be inserted.
381  // AM *********************** F I X E D **************************** AM
382 
383  // Remains to get the same result with a single loop.
384 
385  // AM *********************** F I X E D **************************** AM
386  // Another Bug: in EADL Auger Transition are normalized to all the transitions deriving from
387  // a vacancy in one shell, but not all of these are present in data tables. So if a transition
388  // doesn't occur in the main one a local energy deposition must occur, instead of (like now)
389  // generating the last transition present in EADL data.
390  // AM *********************** F I X E D **************************** AM
391 
392 
393  G4double totalVacancyAugerProbability = partSum;
394 
395 
396  //And now we start to select the right auger transition and emission
397  G4int transitionRandomShellIndex = 0;
398  G4int transitionRandomShellId = 1;
399  G4int augerIndex = 0;
400  partSum = 0;
401  G4double partialProb = G4UniformRand();
402  // G4int augerOriginatingShellId = 0;
403 
404  G4int numberOfPossibleAuger = 0;
405 
406  G4bool foundFlag = false;
407 
408  while (transitionRandomShellIndex < transitionSize) {
409 
410  std::vector<G4int>::const_iterator pos =
411  anAugerTransition->TransitionOriginatingShellIds()->begin();
412 
413  transitionRandomShellId = *(pos+transitionRandomShellIndex);
414 
415  augerIndex = 0;
416  numberOfPossibleAuger = (anAugerTransition->
417  AugerTransitionProbabilities(transitionRandomShellId))->size();
418 
419  while (augerIndex < numberOfPossibleAuger) {
420  G4double thisProb =anAugerTransition->AugerTransitionProbability(augerIndex,
421  transitionRandomShellId);
422 
423  partSum += thisProb;
424 
425  if (partSum >= (partialProb*totalVacancyAugerProbability) ) { // was /
426  foundFlag = true;
427  break;
428  }
429  augerIndex++;
430  }
431  if (partSum >= (partialProb*totalVacancyAugerProbability) ) {break;} // was /
432  transitionRandomShellIndex++;
433  }
434 
435  // Now we have the index of the shell from wich comes the auger electron (augerIndex),
436  // and the id of the shell, from which the transition e- come (transitionRandomShellid)
437  // If no Transition has been found, 0 is returned.
438 
439  if (!foundFlag) {return 0;}
440 
441  // Isotropic angular distribution for the outcoming e-
442  G4double newcosTh = 1.-2.*G4UniformRand();
443  G4double newsinTh = std::sqrt(1.-newcosTh*newcosTh);
444  G4double newPhi = twopi*G4UniformRand();
445 
446  G4double xDir = newsinTh*std::sin(newPhi);
447  G4double yDir = newsinTh*std::cos(newPhi);
448  G4double zDir = newcosTh;
449 
450  G4ThreeVector newElectronDirection(xDir,yDir,zDir);
451 
452  // energy of the auger electron emitted
453 
454 
455  G4double transitionEnergy = anAugerTransition->AugerTransitionEnergy(augerIndex, transitionRandomShellId);
456  /*
457  G4cout << "AUger TransitionId " << anAugerTransition->FinalShellId() << G4endl;
458  G4cout << "augerIndex: " << augerIndex << G4endl;
459  G4cout << "transitionShellId: " << transitionRandomShellId << G4endl;
460  */
461 
462  // This is the shell where the new vacancy is: it is the same
463  // shell where the electron came from
464  newShellId = transitionRandomShellId;
465 
466 
468  newElectronDirection,
469  transitionEnergy);
470  return newPart;
471 
472  }
473  else
474  {
475  //G4Exception("G4AtomicDeexcitation: no auger transition found");
476  return 0;
477  }
478 
479 }
480 
482 {
483  minGammaEnergy = cut;
484 }
485 
487 {
488  minElectronEnergy = cut;
489 }
490 
492 {
493  fAuger = val;
494 }
495 
496 
497 
498 
499 
500 
501 
G4double AugerTransitionProbability(G4int index, G4int startShellId) const
void SetCutForAugerElectrons(G4double cut)
CLHEP::Hep3Vector G4ThreeVector
void ActivateAugerElectronProduction(G4bool val)
const G4AugerTransition * ReachableAugerShell(G4int Z, G4int shellIndex) const
G4int NumberOfReachableShells(G4int Z) const
G4double AugerTransitionEnergy(G4int index, G4int startShellId) const
const G4DataVector & TransitionProbabilities() const
G4DynamicParticle * GenerateAuger(G4int Z, G4int shellId)
int G4int
Definition: G4Types.hh:78
G4int FinalShellId() const
G4int OriginatingShellId(G4int index) const
#define G4UniformRand()
Definition: Randomize.hh:97
G4GLOB_DLL std::ostream G4cout
bool G4bool
Definition: G4Types.hh:79
static const double twopi
Definition: G4SIunits.hh:75
G4int NumberOfReachableAugerShells(G4int Z) const
G4DynamicParticle * GenerateFluorescence(G4int Z, G4int shellId, G4int provShellId)
static G4Gamma * Gamma()
Definition: G4Gamma.cc:86
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static const double eV
Definition: G4SIunits.hh:212
G4int SelectTypeOfTransition(G4int Z, G4int shellId)
G4double TransitionProbability(G4int index) const
const G4FluoTransition * ReachableShell(G4int Z, size_t shellIndex) const
static G4Electron * Electron()
Definition: G4Electron.cc:94
#define G4endl
Definition: G4ios.hh:61
const std::vector< G4int > * TransitionOriginatingShellIds() const
std::vector< G4DynamicParticle * > * GenerateParticles(G4int Z, G4int shellId)
double G4double
Definition: G4Types.hh:76
const G4DataVector * AugerTransitionProbabilities(G4int startShellId) const
void SetCutForSecondaryPhotons(G4double cut)
G4int FinalShellId() const
static G4AtomicTransitionManager * Instance()
static const G4double pos