File indexing completed on 2026-07-13 08:21:05
0001 #include "G4HepEmGammaManager.hh"
0002
0003 #include "G4HepEmData.hh"
0004 #include "G4HepEmParameters.hh"
0005 #include "G4HepEmTLData.hh"
0006
0007 #include "G4HepEmConstants.hh"
0008 #include "G4HepEmMatCutData.hh"
0009 #include "G4HepEmMaterialData.hh"
0010 #include "G4HepEmGammaData.hh"
0011
0012 #include "G4HepEmMath.hh"
0013
0014 #include "G4HepEmRunUtils.hh"
0015 #include "G4HepEmTrack.hh"
0016 #include "G4HepEmElectronTrack.hh"
0017 #include "G4HepEmGammaTrack.hh"
0018
0019 #include "G4HepEmGammaInteractionConversion.hh"
0020 #include "G4HepEmGammaInteractionCompton.hh"
0021 #include "G4HepEmGammaInteractionPhotoelectric.hh"
0022
0023 #include <iostream>
0024
0025
0026
0027 void G4HepEmGammaManager::HowFar(struct G4HepEmData* hepEmData, struct G4HepEmParameters* hepEmPars, G4HepEmTLData* tlData) {
0028 G4HepEmGammaTrack* theGammaTrack = tlData->GetPrimaryGammaTrack();
0029 G4HepEmTrack* theTrack = theGammaTrack->GetTrack();
0030
0031 if (theTrack->GetNumIALeft(0) <= 0.0) {
0032 theTrack->SetNumIALeft(-G4HepEmLog(tlData->GetRNGEngine()->flat()), 0);
0033 }
0034 HowFar(hepEmData, hepEmPars, theGammaTrack);
0035 }
0036
0037
0038 void G4HepEmGammaManager::HowFar(struct G4HepEmData* hepEmData, struct G4HepEmParameters* , G4HepEmGammaTrack* theGammaTrack) {
0039 G4HepEmTrack* theTrack = theGammaTrack->GetTrack();
0040
0041
0042 const double totMXSec = GetTotalMacXSec(hepEmData, theGammaTrack);
0043 const double totalMFP = (totMXSec>0.) ? 1./totMXSec : kALargeValue;
0044
0045 theTrack->SetMFP(totalMFP, 0);
0046
0047 theTrack->SetGStepLength(totalMFP*theTrack->GetNumIALeft(0));
0048 }
0049
0050
0051
0052
0053
0054 void G4HepEmGammaManager::Perform(struct G4HepEmData* hepEmData, struct G4HepEmParameters* hepEmPars, G4HepEmTLData* tlData) {
0055 G4HepEmTrack* theTrack = tlData->GetPrimaryGammaTrack()->GetTrack();
0056
0057
0058
0059 UpdateNumIALeft(theTrack);
0060
0061 theTrack->SetEnergyDeposit(0.0);
0062
0063
0064
0065 if (theTrack->GetOnBoundary()) {
0066 return;
0067 }
0068
0069
0070 const int iDProc = theTrack->GetWinnerProcessIndex();
0071 theTrack->SetNumIALeft(-1.0, iDProc);
0072
0073
0074 switch (iDProc) {
0075 case 0:
0076 G4HepEmGammaInteractionConversion::Perform(tlData, hepEmData);
0077 break;
0078 case 1:
0079 G4HepEmGammaInteractionCompton::Perform(tlData, hepEmData);
0080 break;
0081 case 2:
0082 G4HepEmGammaInteractionPhotoelectric::Perform(tlData, hepEmData);
0083 break;
0084 case 3:
0085
0086 break;
0087 }
0088
0089 const double finalEkin = theTrack->GetEKin();
0090 if (finalEkin > 0.0 && finalEkin <= hepEmPars->fGammaTrackingCut) {
0091 theTrack->SetEKin(0.0);
0092 theTrack->AddEnergyDeposit(finalEkin);
0093 }
0094 }
0095
0096
0097 void G4HepEmGammaManager::UpdateNumIALeft(G4HepEmTrack* theTrack) {
0098 const double pStepLength = theTrack->GetGStepLength();
0099
0100
0101
0102 double* preStepMFP = theTrack->GetMFP();
0103 double* numInterALeft = theTrack->GetNumIALeft();
0104 numInterALeft[0] -= pStepLength/preStepMFP[0];
0105 }
0106
0107
0108 double G4HepEmGammaManager::GetTotalMacXSec(const struct G4HepEmData* hepEmData, G4HepEmGammaTrack* theGammaTrack) {
0109 G4HepEmTrack* theTrack = theGammaTrack->GetTrack();
0110 const double theEkin = theTrack->GetEKin();
0111 const double theLEkin = theTrack->GetLogEKin();
0112 const int theMatIndx = hepEmData->fTheMatCutData->fMatCutData[theTrack->GetMCIndex()].fHepEmMatIndex;
0113
0114 const G4HepEmGammaData* gmData = hepEmData->fTheGammaData;
0115
0116
0117 if (theEkin > gmData->fEMax1) {
0118
0119
0120 const int ndata = gmData->fEGridSize2;
0121 const int istart = theMatIndx*gmData->fDataPerMat + gmData->fNumData0 + gmData->fNumData1;
0122 return GetSplineLog4(ndata, &(gmData->fMacXsecData[istart]), theEkin, theLEkin, gmData->fLogEMin2, gmData->fEILDelta2, 1);
0123 }
0124
0125
0126
0127
0128
0129
0130 if (theEkin > gmData->fEMax0) {
0131
0132
0133 const int ndata = gmData->fEGridSize1;
0134 const int istart = theMatIndx*gmData->fDataPerMat + gmData->fNumData0;
0135
0136 double mx[2];
0137 GetLinearLog2(ndata, &(gmData->fMacXsecData[istart]), theEkin, theLEkin, gmData->fLogEMin1, gmData->fEILDelta1, mx);
0138 theGammaTrack->SetPEmxSec(mx[1]);
0139 return mx[0];
0140 }
0141
0142
0143
0144
0145
0146 const int ndata = gmData->fEGridSize0;
0147 const int istart = theMatIndx*gmData->fDataPerMat;
0148 const double comp = GetLinearLog(ndata, &(gmData->fMacXsecData[istart]), theEkin, theLEkin, gmData->fLogEMin0, gmData->fEILDelta0);
0149 const double pe = G4HepEmMax(0.0, GetMacXSecPE(hepEmData, theMatIndx, theEkin));
0150 theGammaTrack->SetPEmxSec(pe);
0151 return comp+pe;
0152 }
0153
0154
0155 double G4HepEmGammaManager::GetMacXSecPE(const struct G4HepEmData* hepEmData, const int imat, const double ekin) {
0156 const G4HepEmMatData* matData = &hepEmData->fTheMaterialData->fMaterialData[imat];
0157 int interval = 0;
0158 if (ekin >= matData->fSandiaEnergies[0]) {
0159
0160 for (int i = matData->fNumOfSandiaIntervals - 1; i >= 0; i--) {
0161 if (ekin >= matData->fSandiaEnergies[i]) {
0162 interval = i;
0163 break;
0164 }
0165 }
0166 }
0167 const double* sandiaCof = &matData->fSandiaCoefficients[4 * interval];
0168 const double inv = 1 / ekin;
0169 return inv * (sandiaCof[0] + inv * (sandiaCof[1] + inv * (sandiaCof[2] + inv * sandiaCof[3])));
0170 }
0171
0172
0173 void G4HepEmGammaManager::SelectInteraction(const struct G4HepEmData* hepEmData, G4HepEmTLData* tlData) {
0174 G4HepEmGammaTrack* theGammaTrack = tlData->GetPrimaryGammaTrack();
0175
0176
0177 SampleInteraction(hepEmData, theGammaTrack, tlData->GetRNGEngine()->flat());
0178 }
0179
0180
0181
0182
0183
0184
0185
0186
0187 void G4HepEmGammaManager::SampleInteraction(const struct G4HepEmData* hepEmData, G4HepEmGammaTrack* theGammaTrack, const double urnd) {
0188 G4HepEmTrack* theTrack = theGammaTrack->GetTrack();
0189 const double theEkin = theTrack->GetEKin();
0190 const double theTMFP = theTrack->GetMFP(0);
0191
0192 theTrack->SetNumIALeft(-1.0, 0);
0193
0194 const G4HepEmGammaData* gmData = hepEmData->fTheGammaData;
0195
0196 if (theEkin > gmData->fEMax1) {
0197 const double theLEkin = theTrack->GetLogEKin();
0198 const int theMatIndx = hepEmData->fTheMatCutData->fMatCutData[theTrack->GetMCIndex()].fHepEmMatIndex;
0199 const int ndata = gmData->fEGridSize2;
0200 const int istart = theMatIndx*gmData->fDataPerMat + gmData->fNumData0 + gmData->fNumData1;
0201 double mxSec = 0.0;
0202 double cProb = 0.0;
0203 int pid = 2;
0204 do {
0205 mxSec = GetSplineLog4(ndata, &(gmData->fMacXsecData[istart]), theEkin, theLEkin, gmData->fLogEMin2, gmData->fEILDelta2, pid);
0206 cProb += mxSec*theTMFP;
0207 ++pid;
0208 } while (pid<6 && urnd>cProb);
0209 theTrack->SetWinnerProcessIndex(pid-3);
0210 theGammaTrack->SetPEmxSec(mxSec);
0211 return;
0212 }
0213
0214
0215
0216 const double mxPE = theGammaTrack->GetPEmxSec();
0217 const int pid = (urnd > theTMFP*mxPE) ? 1:2;
0218 theTrack->SetWinnerProcessIndex(pid);
0219 }