72 :
G4VEmModel(nam),fParticleChange(0),isInitialised(false),
73 fAtomDeexcitation(0),kineticEnergy1(0.*
eV),
74 cosThetaPrimary(1.0),energySecondary(0.*
eV),
75 cosThetaSecondary(0.0),targetOscillator(-1),
76 theCrossSectionHandler(0)
78 fIntrinsicLowEnergyLimit = 100.0*
eV;
79 fIntrinsicHighEnergyLimit = 100.0*
GeV;
103 if (theCrossSectionHandler)
104 delete theCrossSectionHandler;
112 if (verboseLevel > 3)
113 G4cout <<
"Calling G4PenelopeIonisationModel::Initialise()" <<
G4endl;
117 if (!fAtomDeexcitation)
120 G4cout <<
"WARNING from G4PenelopeIonisationModel " <<
G4endl;
121 G4cout <<
"Atomic de-excitation module is not instantiated, so there will not be ";
123 G4cout <<
"Please make sure this is intended" <<
G4endl;
128 nBins = std::max(nBins,(
size_t)100);
131 if (theCrossSectionHandler)
133 delete theCrossSectionHandler;
134 theCrossSectionHandler = 0;
139 if (verboseLevel > 2) {
140 G4cout <<
"Penelope Ionisation model v2008 is initialized " << G4endl
148 if(isInitialised)
return;
150 isInitialised =
true;
178 if (verboseLevel > 3)
179 G4cout <<
"Calling CrossSectionPerVolume() of G4PenelopeIonisationModel" <<
G4endl;
197 if (verboseLevel > 3)
198 G4cout <<
"Material " << material->
GetName() <<
" has " << atPerMol <<
199 "atoms per molecule" <<
G4endl;
203 moleculeDensity = atomDensity/atPerMol;
205 G4double crossPerVolume = crossPerMolecule*moleculeDensity;
207 if (verboseLevel > 2)
210 G4cout <<
"Mean free path for delta emission > " << cutEnergy/
keV <<
" keV at " <<
211 energy/
keV <<
" keV = " << (1./crossPerVolume)/
mm <<
" mm" << G4endl;
214 G4cout <<
"Total free path for ionisation (no threshold) at " <<
215 energy/
keV <<
" keV = " << (1./totalCross)/
mm <<
" mm" << G4endl;
217 return crossPerVolume;
232 G4cout <<
"*** G4PenelopeIonisationModel -- WARNING ***" <<
G4endl;
233 G4cout <<
"Penelope Ionisation model v2008 does not calculate cross section _per atom_ " <<
G4endl;
234 G4cout <<
"so the result is always zero. For physics values, please invoke " <<
G4endl;
235 G4cout <<
"GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" <<
G4endl;
261 if (verboseLevel > 3)
262 G4cout <<
"Calling ComputeDEDX() of G4PenelopeIonisationModel" <<
G4endl;
278 moleculeDensity = atomDensity/atPerMol;
280 G4double sPowerPerVolume = sPowerPerMolecule*moleculeDensity;
282 if (verboseLevel > 2)
285 G4cout <<
"Stopping power < " << cutEnergy/
keV <<
" keV at " <<
286 kineticEnergy/
keV <<
" keV = " <<
287 sPowerPerVolume/(
keV/
mm) <<
" keV/mm" << G4endl;
289 return sPowerPerVolume;
297 return fIntrinsicLowEnergyLimit;
339 if (verboseLevel > 3)
340 G4cout <<
"Calling SamplingSecondaries() of G4PenelopeIonisationModel" <<
G4endl;
345 if (kineticEnergy0 <= fIntrinsicLowEnergyLimit)
359 kineticEnergy1=kineticEnergy0;
362 cosThetaSecondary=1.0;
363 targetOscillator = -1;
366 SampleFinalStateElectron(material,cutE,kineticEnergy0);
368 SampleFinalStatePositron(material,cutE,kineticEnergy0);
373 G4Exception(
"G4PenelopeIonisationModel::SamplingSecondaries()",
377 if (energySecondary == 0)
return;
379 if (verboseLevel > 3)
381 G4cout <<
"G4PenelopeIonisationModel::SamplingSecondaries() for " <<
383 G4cout <<
"Final eKin = " << kineticEnergy1 <<
" keV" <<
G4endl;
384 G4cout <<
"Final cosTheta = " << cosThetaPrimary <<
G4endl;
385 G4cout <<
"Delta-ray eKin = " << energySecondary <<
" keV" <<
G4endl;
386 G4cout <<
"Delta-ray cosTheta = " << cosThetaSecondary <<
G4endl;
391 G4double sint = std::sqrt(1. - cosThetaPrimary*cosThetaPrimary);
393 G4double dirx = sint * std::cos(phiPrimary);
394 G4double diry = sint * std::sin(phiPrimary);
398 electronDirection1.
rotateUz(particleDirection0);
400 if (kineticEnergy1 > 0)
410 G4double ionEnergyInPenelopeDatabase =
411 (*theTable)[targetOscillator]->GetIonisationEnergy();
415 G4int shFlag = (*theTable)[targetOscillator]->GetShellFlag();
416 G4int Z = (
G4int) (*theTable)[targetOscillator]->GetParentZ();
425 if (Z > 0 && shFlag<30)
427 shell = transitionManager->
Shell(Z,shFlag-1);
435 energySecondary += ionEnergyInPenelopeDatabase-
bindingEnergy;
442 if (energySecondary < 0)
448 localEnergyDeposit += energySecondary;
449 energySecondary = 0.0;
454 if (fAtomDeexcitation && shell)
459 size_t nBefore = fvect->size();
461 size_t nAfter = fvect->size();
463 if (nAfter > nBefore)
465 for (
size_t j=nBefore;j<nAfter;j++)
467 G4double itsEnergy = ((*fvect)[j])->GetKineticEnergy();
468 localEnergyDeposit -= itsEnergy;
470 energyInFluorescence += itsEnergy;
472 energyInAuger += itsEnergy;
479 if (energySecondary > cutE)
482 G4double sinThetaE = std::sqrt(1.-cosThetaSecondary*cosThetaSecondary);
484 G4double xEl = sinThetaE * std::cos(phiEl);
485 G4double yEl = sinThetaE * std::sin(phiEl);
488 eDirection.
rotateUz(particleDirection0);
490 eDirection,energySecondary) ;
491 fvect->push_back(electron);
495 localEnergyDeposit += energySecondary;
499 if (localEnergyDeposit < 0)
502 <<
"G4PenelopeIonisationModel::SampleSecondaries - Negative energy deposit"
504 localEnergyDeposit=0.;
508 if (verboseLevel > 1)
510 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
511 G4cout <<
"Energy balance from G4PenelopeIonisation" <<
G4endl;
512 G4cout <<
"Incoming primary energy: " << kineticEnergy0/
keV <<
" keV" <<
G4endl;
513 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
514 G4cout <<
"Outgoing primary energy: " << kineticEnergy1/
keV <<
" keV" <<
G4endl;
516 if (energyInFluorescence)
517 G4cout <<
"Fluorescence x-rays: " << energyInFluorescence/
keV <<
" keV" <<
G4endl;
519 G4cout <<
"Auger electrons: " << energyInAuger/
keV <<
" keV" <<
G4endl;
520 G4cout <<
"Local energy deposit " << localEnergyDeposit/
keV <<
" keV" <<
G4endl;
521 G4cout <<
"Total final state: " << (energySecondary+energyInFluorescence+kineticEnergy1+
522 localEnergyDeposit+energyInAuger)/
keV <<
524 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
527 if (verboseLevel > 0)
529 G4double energyDiff = std::fabs(energySecondary+energyInFluorescence+kineticEnergy1+
530 localEnergyDeposit+energyInAuger-kineticEnergy0);
531 if (energyDiff > 0.05*
keV)
532 G4cout <<
"Warning from G4PenelopeIonisation: problem with energy conservation: " <<
533 (energySecondary+energyInFluorescence+kineticEnergy1+localEnergyDeposit+energyInAuger)/
keV <<
534 " keV (final) vs. " <<
535 kineticEnergy0/
keV <<
" keV (initial)" << G4endl;
541 void G4PenelopeIonisationModel::SampleFinalStateElectron(
const G4Material*
mat,
554 size_t numberOfOscillators = theTable->size();
562 targetOscillator = numberOfOscillators-1;
565 for (
size_t i=0;i<numberOfOscillators-1;i++)
577 targetOscillator = (
G4int) i;
583 if (verboseLevel > 3)
585 G4cout <<
"SampleFinalStateElectron: sampled oscillator #" << targetOscillator <<
"." <<
G4endl;
586 G4cout <<
"Ionisation energy: " << (*theTable)[targetOscillator]->GetIonisationEnergy()/
eV <<
588 G4cout <<
"Resonance energy: : " << (*theTable)[targetOscillator]->GetResonanceEnergy()/
eV <<
" eV "
599 G4double resEne = (*theTable)[targetOscillator]->GetResonanceEnergy();
601 G4double ionEne = (*theTable)[targetOscillator]->GetIonisationEnergy();
602 G4double cutoffEne = (*theTable)[targetOscillator]->GetCutoffRecoilResonantEnergy();
610 if (resEne > cutEnergy && resEne < kineticEnergy)
612 cps = kineticEnergy*rb;
614 G4double XHDT0 = std::max(std::log(gam2)-beta2-delta,0.);
615 if (resEne > 1.0
e-6*kineticEnergy)
629 XHDT = XHDT0*invResEne;
648 G4double EE = kineticEnergy + ionEne;
650 G4double wcl = std::max(cutEnergy,cutoffEne);
657 XHC = (amol*(0.5-rcl)+1.0/rcl-rrl1+
658 (1.0-amol)*std::log(rcl*rrl1))/EE;
665 if (XHTOT < 1.
e-14*
barn)
667 kineticEnergy1=kineticEnergy;
670 cosThetaSecondary=1.0;
671 targetOscillator = numberOfOscillators-1;
693 rk = rcl/(1.0-fb*(1.0-(rcl+rcl)));
695 rk = rcl + (fb-1.0)*(0.5-rcl)/ARCL;
698 G4double phi = 1.0+rkf*rkf-rkf+amol*(rk2+rkf);
705 kineticEnergy1 = kineticEnergy - deltaE;
706 cosThetaPrimary = std::sqrt(kineticEnergy1*rb/(kineticEnergy*(rb-deltaE)));
708 energySecondary = deltaE - ionEne;
709 cosThetaSecondary= std::sqrt(deltaE*rb/(kineticEnergy*(deltaE+2.0*
electron_mass_c2)));
710 if (verboseLevel > 3)
711 G4cout <<
"SampleFinalStateElectron: sampled close collision " <<
G4endl;
718 kineticEnergy1 = kineticEnergy - deltaE;
727 cosThetaPrimary = (cpps+cps-QTREV)/(2.0*cp*std::sqrt(cpps));
728 if (cosThetaPrimary > 1.)
729 cosThetaPrimary = 1.0;
731 energySecondary = deltaE - ionEne;
732 cosThetaSecondary = 0.5*(deltaE*(kineticEnergy+rb-deltaE)+QTREV)/std::sqrt(cps*QTREV);
733 if (cosThetaSecondary > 1.0)
734 cosThetaSecondary = 1.0;
735 if (verboseLevel > 3)
736 G4cout <<
"SampleFinalStateElectron: sampled distant longitudinal collision " <<
G4endl;
741 cosThetaPrimary = 1.0;
743 energySecondary = deltaE - ionEne;
744 cosThetaSecondary = 0.5;
745 if (verboseLevel > 3)
746 G4cout <<
"SampleFinalStateElectron: sampled distant transverse collision " <<
G4endl;
754 void G4PenelopeIonisationModel::SampleFinalStatePositron(
const G4Material* mat,
767 size_t numberOfOscillators = theTable->size();
774 targetOscillator = numberOfOscillators-1;
776 for (
size_t i=0;i<numberOfOscillators-1;i++)
781 targetOscillator = (
G4int) i;
786 if (verboseLevel > 3)
788 G4cout <<
"SampleFinalStatePositron: sampled oscillator #" << targetOscillator <<
"." <<
G4endl;
789 G4cout <<
"Ionisation energy: " << (*theTable)[targetOscillator]->GetIonisationEnergy()/
eV
791 G4cout <<
"Resonance energy: : " << (*theTable)[targetOscillator]->GetResonanceEnergy()/
eV
803 G4double bha1 = amol*(2.0*g12-1.0)/(gam2-1.0);
805 G4double bha3 = amol*2.0*gam*(gam-1.0)/g12;
806 G4double bha4 = amol*(gam-1.0)*(gam-1.0)/g12;
811 G4double resEne = (*theTable)[targetOscillator]->GetResonanceEnergy();
813 G4double ionEne = (*theTable)[targetOscillator]->GetIonisationEnergy();
814 G4double cutoffEne = (*theTable)[targetOscillator]->GetCutoffRecoilResonantEnergy();
823 if (resEne > cutEnergy && resEne < kineticEnergy)
825 cps = kineticEnergy*rb;
827 G4double XHDT0 = std::max(std::log(gam2)-beta2-delta,0.);
828 if (resEne > 1.0
e-6*kineticEnergy)
842 XHDT = XHDT0*invResEne;
861 G4double wcl = std::max(cutEnergy,cutoffEne);
867 XHC = ((1.0/rcl-1.0)+bha1*std::log(rcl)+bha2*rl1
868 + (bha3/2.0)*(rcl*rcl-1.0)
869 + (bha4/3.0)*(1.0-rcl*rcl*rcl))/kineticEnergy;
876 if (XHTOT < 1.
e-14*
barn)
878 kineticEnergy1=kineticEnergy;
881 cosThetaSecondary=1.0;
882 targetOscillator = numberOfOscillators-1;
900 G4double phi = 1.0-rk*(bha1-rk*(bha2-rk*(bha3-bha4*rk)));
906 kineticEnergy1 = kineticEnergy - deltaE;
907 cosThetaPrimary = std::sqrt(kineticEnergy1*rb/(kineticEnergy*(rb-deltaE)));
909 energySecondary = deltaE - ionEne;
910 cosThetaSecondary= std::sqrt(deltaE*rb/(kineticEnergy*(deltaE+2.0*
electron_mass_c2)));
911 if (verboseLevel > 3)
912 G4cout <<
"SampleFinalStatePositron: sampled close collision " <<
G4endl;
919 kineticEnergy1 = kineticEnergy - deltaE;
927 cosThetaPrimary = (cpps+cps-QTREV)/(2.0*cp*std::sqrt(cpps));
928 if (cosThetaPrimary > 1.)
929 cosThetaPrimary = 1.0;
931 energySecondary = deltaE - ionEne;
932 cosThetaSecondary = 0.5*(deltaE*(kineticEnergy+rb-deltaE)+QTREV)/std::sqrt(cps*QTREV);
933 if (cosThetaSecondary > 1.0)
934 cosThetaSecondary = 1.0;
935 if (verboseLevel > 3)
936 G4cout <<
"SampleFinalStatePositron: sampled distant longitudinal collision " <<
G4endl;
941 cosThetaPrimary = 1.0;
943 energySecondary = deltaE - ionEne;
944 cosThetaSecondary = 0.5;
946 if (verboseLevel > 3)
947 G4cout <<
"SampleFinalStatePositron: sampled distant transverse collision " <<
G4endl;