File indexing completed on 2026-07-13 08:21:04
0001
0002 #include "G4HepEmGammaInteractionPhotoelectric.hh"
0003
0004
0005 #include "G4HepEmTLData.hh"
0006 #include "G4HepEmData.hh"
0007 #include "G4HepEmElementData.hh"
0008 #include "G4HepEmMaterialData.hh"
0009 #include "G4HepEmMatCutData.hh"
0010 #include "G4HepEmRunUtils.hh"
0011 #include "G4HepEmConstants.hh"
0012
0013 void G4HepEmGammaInteractionPhotoelectric::Perform(G4HepEmTLData* tlData, struct G4HepEmData* hepEmData) {
0014 G4HepEmGammaTrack* theGammaTrack = tlData->GetPrimaryGammaTrack();
0015 G4HepEmTrack* thePrimaryTrack = theGammaTrack->GetTrack();
0016 const double* theGammaDir = thePrimaryTrack->GetDirection();
0017 const double theGammaE = thePrimaryTrack->GetEKin();
0018
0019 const int theMCIndx = thePrimaryTrack->GetMCIndex();
0020 const double mxsec = theGammaTrack->GetPEmxSec();
0021
0022 const double bindingEnergy = SelectElementBindingEnergy(hepEmData, theMCIndx, mxsec, theGammaE, tlData->GetRNGEngine());
0023
0024 const double theLowEnergyThreshold = 0.000001;
0025 const double photoElecE = theGammaE - bindingEnergy;
0026 if (photoElecE > theLowEnergyThreshold) {
0027 G4HepEmTrack* theSecTrack = tlData->AddSecondaryElectronTrack()->GetTrack();
0028 double* theSecElDir = theSecTrack->GetDirection();
0029 SamplePhotoElectronDirection(photoElecE, theGammaDir, theSecElDir, tlData->GetRNGEngine());
0030 theSecTrack->SetEKin(photoElecE);
0031 theSecTrack->SetParentID(thePrimaryTrack->GetID());
0032 thePrimaryTrack->SetEnergyDeposit(bindingEnergy);
0033 } else {
0034 thePrimaryTrack->SetEnergyDeposit(theGammaE);
0035 }
0036 thePrimaryTrack->SetEKin(0.0);
0037 }
0038
0039 double G4HepEmGammaInteractionPhotoelectric::SelectElementBindingEnergy(const struct G4HepEmData* hepEmData, const int imc, const double mxsec, const double ekin, G4HepEmRandomEngine *rnge) {
0040 const int theMatIndx = hepEmData->fTheMatCutData->fMatCutData[imc].fHepEmMatIndex;
0041 const G4HepEmMatData& theMData = hepEmData->fTheMaterialData->fMaterialData[theMatIndx];
0042
0043
0044
0045
0046 int ielem = 0;
0047 if (theMData.fNumOfElement > 1) {
0048 const double x = rnge->flat() * mxsec;
0049 double sum = 0;
0050 double invE = 1 / ekin;
0051 for (int i = 0; i < theMData.fNumOfElement; i++) {
0052 const G4HepEmElemData& theEData = hepEmData->fTheElementData->fElementData[theMData.fElementVect[i]];
0053 int interval = 0;
0054 if (ekin >= theEData.fSandiaEnergies[0]) {
0055
0056 for (int i = theEData.fNumOfSandiaIntervals - 1; i >= 0; i--) {
0057 if (ekin >= theEData.fSandiaEnergies[i]) {
0058 interval = i;
0059 break;
0060 }
0061 }
0062 }
0063 const double* sandiaCof = &theEData.fSandiaCoefficients[4 * interval];
0064 sum += theMData.fNumOfAtomsPerVolumeVect[i] *
0065 invE * (sandiaCof[0] + invE * (sandiaCof[1] + invE * (sandiaCof[2] + invE * sandiaCof[3])));
0066 if (x <= sum) {
0067 ielem = i;
0068 break;
0069 }
0070 }
0071 }
0072
0073
0074
0075
0076
0077 return hepEmData->fTheElementData->fElementData[theMData.fElementVect[ielem]].fKShellBindingEnergy;
0078 }
0079
0080 void G4HepEmGammaInteractionPhotoelectric::SamplePhotoElectronDirection(const double kinE, const double* theGammaDir, double* theDir, G4HepEmRandomEngine* rnge) {
0081
0082
0083
0084
0085 const double tau = kinE * kInvElectronMassC2;
0086 const double gamma = 1.0 + tau;
0087 const double beta = std::sqrt(tau*(tau + 2.0))/gamma;
0088
0089
0090
0091 const double ac = (1.0 - beta)/beta;
0092 const double a1 = 0.5*beta*gamma*tau*(gamma-2.0);
0093 const double a2 = ac + 2.0;
0094
0095
0096 const double gtmax = 2.0*(a1 + 1.0/ac);
0097
0098 double tsam = 0.0;
0099 double gtr = 0.0;
0100
0101
0102
0103
0104 double rndm[2];
0105 do {
0106 rnge->flatArray(2, rndm);
0107 tsam = 2.0*ac * (2.0*rndm[0] + a2*std::sqrt(rndm[0])) / (a2*a2 - 4.0*rndm[0]);
0108 gtr = (2.0 - tsam) * (a1 + 1.0/(ac+tsam));
0109
0110 } while(rndm[1]*gtmax > gtr);
0111
0112 const double costheta = 1.0 - tsam;
0113
0114 const double sint = std::sqrt(tsam*(2.0 - tsam));
0115 const double phi = k2Pi*rnge->flat();
0116
0117 theDir[0] = sint * std::cos(phi);
0118 theDir[1] = sint * std::sin(phi);
0119 theDir[2] = costheta;
0120 RotateToReferenceFrame(theDir, theGammaDir);
0121 }