Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4GSMottCorrection.cc
Go to the documentation of this file.
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//
27// ----------------------------------------------------------------------------
28//
29//
30// File name: G4GSMottCorrection
31//
32// Author: Mihaly Novak
33//
34// Creation date: 23.08.2017
35//
36// Modifications:
37// 02.02.2018 M.Novak: fixed initialization of first moment correction.
38//
39// Class description: see the header file.
40//
41// -----------------------------------------------------------------------------
42
43#include "G4GSMottCorrection.hh"
44
46#include "zlib.h"
47#include "Randomize.hh"
48#include "G4Log.hh"
49#include "G4Exp.hh"
50
53#include "G4Material.hh"
54#include "G4ElementVector.hh"
55#include "G4Element.hh"
56
57#include <iostream>
58#include <fstream>
59#include <cmath>
60#include <algorithm>
61
62
63const std::string G4GSMottCorrection::gElemSymbols[] = {"H","He","Li","Be","B" ,
64 "C" ,"N" ,"O" ,"F" ,"Ne","Na","Mg","Al","Si","P" , "S","Cl","Ar","K" ,"Ca","Sc",
65 "Ti","V" ,"Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr","Rb",
66 "Sr","Y" ,"Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I" ,
67 "Xe","Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm",
68 "Yb","Lu","Hf","Ta","W" ,"Re","Os","Ir","Pt","Au","Hg","Tl","Pb","Bi","Po","At",
69 "Rn","Fr","Ra","Ac","Th","Pa","U" ,"Np","Pu","Am","Cm","Bk","Cf"};
70
71G4GSMottCorrection::G4GSMottCorrection(G4bool iselectron) : fIsElectron(iselectron) {
72 // init grids related data member values
73 fMaxEkin = CLHEP::electron_mass_c2*(1./std::sqrt(1.-gMaxBeta2)-1.);
74 fLogMinEkin = G4Log(gMinEkin);
75 fInvLogDelEkin = (gNumEkin-gNumBeta2)/G4Log(gMidEkin/gMinEkin);
76 G4double pt2 = gMidEkin*(gMidEkin+2.0*CLHEP::electron_mass_c2);
77 fMinBeta2 = pt2/(pt2+CLHEP::electron_mass_c2*CLHEP::electron_mass_c2);
78 fInvDelBeta2 = (gNumBeta2-1.)/(gMaxBeta2-fMinBeta2);
79 fInvDelDelta = (gNumDelta-1.)/gMaxDelta;
80 fInvDelAngle = gNumAngle-1.;
81}
82
83
85 ClearMCDataPerElement();
86 ClearMCDataPerMaterial();
87}
88
89
91 G4double &mcToQ1, G4double &mcToG2PerG1) {
92 G4int ekinIndxLow = 0;
93 G4double remRfaction = 0.;
94 if (beta2>=gMaxBeta2) {
95 ekinIndxLow = gNumEkin - 1;
96 // remRfaction = -1.
97 } else if (beta2>=fMinBeta2) { // linear interpolation on \beta^2
98 remRfaction = (beta2 - fMinBeta2) * fInvDelBeta2;
99 ekinIndxLow = (G4int)remRfaction;
100 remRfaction -= ekinIndxLow;
101 ekinIndxLow += (gNumEkin - gNumBeta2);
102 } else if (logekin>=fLogMinEkin) {
103 remRfaction = (logekin - fLogMinEkin) * fInvLogDelEkin;
104 ekinIndxLow = (G4int)remRfaction;
105 remRfaction -= ekinIndxLow;
106 } // the defaults otherwise i.e. use the lowest energy values when ekin is smaller than the minum ekin
107 //
108 DataPerEkin *perEkinLow = fMCDataPerMaterial[matindx]->fDataPerEkin[ekinIndxLow];
109 mcToScr = perEkinLow->fMCScreening;
110 mcToQ1 = perEkinLow->fMCFirstMoment;
111 mcToG2PerG1 = perEkinLow->fMCSecondMoment;
112 if (remRfaction>0.) {
113 DataPerEkin *perEkinHigh = fMCDataPerMaterial[matindx]->fDataPerEkin[ekinIndxLow+1];
114 mcToScr += remRfaction*(perEkinHigh->fMCScreening - perEkinLow->fMCScreening);
115 mcToQ1 += remRfaction*(perEkinHigh->fMCFirstMoment - perEkinLow->fMCFirstMoment);
116 mcToG2PerG1 += remRfaction*(perEkinHigh->fMCSecondMoment - perEkinLow->fMCSecondMoment);
117 }
118}
119
120
121// accept cost if rndm [0,1] < return value
123 G4int matindx, G4int &ekindx, G4int &deltindx) {
124 G4double val = 1.0;
125 G4double delta = q1/(0.5+q1);
126 // check if converged to 1 for all angles => accept cost
127 if (delta>=gMaxDelta) {
128 return val;
129 }
130 //
131 // check if kinetic energy index needs to be determined
132 if (ekindx<0) {
133 G4int ekinIndxLow = 0;
134 G4double probIndxHigh = 0.; // will be the prob. of taking the ekinIndxLow+1 bin
135 if (beta2>gMaxBeta2) {
136 ekinIndxLow = gNumEkin - 1;
137 // probIndxHigh = -1.
138 } else if (beta2>=fMinBeta2) { // linear interpolation on \beta^2
139 probIndxHigh = (beta2 - fMinBeta2) * fInvDelBeta2;
140 ekinIndxLow = (G4int)probIndxHigh;
141 probIndxHigh -= ekinIndxLow;
142 ekinIndxLow += (gNumEkin - gNumBeta2);
143 } else if (logekin>fLogMinEkin) { // linear interpolation on \ln(E_{kin})
144 probIndxHigh = (logekin - fLogMinEkin) * fInvLogDelEkin;
145 ekinIndxLow = (G4int)probIndxHigh;
146 probIndxHigh -= ekinIndxLow;
147 } // the defaults otherwise i.e. use the lowest energy values when ekin is smaller than the minum ekin
148 //
149 // check if need to take the higher ekin index
150 if (G4UniformRand()<probIndxHigh) {
151 ++ekinIndxLow;
152 }
153 // set kinetic energy grid index
154 ekindx = ekinIndxLow;
155 }
156 // check if delta value index needs to be determined (note: in case of single scattering deltindx will be set to 0 by
157 // by the caller but the ekindx will be -1: kinetic energy index is not known but the delta index is known)
158 if (deltindx<0) {
159 // note: delta is for sure < gMaxDelta at this point ( and minimum delta value is 0)
160 G4double probIndxHigh = delta*fInvDelDelta; // will be the prob. of taking the deltIndxLow+1 bin
161 G4int deltIndxLow = (G4int)probIndxHigh;
162 probIndxHigh -= deltIndxLow;
163 // check if need to take the higher delta index
164 if (G4UniformRand()<probIndxHigh) {
165 ++deltIndxLow;
166 }
167 // set the delta value grid index
168 deltindx = deltIndxLow;
169 }
170 //
171 // get the corresponding distribution
172 DataPerDelta *perDelta = fMCDataPerMaterial[matindx]->fDataPerEkin[ekindx]->fDataPerDelta[deltindx];
173 //
174 // determine lower index of the angular bin
175 G4double ang = std::sqrt(0.5*(1.-cost)); // sin(0.5\theta) in [0,1]
176 G4double remRfaction = ang*fInvDelAngle;
177 G4int angIndx = (G4int)remRfaction;
178 remRfaction -= angIndx;
179 if (angIndx<gNumAngle-2) { // normal case: linear interpolation
180 val = remRfaction*(perDelta->fRejFuntion[angIndx+1]-perDelta->fRejFuntion[angIndx]) + perDelta->fRejFuntion[angIndx];
181 } else { // last bin
182 G4double dum = ang-1.+1./fInvDelAngle;
183 val = perDelta->fSA + dum*(perDelta->fSB + dum*(perDelta->fSC + dum*perDelta->fSD));
184 }
185 return val;
186}
187
188
190 // load Mott-correction data for each elements that belongs to materials that are used in the detector
191 InitMCDataPerElement();
192 // clrea Mott-correction data per material
193 ClearMCDataPerMaterial();
194 // initialise Mott-correction data for the materials that are used in the detector
195 InitMCDataPerMaterials();
196}
197
198
199void G4GSMottCorrection::InitMCDataPerElement() {
200 // do it only once
201 if (fMCDataPerElement.size()<gMaxZet+1) {
202 fMCDataPerElement.resize(gMaxZet+1,nullptr);
203 }
204 // loop over all materials, for those that are used check the list of elements and load data from file if the
205 // corresponding data has not been loaded yet
207 G4int numMatCuts = (G4int)thePCTable->GetTableSize();
208 for (G4int imc=0; imc<numMatCuts; ++imc) {
209 const G4MaterialCutsCouple *matCut = thePCTable->GetMaterialCutsCouple(imc);
210 if (!matCut->IsUsed()) {
211 continue;
212 }
213 const G4Material *mat = matCut->GetMaterial();
214 const G4ElementVector *elemVect = mat->GetElementVector();
215 //
216 std::size_t numElems = elemVect->size();
217 for (std::size_t ielem=0; ielem<numElems; ++ielem) {
218 const G4Element *elem = (*elemVect)[ielem];
219 G4int izet = G4lrint(elem->GetZ());
220 if (izet>gMaxZet) {
221 izet = gMaxZet;
222 }
223 if (!fMCDataPerElement[izet]) {
224 LoadMCDataElement(elem);
225 }
226 }
227 }
228}
229
230
231void G4GSMottCorrection::InitMCDataPerMaterials() {
232 // prepare size of the container
233 std::size_t numMaterials = G4Material::GetNumberOfMaterials();
234 if (fMCDataPerMaterial.size()!=numMaterials) {
235 fMCDataPerMaterial.resize(numMaterials);
236 }
237 // init. Mott-correction data for the Materials that are used in the geometry
239 G4int numMatCuts = (G4int)thePCTable->GetTableSize();
240 for (G4int imc=0; imc<numMatCuts; ++imc) {
241 const G4MaterialCutsCouple *matCut = thePCTable->GetMaterialCutsCouple(imc);
242 if (!matCut->IsUsed()) {
243 continue;
244 }
245 const G4Material *mat = matCut->GetMaterial();
246 if (!fMCDataPerMaterial[mat->GetIndex()]) {
247 InitMCDataMaterial(mat);
248 }
249 }
250}
251
252
253// it's called only if data has not been loaded for this element yet
254void G4GSMottCorrection::LoadMCDataElement(const G4Element *elem) {
255 // allocate memory
256 G4int izet = elem->GetZasInt();
257 if (izet>gMaxZet) {
258 izet = gMaxZet;
259 }
260 auto perElem = new DataPerMaterial();
261 AllocateDataPerMaterial(perElem);
262 fMCDataPerElement[izet] = perElem;
263 //
264 // load data from file
265 const char* tmppath = G4FindDataDir("G4LEDATA");
266 if (!tmppath) {
267 G4Exception("G4GSMottCorrection::LoadMCDataElement()","em0006",
269 "Environment variable G4LEDATA not defined");
270 return;
271 }
272 std::string path(tmppath);
273 if (fIsElectron) {
274 path += "/msc_GS/MottCor/el/";
275 } else {
276 path += "/msc_GS/MottCor/pos/";
277 }
278 std::string fname = path+"rej_"+gElemSymbols[izet-1];
279 std::istringstream infile(std::ios::in);
280 ReadCompressedFile(fname, infile);
281 // check if file is open !!!
282 for (G4int iek=0; iek<gNumEkin; ++iek) {
283 DataPerEkin *perEkin = perElem->fDataPerEkin[iek];
284 // 1. get the 3 Mott-correction factors for the current kinetic energy
285 infile >> perEkin->fMCScreening;
286 infile >> perEkin->fMCFirstMoment;
287 infile >> perEkin->fMCSecondMoment;
288 // 2. load each data per delta:
289 for (G4int idel=0; idel<gNumDelta; ++idel) {
290 DataPerDelta *perDelta = perEkin->fDataPerDelta[idel];
291 // 2./a. : first the rejection function values
292 for (G4int iang=0; iang<gNumAngle; ++iang) {
293 infile >> perDelta->fRejFuntion[iang];
294 }
295 // 2./b. : then the 4 spline parameter for the last bin
296 infile >> perDelta->fSA;
297 infile >> perDelta->fSB;
298 infile >> perDelta->fSC;
299 infile >> perDelta->fSD;
300 }
301 }
302}
303
304// uncompress one data file into the input string stream
305void G4GSMottCorrection::ReadCompressedFile(std::string fname, std::istringstream &iss) {
306 std::string *dataString = nullptr;
307 std::string compfilename(fname+".z");
308 // create input stream with binary mode operation and positioning at the end of the file
309 std::ifstream in(compfilename, std::ios::binary | std::ios::ate);
310 if (in.good()) {
311 // get current position in the stream (was set to the end)
312 std::streamoff fileSize = in.tellg();
313 // set current position being the beginning of the stream
314 in.seekg(0,std::ios::beg);
315 // create (zlib) byte buffer for the data
316 Bytef *compdata = new Bytef[fileSize];
317 while(in) {
318 in.read((char*)compdata, fileSize);
319 }
320 // create (zlib) byte buffer for the uncompressed data
321 uLongf complen = (uLongf)(fileSize*4);
322 Bytef *uncompdata = new Bytef[complen];
323 while (Z_OK!=uncompress(uncompdata, &complen, compdata, fileSize)) {
324 // increase uncompressed byte buffer
325 delete[] uncompdata;
326 complen *= 2;
327 uncompdata = new Bytef[complen];
328 }
329 // delete the compressed data buffer
330 delete [] compdata;
331 // create a string from the uncompressed data (will be deallocated by the caller)
332 dataString = new std::string((char*)uncompdata, (long)complen);
333 // delete the uncompressed data buffer
334 delete [] uncompdata;
335 } else {
336 std::string msg = " Problem while trying to read " + compfilename + " data file.\n";
337 G4Exception("G4GSMottCorrection::ReadCompressedFile","em0006", FatalException,msg.c_str());
338 return;
339 }
340 // create the input string stream from the data string
341 if (dataString) {
342 iss.str(*dataString);
343 in.close();
344 delete dataString;
345 }
346}
347
348
349void G4GSMottCorrection::InitMCDataMaterial(const G4Material *mat) {
350 constexpr G4double const1 = 7821.6; // [cm2/g]
351 constexpr G4double const2 = 0.1569; // [cm2 MeV2 / g]
352 constexpr G4double finstrc2 = 5.325135453E-5; // fine-structure const. square
353
354 G4double constFactor = CLHEP::electron_mass_c2*CLHEP::fine_structure_const/0.88534;
355 constFactor *= constFactor; // (mc^2)^2\alpha^2/( C_{TF}^2)
356 // allocate memory
357 auto perMat = new DataPerMaterial();
358 AllocateDataPerMaterial(perMat);
359 fMCDataPerMaterial[mat->GetIndex()] = perMat;
360 //
361 const G4ElementVector* elemVect = mat->GetElementVector();
362 const G4int numElems = (G4int)mat->GetNumberOfElements();
363 const G4double* nbAtomsPerVolVect = mat->GetVecNbOfAtomsPerVolume();
364 G4double totNbAtomsPerVol = mat->GetTotNbOfAtomsPerVolume();
365 //
366 // 1. Compute material dependent part of Moliere's b_c \chi_c^2
367 // (with \xi=1 (i.e. total sub-threshold scattering power correction)
368 G4double moliereBc = 0.0;
369 G4double moliereXc2 = 0.0;
370 G4double zs = 0.0;
371 G4double ze = 0.0;
372 G4double zx = 0.0;
373 G4double sa = 0.0;
374 G4double xi = 1.0;
375 for (G4int ielem=0; ielem<numElems; ++ielem) {
376 G4double zet = (*elemVect)[ielem]->GetZ();
377 if (zet>gMaxZet) {
378 zet = (G4double)gMaxZet;
379 }
380 G4double iwa = (*elemVect)[ielem]->GetN();
381 G4double ipz = nbAtomsPerVolVect[ielem]/totNbAtomsPerVol;
382 G4double dum = ipz*zet*(zet+xi);
383 zs += dum;
384 ze += dum*(-2.0/3.0)*G4Log(zet);
385 zx += dum*G4Log(1.0+3.34*finstrc2*zet*zet);
386 sa += ipz*iwa;
387 }
388 G4double density = mat->GetDensity()*CLHEP::cm3/CLHEP::g; // [g/cm3]
389 //
390 moliereBc = const1*density*zs/sa*G4Exp(ze/zs)/G4Exp(zx/zs); //[1/cm]
391 moliereXc2 = const2*density*zs/sa; // [MeV2/cm]
392 // change to Geant4 internal units of 1/length and energ2/length
393 moliereBc *= 1.0/CLHEP::cm;
394 moliereXc2 *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
395 //
396 // 2. loop over the kinetic energy grid
397 for (G4int iek=0; iek<gNumEkin; ++iek) {
398 // 2./a. set current kinetic energy and pt2 value
399 G4double ekin = G4Exp(fLogMinEkin+iek/fInvLogDelEkin);
400 G4double pt2 = ekin*(ekin+2.0*CLHEP::electron_mass_c2);
401 if (ekin>gMidEkin) {
402 G4double b2 = fMinBeta2+(iek-(gNumEkin-gNumBeta2))/fInvDelBeta2;
403 ekin = CLHEP::electron_mass_c2*(1./std::sqrt(1.-b2)-1.);
404 pt2 = ekin*(ekin+2.0*CLHEP::electron_mass_c2);
405 }
406 // 2./b. loop over the elements at the current kinetic energy point
407 for (G4int ielem=0; ielem<numElems; ++ielem) {
408 const G4Element *elem = (*elemVect)[ielem];
409 G4double zet = elem->GetZ();
410 if (zet>gMaxZet) {
411 zet = (G4double)gMaxZet;
412 }
413 G4int izet = G4lrint(zet);
414 // xi should be one i.e. z(z+1) since total sub-threshold scattering power correction
415 G4double nZZPlus1 = nbAtomsPerVolVect[ielem]*zet*(zet+1.0)/totNbAtomsPerVol;
416 G4double Z23 = std::pow(zet,2./3.);
417 //
418 DataPerEkin *perElemPerEkin = fMCDataPerElement[izet]->fDataPerEkin[iek];
419 DataPerEkin *perMatPerEkin = perMat->fDataPerEkin[iek];
420 //
421 // 2./b./(i) Add the 3 Mott-correction factors
422 G4double mcScrCF = perElemPerEkin->fMCScreening; // \kappa_i[1.13+3.76(\alpha Z_i)^2] with \kappa_i=scr_mc/scr_sr
423 // compute the screening parameter correction factor (Z_i contribution to the material)
424 // src_{mc} = C \exp\left[ \frac{ \sum_i n_i Z_i(Z_i+1)\ln[Z_{i}^{2/3}\kappa_i(1.13+3.76(\alpha Z_i)^2)] } {\sum_i n_i Z_i(Z_i+1)}
425 // with C = \frac{(mc^2)^\alpha^2} {4(pc)^2 C_{TF}^2} = constFactor/(4*(pc)^2)
426 // here we compute the \sum_i n_i Z_i(Z_i+1)\ln[Z_{i}^{2/3}\kappa_i(1.13+3.76(\alpha Z_i)^2)] part
427 perMatPerEkin->fMCScreening += nZZPlus1*G4Log(Z23*mcScrCF);
428 // compute the corrected screening parameter for the current Z_i and E_{kin}
429 // src(Z_i)_{mc} = \frac{(mc^2)^\alpha^2 Z_i^{2/3}} {4(pc)^2 C_{TF}^2} \kappa_i[1.13+3.76(\alpha Z_i)^2]
430 mcScrCF *= constFactor*Z23/(4.*pt2);
431 // compute first moment correction factor
432 // q1_{mc} = \frac{ \sum_i n_i Z_i(Z_i+1) A_i B_i } {\sum_i n_i Z_i(Z_i+1)} \frac{1}{C}
433 // where:
434 // A_i(src(Z_i)_{mc}) = [\ln(1+1/src(Z_i)_{mc}) - 1/(1+src(Z_i)_{mc})]; where \sigma(Z_i)_{tr1}^(sr) = A_i(src(Z_i)_{mc}) [2\pi r_0 Z_i mc^2/(pc)\beta]^2
435 // B_i = \beta_i \gamma_i with beta_i(Z_i) = \sigma(Z_i)_{tr1}^(PWA)/\sigma(Z_i,src(Z_i)_{mc})_{tr1}^(sr)
436 // and \gamma_i = \sigma(Z_i)_{el}^(MC-DCS)/\sigma(Z_i,src(Z_i)_{mc})_{el}^(sr)
437 // C(src_{mc}) = [\ln(1+1/src_{mc}) - 1/(1+src_{mc})]; where \sigma_{tr1}^(sr) = C(src_{mc}) [2\pi r_0 Z_i mc^2/(pc)\beta]^2
438 // A_i x B_i is stored in file per e-/e+, E_{kin} and Z_i
439 // here we compute the \sum_i n_i Z_i(Z_i+1) A_i B_i part
440 perMatPerEkin->fMCFirstMoment += nZZPlus1*(G4Log(1.+1./mcScrCF)-1./(1.+mcScrCF))*perElemPerEkin->fMCFirstMoment;
441 // compute the second moment correction factor
442 // [G2/G1]_{mc} = \frac{ \sum_i n_i Z_i(Z_i+1) A_i } {\sum_i n_i Z_i(Z_i+1)} \frac{1}{C}
443 // with A_i(Z_i) = G2(Z_i)^{PWA}/G1(Z_i)^{PWA} and C=G2(Z_i,scr_{mc})^{sr}/G1(Z_i,scr_{mc})^{sr}}
444 // here we compute the \sum_i n_i Z_i(Z_i+1) A_i part
445 perMatPerEkin->fMCSecondMoment += nZZPlus1*perElemPerEkin->fMCSecondMoment;
446 //
447 // 2./b./(ii) Go for the rejection funtion part
448 // I. loop over delta values
449 for (G4int idel=0; idel<gNumDelta; ++idel) {
450 DataPerDelta *perMatPerDelta = perMatPerEkin->fDataPerDelta[idel];
451 DataPerDelta *perElemPerDelta = perElemPerEkin->fDataPerDelta[idel];
452 // I./a. loop over angles (i.e. the \sin(0.5\theta) values) and add the rejection function
453 for (G4int iang=0; iang<gNumAngle; ++iang) {
454 perMatPerDelta->fRejFuntion[iang] += nZZPlus1*perElemPerDelta->fRejFuntion[iang];
455 }
456 // I./b. get the last bin spline parameters and add them (a+bx+cx^2+dx^3)
457 perMatPerDelta->fSA += nZZPlus1*perElemPerDelta->fSA;
458 perMatPerDelta->fSB += nZZPlus1*perElemPerDelta->fSB;
459 perMatPerDelta->fSC += nZZPlus1*perElemPerDelta->fSC;
460 perMatPerDelta->fSD += nZZPlus1*perElemPerDelta->fSD;
461 }
462 //
463 // 2./b./(iii) When the last element has been added:
464 if (ielem==numElems-1) {
465 //
466 // 1. the remaining part of the sreening correction and divide the corrected screening par. with Moliere's one:
467 // (Moliere screening parameter = moliereXc2/(4(pc)^2 moliereBc) )
468 G4double dumScr = G4Exp(perMatPerEkin->fMCScreening/zs);
469 perMatPerEkin->fMCScreening = constFactor*dumScr*moliereBc/moliereXc2;
470 //
471 // 2. the remaining part of the first moment correction and divide by the one computed by using the corrected
472 // screening parameter (= (mc^2)^\alpha^2/(4(pc)^2C_{TF}^2) dumScr
473 G4double scrCorTed = constFactor*dumScr/(4.*pt2);
474 G4double dum0 = G4Log(1.+1./scrCorTed);
475 perMatPerEkin->fMCFirstMoment = perMatPerEkin->fMCFirstMoment/(zs*(dum0-1./(1.+scrCorTed)));
476 //
477 // 3. the remaining part of the second moment correction and divide by the one computed by using the corrected
478 // screening parameter
479 G4double G2PerG1 = 3.*(1.+scrCorTed)*((1.+2.*scrCorTed)*dum0-2.)/((1.+scrCorTed)*dum0-1.);
480 perMatPerEkin->fMCSecondMoment = perMatPerEkin->fMCSecondMoment/(zs*G2PerG1);
481 //
482 // 4. scale the maximum of the rejection function to unity and correct the last bin spline parameters as well
483 // I. loop over delta values
484 for (G4int idel=0; idel<gNumDelta; ++idel) {
485 DataPerDelta *perMatPerDelta = perMatPerEkin->fDataPerDelta[idel];
486 G4double maxVal = -1.;
487 // II. llop over angles
488 for (G4int iang=0; iang<gNumAngle; ++iang) {
489 if (perMatPerDelta->fRejFuntion[iang]>maxVal)
490 maxVal = perMatPerDelta->fRejFuntion[iang];
491 }
492 for (G4int iang=0; iang<gNumAngle; ++iang) {
493 perMatPerDelta->fRejFuntion[iang] /=maxVal;
494 }
495 perMatPerDelta->fSA /= maxVal;
496 perMatPerDelta->fSB /= maxVal;
497 perMatPerDelta->fSC /= maxVal;
498 perMatPerDelta->fSD /= maxVal;
499 }
500 }
501 }
502 }
503}
504
505
506void G4GSMottCorrection::AllocateDataPerMaterial(DataPerMaterial *data) {
507 data->fDataPerEkin = new DataPerEkin*[gNumEkin]();
508 for (G4int iek=0; iek<gNumEkin; ++iek) {
509 auto perEkin = new DataPerEkin();
510 perEkin->fDataPerDelta = new DataPerDelta*[gNumDelta]();
511 for (G4int idel=0; idel<gNumDelta; ++idel) {
512 auto perDelta = new DataPerDelta();
513 perDelta->fRejFuntion = new double[gNumAngle]();
514 perEkin->fDataPerDelta[idel] = perDelta;
515 }
516 data->fDataPerEkin[iek] = perEkin;
517 }
518}
519
520void G4GSMottCorrection::DeAllocateDataPerMaterial(DataPerMaterial *data) {
521 for (G4int iek=0; iek<gNumEkin; ++iek) {
522 DataPerEkin *perEkin = data->fDataPerEkin[iek]; //new DataPerEkin();
523 for (G4int idel=0; idel<gNumDelta; ++idel) {
524 DataPerDelta *perDelta = perEkin->fDataPerDelta[idel];
525 delete [] perDelta->fRejFuntion;
526 delete perDelta;
527 }
528 delete [] perEkin->fDataPerDelta;
529 delete perEkin;
530 }
531 delete [] data->fDataPerEkin;
532}
533
534
535void G4GSMottCorrection::ClearMCDataPerElement() {
536 for (std::size_t i=0; i<fMCDataPerElement.size(); ++i) {
537 if (fMCDataPerElement[i]) {
538 DeAllocateDataPerMaterial(fMCDataPerElement[i]);
539 delete fMCDataPerElement[i];
540 }
541 }
542 fMCDataPerElement.clear();
543}
544
545void G4GSMottCorrection::ClearMCDataPerMaterial() {
546 for (std::size_t i=0; i<fMCDataPerMaterial.size(); ++i) {
547 if (fMCDataPerMaterial[i]) {
548 DeAllocateDataPerMaterial(fMCDataPerMaterial[i]);
549 delete fMCDataPerMaterial[i];
550 }
551 }
552 fMCDataPerMaterial.clear();
553}
std::vector< const G4Element * > G4ElementVector
const char * G4FindDataDir(const char *)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
#define elem(i, j)
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4UniformRand()
Definition: Randomize.hh:52
G4GSMottCorrection(G4bool iselectron=true)
void GetMottCorrectionFactors(G4double logekin, G4double beta2, G4int matindx, G4double &mcToScr, G4double &mcToQ1, G4double &mcToG2PerG1)
G4double GetMottRejectionValue(G4double logekin, G4double G4beta2, G4double q1, G4double cost, G4int matindx, G4int &ekindx, G4int &deltindx)
const G4Material * GetMaterial() const
G4double GetDensity() const
Definition: G4Material.hh:175
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:185
G4double GetTotNbOfAtomsPerVolume() const
Definition: G4Material.hh:204
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:684
size_t GetNumberOfElements() const
Definition: G4Material.hh:181
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:201
size_t GetIndex() const
Definition: G4Material.hh:255
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
int G4lrint(double ad)
Definition: templates.hh:134
int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
Definition: uncompr.c:85
#define Z_OK
Definition: zlib.h:177