65const G4int G4PenelopePhotoElectricModel::fMaxZ;
66G4PhysicsTable* G4PenelopePhotoElectricModel::fLogAtomicShellXS[] = {
nullptr};
72 :
G4VEmModel(nam),fParticleChange(nullptr),fParticle(nullptr),
73 fAtomDeexcitation(nullptr),fIsInitialised(false),fLocalTable(false)
75 fIntrinsicLowEnergyLimit = 100.0*eV;
76 fIntrinsicHighEnergyLimit = 100.0*GeV;
104 for(
G4int i=0; i<=fMaxZ; ++i)
106 if(fLogAtomicShellXS[i]) {
108 delete fLogAtomicShellXS[i];
109 fLogAtomicShellXS[i] =
nullptr;
120 if (fVerboseLevel > 3)
121 G4cout <<
"Calling G4PenelopePhotoElectricModel::Initialise()" <<
G4endl;
125 if (!fAtomDeexcitation)
128 G4cout <<
"WARNING from G4PenelopePhotoElectricModel " <<
G4endl;
129 G4cout <<
"Atomic de-excitation module is not instantiated, so there will not be ";
131 G4cout <<
"Please make sure this is intended" <<
G4endl;
134 SetParticle(particle);
150 G4int iZ = theElementVector->at(j)->GetZasInt();
152 if (!fLogAtomicShellXS[iZ])
159 if (fVerboseLevel > 0) {
160 G4cout <<
"Penelope Photo-Electric model v2008 is initialized " <<
G4endl
167 if(fIsInitialised)
return;
169 fIsInitialised =
true;
176 if (fVerboseLevel > 3)
177 G4cout <<
"Calling G4PenelopePhotoElectricModel::InitialiseLocal()" <<
G4endl;
189 for(
G4int i=0; i<=fMaxZ; ++i)
190 fLogAtomicShellXS[i] = theModel->fLogAtomicShellXS[i];
192 fVerboseLevel = theModel->fVerboseLevel;
209 if (fVerboseLevel > 3)
210 G4cout <<
"Calling ComputeCrossSectionPerAtom() of G4PenelopePhotoElectricModel" <<
G4endl;
214 if (!fLogAtomicShellXS[iZ])
218 if (fVerboseLevel > 0)
222 ed <<
"Unable to retrieve the shell cross section table for Z=" << iZ <<
G4endl;
223 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
224 G4Exception(
"G4PenelopePhotoElectricModel::ComputeCrossSectionPerAtom()",
228 G4AutoLock lock(&PenelopePhotoElectricModelMutex);
239 G4Exception(
"G4PenelopePhotoElectricModel::ComputeCrossSectionPerAtom()",
241 "Unable to retrieve the total cross section table");
246 cross =
G4Exp(logXS);
248 if (fVerboseLevel > 2)
249 G4cout <<
"Photoelectric cross section at " << energy/MeV <<
" MeV for Z=" << Z <<
250 " = " << cross/barn <<
" barn" <<
G4endl;
276 if (fVerboseLevel > 3)
277 G4cout <<
"Calling SamplingSecondaries() of G4PenelopePhotoElectricModel" <<
G4endl;
285 if (photonEnergy <= fIntrinsicLowEnergyLimit)
294 if (fVerboseLevel > 2)
301 if (fVerboseLevel > 2)
310 std::size_t shellIndex = SelectRandomShell(Z,photonEnergy);
312 if (fVerboseLevel > 2)
313 G4cout <<
"Selected shell " << shellIndex <<
" of element " << anElement->
GetName() <<
G4endl;
324 std::size_t numberOfShells = (std::size_t) transitionManager->
NumberOfShells(Z);
325 if (shellIndex >= numberOfShells)
326 shellIndex = numberOfShells-1;
337 bindingEnergy = 0.*eV;
343 G4double eKineticEnergy = photonEnergy - bindingEnergy;
347 if (eKineticEnergy > 0.)
351 cosTheta = SampleElectronDirection(eKineticEnergy);
352 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
354 G4double dirx = sinTheta * std::cos(phi);
355 G4double diry = sinTheta * std::sin(phi);
358 electronDirection.
rotateUz(photonDirection);
362 fvect->push_back(electron);
365 bindingEnergy = photonEnergy;
373 if (fAtomDeexcitation && shellIndex<9)
378 std::size_t nBefore = fvect->size();
380 std::size_t nAfter = fvect->size();
382 if (nAfter > nBefore)
384 for (std::size_t j=nBefore;j<nAfter;++j)
386 G4double itsEnergy = ((*fvect)[j])->GetKineticEnergy();
387 if (itsEnergy < bindingEnergy)
389 bindingEnergy -= itsEnergy;
391 energyInFluorescence += itsEnergy;
393 energyInAuger += itsEnergy;
398 (*fvect)[j] =
nullptr;
406 localEnergyDeposit += bindingEnergy;
408 if (localEnergyDeposit < 0)
410 G4Exception(
"G4PenelopePhotoElectricModel::SampleSecondaries()",
411 "em2099",
JustWarning,
"WARNING: Negative local energy deposit");
412 localEnergyDeposit = 0;
417 if (fVerboseLevel > 1)
419 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
420 G4cout <<
"Energy balance from G4PenelopePhotoElectric" <<
G4endl;
421 G4cout <<
"Selected shell: " << WriteTargetShell(shellIndex) <<
" of element " <<
423 G4cout <<
"Incoming photon energy: " << photonEnergy/keV <<
" keV" <<
G4endl;
424 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
426 G4cout <<
"Outgoing electron " << eKineticEnergy/keV <<
" keV" <<
G4endl;
427 if (energyInFluorescence)
428 G4cout <<
"Fluorescence x-rays: " << energyInFluorescence/keV <<
" keV" <<
G4endl;
430 G4cout <<
"Auger electrons: " << energyInAuger/keV <<
" keV" <<
G4endl;
431 G4cout <<
"Local energy deposit " << localEnergyDeposit/keV <<
" keV" <<
G4endl;
432 G4cout <<
"Total final state: " <<
433 (eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger)/keV <<
435 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
437 if (fVerboseLevel > 0)
440 std::fabs(eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger-photonEnergy);
441 if (energyDiff > 0.05*keV)
443 G4cout <<
"Warning from G4PenelopePhotoElectric: problem with energy conservation: " <<
444 (eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger)/keV
445 <<
" keV (final) vs. " <<
446 photonEnergy/keV <<
" keV (initial)" <<
G4endl;
447 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
448 G4cout <<
"Energy balance from G4PenelopePhotoElectric" <<
G4endl;
449 G4cout <<
"Selected shell: " << WriteTargetShell(shellIndex) <<
" of element " <<
451 G4cout <<
"Incoming photon energy: " << photonEnergy/keV <<
" keV" <<
G4endl;
452 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
454 G4cout <<
"Outgoing electron " << eKineticEnergy/keV <<
" keV" <<
G4endl;
455 if (energyInFluorescence)
456 G4cout <<
"Fluorescence x-rays: " << energyInFluorescence/keV <<
" keV" <<
G4endl;
458 G4cout <<
"Auger electrons: " << energyInAuger/keV <<
" keV" <<
G4endl;
459 G4cout <<
"Local energy deposit " << localEnergyDeposit/keV <<
" keV" <<
G4endl;
460 G4cout <<
"Total final state: " <<
461 (eKineticEnergy+energyInFluorescence+localEnergyDeposit+energyInAuger)/keV <<
463 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
470G4double G4PenelopePhotoElectricModel::SampleElectronDirection(
G4double energy)
473 if (energy>1*GeV)
return costheta;
478 G4double gamma = 1.0 + energy/electron_mass_c2;
480 G4double beta = std::sqrt((gamma2-1.0)/gamma2);
485 G4double a1 = 0.5*beta*gamma*(gamma-1.0)*(gamma-2.0);
497 tsam = 2.0*ac * (2.0*rand + a2*std::sqrt(rand)) / (a2*a2 - 4.0*rand);
498 gtr = (2.0 - tsam) * (a1 + 1.0/(ac+tsam));
507void G4PenelopePhotoElectricModel::ReadDataFile(
G4int Z)
511 G4Exception(
"G4PenelopePhotoElectricModel::ReadDataFile()",
514 if (fVerboseLevel > 2)
516 G4cout <<
"G4PenelopePhotoElectricModel::ReadDataFile()" <<
G4endl;
517 G4cout <<
"Going to read PhotoElectric data files for Z=" << Z <<
G4endl;
523 G4String excep =
"G4PenelopePhotoElectricModel - G4LEDATA environment variable not set!";
524 G4Exception(
"G4PenelopePhotoElectricModel::ReadDataFile()",
532 std::ostringstream ost;
534 ost << path <<
"/penelope/photoelectric/pdgph" << Z <<
".p08";
536 ost << path <<
"/penelope/photoelectric/pdgph0" << Z <<
".p08";
537 std::ifstream file(ost.str().c_str());
540 G4String excep =
"G4PenelopePhotoElectricModel - data file " +
G4String(ost.str()) +
" not found!";
541 G4Exception(
"G4PenelopePhotoElectricModel::ReadDataFile()",
548 while( getline(file, line) )
555 file.open(ost.str().c_str());
558 std::size_t nShells= 0;
559 file >> readZ >> nShells;
561 if (fVerboseLevel > 3)
562 G4cout <<
"Element Z=" << Z <<
" , nShells = " << nShells <<
G4endl;
565 if (readZ != Z || nShells <= 0 || nShells > 50)
568 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
569 G4Exception(
"G4PenelopePhotoElectricModel::ReadDataFile()",
581 for (std::size_t i=0;i<nShells+1;++i)
585 for (k=0;k<ndata && !file.eof();++k)
593 for (std::size_t i=0;i<nShells+1;++i)
598 if (aValue < 1e-40*cm2)
604 if (fVerboseLevel > 2)
606 G4cout <<
"G4PenelopePhotoElectricModel: read " << k <<
" points for element Z = "
610 fLogAtomicShellXS[Z] = thePhysicsTable;
622 G4Exception(
"G4PenelopePhotoElectricModel::GetNumberOfShellXS()",
626 if (!fLogAtomicShellXS[Z])
629 if (!fLogAtomicShellXS[Z])
632 ed <<
"Cannot find shell cross section data for Z=" << Z <<
G4endl;
633 G4Exception(
"G4PenelopePhotoElectricModel::GetNumberOfShellXS()",
637 std::size_t nEntries = fLogAtomicShellXS[Z]->
entries();
648 if (shellID >= entries)
650 G4cout <<
"Element Z=" << Z <<
" has data for " << entries <<
" shells only" <<
G4endl;
651 G4cout <<
"so shellID should be from 0 to " << entries-1 <<
G4endl;
661 G4Exception(
"G4PenelopePhotoElectricModel::GetShellCrossSection()",
663 "Unable to retrieve the total cross section table");
669 if (cross < 2e-40*cm2) cross = 0;
675G4String G4PenelopePhotoElectricModel::WriteTargetShell(std::size_t shellID)
680 else if (shellID == 1)
682 else if (shellID == 2)
684 else if (shellID == 3)
686 else if (shellID == 4)
688 else if (shellID == 5)
690 else if (shellID == 6)
692 else if (shellID == 7)
694 else if (shellID == 8)
711std::size_t G4PenelopePhotoElectricModel::SelectRandomShell(
G4int Z,
G4double energy)
716 if (!fLogAtomicShellXS[Z])
719 ed <<
"Cannot find shell cross section data for Z=" << Z <<
G4endl;
720 G4Exception(
"G4PenelopePhotoElectricModel::SelectRandomShell()",
739 for (std::size_t k=1;k<theTable->
entries();++k)
std::vector< const G4Element * > G4ElementVector
const char * G4FindDataDir(const char *)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
G4double BindingEnergy() const
G4AtomicShell * Shell(G4int Z, size_t shellIndex) const
G4int NumberOfShells(G4int Z) const
static G4AtomicTransitionManager * Instance()
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
static G4Electron * Definition()
static G4Electron * Electron()
const G4String & GetName() const
static G4Gamma * GammaDefinition()
static G4Gamma * Definition()
static G4LossTableManager * Instance()
G4VAtomDeexcitation * AtomDeexcitation()
const G4Material * GetMaterial() const
const G4ElementVector * GetElementVector() const
std::size_t GetNumberOfElements() const
const G4String & GetName() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
std::size_t GetNumberOfShellXS(G4int)
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
G4PenelopePhotoElectricModel(const G4ParticleDefinition *p=nullptr, const G4String &processName="PenPhotoElec")
G4double GetShellCrossSection(G4int Z, std::size_t shellID, G4double energy)
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) override
G4ParticleChangeForGamma * fParticleChange
virtual ~G4PenelopePhotoElectricModel()
const G4ParticleDefinition * fParticle
void PutValue(const std::size_t index, const G4double e, const G4double value)
void push_back(G4PhysicsVector *)
std::size_t entries() const
G4double Value(const G4double energy, std::size_t &lastidx) const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
G4bool CheckDeexcitationActiveRegion(G4int coupleIndex)
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
void SetHighEnergyLimit(G4double)
void SetElementSelectors(std::vector< G4EmElementSelector * > *)
G4ParticleChangeForGamma * GetParticleChangeForGamma()
G4double LowEnergyLimit() const
std::vector< G4EmElementSelector * > * GetElementSelectors()
G4double HighEnergyLimit() const
const G4Element * SelectRandomAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
void SetDeexcitationFlag(G4bool val)
void InitialiseElementSelectors(const G4ParticleDefinition *, const G4DataVector &)
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double energy(const ThreeVector &p, const G4double m)