source: trunk/source/processes/electromagnetic/lowenergy/src/G4UAtomicDeexcitation.cc @ 1350

Last change on this file since 1350 was 1350, checked in by garnier, 13 years ago

update to last version 4.9.4

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