Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/standard/src/G4eBremsstrahlungRelModel.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/G4eBremsstrahlungRelModel.cc (Version 11.3.0) and /processes/electromagnetic/standard/src/G4eBremsstrahlungRelModel.cc (Version 8.1)


  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:     G4eBremsstrahlungRelModel       
 33 //                                                
 34 // Author:        Andreas Schaelicke              
 35 //                                                
 36 // Creation date: 12.08.2008                      
 37 //                                                
 38 // Modifications:                                 
 39 //                                                
 40 // 13.11.08    add SetLPMflag and SetLPMconsta    
 41 // 13.11.08    change default LPMconstant valu    
 42 // 13.10.10    add angular distributon interfa    
 43 // 31.05.16    change LPMconstant such that it    
 44 //             that consistent to Migdal's one    
 45 //             computation; better agreement w    
 46 // 15.07.18    improved LPM suppression functi    
 47 //             steps), code cleanup and optimi    
 48 //             model related comments, consist    
 49 //                                                
 50 // Main References:                               
 51 //  Y.-S.Tsai, Rev. Mod. Phys. 46 (1974) 815;     
 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                                                   
 60 #include "G4eBremsstrahlungRelModel.hh"           
 61 #include "G4PhysicalConstants.hh"                 
 62 #include "G4SystemOfUnits.hh"                     
 63 #include "G4Electron.hh"                          
 64 #include "G4Gamma.hh"                             
 65 #include "Randomize.hh"                           
 66 #include "G4Material.hh"                          
 67 #include "G4Element.hh"                           
 68 #include "G4ElementVector.hh"                     
 69 #include "G4ParticleChangeForLoss.hh"             
 70 #include "G4ModifiedTsai.hh"                      
 71 #include "G4Exp.hh"                               
 72 #include "G4Log.hh"                               
 73 #include "G4Pow.hh"                               
 74 #include "G4EmParameters.hh"                      
 75 #include "G4AutoLock.hh"                          
 76 #include <thread>                                 
 77                                                   
 78 const G4int G4eBremsstrahlungRelModel::gMaxZet    
 79                                                   
 80 // constant DCS factor: 16\alpha r_0^2/3          
 81 const G4double G4eBremsstrahlungRelModel::gBre    
 82   = 16. * CLHEP::fine_structure_const * CLHEP:    
 83     * CLHEP::classic_electr_radius/3.;            
 84                                                   
 85 // Migdal's constant: 4\pi r_0*electron_reduce    
 86 const G4double G4eBremsstrahlungRelModel::gMig    
 87   = 4. * CLHEP::pi * CLHEP::classic_electr_rad    
 88     * CLHEP::electron_Compton_length * CLHEP::    
 89                                                   
 90 // LPM constant: \alpha(mc^2)^2/(4\pi*\hbar c)    
 91 const G4double G4eBremsstrahlungRelModel::gLPM    
 92   = CLHEP::fine_structure_const * CLHEP::elect    
 93     * CLHEP::electron_mass_c2 / (4. * CLHEP::p    
 94                                                   
 95 // abscissas and weights of an 8 point Gauss-L    
 96 // for numerical integration on [0,1]             
 97 const G4double G4eBremsstrahlungRelModel::gXGL    
 98   1.98550718e-02, 1.01666761e-01, 2.37233795e-    
 99   5.91717321e-01, 7.62766205e-01, 8.98333239e-    
100 };                                                
101 const G4double G4eBremsstrahlungRelModel::gWGL    
102   5.06142681e-02, 1.11190517e-01, 1.56853323e-    
103   1.81341892e-01, 1.56853323e-01, 1.11190517e-    
104 };                                                
105                                                   
106 // elastic and inelatic radiation logarithms f    
107 // Thomas-Fermi model doesn't work): computed     
108 const G4double G4eBremsstrahlungRelModel::gFel    
109   0.0, 5.3104, 4.7935, 4.7402, 4.7112, 4.6694,    
110 };                                                
111 const G4double G4eBremsstrahlungRelModel::gFin    
112   0.0, 5.9173, 5.6125, 5.5377, 5.4728, 5.4174,    
113 };                                                
114                                                   
115 // LPM supression functions evaluated at initi    
116 std::shared_ptr<G4eBremsstrahlungRelModel::LPM    
117 {                                                 
118   // We have to use shared pointer for the LPM    
119   // by the G4eBremsstrahlungRelModel used in     
120   // model is owned (well deleted) by (at leas    
121   // a G4SeltzerBergerModel which is owned by     
122   // which owned by a G4ThreadLocalSingleton<G    
123   // which is a static global and thus deleted    
124   // is deleted.                                  
125   static auto _instance = std::make_shared<G4e    
126   return _instance;                               
127 }                                                 
128                                                   
129 // special data structure per element i.e. per    
130 std::shared_ptr<std::vector<G4eBremsstrahlungR    
131 {                                                 
132   // Same code comment as for gLPMFuncs.          
133   static auto _instance = std::make_shared<std    
134   return _instance;                               
135 }                                                 
136                                                   
137 static std::once_flag applyOnce;                  
138                                                   
139 namespace                                         
140 {                                                 
141   G4Mutex theBremRelMutex = G4MUTEX_INITIALIZE    
142 }                                                 
143                                                   
144 G4eBremsstrahlungRelModel::G4eBremsstrahlungRe    
145                                                   
146 : G4VEmModel(nam), fLPMFuncs(gLPMFuncs()), fEl    
147 {                                                 
148   fGammaParticle       = G4Gamma::Gamma();        
149   //                                              
150   fLowestKinEnergy     = 1.0*CLHEP::MeV;          
151   SetLowEnergyLimit(fLowestKinEnergy);            
152   //                                              
153   fLPMEnergyThreshold  = 1.e+39;                  
154   fLPMEnergy           = 0.;                      
155   SetAngularDistribution(new G4ModifiedTsai())    
156   //                                              
157   if (nullptr != p) {                             
158     SetParticle(p);                               
159   }                                               
160 }                                                 
161                                                   
162 G4eBremsstrahlungRelModel::~G4eBremsstrahlungR    
163 {                                                 
164   if (fIsInitializer) {                           
165     // clear ElementData container                
166     for (auto const & ptr : *fElementData) { d    
167     fElementData->clear();                        
168     // clear LPMFunctions (if any)                
169     if (fLPMFuncs->fIsInitialized) {              
170       fLPMFuncs->fLPMFuncG.clear();               
171       fLPMFuncs->fLPMFuncPhi.clear();             
172       fLPMFuncs->fIsInitialized = false;          
173     }                                             
174   }                                               
175 }                                                 
176                                                   
177 void G4eBremsstrahlungRelModel::Initialise(con    
178                                            con    
179 {                                                 
180   // parameters in each thread                    
181   if (fPrimaryParticle != p) {                    
182     SetParticle(p);                               
183   }                                               
184   fUseLPM = G4EmParameters::Instance()->LPM();    
185   fCurrentIZ = 0;                                 
186                                                   
187   // init static element data and precompute L    
188   std::call_once(applyOnce, [this]() { fIsInit    
189                                                   
190   // for all treads and derived classes           
191   if (fIsInitializer || fElementData->empty())    
192     G4AutoLock l(&theBremRelMutex);               
193     if (fElementData->empty()) {                  
194       fElementData->resize(gMaxZet+1, nullptr)    
195     }                                             
196     InitialiseElementData();                      
197     InitLPMFunctions();                           
198     l.unlock();                                   
199   }                                               
200                                                   
201   // element selectors are initialized in the     
202   if (IsMaster()) {                               
203     InitialiseElementSelectors(p, cuts);          
204   }                                               
205   // initialisation in all threads                
206   if (nullptr == fParticleChange) {               
207     fParticleChange = GetParticleChangeForLoss    
208   }                                               
209   if (GetTripletModel()) {                        
210     GetTripletModel()->Initialise(p, cuts);       
211     fIsScatOffElectron = true;                    
212   }                                               
213 }                                                 
214                                                   
215 void G4eBremsstrahlungRelModel::InitialiseLoca    
216                                                   
217 {                                                 
218   SetElementSelectors(masterModel->GetElementS    
219 }                                                 
220                                                   
221 void G4eBremsstrahlungRelModel::SetParticle(co    
222 {                                                 
223   fPrimaryParticle     = p;                       
224   fPrimaryParticleMass = p->GetPDGMass();         
225   fIsElectron          = (p==G4Electron::Elect    
226 }                                                 
227                                                   
228 // Sets kinematical variables like E_kin, E_t     
229 // variables like LPM energy and characteristi    
230 // k_p^2) for the Ter-Mikaelian suppression ef    
231 void G4eBremsstrahlungRelModel::SetupForMateri    
232                                                   
233                                                   
234 {                                                 
235   fDensityFactor = gMigdalConstant*mat->GetEle    
236   fLPMEnergy     = gLPMconstant*mat->GetRadlen    
237   // threshold for LPM effect (i.e. below whic    
238   if (fUseLPM) {                                  
239     fLPMEnergyThreshold = std::sqrt(fDensityFa    
240   } else {                                        
241     fLPMEnergyThreshold = 1.e+39;   // i.e. do    
242   }                                               
243   // calculate threshold for density effect: k    
244   fPrimaryKinEnergy   = kineticEnergy;            
245   fPrimaryTotalEnergy = kineticEnergy+fPrimary    
246   fDensityCorr        = fDensityFactor*fPrimar    
247   // set activation flag for LPM effects in th    
248   fIsLPMActive = (fPrimaryTotalEnergy>fLPMEner    
249 }                                                 
250                                                   
251 // minimum primary (e-/e+) energy at which dis    
252 G4double G4eBremsstrahlungRelModel::MinPrimary    
253                                                   
254                                                   
255 {                                                 
256   return std::max(fLowestKinEnergy, cut);         
257 }                                                 
258                                                   
259 // Computes the restricted dE/dx as the approp    
260 // element contributions that are computed by     
261 G4double                                          
262 G4eBremsstrahlungRelModel::ComputeDEDXPerVolum    
263                                                   
264                                                   
265                                                   
266 {                                                 
267   G4double dedx = 0.0;                            
268   if (nullptr == fPrimaryParticle) {              
269     SetParticle(p);                               
270   }                                               
271   if (kineticEnergy < LowEnergyLimit()) {         
272     return dedx;                                  
273   }                                               
274   // maximum value of the dE/dx integral (the     
275   G4double tmax = std::min(cutEnergy, kineticE    
276   if (tmax == 0.0) {                              
277     return dedx;                                  
278   }                                               
279   // sets kinematical and material related var    
280   SetupForMaterial(fPrimaryParticle, material,    
281   // get element compositions of the material     
282   const G4ElementVector* theElemVector = mater    
283   const G4double* theAtomNumDensVector = mater    
284   const std::size_t numberOfElements = theElem    
285   // loop over the elements of the material an    
286   // the restricted dE/dx by numerical integra    
287   for (std::size_t ie = 0; ie < numberOfElemen    
288     G4VEmModel::SetCurrentElement((*theElemVec    
289     G4int zet = (*theElemVector)[ie]->GetZasIn    
290     fCurrentIZ = std::min(zet, gMaxZet);          
291     dedx              += (zet*zet)*theAtomNumD    
292   }                                               
293   // apply the constant factor C/Z = 16\alpha     
294   dedx *= gBremFactor;                            
295   return std::max(dedx,0.);                       
296 }                                                 
297                                                   
298 // Computes the integral part of the restricte    
299 // element (Z) by numerically integrating the     
300 // k_min=0 and k_max = tmax = min[gamma-cut, e    
301 // The numerical integration is done by dividi    
302 // subintervals and an 8 pint GL integral (on     
303 // inteval by tranforming k to alpha=k/E_t (E_    
304 // and each sub-interavl is transformed to [0,    
305 // in xi(alpha) = xi(k) = [k/E_t-alpha_i]/delt    
306 // the i = 1,2,..,n-th sub-interval so xi(k) i    
307 // This transformation from 'k' to 'xi(k)' res    
308 // of E_t*delta at each step.                     
309 // The restricted dE/dx = N int_{0}^{k_max} k*    
310 // one with LPM and one without LPM effects (s    
311 // the ds/dk(Z,k) but ds/dk(Z,k)*[F*k/C] is co    
312 // (i)    what we need here is ds/dk*k and not    
313 // (ii)   the Ter-Mikaelian suppression i.e. F    
314 // (iii)  the constant factor C (includes Z^2     
315 G4double G4eBremsstrahlungRelModel::ComputeBre    
316 {                                                 
317   // number of intervals and integration step     
318   const G4double alphaMax = tmax/fPrimaryTotal    
319   const G4int        nSub = (G4int)(20*alphaMa    
320   const G4double    delta = alphaMax/((G4doubl    
321   // set minimum value of the first sub-inteva    
322   G4double alpha_i        = 0.0;                  
323   G4double dedxInteg      = 0.0;                  
324   for (G4int l = 0; l < nSub; ++l) {              
325     for (G4int igl = 0; igl < 8; ++igl) {         
326       // compute the emitted photon energy k      
327       const G4double k   = (alpha_i+gXGL[igl]*    
328       // compute the DCS value at k (without t    
329       const G4double dcs = fIsLPMActive           
330                           ? ComputeRelDXSectio    
331                           : ComputeDXSectionPe    
332       // account Ter-Mikaelian suppression: ti    
333       dedxInteg += gWGL[igl]*dcs/(1.0+fDensity    
334     }                                             
335     // update sub-interval minimum value          
336     alpha_i += delta;                             
337   }                                               
338   // apply corrections due to variable transfo    
339   dedxInteg *= delta*fPrimaryTotalEnergy;         
340   return std::max(dedxInteg,0.);                  
341 }                                                 
342                                                   
343 // Computes restrected atomic cross section by    
344 // DCS between the proper kinematical limits a    
345 G4double G4eBremsstrahlungRelModel::ComputeCro    
346                                                   
347                                                   
348                                                   
349                                                   
350                                                   
351                                                   
352 {                                                 
353   G4double crossSection = 0.0;                    
354   if (nullptr == fPrimaryParticle) {              
355     SetParticle(p);                               
356   }                                               
357   if (kineticEnergy < LowEnergyLimit()) {         
358     return crossSection;                          
359   }                                               
360   // min/max kinetic energy limits of the DCS     
361   const G4double tmin = std::min(cut, kineticE    
362   const G4double tmax = std::min(maxEnergy, ki    
363   // zero restricted x-section if e- kinetic e    
364   if (tmin >= tmax) {                             
365     return crossSection;                          
366   }                                               
367   fCurrentIZ = std::min(G4lrint(Z), gMaxZet);     
368   // integrate numerically (dependent part of)    
369   // a. integrate between tmin and kineticEner    
370   crossSection = ComputeXSectionPerAtom(tmin);    
371   // allow partial integration: only if maxEne    
372   // b. integrate between tmax and kineticEner    
373   // (so the result in this case is the integr    
374   // maxEnergy)                                   
375   if (tmax < kineticEnergy) {                     
376     crossSection -= ComputeXSectionPerAtom(tma    
377   }                                               
378   // multiply with the constant factors: 16\al    
379   crossSection *= Z*Z*gBremFactor;                
380   return std::max(crossSection, 0.);              
381 }                                                 
382                                                   
383 // Numerical integral of the (k dependent part    
384 // k_max = E_k (where E_k is the kinetic energ    
385 // minimum of energy of the  emitted photon).     
386 // transformed alpha(k) = ln(k/E_t) variable (    
387 // the primary e-). The integration range is d    
388 // delta = [ln(k_min/E_t)-ln(k_max/E_t)]/n wid    
389 // on [0,1] is applied on each sub-inteval so     
390 // xi(alpha) = xi(k) = [ln(k/E_t)-alpha_i]/del    
391 // (i-1)*delta for the i = 1,2,..,n-th sub-int    
392 // sub-intevals. From the transformed xi, k(xi    
393 // Since the integration is done in variable x    
394 // transformation results in a multiplicative     
395 // However, DCS differential in k is ~1/k so t    
396 // becomes delta and the 1/k factor is dropped    
397 // NOTE:                                          
398 //   - LPM suppression is accounted above thre    
399 //     flag is set in SetUpForMaterial() => 2     
400 //   - Ter-Mikaelian suppression is always acc    
401 G4double G4eBremsstrahlungRelModel::ComputeXSe    
402 {                                                 
403   G4double xSection = 0.0;                        
404   const G4double alphaMin = G4Log(tmin/fPrimar    
405   const G4double alphaMax = G4Log(fPrimaryKinE    
406   const G4int nSub = std::max((G4int)(0.45*alp    
407   const G4double delta = alphaMax/((G4double)n    
408   // set minimum value of the first sub-inteva    
409   G4double alpha_i = alphaMin;                    
410   for (G4int l = 0; l < nSub; ++l) {              
411     for (G4int igl = 0; igl < 8; ++igl) {         
412       // compute the emitted photon energy k      
413       const G4double k   = G4Exp(alpha_i+gXGL[    
414       // compute the DCS value at k (without t    
415       const G4double dcs = fIsLPMActive           
416                           ? ComputeRelDXSectio    
417                           : ComputeDXSectionPe    
418       // account Ter-Mikaelian suppression: ti    
419       xSection += gWGL[igl]*dcs/(1.0+fDensityC    
420     }                                             
421     // update sub-interval minimum value          
422     alpha_i += delta;                             
423   }                                               
424   // apply corrections due to variable transfo    
425   xSection *= delta;                              
426   // final check                                  
427   return std::max(xSection, 0.);                  
428 }                                                 
429                                                   
430 // DCS WITH LPM EFFECT: complete screening apr    
431 // ds/dk(Z,k) = C/[F*k]*{ Xi(s*F)*[y^2*G/4 +(1    
432 //                        +(1-y)*[1+1/Z]/12}      
433 // Xi(s),G(s), Phi(s) are LPM suppression func    
434 //                                                
435 // LPM SUPPRESSION: The 's' is the suppression    
436 // 1+(k_p/k)^2 with k_p = hbar*w_p*E/(m*c^2) i    
437 // dependent constant. F accounts the Ter-Mika    
438 // transition in the emitted photon energy. Al    
439 // goes to 0 when s goes to 0 and goes to 1 wh    
440 // So evaluating the LPM suppression functions    
441 // smooth transition depending on the emitted     
442 // smoothly turned off i.e. Xi(sF)=G(sF)=Phi(s    
443 // and sF ~ s when k >> k_p since F ~ 1 in tha    
444 // HERE, ds/dk(Z,k)*[F*k/C] is computed since:    
445 //  (i)   DCS ~ 1/k factor will disappear due     
446 //        v(k)=ln(k/E_t) -> dk/dv=E_t*e^v=k ->    
447 //        would cnacell out the 1/k factor =>     
448 //  (ii)  the constant factor C and Z don't de    
449 //  (iii) the 1/F(k) factor is accounted in th    
450 //        tion computation) or implicitly thro    
451 //        (in the final state sampling algorit    
452 // COMPLETE SCREENING: see more at the DCS wit    
453 G4double                                          
454 G4eBremsstrahlungRelModel::ComputeRelDXSection    
455 {                                                 
456   G4double dxsec = 0.0;                           
457   if (gammaEnergy < 0.) {                         
458     return dxsec;                                 
459   }                                               
460   const G4double y     = gammaEnergy/fPrimaryT    
461   const G4double onemy = 1.-y;                    
462   const G4double dum0  = 0.25*y*y;                
463   // evaluate LPM functions (combined with the    
464   G4double funcGS, funcPhiS, funcXiS;             
465   ComputeLPMfunctions(funcXiS, funcGS, funcPhi    
466   const ElementData* elDat = (*fElementData)[f    
467   const G4double term1     = funcXiS*(dum0*fun    
468   dxsec = term1*elDat->fZFactor1+onemy*elDat->    
469   //                                              
470   if (fIsScatOffElectron) {                       
471     fSumTerm = dxsec;                             
472     fNucTerm = term1*elDat->fZFactor11 + onemy    
473   }                                               
474   return std::max(dxsec,0.0);                     
475 }                                                 
476                                                   
477 // DCS WITHOUT LPM EFFECT: DCS with sceening (    
478 // ds/dk(Z,k)=C/[F*k]*{(1-y+3*y^2/4)*[(0.25*ph    
479 // -2*ln(Z)/3)/Z]+ (1-y)*[(phi1(g)-phi2(g))+(p    
480 // where f_c(Z) is the Coulomb correction fact    
481 // psi2(e) are coherent and incoherent screeni    
482 // model of the atom, the screening functions     
483 // depend on Z (not explicitly). These numeric    
484 // approximated as Tsai Eqs. [3.38-3.41] with     
485 // e=epsilon given by Tsai Eqs. [3.30 and 3.31    
486 // ComputeScreeningFunctions()). Note, that in    
487 // g = e = 0 => 0.25*phi1(0)-ln(Z)/3 = ln(184.    
488 // 0.25*psi1(0)-2*ln(Z)/3=ln(1193.923/Z^(2/3))    
489 // psi1(0)-psi2(0) = 2/3 so the DCS in complet    
490 // COMPLETE SCREENING:                            
491 // ds/dk(Z,k)=C/k*{(1-y+3*y^2/4)*[L_el-f_c+L_i    
492 // used in case of DCS with LPM above (if all     
493 // absent i.e. their value = 1).                  
494 // Since the Thomas-Fermi model of the atom is    
495 // complete screening is used here at low Z(<5    
496 // computed by using the Dirac-Fock model of t    
497 // NOTE: that the Ter-Mikaelian suppression is    
498 // 1/F factor but it is included in the caller    
499 // HERE, ds/dk(Z,k)*[F*k/C] is computed exactl    
500 G4double                                          
501 G4eBremsstrahlungRelModel::ComputeDXSectionPer    
502 {                                                 
503   G4double dxsec = 0.0;                           
504   if (gammaEnergy < 0.) {                         
505     return dxsec;                                 
506   }                                               
507   const G4double y         = gammaEnergy/fPrim    
508   const G4double onemy     = 1.-y;                
509   const G4double dum0      = onemy+0.75*y*y;      
510   const ElementData* elDat = (*fElementData)[f    
511   // use complete screening and L_el, L_inel f    
512   if (fCurrentIZ < 5 || fIsUseCompleteScreenin    
513     dxsec  = dum0*elDat->fZFactor1;               
514     dxsec += onemy*elDat->fZFactor2;              
515     if (fIsScatOffElectron) {                     
516       fSumTerm = dxsec;                           
517       fNucTerm = dum0*elDat->fZFactor11+onemy/    
518     }                                             
519   } else {                                        
520     // use Tsai's analytical approx. (Tsai Eqs    
521     // numerical screening functions computed     
522     const G4double invZ    = 1./(G4double)fCur    
523     const G4double Fz      = elDat->fFz;          
524     const G4double logZ    = elDat->fLogZ;        
525     const G4double dum1    = y/(fPrimaryTotalE    
526     const G4double gamma   = dum1*elDat->fGamm    
527     const G4double epsilon = dum1*elDat->fEpsi    
528     // evaluate the screening functions           
529     G4double phi1, phi1m2, psi1, psi1m2;          
530     ComputeScreeningFunctions(phi1, phi1m2, ps    
531     dxsec  = dum0*((0.25*phi1-Fz) + (0.25*psi1    
532     dxsec += 0.125*onemy*(phi1m2 + psi1m2*invZ    
533     if (fIsScatOffElectron) {                     
534       fSumTerm = dxsec;                           
535       fNucTerm = dum0*(0.25*phi1-Fz) + 0.125*o    
536     }                                             
537   }                                               
538   return std::max(dxsec,0.0);                     
539 }                                                 
540                                                   
541 // Coherent and incoherent screening function     
542 // Eqs.[3.38-3.41]). Tsai's analytical approxi    
543 // functions computed by using the Thomas-Ferm    
544 // ximation to the numerical TF screening func    
545 // screening functions can be expressed in a '    
546 // pendent variable (see Tsai Eqs. Eqs. [3.30     
547 void G4eBremsstrahlungRelModel::ComputeScreeni    
548                                                   
549                                                   
550                                                   
551                                                   
552                                                   
553 {                                                 
554   const G4double gam2 = gam*gam;                  
555   phi1   = 16.863-2.0*G4Log(1.0+0.311877*gam2)    
556           +1.6*G4Exp(-1.5*gam);                   
557   phi1m2 = 2.0/(3.0+19.5*gam+18.0*gam2);    //    
558   const G4double eps2 = eps*eps;                  
559   psi1   = 24.34-2.0*G4Log(1.0+13.111641*eps2)    
560           +1.2*G4Exp(-29.2*eps);                  
561   psi1m2 = 2.0/(3.0+120.0*eps+1200.0*eps2); //    
562 }                                                 
563                                                   
564 void                                              
565 G4eBremsstrahlungRelModel::SampleSecondaries(s    
566                                              c    
567                                              c    
568                                              G    
569                                              G    
570 {                                                 
571   const G4double kineticEnergy    = dp->GetKin    
572   if (kineticEnergy < LowEnergyLimit()) {         
573     return;                                       
574   }                                               
575   // min, max kinetic energy limits               
576   const G4double tmin = std::min(cutEnergy, ki    
577   const G4double tmax = std::min(maxEnergy, ki    
578   if (tmin >= tmax) {                             
579     return;                                       
580   }                                               
581   //                                              
582   SetupForMaterial(fPrimaryParticle, couple->G    
583   const G4Element* elm = SelectTargetAtom(coup    
584                                           dp->    
585   //                                              
586   fCurrentIZ = elm->GetZasInt();                  
587   const ElementData* elDat = (*fElementData)[f    
588   const G4double funcMax = elDat->fZFactor1+el    
589   // get the random engine                        
590   G4double rndm[2];                               
591   CLHEP::HepRandomEngine* rndmEngine = G4Rando    
592   // min max of the transformed variable: x(k)    
593   const G4double xmin   = G4Log(tmin*tmin+fDen    
594   const G4double xrange = G4Log(tmax*tmax+fDen    
595   G4double gammaEnergy, funcVal;                  
596   do {                                            
597     rndmEngine->flatArray(2, rndm);               
598     gammaEnergy = std::sqrt(std::max(G4Exp(xmi    
599     funcVal     = fIsLPMActive                    
600                  ? ComputeRelDXSectionPerAtom(    
601                  : ComputeDXSectionPerAtom(gam    
602     // cross-check of proper function maximum     
603 //    if (funcVal > funcMax) {                    
604 //      G4cout << "### G4eBremsstrahlungRelMod    
605 //       << funcVal << " > " << funcMax           
606 //       << " Egamma(MeV)= " << gammaEnergy       
607 //       << " Ee(MeV)= " << kineticEnergy         
608 //       << "  " << GetName()                     
609 //       << G4endl;                               
610 //    }                                           
611     // Loop checking, 03-Aug-2015, Vladimir Iv    
612   } while (funcVal < funcMax*rndm[1]);            
613   //                                              
614   // scattering off nucleus or off e- by tripl    
615   if (fIsScatOffElectron && rndmEngine->flat()    
616     GetTripletModel()->SampleSecondaries(vdp,     
617     return;                                       
618   }                                               
619   //                                              
620   // angles of the emitted gamma. ( Z - axis a    
621   // use general interface                        
622   G4ThreeVector gamDir =                          
623     GetAngularDistribution()->SampleDirection(    
624                                                   
625   // create G4DynamicParticle object for the G    
626   auto gamma = new G4DynamicParticle(fGammaPar    
627   vdp->push_back(gamma);                          
628   // compute post-interaction kinematics of pr    
629   // energy-momentum conservation                 
630   const G4double totMomentum = std::sqrt(kinet    
631                                fPrimaryTotalEn    
632   G4ThreeVector dir =                             
633              (totMomentum*dp->GetMomentumDirec    
634   const G4double finalE   = kineticEnergy-gamm    
635   // if secondary gamma energy is higher than     
636   // then stop tracking the primary particle a    
637   // instead of the primary one                   
638   if (gammaEnergy > SecondaryThreshold()) {       
639     fParticleChange->ProposeTrackStatus(fStopA    
640     fParticleChange->SetProposedKineticEnergy(    
641     auto el = new G4DynamicParticle(              
642               const_cast<G4ParticleDefinition*    
643     vdp->push_back(el);                           
644   } else { // continue tracking the primary e-    
645     fParticleChange->SetProposedMomentumDirect    
646     fParticleChange->SetProposedKineticEnergy(    
647   }                                               
648 }                                                 
649                                                   
650 void G4eBremsstrahlungRelModel::InitialiseElem    
651 {                                                 
652   // create for all elements that are in the d    
653   auto elemTable = G4Element::GetElementTable(    
654   for (auto const & elem : *elemTable) {          
655     const G4double zet = elem->GetZ();            
656     const G4int izet = std::min(elem->GetZasIn    
657     if (nullptr == (*fElementData)[izet]) {       
658       auto elemData  = new ElementData();         
659       const G4double fc = elem->GetfCoulomb();    
660       G4double Fel      = 1.;                     
661       G4double Finel    = 1.;                     
662       elemData->fLogZ   = G4Log(zet);             
663       elemData->fFz     = elemData->fLogZ/3.+f    
664       if (izet < 5) {                             
665         Fel   = gFelLowZet[izet];                 
666         Finel = gFinelLowZet[izet];               
667       } else {                                    
668         Fel   = G4Log(184.15) -    elemData->f    
669         Finel = G4Log(1194)   - 2.*elemData->f    
670       }                                           
671       const G4double z13 = G4Pow::GetInstance(    
672       const G4double z23 = z13*z13;               
673       elemData->fZFactor1      = (Fel-fc)+Fine    
674       elemData->fZFactor11     = (Fel-fc); //     
675       elemData->fZFactor2      = (1.+1./zet)/1    
676       elemData->fVarS1         = z23/(184.15*1    
677       elemData->fILVarS1Cond   = 1./(G4Log(std    
678       elemData->fILVarS1       = 1./G4Log(elem    
679       elemData->fGammaFactor   = 100.0*electro    
680       elemData->fEpsilonFactor = 100.0*electro    
681       (*fElementData)[izet] = elemData;           
682     }                                             
683   }                                               
684 }                                                 
685                                                   
686 void G4eBremsstrahlungRelModel::ComputeLPMfunc    
687                                                   
688                                                   
689                                                   
690 {                                                 
691   static const G4double sqrt2 = std::sqrt(2.);    
692   const G4double    redegamma = egamma/fPrimar    
693   const G4double    varSprime = std::sqrt(0.12    
694                                 ((1.0-redegamm    
695   const ElementData* elDat    = (*fElementData    
696   const G4double varS1        = elDat->fVarS1;    
697   const G4double condition    = sqrt2*varS1;      
698   G4double funcXiSprime = 2.0;                    
699   if (varSprime > 1.0) {                          
700     funcXiSprime = 1.0;                           
701   } else if (varSprime > condition) {             
702     const G4double ilVarS1Cond = elDat->fILVar    
703     const G4double funcHSprime = G4Log(varSpri    
704     funcXiSprime = 1.0 + funcHSprime - 0.08*(1    
705                                       *(2.0-fu    
706   }                                               
707   const G4double varS    = varSprime/std::sqrt    
708   // - include dielectric suppression effect i    
709   const G4double varShat = varS*(1.0+fDensityC    
710   funcXiS = 2.0;                                  
711   if (varShat > 1.0) {                            
712     funcXiS = 1.0;                                
713   } else if (varShat > varS1) {                   
714     funcXiS = 1.0+G4Log(varShat)*elDat->fILVar    
715   }                                               
716   GetLPMFunctions(funcGS, funcPhiS, varShat);     
717   //ComputeLPMGsPhis(funcGS, funcPhiS, varShat    
718   //                                              
719   //MAKE SURE SUPPRESSION IS SMALLER THAN 1: d    
720   if (funcXiS*funcPhiS > 1. || varShat > 0.57)    
721     funcXiS=1./funcPhiS;                          
722   }                                               
723 }                                                 
724                                                   
725 void G4eBremsstrahlungRelModel::ComputeLPMGsPh    
726                                                   
727                                                   
728 {                                                 
729   if (varShat < 0.01) {                           
730     funcPhiS = 6.0*varShat*(1.0-CLHEP::pi*varS    
731     funcGS   = 12.0*varShat-2.0*funcPhiS;         
732   } else {                                        
733     const G4double varShat2 = varShat*varShat;    
734     const G4double varShat3 = varShat*varShat2    
735     const G4double varShat4 = varShat2*varShat    
736     // use Stanev approximation: for \psi(s) a    
737     if (varShat < 0.415827) {                     
738       funcPhiS = 1.0-G4Exp(-6.0*varShat*(1.0+v    
739                 + varShat3/(0.623+0.796*varSha    
740       // 1-\exp \left\{-4s-\frac{8s^2}{1+3.936    
741       const G4double funcPsiS = 1.0 - G4Exp(-4    
742                                - 8.0*varShat2/    
743                                - 0.05*varShat3    
744       // G(s) = 3 \psi(s) - 2 \phi(s)             
745       funcGS = 3.0*funcPsiS - 2.0*funcPhiS;       
746     } else if (varShat<1.55) {                    
747       funcPhiS = 1.0-G4Exp(-6.0*varShat*(1.0+v    
748                 + varShat3/(0.623+0.796*varSha    
749       const G4double dum0  = -0.160723            
750                              -1.798138*varShat    
751                              -0.120772*varShat    
752       funcGS = std::tanh(dum0);                   
753     } else {                                      
754       funcPhiS = 1.0-0.011905/varShat4;           
755       if (varShat<1.9156) {                       
756         const G4double dum0 = -0.160723           
757                               -1.798138*varSha    
758                               -0.120772*varSha    
759         funcGS = std::tanh(dum0);                 
760       } else {                                    
761         funcGS   = 1.0-0.023065/varShat4;         
762       }                                           
763     }                                             
764   }                                               
765 }                                                 
766                                                   
767 // s goes up to 2 with ds = 0.01 to be the def    
768 void G4eBremsstrahlungRelModel::InitLPMFunctio    
769 {                                                 
770   if (!fLPMFuncs->fIsInitialized) {               
771     const G4int num = fLPMFuncs->fSLimit*fLPMF    
772     fLPMFuncs->fLPMFuncG.resize(num);             
773     fLPMFuncs->fLPMFuncPhi.resize(num);           
774     for (G4int i = 0; i < num; ++i) {             
775       const G4double sval=i/fLPMFuncs->fISDelt    
776       ComputeLPMGsPhis(fLPMFuncs->fLPMFuncG[i]    
777     }                                             
778     fLPMFuncs->fIsInitialized = true;             
779   }                                               
780 }                                                 
781                                                   
782 void G4eBremsstrahlungRelModel::GetLPMFunction    
783                                                   
784                                                   
785 {                                                 
786   if (sval < fLPMFuncs->fSLimit) {                
787     G4double     val = sval*fLPMFuncs->fISDelt    
788     const G4int ilow = (G4int)val;                
789     val    -= ilow;                               
790     lpmGs   = (fLPMFuncs->fLPMFuncG[ilow+1]-fL    
791               + fLPMFuncs->fLPMFuncG[ilow];       
792     lpmPhis = (fLPMFuncs->fLPMFuncPhi[ilow+1]-    
793               + fLPMFuncs->fLPMFuncPhi[ilow];     
794   } else {                                        
795     G4double ss = sval*sval;                      
796     ss *= ss;                                     
797     lpmPhis = 1.0-0.01190476/ss;                  
798     lpmGs   = 1.0-0.0230655/ss;                   
799   }                                               
800 }                                                 
801                                                   
802