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

Last change on this file since 1315 was 1315, checked in by garnier, 14 years ago

update geant4-09-04-beta-cand-01 interfaces-V09-03-09 vis-V09-03-08

File size: 15.4 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-04-beta-cand-01 $
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
298              //G4Exception("G4AtomicDeexcitation: No Auger transition found");
299              return 0;
300            }
301        }
302        while (shellId != (transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId()) ) ;
303      }
304
305
306      // Now we have that shellnum is the shellIndex of the shell named ShellId
307
308      //      G4cout << " the index of the shell is: "<<shellNum<<G4endl;
309
310      // But we have now to select two shells: one for the transition,
311      // and another for the auger emission.
312
313      G4int transitionLoopShellIndex = 0;     
314      G4double partSum = 0;
315      const G4AugerTransition* anAugerTransition = 
316            transitionManager->ReachableAugerShell(Z,shellNum);
317
318      //      G4cout << " corresponding to the ID: "<< anAugerTransition->FinalShellId() << G4endl;
319
320
321      G4int transitionSize = 
322            (anAugerTransition->TransitionOriginatingShellIds())->size();
323      while (transitionLoopShellIndex < transitionSize) {
324
325        std::vector<G4int>::const_iterator pos = 
326               anAugerTransition->TransitionOriginatingShellIds()->begin();
327
328        G4int transitionLoopShellId = *(pos+transitionLoopShellIndex);
329        G4int numberOfPossibleAuger = 
330              (anAugerTransition->AugerTransitionProbabilities(transitionLoopShellId))->size();
331        G4int augerIndex = 0;
332        //      G4int partSum2 = 0;
333
334
335        if (augerIndex < numberOfPossibleAuger) {
336         
337          do 
338            {
339              G4double thisProb = anAugerTransition->AugerTransitionProbability(augerIndex, 
340                                                                                transitionLoopShellId);
341              partSum += thisProb;
342              augerIndex++;
343             
344            } while (augerIndex < numberOfPossibleAuger);
345                }
346        transitionLoopShellIndex++;
347      }
348     
349
350
351      // Now we have the entire probability of an auger transition for the vacancy
352      // located in shellNum (index of shellId)
353
354      // AM *********************** F I X E D **************************** AM
355      // Here we duplicate the previous loop, this time looking to the sum of the probabilities
356      // to be under the random number shoot by G4 UniformRdandom. This could have been done in the
357      // previuos loop, while integrating the probabilities. There is a bug that will be fixed
358      // 5 minutes from now: a line:
359      // G4int numberOfPossibleAuger = (anAugerTransition->
360      // AugerTransitionProbabilities(transitionLoopShellId))->size();
361      // to be inserted.
362      // AM *********************** F I X E D **************************** AM
363
364      // Remains to get the same result with a single loop.
365
366      // AM *********************** F I X E D **************************** AM
367      // Another Bug: in EADL Auger Transition are normalized to all the transitions deriving from
368      // a vacancy in one shell, but not all of these are present in data tables. So if a transition
369      // doesn't occur in the main one a local energy deposition must occur, instead of (like now)
370      // generating the last transition present in EADL data.
371      // AM *********************** F I X E D **************************** AM
372
373
374      G4double totalVacancyAugerProbability = partSum;
375
376
377      //And now we start to select the right auger transition and emission
378      G4int transitionRandomShellIndex = 0;
379      G4int transitionRandomShellId = 1;
380      G4int augerIndex = 0;
381      partSum = 0; 
382      G4double partialProb = G4UniformRand();
383      // G4int augerOriginatingShellId = 0;
384     
385      G4int numberOfPossibleAuger = 0;
386     
387      G4bool foundFlag = false;
388
389      while (transitionRandomShellIndex < transitionSize) {
390
391        std::vector<G4int>::const_iterator pos = 
392               anAugerTransition->TransitionOriginatingShellIds()->begin();
393
394        transitionRandomShellId = *(pos+transitionRandomShellIndex);
395       
396        augerIndex = 0;
397        numberOfPossibleAuger = (anAugerTransition-> 
398                                 AugerTransitionProbabilities(transitionRandomShellId))->size();
399
400        while (augerIndex < numberOfPossibleAuger) {
401          G4double thisProb =anAugerTransition->AugerTransitionProbability(augerIndex, 
402                                                                           transitionRandomShellId);
403
404          partSum += thisProb;
405         
406          if (partSum >= (partialProb*totalVacancyAugerProbability) ) { // was /
407            foundFlag = true;
408            break;
409          }
410          augerIndex++;
411        }
412        if (partSum >= (partialProb*totalVacancyAugerProbability) ) {break;} // was /
413        transitionRandomShellIndex++;
414      }
415
416      // Now we have the index of the shell from wich comes the auger electron (augerIndex),
417      // and the id of the shell, from which the transition e- come (transitionRandomShellid)
418      // If no Transition has been found, 0 is returned. 
419
420      if (!foundFlag) {return 0;}     
421     
422      // Isotropic angular distribution for the outcoming e-
423      G4double newcosTh = 1.-2.*G4UniformRand();
424      G4double  newsinTh = std::sqrt(1.-newcosTh*newcosTh);
425      G4double newPhi = twopi*G4UniformRand();
426     
427      G4double xDir =  newsinTh*std::sin(newPhi);
428      G4double yDir = newsinTh*std::cos(newPhi);
429      G4double zDir = newcosTh;
430     
431      G4ThreeVector newElectronDirection(xDir,yDir,zDir);
432     
433      // energy of the auger electron emitted
434     
435     
436      G4double transitionEnergy = anAugerTransition->AugerTransitionEnergy(augerIndex, transitionRandomShellId);
437      /*
438        G4cout << "AUger TransitionId " << anAugerTransition->FinalShellId() << G4endl;
439        G4cout << "augerIndex: " << augerIndex << G4endl;
440        G4cout << "transitionShellId: " << transitionRandomShellId << G4endl;
441      */
442     
443      // This is the shell where the new vacancy is: it is the same
444      // shell where the electron came from
445      newShellId = transitionRandomShellId;
446     
447     
448      G4DynamicParticle* newPart = new G4DynamicParticle(G4Electron::Electron(), 
449                                                         newElectronDirection,
450                                                         transitionEnergy);
451      return newPart;
452
453    }
454  else 
455    {
456      //G4Exception("G4AtomicDeexcitation: no auger transition found");
457      return 0;
458    }
459 
460}
461
462void G4AtomicDeexcitation::SetCutForSecondaryPhotons(G4double cut)
463{
464  minGammaEnergy = cut;
465}
466
467void G4AtomicDeexcitation::SetCutForAugerElectrons(G4double cut)
468{
469  minElectronEnergy = cut;
470}
471
472void G4AtomicDeexcitation::ActivateAugerElectronProduction(G4bool val)
473{
474  fAuger = val;
475}
476
477
478
479
480
481
482
Note: See TracBrowser for help on using the repository browser.