Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4GoudsmitSaundersonTable.cc
이 파일의 문서화 페이지로 가기
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // $Id: G4GoudsmitSaundersonTable.cc 110527 2018-05-29 06:09:58Z gcosmo $
27 //
28 // -----------------------------------------------------------------------------
29 //
30 // GEANT4 Class implementation file
31 //
32 // File name: G4GoudsmitSaundersonTable
33 //
34 // Author: Mihaly Novak / (Omrane Kadri)
35 //
36 // Creation date: 20.02.2009
37 //
38 // Class description:
39 // Class to handle multiple scattering angular distributions precomputed by
40 // using Kawrakow-Bielajew Goudsmit-Saunderson MSC model based on the screened
41 // Rutherford DCS for elastic scattering of electrons/positrons [1,2]. This
42 // class is used by G4GoudsmitSaundersonMscModel to sample the angular
43 // deflection of electrons/positrons after travelling a given path.
44 //
45 // Modifications:
46 // 04.03.2009 V.Ivanchenko cleanup and format according to Geant4 EM style
47 // 26.08.2009 O.Kadri: avoiding unuseful calculations and optimizing the root
48 // finding parameter error's within SampleTheta method
49 // 08.02.2010 O.Kadri: reduce delared variables; reduce error of finding root
50 // in secant method
51 // 26.03.2010 O.Kadri: minimum of used arrays in computation within the dichotomie
52 // finding method the error was the lowest value of uvalues
53 // 12.05.2010 O.Kadri: changing of sqrt((b-a)*(b-a)) with fabs(b-a)
54 // 18.05.2015 M. Novak This class has been completely replaced (only the original
55 // class name was kept; class description was also inserted):
56 // A new version of Kawrakow-Bielajew Goudsmit-Saunderson MSC model
57 // based on the screened Rutherford DCS for elastic scattering of
58 // electrons/positrons has been introduced[1,2]. The corresponding MSC
59 // angular distributions over a 2D parameter grid have been recomputed
60 // and the CDFs are now stored in a variable transformed (smooth) form
61 // together with the corresponding rational interpolation parameters.
62 // The new version is several times faster, more robust and accurate
63 // compared to the earlier version (G4GoudsmitSaundersonMscModel class
64 // that use these data has been also completely replaced)
65 // 28.04.2017 M. Novak: New representation of the angular distribution data with
66 // significantly reduced data size.
67 // 23.08.2017 M. Novak: Added funtionality to handle Mott-correction to the
68 // base GS angular distributions and some other factors (screening
69 // parameter, first and second moments) when Mott-correction is
70 // activated in the GS-MSC model.
71 //
72 // References:
73 // [1] A.F.Bielajew, NIMB, 111 (1996) 195-208
74 // [2] I.Kawrakow, A.F.Bielajew, NIMB 134(1998) 325-336
75 //
76 // -----------------------------------------------------------------------------
77 
79 
80 
81 #include "G4PhysicalConstants.hh"
82 #include "Randomize.hh"
83 #include "G4Log.hh"
84 #include "G4Exp.hh"
85 
86 #include "G4GSMottCorrection.hh"
87 #include "G4MaterialTable.hh"
88 #include "G4Material.hh"
89 #include "G4MaterialCutsCouple.hh"
90 #include "G4ProductionCutsTable.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, based on the Screened-Rutherford DCS
102 // are the same for e- and e+ so make sure we load them only onece
104 //
105 std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions1;
106 std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions2;
107 //
108 std::vector<double> G4GoudsmitSaundersonTable::gMoliereBc;
109 std::vector<double> G4GoudsmitSaundersonTable::gMoliereXc2;
110 
111 
113  fIsElectron = iselectron;
114  // set initial values: final values will be set in the Initialize method
115  fLogLambda0 = 0.; // will be set properly at init.
116  fLogDeltaLambda = 0.; // will be set properly at init.
117  fInvLogDeltaLambda = 0.; // will be set properly at init.
118  fInvDeltaQ1 = 0.; // will be set properly at init.
119  fDeltaQ2 = 0.; // will be set properly at init.
120  fInvDeltaQ2 = 0.; // will be set properly at init.
121  //
122  fLowEnergyLimit = 0.1*CLHEP::keV; // will be set properly at init.
123  fHighEnergyLimit = 100.0*CLHEP::MeV; // will be set properly at init.
124  //
125  fIsMottCorrection = false; // will be set properly at init.
126  fIsPWACorrection = false; // will be set properly at init.
127  fMottCorrection = nullptr;
128  //
129  fNumSPCEbinPerDec = 3;
130 }
131 
133  for (size_t i=0; i<gGSMSCAngularDistributions1.size(); ++i) {
135  delete [] gGSMSCAngularDistributions1[i]->fUValues;
136  delete [] gGSMSCAngularDistributions1[i]->fParamA;
137  delete [] gGSMSCAngularDistributions1[i]->fParamB;
138  delete gGSMSCAngularDistributions1[i];
139  }
140  }
142  for (size_t i=0; i<gGSMSCAngularDistributions2.size(); ++i) {
144  delete [] gGSMSCAngularDistributions2[i]->fUValues;
145  delete [] gGSMSCAngularDistributions2[i]->fParamA;
146  delete [] gGSMSCAngularDistributions2[i]->fParamB;
147  delete gGSMSCAngularDistributions2[i];
148  }
149  }
151  if (fMottCorrection) {
152  delete fMottCorrection;
153  fMottCorrection = nullptr;
154  }
155  // clear scp correction data
156  for (size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
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(G4double lownergylimit, G4double highenergylimit) {
168  fLowEnergyLimit = lownergylimit;
169  fHighEnergyLimit = highenergylimit;
170  G4double lLambdaMin = G4Log(gLAMBMIN);
171  G4double lLambdaMax = G4Log(gLAMBMAX);
172  fLogLambda0 = lLambdaMin;
173  fLogDeltaLambda = (lLambdaMax-lLambdaMin)/(gLAMBNUM-1.);
175  fInvDeltaQ1 = 1./((gQMAX1-gQMIN1)/(gQNUM1-1.));
176  fDeltaQ2 = (gQMAX2-gQMIN2)/(gQNUM2-1.);
177  fInvDeltaQ2 = 1./fDeltaQ2;
178  // load precomputed angular distributions and set up several values used during the sampling
179  // these are particle independet => they go to static container: load them only onece
180  if (!gIsInitialised) {
181  // load pre-computed GS angular distributions (computed based on Screened-Rutherford DCS)
182  LoadMSCData();
183  gIsInitialised = true;
184  }
186  // Mott-correction: particle(e- or e+) dependet so init them
187  if (fIsMottCorrection) {
188  if (!fMottCorrection) {
189  fMottCorrection = new G4GSMottCorrection(fIsElectron);
190  }
191  fMottCorrection->Initialise();
192  }
193  // init scattering power correction data; used only together with Mott-correction
194  // (Moliere's parameters must be initialised before)
195  if (fMottCorrection) {
197  }
198 }
199 
200 
201 // samplig multiple scattering angles cos(theta) and sin(thata)
202 // - including no-scattering, single, "few" scattering cases as well
203 // - Mott-correction will be included if it was requested by the user (i.e. if fIsMottCorrection=true)
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 kinetic energy
210 // beta2 : the corresponding beta square
211 // matindx : index of the current material
212 // returns true if it was msc
214  G4double &sint, G4double lekin, G4double beta2, G4int matindx,
215  GSMSCAngularDtr **gsDtr, G4int &mcekini, G4int &mcdelti,
216  G4double &transfPar, G4bool isfirst) {
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 single scattering PDF
228  // - Mott-correction will be included if it was requested by the user (i.e. if fIsMottCorrection=true)
229  if (rand0<(1.+lambdaval)*expn) {
230  // cost is sampled in SingleScattering()
231  cost = SingleScattering(lambdaval, scra, lekin, beta2, matindx);
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(theta)
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 events along the step is < 1 but
243  // the currently sampled case is not 0 or 1 scattering. [Our minimal
244  // lambdaval (that we have precomputed, transformed angular distributions
245  // stored in a form of equally probabe intervalls together with rational
246  // interp. parameters) is 1.]
247  // -probability of having n elastic events follows Poisson stat. with
248  // lambdaval parameter.
249  // -the max. probability (when lambdaval=1) of having more than one
250  // elastic events is 0.2642411 and the prob of having 2,3,..,n elastic
251  // events decays rapidly with n. So set a max n to 10.
252  // -sampling of this cases is done in a one-by-one single elastic event way
253  // where the current #elastic event is sampled from the Poisson distr.
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 zero scattering values
259  cost = 1.0;
260  sint = 0.0;
261  for (G4int iel=1; iel<10; ++iel) {
262  // prob of having iel scattering from Poisson
263  prob *= lambdaval/(G4double)iel;
264  cumprob += prob;
265  //
266  //sample cos(theta) from the singe scattering pdf:
267  // - Mott-correction will be included if it was requested by the user (i.e. if fIsMottCorrection=true)
268  curcost = SingleScattering(lambdaval, scra, lekin, beta2, matindx);
269  G4double dum0 = 1.-curcost;
270  cursint = dum0*(2.0-dum0); // sin^2(theta)
271  //
272  // if we got current deflection that is not too small
273  // then update cos(theta) sin(theta)
274  if (cursint>1.0e-20) {
275  cursint = std::sqrt(cursint);
277  cost = cost*curcost-sint*cursint*std::cos(curphi);
278  sint = std::sqrt(std::max(0.0, (1.0-cost)*(1.0+cost)));
279  }
280  //
281  // check if we have done enough scattering i.e. sampling from the Poisson
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 >= 1:
291  // - use the precomputed and transformed Goudsmit-Saunderson angular
292  // distributions to sample cos(theta)
293  // - Mott-correction will be included if it was requested by the user (i.e. if fIsMottCorrection=true)
294  cost = SampleCosTheta(lambdaval, qval, scra, lekin, beta2, matindx, gsDtr, mcekini, mcdelti, transfPar, isfirst);
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 the sampled 1-cos(theta)
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 
307  G4double lekin, G4double beta2, G4int matindx,
308  GSMSCAngularDtr **gsDtr, G4int &mcekini,G4int &mcdelti,
309  G4double &transfPar, G4bool isfirst) {
310  G4double cost = 1.;
311  // determine the base GS angular distribution if it is the first call (when sub-step sampling is used)
312  if (isfirst) {
313  *gsDtr = GetGSAngularDtr(scra, lambdaval, qval, transfPar);
314  }
315  // sample cost from the GS angular distribution (computed based on Screened-Rutherford DCS)
316  cost = SampleGSSRCosTheta(*gsDtr, transfPar);
317  // Mott-correction if it was requested by the user
318  if (fIsMottCorrection && *gsDtr) { // no Mott-correction in case of izotropic theta
319  static const G4int nlooplim = 1000;
320  G4int nloop = 0 ; // rejection loop counter
321 // G4int ekindx = -1; // evaluate only in the first call
322 // G4int deltindx = -1 ; // evaluate only in the first call
323  G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
324  while (G4UniformRand()>val && ++nloop<nlooplim) {
325  // sampling cos(theta)
326  cost = SampleGSSRCosTheta(*gsDtr, transfPar);
327  val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
328  };
329  }
330  return cost;
331 }
332 
333 
334 // returns with cost sampled from the GS angular distribution computed based on Screened-Rutherford DCS
336  // check if isotropic theta (i.e. cost is uniform on [-1:1])
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]+gsDtr->fParamB[indxl])*dum0;
351  G4double dum2 = delta*delta + gsDtr->fParamA[indxl]*dum0 + gsDtr->fParamB[indxl]*aval*aval;
352  G4double sample = gsDtr->fUValues[indxl] + dum1/dum2 *(gsDtr->fUValues[indxl+1]-gsDtr->fUValues[indxl]);
353  // transform back u to cos(theta) :
354  // this is the sampled cos(theta) = (2.0*para*sample)/(1.0-sample+para)
355  return 1.-(2.0*transfpar*sample)/(1.0-sample+transfpar);
356 }
357 
358 
359 // determine the GS angular distribution we need to sample from: will set other things as well ...
361  G4double &lambdaval, G4double &qval, G4double &transfpar) {
362  GSMSCAngularDtr *dtr = nullptr;
363  G4bool first = false;
364  // isotropic cost above gQMAX2 (i.e. dtr stays nullptr)
365  if (qval<gQMAX2) {
366  G4int lamIndx = -1; // lambda value index
367  G4int qIndx = -1; // lambda value index
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 taking higher index
373  // check if first or second grid needs to be used
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 in [gLAMBMIN,gLAMBMAX)
388  // lambda<gLAMBMIN=1 is already handeled before so lambda>= gLAMBMIN for sure
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) index: linear interp. on log(lambda) scale
396  if (lamIndx<0) {
397  pIndxH = (lLambda-fLogLambda0)*fInvLogDeltaLambda;
398  lamIndx = (G4int)(pIndxH); // lower index of the lambda bin
399  pIndxH = pIndxH-lamIndx; // probability of taking the higher index distribution
400  if (G4UniformRand()<pIndxH) {
401  ++lamIndx;
402  }
403  }
404  //
405  // determine lower Q (=s/lambda_el G1) index: linear interp. on Q
406  if (qIndx<0) {
407  pIndxH = (qval-minQVal)*invDelQ;
408  qIndx = (G4int)(pIndxH); // lower index of the Q bin
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 isotropic cot distribution because:
422  // - if the selected lamIndx, qIndx correspond to L(=s/lambda_el) and Q(=s/lambda_el G1) such that G1(=Q/L) > 1
423  // G1 should always be < 1 and if G1 is ~1 -> the dtr is isotropic (this can only happen in case of the 2. grid)
424  //
425  // compute the transformation parameter
426  if (lambdaval>10.0) {
427  transfpar = 0.5*(-2.77164+lLambda*( 2.94874-lLambda*(0.1535754-lLambda*0.00552888) ));
428  } else {
429  transfpar = 0.5*(1.347+lLambda*(0.209364-lLambda*(0.45525-lLambda*(0.50142-lLambda*0.081234))));
430  }
431  transfpar *= (lambdaval+4.0)*scra;
432  }
433  // return with the selected GS angular distribution that we need to sample cost from (if nullptr => isotropic cost)
434  return dtr;
435 }
436 
437 
439  char* path = getenv("G4LEDATA");
440  if (!path) {
441  G4Exception("G4GoudsmitSaundersonTable::LoadMSCData()","em0006",
443  "Environment variable G4LEDATA not defined");
444  return;
445  }
446  //
448  const G4String str1 = G4String(path) + "/msc_GS/GSGrid_1/gsDistr_";
449  for (G4int il=0; il<gLAMBNUM; ++il) {
450  G4String fname = str1 + std::to_string(il);
451  std::ifstream infile(fname,std::ios::in);
452  if (!infile.is_open()) {
453  G4String msgc = "Cannot open file: " + fname;
454  G4Exception("G4GoudsmitSaundersonTable::LoadMSCData()","em0006",
455  FatalException, msgc.c_str());
456  return;
457  }
458  for (G4int iq=0; iq<gQNUM1; ++iq) {
459  GSMSCAngularDtr *gsd = new GSMSCAngularDtr();
460  infile >> gsd->fNumData;
461  gsd->fUValues = new G4double[gsd->fNumData]();
462  gsd->fParamA = new G4double[gsd->fNumData]();
463  gsd->fParamB = new G4double[gsd->fNumData]();
464  G4double ddummy;
465  infile >> ddummy; infile >> ddummy;
466  for (G4int i=0; i<gsd->fNumData; ++i) {
467  infile >> gsd->fUValues[i];
468  infile >> gsd->fParamA[i];
469  infile >> gsd->fParamB[i];
470  }
471  gGSMSCAngularDistributions1[il*gQNUM1+iq] = gsd;
472  }
473  infile.close();
474  }
475  //
476  // second grid
477  gGSMSCAngularDistributions2.resize(gLAMBNUM*gQNUM2,nullptr);
478  const G4String str2 = G4String(path) + "/msc_GS/GSGrid_2/gsDistr_";
479  for (G4int il=0; il<gLAMBNUM; ++il) {
480  G4String fname = str2 + std::to_string(il);
481  std::ifstream infile(fname,std::ios::in);
482  if (!infile.is_open()) {
483  G4String msgc = "Cannot open file: " + fname;
484  G4Exception("G4GoudsmitSaundersonTable::LoadMSCData()","em0006",
485  FatalException, msgc.c_str());
486  return;
487  }
488  for (G4int iq=0; iq<gQNUM2; ++iq) {
489  G4int numData;
490  infile >> numData;
491  if (numData>1) {
492  GSMSCAngularDtr *gsd = new GSMSCAngularDtr();
493  gsd->fNumData = numData;
494  gsd->fUValues = new G4double[gsd->fNumData]();
495  gsd->fParamA = new G4double[gsd->fNumData]();
496  gsd->fParamB = new G4double[gsd->fNumData]();
497  double ddummy;
498  infile >> ddummy; infile >> ddummy;
499  for (G4int i=0; i<gsd->fNumData; ++i) {
500  infile >> gsd->fUValues[i];
501  infile >> gsd->fParamA[i];
502  infile >> gsd->fParamB[i];
503  }
504  gGSMSCAngularDistributions2[il*gQNUM2+iq] = gsd;
505  } else {
506  gGSMSCAngularDistributions2[il*gQNUM2+iq] = nullptr;
507  }
508  }
509  infile.close();
510  }
511 }
512 
513 // samples cost in single scattering based on Screened-Rutherford DCS
514 // (with Mott-correction if it was requested)
516  G4double lekin, G4double beta2,
517  G4int matindx) {
518  G4double rand1 = G4UniformRand();
519  // sample cost from the Screened-Rutherford DCS
520  G4double cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
521  // Mott-correction if it was requested by the user
522  if (fIsMottCorrection) {
523  static const G4int nlooplim = 1000; // rejection loop limit
524  G4int nloop = 0 ; // loop counter
525  G4int ekindx = -1 ; // evaluate only in the first call
526  G4int deltindx = 0 ; // single scattering case
527  G4double q1 = 0.; // not used when deltindx = 0;
528  // computing Mott rejection function value
529  G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost,
530  matindx, ekindx, deltindx);
531  while (G4UniformRand()>val && ++nloop<nlooplim) {
532  // sampling cos(theta) from the Screened-Rutherford DCS
533  rand1 = G4UniformRand();
534  cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
535  // computing Mott rejection function value
536  val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost, matindx,
537  ekindx, deltindx);
538  };
539  }
540  return cost;
541 }
542 
543 
545  G4int matindx, G4double &mcToScr,
546  G4double &mcToQ1, G4double &mcToG2PerG1) {
547  if (fIsMottCorrection) {
548  fMottCorrection->GetMottCorrectionFactors(logekin, beta2, matindx, mcToScr, mcToQ1, mcToG2PerG1);
549  }
550 }
551 
552 
553 // compute material dependent Moliere MSC parameters at initialisation
555  const G4double const1 = 7821.6; // [cm2/g]
556  const G4double const2 = 0.1569; // [cm2 MeV2 / g]
557  const G4double finstrc2 = 5.325135453E-5; // fine-structure const. square
558 
559  G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
560  // get number of materials in the table
561  size_t numMaterials = theMaterialTable->size();
562  // make sure that we have long enough vectors
563  if(gMoliereBc.size()<numMaterials) {
564  gMoliereBc.resize(numMaterials);
565  gMoliereXc2.resize(numMaterials);
566  }
567  G4double xi = 1.0;
568  G4int maxZ = 200;
570  // xi = 1.0; <= always set to 1 from now on
572  }
573  //
574  for (size_t imat=0; imat<numMaterials; ++imat) {
575  const G4Material* theMaterial = (*theMaterialTable)[imat];
576  const G4ElementVector* theElemVect = theMaterial->GetElementVector();
577  const G4int numelems = theMaterial->GetNumberOfElements();
578  //
579  const G4double* theNbAtomsPerVolVect = theMaterial->GetVecNbOfAtomsPerVolume();
580  G4double theTotNbAtomsPerVol = theMaterial->GetTotNbOfAtomsPerVolume();
581  //
582  G4double zs = 0.0;
583  G4double zx = 0.0;
584  G4double ze = 0.0;
585  G4double sa = 0.0;
586  //
587  for(G4int ielem = 0; ielem < numelems; ielem++) {
588  G4double zet = (*theElemVect)[ielem]->GetZ();
589  if (zet>maxZ) {
590  zet = (G4double)maxZ;
591  }
592  G4double iwa = (*theElemVect)[ielem]->GetN();
593  G4double ipz = theNbAtomsPerVolVect[ielem]/theTotNbAtomsPerVol;
594  G4double dum = ipz*zet*(zet+xi);
595  zs += dum;
596  ze += dum*(-2.0/3.0)*G4Log(zet);
597  zx += dum*G4Log(1.0+3.34*finstrc2*zet*zet);
598  sa += ipz*iwa;
599  }
600  G4double density = theMaterial->GetDensity()*CLHEP::cm3/CLHEP::g; // [g/cm3]
601  //
602  gMoliereBc[theMaterial->GetIndex()] = const1*density*zs/sa*G4Exp(ze/zs)/G4Exp(zx/zs); //[1/cm]
603  gMoliereXc2[theMaterial->GetIndex()] = const2*density*zs/sa; // [MeV2/cm]
604  // change to Geant4 internal units of 1/length and energ2/length
605  gMoliereBc[theMaterial->GetIndex()] *= 1.0/CLHEP::cm;
606  gMoliereXc2[theMaterial->GetIndex()] *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
607  }
608 }
609 
610 
611 // this method is temporary, will be removed/replaced with a more effictien solution after 10.3.ref09
613  G4int imc = matcut->GetIndex();
614  G4double corFactor = 1.0;
615  if (!(fSCPCPerMatCuts[imc]->fIsUse) || ekin<=fSCPCPerMatCuts[imc]->fPrCut) {
616  return corFactor;
617  }
618  // get the scattering power correction factor
619  G4double lekin = G4Log(ekin);
620  G4double remaining = (lekin-fSCPCPerMatCuts[imc]->fLEmin)*fSCPCPerMatCuts[imc]->fILDel;
621  G4int lindx = (G4int)remaining;
622  remaining -= lindx;
623  G4int imax = fSCPCPerMatCuts[imc]->fVSCPC.size()-1;
624  if (lindx>=imax) {
625  corFactor = fSCPCPerMatCuts[imc]->fVSCPC[imax];
626  } else {
627  corFactor = fSCPCPerMatCuts[imc]->fVSCPC[lindx] + remaining*(fSCPCPerMatCuts[imc]->fVSCPC[lindx+1]-fSCPCPerMatCuts[imc]->fVSCPC[lindx]);
628  }
629  return corFactor;
630 }
631 
632 
634  // get the material-cuts table
636  size_t numMatCuts = thePCTable->GetTableSize();
637  // clear container if any
638  for (size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
639  if (fSCPCPerMatCuts[imc]) {
640  fSCPCPerMatCuts[imc]->fVSCPC.clear();
641  delete fSCPCPerMatCuts[imc];
642  fSCPCPerMatCuts[imc] = nullptr;
643  }
644  }
645  //
646  // set size of the container and create the corresponding data structures
647  fSCPCPerMatCuts.resize(numMatCuts,nullptr);
648  // loop over the material-cuts and create scattering power correction data structure for each
649  for (size_t imc=0; imc<numMatCuts; ++imc) {
650  const G4MaterialCutsCouple *matCut = thePCTable->GetMaterialCutsCouple(imc);
651  // get e- production cut in the current material-cuts in energy
652  G4double limit;
653  G4double ecut;
654  if (fIsElectron) {
655  ecut = (*(thePCTable->GetEnergyCutsVector(idxG4ElectronCut)))[matCut->GetIndex()];
656  limit = 2.*ecut;
657  } else {
658  ecut = (*(thePCTable->GetEnergyCutsVector(idxG4PositronCut)))[matCut->GetIndex()];
659  limit = ecut;
660  }
663  if (min>=max) {
664  fSCPCPerMatCuts[imc] = new SCPCorrection();
665  fSCPCPerMatCuts[imc]->fIsUse = false;
666  fSCPCPerMatCuts[imc]->fPrCut = min;
667  continue;
668  }
669  G4int numEbins = fNumSPCEbinPerDec*G4lrint(std::log10(max/min));
670  numEbins = std::max(numEbins,3);
671  G4double lmin = G4Log(min);
672  G4double ldel = G4Log(max/min)/(numEbins-1.0);
673  fSCPCPerMatCuts[imc] = new SCPCorrection();
674  fSCPCPerMatCuts[imc]->fVSCPC.resize(numEbins,1.0);
675  fSCPCPerMatCuts[imc]->fIsUse = true;
676  fSCPCPerMatCuts[imc]->fPrCut = min;
677  fSCPCPerMatCuts[imc]->fLEmin = lmin;
678  fSCPCPerMatCuts[imc]->fILDel = 1./ldel;
679  for (G4int ie=0; ie<numEbins; ++ie) {
680  G4double ekin = G4Exp(lmin+ie*ldel);
681  G4double scpCorr = 1.0;
682  // compute correction factor: I.Kawrakow NIMB 114(1996)307-326 (Eqs(32-37))
683  if (ie>0) {
685  G4double tauCut = ecut/CLHEP::electron_mass_c2;
686  // Moliere's screening parameter
687  G4int matindx = matCut->GetMaterial()->GetIndex();
688  G4double A = GetMoliereXc2(matindx)/(4.0*tau*(tau+2.)*GetMoliereBc(matindx));
689  G4double gr = (1.+2.*A)*G4Log(1.+1./A)-2.;
690  G4double dum0 = (tau+2.)/(tau+1.);
691  G4double dum1 = tau+1.;
692  G4double gm = G4Log(0.5*tau/tauCut) + (1.+dum0*dum0)*G4Log(2.*(tau-tauCut+2.)/(tau+4.))
693  - 0.25*(tau+2.)*( tau+2.+2.*(2.*tau+1.)/(dum1*dum1))*
694  G4Log((tau+4.)*(tau-tauCut)/tau/(tau-tauCut+2.))
695  + 0.5*(tau-2*tauCut)*(tau+2.)*(1./(tau-tauCut)-1./(dum1*dum1));
696  if (gm<gr) {
697  gm = gm/gr;
698  } else {
699  gm = 1.;
700  }
702  scpCorr = 1.-gm*z0/(z0*(z0+1.));
703  }
704  fSCPCPerMatCuts[imc]->fVSCPC[ie] = scpCorr;
705  }
706  }
707 }
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:183
T max(const T t1, const T t2)
brief Return the largest of the two arguments
std::vector< SCPCorrection * > fSCPCPerMatCuts
void GetMottCorrectionFactors(G4double logekin, G4double beta2, G4int matindx, G4double &mcToScr, G4double &mcToQ1, G4double &mcToG2PerG1)
static constexpr G4double gQMIN1
static constexpr double cm3
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:593
static constexpr G4double gQMAX1
static constexpr double g
G4double SingleScattering(G4double lambdaval, G4double scra, G4double lekin, G4double beta2, G4int matindx)
size_t GetIndex() const
Definition: G4Material.hh:262
static constexpr G4double gLAMBMIN
G4bool Sampling(G4double lambdaval, G4double qval, G4double scra, G4double &cost, G4double &sint, G4double lekin, G4double beta2, G4int matindx, GSMSCAngularDtr **gsDtr, G4int &mcekini, G4int &mcdelti, G4double &transfPar, G4bool isfirst)
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:191
G4GoudsmitSaundersonTable(G4bool iselectron)
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:207
void Initialise(G4double lownergylimit, G4double highenergylimit)
G4double GetMoliereBc(G4int matindx)
const std::vector< G4double > * GetEnergyCutsVector(size_t pcIdx) const
G4double G4Log(G4double x)
Definition: G4Log.hh:230
static const G4int maxZ
GSMSCAngularDtr * GetGSAngularDtr(G4double scra, G4double &lambdaval, G4double &qval, G4double &transfpar)
static constexpr double cm
Definition: SystemOfUnits.h:99
double G4double
Definition: G4Types.hh:76
bool G4bool
Definition: G4Types.hh:79
G4double GetMoliereXc2(G4int matindx)
static constexpr G4double gLAMBMAX
static constexpr double electron_mass_c2
G4double SampleGSSRCosTheta(const GSMSCAngularDtr *gsDrt, G4double transfpar)
static G4int GetMaxZet()
static constexpr double MeV
#define G4UniformRand()
Definition: Randomize.hh:53
double A(double temperature)
static const G4int nlooplim
static std::vector< GSMSCAngularDtr * > gGSMSCAngularDistributions1
std::vector< G4Material * > G4MaterialTable
G4double ComputeScatteringPowerCorrection(const G4MaterialCutsCouple *matcut, G4double ekin)
static constexpr G4double gQMIN2
static constexpr double twopi
Definition: SystemOfUnits.h:55
static G4ProductionCutsTable * GetProductionCutsTable()
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.hh:65
static const G4int imax
int G4lrint(double ad)
Definition: templates.hh:151
std::vector< G4Element * > G4ElementVector
int G4int
Definition: G4Types.hh:78
ifstream in
Definition: comparison.C:7
G4IonisParamMat * GetIonisation() const
Definition: G4Material.hh:227
G4double GetZeffective() const
static std::vector< GSMSCAngularDtr * > gGSMSCAngularDistributions2
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
const G4Material * GetMaterial() const
G4double SampleCosTheta(G4double lambdaval, G4double qval, G4double scra, G4double lekin, G4double beta2, G4int matindx, GSMSCAngularDtr **gsDtr, G4int &mcekini, G4int &mcdelti, G4double &transfPar, G4bool isfirst)
G4double GetTotNbOfAtomsPerVolume() const
Definition: G4Material.hh:210
static constexpr G4double gQMAX2
static constexpr double keV
size_t GetNumberOfElements() const
Definition: G4Material.hh:187
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4double GetDensity() const
Definition: G4Material.hh:181