#include <G4PenelopePhotoElectricModel.hh>
Inheritance diagram for G4PenelopePhotoElectricModel:
Public Member Functions | |
G4PenelopePhotoElectricModel (const G4ParticleDefinition *p=0, const G4String &processName="PenPhotoElec") | |
virtual | ~G4PenelopePhotoElectricModel () |
virtual void | Initialise (const G4ParticleDefinition *, const G4DataVector &) |
virtual G4double | ComputeCrossSectionPerAtom (const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) |
virtual void | SampleSecondaries (std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) |
void | SetVerbosityLevel (G4int lev) |
G4int | GetVerbosityLevel () |
size_t | GetNumberOfShellXS (G4int) |
G4double | GetShellCrossSection (G4int Z, size_t shellID, G4double energy) |
Protected Attributes | |
G4ParticleChangeForGamma * | fParticleChange |
Definition at line 58 of file G4PenelopePhotoElectricModel.hh.
G4PenelopePhotoElectricModel::G4PenelopePhotoElectricModel | ( | const G4ParticleDefinition * | p = 0 , |
|
const G4String & | processName = "PenPhotoElec" | |||
) |
Definition at line 60 of file G4PenelopePhotoElectricModel.cc.
References G4AtomicTransitionManager::Instance(), G4VEmModel::SetDeexcitationFlag(), and G4VEmModel::SetHighEnergyLimit().
00062 :G4VEmModel(nam),fParticleChange(0),isInitialised(false),fAtomDeexcitation(0), 00063 logAtomicShellXS(0) 00064 { 00065 fIntrinsicLowEnergyLimit = 100.0*eV; 00066 fIntrinsicHighEnergyLimit = 100.0*GeV; 00067 // SetLowEnergyLimit(fIntrinsicLowEnergyLimit); 00068 SetHighEnergyLimit(fIntrinsicHighEnergyLimit); 00069 // 00070 verboseLevel= 0; 00071 // Verbosity scale: 00072 // 0 = nothing 00073 // 1 = warning for energy non-conservation 00074 // 2 = details of energy budget 00075 // 3 = calculation of cross sections, file openings, sampling of atoms 00076 // 4 = entering in methods 00077 00078 //Mark this model as "applicable" for atomic deexcitation 00079 SetDeexcitationFlag(true); 00080 00081 fTransitionManager = G4AtomicTransitionManager::Instance(); 00082 }
G4PenelopePhotoElectricModel::~G4PenelopePhotoElectricModel | ( | ) | [virtual] |
Definition at line 86 of file G4PenelopePhotoElectricModel.cc.
00087 { 00088 std::map <G4int,G4PhysicsTable*>::iterator i; 00089 if (logAtomicShellXS) 00090 { 00091 for (i=logAtomicShellXS->begin();i != logAtomicShellXS->end();i++) 00092 { 00093 G4PhysicsTable* tab = i->second; 00094 tab->clearAndDestroy(); 00095 delete tab; 00096 } 00097 } 00098 delete logAtomicShellXS; 00099 }
G4double G4PenelopePhotoElectricModel::ComputeCrossSectionPerAtom | ( | const G4ParticleDefinition * | , | |
G4double | kinEnergy, | |||
G4double | Z, | |||
G4double | A = 0 , |
|||
G4double | cut = 0 , |
|||
G4double | emax = DBL_MAX | |||
) | [virtual] |
Reimplemented from G4VEmModel.
Definition at line 141 of file G4PenelopePhotoElectricModel.cc.
References FatalException, G4cout, G4endl, G4Exception(), and G4PhysicsVector::Value().
00146 { 00147 // 00148 // Penelope model v2008 00149 // 00150 00151 if (verboseLevel > 3) 00152 G4cout << "Calling ComputeCrossSectionPerAtom() of G4PenelopePhotoElectricModel" << G4endl; 00153 00154 G4int iZ = (G4int) Z; 00155 00156 //read data files 00157 if (!logAtomicShellXS->count(iZ)) 00158 ReadDataFile(iZ); 00159 //now it should be ok 00160 if (!logAtomicShellXS->count(iZ)) 00161 G4Exception("G4PenelopePhotoElectricModel::ComputeCrossSectionPerAtom()", 00162 "em2038",FatalException, 00163 "Unable to retrieve the shell cross section table"); 00164 00165 G4double cross = 0; 00166 00167 G4PhysicsTable* theTable = logAtomicShellXS->find(iZ)->second; 00168 G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[0]; 00169 00170 if (!totalXSLog) 00171 { 00172 G4Exception("G4PenelopePhotoElectricModel::ComputeCrossSectionPerAtom()", 00173 "em2039",FatalException, 00174 "Unable to retrieve the total cross section table"); 00175 return 0; 00176 } 00177 G4double logene = std::log(energy); 00178 G4double logXS = totalXSLog->Value(logene); 00179 cross = std::exp(logXS); 00180 00181 if (verboseLevel > 2) 00182 G4cout << "Photoelectric cross section at " << energy/MeV << " MeV for Z=" << Z << 00183 " = " << cross/barn << " barn" << G4endl; 00184 return cross; 00185 }
size_t G4PenelopePhotoElectricModel::GetNumberOfShellXS | ( | G4int | ) |
Definition at line 620 of file G4PenelopePhotoElectricModel.cc.
References FatalException, and G4Exception().
Referenced by GetShellCrossSection().
00621 { 00622 //read data files 00623 if (!logAtomicShellXS->count(Z)) 00624 ReadDataFile(Z); 00625 //now it should be ok 00626 if (!logAtomicShellXS->count(Z)) 00627 { 00628 G4ExceptionDescription ed; 00629 ed << "Cannot find shell cross section data for Z=" << Z << G4endl; 00630 G4Exception("G4PenelopePhotoElectricModel::GetNumberOfShellXS()", 00631 "em2038",FatalException,ed); 00632 } 00633 //one vector is allocated for the _total_ cross section 00634 size_t nEntries = logAtomicShellXS->find(Z)->second->entries(); 00635 return (nEntries-1); 00636 }
G4double G4PenelopePhotoElectricModel::GetShellCrossSection | ( | G4int | Z, | |
size_t | shellID, | |||
G4double | energy | |||
) |
Definition at line 640 of file G4PenelopePhotoElectricModel.cc.
References FatalException, G4cout, G4Exception(), GetNumberOfShellXS(), and G4PhysicsVector::Value().
00641 { 00642 //this forces also the loading of the data 00643 size_t entries = GetNumberOfShellXS(Z); 00644 00645 if (shellID >= entries) 00646 { 00647 G4cout << "Element Z=" << Z << " has data for " << entries << " shells only" << G4endl; 00648 G4cout << "so shellID should be from 0 to " << entries-1 << G4endl; 00649 return 0; 00650 } 00651 00652 G4PhysicsTable* theTable = logAtomicShellXS->find(Z)->second; 00653 //[0] is the total XS, shellID is in the element [shellID+1] 00654 G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[shellID+1]; 00655 00656 if (!totalXSLog) 00657 { 00658 G4Exception("G4PenelopePhotoElectricModel::GetShellCrossSection()", 00659 "em2039",FatalException, 00660 "Unable to retrieve the total cross section table"); 00661 return 0; 00662 } 00663 G4double logene = std::log(energy); 00664 G4double logXS = totalXSLog->Value(logene); 00665 G4double cross = std::exp(logXS); 00666 if (cross < 2e-40*cm2) cross = 0; 00667 return cross; 00668 }
G4int G4PenelopePhotoElectricModel::GetVerbosityLevel | ( | ) | [inline] |
void G4PenelopePhotoElectricModel::Initialise | ( | const G4ParticleDefinition * | , | |
const G4DataVector & | ||||
) | [virtual] |
Implements G4VEmModel.
Definition at line 103 of file G4PenelopePhotoElectricModel.cc.
References G4LossTableManager::AtomDeexcitation(), fParticleChange, G4cout, G4endl, G4VEmModel::GetParticleChangeForGamma(), G4VEmModel::HighEnergyLimit(), G4VEmModel::InitialiseElementSelectors(), G4LossTableManager::Instance(), and G4VEmModel::LowEnergyLimit().
00105 { 00106 if (verboseLevel > 3) 00107 G4cout << "Calling G4PenelopePhotoElectricModel::Initialise()" << G4endl; 00108 00109 // logAtomicShellXS is created only once, since it is never cleared 00110 if (!logAtomicShellXS) 00111 logAtomicShellXS = new std::map<G4int,G4PhysicsTable*>; 00112 00113 InitialiseElementSelectors(particle,cuts); 00114 00115 fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation(); 00116 //Issue warning if the AtomicDeexcitation has not been declared 00117 if (!fAtomDeexcitation) 00118 { 00119 G4cout << G4endl; 00120 G4cout << "WARNING from G4PenelopePhotoElectricModel " << G4endl; 00121 G4cout << "Atomic de-excitation module is not instantiated, so there will not be "; 00122 G4cout << "any fluorescence/Auger emission." << G4endl; 00123 G4cout << "Please make sure this is intended" << G4endl; 00124 } 00125 00126 if (verboseLevel > 0) { 00127 G4cout << "Penelope Photo-Electric model v2008 is initialized " << G4endl 00128 << "Energy range: " 00129 << LowEnergyLimit() / MeV << " MeV - " 00130 << HighEnergyLimit() / GeV << " GeV"; 00131 } 00132 00133 if(isInitialised) return; 00134 fParticleChange = GetParticleChangeForGamma(); 00135 isInitialised = true; 00136 00137 }
void G4PenelopePhotoElectricModel::SampleSecondaries | ( | std::vector< G4DynamicParticle * > * | , | |
const G4MaterialCutsCouple * | , | |||
const G4DynamicParticle * | , | |||
G4double | tmin, | |||
G4double | maxEnergy | |||
) | [virtual] |
Implements G4VEmModel.
Definition at line 189 of file G4PenelopePhotoElectricModel.cc.
References G4AtomicShell::BindingEnergy(), G4InuclSpecialFunctions::bindingEnergy(), G4VAtomDeexcitation::CheckDeexcitationActiveRegion(), G4Electron::Definition(), G4Gamma::Definition(), G4Electron::Electron(), fParticleChange, fStopAndKill, G4cout, G4endl, G4UniformRand, G4Gamma::GammaDefinition(), G4VAtomDeexcitation::GenerateParticles(), G4MaterialCutsCouple::GetIndex(), G4DynamicParticle::GetKineticEnergy(), G4MaterialCutsCouple::GetMaterial(), G4DynamicParticle::GetMomentumDirection(), G4Element::GetName(), G4Material::GetName(), G4Element::GetZ(), G4AtomicTransitionManager::Instance(), G4AtomicTransitionManager::NumberOfShells(), G4VParticleChange::ProposeLocalEnergyDeposit(), G4VParticleChange::ProposeTrackStatus(), G4VEmModel::SelectRandomAtom(), G4ParticleChangeForGamma::SetProposedKineticEnergy(), and G4AtomicTransitionManager::Shell().
00194 { 00195 // 00196 // Photoelectric effect, Penelope model v2008 00197 // 00198 // The target atom and the target shell are sampled according to the Livermore 00199 // database 00200 // D.E. Cullen et al., Report UCRL-50400 (1989) 00201 // The angular distribution of the electron in the final state is sampled 00202 // according to the Sauter distribution from 00203 // F. Sauter, Ann. Phys. 11 (1931) 454 00204 // The energy of the final electron is given by the initial photon energy minus 00205 // the binding energy. Fluorescence de-excitation is subsequently produced 00206 // (to fill the vacancy) according to the general Geant4 G4DeexcitationManager: 00207 // J. Stepanek, Comp. Phys. Comm. 1206 pp 1-1-9 (1997) 00208 00209 if (verboseLevel > 3) 00210 G4cout << "Calling SamplingSecondaries() of G4PenelopePhotoElectricModel" << G4endl; 00211 00212 G4double photonEnergy = aDynamicGamma->GetKineticEnergy(); 00213 00214 // always kill primary 00215 fParticleChange->ProposeTrackStatus(fStopAndKill); 00216 fParticleChange->SetProposedKineticEnergy(0.); 00217 00218 if (photonEnergy <= fIntrinsicLowEnergyLimit) 00219 { 00220 fParticleChange->ProposeLocalEnergyDeposit(photonEnergy); 00221 return ; 00222 } 00223 00224 G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection(); 00225 00226 // Select randomly one element in the current material 00227 if (verboseLevel > 2) 00228 G4cout << "Going to select element in " << couple->GetMaterial()->GetName() << G4endl; 00229 00230 // atom can be selected efficiently if element selectors are initialised 00231 const G4Element* anElement = 00232 SelectRandomAtom(couple,G4Gamma::GammaDefinition(),photonEnergy); 00233 G4int Z = (G4int) anElement->GetZ(); 00234 if (verboseLevel > 2) 00235 G4cout << "Selected " << anElement->GetName() << G4endl; 00236 00237 // Select the ionised shell in the current atom according to shell cross sections 00238 //shellIndex = 0 --> K shell 00239 // 1-3 --> L shells 00240 // 4-8 --> M shells 00241 // 9 --> outer shells cumulatively 00242 // 00243 size_t shellIndex = SelectRandomShell(Z,photonEnergy); 00244 00245 if (verboseLevel > 2) 00246 G4cout << "Selected shell " << shellIndex << " of element " << anElement->GetName() << G4endl; 00247 00248 // Retrieve the corresponding identifier and binding energy of the selected shell 00249 const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance(); 00250 00251 //The number of shell cross section possibly reported in the Penelope database 00252 //might be different from the number of shells in the G4AtomicTransitionManager 00253 //(namely, Penelope may contain more shell, especially for very light elements). 00254 //In order to avoid a warning message from the G4AtomicTransitionManager, I 00255 //add this protection. Results are anyway changed, because when G4AtomicTransitionManager 00256 //has a shellID>maxID, it sets the shellID to the last valid shell. 00257 size_t numberOfShells = (size_t) transitionManager->NumberOfShells(Z); 00258 if (shellIndex >= numberOfShells) 00259 shellIndex = numberOfShells-1; 00260 00261 const G4AtomicShell* shell = fTransitionManager->Shell(Z,shellIndex); 00262 G4double bindingEnergy = shell->BindingEnergy(); 00263 //G4int shellId = shell->ShellId(); 00264 00265 //Penelope considers only K, L and M shells. Cross sections of outer shells are 00266 //not included in the Penelope database. If SelectRandomShell() returns 00267 //shellIndex = 9, it means that an outer shell was ionized. In this case the 00268 //Penelope recipe is to set bindingEnergy = 0 (the energy is entirely assigned 00269 //to the electron) and to disregard fluorescence. 00270 if (shellIndex == 9) 00271 bindingEnergy = 0.*eV; 00272 00273 00274 G4double localEnergyDeposit = 0.0; 00275 G4double cosTheta = 1.0; 00276 00277 // Primary outcoming electron 00278 G4double eKineticEnergy = photonEnergy - bindingEnergy; 00279 00280 // There may be cases where the binding energy of the selected shell is > photon energy 00281 // In such cases do not generate secondaries 00282 if (eKineticEnergy > 0.) 00283 { 00284 // The electron is created 00285 // Direction sampled from the Sauter distribution 00286 cosTheta = SampleElectronDirection(eKineticEnergy); 00287 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta); 00288 G4double phi = twopi * G4UniformRand() ; 00289 G4double dirx = sinTheta * std::cos(phi); 00290 G4double diry = sinTheta * std::sin(phi); 00291 G4double dirz = cosTheta ; 00292 G4ThreeVector electronDirection(dirx,diry,dirz); //electron direction 00293 electronDirection.rotateUz(photonDirection); 00294 G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(), 00295 electronDirection, 00296 eKineticEnergy); 00297 fvect->push_back(electron); 00298 } 00299 else 00300 bindingEnergy = photonEnergy; 00301 00302 00303 G4double energyInFluorescence = 0; //testing purposes 00304 G4double energyInAuger = 0; //testing purposes 00305 00306 //Now, take care of fluorescence, if required. According to the Penelope 00307 //recipe, I have to skip fluoresence completely if shellIndex == 9 00308 //(= sampling of a shell outer than K,L,M) 00309 if (fAtomDeexcitation && shellIndex<9) 00310 { 00311 G4int index = couple->GetIndex(); 00312 if (fAtomDeexcitation->CheckDeexcitationActiveRegion(index)) 00313 { 00314 size_t nBefore = fvect->size(); 00315 fAtomDeexcitation->GenerateParticles(fvect,shell,Z,index); 00316 size_t nAfter = fvect->size(); 00317 00318 if (nAfter > nBefore) //actual production of fluorescence 00319 { 00320 for (size_t j=nBefore;j<nAfter;j++) //loop on products 00321 { 00322 G4double itsEnergy = ((*fvect)[j])->GetKineticEnergy(); 00323 bindingEnergy -= itsEnergy; 00324 if (((*fvect)[j])->GetParticleDefinition() == G4Gamma::Definition()) 00325 energyInFluorescence += itsEnergy; 00326 else if (((*fvect)[j])->GetParticleDefinition() == G4Electron::Definition()) 00327 energyInAuger += itsEnergy; 00328 00329 } 00330 } 00331 00332 } 00333 } 00334 00335 //Residual energy is deposited locally 00336 localEnergyDeposit += bindingEnergy; 00337 00338 if (localEnergyDeposit < 0) 00339 { 00340 G4cout << "WARNING - " 00341 << "G4PenelopePhotoElectricModel::SampleSecondaries() - Negative energy deposit" 00342 << G4endl; 00343 localEnergyDeposit = 0; 00344 } 00345 00346 fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit); 00347 00348 if (verboseLevel > 1) 00349 { 00350 G4cout << "-----------------------------------------------------------" << G4endl; 00351 G4cout << "Energy balance from G4PenelopePhotoElectric" << G4endl; 00352 G4cout << "Selected shell: " << WriteTargetShell(shellIndex) << " of element " << 00353 anElement->GetName() << G4endl; 00354 G4cout << "Incoming photon energy: " << photonEnergy/keV << " keV" << G4endl; 00355 G4cout << "-----------------------------------------------------------" << G4endl; 00356 if (eKineticEnergy) 00357 G4cout << "Outgoing electron " << eKineticEnergy/keV << " keV" << G4endl; 00358 if (energyInFluorescence) 00359 G4cout << "Fluorescence x-rays: " << energyInFluorescence/keV << " keV" << G4endl; 00360 if (energyInAuger) 00361 G4cout << "Auger electrons: " << energyInAuger/keV << " keV" << G4endl; 00362 G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl; 00363 G4cout << "Total final state: " << 00364 (eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger)/keV << 00365 " keV" << G4endl; 00366 G4cout << "-----------------------------------------------------------" << G4endl; 00367 } 00368 if (verboseLevel > 0) 00369 { 00370 G4double energyDiff = 00371 std::fabs(eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger-photonEnergy); 00372 if (energyDiff > 0.05*keV) 00373 { 00374 G4cout << "Warning from G4PenelopePhotoElectric: problem with energy conservation: " << 00375 (eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger)/keV 00376 << " keV (final) vs. " << 00377 photonEnergy/keV << " keV (initial)" << G4endl; 00378 G4cout << "-----------------------------------------------------------" << G4endl; 00379 G4cout << "Energy balance from G4PenelopePhotoElectric" << G4endl; 00380 G4cout << "Selected shell: " << WriteTargetShell(shellIndex) << " of element " << 00381 anElement->GetName() << G4endl; 00382 G4cout << "Incoming photon energy: " << photonEnergy/keV << " keV" << G4endl; 00383 G4cout << "-----------------------------------------------------------" << G4endl; 00384 if (eKineticEnergy) 00385 G4cout << "Outgoing electron " << eKineticEnergy/keV << " keV" << G4endl; 00386 if (energyInFluorescence) 00387 G4cout << "Fluorescence x-rays: " << energyInFluorescence/keV << " keV" << G4endl; 00388 if (energyInAuger) 00389 G4cout << "Auger electrons: " << energyInAuger/keV << " keV" << G4endl; 00390 G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl; 00391 G4cout << "Total final state: " << 00392 (eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger)/keV << 00393 " keV" << G4endl; 00394 G4cout << "-----------------------------------------------------------" << G4endl; 00395 } 00396 } 00397 }
void G4PenelopePhotoElectricModel::SetVerbosityLevel | ( | G4int | lev | ) | [inline] |
Definition at line 93 of file G4PenelopePhotoElectricModel.hh.
Referenced by Initialise(), and SampleSecondaries().