source: trunk/source/processes/electromagnetic/lowenergy/src/G4AtomicDeexcitation.cc @ 991

Last change on this file since 991 was 991, checked in by garnier, 15 years ago

update

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