64 :
G4VEmModel(nam),fParticleChange(0),fParticle(0),
65 isInitialised(false),fAtomDeexcitation(0),
68 fIntrinsicLowEnergyLimit = 100.0*
eV;
69 fIntrinsicHighEnergyLimit = 100.0*
GeV;
102 if (verboseLevel > 3)
103 G4cout <<
"Calling G4PenelopeComptonModel::Initialise()" <<
G4endl;
107 if (!fAtomDeexcitation)
110 G4cout <<
"WARNING from G4PenelopeComptonModel " <<
G4endl;
111 G4cout <<
"Atomic de-excitation module is not instantiated, so there will not be ";
113 G4cout <<
"Please make sure this is intended" <<
G4endl;
121 if (verboseLevel > 0)
123 G4cout <<
"Penelope Compton model v2008 is initialized " << G4endl
130 if(isInitialised)
return;
132 isInitialised =
true;
141 if (verboseLevel > 3)
142 G4cout <<
"Calling G4PenelopeComptonModel::InitialiseLocal()" <<
G4endl;
155 verboseLevel = theModel->verboseLevel;
181 if (verboseLevel > 3)
182 G4cout <<
"Calling CrossSectionPerVolume() of G4PenelopeComptonModel" <<
G4endl;
192 size_t numberOfOscillators = theTable->size();
193 for (
size_t i=0;i<numberOfOscillators;i++)
197 cs += OscillatorTotalCrossSection(energy,theOsc);
201 cs = KleinNishinaCrossSection(energy,material);
212 if (verboseLevel > 3)
213 G4cout <<
"Material " << material->
GetName() <<
" has " << atPerMol <<
214 "atoms per molecule" <<
G4endl;
219 moleculeDensity = atomDensity/atPerMol;
221 G4double csvolume = cs*moleculeDensity;
223 if (verboseLevel > 2)
224 G4cout <<
"Compton mean free path at " << energy/
keV <<
" keV for material " <<
225 material->
GetName() <<
" = " << (1./csvolume)/
mm <<
" mm" << G4endl;
241 G4cout <<
"*** G4PenelopeComptonModel -- WARNING ***" <<
G4endl;
242 G4cout <<
"Penelope Compton model v2008 does not calculate cross section _per atom_ " <<
G4endl;
243 G4cout <<
"so the result is always zero. For physics values, please invoke " <<
G4endl;
244 G4cout <<
"GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" <<
G4endl;
277 if (verboseLevel > 3)
278 G4cout <<
"Calling SampleSecondaries() of G4PenelopeComptonModel" <<
G4endl;
282 if (photonEnergy0 <= fIntrinsicLowEnergyLimit)
304 size_t numberOfOscillators = theTable->size();
305 size_t targetOscillator = 0;
322 if (photonEnergy0 > 5*
MeV)
331 TST = (1.0+tau*(ek1+tau*(ek2+tau*eks)))/(eks*tau*(1.0+tau*tau));
334 cosTheta = 1.0 - (1.0-tau)/(ek*tau);
338 targetOscillator = numberOfOscillators-1;
340 G4bool levelFound =
false;
341 for (
size_t j=0;j<numberOfOscillators && !levelFound; j++)
343 S += (*theTable)[j]->GetOscillatorStrength();
346 targetOscillator = j;
351 ionEnergy = (*theTable)[targetOscillator]->GetIonisationEnergy();
352 }
while((epsilon*photonEnergy0-photonEnergy0+ionEnergy) >0);
361 for (
size_t i=0;i<numberOfOscillators;i++)
363 ionEnergy = (*theTable)[i]->GetIonisationEnergy();
364 if (photonEnergy0 > ionEnergy)
366 G4double aux2 = photonEnergy0*(photonEnergy0-ionEnergy)*2.0;
367 hartreeFunc = (*theTable)[i]->GetHartreeFactor();
368 oscStren = (*theTable)[i]->GetOscillatorStrength();
372 rni = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
373 (std::sqrt(0.5)+std::sqrt(2.0)*pzomc));
375 rni = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
376 (std::sqrt(0.5)-std::sqrt(2.0)*pzomc));
388 cdt1 = (1.0-tau)/(ek*tau);
391 for (
size_t i=0;i<numberOfOscillators;i++)
393 ionEnergy = (*theTable)[i]->GetIonisationEnergy();
394 if (photonEnergy0 > ionEnergy)
396 aux = photonEnergy0*(photonEnergy0-ionEnergy)*cdt1;
397 hartreeFunc = (*theTable)[i]->GetHartreeFactor();
398 oscStren = (*theTable)[i]->GetOscillatorStrength();
402 rn[i] = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
403 (std::sqrt(0.5)+std::sqrt(2.0)*pzomc));
405 rn[i] = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
406 (std::sqrt(0.5)-std::sqrt(2.0)*pzomc));
414 TST = S*(1.0+tau*(ek1+tau*(ek2+tau*eks)))/(eks*tau*(1.0+tau*tau));
417 cosTheta = 1.0 - cdt1;
426 targetOscillator = numberOfOscillators-1;
427 G4bool levelFound =
false;
428 for (
size_t i=0;i<numberOfOscillators && !levelFound;i++)
432 targetOscillator = i;
437 hartreeFunc = (*theTable)[targetOscillator]->GetHartreeFactor();
438 oscStren = (*theTable)[targetOscillator]->GetOscillatorStrength();
440 pzomc = (std::sqrt(0.5)-std::sqrt(0.5-std::log(2.0*A)))/
441 (std::sqrt(2.0)*hartreeFunc);
443 pzomc = (std::sqrt(0.5-std::log(2.0-2.0*A))-std::sqrt(0.5))/
444 (std::sqrt(2.0)*hartreeFunc);
445 }
while (pzomc < -1);
448 G4double XQC = 1.0+tau*(tau-2.0*cosTheta);
449 G4double AF = std::sqrt(XQC)*(1.0+tau*(tau-cosTheta)/XQC);
462 epsilon = (tau/b1)*(b2+std::sqrt(std::abs(b2*b2-b1*(1.0-T))));
464 epsilon = (tau/b1)*(b2-std::sqrt(std::abs(b2*b2-b1*(1.0-T))));
468 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
470 G4double dirx = sinTheta * std::cos(phi);
471 G4double diry = sinTheta * std::sin(phi);
476 photonDirection1.
rotateUz(photonDirection0);
479 G4double photonEnergy1 = epsilon * photonEnergy0;
481 if (photonEnergy1 > 0.)
490 G4double diffEnergy = photonEnergy0*(1-epsilon);
491 ionEnergy = (*theTable)[targetOscillator]->GetIonisationEnergy();
494 photonEnergy0*photonEnergy0+photonEnergy1*(photonEnergy1-2.0*photonEnergy0*cosTheta);
498 cosThetaE = (photonEnergy0-photonEnergy1*cosTheta)/std::sqrt(Q2);
501 G4double sinThetaE = std::sqrt(1-cosThetaE*cosThetaE);
505 G4int shFlag = (*theTable)[targetOscillator]->GetShellFlag();
506 G4int Z = (
G4int) (*theTable)[targetOscillator]->GetParentZ();
513 if (Z > 0 && shFlag<30)
515 shell = fTransitionManager->
Shell(Z,shFlag-1);
519 G4double ionEnergyInPenelopeDatabase = ionEnergy;
521 ionEnergy =
std::max(bindingEnergy,ionEnergyInPenelopeDatabase);
525 G4double eKineticEnergy = diffEnergy - ionEnergy;
526 G4double localEnergyDeposit = ionEnergy;
530 if (eKineticEnergy < 0)
536 localEnergyDeposit = diffEnergy;
537 eKineticEnergy = 0.0;
543 if (fAtomDeexcitation && shell)
548 size_t nBefore = fvect->size();
550 size_t nAfter = fvect->size();
552 if (nAfter > nBefore)
554 for (
size_t j=nBefore;j<nAfter;j++)
556 G4double itsEnergy = ((*fvect)[j])->GetKineticEnergy();
557 localEnergyDeposit -= itsEnergy;
559 energyInFluorescence += itsEnergy;
561 energyInAuger += itsEnergy;
644 eDirection.
rotateUz(photonDirection0);
646 eDirection,eKineticEnergy) ;
647 fvect->push_back(electron);
650 if (localEnergyDeposit < 0)
653 <<
"G4PenelopeComptonModel::SampleSecondaries - Negative energy deposit"
655 localEnergyDeposit=0.;
661 electronEnergy = eKineticEnergy;
662 if (verboseLevel > 1)
664 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
665 G4cout <<
"Energy balance from G4PenelopeCompton" <<
G4endl;
666 G4cout <<
"Incoming photon energy: " << photonEnergy0/
keV <<
" keV" <<
G4endl;
667 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
668 G4cout <<
"Scattered photon: " << photonEnergy1/
keV <<
" keV" <<
G4endl;
669 G4cout <<
"Scattered electron " << electronEnergy/
keV <<
" keV" <<
G4endl;
670 if (energyInFluorescence)
671 G4cout <<
"Fluorescence x-rays: " << energyInFluorescence/
keV <<
" keV" <<
G4endl;
673 G4cout <<
"Auger electrons: " << energyInAuger/
keV <<
" keV" <<
G4endl;
674 G4cout <<
"Local energy deposit " << localEnergyDeposit/
keV <<
" keV" <<
G4endl;
675 G4cout <<
"Total final state: " << (photonEnergy1+electronEnergy+energyInFluorescence+
676 localEnergyDeposit+energyInAuger)/
keV <<
678 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
680 if (verboseLevel > 0)
682 G4double energyDiff = std::fabs(photonEnergy1+
683 electronEnergy+energyInFluorescence+
684 localEnergyDeposit+energyInAuger-photonEnergy0);
685 if (energyDiff > 0.05*
keV)
686 G4cout <<
"Warning from G4PenelopeCompton: problem with energy conservation: " <<
687 (photonEnergy1+electronEnergy+energyInFluorescence+energyInAuger+localEnergyDeposit)/
keV <<
688 " keV (final) vs. " <<
689 photonEnergy0/
keV <<
" keV (initial)" << G4endl;
712 static const G4double k2 = std::sqrt(2.);
715 if (energy < ionEnergy)
724 G4double aux = energy*(energy-ionEnergy)*cdt1;
730 sia = 1.0-0.5*std::exp(0.5-(k1+k2*x)*(k1+k2*x));
732 sia = 0.5*std::exp(0.5-(k1-k2*x)*(k1-k2*x));
737 if (std::fabs(Pzimax) < pf)
739 G4double QCOE2 = 1.0+ECOE*ECOE-2.0*ECOE*cosTheta;
742 (1.0+ECOE*(ECOE-cosTheta)/QCOE2)*harFunc
743 *0.25*(2*p2-(p2*p2)/(pf*pf)-(pf*pf));
747 G4double XKN = EOEC+ECOE-1.0+cosTheta*cosTheta;
750 G4double diffCS = ECOE*ECOE*XKN*sia;
767 const G4int npoints=10;
768 const G4int ncallsmax=20000;
770 static const G4double Abscissas[10] = {7.652651133497334e-02,2.2778585114164508e-01,3.7370608871541956e-01,
771 5.1086700195082710e-01,6.3605368072651503e-01,7.4633190646015079e-01,
772 8.3911697182221882e-01,9.1223442825132591e-01,9.6397192727791379e-01,
773 9.9312859918509492e-01};
774 static const G4double Weights[10] = {1.5275338713072585e-01,1.4917298647260375e-01,1.4209610931838205e-01,
775 1.3168863844917663e-01,1.1819453196151842e-01,1.0193011981724044e-01,
776 8.3276741576704749e-02,6.2672048334109064e-02,4.0601429800386941e-02,
777 1.7614007139152118e-02};
795 (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
796 for (
G4int i=2;i<=npoints;i++)
800 (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
802 G4int icall = 2*npoints;
804 G4double S[nst],x[nst],sn[nst],xrn[nst];
817 for (
G4int i=1;i<=LH;i++){
826 (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
828 for (
G4int j=1;j<npoints;j++)
831 dLocal += Weights[j]*
832 (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
839 (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
841 for (
G4int j=1;j<npoints;j++)
844 dLocal += Weights[j]*
845 (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
848 icall=icall+4*npoints;
850 if (std::abs(s12-si)<
std::max(Ptol*std::abs(s12),1e-35))
862 if (icall>ncallsmax || LHN>nst)
865 G4cout <<
"LowPoint: " << LowPoint <<
", High Point: " << HighPoint <<
G4endl;
867 G4cout <<
"Calls: " << icall <<
", Integral: " << sumga <<
", Error: " << Err <<
G4endl;
868 G4cout <<
"Number of open subintervals: " << LHN <<
G4endl;
869 G4cout <<
"WARNING: the required accuracy has not been attained" <<
G4endl;
873 Err=std::abs(sumr)/
std::max(std::abs(sumr+sumga),1e-35);
874 if (Err < Ctol || LHN == 0)
877 for (
G4int i=0;i<LH;i++)
882 }
while(Ctol < 1.0 && loopAgain);
906 G4double csl = 0.5*eks*t0*t0+ek2*t0+ek1*std::log(t0)-(1.0/t0);
910 for (
size_t i=0;i<theTable->size();i++)
914 G4double tau=(energy-ionEnergy)/energy;
917 G4double csu = 0.5*eks*tau*tau+ek2*tau+ek1*std::log(tau)-(1.0/tau);
920 cs += stre*(csu-csl);
G4double GetIonisationEnergy()
G4double LowEnergyLimit() const
G4bool CheckDeexcitationActiveRegion(G4int coupleIndex)
static G4LossTableManager * Instance()
G4double GetKineticEnergy() const
G4double HighEnergyLimit() const
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double, G4double, G4double, G4double, G4double)
const G4String & GetName() const
virtual void SetupForMaterial(const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
static G4Electron * Definition()
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
G4double BindingEnergy() const
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4PenelopeOscillatorTable * GetOscillatorTableCompton(const G4Material *)
G4double GetOscillatorStrength()
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void SetHighEnergyLimit(G4double)
G4GLOB_DLL std::ostream G4cout
const G4ThreeVector & GetMomentumDirection() const
Hep3Vector & rotateUz(const Hep3Vector &)
static G4PenelopeOscillatorManager * GetOscillatorManager()
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
G4double GetTotNbOfAtomsPerVolume() const
G4ParticleChangeForGamma * fParticleChange
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
T max(const T t1, const T t2)
brief Return the largest of the two arguments
const G4ParticleDefinition * fParticle
std::vector< G4PenelopeOscillator * > G4PenelopeOscillatorTable
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
static G4Electron * Electron()
void SetProposedKineticEnergy(G4double proposedKinEnergy)
virtual ~G4PenelopeComptonModel()
G4PenelopeComptonModel(const G4ParticleDefinition *p=0, const G4String &processName="PenCompton")
G4VAtomDeexcitation * AtomDeexcitation()
void ProposeTrackStatus(G4TrackStatus status)
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
void SetDeexcitationFlag(G4bool val)
G4double GetAtomsPerMolecule(const G4Material *)
Returns the total number of atoms per molecule.
G4double bindingEnergy(G4int A, G4int Z)
static G4AtomicTransitionManager * Instance()
G4AtomicShell * Shell(G4int Z, size_t shellIndex) const
G4double GetTotalZ(const G4Material *)
G4ParticleChangeForGamma * GetParticleChangeForGamma()
static G4Gamma * Definition()
const G4Material * GetMaterial() const
G4double GetHartreeFactor()
virtual void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel)