Geant4 Cross Reference

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


  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 implementation file               
 30 //                                                
 31 // File name:     G4GoudsmitSaundersonTable       
 32 //                                                
 33 // Author:        Mihaly Novak / (Omrane Kadri    
 34 //                                                
 35 // Creation date: 20.02.2009                      
 36 //                                                
 37 // Class description:                             
 38 //   Class to handle multiple scattering angul    
 39 //   using Kawrakow-Bielajew Goudsmit-Saunders    
 40 //   Rutherford DCS for elastic scattering of     
 41 //   class is used by G4GoudsmitSaundersonMscM    
 42 //   deflection of electrons/positrons after t    
 43 //                                                
 44 // Modifications:                                 
 45 // 04.03.2009 V.Ivanchenko cleanup and format     
 46 // 26.08.2009 O.Kadri: avoiding unuseful calcu    
 47 //                     finding parameter error    
 48 // 08.02.2010 O.Kadri: reduce delared variable    
 49 //                     in secant method           
 50 // 26.03.2010 O.Kadri: minimum of used arrays     
 51 //                     finding method the erro    
 52 // 12.05.2010 O.Kadri: changing of sqrt((b-a)*    
 53 // 18.05.2015 M. Novak This class has been com    
 54 //            class name was kept; class descr    
 55 //            A new version of Kawrakow-Bielaj    
 56 //            based on the screened Rutherford    
 57 //            electrons/positrons has been int    
 58 //            angular distributions over a 2D     
 59 //            and the CDFs are now stored in a    
 60 //            together with the corresponding     
 61 //            The new version is several times    
 62 //            compared to the earlier version     
 63 //            that use these data has been als    
 64 // 28.04.2017 M. Novak: New representation of     
 65 //            significantly reduced data size.    
 66 // 23.08.2017 M. Novak: Added funtionality to     
 67 //            base GS angular distributions an    
 68 //            parameter, first and second mome    
 69 //            activated in the GS-MSC model.      
 70 //                                                
 71 // References:                                    
 72 //   [1] A.F.Bielajew, NIMB, 111 (1996) 195-20    
 73 //   [2] I.Kawrakow, A.F.Bielajew, NIMB 134(19    
 74 //                                                
 75 // -------------------------------------------    
 76                                                   
 77 #include "G4GoudsmitSaundersonTable.hh"           
 78                                                   
 79                                                   
 80 #include "G4PhysicalConstants.hh"                 
 81 #include "Randomize.hh"                           
 82 #include "G4Log.hh"                               
 83 #include "G4Exp.hh"                               
 84                                                   
 85 #include "G4GSMottCorrection.hh"                  
 86 #include "G4MaterialTable.hh"                     
 87 #include "G4Material.hh"                          
 88 #include "G4MaterialCutsCouple.hh"                
 89 #include "G4ProductionCutsTable.hh"               
 90 #include "G4EmParameters.hh"                      
 91                                                   
 92 #include "G4String.hh"                            
 93                                                   
 94 #include <fstream>                                
 95 #include <cstdlib>                                
 96 #include <cmath>                                  
 97                                                   
 98 #include <iostream>                               
 99 #include <iomanip>                                
100                                                   
101 // perecomputed GS angular distributions, base    
102 // are the same for e- and e+ so make sure we     
103 G4bool G4GoudsmitSaundersonTable::gIsInitialis    
104 //                                                
105 std::vector<G4GoudsmitSaundersonTable::GSMSCAn    
106 std::vector<G4GoudsmitSaundersonTable::GSMSCAn    
107 //                                                
108 std::vector<double> G4GoudsmitSaundersonTable:    
109 std::vector<double> G4GoudsmitSaundersonTable:    
110                                                   
111                                                   
112 G4GoudsmitSaundersonTable::G4GoudsmitSaunderso    
113   fIsElectron         = iselectron;               
114   // set initial values: final values will be     
115   fLogLambda0         = 0.;              // wi    
116   fLogDeltaLambda     = 0.;              // wi    
117   fInvLogDeltaLambda  = 0.;              // wi    
118   fInvDeltaQ1         = 0.;              // wi    
119   fDeltaQ2            = 0.;              // wi    
120   fInvDeltaQ2         = 0.;              // wi    
121   //                                              
122   fLowEnergyLimit     =   0.1*CLHEP::keV; // w    
123   fHighEnergyLimit    = 100.0*CLHEP::MeV; // w    
124   //                                              
125   fIsMottCorrection   = false;            // w    
126   fIsPWACorrection    = false;            // w    
127   fMottCorrection     = nullptr;                  
128   //                                              
129   fNumSPCEbinPerDec   = 3;                        
130 }                                                 
131                                                   
132 G4GoudsmitSaundersonTable::~G4GoudsmitSaunders    
133   for (std::size_t i=0; i<gGSMSCAngularDistrib    
134     if (gGSMSCAngularDistributions1[i]) {         
135       delete [] gGSMSCAngularDistributions1[i]    
136       delete [] gGSMSCAngularDistributions1[i]    
137       delete [] gGSMSCAngularDistributions1[i]    
138       delete gGSMSCAngularDistributions1[i];      
139     }                                             
140   }                                               
141   gGSMSCAngularDistributions1.clear();            
142   for (std::size_t i=0; i<gGSMSCAngularDistrib    
143     if (gGSMSCAngularDistributions2[i]) {         
144       delete [] gGSMSCAngularDistributions2[i]    
145       delete [] gGSMSCAngularDistributions2[i]    
146       delete [] gGSMSCAngularDistributions2[i]    
147       delete gGSMSCAngularDistributions2[i];      
148     }                                             
149   }                                               
150   gGSMSCAngularDistributions2.clear();            
151   if (fMottCorrection) {                          
152     delete fMottCorrection;                       
153     fMottCorrection = nullptr;                    
154   }                                               
155   // clear scp correction data                    
156   for (std::size_t imc=0; imc<fSCPCPerMatCuts.    
157     if (fSCPCPerMatCuts[imc]) {                   
158       fSCPCPerMatCuts[imc]->fVSCPC.clear();       
159       delete fSCPCPerMatCuts[imc];                
160     }                                             
161   }                                               
162   fSCPCPerMatCuts.clear();                        
163   //                                              
164   gIsInitialised = false;                         
165 }                                                 
166                                                   
167 void G4GoudsmitSaundersonTable::Initialise(G4d    
168   fLowEnergyLimit     = lownergylimit;            
169   fHighEnergyLimit    = highenergylimit;          
170   G4double lLambdaMin = G4Log(gLAMBMIN);          
171   G4double lLambdaMax = G4Log(gLAMBMAX);          
172   fLogLambda0         = lLambdaMin;               
173   fLogDeltaLambda     = (lLambdaMax-lLambdaMin    
174   fInvLogDeltaLambda  = 1./fLogDeltaLambda;       
175   fInvDeltaQ1         = 1./((gQMAX1-gQMIN1)/(g    
176   fDeltaQ2            = (gQMAX2-gQMIN2)/(gQNUM    
177   fInvDeltaQ2         = 1./fDeltaQ2;              
178   // load precomputed angular distributions an    
179   // these are particle independet => they go     
180   if (!gIsInitialised) {                          
181     // load pre-computed GS angular distributi    
182     LoadMSCData();                                
183     gIsInitialised = true;                        
184   }                                               
185   InitMoliereMSCParams();                         
186   // Mott-correction: particle(e- or e+) depen    
187   if (fIsMottCorrection) {                        
188     if (!fMottCorrection) {                       
189       fMottCorrection = new G4GSMottCorrection    
190     }                                             
191     fMottCorrection->Initialise();                
192   }                                               
193   // init scattering power correction data; us    
194   // (Moliere's parameters must be initialised    
195   if (fMottCorrection) {                          
196     InitSCPCorrection();                          
197   }                                               
198 }                                                 
199                                                   
200                                                   
201 // samplig multiple scattering angles cos(thet    
202 //  - including no-scattering, single, "few" s    
203 //  - Mott-correction will be included if it w    
204 // lambdaval : s/lambda_el                        
205 // qval      : s/lambda_el G1                     
206 // scra      : screening parameter                
207 // cost      : will be the smapled cos(theta)     
208 // sint      : will be the smapled sin(theta)     
209 // lekin     : logarithm of the current kineti    
210 // beta2     : the corresponding beta square      
211 // matindx   : index of the current material      
212 // returns true if it was msc                     
213 G4bool G4GoudsmitSaundersonTable::Sampling(G4d    
214                                            G4d    
215                                            GSM    
216                                            G4d    
217   G4double rand0 = G4UniformRand();               
218   G4double expn  = G4Exp(-lambdaval);             
219   //                                              
220   // no scattering case                           
221   if (rand0<expn) {                               
222     cost = 1.0;                                   
223     sint = 0.0;                                   
224     return false;                                 
225   }                                               
226   //                                              
227   // single scattering case : sample from the     
228   // - Mott-correction will be included if it     
229   if (rand0<(1.+lambdaval)*expn) {                
230     // cost is sampled in SingleScattering()      
231     cost = SingleScattering(lambdaval, scra, l    
232     // add protections                            
233     if (cost<-1.0) cost = -1.0;                   
234     if (cost>1.0)  cost =  1.0;                   
235     // compute sin(theta) from the sampled cos    
236     G4double dum0 = 1.-cost;                      
237     sint = std::sqrt(dum0*(2.0-dum0));            
238     return false;                                 
239   }                                               
240   //                                              
241   // handle this case:                            
242   //      -lambdaval < 1 i.e. mean #elastic ev    
243   //       the currently sampled case is not 0    
244   //       lambdaval (that we have precomputed    
245   //       stored in a form of equally probabe    
246   //       interp. parameters) is 1.]             
247   //      -probability of having n elastic eve    
248   //       lambdaval parameter.                   
249   //      -the max. probability (when lambdava    
250   //       elastic events is 0.2642411 and the    
251   //       events decays rapidly with n. So se    
252   //      -sampling of this cases is done in a    
253   //       where the current #elastic event is    
254   if (lambdaval<1.0) {                            
255     G4double prob, cumprob;                       
256     prob = cumprob = expn;                        
257     G4double curcost,cursint;                     
258     // init cos(theta) and sin(theta) to the z    
259     cost = 1.0;                                   
260     sint = 0.0;                                   
261     for (G4int iel=1; iel<10; ++iel) {            
262       // prob of having iel scattering from Po    
263       prob    *= lambdaval/(G4double)iel;         
264       cumprob += prob;                            
265       //                                          
266       //sample cos(theta) from the singe scatt    
267       // - Mott-correction will be included if    
268       curcost       = SingleScattering(lambdav    
269       G4double dum0 = 1.-curcost;                 
270       cursint       = dum0*(2.0-dum0); // sin^    
271       //                                          
272       // if we got current deflection that is     
273       // then update cos(theta) sin(theta)        
274       if (cursint>1.0e-20) {                      
275         cursint         = std::sqrt(cursint);     
276         G4double curphi = CLHEP::twopi*G4Unifo    
277         cost            = cost*curcost-sint*cu    
278         sint            = std::sqrt(std::max(0    
279       }                                           
280       //                                          
281       // check if we have done enough scatteri    
282       if (rand0<cumprob) {                        
283         return false;                             
284       }                                           
285     }                                             
286     // if reached the max iter i.e. 10            
287     return false;                                 
288   }                                               
289   //                                              
290   // multiple scattering case with lambdavalue    
291   //   - use the precomputed and transformed G    
292   //     distributions to sample cos(theta)       
293   //   - Mott-correction will be included if i    
294   cost = SampleCosTheta(lambdaval, qval, scra,    
295   // add protections                              
296   if (cost<-1.0)  cost = -1.0;                    
297   if (cost> 1.0)  cost =  1.0;                    
298   // compute cos(theta) and sin(theta) from th    
299   G4double dum0 = 1.0-cost;                       
300   sint = std::sqrt(dum0*(2.0-dum0));              
301   // return true if it was msc                    
302   return true;                                    
303 }                                                 
304                                                   
305                                                   
306 G4double G4GoudsmitSaundersonTable::SampleCosT    
307                                                   
308                                                   
309                                                   
310   G4double cost = 1.;                             
311   // determine the base GS angular distributio    
312   if (isfirst) {                                  
313     *gsDtr = GetGSAngularDtr(scra, lambdaval,     
314   }                                               
315   // sample cost from the GS angular distribut    
316   cost = SampleGSSRCosTheta(*gsDtr, transfPar)    
317   // Mott-correction if it was requested by th    
318   if (fIsMottCorrection && *gsDtr) {     // no    
319     static const G4int nlooplim = 1000;           
320     G4int    nloop    =  0 ; // rejection loop    
321 //    G4int    ekindx   = -1; // evaluate only    
322 //    G4int    deltindx = -1 ; // evaluate onl    
323     G4double val      = fMottCorrection->GetMo    
324     while (G4UniformRand()>val && ++nloop<nloo    
325       // sampling cos(theta)                      
326       cost = SampleGSSRCosTheta(*gsDtr, transf    
327       val  = fMottCorrection->GetMottRejection    
328     };                                            
329   }                                               
330   return cost;                                    
331 }                                                 
332                                                   
333                                                   
334 // returns with cost sampled from the GS angul    
335 G4double G4GoudsmitSaundersonTable::SampleGSSR    
336   // check if isotropic theta (i.e. cost is un    
337   if (!gsDtr) {                                   
338     return 1.-2.0*G4UniformRand();                
339   }                                               
340   //                                              
341   // sampling form the selected distribution      
342   G4double ndatm1 = gsDtr->fNumData-1.;           
343   G4double delta  = 1.0/ndatm1;                   
344   // determine lower cumulative bin inidex        
345   G4double rndm   = G4UniformRand();              
346   G4int indxl     = rndm*ndatm1;                  
347   G4double  aval  = rndm-indxl*delta;             
348   G4double  dum0  = delta*aval;                   
349                                                   
350   G4double  dum1  = (1.0+gsDtr->fParamA[indxl]    
351   G4double  dum2  = delta*delta + gsDtr->fPara    
352   G4double sample = gsDtr->fUValues[indxl] +      
353   // transform back u to cos(theta) :             
354   // this is the sampled cos(theta) = (2.0*par    
355   return 1.-(2.0*transfpar*sample)/(1.0-sample    
356 }                                                 
357                                                   
358                                                   
359 // determine the GS angular distribution we ne    
360 G4GoudsmitSaundersonTable::GSMSCAngularDtr* G4    
361                                                   
362   GSMSCAngularDtr *dtr = nullptr;                 
363   G4bool first         = false;                   
364   // isotropic cost above gQMAX2 (i.e. dtr sta    
365   if (qval<gQMAX2) {                              
366     G4int    lamIndx  = -1; // lambda value in    
367     G4int    qIndx    = -1; // lambda value in    
368     // init to second grid Q values               
369     G4int    numQVal  = gQNUM2;                   
370     G4double minQVal  = gQMIN2;                   
371     G4double invDelQ  = fInvDeltaQ2;              
372     G4double pIndxH   = 0.; // probability of     
373     // check if first or second grid needs to     
374     if (qval<gQMIN2) {  // first grid             
375       first = true;                               
376       // protect against qval<gQMIN1              
377       if (qval<gQMIN1) {                          
378         qval   = gQMIN1;                          
379         qIndx  = 0;                               
380         //pIndxH = 0.;                            
381       }                                           
382       // set to first grid Q values               
383       numQVal  = gQNUM1;                          
384       minQVal  = gQMIN1;                          
385       invDelQ  = fInvDeltaQ1;                     
386     }                                             
387     // make sure that lambda = s/lambda_el is     
388     // lambda<gLAMBMIN=1 is already handeled b    
389     if (lambdaval>=gLAMBMAX) {                    
390       lambdaval = gLAMBMAX-1.e-8;                 
391       lamIndx   = gLAMBNUM-1;                     
392     }                                             
393     G4double lLambda  = G4Log(lambdaval);         
394     //                                            
395     // determine lower lambda (=s/lambda_el) i    
396     if (lamIndx<0) {                              
397       pIndxH  = (lLambda-fLogLambda0)*fInvLogD    
398       lamIndx = (G4int)(pIndxH);        // low    
399       pIndxH  = pIndxH-lamIndx;       // proba    
400       if (G4UniformRand()<pIndxH) {               
401         ++lamIndx;                                
402       }                                           
403     }                                             
404     //                                            
405     // determine lower Q (=s/lambda_el G1) ind    
406     if (qIndx<0) {                                
407       pIndxH  = (qval-minQVal)*invDelQ;           
408       qIndx   = (G4int)(pIndxH);        // low    
409       pIndxH  = pIndxH-qIndx;                     
410       if (G4UniformRand()<pIndxH) {               
411         ++qIndx;                                  
412       }                                           
413     }                                             
414     // set indx                                   
415     G4int indx = lamIndx*numQVal+qIndx;           
416     if (first) {                                  
417       dtr = gGSMSCAngularDistributions1[indx];    
418     } else {                                      
419       dtr = gGSMSCAngularDistributions2[indx];    
420     }                                             
421     // dtr might be nullptr that indicates iso    
422     // - if the selected lamIndx, qIndx corres    
423     //   G1 should always be < 1 and if G1 is     
424     //                                            
425     // compute the transformation parameter       
426     if (lambdaval>10.0) {                         
427       transfpar = 0.5*(-2.77164+lLambda*( 2.94    
428     } else {                                      
429       transfpar = 0.5*(1.347+lLambda*(0.209364    
430     }                                             
431     transfpar *= (lambdaval+4.0)*scra;            
432   }                                               
433   // return with the selected GS angular distr    
434   return dtr;                                     
435 }                                                 
436                                                   
437                                                   
438 void G4GoudsmitSaundersonTable::LoadMSCData()     
439   gGSMSCAngularDistributions1.resize(gLAMBNUM*    
440   const G4String str1 = G4EmParameters::Instan    
441   for (G4int il=0; il<gLAMBNUM; ++il) {           
442     G4String fname = str1 + std::to_string(il)    
443     std::ifstream infile(fname,std::ios::in);     
444     if (!infile.is_open()) {                      
445       G4String msgc = "Cannot open file: " + f    
446       G4Exception("G4GoudsmitSaundersonTable::    
447       FatalException, msgc.c_str());              
448       return;                                     
449     }                                             
450     for (G4int iq=0; iq<gQNUM1; ++iq) {           
451       auto gsd = new GSMSCAngularDtr();           
452       infile >> gsd->fNumData;                    
453       gsd->fUValues = new G4double[gsd->fNumDa    
454       gsd->fParamA  = new G4double[gsd->fNumDa    
455       gsd->fParamB  = new G4double[gsd->fNumDa    
456       G4double ddummy;                            
457       infile >> ddummy; infile >> ddummy;         
458       for (G4int i=0; i<gsd->fNumData; ++i) {     
459         infile >> gsd->fUValues[i];               
460         infile >> gsd->fParamA[i];                
461         infile >> gsd->fParamB[i];                
462       }                                           
463       gGSMSCAngularDistributions1[il*gQNUM1+iq    
464     }                                             
465     infile.close();                               
466   }                                               
467   //                                              
468   // second grid                                  
469   gGSMSCAngularDistributions2.resize(gLAMBNUM*    
470   const G4String str2 = G4EmParameters::Instan    
471   for (G4int il=0; il<gLAMBNUM; ++il) {           
472     G4String fname = str2 + std::to_string(il)    
473     std::ifstream infile(fname,std::ios::in);     
474     if (!infile.is_open()) {                      
475       G4String msgc = "Cannot open file: " + f    
476       G4Exception("G4GoudsmitSaundersonTable::    
477       FatalException, msgc.c_str());              
478       return;                                     
479     }                                             
480     for (G4int iq=0; iq<gQNUM2; ++iq) {           
481       G4int numData;                              
482       infile >> numData;                          
483       if (numData>1) {                            
484         auto gsd = new GSMSCAngularDtr();         
485         gsd->fNumData = numData;                  
486         gsd->fUValues = new G4double[gsd->fNum    
487         gsd->fParamA  = new G4double[gsd->fNum    
488         gsd->fParamB  = new G4double[gsd->fNum    
489         double ddummy;                            
490         infile >> ddummy; infile >> ddummy;       
491         for (G4int i=0; i<gsd->fNumData; ++i)     
492           infile >> gsd->fUValues[i];             
493           infile >> gsd->fParamA[i];              
494           infile >> gsd->fParamB[i];              
495         }                                         
496         gGSMSCAngularDistributions2[il*gQNUM2+    
497       } else {                                    
498         gGSMSCAngularDistributions2[il*gQNUM2+    
499       }                                           
500     }                                             
501     infile.close();                               
502   }                                               
503 }                                                 
504                                                   
505 // samples cost in single scattering based on     
506 // (with Mott-correction if it was requested)     
507 G4double G4GoudsmitSaundersonTable::SingleScat    
508                                                   
509                                                   
510   G4double rand1 = G4UniformRand();               
511   // sample cost from the Screened-Rutherford     
512   G4double cost  = 1.-2.0*scra*rand1/(1.0-rand    
513   // Mott-correction if it was requested by th    
514   if (fIsMottCorrection) {                        
515     static const G4int nlooplim = 1000;  // re    
516     G4int    nloop    =  0 ; // loop counter      
517     G4int    ekindx   = -1 ; // evaluate only     
518     G4int    deltindx =  0 ; // single scatter    
519     G4double q1       =  0.; // not used when     
520     // computing Mott rejection function value    
521     G4double val      = fMottCorrection->GetMo    
522                                                   
523     while (G4UniformRand()>val && ++nloop<nloo    
524       // sampling cos(theta) from the Screened    
525       rand1 = G4UniformRand();                    
526       cost  = 1.-2.0*scra*rand1/(1.0-rand1+scr    
527       // computing Mott rejection function val    
528       val   = fMottCorrection->GetMottRejectio    
529                                                   
530     };                                            
531   }                                               
532   return cost;                                    
533 }                                                 
534                                                   
535                                                   
536 void  G4GoudsmitSaundersonTable::GetMottCorrec    
537                                                   
538                                                   
539   if (fIsMottCorrection) {                        
540     fMottCorrection->GetMottCorrectionFactors(    
541   }                                               
542 }                                                 
543                                                   
544                                                   
545 // compute material dependent Moliere MSC para    
546 void G4GoudsmitSaundersonTable::InitMoliereMSC    
547    const G4double const1   = 7821.6;      // [    
548    const G4double const2   = 0.1569;      // [    
549    const G4double finstrc2 = 5.325135453E-5; /    
550                                                   
551    G4MaterialTable* theMaterialTable = G4Mater    
552    // get number of materials in the table        
553    std::size_t numMaterials = theMaterialTable    
554    // make sure that we have long enough vecto    
555    if(gMoliereBc.size()<numMaterials) {           
556      gMoliereBc.resize(numMaterials);             
557      gMoliereXc2.resize(numMaterials);            
558    }                                              
559    G4double xi   = 1.0;                           
560    G4int    maxZ = 200;                           
561    if (fIsMottCorrection || fIsPWACorrection)     
562      // xi   = 1.0;  <= always set to 1 from n    
563      maxZ = G4GSMottCorrection::GetMaxZet();      
564    }                                              
565    //                                             
566    for (std::size_t imat=0; imat<numMaterials;    
567      const G4Material*      theMaterial     =     
568      const G4ElementVector* theElemVect     =     
569      const G4int            numelems        =     
570      //                                           
571      const G4double*        theNbAtomsPerVolVe    
572      G4double               theTotNbAtomsPerVo    
573      //                                           
574      G4double zs = 0.0;                           
575      G4double zx = 0.0;                           
576      G4double ze = 0.0;                           
577      G4double sa = 0.0;                           
578      //                                           
579      for(G4int ielem = 0; ielem < numelems; ie    
580        G4double zet = (*theElemVect)[ielem]->G    
581        if (zet>maxZ) {                            
582          zet = (G4double)maxZ;                    
583        }                                          
584        G4double iwa  = (*theElemVect)[ielem]->    
585        G4double ipz  = theNbAtomsPerVolVect[ie    
586        G4double dum  = ipz*zet*(zet+xi);          
587        zs           += dum;                       
588        ze           += dum*(-2.0/3.0)*G4Log(ze    
589        zx           += dum*G4Log(1.0+3.34*fins    
590        sa           += ipz*iwa;                   
591      }                                            
592      G4double density = theMaterial->GetDensit    
593      //                                           
594      gMoliereBc[theMaterial->GetIndex()]  = co    
595      gMoliereXc2[theMaterial->GetIndex()] = co    
596      // change to Geant4 internal units of 1/l    
597      gMoliereBc[theMaterial->GetIndex()]  *= 1    
598      gMoliereXc2[theMaterial->GetIndex()] *= C    
599    }                                              
600 }                                                 
601                                                   
602                                                   
603 // this method is temporary, will be removed/r    
604 G4double G4GoudsmitSaundersonTable::ComputeSca    
605   G4int    imc       = matcut->GetIndex();        
606   G4double corFactor = 1.0;                       
607   if (!(fSCPCPerMatCuts[imc]->fIsUse) || ekin<    
608     return corFactor;                             
609   }                                               
610   // get the scattering power correction facto    
611   G4double lekin      = G4Log(ekin);              
612   G4double remaining  = (lekin-fSCPCPerMatCuts    
613   std::size_t lindx   = (std::size_t)remaining    
614   remaining          -= lindx;                    
615   std::size_t imax    = fSCPCPerMatCuts[imc]->    
616   if (lindx>=imax) {                              
617     corFactor = fSCPCPerMatCuts[imc]->fVSCPC[i    
618   } else {                                        
619     corFactor = fSCPCPerMatCuts[imc]->fVSCPC[l    
620   }                                               
621   return corFactor;                               
622 }                                                 
623                                                   
624                                                   
625 void G4GoudsmitSaundersonTable::InitSCPCorrect    
626   // get the material-cuts table                  
627   G4ProductionCutsTable *thePCTable = G4Produc    
628   std::size_t numMatCuts            = thePCTab    
629   // clear container if any                       
630   for (std::size_t imc=0; imc<fSCPCPerMatCuts.    
631     if (fSCPCPerMatCuts[imc]) {                   
632       fSCPCPerMatCuts[imc]->fVSCPC.clear();       
633       delete fSCPCPerMatCuts[imc];                
634       fSCPCPerMatCuts[imc] = nullptr;             
635     }                                             
636   }                                               
637   //                                              
638   // set size of the container and create the     
639   fSCPCPerMatCuts.resize(numMatCuts,nullptr);     
640   // loop over the material-cuts and create sc    
641   for (G4int imc=0; imc<(G4int)numMatCuts; ++i    
642     const G4MaterialCutsCouple *matCut =  theP    
643     // get e- production cut in the current ma    
644     G4double limit;                               
645     G4double ecut;                                
646     if (fIsElectron) {                            
647       ecut  = (*(thePCTable->GetEnergyCutsVect    
648       limit = 2.*ecut;                            
649     } else {                                      
650       ecut  = (*(thePCTable->GetEnergyCutsVect    
651       limit = ecut;                               
652     }                                             
653     G4double min = std::max(limit,fLowEnergyLi    
654     G4double max = fHighEnergyLimit;              
655     if (min>=max) {                               
656       fSCPCPerMatCuts[imc] = new SCPCorrection    
657       fSCPCPerMatCuts[imc]->fIsUse = false;       
658       fSCPCPerMatCuts[imc]->fPrCut = min;         
659       continue;                                   
660     }                                             
661     G4int numEbins       = fNumSPCEbinPerDec*G    
662     numEbins             = std::max(numEbins,3    
663     G4double lmin        = G4Log(min);            
664     G4double ldel        = G4Log(max/min)/(num    
665     fSCPCPerMatCuts[imc] = new SCPCorrection()    
666     fSCPCPerMatCuts[imc]->fVSCPC.resize(numEbi    
667     fSCPCPerMatCuts[imc]->fIsUse = true;          
668     fSCPCPerMatCuts[imc]->fPrCut = min;           
669     fSCPCPerMatCuts[imc]->fLEmin = lmin;          
670     fSCPCPerMatCuts[imc]->fILDel = 1./ldel;       
671     for (G4int ie=0; ie<numEbins; ++ie) {         
672       G4double ekin    = G4Exp(lmin+ie*ldel);     
673       G4double scpCorr = 1.0;                     
674       // compute correction factor: I.Kawrakow    
675       if (ie>0) {                                 
676          G4double tau     = ekin/CLHEP::electr    
677          G4double tauCut  = ecut/CLHEP::electr    
678          // Moliere's screening parameter         
679          G4int    matindx = (G4int)matCut->Get    
680          G4double A       = GetMoliereXc2(mati    
681          G4double gr      = (1.+2.*A)*G4Log(1.    
682          G4double dum0    = (tau+2.)/(tau+1.);    
683          G4double dum1    = tau+1.;               
684          G4double gm      = G4Log(0.5*tau/tauC    
685                             - 0.25*(tau+2.)*(     
686                               G4Log((tau+4.)*(    
687                             + 0.5*(tau-2*tauCu    
688          if (gm<gr) {                             
689            gm = gm/gr;                            
690          } else {                                 
691            gm = 1.;                               
692          }                                        
693          G4double z0 = matCut->GetMaterial()->    
694          scpCorr     = 1.-gm*z0/(z0*(z0+1.));     
695       }                                           
696       fSCPCPerMatCuts[imc]->fVSCPC[ie] = scpCo    
697     }                                             
698   }                                               
699 }                                                 
700