ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4IonisParamMat.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4IonisParamMat.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 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
27 
28 // 09-07-98, data moved from G4Material, M.Maire
29 // 18-07-98, bug corrected in ComputeDensityEffect() for gas
30 // 16-01-01, bug corrected in ComputeDensityEffect() E100eV (L.Urban)
31 // 08-02-01, fShellCorrectionVector correctly handled (mma)
32 // 28-10-02, add setMeanExcitationEnergy (V.Ivanchenko)
33 // 06-09-04, factor 2 to shell correction term (V.Ivanchenko)
34 // 10-05-05, add a missing coma in FindMeanExcitationEnergy() - Bug#746 (mma)
35 // 27-09-07, add computation of parameters for ions (V.Ivanchenko)
36 // 04-03-08, remove reference to G4NistManager. Add fBirks constant (mma)
37 // 30-10-09, add G4DensityEffectData class and density effect computation (VI)
38 
39 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
40 
41 #include "G4IonisParamMat.hh"
42 #include "G4Material.hh"
43 #include "G4DensityEffectData.hh"
45 #include "G4AtomicShells.hh"
46 #include "G4NistManager.hh"
47 #include "G4Pow.hh"
48 #include "G4PhysicalConstants.hh"
49 #include "G4SystemOfUnits.hh"
50 
52 
53 #ifdef G4MULTITHREADED
54  G4Mutex G4IonisParamMat::ionisMutex = G4MUTEX_INITIALIZER;
55 #endif
56 
57 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
58 
60  : fMaterial(material)
61 {
62  fBirks = 0.;
63  fMeanEnergyPerIon = 0.0;
64  twoln10 = 2.*G4Pow::GetInstance()->logZ(10);
65 
66  // minimal set of default parameters for density effect
67  fCdensity = 0.0;
68  fD0density = 0.0;
69  fAdjustmentFactor = 1.0;
70  if(fDensityData == nullptr) { fDensityData = new G4DensityEffectData(); }
71  fDensityEffectCalc = nullptr;
72 
73  // compute parameters
78 }
79 
80 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
81 
82 // Fake default constructor - sets only member data and allocates memory
83 // for usage restricted to object persistency
84 
86  : fMaterial(nullptr), fShellCorrectionVector(nullptr)
87 {
89  fLogMeanExcEnergy = 0.0;
90  fTaul = 0.0;
91  fCdensity = 0.0;
92  fMdensity = 0.0;
93  fAdensity = 0.0;
94  fX0density = 0.0;
95  fX1density = 0.0;
96  fD0density = 0.0;
97  fPlasmaEnergy = 0.0;
98  fAdjustmentFactor = 0.0;
99  fF1fluct = 0.0;
100  fF2fluct = 0.0;
101  fEnergy1fluct = 0.0;
102  fLogEnergy1fluct = 0.0;
103  fEnergy2fluct = 0.0;
104  fLogEnergy2fluct = 0.0;
105  fEnergy0fluct = 0.0;
106  fRateionexcfluct = 0.0;
107  fZeff = 0.0;
108  fFermiEnergy = 0.0;
109  fLfactor = 0.0;
110  fInvA23 = 0.0;
111  fBirks = 0.0;
112  fMeanEnergyPerIon = 0.0;
113  twoln10 = 2.*G4Pow::GetInstance()->logZ(10);
114 
115  fDensityEffectCalc = nullptr;
116  if(fDensityData == nullptr) { fDensityData = new G4DensityEffectData(); }
117 }
118 
119 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
120 
122 {
123  delete fDensityEffectCalc;
124  delete [] fShellCorrectionVector;
125  delete fDensityData;
126  fDensityData = nullptr;
127  fShellCorrectionVector = nullptr;
128  fDensityEffectCalc = nullptr;
129 }
130 
131 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
132 
134 {
135  // compute mean excitation energy and shell correction vector
136  fTaul = (*(fMaterial->GetElementVector()))[0]->GetIonisation()->GetTaul();
137 
139  fLogMeanExcEnergy = 0.;
140 
141  size_t nElements = fMaterial->GetNumberOfElements();
142  const G4ElementVector* elmVector = fMaterial->GetElementVector();
143  const G4double* nAtomsPerVolume = fMaterial->GetVecNbOfAtomsPerVolume();
144 
146 
147  // Chemical formula defines mean excitation energy
148  if(fMeanExcitationEnergy > 0.0) {
150 
151  // Compute average
152  } else {
153  for (size_t i=0; i < nElements; i++) {
154  const G4Element* elm = (*elmVector)[i];
155  fLogMeanExcEnergy += nAtomsPerVolume[i]*elm->GetZ()
157  }
160  }
161 
163 
164  for (G4int j=0; j<=2; j++)
165  {
166  fShellCorrectionVector[j] = 0.;
167 
168  for (size_t k=0; k<nElements; k++) {
169  fShellCorrectionVector[j] += nAtomsPerVolume[k]
170  *(((*elmVector)[k])->GetIonisation()->GetShellCorrectionVector())[j];
171  }
173  }
174 }
175 
176 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
177 
179 {
180  return fDensityData;
181 }
182 
183 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
184 
186 {
189 }
190 
191 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
192 
194 {
196 
197  // Check if density effect data exist in the table
198  // R.M. Sternheimer, Atomic Data and Nuclear Data Tables, 30: 261 (1984)
199  // or is assign to one of data set in this table
202  G4int Z0 = ((*(fMaterial->GetElementVector()))[0])->GetZasInt();
203  const G4Material* bmat = fMaterial->GetBaseMaterial();
205 
206  // arbitrary empirical limits
207  // parameterisation with very different density is not applicable
208  static const G4double corrmax = 1.;
209  static const G4double massfracmax = 0.9;
210 
211  // for simple non-NIST materials
212  G4double corr = 0.0;
213 
214  if(idx < 0 && 1 == nelm) {
216 
217  // Correction for base material or for non-nominal density
218  // Except cases of very different density defined in user code
219  if(idx >= 0) {
220  G4double dens = nist->GetNominalDensity(Z0);
221  if(dens <= 0.0) { idx = -1; }
222  else {
223  corr = G4Log(dens/fMaterial->GetDensity());
224  }
225  if(std::abs(corr) > corrmax) { idx = -1; }
226  }
227  }
228  // for base material case
229  if(idx < 0 && bmat) {
230  idx = fDensityData->GetIndex(bmat->GetName());
231  if(idx >= 0) {
232  corr = G4Log(bmat->GetDensity()/fMaterial->GetDensity());
233  if(std::abs(corr) > corrmax) { idx = -1; }
234  }
235  }
236 
237  // for compound non-NIST materials with one element dominating
238  if(idx < 0 && 1 < nelm) {
240  for(G4int i=0; i<nelm; ++i) {
241  const G4double frac = fMaterial->GetVecNbOfAtomsPerVolume()[i]/tot;
242  if(frac > massfracmax) {
243  Z0 = ((*(fMaterial->GetElementVector()))[i])->GetZasInt();
245  G4double dens = nist->GetNominalDensity(Z0);
246  if(idx >= 0 && dens > 0.0) {
247  corr = G4Log(dens/fMaterial->GetDensity());
248  if(std::abs(corr) > corrmax) { idx = -1; }
249  else { break; }
250  }
251  }
252  }
253  }
254  //G4cout<<"DensityEffect for "<<fMaterial->GetName()<<" "<< idx << G4endl;
255 
256  if(idx >= 0) {
257 
258  // Take parameters for the density effect correction from
259  // R.M. Sternheimer et al. Density Effect For The Ionization Loss
260  // of Charged Particles in Various Substances.
261  // Atom. Data Nucl. Data Tabl. 30 (1984) 261-271.
262 
271 
272  // parameter C is computed and not taken from Sternheimer tables
273  //fCdensity = 1. + 2*G4Log(fMeanExcitationEnergy/fPlasmaEnergy);
274  //G4cout << "IonisParamMat: " << fMaterial->GetName()
275  // << " Cst= " << Cdensity << " C= " << fCdensity << G4endl;
276 
277  // correction on nominal density
278  fCdensity += corr;
279  fX0density += corr/twoln10;
280  fX1density += corr/twoln10;
281 
282  } else {
283 
284  static const G4double Cd2 = 4*pi*hbarc_squared*classic_electr_radius;
286 
287  // Compute parameters for the density effect correction in DE/Dx formula.
288  // The parametrization is from R.M. Sternheimer, Phys. Rev.B,3:3681 (1971)
289  G4int icase;
290 
292  //
293  // condensed materials
294  //
295  if ((State == kStateSolid)||(State == kStateLiquid)) {
296 
297  static const G4double E100eV = 100.*eV;
298  static const G4double ClimiS[] = {3.681 , 5.215 };
299  static const G4double X0valS[] = {1.0 , 1.5 };
300  static const G4double X1valS[] = {2.0 , 3.0 };
301 
302  if(fMeanExcitationEnergy < E100eV) { icase = 0; }
303  else { icase = 1; }
304 
305  if(fCdensity < ClimiS[icase]) { fX0density = 0.2; }
306  else { fX0density = 0.326*fCdensity - X0valS[icase]; }
307 
308  fX1density = X1valS[icase]; fMdensity = 3.0;
309 
310  //special: Hydrogen
311  if (1 == nelm && 1 == Z0) {
312  fX0density = 0.425; fX1density = 2.0; fMdensity = 5.949;
313  }
314  } else {
315  //
316  // gases
317  //
318  fMdensity = 3.;
319  fX1density = 4.0;
320  if(fCdensity < 10.) {
321  fX0density = 1.6;
322  } else if(fCdensity < 11.5) {
323  fX0density = 1.6 + 0.2*(fCdensity - 10.);
324  } else if(fCdensity < 12.25) {
325  fX0density = 1.9 + (fCdensity - 11.5)/7.5;
326  } else if(fCdensity < 13.804) {
327  fX0density = 2.0;
328  fX1density = 4.0 + (fCdensity - 12.25)/1.554;
329  } else {
330  fX0density = 0.326*fCdensity-2.5; fX1density = 5.0;
331  }
332 
333  //special: Hydrogen
334  if (1 == nelm && 1 == Z0) {
335  fX0density = 1.837; fX1density = 3.0; fMdensity = 4.754;
336  }
337 
338  //special: Helium
339  if (1 == nelm && 2 == Z0) {
340  fX0density = 2.191; fX1density = 3.0; fMdensity = 3.297;
341  }
342  }
343  }
344 
345  // change parameters if the gas is not in STP.
346  // For the correction the density(STP) is needed.
347  // Density(STP) is calculated here :
348 
349  if (State == kStateGas) {
350  G4double Density = fMaterial->GetDensity();
351  G4double Pressure = fMaterial->GetPressure();
353 
354  G4double DensitySTP = Density*STP_Pressure*Temp/(Pressure*NTP_Temperature);
355 
356  G4double ParCorr = G4Log(Density/DensitySTP);
357 
358  fCdensity -= ParCorr;
359  fX0density -= ParCorr/twoln10;
360  fX1density -= ParCorr/twoln10;
361  }
362 
363  // fAdensity parameter can be fixed for not conductive materials
364  if(0.0 == fD0density) {
367  /std::pow((fX1density-fX0density),fMdensity);
368  }
369  /*
370  G4cout << "G4IonisParamMat: density effect data for <"
371  << fMaterial->GetName()
372  << "> " << G4endl;
373  G4cout << "Eplasma(eV)= " << fPlasmaEnergy/eV
374  << " rho= " << fAdjustmentFactor
375  << " -C= " << fCdensity
376  << " x0= " << fX0density
377  << " x1= " << fX1density
378  << " a= " << fAdensity
379  << " m= " << fMdensity
380  << G4endl;
381  */
382 }
383 
384 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
385 
387 {
388  // compute parameters for the energy loss fluctuation model
389  // needs an 'effective Z'
390  G4double Zeff = 0.;
391  for (size_t i=0; i<fMaterial->GetNumberOfElements(); ++i) {
392  Zeff += (fMaterial->GetFractionVector())[i]
393  *((*(fMaterial->GetElementVector()))[i]->GetZ());
394  }
395  fF2fluct = (Zeff > 2.) ? 2./Zeff : 0.0;
396 
397  fF1fluct = 1. - fF2fluct;
398  fEnergy2fluct = 10.*Zeff*Zeff*eV;
401  /fF1fluct;
403  fEnergy0fluct = 10.*eV;
404  fRateionexcfluct = 0.4;
405 }
406 
407 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
408 
410 {
411  // get elements in the actual material,
412  const G4ElementVector* theElementVector = fMaterial->GetElementVector() ;
413  const G4double* theAtomicNumDensityVector =
415  const G4int NumberOfElements = fMaterial->GetNumberOfElements() ;
416 
417  // loop for the elements in the material
418  // to find out average values Z, vF, lF
419  G4double z(0.0), vF(0.0), lF(0.0), a23(0.0);
420 
421  G4Pow* g4pow = G4Pow::GetInstance();
422  if( 1 == NumberOfElements ) {
423  const G4Element* element = (*theElementVector)[0];
424  z = element->GetZ();
425  vF= element->GetIonisation()->GetFermiVelocity();
426  lF= element->GetIonisation()->GetLFactor();
427  a23 = 1.0/g4pow->A23(element->GetN());
428 
429  } else {
430  G4double norm(0.0);
431  for (G4int iel=0; iel<NumberOfElements; ++iel) {
432  const G4Element* element = (*theElementVector)[iel];
433  const G4double weight = theAtomicNumDensityVector[iel];
434  norm += weight;
435  z += element->GetZ() * weight;
436  vF += element->GetIonisation()->GetFermiVelocity() * weight;
437  lF += element->GetIonisation()->GetLFactor() * weight;
438  a23 += weight/g4pow->A23(element->GetN());
439  }
440  z /= norm;
441  vF /= norm;
442  lF /= norm;
443  a23 /= norm;
444  }
445  fZeff = z;
446  fLfactor = lF;
447  fFermiEnergy = 25.*keV*vF*vF;
448  fInvA23 = a23;
449 }
450 
451 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
452 
454 {
455  if(value == fMeanExcitationEnergy || value <= 0.0) { return; }
456  if (G4NistManager::Instance()->GetVerbose() > 1) {
457  G4cout << "G4Material: Mean excitation energy is changed for "
458  << fMaterial->GetName()
459  << " Iold= " << fMeanExcitationEnergy/eV
460  << "eV; Inew= " << value/eV << " eV;"
461  << G4endl;
462  }
463 
465 
466  // add corrections to density effect
467  G4double newlog = G4Log(value);
468  G4double corr = 2*(newlog - fLogMeanExcEnergy);
469  fCdensity += corr;
470  fX0density += corr/twoln10;
471  fX1density += corr/twoln10;
472 
473  // recompute parameters of fluctuation model
474  fLogMeanExcEnergy = newlog;
476 }
477 
478 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
479 
481  G4double ad, G4double x0,
482  G4double x1, G4double d0)
483 {
484  // no check on consistence of user parameters
485 #ifdef G4MULTITHREADED
486  G4MUTEXLOCK(&ionisMutex);
487 #endif
488  fCdensity = cd;
489  fMdensity = md;
490  fAdensity = ad;
491  fX0density = x0;
492  fX1density = x1;
493  fD0density = d0;
494 #ifdef G4MULTITHREADED
495  G4MUTEXUNLOCK(&ionisMutex);
496 #endif
497 }
498 
499 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
500 
502 {
503 #ifdef G4MULTITHREADED
504  G4MUTEXLOCK(&ionisMutex);
505 #endif
506  const G4IonisParamMat* ipm = bmat->GetIonisation();
507  fCdensity = ipm->GetCdensity();
508  fMdensity = ipm->GetMdensity();
509  fAdensity = ipm->GetAdensity();
510  fX0density = ipm->GetX0density();
511  fX1density = ipm->GetX1density();
512  fD0density = ipm->GetD0density();
513 
514  G4double corr = G4Log(bmat->GetDensity()/fMaterial->GetDensity());
515  fCdensity += corr;
516  fX0density += corr/twoln10;
517  fX1density += corr/twoln10;
518 #ifdef G4MULTITHREADED
519  G4MUTEXUNLOCK(&ionisMutex);
520 #endif
521 }
522 
523 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
524 
526 {
527  if(val) {
528  if(!fDensityEffectCalc) {
529  G4int n = 0;
530  for(size_t i=0; i<fMaterial->GetNumberOfElements(); ++i) {
531  const G4int Z = fMaterial->GetElement(i)->GetZasInt();
533  }
534  // The last level is the conduction level. If this is *not* a conductor,
535  // make a dummy conductor level with zero electrons in it.
537  }
538  } else {
539  delete fDensityEffectCalc;
540  fDensityEffectCalc = nullptr;
541  }
542 }
543 
544 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
545 
547 {
548  G4double res = 0.0;
549  // data from density effect data
550  if(fDensityData) {
552  if(idx >= 0) {
554  }
555  }
556 
557  // The data on mean excitation energy for compaunds
558  // from "Stopping Powers for Electrons and Positrons"
559  // ICRU Report N#37, 1984 (energy in eV)
560  // this value overwrites Density effect data
561  G4String chFormula = mat->GetChemicalFormula();
562  if(chFormula != "") {
563 
564  static const size_t numberOfMolecula = 54;
565  static const G4String name[numberOfMolecula] = {
566  // gas 0 - 12
567  "NH_3", "C_4H_10", "CO_2", "C_2H_6", "C_7H_16-Gas",
568  // "G4_AMMONIA", "G4_BUTANE","G4_CARBON_DIOXIDE","G4_ETHANE", "G4_N-HEPTANE"
569  "C_6H_14-Gas", "CH_4", "NO", "N_2O", "C_8H_18-Gas",
570  // "G4_N-HEXANE" , "G4_METHANE", "x", "G4_NITROUS_OXIDE", "G4_OCTANE"
571  "C_5H_12-Gas", "C_3H_8", "H_2O-Gas",
572  // "G4_N-PENTANE", "G4_PROPANE", "G4_WATER_VAPOR"
573 
574  // liquid 13 - 39
575  "C_3H_6O", "C_6H_5NH_2", "C_6H_6", "C_4H_9OH", "CCl_4",
576  //"G4_ACETONE","G4_ANILINE","G4_BENZENE","G4_N-BUTYL_ALCOHOL","G4_CARBON_TETRACHLORIDE"
577  "C_6H_5Cl", "CHCl_3", "C_6H_12", "C_6H_4Cl_2", "C_4Cl_2H_8O",
578  //"G4_CHLOROBENZENE","G4_CHLOROFORM","G4_CYCLOHEXANE","G4_1,2-DICHLOROBENZENE",
579  //"G4_DICHLORODIETHYL_ETHER"
580  "C_2Cl_2H_4", "(C_2H_5)_2O", "C_2H_5OH", "C_3H_5(OH)_3","C_7H_16",
581  //"G4_1,2-DICHLOROETHANE","G4_DIETHYL_ETHER","G4_ETHYL_ALCOHOL","G4_GLYCEROL","G4_N-HEPTANE"
582  "C_6H_14", "CH_3OH", "C_6H_5NO_2","C_5H_12", "C_3H_7OH",
583  //"G4_N-HEXANE","G4_METHANOL","G4_NITROBENZENE","G4_N-PENTANE","G4_N-PROPYL_ALCOHOL",
584  "C_5H_5N", "C_8H_8", "C_2Cl_4", "C_7H_8", "C_2Cl_3H",
585  //"G4_PYRIDINE","G4_POLYSTYRENE","G4_TETRACHLOROETHYLENE","G4_TOLUENE","G4_TRICHLOROETHYLENE"
586  "H_2O", "C_8H_10",
587  // "G4_WATER", "G4_XYLENE"
588 
589  // solid 40 - 53
590  "C_5H_5N_5", "C_5H_5N_5O", "(C_6H_11NO)-nylon", "C_25H_52",
591  // "G4_ADENINE", "G4_GUANINE", "G4_NYLON-6-6", "G4_PARAFFIN"
592  "(C_2H_4)-Polyethylene", "(C_5H_8O_2)-Polymethil_Methacrylate",
593  // "G4_ETHYLENE", "G4_PLEXIGLASS"
594  "(C_8H_8)-Polystyrene", "A-150-tissue", "Al_2O_3", "CaF_2",
595  // "G4_POLYSTYRENE", "G4_A-150_TISSUE", "G4_ALUMINUM_OXIDE", "G4_CALCIUM_FLUORIDE"
596  "LiF", "Photo_Emulsion", "(C_2F_4)-Teflon", "SiO_2"
597  // "G4_LITHIUM_FLUORIDE", "G4_PHOTO_EMULSION", "G4_TEFLON", "G4_SILICON_DIOXIDE"
598  } ;
599 
600  static const G4double meanExcitation[numberOfMolecula] = {
601 
602  53.7, 48.3, 85.0, 45.4, 49.2,
603  49.1, 41.7, 87.8, 84.9, 49.5,
604  48.2, 47.1, 71.6,
605 
606  64.2, 66.2, 63.4, 59.9, 166.3,
607  89.1, 156.0, 56.4, 106.5, 103.3,
608  111.9, 60.0, 62.9, 72.6, 54.4,
609  54.0, 67.6, 75.8, 53.6, 61.1,
610  66.2, 64.0, 159.2, 62.5, 148.1,
611  75.0, 61.8,
612 
613  71.4, 75.0, 63.9, 48.3, 57.4,
614  74.0, 68.7, 65.1, 145.2, 166.,
615  94.0, 331.0, 99.1, 139.2
616  };
617 
618  for(size_t i=0; i<numberOfMolecula; i++) {
619  if(chFormula == name[i]) {
620  res = meanExcitation[i]*eV;
621  break;
622  }
623  }
624  }
625  return res;
626 }
627 
628 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
629