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