G4AtomicDeexcitation.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 //
00028 // Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
00029 //          Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
00030 //
00031 // History:
00032 // -----------
00033 //  
00034 //  16 Sept 2001  First committed to cvs
00035 //  12 Sep  2003  Bug in auger production fixed
00036 //
00037 // -------------------------------------------------------------------
00038 
00039 #include "G4AtomicDeexcitation.hh"
00040 #include "Randomize.hh"
00041 #include "G4PhysicalConstants.hh"
00042 #include "G4SystemOfUnits.hh"
00043 #include "G4Gamma.hh"
00044 #include "G4Electron.hh"
00045 #include "G4AtomicTransitionManager.hh"
00046 #include "G4FluoTransition.hh"
00047 
00048 G4AtomicDeexcitation::G4AtomicDeexcitation():
00049   minGammaEnergy(100.*eV),
00050   minElectronEnergy(100.*eV),
00051   fAuger(false)
00052 {
00053 
00054   G4cout << " ********************************************************** " << G4endl; 
00055   G4cout << " *                  W A R N I N G ! ! !                   * " << G4endl;
00056   G4cout << " ********************************************************** " << G4endl;
00057   G4cout << " *                                                        * " << G4endl; 
00058   G4cout << " *  Class G4AtomicDeexcitation is obsolete. It has been   * " << G4endl;
00059   G4cout << " * discontinued and is going to be removed by next Geant4 * " << G4endl; 
00060   G4cout << " *     release please migrate to G4UAtomDeexcitation.     * " << G4endl;
00061   G4cout << " *                                                        * " << G4endl;
00062   G4cout << " ********************************************************** " << G4endl; 
00063 
00064   augerVacancyId=0;
00065   newShellId=0;
00066 }
00067 
00068 G4AtomicDeexcitation::~G4AtomicDeexcitation()
00069 {}
00070 
00071 std::vector<G4DynamicParticle*>* G4AtomicDeexcitation::GenerateParticles(G4int Z,G4int givenShellId)
00072 { 
00073 
00074   std::vector<G4DynamicParticle*>* vectorOfParticles;
00075   vectorOfParticles = new std::vector<G4DynamicParticle*>;
00076 
00077   G4DynamicParticle* aParticle;
00078   G4int provShellId = 0;
00079   G4int counter = 0;
00080   
00081   // The aim of this loop is to generate more than one fluorecence photon 
00082   // from the same ionizing event 
00083   do
00084     {
00085       if (counter == 0) 
00086         // First call to GenerateParticles(...):
00087         // givenShellId is given by the process
00088         {
00089           provShellId = SelectTypeOfTransition(Z, givenShellId);
00090           
00091           if  ( provShellId >0) 
00092             {
00093               aParticle = GenerateFluorescence(Z,givenShellId,provShellId);  
00094             }
00095           else if ( provShellId == -1)
00096             {
00097               aParticle = GenerateAuger(Z, givenShellId);
00098             }
00099           else
00100             {
00101               G4Exception("G4AtomicDeexcitation::Constructor", "de0002", JustWarning, "Transition selection invalid, energy local deposited");
00102             }
00103         }
00104       else 
00105         // Following calls to GenerateParticles(...):
00106         // newShellId is given by GenerateFluorescence(...)
00107         {
00108           provShellId = SelectTypeOfTransition(Z,newShellId);
00109           if  (provShellId >0)
00110             {
00111               aParticle = GenerateFluorescence(Z,newShellId,provShellId);
00112             }
00113           else if ( provShellId == -1)
00114             {
00115               aParticle = GenerateAuger(Z, newShellId);
00116             }
00117           else
00118             {
00119               G4Exception("G4AtomicDeexcitation::constructor", "de0002", JustWarning, "Transition selection invalid, energy local deposited" );
00120             }
00121         }
00122       counter++;
00123       if (aParticle != 0) {vectorOfParticles->push_back(aParticle);}
00124       else {provShellId = -2;}
00125     }
00126   
00127   // Look this in a particular way: only one auger emitted! // ????
00128   while (provShellId > -2); 
00129 
00130   // debug  
00131   // if (vectorOfParticles->size() > 0) {
00132   //   G4cout << " DEEXCITATION!" << G4endl;
00133   // }
00134 
00135   return vectorOfParticles;
00136 }
00137 
00138 G4int G4AtomicDeexcitation::SelectTypeOfTransition(G4int Z, G4int shellId)
00139 {
00140   if (shellId <=0 ) 
00141     {G4Exception("G4AtomicDeexcitation::SelectTypeOfTransition()","de0002", JustWarning ,"zero or negative shellId");}
00142 
00143   //G4bool fluoTransitionFoundFlag = false;
00144   
00145   const G4AtomicTransitionManager*  transitionManager = 
00146         G4AtomicTransitionManager::Instance();
00147   G4int provShellId = -1;
00148   G4int shellNum = 0;
00149   G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);  
00150   
00151   const G4FluoTransition* refShell = transitionManager->ReachableShell(Z,maxNumOfShells-1);
00152 
00153   // This loop gives shellNum the value of the index of shellId
00154   // in the vector storing the list of the shells reachable through
00155   // a radiative transition
00156   if ( shellId <= refShell->FinalShellId())
00157     {
00158       while (shellId != transitionManager->ReachableShell(Z,shellNum)->FinalShellId())
00159         {
00160           if(shellNum ==maxNumOfShells-1)
00161             {
00162               break;
00163             }
00164           shellNum++;
00165         }
00166       G4int transProb = 0; //AM change 29/6/07 was 1
00167    
00168       G4double partialProb = G4UniformRand();      
00169       G4double partSum = 0;
00170       const G4FluoTransition* aShell = transitionManager->ReachableShell(Z,shellNum);      
00171       G4int trSize =  (aShell->TransitionProbabilities()).size();
00172     
00173       // Loop over the shells wich can provide an electron for a 
00174       // radiative transition towards shellId:
00175       // in every loop the partial sum of the first transProb shells
00176       // is calculated and compared with a random number [0,1].
00177       // If the partial sum is greater, the shell whose index is transProb
00178       // is chosen as the starting shell for a radiative transition
00179       // and its identity is returned
00180       // Else, terminateded the loop, -1 is returned
00181       while(transProb < trSize){
00182         
00183          partSum += aShell->TransitionProbability(transProb);
00184 
00185          if(partialProb <= partSum)
00186            {
00187              provShellId = aShell->OriginatingShellId(transProb);
00188              //fluoTransitionFoundFlag = true;
00189 
00190              break;
00191            }
00192          transProb++;
00193       }
00194 
00195       // here provShellId is the right one or is -1.
00196       // if -1, the control is passed to the Auger generation part of the package 
00197     }
00198 
00199 
00200 
00201   else 
00202     {
00203  
00204      provShellId = -1;
00205 
00206     }
00207   return provShellId;
00208 }
00209 
00210 G4DynamicParticle* G4AtomicDeexcitation::GenerateFluorescence(G4int Z, 
00211                                                               G4int shellId,
00212                                                               G4int provShellId )
00213 { 
00214 
00215 
00216   const G4AtomicTransitionManager*  transitionManager = G4AtomicTransitionManager::Instance();
00217   //  G4int provenienceShell = provShellId;
00218 
00219   //isotropic angular distribution for the outcoming photon
00220   G4double newcosTh = 1.-2.*G4UniformRand();
00221   G4double  newsinTh = std::sqrt(1.-newcosTh*newcosTh);
00222   G4double newPhi = twopi*G4UniformRand();
00223   
00224   G4double xDir =  newsinTh*std::sin(newPhi);
00225   G4double yDir = newsinTh*std::cos(newPhi);
00226   G4double zDir = newcosTh;
00227   
00228   G4ThreeVector newGammaDirection(xDir,yDir,zDir);
00229   
00230   G4int shellNum = 0;
00231   G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);
00232   
00233   // find the index of the shell named shellId
00234   while (shellId != transitionManager->
00235          ReachableShell(Z,shellNum)->FinalShellId())
00236     {
00237       if(shellNum == maxNumOfShells-1)
00238         {
00239           break;
00240         }
00241       shellNum++;
00242     }
00243   // number of shell from wich an electron can reach shellId
00244   size_t transitionSize = transitionManager->
00245     ReachableShell(Z,shellNum)->OriginatingShellIds().size();
00246   
00247   size_t index = 0;
00248   
00249   // find the index of the shell named provShellId in the vector
00250   // storing the shells from which shellId can be reached 
00251   while (provShellId != transitionManager->
00252          ReachableShell(Z,shellNum)->OriginatingShellId(index))
00253     {
00254       if(index ==  transitionSize-1)
00255         {
00256           break;
00257         }
00258       index++;
00259     }
00260   // energy of the gamma leaving provShellId for shellId
00261   G4double transitionEnergy = transitionManager->
00262     ReachableShell(Z,shellNum)->TransitionEnergy(index);
00263   
00264   // This is the shell where the new vacancy is: it is the same
00265   // shell where the electron came from
00266   newShellId = transitionManager->
00267     ReachableShell(Z,shellNum)->OriginatingShellId(index);
00268   
00269   
00270   G4DynamicParticle* newPart = new G4DynamicParticle(G4Gamma::Gamma(), 
00271                                                      newGammaDirection,
00272                                                      transitionEnergy);
00273   return newPart;
00274 }
00275 
00276 G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
00277 {
00278   if(!fAuger) return 0;
00279   
00280 
00281   const G4AtomicTransitionManager*  transitionManager = 
00282         G4AtomicTransitionManager::Instance();
00283 
00284 
00285 
00286   if (shellId <=0 ) 
00287     {G4Exception("G4AtomicDeexcitation::GenerateAuger()","de0002", JustWarning ,"zero or negative shellId");}
00288   
00289   // G4int provShellId = -1;
00290   G4int maxNumOfShells = transitionManager->NumberOfReachableAugerShells(Z);  
00291   
00292   const G4AugerTransition* refAugerTransition = 
00293         transitionManager->ReachableAugerShell(Z,maxNumOfShells-1);
00294 
00295 
00296   // This loop gives to shellNum the value of the index of shellId
00297   // in the vector storing the list of the vacancies in the variuos shells 
00298   // that can originate a NON-radiative transition
00299   
00300   // ---- MGP ---- Next line commented out to remove compilation warning
00301   // G4int p = refAugerTransition->FinalShellId();
00302 
00303   G4int shellNum = 0;
00304 
00305 
00306   if ( shellId <= refAugerTransition->FinalShellId() ) 
00307     //"FinalShellId" is final from the point of view of the elctron who makes the transition, 
00308     // being the Id of the shell in which there is a vacancy
00309     {
00310       G4int pippo = transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId();
00311       if (shellId  != pippo ) {
00312         do { 
00313           shellNum++;
00314           if(shellNum == maxNumOfShells)
00315             {
00316 
00317               //G4Exception("G4AtomicDeexcitation: No Auger transition found");
00318               return 0;
00319             }
00320         }
00321         while (shellId != (transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId()) ) ;
00322       }
00323 
00324 
00325       // Now we have that shellnum is the shellIndex of the shell named ShellId
00326 
00327       //      G4cout << " the index of the shell is: "<<shellNum<<G4endl;
00328 
00329       // But we have now to select two shells: one for the transition, 
00330       // and another for the auger emission.
00331 
00332       G4int transitionLoopShellIndex = 0;      
00333       G4double partSum = 0;
00334       const G4AugerTransition* anAugerTransition = 
00335             transitionManager->ReachableAugerShell(Z,shellNum);
00336 
00337       //      G4cout << " corresponding to the ID: "<< anAugerTransition->FinalShellId() << G4endl;
00338 
00339 
00340       G4int transitionSize = 
00341             (anAugerTransition->TransitionOriginatingShellIds())->size();
00342       while (transitionLoopShellIndex < transitionSize) {
00343 
00344         std::vector<G4int>::const_iterator pos = 
00345                anAugerTransition->TransitionOriginatingShellIds()->begin();
00346 
00347         G4int transitionLoopShellId = *(pos+transitionLoopShellIndex);
00348         G4int numberOfPossibleAuger = 
00349               (anAugerTransition->AugerTransitionProbabilities(transitionLoopShellId))->size();
00350         G4int augerIndex = 0;
00351         //      G4int partSum2 = 0;
00352 
00353 
00354         if (augerIndex < numberOfPossibleAuger) {
00355           
00356           do 
00357             {
00358               G4double thisProb = anAugerTransition->AugerTransitionProbability(augerIndex, 
00359                                                                                 transitionLoopShellId);
00360               partSum += thisProb;
00361               augerIndex++;
00362               
00363             } while (augerIndex < numberOfPossibleAuger);
00364                 }
00365         transitionLoopShellIndex++;
00366       }
00367       
00368 
00369 
00370       // Now we have the entire probability of an auger transition for the vacancy 
00371       // located in shellNum (index of shellId) 
00372 
00373       // AM *********************** F I X E D **************************** AM
00374       // Here we duplicate the previous loop, this time looking to the sum of the probabilities 
00375       // to be under the random number shoot by G4 UniformRdandom. This could have been done in the 
00376       // previuos loop, while integrating the probabilities. There is a bug that will be fixed 
00377       // 5 minutes from now: a line:
00378       // G4int numberOfPossibleAuger = (anAugerTransition->
00379       // AugerTransitionProbabilities(transitionLoopShellId))->size();
00380       // to be inserted.
00381       // AM *********************** F I X E D **************************** AM
00382 
00383       // Remains to get the same result with a single loop.
00384 
00385       // AM *********************** F I X E D **************************** AM
00386       // Another Bug: in EADL Auger Transition are normalized to all the transitions deriving from 
00387       // a vacancy in one shell, but not all of these are present in data tables. So if a transition 
00388       // doesn't occur in the main one a local energy deposition must occur, instead of (like now) 
00389       // generating the last transition present in EADL data.
00390       // AM *********************** F I X E D **************************** AM
00391 
00392 
00393       G4double totalVacancyAugerProbability = partSum;
00394 
00395 
00396       //And now we start to select the right auger transition and emission
00397       G4int transitionRandomShellIndex = 0;
00398       G4int transitionRandomShellId = 1;
00399       G4int augerIndex = 0;
00400       partSum = 0; 
00401       G4double partialProb = G4UniformRand();
00402       // G4int augerOriginatingShellId = 0;
00403       
00404       G4int numberOfPossibleAuger = 0;
00405       
00406       G4bool foundFlag = false;
00407 
00408       while (transitionRandomShellIndex < transitionSize) {
00409 
00410         std::vector<G4int>::const_iterator pos = 
00411                anAugerTransition->TransitionOriginatingShellIds()->begin();
00412 
00413         transitionRandomShellId = *(pos+transitionRandomShellIndex);
00414         
00415         augerIndex = 0;
00416         numberOfPossibleAuger = (anAugerTransition-> 
00417                                  AugerTransitionProbabilities(transitionRandomShellId))->size();
00418 
00419         while (augerIndex < numberOfPossibleAuger) {
00420           G4double thisProb =anAugerTransition->AugerTransitionProbability(augerIndex, 
00421                                                                            transitionRandomShellId);
00422 
00423           partSum += thisProb;
00424           
00425           if (partSum >= (partialProb*totalVacancyAugerProbability) ) { // was /
00426             foundFlag = true;
00427             break;
00428           }
00429           augerIndex++;
00430         }
00431         if (partSum >= (partialProb*totalVacancyAugerProbability) ) {break;} // was /
00432         transitionRandomShellIndex++;
00433       }
00434 
00435       // Now we have the index of the shell from wich comes the auger electron (augerIndex), 
00436       // and the id of the shell, from which the transition e- come (transitionRandomShellid)
00437       // If no Transition has been found, 0 is returned.  
00438 
00439       if (!foundFlag) {return 0;}      
00440       
00441       // Isotropic angular distribution for the outcoming e-
00442       G4double newcosTh = 1.-2.*G4UniformRand();
00443       G4double  newsinTh = std::sqrt(1.-newcosTh*newcosTh);
00444       G4double newPhi = twopi*G4UniformRand();
00445       
00446       G4double xDir =  newsinTh*std::sin(newPhi);
00447       G4double yDir = newsinTh*std::cos(newPhi);
00448       G4double zDir = newcosTh;
00449       
00450       G4ThreeVector newElectronDirection(xDir,yDir,zDir);
00451       
00452       // energy of the auger electron emitted
00453       
00454       
00455       G4double transitionEnergy = anAugerTransition->AugerTransitionEnergy(augerIndex, transitionRandomShellId);
00456       /*
00457         G4cout << "AUger TransitionId " << anAugerTransition->FinalShellId() << G4endl;
00458         G4cout << "augerIndex: " << augerIndex << G4endl;
00459         G4cout << "transitionShellId: " << transitionRandomShellId << G4endl;
00460       */
00461       
00462       // This is the shell where the new vacancy is: it is the same
00463       // shell where the electron came from
00464       newShellId = transitionRandomShellId;
00465       
00466       
00467       G4DynamicParticle* newPart = new G4DynamicParticle(G4Electron::Electron(), 
00468                                                          newElectronDirection,
00469                                                          transitionEnergy);
00470       return newPart;
00471 
00472     }
00473   else 
00474     {
00475       //G4Exception("G4AtomicDeexcitation: no auger transition found");
00476       return 0;
00477     }
00478   
00479 }
00480 
00481 void G4AtomicDeexcitation::SetCutForSecondaryPhotons(G4double cut)
00482 {
00483   minGammaEnergy = cut;
00484 }
00485 
00486 void G4AtomicDeexcitation::SetCutForAugerElectrons(G4double cut)
00487 {
00488   minElectronEnergy = cut;
00489 }
00490 
00491 void G4AtomicDeexcitation::ActivateAugerElectronProduction(G4bool val)
00492 {
00493   fAuger = val;
00494 }
00495 
00496 
00497 
00498 
00499 
00500 
00501 

Generated on Mon May 27 17:47:41 2013 for Geant4 by  doxygen 1.4.7