Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4PairProductionRelModel.cc
이 파일의 문서화 페이지로 가기
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // $Id: G4PairProductionRelModel.cc 110939 2018-06-27 12:02:21Z gunter $
27 //
28 // -------------------------------------------------------------------
29 //
30 // GEANT4 Class file
31 //
32 //
33 // File name: G4PairProductionRelModel
34 //
35 // Author: Andreas Schaelicke
36 //
37 // Creation date: 02.04.2009
38 //
39 // Modifications:
40 // 20.03.17 Change LPMconstant such that it gives suppression variable 's'
41 // that consistent to Migdal's one; fix a small bug in 'logTS1'
42 // computation; suppression is consistent now with the one in the
43 // brem. model (F.Hariri)
44 // 28-05-18 New version with improved screening function approximation, improved
45 // LPM function approximation, efficiency, documentation and cleanup.
46 // Corrected call to selecting target atom in the final state sampling.
47 // (M. Novak)
48 //
49 // Class Description:
50 //
51 // Main References:
52 // J.W.Motz et.al., Rev. Mod. Phys. 41 (1969) 581.
53 // S.Klein, Rev. Mod. Phys. 71 (1999) 1501.
54 // T.Stanev et.al., Phys. Rev. D25 (1982) 1291.
55 // M.L.Ter-Mikaelian, High-energy Electromagnetic Processes in Condensed Media,
56 // Wiley, 1972.
57 //
58 // -------------------------------------------------------------------
59 
61 #include "G4PhysicalConstants.hh"
62 #include "G4SystemOfUnits.hh"
63 #include "G4Gamma.hh"
64 #include "G4Electron.hh"
65 #include "G4Positron.hh"
67 #include "G4LossTableManager.hh"
68 #include "G4ModifiedTsai.hh"
69 
70 
72 
73 // LPM constant: \alpha(mc^2)^2/(4\pi*\hbar c)
76  /(4.*CLHEP::pi*CLHEP::hbarc);
77 
78 // abscissas and weights of an 8 point Gauss-Legendre quadrature
79 // for numerical integration on [0,1]
81  1.98550718e-02, 1.01666761e-01, 2.37233795e-01, 4.08282679e-01,
82  5.91717321e-01, 7.62766205e-01, 8.98333239e-01, 9.80144928e-01
83 };
85  5.06142681e-02, 1.11190517e-01, 1.56853323e-01, 1.81341892e-01,
86  1.81341892e-01, 1.56853323e-01, 1.11190517e-01, 5.06142681e-02
87 };
88 
89 // elastic and inelatic radiation logarithms for light elements (where the
90 // Thomas-Fermi model doesn't work): computed by using Dirac-Fock model of atom.
92  0.0, 5.3104, 4.7935, 4.7402, 4.7112, 4.6694, 4.6134, 4.5520
93 };
95  0.0, 5.9173, 5.6125, 5.5377, 5.4728, 5.4174, 5.3688, 5.3236
96 };
97 
98 // constant cross section factor
102 
103 // gamma energy limit above which LPM suppression will be applied (if the
104 // fIsUseLPMCorrection flag is true)
106 
107 // special data structure per element i.e. per Z
108 std::vector<G4PairProductionRelModel::ElementData*> G4PairProductionRelModel::gElementData;
109 
110 // LPM supression functions evaluated at initialisation time
112 
113 
114 
115 // CTR
117  const G4String& nam)
118  : G4VEmModel(nam), fIsUseLPMCorrection(true), fIsUseCompleteScreening(false),
119  fLPMEnergy(0.), fG4Calc(G4Pow::GetInstance()), fTheGamma(G4Gamma::Gamma()),
120  fTheElectron(G4Electron::Electron()), fThePositron(G4Positron::Positron()),
121  fParticleChange(nullptr)
122 {
124 }
125 
126 
127 // DTR
129 {
130  if (IsMaster()) {
131  // clear ElementData container
132  for (size_t iz = 0; iz < gElementData.size(); ++iz) {
133  if (gElementData[iz]) delete gElementData[iz];
134  }
135  gElementData.clear();
136  // clear LPMFunctions (if any)
137  if (fIsUseLPMCorrection) {
138  gLPMFuncs.fLPMFuncG.clear();
139  gLPMFuncs.fLPMFuncPhi.clear();
140  }
141  }
142 }
143 
144 
145 
147  const G4DataVector& cuts)
148 {
149  if (IsMaster()) {
150  // init element data and LPM funcs
151  if (IsMaster()) {
153  if (fIsUseLPMCorrection) {
155  }
156  }
157  }
159  if(IsMaster() && LowEnergyLimit() < HighEnergyLimit()) {
161  }
162 }
163 
164 
165 
167  G4VEmModel* masterModel)
168 {
169  if(LowEnergyLimit() < HighEnergyLimit()) {
171  }
172 }
173 
174 
175 
177  G4double Z)
178 {
179  G4double xSection = 0.0;
180  // check if LPM suppression needs to be used
181  const G4bool isLPM = (fIsUseLPMCorrection && gammaEnergy>gEgLPMActivation);
182  // determine the kinematical limits (taken into account the correction due to
183  // the way in which the Coulomb correction is applied i.e. avoid negative DCS)
184  const G4int iz = std::min(gMaxZet, G4lrint(Z));
185  const G4double eps0 = CLHEP::electron_mass_c2/gammaEnergy;
186  const G4double dmax = gElementData[iz]->fDeltaMax;
187  const G4double dmin = 4.*eps0*gElementData[iz]->fDeltaFactor;
188  const G4double eps1 = 0.5 - 0.5*std::sqrt(1.-dmin/dmax);
189  const G4double epsMin = std::max(eps0, eps1);
190  const G4double epsMax = 0.5; // DCS is symmetric around eps=0.5
191  // let Et be the total energy transferred to the e- or to the e+
192  // the [Et-min, Et-max] interval will be divided into i=1,2,..,n subintervals
193  // with width of dInterv = (Et-max - Et-min)/n and numerical integration will
194  // be done in each sub-inteval using the xi = (Et - Et_i-min)/dInterv variable
195  // that is in [0,1]. The 8-point GL q. is used for the integration on [0,1].
196  const G4int numSub = 2;
197  const G4double dInterv= (epsMax - epsMin)*gammaEnergy/G4double(numSub);
198  G4double minEti = epsMin*gammaEnergy; // Et-min i.e. Et_0-min
199  for (G4int i = 0; i < numSub; ++i) {
200  for (G4int ngl = 0; ngl < 8; ++ngl) {
201  const G4double Et = (minEti + gXGL[ngl]*dInterv);
202  const G4double xs = isLPM ? ComputeRelDXSectionPerAtom(Et, gammaEnergy, Z)
203  : ComputeDXSectionPerAtom(Et, gammaEnergy, Z);
204  xSection += gWGL[ngl]*xs;
205  }
206  // update minimum Et of the sub-inteval
207  minEti += dInterv;
208  }
209  // apply corrections of variable transformation and half interval integration
210  xSection = std::max(2.*xSection*dInterv, 0.);
211  return xSection;
212 }
213 
214 
215 // DCS WITHOUT LPM SUPPRESSION
216 // Computes DCS value for a given target element (Z), initial gamma energy (Eg),
217 // total energy transferred to one of the e-/e+ pair(Et) WITHOUT LPM suppression
218 // The constant factor 4 \alpha r_0^2 Z (Z +\eta(Z)) is not included here and
219 // the returned value will be differential in total energy transfer instead of
220 // the eps=Et/Eg. The computed part of the DCS
221 // NORMAL CASE: DEFAULT STTING (i.e. fIsUseCompleteScreening = FALSE)
222 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = (eps^2+(1-eps)^2)*[phi1(d)/4-ln(Z)/3-fc]
223 // + 2*eps(1-eps)*[phi2(d)/4-ln(Z)/3-fc]/3 where the universal (in the TF model)
224 // screening variable d=d(eps)=136Z^(-1/3)eps0/[eps*(1-eps)] with eps0=mc^2/Eg.
225 // COMPLETE SCREENING (when d(eps) approx-equal-to 0) : NEED TO BE SET BY USER
226 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = (eps^2+(1-eps)^2+eps*(1-eps)/3)*[Lel-fc]
227 // -eps(1-eps)/9 where Lel=phi1(0)/4-ln(Z)/3 is the elastic(coherent) radiation
228 // logarithm, fc is the Coulomb correction and the relation phi2(0)/4-ln(Z)/3 =
229 // phi1(0)/4-1/6-ln(Z)/3 = Lel-1/6 (due to phi2(0)=phi1(0)-2/3) was used.
231  G4double gammaEnergy,
232  G4double Z)
233 {
234  G4double xSection = 0.;
235  const G4int iz = std::min(gMaxZet, G4lrint(Z));
236  const G4double eps = pEnergy/gammaEnergy;
237  const G4double epsm = 1.-eps;
238  const G4double dum = eps*epsm;
240  // complete screening:
241  const G4double Lel = gElementData[iz]->fLradEl;
242  const G4double fc = gElementData[iz]->fCoulomb;
243  xSection = (eps*eps + epsm*epsm + 2.*dum/3.)*(Lel-fc) - dum/9.;
244  } else {
245  // normal case:
246  const G4double eps0 = CLHEP::electron_mass_c2/gammaEnergy;
247  const G4double fc = gElementData[iz]->fCoulomb;
248  const G4double lnZ13 = gElementData[iz]->fLogZ13;
249  const G4double delta = gElementData[iz]->fDeltaFactor*eps0/dum;
250  G4double phi1, phi2;
251  ComputePhi12(delta, phi1, phi2);
252  xSection = (eps*eps + epsm*epsm)*(0.25*phi1-lnZ13-fc)
253  + 2.*dum*(0.25*phi2-lnZ13-fc)/3.;
254  }
255  // non-const. part of the DCS differential in total energy transfer not in eps
256  // ds/dEt=ds/deps deps/dEt with deps/dEt=1/Eg
257  return std::max(xSection, 0.0)/gammaEnergy;
258 }
259 
260 
261 // DCS WITH POSSIBLE LPM SUPPRESSION
262 // Computes DCS value for a given target element (Z), initial gamma energy (Eg),
263 // total energy transferred to one of the e-/e+ pair(Et) WITH LPM suppression.
264 // For a given Z, the LPM suppression will depend on the material through the
265 // LMP-Energy. This will determine the suppression variable s and the LPM sup-
266 // pression functions xi(s), fi(s) and G(s).
267 // The constant factor 4 \alpha r_0^2 Z (Z +\eta(Z)) is not included here and
268 // the returned value will be differential in total energy transfer instead of
269 // the eps=Et/Eg. The computed part of the DCS
270 // NORMAL CASE: DEFAULT STTING (i.e. fIsUseCompleteScreening = FALSE)
271 // ds/deps(Et,Eg,Z)=ds/deps(eps,Z) = xi(s)*{ (eps^2+(1-eps)^2)*[2fi(s)/3+G(s)/3]
272 // *[phi1(d)/4-ln(Z)/3-fc] + 2*eps(1-eps)*G(s)*[phi2(d)/4-ln(Z)/3-fc]/3 } where
273 // the universal (in the TF model) screening variable d=d(eps)=136Z^(-1/3)eps0
274 // /[eps*(1-eps)] with eps0=mc^2/Eg.
275 // COMPLETE SCREENING (when d(eps) approx-equal-to 0) : NEED TO BE SET BY USER
276 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = xi(s)*{ [Lel-fc]*[ (eps^2+(1-eps)^2+eps
277 // *(1-eps)/3)*2fi(s)/3 + G(s)/3] - eps(1-eps)*G(s)/9 }
278 // Note, that when the LPM suppression is absent i.e. xi(s)=fi(s)=G(s)=1, both
279 // the normal and the complete screening DCS give back the NO-LMP case above.
281  G4double gammaEnergy,
282  G4double Z)
283 {
284  G4double xSection = 0.;
285  const G4int iz = std::min(gMaxZet, G4lrint(Z));
286  const G4double eps = pEnergy/gammaEnergy;
287  const G4double epsm = 1.-eps;
288  const G4double dum = eps*epsm;
289  // evaluate LPM suppression functions
290  G4double fXiS, fGS, fPhiS;
291  ComputeLPMfunctions(fXiS, fGS, fPhiS, eps, gammaEnergy, iz);
293  // complete screening:
294  const G4double Lel = gElementData[iz]->fLradEl;
295  const G4double fc = gElementData[iz]->fCoulomb;
296  xSection = (Lel-fc)*((eps*eps+epsm*epsm)*2.*fPhiS + fGS)/3. - dum*fGS/9.;
297  } else {
298  // normal case:
299  const G4double eps0 = CLHEP::electron_mass_c2/gammaEnergy;
300  const G4double fc = gElementData[iz]->fCoulomb;
301  const G4double lnZ13 = gElementData[iz]->fLogZ13;
302  const G4double delta = gElementData[iz]->fDeltaFactor*eps0/dum;
303  G4double phi1, phi2;
304  ComputePhi12(delta, phi1, phi2);
305  xSection = (eps*eps + epsm*epsm)*(2.*fPhiS+fGS)*(0.25*phi1-lnZ13-fc)/3.
306  + 2.*dum*fGS*(0.25*phi2-lnZ13-fc)/3.;
307  }
308  // non-const. part of the DCS differential in total energy transfer not in eps
309  // ds/dEt=ds/deps deps/dEt with deps/dEt=1/Eg
310  return std::max(fXiS*xSection, 0.0)/gammaEnergy;
311 }
312 
313 
314 
315 G4double
317  G4double gammaEnergy, G4double Z, G4double, G4double, G4double)
318 {
319  G4double crossSection = 0.0 ;
320  // check kinematical limit
321  if ( gammaEnergy <= 2.0*electron_mass_c2 ) { return crossSection; }
322  // Computes the cross section with or without LPM suppression depending on
323  // settings (by default with if the gamma energy is above a given threshold)
324  // and using or not using complete sreening approximation (by default not).
325  // Only the dependent part is computed in the numerical integration of the DCS
326  // i.e. the result must be multiplied here with 4 \alpha r_0^2 Z(Z+\eta(Z))
327  crossSection = ComputeXSectionPerAtom(gammaEnergy, Z);
328  // apply the constant factors:
329  // - eta(Z) is a correction to account interaction in the field of e-
330  // - gXSecFactor = 4 \alpha r_0^2
331  const G4int iz = std::min(gMaxZet, G4lrint(Z));
332  const G4double eta = gElementData[iz]->fEtaValue;
333  crossSection *= gXSecFactor*Z*(Z+eta);
334  // final protection
335  return std::max(crossSection, 0.);
336 }
337 
338 
340  const G4Material* mat, G4double)
341 {
343 }
344 
345 
346 
347 void
348 G4PairProductionRelModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
349  const G4MaterialCutsCouple* couple,
350  const G4DynamicParticle* aDynamicGamma,
351  G4double,
352  G4double)
353 // The secondaries e+e- energies are sampled using the Bethe - Heitler
354 // cross sections with Coulomb correction.
355 // A modified version of the random number techniques of Butcher & Messel
356 // is used (Nuc Phys 20(1960),15).
357 //
358 // GEANT4 internal units.
359 //
360 // Note 1 : Effects due to the breakdown of the Born approximation at
361 // low energy are ignored.
362 // Note 2 : The differential cross section implicitly takes account of
363 // pair creation in both nuclear and atomic electron fields.
364 // However triplet prodution is not generated.
365 {
366  const G4Material* mat = couple->GetMaterial();
367  const G4double gammaEnergy = aDynamicGamma->GetKineticEnergy();
368  const G4double eps0 = CLHEP::electron_mass_c2/gammaEnergy ;
369  //
370  // check kinematical limit: gamma energy(Eg) must be at least 2 e- rest mass
371  // (but the model should be used at higher energies above 100 MeV)
372  if (eps0 > 0.5) { return; }
373  //
374  // select target atom of the material
375  const G4Element* anElement = SelectRandomAtom(couple, fTheGamma, gammaEnergy);
376  CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
377  //
378  // 'eps' is the total energy transferred to one of the e-/e+ pair in initial
379  // gamma energy units Eg. Since the corresponding DCS is symmetric on eps=0.5,
380  // the kinematical limits for eps0=mc^2/Eg <= eps <= 0.5
381  //
382  // The Coulomb factor for the target element (Z) (Eg>50 MeV is assumed)
383  // F(Z) = 8*ln(Z)/3 + 8*fc(Z)
384  //
385  // The screening variable 'delta(eps)' = 136*Z^{-1/3}*eps0/[eps(1-eps)]
386  // Due to the Coulomb correction, the DCS can go below zero even at
387  // kinematicaly allowed eps > eps0 values. In order to exclude this eps
388  // range with negative DCS, the minimum eps value will be set to eps_min =
389  // max[eps0, epsp] with epsp is the solution of SF(delta(epsp)) - F(Z)/2 = 0
390  // with SF being the screening function (SF1=SF2 at high value of delta).
391  // The solution is epsp = 0.5 - 0.5*sqrt[ 1 - 4*136*Z^{-1/3}eps0/deltap]
392  // with deltap = Exp[(42.038-F(Z))/8.29]-0.958. So the limits are:
393  // - when eps=eps_max = 0.5 => delta_min = 136*Z^{-1/3}*eps0/4
394  // - epsp = 0.5 - 0.5*sqrt[ 1 - delta_min/deltap]
395  // - and eps_min = max[eps0, epsp]
396  const G4int iZet = std::min(gMaxZet, anElement->GetZasInt());
397  const G4double deltaFactor = gElementData[iZet]->fDeltaFactor*eps0;
398  const G4double deltaMin = 4.*deltaFactor;
399  const G4double deltaMax = gElementData[iZet]->fDeltaMax;
400  // compute the limits of eps
401  const G4double epsp = 0.5 - 0.5*std::sqrt(1. - deltaMin/deltaMax) ;
402  const G4double epsMin = std::max(eps0,epsp);
403  const G4double epsRange = 0.5 - epsMin;
404  const G4double FZ = 8.*(gElementData[iZet]->fLogZ13 +
405  gElementData[iZet]->fCoulomb);
406  //
407  // sample the energy rate (eps) of the created electron (or positron)
408  G4double F10, F20;
409  ScreenFunction12(deltaMin, F10, F20);
410  F10 -= FZ;
411  F20 -= FZ;
412  const G4double NormF1 = std::max(F10 * epsRange * epsRange, 0.);
413  const G4double NormF2 = std::max(1.5 * F20 , 0.);
414  const G4double NormCond = NormF1/(NormF1 + NormF2);
415  // check if LPM correction is active
416  const G4bool isLPM = (fIsUseLPMCorrection && gammaEnergy>gEgLPMActivation);
418  // we will need 3 uniform random number for each trial of sampling
419  G4double rndmv[3];
420  G4double greject = 0.;
421  G4double eps;
422  do {
423  rndmEngine->flatArray(3, rndmv);
424  if (NormCond > rndmv[0]) {
425  eps = 0.5 - epsRange * fG4Calc->A13(rndmv[1]);
426  const G4double delta = deltaFactor/(eps*(1.-eps));
427  if (isLPM) {
428  G4double lpmXiS, lpmGS, lpmPhiS, phi1, phi2;
429  ComputePhi12(delta, phi1, phi2);
430  ComputeLPMfunctions(lpmXiS, lpmGS, lpmPhiS, eps, gammaEnergy, iZet);
431  greject = lpmXiS*((2.*lpmPhiS+lpmGS)*phi1-lpmGS*phi2-lpmPhiS*FZ)/F10;
432  } else {
433  greject = (ScreenFunction1(delta)-FZ)/F10;
434  }
435  } else {
436  eps = epsMin + epsRange*rndmv[1];
437  const G4double delta = deltaFactor/(eps*(1.-eps));
438  if (isLPM) {
439  G4double lpmXiS, lpmGS, lpmPhiS, phi1, phi2;
440  ComputePhi12(delta, phi1, phi2);
441  ComputeLPMfunctions(lpmXiS, lpmGS, lpmPhiS, eps, gammaEnergy, iZet);
442  greject = lpmXiS*( (lpmPhiS+0.5*lpmGS)*phi1 + 0.5*lpmGS*phi2
443  -0.5*(lpmGS+lpmPhiS)*FZ )/F20;
444  } else {
445  greject = (ScreenFunction2(delta)-FZ)/F20;
446  }
447  }
448  // Loop checking, 03-Aug-2015, Vladimir Ivanchenko
449  } while (greject < rndmv[2]);
450  // end of eps sampling
451  //
452  // select charges randomly
453  G4double eTotEnergy, pTotEnergy;
454  if (rndmEngine->flat() > 0.5) {
455  eTotEnergy = (1.-eps)*gammaEnergy;
456  pTotEnergy = eps*gammaEnergy;
457  } else {
458  pTotEnergy = (1.-eps)*gammaEnergy;
459  eTotEnergy = eps*gammaEnergy;
460  }
461  //
462  // sample pair kinematics
463  //
464  const G4double eKinEnergy = std::max(0.,eTotEnergy - CLHEP::electron_mass_c2);
465  const G4double pKinEnergy = std::max(0.,pTotEnergy - CLHEP::electron_mass_c2);
466  //
467  G4ThreeVector eDirection, pDirection;
468  //
470  eKinEnergy, pKinEnergy,
471  eDirection, pDirection);
472  // create G4DynamicParticle object for the particle1
473  G4DynamicParticle* aParticle1= new G4DynamicParticle(
474  fTheElectron,eDirection,eKinEnergy);
475 
476  // create G4DynamicParticle object for the particle2
477  G4DynamicParticle* aParticle2= new G4DynamicParticle(
478  fThePositron,pDirection,pKinEnergy);
479  // Fill output vector
480  fvect->push_back(aParticle1);
481  fvect->push_back(aParticle2);
482  // kill incident photon
485 }
486 
487 
488 
489 // should be called only by the master and at initialisation
491 {
492  G4int size = gElementData.size();
493  if (size < gMaxZet+1) {
494  gElementData.resize(gMaxZet+1, nullptr);
495  }
496  // create for all elements that are in the detector
497  const G4ElementTable* elemTable = G4Element::GetElementTable();
498  size_t numElems = (*elemTable).size();
499  for (size_t ie = 0; ie < numElems; ++ie) {
500  const G4Element* elem = (*elemTable)[ie];
501  const G4int iz = std::min(gMaxZet, elem->GetZasInt());
502  if (!gElementData[iz]) { // create it if doesn't exist yet
503  const G4double logZ13 = elem->GetIonisation()->GetlogZ3();
504  const G4double Z13 = elem->GetIonisation()->GetZ3();
505  const G4double fc = elem->GetfCoulomb();
506  const G4double FZ = 8.*(logZ13 + fc);
507  G4double Fel;
508  G4double Finel;
509  if (iz<5) { // use data from Dirac-Fock atomic model
510  Fel = gFelLowZet[iz];
511  Finel = gFinelLowZet[iz];
512  } else { // use the results of the Thomas-Fermi-Moliere model
513  Fel = G4Log(184.) - logZ13;
514  Finel = G4Log(1194.) - 2.*logZ13;
515  }
516  ElementData* elD = new ElementData();
517  elD->fLogZ13 = logZ13;
518  elD->fCoulomb = fc;
519  elD->fLradEl = Fel;
520  elD->fDeltaFactor = 136./Z13;
521  elD->fDeltaMax = G4Exp((42.038 - FZ)/8.29) - 0.958;
522  elD->fEtaValue = Finel/(Fel-fc);
523  elD->fLPMVarS1Cond = std::sqrt(2.)*Z13*Z13/(184.*184.);
524  elD->fLPMILVarS1Cond = 1./G4Log(elD->fLPMVarS1Cond);
525  gElementData[iz] = elD;
526  }
527  }
528 }
529 
530 
531 
532 // s goes up to 2 with ds = 0.01 be default
534  if (!gLPMFuncs.fIsInitialized) {
535  const G4int num = gLPMFuncs.fSLimit*gLPMFuncs.fISDelta+1;
536  gLPMFuncs.fLPMFuncG.resize(num);
537  gLPMFuncs.fLPMFuncPhi.resize(num);
538  for (G4int i=0; i<num; ++i) {
539  const G4double sval = i/gLPMFuncs.fISDelta;
541  }
542  gLPMFuncs.fIsInitialized = true;
543  }
544 }
545 
546 
547 
548 // used only at initialisation time
549 void G4PairProductionRelModel::ComputeLPMGsPhis(G4double &funcGS, G4double &funcPhiS, const G4double varShat) {
550  if (varShat < 0.01) {
551  funcPhiS = 6.0*varShat*(1.0-CLHEP::pi*varShat);
552  funcGS = 12.0*varShat-2.0*funcPhiS;
553  } else {
554  const G4double varShat2 = varShat*varShat;
555  const G4double varShat3 = varShat*varShat2;
556  const G4double varShat4 = varShat2*varShat2;
557  if (varShat < 0.415827397755) { // Stanev ap.: for \psi(s) and compute G(s)
558  funcPhiS = 1.0-G4Exp( -6.0*varShat*(1.0+varShat*(3.0-CLHEP::pi))
559  + varShat3/(0.623+0.796*varShat+0.658*varShat2));
560  // 1-\exp \left\{-4s-\frac{8s^2}{1+3.936s+4.97s^2-0.05s^3+7.5s^4} \right\}
561  const G4double funcPsiS = 1.0-G4Exp( -4.0*varShat - 8.0*varShat2/(1.0
562  + 3.936*varShat+4.97*varShat2-0.05*varShat3+7.5*varShat4));
563  // G(s) = 3 \psi(s) - 2 \phi(s)
564  funcGS = 3.0*funcPsiS - 2.0*funcPhiS;
565  } else if (varShat < 1.55) {
566  funcPhiS = 1.0-G4Exp( -6.0*varShat*(1.0+varShat*(3.0-CLHEP::pi))
567  + varShat3/(0.623+0.796*varShat+0.658*varShat2));
568  const G4double dum0 = -0.16072300849123999+3.7550300067531581*varShat
569  -1.7981383069010097 *varShat2
570  +0.67282686077812381*varShat3
571  -0.1207722909879257 *varShat4;
572  funcGS = std::tanh(dum0);
573  } else {
574  funcPhiS = 1.0-0.01190476/varShat4;
575  if (varShat < 1.9156) {
576  const G4double dum0 = -0.16072300849123999+3.7550300067531581*varShat
577  -1.7981383069010097 *varShat2
578  +0.67282686077812381*varShat3
579  -0.1207722909879257 *varShat4;
580  funcGS = std::tanh(dum0);
581  } else {
582  funcGS = 1.0-0.0230655/varShat4;
583  }
584  }
585  }
586 }
587 
588 
589 
590 // used at run-time to get some pre-computed LPM function values
592  G4double &lpmPhis,
593  const G4double sval) {
594  if (sval < gLPMFuncs.fSLimit) {
595  G4double val = sval*gLPMFuncs.fISDelta;
596  const G4int ilow = (G4int)val;
597  val -= ilow;
598  lpmGs = (gLPMFuncs.fLPMFuncG[ilow+1]-gLPMFuncs.fLPMFuncG[ilow])*val
599  + gLPMFuncs.fLPMFuncG[ilow];
600  lpmPhis = (gLPMFuncs.fLPMFuncPhi[ilow+1]-gLPMFuncs.fLPMFuncPhi[ilow])*val
601  + gLPMFuncs.fLPMFuncPhi[ilow];
602  } else {
603  G4double ss = sval*sval;
604  ss *= ss;
605  lpmPhis = 1.0-0.01190476/ss;
606  lpmGs = 1.0-0.0230655/ss;
607  }
608 }
609 
610 
611 
613  G4double &funcGS, G4double &funcPhiS, const G4double eps,
614  const G4double egamma, const G4int izet)
615 {
616  // 1. y = E_+/E_{\gamma} with E_+ being the total energy transfered
617  // to one of the e-/e+ pair
618  // s' = \sqrt{ \frac{1}{8} \frac{1}{y(1-y)} \frac{E^{KL}_{LPM}}{E_{\gamma}} }
619  const G4double varSprime = std::sqrt(0.125*fLPMEnergy/(eps*egamma*(1.0-eps)));
620  const G4double condition = gElementData[izet]->fLPMVarS1Cond;
621  funcXiS = 2.0;
622  if (varSprime > 1.0) {
623  funcXiS = 1.0;
624  } else if (varSprime > condition) {
625  const G4double dum = gElementData[izet]->fLPMILVarS1Cond;
626  const G4double funcHSprime = G4Log(varSprime)*dum;
627  funcXiS = 1.0 + funcHSprime
628  - 0.08*(1.0-funcHSprime)*funcHSprime*(2.0-funcHSprime)*dum;
629  }
630  // 2. s=\frac{s'}{\sqrt{\xi(s')}}
631  const G4double varShat = varSprime / std::sqrt(funcXiS);
632  GetLPMFunctions(funcGS, funcPhiS, varShat);
633  // MAKE SURE SUPPRESSION IS SMALLER THAN 1: due to Migdal's approximation on xi
634  if (funcXiS * funcPhiS > 1. || varShat > 0.57) {
635  funcXiS = 1. / funcPhiS;
636  }
637 }
638 
#define F10
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
void SetElementSelectors(std::vector< G4EmElementSelector * > *)
Definition: G4VEmModel.hh:792
G4ParticleDefinition * fThePositron
virtual void SamplePairDirections(const G4DynamicParticle *dp, G4double elecKinEnergy, G4double posiKinEnergy, G4ThreeVector &dirElectron, G4ThreeVector &dirPositron, G4int Z=0, const G4Material *mat=nullptr)
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:183
T max(const T t1, const T t2)
brief Return the largest of the two arguments
G4double A13(G4double A) const
Definition: G4Pow.cc:138
void ScreenFunction12(const G4double delta, G4double &f1, G4double &f2)
static std::vector< ElementData * > gElementData
static const G4double gFinelLowZet[8]
G4double GetRadlen() const
Definition: G4Material.hh:221
const char * p
Definition: xmltok.h:285
static constexpr double hbarc
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4double ScreenFunction2(const G4double delta)
static const G4double gEgLPMActivation
void GetLPMFunctions(G4double &lpmGs, G4double &lpmPhis, const G4double sval)
G4double ComputeDXSectionPerAtom(G4double eplusEnergy, G4double gammaEnergy, G4double Z)
void SetProposedKineticEnergy(G4double proposedKinEnergy)
virtual void flatArray(const int size, double *vect)=0
const G4Element * SelectRandomAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.hh:552
G4double condition(const G4ErrorSymMatrix &m)
std::vector< G4EmElementSelector * > * GetElementSelectors()
Definition: G4VEmModel.hh:784
static constexpr double classic_electr_radius
G4ParticleDefinition * fTheElectron
G4double G4Log(G4double x)
Definition: G4Log.hh:230
G4ParticleDefinition * fTheGamma
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:616
virtual void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
static const G4double gLPMconstant
Float_t Z
double G4double
Definition: G4Types.hh:76
bool G4bool
Definition: G4Types.hh:79
virtual double flat()=0
void InitialiseElementSelectors(const G4ParticleDefinition *, const G4DataVector &)
Definition: G4VEmModel.cc:146
void ComputeLPMGsPhis(G4double &funcGS, G4double &funcPhiS, const G4double varShat)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0., G4double cut=0., G4double emax=DBL_MAX) override
G4ParticleChangeForGamma * fParticleChange
static constexpr double electron_mass_c2
void ComputePhi12(const G4double delta, G4double &phi1, G4double &phi2)
G4double GetZ3() const
std::vector< G4Element * > G4ElementTable
static const G4double gXGL[8]
#define F20
void SetAngularDistribution(G4VEmAngularDistribution *)
Definition: G4VEmModel.hh:582
Float_t mat
static const G4double gWGL[8]
G4double ScreenFunction1(const G4double delta)
static const G4double gFelLowZet[8]
G4int GetZasInt() const
Definition: G4Element.hh:132
G4double ComputeRelDXSectionPerAtom(G4double eplusEnergy, G4double gammaEnergy, G4double Z)
virtual void SetupForMaterial(const G4ParticleDefinition *, const G4Material *, G4double) override
std::map< G4String, G4AttDef > * GetInstance(const G4String &storeKey, G4bool &isNew)
int G4lrint(double ad)
Definition: templates.hh:151
int G4int
Definition: G4Types.hh:78
Definition: G4Pow.hh:56
G4PairProductionRelModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="BetheHeitlerLPM")
G4IonisParamElm * GetIonisation() const
Definition: G4Element.hh:199
G4double GetKineticEnergy() const
void ComputeLPMfunctions(G4double &fXiS, G4double &fGS, G4double &fPhiS, const G4double eps, const G4double egamma, const G4int izet)
G4bool IsMaster() const
Definition: G4VEmModel.hh:700
G4VEmAngularDistribution * GetAngularDistribution()
Definition: G4VEmModel.hh:575
const G4Material * GetMaterial() const
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:131
static const G4double eps
G4double GetfCoulomb() const
Definition: G4Element.hh:191
G4double GetlogZ3() const
static constexpr double fine_structure_const
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:609
void ProposeTrackStatus(G4TrackStatus status)
static constexpr double GeV
static constexpr double pi
Definition: SystemOfUnits.h:54
G4double ComputeXSectionPerAtom(G4double gammaEnergy, G4double Z)
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
static G4ElementTable * GetElementTable()
Definition: G4Element.cc:398