Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // >> 26 // $Id: G4PairProductionRelModel.cc 83685 2014-09-09 12:39:00Z gcosmo $ 26 // 27 // 27 // ------------------------------------------- 28 // ------------------------------------------------------------------- 28 // 29 // 29 // GEANT4 Class file 30 // GEANT4 Class file 30 // 31 // 31 // 32 // 32 // File name: G4PairProductionRelModel 33 // File name: G4PairProductionRelModel 33 // 34 // 34 // Author: Andreas Schaelicke 35 // Author: Andreas Schaelicke 35 // 36 // 36 // Creation date: 02.04.2009 37 // Creation date: 02.04.2009 37 // 38 // 38 // Modifications: 39 // Modifications: 39 // 20.03.17 Change LPMconstant such that it gi << 40 // that consistent to Migdal's one; f << 41 // computation; suppression is consis << 42 // brem. model (F.Hariri) << 43 // 28-05-18 New version with improved screenin << 44 // LPM function approximation, effici << 45 // Corrected call to selecting target << 46 // (M. Novak) << 47 // 40 // 48 // Class Description: 41 // Class Description: 49 // 42 // 50 // Main References: 43 // Main References: 51 // J.W.Motz et.al., Rev. Mod. Phys. 41 (1969) 44 // J.W.Motz et.al., Rev. Mod. Phys. 41 (1969) 581. 52 // S.Klein, Rev. Mod. Phys. 71 (1999) 1501. 45 // S.Klein, Rev. Mod. Phys. 71 (1999) 1501. 53 // T.Stanev et.al., Phys. Rev. D25 (1982) 129 46 // T.Stanev et.al., Phys. Rev. D25 (1982) 1291. 54 // M.L.Ter-Mikaelian, High-energy Electromagn << 47 // M.L.Ter-Mikaelian, High-energy Electromagnetic Processes in Condensed Media, 55 // Wiley, 1972. 48 // Wiley, 1972. 56 // 49 // 57 // ------------------------------------------- 50 // ------------------------------------------------------------------- >> 51 // >> 52 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 53 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 58 54 59 #include "G4PairProductionRelModel.hh" 55 #include "G4PairProductionRelModel.hh" 60 #include "G4PhysicalConstants.hh" 56 #include "G4PhysicalConstants.hh" 61 #include "G4SystemOfUnits.hh" 57 #include "G4SystemOfUnits.hh" 62 #include "G4Gamma.hh" 58 #include "G4Gamma.hh" 63 #include "G4Electron.hh" 59 #include "G4Electron.hh" 64 #include "G4Positron.hh" 60 #include "G4Positron.hh" >> 61 #include "G4Log.hh" >> 62 65 #include "G4ParticleChangeForGamma.hh" 63 #include "G4ParticleChangeForGamma.hh" 66 #include "G4LossTableManager.hh" 64 #include "G4LossTableManager.hh" 67 #include "G4ModifiedTsai.hh" << 68 #include "G4Exp.hh" 65 #include "G4Exp.hh" 69 #include "G4Pow.hh" << 70 #include "G4AutoLock.hh" << 71 66 72 const G4int G4PairProductionRelModel::gMaxZet << 73 67 74 // LPM constant: \alpha(mc^2)^2/(4\pi*\hbar c) << 68 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 75 const G4double G4PairProductionRelModel::gLPMc << 76 CLHEP::fine_structure_const*CLHEP::electron_ << 77 /(4.*CLHEP::pi*CLHEP::hbarc); << 78 << 79 // abscissas and weights of an 8 point Gauss-L << 80 // for numerical integration on [0,1] << 81 const G4double G4PairProductionRelModel::gXGL[ << 82 1.98550718e-02, 1.01666761e-01, 2.37233795e- << 83 5.91717321e-01, 7.62766205e-01, 8.98333239e- << 84 }; << 85 const G4double G4PairProductionRelModel::gWGL[ << 86 5.06142681e-02, 1.11190517e-01, 1.56853323e- << 87 1.81341892e-01, 1.56853323e-01, 1.11190517e- << 88 }; << 89 << 90 // elastic and inelatic radiation logarithms f << 91 // Thomas-Fermi model doesn't work): computed << 92 const G4double G4PairProductionRelModel::gFelL << 93 0.0, 5.3104, 4.7935, 4.7402, 4.7112, 4.6694, << 94 }; << 95 const G4double G4PairProductionRelModel::gFine << 96 0.0, 5.9173, 5.6125, 5.5377, 5.4728, 5.4174, << 97 }; << 98 << 99 // constant cross section factor << 100 const G4double G4PairProductionRelModel::gXSec << 101 4.*CLHEP::fine_structure_const*CLHEP::classi << 102 *CLHEP::classic_electr_radius; << 103 << 104 // gamma energy limit above which LPM suppress << 105 // fIsUseLPMCorrection flag is true) << 106 const G4double G4PairProductionRelModel::gEgLP << 107 69 108 // special data structure per element i.e. per << 70 using namespace std; 109 std::vector<G4PairProductionRelModel::ElementD << 110 71 111 // LPM supression functions evaluated at initi << 72 const G4double G4PairProductionRelModel::facFel = G4Log(184.15); 112 G4PairProductionRelModel::LPMFuncs G4PairProdu << 73 const G4double G4PairProductionRelModel::facFinel = G4Log(1194.); // 1440. >> 74 >> 75 const G4double G4PairProductionRelModel::preS1 = 1./(184.15*184.15); >> 76 const G4double G4PairProductionRelModel::logTwo = G4Log(2.); >> 77 >> 78 const G4double G4PairProductionRelModel::xgi[]={ 0.0199, 0.1017, 0.2372, 0.4083, >> 79 0.5917, 0.7628, 0.8983, 0.9801 }; >> 80 const G4double G4PairProductionRelModel::wgi[]={ 0.0506, 0.1112, 0.1569, 0.1813, >> 81 0.1813, 0.1569, 0.1112, 0.0506 }; >> 82 const G4double G4PairProductionRelModel::Fel_light[] = {0., 5.31 , 4.79 , 4.74 , 4.71}; >> 83 const G4double G4PairProductionRelModel::Finel_light[] = {0., 6.144 , 5.621 , 5.805 , 5.924}; >> 84 >> 85 static const G4double xsfactor = >> 86 4*fine_structure_const*classic_electr_radius*classic_electr_radius; >> 87 static const G4double Egsmall=2.*MeV; 113 88 114 namespace << 115 { << 116 G4Mutex thePairProdRelMutex = G4MUTEX_INITIA << 117 } << 118 89 119 // CTR << 120 G4PairProductionRelModel::G4PairProductionRelM 90 G4PairProductionRelModel::G4PairProductionRelModel(const G4ParticleDefinition*, 121 << 91 const G4String& nam) 122 : G4VEmModel(nam), fIsUseLPMCorrection(true) << 92 : G4VEmModel(nam), 123 fLPMEnergy(0.), fG4Calc(G4Pow::GetInstance() << 93 fLPMconstant(fine_structure_const*electron_mass_c2*electron_mass_c2/(4.*pi*hbarc)*0.5), 124 fTheElectron(G4Electron::Electron()), fThePo << 94 fLPMflag(true), 125 fParticleChange(nullptr) << 95 lpmEnergy(0.), >> 96 use_completescreening(false) 126 { 97 { 127 // gamma energy below which the parametrized << 98 fParticleChange = 0; 128 fParametrizedXSectionThreshold = 30.0*CLHEP: << 99 theGamma = G4Gamma::Gamma(); 129 // gamma energy below the Coulomb correction << 100 thePositron = G4Positron::Positron(); 130 fCoulombCorrectionThreshold = 50.0*CLHEP: << 101 theElectron = G4Electron::Electron(); 131 // set angular generator used in the final s << 102 132 SetAngularDistribution(new G4ModifiedTsai()) << 103 nist = G4NistManager::Instance(); >> 104 >> 105 currentZ = z13 = z23 = lnZ = Fel = Finel = fCoulomb = phiLPM = gLPM = xiLPM = 0; >> 106 133 } 107 } 134 108 135 // DTR << 109 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 110 136 G4PairProductionRelModel::~G4PairProductionRel 111 G4PairProductionRelModel::~G4PairProductionRelModel() 137 { << 112 {} 138 if (isFirstInstance) { << 113 139 // clear ElementData container << 114 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 140 for (auto const & ptr : gElementData) { de << 141 gElementData.clear(); << 142 // clear LPMFunctions (if any) << 143 if (fIsUseLPMCorrection) { << 144 gLPMFuncs.fLPMFuncG.clear(); << 145 gLPMFuncs.fLPMFuncPhi.clear(); << 146 gLPMFuncs.fIsInitialized = false; << 147 } << 148 } << 149 } << 150 115 151 void G4PairProductionRelModel::Initialise(cons 116 void G4PairProductionRelModel::Initialise(const G4ParticleDefinition* p, 152 cons << 117 const G4DataVector& cuts) 153 { 118 { 154 if(nullptr == fParticleChange) { fParticleCh << 119 if(!fParticleChange) { fParticleChange = GetParticleChangeForGamma(); } 155 << 120 if(IsMaster() && LowEnergyLimit() < HighEnergyLimit()) { 156 if (isFirstInstance || gElementData.empty()) << 121 InitialiseElementSelectors(p, cuts); 157 // init element data and LPM funcs << 158 G4AutoLock l(&thePairProdRelMutex); << 159 if (gElementData.empty()) { << 160 isFirstInstance = true; << 161 gElementData.resize(gMaxZet+1, nullptr); << 162 } << 163 // static data should be initialised only << 164 InitialiseElementData(); << 165 if (fIsUseLPMCorrection) { << 166 InitLPMFunctions(); << 167 } << 168 l.unlock(); << 169 } << 170 // element selectors should be initialised i << 171 if (IsMaster()) { << 172 InitialiseElementSelectors(p, cuts); << 173 } 122 } 174 } 123 } 175 124 >> 125 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 126 176 void G4PairProductionRelModel::InitialiseLocal 127 void G4PairProductionRelModel::InitialiseLocal(const G4ParticleDefinition*, 177 << 128 G4VEmModel* masterModel) 178 { 129 { 179 SetElementSelectors(masterModel->GetElementS << 130 if(LowEnergyLimit() < HighEnergyLimit()) { >> 131 SetElementSelectors(masterModel->GetElementSelectors()); >> 132 } 180 } 133 } 181 134 182 G4double G4PairProductionRelModel::ComputeXSec << 135 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 183 << 136 >> 137 G4double G4PairProductionRelModel::ComputeXSectionPerAtom(G4double totalEnergy, G4double Z) 184 { 138 { 185 G4double xSection = 0.0; << 139 G4double cross = 0.0; 186 // check if LPM suppression needs to be used << 140 187 const G4bool isLPM = (fIsUseLPMCorrection << 141 // number of intervals and integration step 188 // determine the kinematical limits (taken i << 142 G4double vcut = electron_mass_c2/totalEnergy ; 189 // the way in which the Coulomb correction i << 143 190 const G4int iz = std::min(gMaxZet, G4 << 144 // limits by the screening variable 191 const G4double eps0 = CLHEP::electron_mass << 145 G4double dmax = DeltaMax(); 192 // Coulomb correction is always included in << 146 G4double dmin = min(DeltaMin(totalEnergy),dmax); 193 // that this DCS is only used to get the int << 147 G4double vcut1 = 0.5 - 0.5*sqrt(1. - dmin/dmax) ; 194 const G4double dmax = gElementData[iz]->fD << 148 vcut = max(vcut, vcut1); 195 const G4double dmin = 4.*eps0*gElementData << 149 196 const G4double eps1 = 0.5 - 0.5*std::sqrt( << 150 197 const G4double epsMin = std::max(eps0, eps1) << 151 G4double vmax = 0.5; 198 const G4double epsMax = 0.5; // DCS is symme << 152 G4int n = 1; // needs optimisation 199 // let Et be the total energy transferred to << 153 200 // the [Et-min, Et-max] interval will be div << 154 G4double delta = (vmax - vcut)*totalEnergy/G4double(n); 201 // with width of dInterv = (Et-max - Et-min) << 155 202 // be done in each sub-inteval using the xi << 156 G4double e0 = vcut*totalEnergy; 203 // that is in [0,1]. The 8-point GL q. is us << 157 G4double xs; 204 const G4int numSub = 2; << 158 205 const G4double dInterv= (epsMax - epsMin)*ga << 159 // simple integration 206 G4double minEti = epsMin*gammaEnergy; << 160 for(G4int l=0; l<n; l++,e0 += delta) { 207 for (G4int i = 0; i < numSub; ++i) { << 161 for(G4int i=0; i<8; i++) { 208 for (G4int ngl = 0; ngl < 8; ++ngl) { << 162 209 const G4double Et = (minEti + gXGL[ngl]* << 163 G4double eg = (e0 + xgi[i]*delta); 210 const G4double xs = isLPM ? ComputeRelDX << 164 if (fLPMflag && totalEnergy>100.*GeV) 211 : ComputeDXSec << 165 xs = ComputeRelDXSectionPerAtom(eg,totalEnergy,Z); 212 xSection += gWGL[ngl]*xs; << 166 else >> 167 xs = ComputeDXSectionPerAtom(eg,totalEnergy,Z); >> 168 cross += wgi[i]*xs; >> 169 213 } 170 } 214 // update minimum Et of the sub-inteval << 215 minEti += dInterv; << 216 } 171 } 217 // apply corrections of variable transformat << 172 218 xSection = std::max(2.*xSection*dInterv, 0.) << 173 cross *= delta*2.; 219 return xSection; << 174 >> 175 return cross; 220 } 176 } 221 177 222 // DCS WITHOUT LPM SUPPRESSION << 178 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 223 // Computes DCS value for a given target eleme << 179 224 // total energy transferred to one of the e-/e << 180 G4double 225 // The constant factor 4 \alpha r_0^2 Z (Z +\e << 181 G4PairProductionRelModel::ComputeDXSectionPerAtom(G4double eplusEnergy, 226 // the returned value will be differential in << 182 G4double totalEnergy, 227 // the eps=Et/Eg. The computed part of the DCS << 183 G4double /*Z*/) 228 // NORMAL CASE: DEFAULT STTING (i.e. fIsUseCom << 229 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = (eps^2+ << 230 // + 2*eps(1-eps)*[phi2(d)/4-ln(Z)/3-fc]/3 whe << 231 // screening variable d=d(eps)=136Z^(-1/3)eps0 << 232 // COMPLETE SCREENING (when d(eps) approx-equa << 233 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = (eps^2+ << 234 // -eps(1-eps)/9 where Lel=phi1(0)/4-ln(Z)/3 i << 235 // logarithm, fc is the Coulomb correction and << 236 // phi1(0)/4-1/6-ln(Z)/3 = Lel-1/6 (due to phi << 237 G4double G4PairProductionRelModel::ComputeDXSe << 238 << 239 << 240 { 184 { 241 G4double xSection = 0.; << 185 // most simple case - complete screening: 242 const G4int iz = std::min(gMaxZet, G4lr << 186 243 const G4double eps = pEnergy/gammaEnergy; << 187 // dsig/dE+ = 4 * alpha * Z**2 * r0**2 / k 244 const G4double epsm = 1.-eps; << 188 // * [ (y**2 + (1-y**2) + 2/3*y*(1-y) ) * ( log (183 * Z**-1/3) + 1/9 * y*(1-y) ] 245 const G4double dum = eps*epsm; << 189 // y = E+/k 246 if (fIsUseCompleteScreening) { << 190 G4double yp=eplusEnergy/totalEnergy; 247 // complete screening: << 191 G4double ym=1.-yp; 248 const G4double Lel = gElementData[iz]->f << 192 249 const G4double fc = gElementData[iz]->f << 193 G4double cross = 0.; 250 xSection = (eps*eps + epsm*epsm + 2.*dum/3 << 194 if (use_completescreening) 251 } else { << 195 cross = (yp*yp + ym*ym + 2./3.*ym*yp)*(Fel - fCoulomb) + 1./9.*yp*ym; 252 // normal case: << 196 else { 253 const G4double eps0 = CLHEP::electron_mas << 197 G4double delta = 0.25*DeltaMin(totalEnergy)/(yp*ym); 254 const G4double fc = gElementData[iz]->f << 198 cross = (yp*yp + ym*ym)*(0.25*Phi1(delta) - lnZ/3. - fCoulomb) 255 const G4double lnZ13 = gElementData[iz]->f << 199 + 2./3.*ym*yp*(0.25*Phi2(delta) - lnZ/3. - fCoulomb); 256 const G4double delta = gElementData[iz]->f << 257 G4double phi1, phi2; << 258 ComputePhi12(delta, phi1, phi2); << 259 xSection = (eps*eps + epsm*epsm)*(0.25*ph << 260 + 2.*dum*(0.25*phi2-lnZ13-fc)/3 << 261 } 200 } 262 // non-const. part of the DCS differential i << 201 return cross/totalEnergy; 263 // ds/dEt=ds/deps deps/dEt with deps/dEt=1/E << 202 264 return std::max(xSection, 0.0)/gammaEnergy; << 265 } 203 } >> 204 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 266 205 267 // DCS WITH POSSIBLE LPM SUPPRESSION << 206 G4double 268 // Computes DCS value for a given target eleme << 207 G4PairProductionRelModel::ComputeRelDXSectionPerAtom(G4double eplusEnergy, 269 // total energy transferred to one of the e-/e << 208 G4double totalEnergy, 270 // For a given Z, the LPM suppression will dep << 209 G4double /*Z*/) 271 // LMP-Energy. This will determine the suppres << 272 // pression functions xi(s), fi(s) and G(s). << 273 // The constant factor 4 \alpha r_0^2 Z (Z +\e << 274 // the returned value will be differential in << 275 // the eps=Et/Eg. The computed part of the DCS << 276 // NORMAL CASE: DEFAULT STTING (i.e. fIsUseCom << 277 // ds/deps(Et,Eg,Z)=ds/deps(eps,Z) = xi(s)*{ ( << 278 // *[phi1(d)/4-ln(Z)/3-fc] + 2*eps(1-eps)*G(s) << 279 // the universal (in the TF model) screening v << 280 // /[eps*(1-eps)] with eps0=mc^2/Eg. << 281 // COMPLETE SCREENING (when d(eps) approx-equa << 282 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = xi(s)*{ << 283 // *(1-eps)/3)*2fi(s)/3 + G(s)/3] - eps(1-eps) << 284 // Note, that when the LPM suppression is abse << 285 // the normal and the complete screening DCS g << 286 G4double G4PairProductionRelModel::ComputeRelD << 287 << 288 << 289 { 210 { 290 G4double xSection = 0.; << 211 // most simple case - complete screening: 291 const G4int iz = std::min(gMaxZet, G4lr << 212 292 const G4double eps = pEnergy/gammaEnergy; << 213 // dsig/dE+ = 4 * alpha * Z**2 * r0**2 / k 293 const G4double epsm = 1.-eps; << 214 // * [ (y**2 + (1-y**2) + 2/3*y*(1-y) ) * ( log (183 * Z**-1/3) + 1/9 * y*(1-y) ] 294 const G4double dum = eps*epsm; << 215 // y = E+/k 295 // evaluate LPM suppression functions << 216 G4double yp=eplusEnergy/totalEnergy; 296 G4double fXiS, fGS, fPhiS; << 217 G4double ym=1.-yp; 297 ComputeLPMfunctions(fXiS, fGS, fPhiS, eps, g << 218 298 if (fIsUseCompleteScreening) { << 219 CalcLPMFunctions(totalEnergy,eplusEnergy); // gamma 299 // complete screening: << 220 300 const G4double Lel = gElementData[iz]->f << 221 G4double cross = 0.; 301 const G4double fc = gElementData[iz]->f << 222 if (use_completescreening) 302 xSection = (Lel-fc)*((eps*eps+epsm*epsm)*2 << 223 cross = xiLPM*(2./3.*phiLPM*(yp*yp + ym*ym) + gLPM)*(Fel - fCoulomb); 303 } else { << 224 else { 304 // normal case: << 225 G4double delta = 0.25*DeltaMin(totalEnergy)/(yp*ym); 305 const G4double eps0 = CLHEP::electron_mas << 226 cross = (1./3.*gLPM + 2./3.*phiLPM)*(yp*yp + ym*ym) 306 const G4double fc = gElementData[iz]->f << 227 *(0.25*Phi1(delta) - lnZ/3. - fCoulomb) 307 const G4double lnZ13 = gElementData[iz]->f << 228 + 2./3.*gLPM*ym*yp*(0.25*Phi2(delta) - lnZ/3. - fCoulomb); 308 const G4double delta = gElementData[iz]->f << 229 cross *= xiLPM; 309 G4double phi1, phi2; << 310 ComputePhi12(delta, phi1, phi2); << 311 xSection = (eps*eps + epsm*epsm)*(2.*fPhi << 312 + 2.*dum*fGS*(0.25*phi2-lnZ13-f << 313 } 230 } 314 // non-const. part of the DCS differential i << 231 return cross/totalEnergy; 315 // ds/dEt=ds/deps deps/dEt with deps/dEt=1/E << 232 316 return std::max(fXiS*xSection, 0.0)/gammaEne << 317 } 233 } 318 234 319 G4double << 235 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 320 G4PairProductionRelModel::ComputeCrossSectionP << 236 321 G4double gammaEnergy, G4double Z, G4doub << 237 void >> 238 G4PairProductionRelModel::CalcLPMFunctions(G4double k, G4double eplusEnergy) 322 { 239 { 323 G4double crossSection = 0.0 ; << 240 // *** calculate lpm variable s & sprime *** 324 // check kinematical limit << 241 // Klein eqs. (78) & (79) 325 if ( gammaEnergy <= 2.0*electron_mass_c2 ) { << 242 G4double sprime = sqrt(0.125*k*lpmEnergy/(eplusEnergy*(k-eplusEnergy))); 326 // compute the atomic cross section either b << 243 327 // or by numerically integrationg the DCS (w << 244 G4double s1 = preS1*z23; 328 if ( gammaEnergy < fParametrizedXSectionThre << 245 G4double logS1 = 2./3.*lnZ-2.*facFel; 329 // using the parametrized cross sections ( << 246 G4double logTS1 = logTwo+logS1; 330 crossSection = ComputeParametrizedXSection << 247 331 } else { << 248 xiLPM = 2.; 332 // by numerical integration of the DCS: << 249 333 // Computes the cross section with or with << 250 if (sprime>1) 334 // settings (by default with if the gamma << 251 xiLPM = 1.; 335 // and using or not using complete sreenin << 252 else if (sprime>sqrt(2.)*s1) { 336 // Only the dependent part is computed in << 253 G4double h = G4Log(sprime)/logTS1; 337 // i.e. the result must be multiplied here << 254 xiLPM = 1+h-0.08*(1-h)*(1-sqr(1-h))/logTS1; 338 crossSection = ComputeXSectionPerAtom(gamm << 255 } 339 // apply the constant factors: << 256 340 // - eta(Z) is a correction to account int << 257 G4double s0 = sprime/sqrt(xiLPM); 341 // - gXSecFactor = 4 \alpha r_0^2 << 258 // G4cout<<"k="<<k<<" y="<<eplusEnergy/k<<G4endl; 342 const G4int iz = std::min(gMaxZet, G4l << 259 // G4cout<<"s0="<<s0<<G4endl; 343 const G4double eta = gElementData[iz]->fEt << 260 344 crossSection *= gXSecFactor*Z*(Z+eta) << 261 // *** calculate supression functions phi and G *** >> 262 // Klein eqs. (77) >> 263 G4double s2=s0*s0; >> 264 G4double s3=s0*s2; >> 265 G4double s4=s2*s2; >> 266 >> 267 if (s0<0.1) { >> 268 // high suppression limit >> 269 phiLPM = 6.*s0 - 18.84955592153876*s2 + 39.47841760435743*s3 >> 270 - 57.69873135166053*s4; >> 271 gLPM = 37.69911184307752*s2 - 236.8705056261446*s3 + 807.7822389*s4; >> 272 } >> 273 else if (s0<1.9516) { >> 274 // intermediate suppression >> 275 // using eq.77 approxim. valid s0<2. >> 276 phiLPM = 1.-G4Exp(-6.*s0*(1.+(3.-pi)*s0) >> 277 +s3/(0.623+0.795*s0+0.658*s2)); >> 278 if (s0<0.415827397755) { >> 279 // using eq.77 approxim. valid 0.07<s<2 >> 280 G4double psiLPM = 1-G4Exp(-4*s0-8*s2/(1+3.936*s0+4.97*s2-0.05*s3+7.50*s4)); >> 281 gLPM = 3*psiLPM-2*phiLPM; >> 282 } >> 283 else { >> 284 // using alternative parametrisiation >> 285 G4double pre = -0.16072300849123999 + s0*3.7550300067531581 + s2*-1.7981383069010097 >> 286 + s3*0.67282686077812381 + s4*-0.1207722909879257; >> 287 gLPM = tanh(pre); >> 288 } 345 } 289 } 346 // final protection << 290 else { 347 return std::max(crossSection, 0.); << 291 // low suppression limit valid s>2. >> 292 phiLPM = 1. - 0.0119048/s4; >> 293 gLPM = 1. - 0.0230655/s4; >> 294 } >> 295 >> 296 // *** make sure suppression is smaller than 1 *** >> 297 // *** caused by Migdal approximation in xi *** >> 298 if (xiLPM*phiLPM>1. || s0>0.57) xiLPM=1./phiLPM; 348 } 299 } 349 300 350 void G4PairProductionRelModel::SetupForMateria << 301 351 << 302 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 303 >> 304 G4double >> 305 G4PairProductionRelModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*, >> 306 G4double gammaEnergy, G4double Z, >> 307 G4double, G4double, G4double) 352 { 308 { 353 fLPMEnergy = mat->GetRadlen()*gLPMconstant; << 309 G4double crossSection = 0.0 ; >> 310 // if ( Z < 0.9 ) return crossSection; >> 311 if ( gammaEnergy <= 2.0*electron_mass_c2 ) return crossSection; >> 312 >> 313 SetCurrentElement(Z); >> 314 // choose calculator according to parameters and switches >> 315 // in the moment only one calculator: >> 316 crossSection=ComputeXSectionPerAtom(gammaEnergy,Z); >> 317 >> 318 G4double xi = Finel/(Fel - fCoulomb); // inelastic contribution >> 319 crossSection *= xsfactor*Z*(Z+xi); >> 320 >> 321 return crossSection; 354 } 322 } 355 323 356 void << 324 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 325 >> 326 void 357 G4PairProductionRelModel::SampleSecondaries(st 327 G4PairProductionRelModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect, 358 co << 328 const G4MaterialCutsCouple* couple, 359 co << 329 const G4DynamicParticle* aDynamicGamma, 360 G4 << 330 G4double, 361 G4 << 331 G4double) 362 // The secondaries e+e- energies are sampled u 332 // The secondaries e+e- energies are sampled using the Bethe - Heitler 363 // cross sections with Coulomb correction. 333 // cross sections with Coulomb correction. 364 // A modified version of the random number tec 334 // A modified version of the random number techniques of Butcher & Messel 365 // is used (Nuc Phys 20(1960),15). 335 // is used (Nuc Phys 20(1960),15). 366 // 336 // 367 // GEANT4 internal units. 337 // GEANT4 internal units. 368 // 338 // 369 // Note 1 : Effects due to the breakdown of th 339 // Note 1 : Effects due to the breakdown of the Born approximation at 370 // low energy are ignored. 340 // low energy are ignored. 371 // Note 2 : The differential cross section imp << 341 // Note 2 : The differential cross section implicitly takes account of 372 // pair creation in both nuclear and 342 // pair creation in both nuclear and atomic electron fields. 373 // However triplet prodution is not g 343 // However triplet prodution is not generated. 374 { 344 { 375 const G4Material* mat = couple->GetM << 345 const G4Material* aMaterial = couple->GetMaterial(); 376 const G4double gammaEnergy = aDynamicGamm << 346 377 const G4double eps0 = CLHEP::elect << 347 G4double GammaEnergy = aDynamicGamma->GetKineticEnergy(); 378 // << 348 G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection(); 379 // check kinematical limit: gamma energy(Eg) << 349 380 // (but the model should be used at higher e << 350 G4double epsil ; 381 if (eps0 > 0.5) { return; } << 351 G4double epsil0 = electron_mass_c2/GammaEnergy ; 382 // << 352 if(epsil0 > 1.0) { return; } 383 // select target atom of the material << 353 384 const G4Element* anElement = SelectTargetAto << 354 // do it fast if GammaEnergy < 2. MeV 385 aDyna << 355 SetupForMaterial(theGamma, aMaterial, GammaEnergy); 386 CLHEP::HepRandomEngine* rndmEngine = G4Rando << 356 387 // << 357 // select randomly one element constituing the material 388 // 'eps' is the total energy transferred to << 358 const G4Element* anElement = 389 // gamma energy units Eg. Since the correspo << 359 SelectRandomAtom(aMaterial, theGamma, GammaEnergy); 390 // the kinematical limits for eps0=mc^2/Eg < << 360 391 // 1. 'eps' is sampled uniformly on the [eps << 361 if (GammaEnergy < Egsmall) { 392 // 2. otherwise, on the [eps_min, 0.5] inter << 362 393 G4double eps; << 363 epsil = epsil0 + (0.5-epsil0)*G4UniformRand(); 394 // case 1. << 364 395 static const G4double Egsmall = 2.*CLHEP::Me << 396 if (gammaEnergy < Egsmall) { << 397 eps = eps0 + (0.5-eps0)*rndmEngine->flat() << 398 } else { 365 } else { 399 // case 2. << 366 // now comes the case with GammaEnergy >= 2. MeV 400 // get the Coulomb factor for the target e << 367 401 // F(Z) = 8*ln(Z)/3 if Eg <= 50 << 368 // Extract Coulomb factor for this Element 402 // F(Z) = 8*ln(Z)/3 + 8*fc(Z) if Eg > 50 << 369 G4double FZ = 8.*(anElement->GetIonisation()->GetlogZ3()); >> 370 if (GammaEnergy > 50.*MeV) { FZ += 8.*(anElement->GetfCoulomb()); } >> 371 >> 372 // limits of the screening variable >> 373 G4double screenfac = 136.*epsil0/(anElement->GetIonisation()->GetZ3()); >> 374 G4double screenmax = G4Exp ((42.24 - FZ)/8.368) - 0.952 ; >> 375 G4double screenmin = min(4.*screenfac,screenmax); >> 376 >> 377 // limits of the energy sampling >> 378 G4double epsil1 = 0.5 - 0.5*sqrt(1. - screenmin/screenmax) ; >> 379 G4double epsilmin = max(epsil0,epsil1) , epsilrange = 0.5 - epsilmin; >> 380 403 // 381 // 404 // The screening variable 'delta(eps)' = 1 << 382 // sample the energy rate of the created electron (or positron) 405 // Due to the Coulomb correction, the DCS << 406 // kinematicaly allowed eps > eps0 values. << 407 // range with negative DCS, the minimum ep << 408 // max[eps0, epsp] with epsp is the soluti << 409 // with SF being the screening function (S << 410 // The solution is epsp = 0.5 - 0.5*sqrt[ << 411 // with deltap = Exp[(42.038-F(Z))/8.29]-0 << 412 // - when eps=eps_max = 0.5 => << 413 // - epsp = 0.5 - 0.5*sqrt[ 1 - delta_min/ << 414 // - and eps_min = max[eps0, epsp] << 415 const G4int iZet = std::min(gMax << 416 const G4double deltaFactor = gElementData[ << 417 const G4double deltaMin = 4.*deltaFacto << 418 G4double deltaMax = gElementData[ << 419 G4double FZ = 8.*gElementDa << 420 if ( gammaEnergy > fCoulombCorrectionThres << 421 FZ += 8.*gElementData[iZet]->fCoulo << 422 deltaMax = gElementData[iZet]->fDeltaMax << 423 } << 424 // compute the limits of eps << 425 const G4double epsp = 0.5 - 0.5*std << 426 const G4double epsMin = std::max(eps0 << 427 const G4double epsRange = 0.5 - epsMin; << 428 // 383 // 429 // sample the energy rate (eps) of the cre << 384 //G4double epsil, screenvar, greject ; 430 G4double F10, F20; << 385 G4double screenvar, greject ; 431 ScreenFunction12(deltaMin, F10, F20); << 386 432 F10 -= FZ; << 387 G4double F10 = ScreenFunction1(screenmin) - FZ; 433 F20 -= FZ; << 388 G4double F20 = ScreenFunction2(screenmin) - FZ; 434 const G4double NormF1 = std::max(F10 * e << 389 G4double NormF1 = max(F10*epsilrange*epsilrange,0.); 435 const G4double NormF2 = std::max(1.5 * F << 390 G4double NormF2 = max(1.5*F20,0.); 436 const G4double NormCond = NormF1/(NormF1 + << 391 437 // check if LPM correction is active << 438 const G4bool isLPM = (fIsUseLPMCorrection << 439 fLPMEnergy = mat->GetRadlen()*gLPMconstant << 440 // we will need 3 uniform random number fo << 441 G4double rndmv[3]; << 442 G4double greject = 0.; << 443 do { 392 do { 444 rndmEngine->flatArray(3, rndmv); << 393 if ( NormF1/(NormF1+NormF2) > G4UniformRand() ) { 445 if (NormCond > rndmv[0]) { << 394 epsil = 0.5 - epsilrange*nist->GetZ13(G4UniformRand()); 446 eps = 0.5 - epsRange * fG4Calc->A13(rn << 395 screenvar = screenfac/(epsil*(1-epsil)); 447 const G4double delta = deltaFactor/(ep << 396 if (fLPMflag && GammaEnergy>100.*GeV) { 448 if (isLPM) { << 397 CalcLPMFunctions(GammaEnergy,GammaEnergy*epsil); 449 G4double lpmXiS, lpmGS, lpmPhiS, phi << 398 greject = xiLPM*((gLPM+2.*phiLPM)*Phi1(screenvar) - 450 ComputePhi12(delta, phi1, phi2); << 399 gLPM*Phi2(screenvar) - phiLPM*FZ)/F10; 451 ComputeLPMfunctions(lpmXiS, lpmGS, l << 400 } 452 greject = lpmXiS*((2.*lpmPhiS+lpmGS) << 401 else { 453 } else { << 402 greject = (ScreenFunction1(screenvar) - FZ)/F10; 454 greject = (ScreenFunction1(delta)-FZ << 403 } 455 } << 404 456 } else { << 405 } else { 457 eps = epsMin + epsRange*rndmv[1]; << 406 epsil = epsilmin + epsilrange*G4UniformRand(); 458 const G4double delta = deltaFactor/(ep << 407 screenvar = screenfac/(epsil*(1-epsil)); 459 if (isLPM) { << 408 if (fLPMflag && GammaEnergy>100.*GeV) { 460 G4double lpmXiS, lpmGS, lpmPhiS, phi << 409 CalcLPMFunctions(GammaEnergy,GammaEnergy*epsil); 461 ComputePhi12(delta, phi1, phi2); << 410 greject = xiLPM*((0.5*gLPM+phiLPM)*Phi1(screenvar) + 462 ComputeLPMfunctions(lpmXiS, lpmGS, l << 411 0.5*gLPM*Phi2(screenvar) - 0.5*(gLPM+phiLPM)*FZ)/F20; 463 greject = lpmXiS*( (lpmPhiS+0.5*lpmG << 412 } 464 -0.5*(lpmGS+lpmPh << 413 else { 465 } else { << 414 greject = (ScreenFunction2(screenvar) - FZ)/F20; 466 greject = (ScreenFunction2(delta)-FZ << 415 } 467 } << 468 } 416 } 469 // Loop checking, 03-Aug-2015, Vladimir << 417 470 } while (greject < rndmv[2]); << 418 } while( greject < G4UniformRand() ); 471 // end of eps sampling << 419 472 } << 420 } // end of epsil sampling >> 421 >> 422 // >> 423 // fixe charges randomly 473 // 424 // 474 // select charges randomly << 425 475 G4double eTotEnergy, pTotEnergy; << 426 G4double ElectTotEnergy, PositTotEnergy; 476 if (rndmEngine->flat() > 0.5) { << 427 if (G4UniformRand() > 0.5) { 477 eTotEnergy = (1.-eps)*gammaEnergy; << 428 478 pTotEnergy = eps*gammaEnergy; << 429 ElectTotEnergy = (1.-epsil)*GammaEnergy; >> 430 PositTotEnergy = epsil*GammaEnergy; >> 431 479 } else { 432 } else { 480 pTotEnergy = (1.-eps)*gammaEnergy; << 433 481 eTotEnergy = eps*gammaEnergy; << 434 PositTotEnergy = (1.-epsil)*GammaEnergy; >> 435 ElectTotEnergy = epsil*GammaEnergy; 482 } 436 } >> 437 >> 438 // >> 439 // scattered electron (positron) angles. ( Z - axis along the parent photon) 483 // 440 // 484 // sample pair kinematics << 441 // universal distribution suggested by L. Urban 485 // << 442 // (Geant3 manual (1993) Phys211), 486 const G4double eKinEnergy = std::max(0.,eTot << 443 // derived from Tsai distribution (Rev Mod Phys 49,421(1977)) 487 const G4double pKinEnergy = std::max(0.,pTot << 444 >> 445 G4double u; >> 446 static const G4double a1 = 0.625; >> 447 static const G4double a2 = 3.*a1; >> 448 static const G4double d = 27. ; >> 449 >> 450 if (9./(9.+d) >G4UniformRand()) u= - G4Log(G4UniformRand()*G4UniformRand())/a1; >> 451 else u= - G4Log(G4UniformRand()*G4UniformRand())/a2; >> 452 >> 453 G4double TetEl = u*electron_mass_c2/ElectTotEnergy; >> 454 G4double TetPo = u*electron_mass_c2/PositTotEnergy; >> 455 G4double Phi = twopi * G4UniformRand(); >> 456 G4double dxEl= sin(TetEl)*cos(Phi),dyEl= sin(TetEl)*sin(Phi),dzEl=cos(TetEl); >> 457 G4double dxPo=-sin(TetPo)*cos(Phi),dyPo=-sin(TetPo)*sin(Phi),dzPo=cos(TetPo); >> 458 488 // 459 // 489 G4ThreeVector eDirection, pDirection; << 460 // kinematic of the created pair 490 // 461 // 491 GetAngularDistribution()->SamplePairDirectio << 462 // the electron and positron are assumed to have a symetric 492 eKinEnergy, pKinEnergy, eDirectio << 463 // angular distribution with respect to the Z axis along the parent photon. 493 // create G4DynamicParticle object for the p << 464 494 auto aParticle1 = new G4DynamicParticle(fThe << 465 G4double ElectKineEnergy = max(0.,ElectTotEnergy - electron_mass_c2); >> 466 >> 467 G4ThreeVector ElectDirection (dxEl, dyEl, dzEl); >> 468 ElectDirection.rotateUz(GammaDirection); >> 469 >> 470 // create G4DynamicParticle object for the particle1 >> 471 G4DynamicParticle* aParticle1= new G4DynamicParticle( >> 472 theElectron,ElectDirection,ElectKineEnergy); >> 473 >> 474 // the e+ is always created (even with Ekine=0) for further annihilation. >> 475 >> 476 G4double PositKineEnergy = max(0.,PositTotEnergy - electron_mass_c2); >> 477 >> 478 G4ThreeVector PositDirection (dxPo, dyPo, dzPo); >> 479 PositDirection.rotateUz(GammaDirection); >> 480 >> 481 // create G4DynamicParticle object for the particle2 >> 482 G4DynamicParticle* aParticle2= new G4DynamicParticle( >> 483 thePositron,PositDirection,PositKineEnergy); 495 484 496 // create G4DynamicParticle object for the p << 497 auto aParticle2 = new G4DynamicParticle(fThe << 498 // Fill output vector 485 // Fill output vector 499 fvect->push_back(aParticle1); 486 fvect->push_back(aParticle1); 500 fvect->push_back(aParticle2); 487 fvect->push_back(aParticle2); >> 488 501 // kill incident photon 489 // kill incident photon 502 fParticleChange->SetProposedKineticEnergy(0. 490 fParticleChange->SetProposedKineticEnergy(0.); 503 fParticleChange->ProposeTrackStatus(fStopAnd << 491 fParticleChange->ProposeTrackStatus(fStopAndKill); 504 } << 505 << 506 // should be called only by the master and at << 507 void G4PairProductionRelModel::InitialiseEleme << 508 { << 509 // create for all elements that are in the d << 510 auto elemTable = G4Element::GetElementTable( << 511 for (auto const & elem : *elemTable) { << 512 const G4int iz = std::min(gMaxZet, elem->G << 513 if (nullptr == gElementData[iz]) { // crea << 514 const G4double logZ13 = elem->GetIonisat << 515 const G4double Z13 = elem->GetIonisat << 516 const G4double fc = elem->GetfCoulom << 517 const G4double FZLow = 8.*logZ13; << 518 const G4double FZHigh = 8.*(logZ13 + fc) << 519 G4double Fel; << 520 G4double Finel; << 521 if (iz<5) { // use data from Dirac-Fock << 522 Fel = gFelLowZet[iz]; << 523 Finel = gFinelLowZet[iz]; << 524 } else { // use the results of the T << 525 Fel = G4Log(184.) - logZ13; << 526 Finel = G4Log(1194.) - 2.*logZ13; << 527 } << 528 auto elD = new ElementData() << 529 elD->fLogZ13 = logZ13; << 530 elD->fCoulomb = fc; << 531 elD->fLradEl = Fel; << 532 elD->fDeltaFactor = 136./Z13; << 533 elD->fDeltaMaxLow = G4Exp((42.038 - F << 534 elD->fDeltaMaxHigh = G4Exp((42.038 - F << 535 elD->fEtaValue = Finel/(Fel-fc); << 536 elD->fLPMVarS1Cond = std::sqrt(2.)*Z13 << 537 elD->fLPMILVarS1Cond = 1./G4Log(elD->fLP << 538 gElementData[iz] = elD; << 539 } << 540 } << 541 } 492 } 542 493 543 // s goes up to 2 with ds = 0.01 be default << 494 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 544 void G4PairProductionRelModel::InitLPMFunction << 545 if (!gLPMFuncs.fIsInitialized) { << 546 const G4int num = gLPMFuncs.fSLimit*gLPMFu << 547 gLPMFuncs.fLPMFuncG.resize(num); << 548 gLPMFuncs.fLPMFuncPhi.resize(num); << 549 for (G4int i=0; i<num; ++i) { << 550 const G4double sval = i/gLPMFuncs.fISDel << 551 ComputeLPMGsPhis(gLPMFuncs.fLPMFuncG[i], << 552 } << 553 gLPMFuncs.fIsInitialized = true; << 554 } << 555 } << 556 495 557 // used only at initialisation time << 558 void G4PairProductionRelModel::ComputeLPMGsPhi << 559 if (varShat < 0.01) { << 560 funcPhiS = 6.0*varShat*(1.0-CLHEP::pi*varS << 561 funcGS = 12.0*varShat-2.0*funcPhiS; << 562 } else { << 563 const G4double varShat2 = varShat*varShat; << 564 const G4double varShat3 = varShat*varShat2 << 565 const G4double varShat4 = varShat2*varShat << 566 if (varShat < 0.415827397755) { // Stanev << 567 funcPhiS = 1.0-G4Exp( -6.0*varShat*(1.0+ << 568 + varShat3/(0.623+0 << 569 // 1-\exp \left\{-4s-\frac{8s^2}{1+3.936 << 570 const G4double funcPsiS = 1.0-G4Exp( -4. << 571 + 3.936*varShat+4.97*varS << 572 // G(s) = 3 \psi(s) - 2 \phi(s) << 573 funcGS = 3.0*funcPsiS - 2.0*funcPhiS; << 574 } else if (varShat < 1.55) { << 575 funcPhiS = 1.0-G4Exp( -6.0*varShat*(1.0+ << 576 + varShat3/(0.623+0 << 577 const G4double dum0 = -0.16072300849123 << 578 -1.79813830690100 << 579 +0.67282686077812 << 580 -0.12077229098792 << 581 funcGS = std::tanh(dum0); << 582 } else { << 583 funcPhiS = 1.0-0.01190476/varShat4; << 584 if (varShat < 1.9156) { << 585 const G4double dum0 = -0.1607230084912 << 586 -1.7981383069010 << 587 +0.6728268607781 << 588 -0.1207722909879 << 589 funcGS = std::tanh(dum0); << 590 } else { << 591 funcGS = 1.0-0.0230655/varShat4; << 592 } << 593 } << 594 } << 595 } << 596 496 597 // used at run-time to get some pre-computed L << 497 void G4PairProductionRelModel::SetupForMaterial(const G4ParticleDefinition*, 598 void G4PairProductionRelModel::GetLPMFunctions << 498 const G4Material* mat, G4double) 599 << 600 << 601 if (sval < gLPMFuncs.fSLimit) { << 602 G4double val = sval*gLPMFuncs.fISDelta << 603 const G4int ilow = (G4int)val; << 604 val -= ilow; << 605 lpmGs = (gLPMFuncs.fLPMFuncG[ilow+1]-gL << 606 + gLPMFuncs.fLPMFuncG[ilow]; << 607 lpmPhis = (gLPMFuncs.fLPMFuncPhi[ilow+1]- << 608 + gLPMFuncs.fLPMFuncPhi[ilow]; << 609 } else { << 610 G4double ss = sval*sval; << 611 ss *= ss; << 612 lpmPhis = 1.0-0.01190476/ss; << 613 lpmGs = 1.0-0.0230655/ss; << 614 } << 615 } << 616 << 617 void G4PairProductionRelModel::ComputeLPMfunct << 618 G4double &funcGS, G4double &f << 619 const G4double egamma, const << 620 { << 621 // 1. y = E_+/E_{\gamma} with E_+ being the << 622 // to one of the e-/e << 623 // s' = \sqrt{ \frac{1}{8} \frac{1}{y(1-y)} << 624 const G4double varSprime = std::sqrt(0.125*f << 625 const G4double condition = gElementData[izet << 626 funcXiS = 2.0; << 627 if (varSprime > 1.0) { << 628 funcXiS = 1.0; << 629 } else if (varSprime > condition) { << 630 const G4double dum = gElementData[izet]->f << 631 const G4double funcHSprime = G4Log(varSpri << 632 funcXiS = 1.0 + funcHSprime << 633 - 0.08*(1.0-funcHSprime)*funcHSpr << 634 } << 635 // 2. s=\frac{s'}{\sqrt{\xi(s')}} << 636 const G4double varShat = varSprime / std::sq << 637 GetLPMFunctions(funcGS, funcPhiS, varShat); << 638 // MAKE SURE SUPPRESSION IS SMALLER THAN 1: << 639 if (funcXiS * funcPhiS > 1. || varShat > 0.5 << 640 funcXiS = 1. / funcPhiS; << 641 } << 642 } << 643 << 644 // Calculates the microscopic cross section in << 645 // G4BetheHeitlerModel and should be used belo << 646 // from the cross section data above 80-90 GeV << 647 // Parametrized formula (L. Urban) is used to << 648 // given numerically in the table of [Hubbell, << 649 // Overbo: "Pair, Triplet, and Total Atomic Cr << 650 // Coefficients) for 1 MeV‐100 GeV Photons i << 651 // physical and chemical reference data 9.4 (1 << 652 // << 653 // The formula gives a good approximation of t << 654 // below 1.5 MeV: sigma=sigma(1.5MeV)*(GammaEn << 655 // *(GammaEn << 656 G4double << 657 G4PairProductionRelModel::ComputeParametrizedX << 658 << 659 { 499 { 660 G4double xSection = 0.0 ; << 500 lpmEnergy = mat->GetRadlen()*fLPMconstant; 661 // short versions << 501 // G4cout<<" lpmEnergy="<<lpmEnergy<<G4endl; 662 static const G4double kMC2 = CLHEP::electro << 663 // zero cross section below the kinematical << 664 if (Z < 0.9 || gammaE <= 2.0*kMC2) { return << 665 // << 666 static const G4double gammaEnergyLimit = 1.5 << 667 // set coefficients a, b c << 668 static const G4double a0 = 8.7842e+2*CLHEP: << 669 static const G4double a1 = -1.9625e+3*CLHEP: << 670 static const G4double a2 = 1.2949e+3*CLHEP: << 671 static const G4double a3 = -2.0028e+2*CLHEP: << 672 static const G4double a4 = 1.2575e+1*CLHEP: << 673 static const G4double a5 = -2.8333e-1*CLHEP: << 674 << 675 static const G4double b0 = -1.0342e+1*CLHEP: << 676 static const G4double b1 = 1.7692e+1*CLHEP: << 677 static const G4double b2 = -8.2381 *CLHEP: << 678 static const G4double b3 = 1.3063 *CLHEP: << 679 static const G4double b4 = -9.0815e-2*CLHEP: << 680 static const G4double b5 = 2.3586e-3*CLHEP: << 681 << 682 static const G4double c0 = -4.5263e+2*CLHEP: << 683 static const G4double c1 = 1.1161e+3*CLHEP: << 684 static const G4double c2 = -8.6749e+2*CLHEP: << 685 static const G4double c3 = 2.1773e+2*CLHEP: << 686 static const G4double c4 = -2.0467e+1*CLHEP: << 687 static const G4double c5 = 6.5372e-1*CLHEP: << 688 // check low energy limit of the approximati << 689 G4double gammaEnergyOrg = gammaE; << 690 if (gammaE < gammaEnergyLimit) { gammaE = ga << 691 // compute gamma energy variables << 692 const G4double x = G4Log(gammaE/kMC2); << 693 const G4double x2 = x *x; << 694 const G4double x3 = x2*x; << 695 const G4double x4 = x3*x; << 696 const G4double x5 = x4*x; << 697 // << 698 const G4double F1 = a0 + a1*x + a2*x2 + a3*x << 699 const G4double F2 = b0 + b1*x + b2*x2 + b3*x << 700 const G4double F3 = c0 + c1*x + c2*x2 + c3*x << 701 // compute the approximated cross section << 702 xSection = (Z + 1.)*(F1*Z + F2*Z*Z + F3); << 703 // check if we are below the limit of the ap << 704 if (gammaEnergyOrg < gammaEnergyLimit) { << 705 const G4double dum = (gammaEnergyOrg-2.*kM << 706 xSection *= dum*dum; << 707 } << 708 return xSection; << 709 } 502 } 710 503 711 << 504 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 712 505