Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // 27 // ------------------------------------------- 28 // 29 // GEANT4 Class file 30 // 31 // 32 // File name: G4PairProductionRelModel 33 // 34 // Author: Andreas Schaelicke 35 // 36 // Creation date: 02.04.2009 37 // 38 // 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 // 48 // Class Description: 49 // 50 // Main References: 51 // J.W.Motz et.al., Rev. Mod. Phys. 41 (1969) 52 // S.Klein, Rev. Mod. Phys. 71 (1999) 1501. 53 // T.Stanev et.al., Phys. Rev. D25 (1982) 129 54 // M.L.Ter-Mikaelian, High-energy Electromagn 55 // Wiley, 1972. 56 // 57 // ------------------------------------------- 58 59 #include "G4PairProductionRelModel.hh" 60 #include "G4PhysicalConstants.hh" 61 #include "G4SystemOfUnits.hh" 62 #include "G4Gamma.hh" 63 #include "G4Electron.hh" 64 #include "G4Positron.hh" 65 #include "G4ParticleChangeForGamma.hh" 66 #include "G4LossTableManager.hh" 67 #include "G4ModifiedTsai.hh" 68 #include "G4Exp.hh" 69 #include "G4Pow.hh" 70 #include "G4AutoLock.hh" 71 72 const G4int G4PairProductionRelModel::gMaxZet 73 74 // LPM constant: \alpha(mc^2)^2/(4\pi*\hbar c) 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 108 // special data structure per element i.e. per 109 std::vector<G4PairProductionRelModel::ElementD 110 111 // LPM supression functions evaluated at initi 112 G4PairProductionRelModel::LPMFuncs G4PairProdu 113 114 namespace 115 { 116 G4Mutex thePairProdRelMutex = G4MUTEX_INITIA 117 } 118 119 // CTR 120 G4PairProductionRelModel::G4PairProductionRelM 121 122 : G4VEmModel(nam), fIsUseLPMCorrection(true) 123 fLPMEnergy(0.), fG4Calc(G4Pow::GetInstance() 124 fTheElectron(G4Electron::Electron()), fThePo 125 fParticleChange(nullptr) 126 { 127 // gamma energy below which the parametrized 128 fParametrizedXSectionThreshold = 30.0*CLHEP: 129 // gamma energy below the Coulomb correction 130 fCoulombCorrectionThreshold = 50.0*CLHEP: 131 // set angular generator used in the final s 132 SetAngularDistribution(new G4ModifiedTsai()) 133 } 134 135 // DTR 136 G4PairProductionRelModel::~G4PairProductionRel 137 { 138 if (isFirstInstance) { 139 // clear ElementData container 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 151 void G4PairProductionRelModel::Initialise(cons 152 cons 153 { 154 if(nullptr == fParticleChange) { fParticleCh 155 156 if (isFirstInstance || gElementData.empty()) 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 } 174 } 175 176 void G4PairProductionRelModel::InitialiseLocal 177 178 { 179 SetElementSelectors(masterModel->GetElementS 180 } 181 182 G4double G4PairProductionRelModel::ComputeXSec 183 184 { 185 G4double xSection = 0.0; 186 // check if LPM suppression needs to be used 187 const G4bool isLPM = (fIsUseLPMCorrection 188 // determine the kinematical limits (taken i 189 // the way in which the Coulomb correction i 190 const G4int iz = std::min(gMaxZet, G4 191 const G4double eps0 = CLHEP::electron_mass 192 // Coulomb correction is always included in 193 // that this DCS is only used to get the int 194 const G4double dmax = gElementData[iz]->fD 195 const G4double dmin = 4.*eps0*gElementData 196 const G4double eps1 = 0.5 - 0.5*std::sqrt( 197 const G4double epsMin = std::max(eps0, eps1) 198 const G4double epsMax = 0.5; // DCS is symme 199 // let Et be the total energy transferred to 200 // the [Et-min, Et-max] interval will be div 201 // with width of dInterv = (Et-max - Et-min) 202 // be done in each sub-inteval using the xi 203 // that is in [0,1]. The 8-point GL q. is us 204 const G4int numSub = 2; 205 const G4double dInterv= (epsMax - epsMin)*ga 206 G4double minEti = epsMin*gammaEnergy; 207 for (G4int i = 0; i < numSub; ++i) { 208 for (G4int ngl = 0; ngl < 8; ++ngl) { 209 const G4double Et = (minEti + gXGL[ngl]* 210 const G4double xs = isLPM ? ComputeRelDX 211 : ComputeDXSec 212 xSection += gWGL[ngl]*xs; 213 } 214 // update minimum Et of the sub-inteval 215 minEti += dInterv; 216 } 217 // apply corrections of variable transformat 218 xSection = std::max(2.*xSection*dInterv, 0.) 219 return xSection; 220 } 221 222 // DCS WITHOUT LPM SUPPRESSION 223 // Computes DCS value for a given target eleme 224 // total energy transferred to one of the e-/e 225 // The constant factor 4 \alpha r_0^2 Z (Z +\e 226 // the returned value will be differential in 227 // the eps=Et/Eg. The computed part of the DCS 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 { 241 G4double xSection = 0.; 242 const G4int iz = std::min(gMaxZet, G4lr 243 const G4double eps = pEnergy/gammaEnergy; 244 const G4double epsm = 1.-eps; 245 const G4double dum = eps*epsm; 246 if (fIsUseCompleteScreening) { 247 // complete screening: 248 const G4double Lel = gElementData[iz]->f 249 const G4double fc = gElementData[iz]->f 250 xSection = (eps*eps + epsm*epsm + 2.*dum/3 251 } else { 252 // normal case: 253 const G4double eps0 = CLHEP::electron_mas 254 const G4double fc = gElementData[iz]->f 255 const G4double lnZ13 = gElementData[iz]->f 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 } 262 // non-const. part of the DCS differential i 263 // ds/dEt=ds/deps deps/dEt with deps/dEt=1/E 264 return std::max(xSection, 0.0)/gammaEnergy; 265 } 266 267 // DCS WITH POSSIBLE LPM SUPPRESSION 268 // Computes DCS value for a given target eleme 269 // total energy transferred to one of the e-/e 270 // For a given Z, the LPM suppression will dep 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 { 290 G4double xSection = 0.; 291 const G4int iz = std::min(gMaxZet, G4lr 292 const G4double eps = pEnergy/gammaEnergy; 293 const G4double epsm = 1.-eps; 294 const G4double dum = eps*epsm; 295 // evaluate LPM suppression functions 296 G4double fXiS, fGS, fPhiS; 297 ComputeLPMfunctions(fXiS, fGS, fPhiS, eps, g 298 if (fIsUseCompleteScreening) { 299 // complete screening: 300 const G4double Lel = gElementData[iz]->f 301 const G4double fc = gElementData[iz]->f 302 xSection = (Lel-fc)*((eps*eps+epsm*epsm)*2 303 } else { 304 // normal case: 305 const G4double eps0 = CLHEP::electron_mas 306 const G4double fc = gElementData[iz]->f 307 const G4double lnZ13 = gElementData[iz]->f 308 const G4double delta = gElementData[iz]->f 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 } 314 // non-const. part of the DCS differential i 315 // ds/dEt=ds/deps deps/dEt with deps/dEt=1/E 316 return std::max(fXiS*xSection, 0.0)/gammaEne 317 } 318 319 G4double 320 G4PairProductionRelModel::ComputeCrossSectionP 321 G4double gammaEnergy, G4double Z, G4doub 322 { 323 G4double crossSection = 0.0 ; 324 // check kinematical limit 325 if ( gammaEnergy <= 2.0*electron_mass_c2 ) { 326 // compute the atomic cross section either b 327 // or by numerically integrationg the DCS (w 328 if ( gammaEnergy < fParametrizedXSectionThre 329 // using the parametrized cross sections ( 330 crossSection = ComputeParametrizedXSection 331 } else { 332 // by numerical integration of the DCS: 333 // Computes the cross section with or with 334 // settings (by default with if the gamma 335 // and using or not using complete sreenin 336 // Only the dependent part is computed in 337 // i.e. the result must be multiplied here 338 crossSection = ComputeXSectionPerAtom(gamm 339 // apply the constant factors: 340 // - eta(Z) is a correction to account int 341 // - gXSecFactor = 4 \alpha r_0^2 342 const G4int iz = std::min(gMaxZet, G4l 343 const G4double eta = gElementData[iz]->fEt 344 crossSection *= gXSecFactor*Z*(Z+eta) 345 } 346 // final protection 347 return std::max(crossSection, 0.); 348 } 349 350 void G4PairProductionRelModel::SetupForMateria 351 352 { 353 fLPMEnergy = mat->GetRadlen()*gLPMconstant; 354 } 355 356 void 357 G4PairProductionRelModel::SampleSecondaries(st 358 co 359 co 360 G4 361 G4 362 // The secondaries e+e- energies are sampled u 363 // cross sections with Coulomb correction. 364 // A modified version of the random number tec 365 // is used (Nuc Phys 20(1960),15). 366 // 367 // GEANT4 internal units. 368 // 369 // Note 1 : Effects due to the breakdown of th 370 // low energy are ignored. 371 // Note 2 : The differential cross section imp 372 // pair creation in both nuclear and 373 // However triplet prodution is not g 374 { 375 const G4Material* mat = couple->GetM 376 const G4double gammaEnergy = aDynamicGamm 377 const G4double eps0 = CLHEP::elect 378 // 379 // check kinematical limit: gamma energy(Eg) 380 // (but the model should be used at higher e 381 if (eps0 > 0.5) { return; } 382 // 383 // select target atom of the material 384 const G4Element* anElement = SelectTargetAto 385 aDyna 386 CLHEP::HepRandomEngine* rndmEngine = G4Rando 387 // 388 // 'eps' is the total energy transferred to 389 // gamma energy units Eg. Since the correspo 390 // the kinematical limits for eps0=mc^2/Eg < 391 // 1. 'eps' is sampled uniformly on the [eps 392 // 2. otherwise, on the [eps_min, 0.5] inter 393 G4double eps; 394 // case 1. 395 static const G4double Egsmall = 2.*CLHEP::Me 396 if (gammaEnergy < Egsmall) { 397 eps = eps0 + (0.5-eps0)*rndmEngine->flat() 398 } else { 399 // case 2. 400 // get the Coulomb factor for the target e 401 // F(Z) = 8*ln(Z)/3 if Eg <= 50 402 // F(Z) = 8*ln(Z)/3 + 8*fc(Z) if Eg > 50 403 // 404 // The screening variable 'delta(eps)' = 1 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 // 429 // sample the energy rate (eps) of the cre 430 G4double F10, F20; 431 ScreenFunction12(deltaMin, F10, F20); 432 F10 -= FZ; 433 F20 -= FZ; 434 const G4double NormF1 = std::max(F10 * e 435 const G4double NormF2 = std::max(1.5 * F 436 const G4double NormCond = NormF1/(NormF1 + 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 { 444 rndmEngine->flatArray(3, rndmv); 445 if (NormCond > rndmv[0]) { 446 eps = 0.5 - epsRange * fG4Calc->A13(rn 447 const G4double delta = deltaFactor/(ep 448 if (isLPM) { 449 G4double lpmXiS, lpmGS, lpmPhiS, phi 450 ComputePhi12(delta, phi1, phi2); 451 ComputeLPMfunctions(lpmXiS, lpmGS, l 452 greject = lpmXiS*((2.*lpmPhiS+lpmGS) 453 } else { 454 greject = (ScreenFunction1(delta)-FZ 455 } 456 } else { 457 eps = epsMin + epsRange*rndmv[1]; 458 const G4double delta = deltaFactor/(ep 459 if (isLPM) { 460 G4double lpmXiS, lpmGS, lpmPhiS, phi 461 ComputePhi12(delta, phi1, phi2); 462 ComputeLPMfunctions(lpmXiS, lpmGS, l 463 greject = lpmXiS*( (lpmPhiS+0.5*lpmG 464 -0.5*(lpmGS+lpmPh 465 } else { 466 greject = (ScreenFunction2(delta)-FZ 467 } 468 } 469 // Loop checking, 03-Aug-2015, Vladimir 470 } while (greject < rndmv[2]); 471 // end of eps sampling 472 } 473 // 474 // select charges randomly 475 G4double eTotEnergy, pTotEnergy; 476 if (rndmEngine->flat() > 0.5) { 477 eTotEnergy = (1.-eps)*gammaEnergy; 478 pTotEnergy = eps*gammaEnergy; 479 } else { 480 pTotEnergy = (1.-eps)*gammaEnergy; 481 eTotEnergy = eps*gammaEnergy; 482 } 483 // 484 // sample pair kinematics 485 // 486 const G4double eKinEnergy = std::max(0.,eTot 487 const G4double pKinEnergy = std::max(0.,pTot 488 // 489 G4ThreeVector eDirection, pDirection; 490 // 491 GetAngularDistribution()->SamplePairDirectio 492 eKinEnergy, pKinEnergy, eDirectio 493 // create G4DynamicParticle object for the p 494 auto aParticle1 = new G4DynamicParticle(fThe 495 496 // create G4DynamicParticle object for the p 497 auto aParticle2 = new G4DynamicParticle(fThe 498 // Fill output vector 499 fvect->push_back(aParticle1); 500 fvect->push_back(aParticle2); 501 // kill incident photon 502 fParticleChange->SetProposedKineticEnergy(0. 503 fParticleChange->ProposeTrackStatus(fStopAnd 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 } 542 543 // s goes up to 2 with ds = 0.01 be default 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 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 597 // used at run-time to get some pre-computed L 598 void G4PairProductionRelModel::GetLPMFunctions 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 { 660 G4double xSection = 0.0 ; 661 // short versions 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 } 710 711 712