Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/lowenergy/src/G4JAEAElasticScatteringModel.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

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