Geant4 Cross Reference

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


  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 // GEANT4 Class file                              
 29 //                                                
 30 //                                                
 31 // File name:     G4SeltzerBergerModel            
 32 //                                                
 33 // Author:        Vladimir Ivanchenko use inhe    
 34 //                base class implementing ultr    
 35 //                model                           
 36 //                                                
 37 // Creation date: 04.10.2011                      
 38 //                                                
 39 // Modifications:                                 
 40 //                                                
 41 // 24.07.2018 Introduced possibility to use sa    
 42 //            emitted photon energy (instead o    
 43 //            Seltzer-Berger scalled DCS for b    
 44 //            Using these sampling tables opti    
 45 //            state generation than the origin    
 46 //            extra memory (+ ~6MB in the case    
 47 //            (M Novak)                           
 48 //                                                
 49 // -------------------------------------------    
 50 //                                                
 51                                                   
 52 #include "G4SeltzerBergerModel.hh"                
 53 #include "G4PhysicalConstants.hh"                 
 54 #include "G4SystemOfUnits.hh"                     
 55 #include "Randomize.hh"                           
 56 #include "G4Material.hh"                          
 57 #include "G4Element.hh"                           
 58 #include "G4ElementVector.hh"                     
 59 #include "G4ParticleChangeForLoss.hh"             
 60 #include "G4SBBremTable.hh"                       
 61 #include "G4ModifiedTsai.hh"                      
 62                                                   
 63 #include "G4EmParameters.hh"                      
 64 #include "G4ProductionCutsTable.hh"               
 65 #include "G4Gamma.hh"                             
 66 #include "G4Electron.hh"                          
 67                                                   
 68 #include "G4Physics2DVector.hh"                   
 69 #include "G4Exp.hh"                               
 70 #include "G4Log.hh"                               
 71 #include "G4AutoLock.hh"                          
 72                                                   
 73 #include "G4ios.hh"                               
 74                                                   
 75 #include <fstream>                                
 76 #include <iomanip>                                
 77 #include <sstream>                                
 78 #include <thread>                                 
 79                                                   
 80 G4double G4SeltzerBergerModel::gYLimitData[] =    
 81 G4Physics2DVector* G4SeltzerBergerModel::gSBDC    
 82 G4SBBremTable* G4SeltzerBergerModel::gSBSampli    
 83                                                   
 84 // constant DCS factor: 16\alpha r_0^2/3          
 85 const G4double G4SeltzerBergerModel::gBremFact    
 86   = 16. * CLHEP::fine_structure_const * CLHEP:    
 87     * CLHEP::classic_electr_radius/3.;            
 88                                                   
 89 // Migdal's constant: 4\pi r_0*electron_reduce    
 90 const G4double G4SeltzerBergerModel::gMigdalCo    
 91   = 4. * CLHEP::pi * CLHEP::classic_electr_rad    
 92     * CLHEP::electron_Compton_length * CLHEP::    
 93                                                   
 94 static constexpr G4double twoMass = 2* CLHEP::    
 95 static constexpr G4double kAlpha = CLHEP::twop    
 96 static std::once_flag applyOnce;                  
 97                                                   
 98 namespace                                         
 99 {                                                 
100   G4Mutex theSBMutex = G4MUTEX_INITIALIZER;       
101                                                   
102   // for numerical integration on [0,1]           
103   const G4double gXGL[8] = {                      
104     1.98550718e-02, 1.01666761e-01, 2.37233795    
105     5.91717321e-01, 7.62766205e-01, 8.98333239    
106   };                                              
107   const G4double gWGL[8] = {                      
108     5.06142681e-02, 1.11190517e-01, 1.56853323    
109     1.81341892e-01, 1.56853323e-01, 1.11190517    
110   };                                              
111 }                                                 
112                                                   
113 G4SeltzerBergerModel::G4SeltzerBergerModel(con    
114                                            con    
115   : G4VEmModel(nam),                              
116     fGammaParticle(G4Gamma::Gamma()),             
117     fLowestKinEnergy(1.0*CLHEP::keV)              
118 {                                                 
119   SetLowEnergyLimit(fLowestKinEnergy);            
120   SetAngularDistribution(new G4ModifiedTsai())    
121   if (fPrimaryParticle != p) { SetParticle(p);    
122 }                                                 
123                                                   
124 G4SeltzerBergerModel::~G4SeltzerBergerModel()     
125 {                                                 
126   // delete SB-DCS data per Z                     
127   if (isInitializer) {                            
128     for (std::size_t iz = 0; iz < gMaxZet; ++i    
129       if (gSBDCSData[iz]) {                       
130         delete gSBDCSData[iz];                    
131         gSBDCSData[iz] = nullptr;                 
132       }                                           
133     }                                             
134     if (gSBSamplingTable) {                       
135       delete gSBSamplingTable;                    
136       gSBSamplingTable = nullptr;                 
137     }                                             
138   }                                               
139 }                                                 
140                                                   
141 void G4SeltzerBergerModel::Initialise(const G4    
142                                       const G4    
143 {                                                 
144   // parameters in each thread                    
145   if (fPrimaryParticle != p) {                    
146     SetParticle(p);                               
147   }                                               
148   fIsUseSamplingTables = G4EmParameters::Insta    
149   fCurrentIZ = 0;                                 
150                                                   
151   // initialise static tables for the Seltzer-    
152   std::call_once(applyOnce, [this]() { isIniti    
153                                                   
154   if (isInitializer) {                            
155     G4AutoLock l(&theSBMutex);                    
156                                                   
157     // initialisation per element is done only    
158     auto elemTable = G4Element::GetElementTabl    
159     for (auto const & elm : *elemTable) {         
160       G4int Z = std::max(1,std::min(elm->GetZa    
161       // load SB-DCS data for this atomic numb    
162       if (gSBDCSData[Z] == nullptr) ReadData(Z    
163     }                                             
164                                                   
165     // init sampling tables if it was requeste    
166     if (fIsUseSamplingTables) {                   
167       if (nullptr == gSBSamplingTable) {          
168         gSBSamplingTable = new G4SBBremTable()    
169       }                                           
170       gSBSamplingTable->Initialize(std::max(fL    
171                                    HighEnergyL    
172     }                                             
173     l.unlock();                                   
174   }                                               
175   // element selectors are initialized in the     
176   if (IsMaster()) {                               
177     InitialiseElementSelectors(p, cuts);          
178   }                                               
179   // initialisation in all threads                
180   if (nullptr == fParticleChange) {               
181     fParticleChange = GetParticleChangeForLoss    
182   }                                               
183   auto trmodel = GetTripletModel();               
184   if (nullptr != trmodel) {                       
185     trmodel->Initialise(p, cuts);                 
186     fIsScatOffElectron = true;                    
187   }                                               
188 }                                                 
189                                                   
190 void G4SeltzerBergerModel::InitialiseLocal(con    
191                                                   
192 {                                                 
193   SetElementSelectors(masterModel->GetElementS    
194 }                                                 
195                                                   
196 void G4SeltzerBergerModel::SetParticle(const G    
197 {                                                 
198   fPrimaryParticle = p;                           
199   fIsElectron = (p == G4Electron::Electron());    
200 }                                                 
201                                                   
202 void G4SeltzerBergerModel::ReadData(G4int Z) {    
203   // return if it has been already loaded         
204   if (gSBDCSData[Z] != nullptr) return;           
205                                                   
206   if (gSBDCSData[Z] == nullptr) {                 
207     std::ostringstream ost;                       
208     ost << G4EmParameters::Instance()->GetDirL    
209     std::ifstream fin(ost.str().c_str());         
210     if (!fin.is_open()) {                         
211       G4ExceptionDescription ed;                  
212       ed << "Bremsstrahlung data file <" << os    
213    << "> is not opened!";                         
214       G4Exception("G4SeltzerBergerModel::ReadD    
215       ed,"G4LEDATA version should be G4EMLOW6.    
216       return;                                     
217     }                                             
218     //G4cout << "G4SeltzerBergerModel read fro    
219     //         << ">" << G4endl;                  
220     auto v = new G4Physics2DVector();             
221     if (v->Retrieve(fin)) {                       
222       v->SetBicubicInterpolation(fIsUseBicubic    
223       static const G4double emaxlog = 4*G4Log(    
224       gYLimitData[Z] = v->Value(0.97, emaxlog,    
225       gSBDCSData[Z] = v;                          
226     } else {                                      
227       G4ExceptionDescription ed;                  
228       ed << "Bremsstrahlung data file <" << os    
229    << "> is not retrieved!";                      
230       G4Exception("G4SeltzerBergerModel::ReadD    
231       ed,"G4LEDATA version should be G4EMLOW6.    
232       delete v;                                   
233     }                                             
234   }                                               
235 }                                                 
236                                                   
237 // minimum primary (e-/e+) energy at which dis    
238 G4double G4SeltzerBergerModel::MinPrimaryEnerg    
239                                                   
240                                                   
241 {                                                 
242   return std::max(fLowestKinEnergy, cut);         
243 }                                                 
244                                                   
245 // Sets kinematical variables like E_kin, E_t     
246 // for characteristic photon energy k_p (more     
247 // k_p^2) for the Ter-Mikaelian suppression ef    
248 void G4SeltzerBergerModel::SetupForMaterial(co    
249                                             co    
250                                       G4double    
251 {                                                 
252   fDensityFactor = gMigdalConstant*mat->GetEle    
253   // calculate threshold for density effect: k    
254   fPrimaryKinEnergy = kinEnergy;                  
255   fPrimaryTotalEnergy = kinEnergy + CLHEP::ele    
256   fDensityCorr = fDensityFactor*fPrimaryTotalE    
257 }                                                 
258                                                   
259 // Computes the restricted dE/dx as the approp    
260 // element contributions that are computed by     
261 G4double                                          
262 G4SeltzerBergerModel::ComputeDEDXPerVolume(con    
263                                            con    
264                                            G4d    
265                                            G4d    
266 {                                                 
267   G4double dedx = 0.0;                            
268   if (nullptr == fPrimaryParticle) {              
269     SetParticle(p);                               
270   }                                               
271   if (kineticEnergy <= fLowestKinEnergy) {        
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 Z = (*theElemVector)[ie]->GetZasInt(    
290     fCurrentIZ = std::min(Z, gMaxZet);            
291     dedx += (Z*Z)*theAtomNumDensVector[ie]*Com    
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 // the ds/dk(Z,k) but ds/dk(Z,k)*[F*k/C] is co    
311 // (i)    what we need here is ds/dk*k and not    
312 // (ii)   the Ter-Mikaelian suppression i.e. F    
313 // (iii)  the constant factor C (includes Z^2     
314 G4double G4SeltzerBergerModel::ComputeBremLoss    
315 {                                                 
316   // number of intervals and integration step     
317   const G4double alphaMax = tmax/fPrimaryTotal    
318   const G4int nSub = (G4int)(20*alphaMax)+3;      
319   const G4double delta = alphaMax/((G4double)n    
320   // set minimum value of the first sub-inteva    
321   G4double alpha_i = 0.0;                         
322   G4double dedxInteg = 0.0;                       
323   for (G4int l = 0; l < nSub; ++l) {              
324     for (G4int igl = 0; igl < 8; ++igl) {         
325       // compute the emitted photon energy k      
326       const G4double k   = (alpha_i+gXGL[igl]*    
327       // compute the DCS value at k (without t    
328       const G4double dcs = ComputeDXSectionPer    
329       // account Ter-Mikaelian suppression: ti    
330       dedxInteg += gWGL[igl]*dcs/(1.0+fDensity    
331     }                                             
332     // update sub-interval minimum value          
333     alpha_i += delta;                             
334   }                                               
335   // apply corrections due to variable transfo    
336   dedxInteg *= delta*fPrimaryTotalEnergy;         
337   return std::max(dedxInteg,0.);                  
338 }                                                 
339                                                   
340 // Computes restrected atomic cross section by    
341 // DCS between the proper kinematical limits a    
342 G4double                                          
343 G4SeltzerBergerModel::ComputeCrossSectionPerAt    
344              G4double kineticEnergy,              
345              G4double Z,                          
346              G4double,                            
347              G4double cut,                        
348              G4double maxEnergy)                  
349 {                                                 
350   G4double crossSection = 0.0;                    
351   if (nullptr == fPrimaryParticle) {              
352     SetParticle(p);                               
353   }                                               
354   if (kineticEnergy <= fLowestKinEnergy) {        
355     return crossSection;                          
356   }                                               
357   // min/max kinetic energy limits of the DCS     
358   const G4double tmin = std::min(cut, kineticE    
359   const G4double tmax = std::min(maxEnergy, ki    
360   // zero restricted x-section if e- kinetic e    
361   if (tmin >= tmax) {                             
362     return crossSection;                          
363   }                                               
364   fCurrentIZ = std::min(G4lrint(Z), gMaxZet);     
365   // integrate numerically (dependent part of)    
366   // a. integrate between tmin and kineticEner    
367   crossSection = ComputeXSectionPerAtom(tmin);    
368   // allow partial integration: only if maxEne    
369   // b. integrate between tmax and kineticEner    
370   // (so the result in this case is the integr    
371   // maxEnergy)                                   
372   if (tmax < kineticEnergy) {                     
373     crossSection -= ComputeXSectionPerAtom(tma    
374   }                                               
375   // multiply with the constant factors: 16\al    
376   crossSection *= Z*Z*gBremFactor;                
377   return std::max(crossSection, 0.);              
378 }                                                 
379                                                   
380 // Numerical integral of the (k dependent part    
381 // k_max = E_k (where E_k is the kinetic energ    
382 // minimum of energy of the  emitted photon).     
383 // transformed alpha(k) = ln(k/E_t) variable (    
384 // the primary e-). The integration range is d    
385 // delta = [ln(k_min/E_t)-ln(k_max/E_t)]/n wid    
386 // on [0,1] is applied on each sub-inteval so     
387 // xi(alpha) = xi(k) = [ln(k/E_t)-alpha_i]/del    
388 // (i-1)*delta for the i = 1,2,..,n-th sub-int    
389 // sub-intevals. From the transformed xi, k(xi    
390 // Since the integration is done in variable x    
391 // transformation results in a multiplicative     
392 // However, DCS differential in k is ~1/k so t    
393 // becomes delta and the 1/k factor is dropped    
394 // Ter-Mikaelian suppression is always account    
395 G4double G4SeltzerBergerModel::ComputeXSection    
396 {                                                 
397   G4double xSection = 0.0;                        
398   const G4double alphaMin = G4Log(tmin/fPrimar    
399   const G4double alphaMax = G4Log(fPrimaryKinE    
400   const G4int    nSub = (G4int)(0.45*(alphaMax    
401   const G4double delta = (alphaMax-alphaMin)/(    
402   // set minimum value of the first sub-inteva    
403   G4double alpha_i = alphaMin;                    
404   for (G4int l = 0; l < nSub; ++l) {              
405     for (G4int igl = 0; igl < 8; ++igl) {         
406       // compute the emitted photon energy k      
407       const G4double k = G4Exp(alpha_i+gXGL[ig    
408       // compute the DCS value at k (without t    
409       const G4double dcs = ComputeDXSectionPer    
410       // account Ter-Mikaelian suppression: ti    
411       xSection += gWGL[igl]*dcs/(1.0+fDensityC    
412     }                                             
413     // update sub-interval minimum value          
414     alpha_i += delta;                             
415   }                                               
416   // apply corrections due to variable transfo    
417   xSection *= delta;                              
418   // final check                                  
419   return std::max(xSection, 0.);                  
420 }                                                 
421                                                   
422 G4double G4SeltzerBergerModel::ComputeDXSectio    
423 {                                                 
424   G4double dxsec = 0.0;                           
425   if (gammaEnergy < 0.0 || fPrimaryKinEnergy <    
426     return dxsec;                                 
427   }                                               
428   // reduced photon energy                        
429   const G4double x = gammaEnergy/fPrimaryKinEn    
430   // l-kinetic energy of the e-/e+                
431   const G4double y = G4Log(fPrimaryKinEnergy/C    
432   // make sure that the Z-related SB-DCS are l    
433   // NOTE: fCurrentIZ should have been set bef    
434   fCurrentIZ = std::max(std::min(fCurrentIZ, g    
435   if (nullptr == gSBDCSData[fCurrentIZ]) {        
436     G4AutoLock l(&theSBMutex);                    
437     ReadData(fCurrentIZ);                         
438     l.unlock();                                   
439   }                                               
440   // NOTE: SetupForMaterial should have been c    
441   const G4double pt2 = fPrimaryKinEnergy*(fPri    
442   const G4double invb2 = fPrimaryTotalEnergy*f    
443   G4double val = gSBDCSData[fCurrentIZ]->Value    
444   dxsec = val*invb2*CLHEP::millibarn/gBremFact    
445   // e+ correction                                
446   if (!fIsElectron) {                             
447     const G4double invbeta1 = std::sqrt(invb2)    
448     const G4double e2 = fPrimaryKinEnergy - ga    
449     if (e2 > 0.0) {                               
450       const G4double invbeta2 =                   
451   (e2 + CLHEP::electron_mass_c2)/std::sqrt(e2*    
452       const G4double dum0 = kAlpha*fCurrentIZ*    
453       if (dum0 < gExpNumLimit) {                  
454         dxsec = 0.0;                              
455       } else {                                    
456         dxsec *= G4Exp(dum0);                     
457       }                                           
458     } else {                                      
459       dxsec = 0.0;                                
460     }                                             
461   }                                               
462   return dxsec;                                   
463 }                                                 
464                                                   
465 void                                              
466 G4SeltzerBergerModel::SampleSecondaries(std::v    
467                                          const    
468                                          const    
469                                          G4dou    
470                                          G4dou    
471 {                                                 
472   const G4double kinEnergy = dp->GetKineticEne    
473   const G4double logKinEnergy = dp->GetLogKine    
474   const G4double tmin = std::min(cutEnergy, ki    
475   const G4double tmax = std::min(maxEnergy, ki    
476   if (tmin >= tmax) {                             
477     return;                                       
478   }                                               
479   // set local variables and select target ele    
480   SetupForMaterial(fPrimaryParticle, couple->G    
481   const G4Element* elm = SelectTargetAtom(coup    
482                                           logK    
483   fCurrentIZ = std::max(std::min(elm->GetZasIn    
484   //                                              
485   const G4double totMomentum = std::sqrt(kinEn    
486   /*                                              
487   G4cout << "G4SeltzerBergerModel::SampleSecon    
488          << kinEnergy/MeV                         
489          << " Z= " << fCurrentIZ << " cut(MeV)    
490          << " emax(MeV)= " << tmax/MeV << " co    
491   */                                              
492   // sample emitted photon energy either by re    
493   const G4double gammaEnergy = !fIsUseSampling    
494         ? SampleEnergyTransfer(kinEnergy, logK    
495         : gSBSamplingTable->SampleEnergyTransf    
496                      fDensityCorr, fCurrentIZ,    
497   // should never happen under normal conditio    
498   if (gammaEnergy <= 0.) {                        
499     return;                                       
500   }                                               
501   //                                              
502   // angles of the emitted gamma. ( Z - axis a    
503   // general interface                            
504   G4ThreeVector gamDir = GetAngularDistributio    
505    fPrimaryTotalEnergy-gammaEnergy, fCurrentIZ    
506   // create G4DynamicParticle object for the e    
507   auto gamma = new G4DynamicParticle(fGammaPar    
508   vdp->push_back(gamma);                          
509   //                                              
510   // compute post-interaction kinematics of th    
511   G4ThreeVector dir =                             
512     (totMomentum*dp->GetMomentumDirection() -     
513   const G4double finalE = kinEnergy - gammaEne    
514   /*                                              
515   G4cout << "### G4SBModel: v= "                  
516          << " Eg(MeV)= " << gammaEnergy           
517          << " Ee(MeV)= " << kineticEnergy         
518          << " DirE " << direction << " DirG "     
519          << G4endl;                               
520   */                                              
521   // if secondary gamma energy is higher than     
522   // then stop tracking the primary particle a    
523   // instead of the primary                       
524   if (gammaEnergy > SecondaryThreshold()) {       
525     fParticleChange->ProposeTrackStatus(fStopA    
526     fParticleChange->SetProposedKineticEnergy(    
527     auto el = new G4DynamicParticle(              
528               const_cast<G4ParticleDefinition*    
529     vdp->push_back(el);                           
530   } else { // continue tracking the primary e-    
531     fParticleChange->SetProposedMomentumDirect    
532     fParticleChange->SetProposedKineticEnergy(    
533   }                                               
534 }                                                 
535                                                   
536 // sample emitted photon energy by usign rejec    
537 G4double                                          
538 G4SeltzerBergerModel::SampleEnergyTransfer(con    
539                                            con    
540                                            con    
541                                            con    
542 {                                                 
543   // min max of the transformed variable: x(k)    
544   // [ln(k_c^2+k_p^2), ln(E_k^2+k_p^2)]           
545   const G4double xmin   = G4Log(tmin*tmin+fDen    
546   const G4double xrange = G4Log(tmax*tmax+fDen    
547   const G4double y      = logKinEnergy;           
548   // majoranta                                    
549   const G4double x0 = tmin/kinEnergy;             
550   G4double vmax;                                  
551   if (nullptr == gSBDCSData[fCurrentIZ]) {        
552     ReadData(fCurrentIZ);                         
553   }                                               
554   vmax = gSBDCSData[fCurrentIZ]->Value(x0, y,     
555   //                                              
556   static const G4double kEPeakLim = 300.*CLHEP    
557   static const G4double kELowLim  =  20.*CLHEP    
558   // majoranta corrected for e-                   
559   if (fIsElectron && x0 < 0.97 &&                 
560       ((kinEnergy>kEPeakLim) || (kinEnergy<kEL    
561     G4double ylim = std::min(gYLimitData[fCurr    
562                          1.1*gSBDCSData[fCurre    
563     vmax = std::max(vmax, ylim);                  
564   }                                               
565   if (x0 < 0.05) {                                
566     vmax *= 1.2;                                  
567   }                                               
568   //G4cout<<"y= "<<y<<" xmin= "<<xmin<<" xmax=    
569   //<<" vmax= "<<vmax<<G4endl;                    
570   static const G4int kNCountMax = 100;            
571   CLHEP::HepRandomEngine* rndmEngine = G4Rando    
572   G4double rndm[2];                               
573   G4double gammaEnergy, v;                        
574   for (G4int nn = 0; nn < kNCountMax; ++nn) {     
575     rndmEngine->flatArray(2, rndm);               
576     gammaEnergy =                                 
577       std::sqrt(std::max(G4Exp(xmin + rndm[0]*    
578     v = gSBDCSData[fCurrentIZ]->Value(gammaEne    
579     // e+ correction                              
580     if (!fIsElectron) {                           
581       const G4double e1 = kinEnergy - tmin;       
582       const G4double invbeta1 =                   
583   (e1 + CLHEP::electron_mass_c2)/std::sqrt(e1*    
584       const G4double       e2 = kinEnergy-gamm    
585       const G4double invbeta2 =                   
586   (e2 + CLHEP::electron_mass_c2)/std::sqrt(e2*    
587       const G4double     dum0 = kAlpha*fCurren    
588       if (dum0 < gExpNumLimit) {                  
589         v = 0.0;                                  
590       } else {                                    
591         v *= G4Exp(dum0);                         
592       }                                           
593     }                                             
594     if (v > 1.05*vmax && fNumWarnings < 11) {     
595       ++fNumWarnings;                             
596       G4ExceptionDescription ed;                  
597       ed << "### G4SeltzerBergerModel Warning:    
598          << v << " > " << vmax << " by " << v/    
599          << " Niter= " << nn                      
600          << " Egamma(MeV)= " << gammaEnergy       
601          << " Ee(MeV)= " << kinEnergy             
602          << " Z= " << fCurrentIZ << "  " << fP    
603       //                                          
604       if (10 == fNumWarnings) {                   
605         ed << "\n ### G4SeltzerBergerModel War    
606       }                                           
607       G4Exception("G4SeltzerBergerModel::Sampl    
608                   JustWarning, ed,"");            
609     }                                             
610     if (v >= vmax*rndm[1]) {                      
611       break;                                      
612     }                                             
613   }                                               
614   return gammaEnergy;                             
615 }                                                 
616