Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/standard/src/G4PairProductionRelModel.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /processes/electromagnetic/standard/src/G4PairProductionRelModel.cc (Version 11.3.0) and /processes/electromagnetic/standard/src/G4PairProductionRelModel.cc (Version 8.1.p2)


  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