#include <G4PenelopeIonisationModel.hh>
Inheritance diagram for G4PenelopeIonisationModel:
Definition at line 64 of file G4PenelopeIonisationModel.hh.
G4PenelopeIonisationModel::G4PenelopeIonisationModel | ( | const G4ParticleDefinition * | p = 0 , |
|
const G4String & | processName = "PenIoni" | |||
) |
Definition at line 70 of file G4PenelopeIonisationModel.cc.
References G4PenelopeOscillatorManager::GetOscillatorManager(), G4VEmModel::SetDeexcitationFlag(), and G4VEmModel::SetHighEnergyLimit().
00072 :G4VEmModel(nam),fParticleChange(0),isInitialised(false), 00073 fAtomDeexcitation(0),kineticEnergy1(0.*eV), 00074 cosThetaPrimary(1.0),energySecondary(0.*eV), 00075 cosThetaSecondary(0.0),targetOscillator(-1), 00076 theCrossSectionHandler(0) 00077 { 00078 fIntrinsicLowEnergyLimit = 100.0*eV; 00079 fIntrinsicHighEnergyLimit = 100.0*GeV; 00080 // SetLowEnergyLimit(fIntrinsicLowEnergyLimit); 00081 SetHighEnergyLimit(fIntrinsicHighEnergyLimit); 00082 nBins = 200; 00083 // 00084 oscManager = G4PenelopeOscillatorManager::GetOscillatorManager(); 00085 // 00086 verboseLevel= 0; 00087 00088 // Verbosity scale: 00089 // 0 = nothing 00090 // 1 = warning for energy non-conservation 00091 // 2 = details of energy budget 00092 // 3 = calculation of cross sections, file openings, sampling of atoms 00093 // 4 = entering in methods 00094 00095 // Atomic deexcitation model activated by default 00096 SetDeexcitationFlag(true); 00097 }
G4PenelopeIonisationModel::~G4PenelopeIonisationModel | ( | ) | [virtual] |
G4double G4PenelopeIonisationModel::ComputeCrossSectionPerAtom | ( | const G4ParticleDefinition * | , | |
G4double | , | |||
G4double | , | |||
G4double | , | |||
G4double | , | |||
G4double | ||||
) | [virtual] |
Reimplemented from G4VEmModel.
Definition at line 225 of file G4PenelopeIonisationModel.cc.
References G4cout, and G4endl.
00231 { 00232 G4cout << "*** G4PenelopeIonisationModel -- WARNING ***" << G4endl; 00233 G4cout << "Penelope Ionisation model v2008 does not calculate cross section _per atom_ " << G4endl; 00234 G4cout << "so the result is always zero. For physics values, please invoke " << G4endl; 00235 G4cout << "GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" << G4endl; 00236 return 0; 00237 }
G4double G4PenelopeIonisationModel::ComputeDEDXPerVolume | ( | const G4Material * | , | |
const G4ParticleDefinition * | , | |||
G4double | kineticEnergy, | |||
G4double | cutEnergy | |||
) | [virtual] |
Reimplemented from G4VEmModel.
Definition at line 241 of file G4PenelopeIonisationModel.cc.
References G4cout, G4endl, G4PenelopeOscillatorManager::GetAtomsPerMolecule(), G4PenelopeIonisationXSHandler::GetCrossSectionTableForCouple(), G4PenelopeCrossSection::GetSoftStoppingPower(), and G4Material::GetTotNbOfAtomsPerVolume().
00245 { 00246 // Penelope model v2008 to calculate the stopping power for soft inelastic collisions 00247 // below the threshold. It makes use of the Generalised Oscillator Strength (GOS) 00248 // model from 00249 // D. Liljequist, J. Phys. D: Appl. Phys. 16 (1983) 1567 00250 // 00251 // The stopping power is calculated analytically using the dsigma/dW cross 00252 // section from the GOS models, which includes separate contributions from 00253 // distant longitudinal collisions, distant transverse collisions and 00254 // close collisions. Only the atomic oscillators that come in the play 00255 // (according to the threshold) are considered for the calculation. 00256 // Differential cross sections have a different form for e+ and e-. 00257 // 00258 // Fermi density correction is calculated analytically according to 00259 // U. Fano, Ann. Rev. Nucl. Sci. 13 (1963),1 00260 00261 if (verboseLevel > 3) 00262 G4cout << "Calling ComputeDEDX() of G4PenelopeIonisationModel" << G4endl; 00263 00264 00265 G4PenelopeCrossSection* theXS = 00266 theCrossSectionHandler->GetCrossSectionTableForCouple(theParticle,material, 00267 cutEnergy); 00268 G4double sPowerPerMolecule = 0.0; 00269 if (theXS) 00270 sPowerPerMolecule = theXS->GetSoftStoppingPower(kineticEnergy); 00271 00272 00273 G4double atomDensity = material->GetTotNbOfAtomsPerVolume(); 00274 G4double atPerMol = oscManager->GetAtomsPerMolecule(material); 00275 00276 G4double moleculeDensity = 0.; 00277 if (atPerMol) 00278 moleculeDensity = atomDensity/atPerMol; 00279 00280 G4double sPowerPerVolume = sPowerPerMolecule*moleculeDensity; 00281 00282 if (verboseLevel > 2) 00283 { 00284 G4cout << "G4PenelopeIonisationModel " << G4endl; 00285 G4cout << "Stopping power < " << cutEnergy/keV << " keV at " << 00286 kineticEnergy/keV << " keV = " << 00287 sPowerPerVolume/(keV/mm) << " keV/mm" << G4endl; 00288 } 00289 return sPowerPerVolume; 00290 }
G4double G4PenelopeIonisationModel::CrossSectionPerVolume | ( | const G4Material * | material, | |
const G4ParticleDefinition * | theParticle, | |||
G4double | kineticEnergy, | |||
G4double | cutEnergy, | |||
G4double | maxEnergy = DBL_MAX | |||
) | [virtual] |
Reimplemented from G4VEmModel.
Definition at line 155 of file G4PenelopeIonisationModel.cc.
References G4cout, G4endl, G4PenelopeOscillatorManager::GetAtomsPerMolecule(), G4PenelopeIonisationXSHandler::GetCrossSectionTableForCouple(), G4PenelopeCrossSection::GetHardCrossSection(), G4Material::GetName(), G4Material::GetTotNbOfAtomsPerVolume(), and G4VEmModel::SetupForMaterial().
00161 { 00162 // Penelope model v2008 to calculate the cross section for inelastic collisions above the 00163 // threshold. It makes use of the Generalised Oscillator Strength (GOS) model from 00164 // D. Liljequist, J. Phys. D: Appl. Phys. 16 (1983) 1567 00165 // 00166 // The total cross section is calculated analytically by taking 00167 // into account the atomic oscillators coming into the play for a given threshold. 00168 // 00169 // For incident e- the maximum energy allowed for the delta-rays is energy/2. 00170 // because particles are undistinghishable. 00171 // 00172 // The contribution is splitted in three parts: distant longitudinal collisions, 00173 // distant transverse collisions and close collisions. Each term is described by 00174 // its own analytical function. 00175 // Fermi density correction is calculated analytically according to 00176 // U. Fano, Ann. Rev. Nucl. Sci. 13 (1963),1 00177 // 00178 if (verboseLevel > 3) 00179 G4cout << "Calling CrossSectionPerVolume() of G4PenelopeIonisationModel" << G4endl; 00180 00181 SetupForMaterial(theParticle, material, energy); 00182 00183 G4double totalCross = 0.0; 00184 G4double crossPerMolecule = 0.; 00185 00186 G4PenelopeCrossSection* theXS = 00187 theCrossSectionHandler->GetCrossSectionTableForCouple(theParticle, 00188 material, 00189 cutEnergy); 00190 00191 if (theXS) 00192 crossPerMolecule = theXS->GetHardCrossSection(energy); 00193 00194 G4double atomDensity = material->GetTotNbOfAtomsPerVolume(); 00195 G4double atPerMol = oscManager->GetAtomsPerMolecule(material); 00196 00197 if (verboseLevel > 3) 00198 G4cout << "Material " << material->GetName() << " has " << atPerMol << 00199 "atoms per molecule" << G4endl; 00200 00201 G4double moleculeDensity = 0.; 00202 if (atPerMol) 00203 moleculeDensity = atomDensity/atPerMol; 00204 00205 G4double crossPerVolume = crossPerMolecule*moleculeDensity; 00206 00207 if (verboseLevel > 2) 00208 { 00209 G4cout << "G4PenelopeIonisationModel " << G4endl; 00210 G4cout << "Mean free path for delta emission > " << cutEnergy/keV << " keV at " << 00211 energy/keV << " keV = " << (1./crossPerVolume)/mm << " mm" << G4endl; 00212 if (theXS) 00213 totalCross = (theXS->GetTotalCrossSection(energy))*moleculeDensity; 00214 G4cout << "Total free path for ionisation (no threshold) at " << 00215 energy/keV << " keV = " << (1./totalCross)/mm << " mm" << G4endl; 00216 } 00217 return crossPerVolume; 00218 }
G4int G4PenelopeIonisationModel::GetVerbosityLevel | ( | ) | [inline] |
void G4PenelopeIonisationModel::Initialise | ( | const G4ParticleDefinition * | , | |
const G4DataVector & | ||||
) | [virtual] |
Implements G4VEmModel.
Definition at line 109 of file G4PenelopeIonisationModel.cc.
References G4LossTableManager::AtomDeexcitation(), fParticleChange, G4cout, G4endl, G4VEmModel::GetParticleChangeForLoss(), G4VEmModel::HighEnergyLimit(), G4LossTableManager::Instance(), G4VEmModel::LowEnergyLimit(), and G4PenelopeIonisationXSHandler::SetVerboseLevel().
00111 { 00112 if (verboseLevel > 3) 00113 G4cout << "Calling G4PenelopeIonisationModel::Initialise()" << G4endl; 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 G4PenelopeIonisationModel " << 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 //Set the number of bins for the tables. 20 points per decade 00127 nBins = (size_t) (20*std::log10(HighEnergyLimit()/LowEnergyLimit())); 00128 nBins = std::max(nBins,(size_t)100); 00129 00130 //Clear and re-build the tables 00131 if (theCrossSectionHandler) 00132 { 00133 delete theCrossSectionHandler; 00134 theCrossSectionHandler = 0; 00135 } 00136 theCrossSectionHandler = new G4PenelopeIonisationXSHandler(nBins); 00137 theCrossSectionHandler->SetVerboseLevel(verboseLevel); 00138 00139 if (verboseLevel > 2) { 00140 G4cout << "Penelope Ionisation model v2008 is initialized " << G4endl 00141 << "Energy range: " 00142 << LowEnergyLimit() / keV << " keV - " 00143 << HighEnergyLimit() / GeV << " GeV. Using " 00144 << nBins << " bins." 00145 << G4endl; 00146 } 00147 00148 if(isInitialised) return; 00149 fParticleChange = GetParticleChangeForLoss(); 00150 isInitialised = true; 00151 }
G4double G4PenelopeIonisationModel::MinEnergyCut | ( | const G4ParticleDefinition * | , | |
const G4MaterialCutsCouple * | ||||
) | [virtual] |
void G4PenelopeIonisationModel::SampleSecondaries | ( | std::vector< G4DynamicParticle * > * | , | |
const G4MaterialCutsCouple * | , | |||
const G4DynamicParticle * | , | |||
G4double | tmin, | |||
G4double | maxEnergy | |||
) | [virtual] |
Implements G4VEmModel.
Definition at line 302 of file G4PenelopeIonisationModel.cc.
References G4AtomicShell::BindingEnergy(), G4InuclSpecialFunctions::bindingEnergy(), G4VAtomDeexcitation::CheckDeexcitationActiveRegion(), G4Electron::Definition(), G4Gamma::Definition(), G4Electron::Electron(), FatalException, fParticleChange, G4cout, G4endl, G4Exception(), G4UniformRand, G4VAtomDeexcitation::GenerateParticles(), G4DynamicParticle::GetDefinition(), G4MaterialCutsCouple::GetIndex(), G4DynamicParticle::GetKineticEnergy(), G4MaterialCutsCouple::GetMaterial(), G4DynamicParticle::GetMomentumDirection(), G4PenelopeOscillatorManager::GetOscillatorTableIonisation(), G4ParticleDefinition::GetParticleName(), G4AtomicTransitionManager::Instance(), G4INCL::Math::pi, G4Positron::Positron(), G4VParticleChange::ProposeLocalEnergyDeposit(), G4ParticleChangeForLoss::ProposeMomentumDirection(), G4ParticleChangeForLoss::SetProposedKineticEnergy(), and G4AtomicTransitionManager::Shell().
00306 { 00307 // Penelope model v2008 to sample the final state following an hard inelastic interaction. 00308 // It makes use of the Generalised Oscillator Strength (GOS) model from 00309 // D. Liljequist, J. Phys. D: Appl. Phys. 16 (1983) 1567 00310 // 00311 // The GOS model is used to calculate the individual cross sections for all 00312 // the atomic oscillators coming in the play, taking into account the three 00313 // contributions (distant longitudinal collisions, distant transverse collisions and 00314 // close collisions). Then the target shell and the interaction channel are 00315 // sampled. Final state of the delta-ray (energy, angle) are generated according 00316 // to the analytical distributions (dSigma/dW) for the selected interaction 00317 // channels. 00318 // For e-, the maximum energy for the delta-ray is initialEnergy/2. (because 00319 // particles are indistinghusbable), while it is the full initialEnergy for 00320 // e+. 00321 // The efficiency of the random sampling algorithm (e.g. for close collisions) 00322 // decreases when initial and cutoff energy increase (e.g. 87% for 10-keV primary 00323 // and 1 keV threshold, 99% for 10-MeV primary and 10-keV threshold). 00324 // Differential cross sections have a different form for e+ and e-. 00325 // 00326 // WARNING: The model provides an _average_ description of inelastic collisions. 00327 // Anyway, the energy spectrum associated to distant excitations of a given 00328 // atomic shell is approximated as a single resonance. The simulated energy spectra 00329 // show _unphysical_ narrow peaks at energies that are multiple of the shell 00330 // resonance energies. The spurious speaks are automatically smoothed out after 00331 // multiple inelastic collisions. 00332 // 00333 // The model determines also the original shell from which the delta-ray is expelled, 00334 // in order to produce fluorescence de-excitation (from G4DeexcitationManager) 00335 // 00336 // Fermi density correction is calculated analytically according to 00337 // U. Fano, Ann. Rev. Nucl. Sci. 13 (1963),1 00338 00339 if (verboseLevel > 3) 00340 G4cout << "Calling SamplingSecondaries() of G4PenelopeIonisationModel" << G4endl; 00341 00342 G4double kineticEnergy0 = aDynamicParticle->GetKineticEnergy(); 00343 const G4ParticleDefinition* theParticle = aDynamicParticle->GetDefinition(); 00344 00345 if (kineticEnergy0 <= fIntrinsicLowEnergyLimit) 00346 { 00347 fParticleChange->SetProposedKineticEnergy(0.); 00348 fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy0); 00349 return ; 00350 } 00351 00352 const G4Material* material = couple->GetMaterial(); 00353 G4PenelopeOscillatorTable* theTable = oscManager->GetOscillatorTableIonisation(material); 00354 00355 G4ParticleMomentum particleDirection0 = aDynamicParticle->GetMomentumDirection(); 00356 00357 //Initialise final-state variables. The proper values will be set by the methods 00358 // SampleFinalStateElectron() and SampleFinalStatePositron() 00359 kineticEnergy1=kineticEnergy0; 00360 cosThetaPrimary=1.0; 00361 energySecondary=0.0; 00362 cosThetaSecondary=1.0; 00363 targetOscillator = -1; 00364 00365 if (theParticle == G4Electron::Electron()) 00366 SampleFinalStateElectron(material,cutE,kineticEnergy0); 00367 else if (theParticle == G4Positron::Positron()) 00368 SampleFinalStatePositron(material,cutE,kineticEnergy0); 00369 else 00370 { 00371 G4ExceptionDescription ed; 00372 ed << "Invalid particle " << theParticle->GetParticleName() << G4endl; 00373 G4Exception("G4PenelopeIonisationModel::SamplingSecondaries()", 00374 "em0001",FatalException,ed); 00375 00376 } 00377 if (energySecondary == 0) return; 00378 00379 if (verboseLevel > 3) 00380 { 00381 G4cout << "G4PenelopeIonisationModel::SamplingSecondaries() for " << 00382 theParticle->GetParticleName() << G4endl; 00383 G4cout << "Final eKin = " << kineticEnergy1 << " keV" << G4endl; 00384 G4cout << "Final cosTheta = " << cosThetaPrimary << G4endl; 00385 G4cout << "Delta-ray eKin = " << energySecondary << " keV" << G4endl; 00386 G4cout << "Delta-ray cosTheta = " << cosThetaSecondary << G4endl; 00387 G4cout << "Oscillator: " << targetOscillator << G4endl; 00388 } 00389 00390 //Update the primary particle 00391 G4double sint = std::sqrt(1. - cosThetaPrimary*cosThetaPrimary); 00392 G4double phiPrimary = twopi * G4UniformRand(); 00393 G4double dirx = sint * std::cos(phiPrimary); 00394 G4double diry = sint * std::sin(phiPrimary); 00395 G4double dirz = cosThetaPrimary; 00396 00397 G4ThreeVector electronDirection1(dirx,diry,dirz); 00398 electronDirection1.rotateUz(particleDirection0); 00399 00400 if (kineticEnergy1 > 0) 00401 { 00402 fParticleChange->ProposeMomentumDirection(electronDirection1); 00403 fParticleChange->SetProposedKineticEnergy(kineticEnergy1); 00404 } 00405 else 00406 fParticleChange->SetProposedKineticEnergy(0.); 00407 00408 00409 //Generate the delta ray 00410 G4double ionEnergyInPenelopeDatabase = 00411 (*theTable)[targetOscillator]->GetIonisationEnergy(); 00412 00413 //Now, try to handle fluorescence 00414 //Notice: merged levels are indicated with Z=0 and flag=30 00415 G4int shFlag = (*theTable)[targetOscillator]->GetShellFlag(); 00416 G4int Z = (G4int) (*theTable)[targetOscillator]->GetParentZ(); 00417 00418 //initialize here, then check photons created by Atomic-Deexcitation, and the final state e- 00419 const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance(); 00420 G4double bindingEnergy = 0.*eV; 00421 //G4int shellId = 0; 00422 00423 const G4AtomicShell* shell = 0; 00424 //Real level 00425 if (Z > 0 && shFlag<30) 00426 { 00427 shell = transitionManager->Shell(Z,shFlag-1); 00428 bindingEnergy = shell->BindingEnergy(); 00429 //shellId = shell->ShellId(); 00430 } 00431 00432 //correct the energySecondary to account for the fact that the Penelope 00433 //database of ionisation energies is in general (slightly) different 00434 //from the fluorescence database used in Geant4. 00435 energySecondary += ionEnergyInPenelopeDatabase-bindingEnergy; 00436 00437 G4double localEnergyDeposit = bindingEnergy; 00438 //testing purposes only 00439 G4double energyInFluorescence = 0; 00440 G4double energyInAuger = 0; 00441 00442 if (energySecondary < 0) 00443 { 00444 //It means that there was some problem/mismatch between the two databases. 00445 //In this case, the available energy is ok to excite the level according 00446 //to the Penelope database, but not according to the Geant4 database 00447 //Full residual energy is deposited locally 00448 localEnergyDeposit += energySecondary; 00449 energySecondary = 0.0; 00450 } 00451 00452 //Notice: shell might be NULL (invalid!) if shFlag=30. Must be protected 00453 //Now, take care of fluorescence, if required 00454 if (fAtomDeexcitation && shell) 00455 { 00456 G4int index = couple->GetIndex(); 00457 if (fAtomDeexcitation->CheckDeexcitationActiveRegion(index)) 00458 { 00459 size_t nBefore = fvect->size(); 00460 fAtomDeexcitation->GenerateParticles(fvect,shell,Z,index); 00461 size_t nAfter = fvect->size(); 00462 00463 if (nAfter > nBefore) //actual production of fluorescence 00464 { 00465 for (size_t j=nBefore;j<nAfter;j++) //loop on products 00466 { 00467 G4double itsEnergy = ((*fvect)[j])->GetKineticEnergy(); 00468 localEnergyDeposit -= itsEnergy; 00469 if (((*fvect)[j])->GetParticleDefinition() == G4Gamma::Definition()) 00470 energyInFluorescence += itsEnergy; 00471 else if (((*fvect)[j])->GetParticleDefinition() == G4Electron::Definition()) 00472 energyInAuger += itsEnergy; 00473 } 00474 } 00475 } 00476 } 00477 00478 // Generate the delta ray --> to be done only if above cut 00479 if (energySecondary > cutE) 00480 { 00481 G4DynamicParticle* electron = 0; 00482 G4double sinThetaE = std::sqrt(1.-cosThetaSecondary*cosThetaSecondary); 00483 G4double phiEl = phiPrimary+pi; //pi with respect to the primary electron/positron 00484 G4double xEl = sinThetaE * std::cos(phiEl); 00485 G4double yEl = sinThetaE * std::sin(phiEl); 00486 G4double zEl = cosThetaSecondary; 00487 G4ThreeVector eDirection(xEl,yEl,zEl); //electron direction 00488 eDirection.rotateUz(particleDirection0); 00489 electron = new G4DynamicParticle (G4Electron::Electron(), 00490 eDirection,energySecondary) ; 00491 fvect->push_back(electron); 00492 } 00493 else 00494 { 00495 localEnergyDeposit += energySecondary; 00496 energySecondary = 0; 00497 } 00498 00499 if (localEnergyDeposit < 0) 00500 { 00501 G4cout << "WARNING-" 00502 << "G4PenelopeIonisationModel::SampleSecondaries - Negative energy deposit" 00503 << G4endl; 00504 localEnergyDeposit=0.; 00505 } 00506 fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit); 00507 00508 if (verboseLevel > 1) 00509 { 00510 G4cout << "-----------------------------------------------------------" << G4endl; 00511 G4cout << "Energy balance from G4PenelopeIonisation" << G4endl; 00512 G4cout << "Incoming primary energy: " << kineticEnergy0/keV << " keV" << G4endl; 00513 G4cout << "-----------------------------------------------------------" << G4endl; 00514 G4cout << "Outgoing primary energy: " << kineticEnergy1/keV << " keV" << G4endl; 00515 G4cout << "Delta ray " << energySecondary/keV << " keV" << G4endl; 00516 if (energyInFluorescence) 00517 G4cout << "Fluorescence x-rays: " << energyInFluorescence/keV << " keV" << G4endl; 00518 if (energyInAuger) 00519 G4cout << "Auger electrons: " << energyInAuger/keV << " keV" << G4endl; 00520 G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl; 00521 G4cout << "Total final state: " << (energySecondary+energyInFluorescence+kineticEnergy1+ 00522 localEnergyDeposit+energyInAuger)/keV << 00523 " keV" << G4endl; 00524 G4cout << "-----------------------------------------------------------" << G4endl; 00525 } 00526 00527 if (verboseLevel > 0) 00528 { 00529 G4double energyDiff = std::fabs(energySecondary+energyInFluorescence+kineticEnergy1+ 00530 localEnergyDeposit+energyInAuger-kineticEnergy0); 00531 if (energyDiff > 0.05*keV) 00532 G4cout << "Warning from G4PenelopeIonisation: problem with energy conservation: " << 00533 (energySecondary+energyInFluorescence+kineticEnergy1+localEnergyDeposit+energyInAuger)/keV << 00534 " keV (final) vs. " << 00535 kineticEnergy0/keV << " keV (initial)" << G4endl; 00536 } 00537 00538 }
void G4PenelopeIonisationModel::SetVerbosityLevel | ( | G4int | lev | ) | [inline] |
Definition at line 108 of file G4PenelopeIonisationModel.hh.
Referenced by Initialise(), and SampleSecondaries().