Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4GSPWACorrections.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: G4GSPWACorrections
31//
32// Author: Mihaly Novak
33//
34// Creation date: 17.10.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 "G4GSPWACorrections.hh"
44
46#include "G4Log.hh"
47#include "G4Exp.hh"
48
51#include "G4Material.hh"
52#include "G4ElementVector.hh"
53#include "G4Element.hh"
54#include "G4EmParameters.hh"
55
56
57const std::string G4GSPWACorrections::gElemSymbols[] = {"H","He","Li","Be","B" ,
58 "C" ,"N" ,"O" ,"F" ,"Ne","Na","Mg","Al","Si","P" , "S","Cl","Ar","K" ,"Ca","Sc",
59 "Ti","V" ,"Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr","Rb",
60 "Sr","Y" ,"Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I" ,
61 "Xe","Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm",
62 "Yb","Lu","Hf","Ta","W" ,"Re","Os","Ir","Pt","Au","Hg","Tl","Pb","Bi","Po","At",
63 "Rn","Fr","Ra","Ac","Th","Pa","U" ,"Np","Pu","Am","Cm","Bk","Cf"};
64
65G4GSPWACorrections::G4GSPWACorrections(G4bool iselectron) : fIsElectron(iselectron) {
66 // init grids related data member values
67 fMaxEkin = CLHEP::electron_mass_c2*(1./std::sqrt(1.-gMaxBeta2)-1.);
68 fLogMinEkin = G4Log(gMinEkin);
69 fInvLogDelEkin = (gNumEkin-gNumBeta2)/G4Log(gMidEkin/gMinEkin);
70 G4double pt2 = gMidEkin*(gMidEkin+2.0*CLHEP::electron_mass_c2);
71 fMinBeta2 = pt2/(pt2+CLHEP::electron_mass_c2*CLHEP::electron_mass_c2);
72 fInvDelBeta2 = (gNumBeta2-1.)/(gMaxBeta2-fMinBeta2);
73}
74
75
77 ClearDataPerElement();
78 ClearDataPerMaterial();
79}
80
81
83 G4double &corToScr, G4double &corToQ1, G4double &corToG2PerG1) {
84 G4int ekinIndxLow = 0;
85 G4double remRfaction = 0.;
86 if (beta2>=gMaxBeta2) {
87 ekinIndxLow = gNumEkin - 1;
88 // remRfaction = -1.
89 } else if (beta2>=fMinBeta2) { // linear interpolation on \beta^2
90 remRfaction = (beta2 - fMinBeta2) * fInvDelBeta2;
91 ekinIndxLow = (G4int)remRfaction;
92 remRfaction -= ekinIndxLow;
93 ekinIndxLow += (gNumEkin - gNumBeta2);
94 } else if (logekin>=fLogMinEkin) {
95 remRfaction = (logekin - fLogMinEkin) * fInvLogDelEkin;
96 ekinIndxLow = (G4int)remRfaction;
97 remRfaction -= ekinIndxLow;
98 } // the defaults otherwise i.e. use the lowest energy values when ekin is smaller than the minum ekin
99 //
100 DataPerMaterial *data = fDataPerMaterial[matindx];
101 corToScr = data->fCorScreening[ekinIndxLow];
102 corToQ1 = data->fCorFirstMoment[ekinIndxLow];
103 corToG2PerG1 = data->fCorSecondMoment[ekinIndxLow];
104 if (remRfaction>0.) {
105 corToScr += remRfaction*(data->fCorScreening[ekinIndxLow+1] - data->fCorScreening[ekinIndxLow]);
106 corToQ1 += remRfaction*(data->fCorFirstMoment[ekinIndxLow+1] - data->fCorFirstMoment[ekinIndxLow]);
107 corToG2PerG1 += remRfaction*(data->fCorSecondMoment[ekinIndxLow+1] - data->fCorSecondMoment[ekinIndxLow]);
108 }
109}
110
111
113 // load PWA correction data for each elements that belongs to materials that are used in the detector
114 InitDataPerElement();
115 // clear PWA correction data per material
116 ClearDataPerMaterial();
117 // initialise PWA correction data for the materials that are used in the detector
118 InitDataPerMaterials();
119}
120
121
122void G4GSPWACorrections::InitDataPerElement() {
123 // do it only once
124 if (fDataPerElement.size()<gMaxZet+1) {
125 fDataPerElement.resize(gMaxZet+1,nullptr);
126 }
127 // loop over all materials, for those that are used check the list of elements and load data from file if the
128 // corresponding data has not been loaded yet
130 G4int numMatCuts = (G4int)thePCTable->GetTableSize();
131 for (G4int imc=0; imc<numMatCuts; ++imc) {
132 const G4MaterialCutsCouple *matCut = thePCTable->GetMaterialCutsCouple(imc);
133 if (!matCut->IsUsed()) {
134 continue;
135 }
136 const G4Material *mat = matCut->GetMaterial();
137 const G4ElementVector *elemVect = mat->GetElementVector();
138 //
139 std::size_t numElems = elemVect->size();
140 for (std::size_t ielem=0; ielem<numElems; ++ielem) {
141 const G4Element *elem = (*elemVect)[ielem];
142 G4int izet = G4lrint(elem->GetZ());
143 if (izet>gMaxZet) {
144 izet = gMaxZet;
145 }
146 if (!fDataPerElement[izet]) {
147 LoadDataElement(elem);
148 }
149 }
150 }
151}
152
153
154void G4GSPWACorrections::InitDataPerMaterials() {
155 // prepare size of the container
156 std::size_t numMaterials = G4Material::GetNumberOfMaterials();
157 if (fDataPerMaterial.size()!=numMaterials) {
158 fDataPerMaterial.resize(numMaterials);
159 }
160 // init. PWA correction data for the Materials that are used in the geometry
162 G4int numMatCuts = (G4int)thePCTable->GetTableSize();
163 for (G4int imc=0; imc<numMatCuts; ++imc) {
164 const G4MaterialCutsCouple *matCut = thePCTable->GetMaterialCutsCouple(imc);
165 if (!matCut->IsUsed()) {
166 continue;
167 }
168 const G4Material *mat = matCut->GetMaterial();
169 if (!fDataPerMaterial[mat->GetIndex()]) {
170 InitDataMaterial(mat);
171 }
172 }
173}
174
175
176// it's called only if data has not been loaded for this element yet
177void G4GSPWACorrections::LoadDataElement(const G4Element *elem) {
178 // allocate memory
179 G4int izet = elem->GetZasInt();
180 if (izet>gMaxZet) {
181 izet = gMaxZet;
182 }
183 // load data from file
184 std::string path = G4EmParameters::Instance()->GetDirLEDATA();
185 if (fIsElectron) {
186 path += "/msc_GS/PWACor/el/";
187 } else {
188 path += "/msc_GS/PWACor/pos/";
189 }
190 std::string fname = path+"cf_"+gElemSymbols[izet-1];
191 std::ifstream infile(fname,std::ios::in);
192 if (!infile.is_open()) {
193 std::string msg = " Problem while trying to read " + fname + " data file.\n";
194 G4Exception("G4GSPWACorrection::LoadDataElement","em0006", FatalException,msg.c_str());
195 return;
196 }
197 // allocate data structure
198 auto perElem = new DataPerMaterial();
199 perElem->fCorScreening.resize(gNumEkin,0.0);
200 perElem->fCorFirstMoment.resize(gNumEkin,0.0);
201 perElem->fCorSecondMoment.resize(gNumEkin,0.0);
202 fDataPerElement[izet] = perElem;
203 G4double dum0;
204 for (G4int iek=0; iek<gNumEkin; ++iek) {
205 infile >> dum0;
206 infile >> perElem->fCorScreening[iek];
207 infile >> perElem->fCorFirstMoment[iek];
208 infile >> perElem->fCorSecondMoment[iek];
209 }
210 infile.close();
211}
212
213
214void G4GSPWACorrections::InitDataMaterial(const G4Material *mat) {
215 constexpr G4double const1 = 7821.6; // [cm2/g]
216 constexpr G4double const2 = 0.1569; // [cm2 MeV2 / g]
217 constexpr G4double finstrc2 = 5.325135453E-5; // fine-structure const. square
218
219 G4double constFactor = CLHEP::electron_mass_c2*CLHEP::fine_structure_const/0.88534;
220 constFactor *= constFactor; // (mc^2)^2\alpha^2/( C_{TF}^2)
221 // allocate memory
222 auto perMat = new DataPerMaterial();
223 perMat->fCorScreening.resize(gNumEkin,0.0);
224 perMat->fCorFirstMoment.resize(gNumEkin,0.0);
225 perMat->fCorSecondMoment.resize(gNumEkin,0.0);
226 fDataPerMaterial[mat->GetIndex()] = perMat;
227 //
228 const G4ElementVector* elemVect = mat->GetElementVector();
229 const G4int numElems = (G4int)mat->GetNumberOfElements();
230 const G4double* nbAtomsPerVolVect = mat->GetVecNbOfAtomsPerVolume();
231 G4double totNbAtomsPerVol = mat->GetTotNbOfAtomsPerVolume();
232 //
233 // 1. Compute material dependent part of Moliere's b_c \chi_c^2
234 // (with \xi=1 (i.e. total sub-threshold scattering power correction)
235 G4double moliereBc = 0.0;
236 G4double moliereXc2 = 0.0;
237 G4double zs = 0.0;
238 G4double ze = 0.0;
239 G4double zx = 0.0;
240 G4double sa = 0.0;
241 G4double xi = 1.0;
242 for (G4int ielem=0; ielem<numElems; ++ielem) {
243 G4double zet = (*elemVect)[ielem]->GetZ();
244 if (zet>gMaxZet) {
245 zet = (G4double)gMaxZet;
246 }
247 G4double iwa = (*elemVect)[ielem]->GetN();
248 G4double ipz = nbAtomsPerVolVect[ielem]/totNbAtomsPerVol;
249 G4double dum = ipz*zet*(zet+xi);
250 zs += dum;
251 ze += dum*(-2.0/3.0)*G4Log(zet);
252 zx += dum*G4Log(1.0+3.34*finstrc2*zet*zet);
253 sa += ipz*iwa;
254 }
255 G4double density = mat->GetDensity()*CLHEP::cm3/CLHEP::g; // [g/cm3]
256 //
257 moliereBc = const1*density*zs/sa*G4Exp(ze/zs)/G4Exp(zx/zs); //[1/cm]
258 moliereXc2 = const2*density*zs/sa; // [MeV2/cm]
259 // change to Geant4 internal units of 1/length and energ2/length
260 moliereBc *= 1.0/CLHEP::cm;
261 moliereXc2 *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
262 //
263 // 2. loop over the kinetic energy grid
264 for (G4int iek=0; iek<gNumEkin; ++iek) {
265 // 2./a. set current kinetic energy and pt2 value
266 G4double ekin = G4Exp(fLogMinEkin+iek/fInvLogDelEkin);
267 G4double pt2 = ekin*(ekin+2.0*CLHEP::electron_mass_c2);
268 if (ekin>gMidEkin) {
269 G4double b2 = fMinBeta2+(iek-(gNumEkin-gNumBeta2))/fInvDelBeta2;
270 ekin = CLHEP::electron_mass_c2*(1./std::sqrt(1.-b2)-1.);
271 pt2 = ekin*(ekin+2.0*CLHEP::electron_mass_c2);
272 }
273 // 2./b. loop over the elements at the current kinetic energy point
274 for (G4int ielem=0; ielem<numElems; ++ielem) {
275 const G4Element *elem = (*elemVect)[ielem];
276 G4double zet = elem->GetZ();
277 if (zet>gMaxZet) {
278 zet = (G4double)gMaxZet;
279 }
280 G4int izet = G4lrint(zet);
281 // loaded PWA corrections for the current element
282 DataPerMaterial *perElem = fDataPerElement[izet];
283 //
284 // xi should be one i.e. z(z+1) since total sub-threshold scattering power correction
285 G4double nZZPlus1 = nbAtomsPerVolVect[ielem]*zet*(zet+1.0)/totNbAtomsPerVol;
286 G4double Z23 = std::pow(zet,2./3.);
287 //
288 // 2./b./(i) Add the 3 PWA correction factors
289 G4double mcScrCF = perElem->fCorScreening[iek]; // \kappa_i[1.13+3.76(\alpha Z_i)^2] with \kappa_i=scr_mc/scr_sr
290 // compute the screening parameter correction factor (Z_i contribution to the material)
291 // 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)}
292 // with C = \frac{(mc^2)^\alpha^2} {4(pc)^2 C_{TF}^2} = constFactor/(4*(pc)^2)
293 // 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
294 perMat->fCorScreening[iek] += nZZPlus1*G4Log(Z23*mcScrCF);
295 // compute the corrected screening parameter for the current Z_i and E_{kin}
296 // 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]
297 mcScrCF *= constFactor*Z23/(4.*pt2);
298 // compute first moment correction factor
299 // 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}
300 // where:
301 // 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
302 // 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)
303 // and \gamma_i = \sigma(Z_i)_{el}^(MC-DCS)/\sigma(Z_i,src(Z_i)_{mc})_{el}^(sr)
304 // 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
305 // A_i x B_i is stored in file per e-/e+, E_{kin} and Z_i
306 // here we compute the \sum_i n_i Z_i(Z_i+1) A_i B_i part
307 perMat->fCorFirstMoment[iek] += nZZPlus1*(G4Log(1.+1./mcScrCF)-1./(1.+mcScrCF))*perElem->fCorFirstMoment[iek];
308 // compute the second moment correction factor
309 // [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}
310 // 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}}
311 // here we compute the \sum_i n_i Z_i(Z_i+1) A_i part
312 perMat->fCorSecondMoment[iek] += nZZPlus1*perElem->fCorSecondMoment[iek];
313 //
314 // 2./b./(ii) When the last element has been added:
315 if (ielem==numElems-1) {
316 //
317 // 1. the remaining part of the sreening correction and divide the corrected screening par. with Moliere's one:
318 // (Moliere screening parameter = moliereXc2/(4(pc)^2 moliereBc) )
319 G4double dumScr = G4Exp(perMat->fCorScreening[iek]/zs);
320 perMat->fCorScreening[iek] = constFactor*dumScr*moliereBc/moliereXc2;
321 //
322 // 2. the remaining part of the first moment correction and divide by the one computed by using the corrected
323 // screening parameter (= (mc^2)^\alpha^2/(4(pc)^2C_{TF}^2) dumScr
324 G4double scrCorTed = constFactor*dumScr/(4.*pt2);
325 G4double dum0 = G4Log(1.+1./scrCorTed);
326 perMat->fCorFirstMoment[iek] = perMat->fCorFirstMoment[iek]/(zs*(dum0-1./(1.+scrCorTed)));
327 //
328 // 3. the remaining part of the second moment correction and divide by the one computed by using the corrected
329 // screening parameter
330 G4double G2PerG1 = 3.*(1.+scrCorTed)*((1.+2.*scrCorTed)*dum0-2.)/((1.+scrCorTed)*dum0-1.);
331 perMat->fCorSecondMoment[iek] = perMat->fCorSecondMoment[iek]/(zs*G2PerG1);
332 }
333 }
334 }
335}
336
337
338
339void G4GSPWACorrections::ClearDataPerElement() {
340 for (std::size_t i=0; i<fDataPerElement.size(); ++i) {
341 if (fDataPerElement[i]) {
342 fDataPerElement[i]->fCorScreening.clear();
343 fDataPerElement[i]->fCorFirstMoment.clear();
344 fDataPerElement[i]->fCorSecondMoment.clear();
345 delete fDataPerElement[i];
346 }
347 }
348 fDataPerElement.clear();
349}
350
351
352void G4GSPWACorrections::ClearDataPerMaterial() {
353 for (std::size_t i=0; i<fDataPerMaterial.size(); ++i) {
354 if (fDataPerMaterial[i]) {
355 fDataPerMaterial[i]->fCorScreening.clear();
356 fDataPerMaterial[i]->fCorFirstMoment.clear();
357 fDataPerMaterial[i]->fCorSecondMoment.clear();
358 delete fDataPerMaterial[i];
359 }
360 }
361 fDataPerMaterial.clear();
362}
std::vector< const G4Element * > G4ElementVector
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
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
G4double GetZ() const
Definition G4Element.hh:119
static G4EmParameters * Instance()
const G4String & GetDirLEDATA() const
G4GSPWACorrections(G4bool iselectron=true)
void GetPWACorrectionFactors(G4double logekin, G4double beta2, G4int matindx, G4double &corToScr, G4double &corToQ1, G4double &corToG2PerG1)
const G4Material * GetMaterial() const
G4double GetDensity() const
const G4ElementVector * GetElementVector() const
G4double GetTotNbOfAtomsPerVolume() const
static std::size_t GetNumberOfMaterials()
const G4double * GetVecNbOfAtomsPerVolume() const
std::size_t GetIndex() const
std::size_t GetNumberOfElements() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
int G4lrint(double ad)
Definition templates.hh:134