Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4JAEAElasticScatteringModel.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 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:
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*/
47#include "G4AutoLock.hh"
48#include "G4SystemOfUnits.hh"
49
50using namespace std;
51namespace { G4Mutex G4JAEAElasticScatteringModelMutex = G4MUTEX_INITIALIZER; }
52
53//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
54//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
55
56G4PhysicsFreeVector* G4JAEAElasticScatteringModel::dataCS[]={nullptr} ;
57G4DataVector* G4JAEAElasticScatteringModel::ES_Data[]={nullptr};
58
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
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
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 =
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
147 G4VEmModel* masterModel)
148{
150}
151
152//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
153
154void 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",
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 {
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
231 G4double GammaEnergy,
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
287 std::vector<G4DynamicParticle*>*,
288 const G4MaterialCutsCouple* couple,
289 const G4DynamicParticle* aDynamicGamma,
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.
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
384void
386 G4int Z)
387{
388 G4AutoLock l(&G4JAEAElasticScatteringModelMutex);
389 if(!dataCS[Z]) { ReadData(Z); }
390 l.unlock();
391}
392
393//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
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
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
std::mutex G4Mutex
Definition: G4Threading.hh:81
@ fStopAndKill
float G4float
Definition: G4Types.hh:84
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
double z() const
double x() const
double y() const
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4ThreeVector & GetPolarization() const
G4double GetZ() const
Definition: G4Element.hh:131
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
void InitialiseForElement(const G4ParticleDefinition *, G4int Z) override
void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) override
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
const G4Material * GetMaterial() const
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:185
size_t GetNumberOfElements() const
Definition: G4Material.hh:181
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
G4double Energy(const std::size_t index) const
G4double Value(const G4double energy, std::size_t &lastidx) const
std::size_t GetVectorLength() const
void FillSecondDerivatives(const G4SplineType=G4SplineType::Base, const G4double dir1=0.0, const G4double dir2=0.0)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
void SetElementSelectors(std::vector< G4EmElementSelector * > *)
Definition: G4VEmModel.hh:831
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:124
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:641
std::vector< G4EmElementSelector * > * GetElementSelectors()
Definition: G4VEmModel.hh:823
G4bool IsMaster() const
Definition: G4VEmModel.hh:725
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:634
const G4Element * SelectRandomAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.hh:561
void InitialiseElementSelectors(const G4ParticleDefinition *, const G4DataVector &)
Definition: G4VEmModel.cc:139
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
int G4lrint(double ad)
Definition: templates.hh:134