ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4JAEAElasticScatteringModel.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4JAEAElasticScatteringModel.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 /*
27 Authors:
28 M. Omer and R. Hajima on 17 October 2016
29 contact:
30 omer.mohamed@jaea.go.jp and hajima.ryoichi@qst.go.jp
31 Publication Information:
32 1- M. Omer, R. Hajima, Including Delbrück scattering in Geant4,
33 Nucl. Instrum. Methods Phys. Res. Sect. B, vol. 405, 2017, pp. 43-49.,
34 https://doi.org/10.1016/j.nimb.2017.05.028
35 2- M. Omer, R. Hajima, Geant4 physics process for elastic scattering of gamma-rays,
36 JAEA Technical Report 2018-007, 2018.
37 https://doi.org/10.11484/jaea-data-code-2018-007
38 */
39 // on base of G4LivermoreRayleighModel
40 
41 
43 #include "G4SystemOfUnits.hh"
44 
45 using namespace std;
46 
47 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
48 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
49 
52 //Initialising an array to hold all elastic scattering data.
53 G4double Diff_CS_data[100][183][300];
54 
56  :G4VEmModel("G4JAEAElasticScatteringModel"),isInitialised(false)
57 {
58  fParticleChange = 0;
59 //Low energy limit for G4JAEAElasticScatteringModel process.
60  lowEnergyLimit = 10 * keV;
61 
62  verboseLevel= 0;
63  // Verbosity scale for debugging purposes:
64  // 0 = nothing
65  // 1 = calculation of cross sections, file openings...
66  // 2 = entering in methods
67 
68  if(verboseLevel > 0)
69  {
70  G4cout << "G4JAEAElasticScatteringModel is constructed " << G4endl;
71  }
72 
73 }
74 
75 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
76 
78 {
79  if(IsMaster()) {
80  for(G4int i=0; i<maxZ; ++i) {
81  if(dataCS[i]) {
82  delete dataCS[i];
83  dataCS[i] = 0;
84  }
85  }
86  }
87 }
88 
89 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
90 
92  const G4DataVector& cuts)
93 {
94  if (verboseLevel > 1)
95  {
96  G4cout << "Calling Initialise() of G4JAEAElasticScatteringModel." << G4endl
97  << "Energy range: "
98  << LowEnergyLimit() / eV << " eV - "
99  << HighEnergyLimit() / GeV << " GeV"
100  << G4endl;
101  }
102 
103  if(IsMaster()) {
104 
105  // Initialise element selector
106  InitialiseElementSelectors(particle, cuts);
107 
108  // Access to elements
109  char* path = std::getenv("G4LEDATA");
110  G4ProductionCutsTable* theCoupleTable =
112  G4int numOfCouples = theCoupleTable->GetTableSize();
113 
114  for(G4int i=0; i<numOfCouples; ++i)
115  {
116  const G4MaterialCutsCouple* couple =
117  theCoupleTable->GetMaterialCutsCouple(i);
118  const G4Material* material = couple->GetMaterial();
119  const G4ElementVector* theElementVector = material->GetElementVector();
120  G4int nelm = material->GetNumberOfElements();
121 
122  for (G4int j=0; j<nelm; ++j)
123  {
124  G4int Z = G4lrint((*theElementVector)[j]->GetZ());
125  if(Z < 1) { Z = 1; }
126  else if(Z > maxZ) { Z = maxZ; }
127  if( (!dataCS[Z]) ) { ReadData(Z, path); }
128  }
129  }
130  }
131 
132  if(isInitialised) { return; }
134  isInitialised = true;
135 
136 }
137 
138 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
139 
141  G4VEmModel* masterModel)
142 {
144 }
145 
146 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
147 
148 void G4JAEAElasticScatteringModel::ReadData(size_t Z, const char* path)
149 {
150 
151  if (verboseLevel > 1)
152  {
153  G4cout << "Calling ReadData() of G4JAEAElasticScatteringModel"
154  << G4endl;
155  }
156 
157  if(dataCS[Z]) { return; }
158 
159  const char* datadir = path;
160 
161  if(!datadir)
162  {
163  datadir = std::getenv("G4LEDATA");
164  if(!datadir)
165  {
166  G4Exception("G4JAEAElasticScatteringModel::ReadData()","em0006",
168  "Environment variable G4LEDATA not defined");
169  return;
170  }
171  }
172 
173 /* Reading all data in the form of 183 * 300 array.
174 The first row is the energy, and the second row is the total cross section.
175 Rows from the 3rd to the 183rd are the differential cross section with an angular resolution of 1 degree.
176 */
177 G4double ESdata[183][300];
178 
179 std::ostringstream ostCS;
180 ostCS << datadir << "/JAEAESData/cs_Z_" << Z <<".dat";
181 std::ifstream alldata(ostCS.str().c_str());
182 if(!alldata.is_open())
183 {
185  ed << "G4JAEAElasticScattering Model data file <" << ostCS.str().c_str()
186  << "> is not opened!" << G4endl;
187  G4Exception("Elastic Scattering::ReadData()","em0003",FatalException,
188  ed,"G4LEDATA version should be G4EMLOW6.27 or later. Elastic Scattering Data are not loaded");
189  return;
190 }
191 else
192 {
193  if(verboseLevel > 3) {
194  G4cout << "File " << ostCS.str()
195  << " is opened by G4JAEAElasticScatteringModel" << G4endl;
196  }
197  }
198 while (!alldata.eof())
199 {
200  for (int i=0; i<183;i++)
201  {
202  for (int j=0; j<300; j++)
203  {
204  alldata >> ESdata[i][j];
205  Diff_CS_data[Z][i][j]=ESdata[i][j];
206  }
207  }
208  if (!alldata) break;
209 }
210 
211 /*
212 Writing the total cross section data to a G4LPhysicsFreeVector.
213 This provides an interpolation of the Energy-Total Cross Section data.
214 */
215 
216  dataCS[Z] = new G4LPhysicsFreeVector(300,0.01,3.);
217 //Note that the total cross section and energy are converted to the internal units.
218  for (int i=0;i<300;i++)
219  dataCS[Z]->PutValue(i,Diff_CS_data[Z][0][i]*1e-3,Diff_CS_data[Z][1][i]*1e-22);
220 
221  // Activation of spline interpolation
222  dataCS[Z] ->SetSpline(true);
223 
224 
225 
226 }
227 
228 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
229 
231  const G4ParticleDefinition*,
232  G4double GammaEnergy,
235 {
236 
237  if (verboseLevel > 1)
238  {
239  G4cout << "G4JAEAElasticScatteringModel::ComputeCrossSectionPerAtom()"
240  << G4endl;
241  }
242 
243  if(GammaEnergy < lowEnergyLimit) { return 0.0; }
244 
245  G4double xs = 0.0;
246 
247  G4int intZ = G4lrint(Z);
248 
249  if(intZ < 1 || intZ > maxZ) { return xs; }
250 
251  G4LPhysicsFreeVector* pv = dataCS[intZ];
252 
253  // if element was not initialised
254  // do initialisation safely for MT mode
255  if(!pv) {
256  InitialiseForElement(0, intZ);
257  pv = dataCS[intZ];
258  if(!pv) { return xs; }
259  }
260 
261  G4int n = pv->GetVectorLength() - 1;
262 
263  G4double e = GammaEnergy;
264  if(e >= pv->Energy(n)) {
265  xs = (*pv)[n];
266  } else if(e >= pv->Energy(0)) {
267  xs = pv->Value(e);
268  }
269 
270  if(verboseLevel > 0)
271  {
272  G4cout << "****** DEBUG: tcs value for Z=" << Z << " at energy (MeV)="
273  << e << G4endl;
274  G4cout << " cs (Geant4 internal unit)=" << xs << G4endl;
275  G4cout << " -> first E*E*cs value in CS data file (iu) =" << (*pv)[0]
276  << G4endl;
277  G4cout << " -> last E*E*cs value in CS data file (iu) =" << (*pv)[n]
278  << G4endl;
279  G4cout << "*********************************************************"
280  << G4endl;
281  }
282 
283  return (xs);
284 }
285 
286 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
287 
289  std::vector<G4DynamicParticle*>*,
290  const G4MaterialCutsCouple* couple,
291  const G4DynamicParticle* aDynamicGamma,
293 {
294  if (verboseLevel > 1) {
295  G4cout << "Calling SampleSecondaries() of G4JAEAElasticScatteringModel"
296  << G4endl;
297  }
298  G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
299 
300  // Absorption of low-energy gamma
301  if (photonEnergy0 <= lowEnergyLimit)
302  {
306  return ;
307  }
308 
309 
310  // Select randomly one element in the current material
311  const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
312  const G4Element* elm = SelectRandomAtom(couple,particle,photonEnergy0);
313  G4int Z = G4lrint(elm->GetZ());
314 
315 
316 //Select the angular distribution depending on the photon energy
317  G4double *whichdistribution = lower_bound(Diff_CS_data[Z][0],Diff_CS_data[Z][0]+300,photonEnergy0*1000.);
318  int index = max(0,(int)(whichdistribution-Diff_CS_data[Z][0]-1));
319 
320 //Rounding up to half the energy-grid separation (5 keV)
321  if (photonEnergy0*1000>=0.5*(Diff_CS_data[Z][0][index]+Diff_CS_data[Z][0][index+1]))
322  index++;
323 /*
324 Getting the normalized probablity distrbution function and
325 normalization factor to create the probability distribution function
326 */
327  G4double normdist=0;
328  for (int i=0;i<=180;i++)
329  {
330  distribution[i]=Diff_CS_data[Z][i+2][index];
331  normdist = normdist + distribution[i];
332  }
333 //Create the cummulative distribution function (cdf)
334  for (int i =0;i<=180;i++) pdf[i]=distribution[i]/normdist;
335  cdf[0]=0;
336  G4double cdfsum =0;
337  for (int i=0; i<=180;i++)
338  {
339  cdfsum=cdfsum+pdf[i];
340  cdf[i]=cdfsum;
341  }
342 //Sampling the polar angle by inverse transform uing cdf.
344  G4double *cdfptr=lower_bound(cdf,cdf+181,r);
345  int cdfindex = (int)(cdfptr-cdf-1);
346  G4double cdfinv = (r-cdf[cdfindex])/(cdf[cdfindex+1]-cdf[cdfindex]);
347  G4double theta = (cdfindex+cdfinv)/180.;
348 //polar is now ready
349  theta = theta*CLHEP::pi;
350 
351 
352 /* Alternative sampling using CLHEP functions
353  CLHEP::RandGeneral GenDistTheta(distribution,181);
354  G4double theta = CLHEP::pi*GenDistTheta.shoot();
355  theta =theta*CLHEP::pi; //polar is now ready
356 */
357 
358 //Azimuth is uniformally distributed
360 
361 G4ThreeVector finaldirection(sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta));
362 finaldirection.rotateUz(aDynamicGamma->GetMomentumDirection());
363 //Sampling the Final State
364  fParticleChange->ProposeMomentumDirection(finaldirection);
366 }
367 
368 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
369 
370 #include "G4AutoLock.hh"
371 namespace { G4Mutex G4JAEAElasticScatteringModelMutex = G4MUTEX_INITIALIZER; }
372 
373 void
375  G4int Z)
376 {
377  G4AutoLock l(&G4JAEAElasticScatteringModelMutex);
378  if(!dataCS[Z]) { ReadData(Z); }
379  l.unlock();
380 }
381 
382 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....