Geant4-11
G4PhotoElectricAngularGeneratorPolarized.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// -------------------------------------------------------------------
28//
29// GEANT4 Class file
30//
31//
32// File name: G4PhotoElectricAngularGeneratorPolarized
33//
34// Author: A. C. Farinha, L. Peralta, P. Rodrigues and A. Trindade
35//
36// Creation date:
37//
38// Modifications:
39// 10 January 2006
40// 06 May 2011, Replace FILE with std::ifstream
41//
42// Class Description:
43//
44// Concrete class for PhotoElectric Electron Angular Polarized Distribution Generation
45//
46// Class Description:
47// PhotoElectric Electron Angular Generator based on the general Gavrila photoelectron angular distribution.
48// Includes polarization effects for K and L1 atomic shells, according to Gavrila (1959, 1961).
49// For higher shells the L1 cross-section is used.
50//
51// The Gavrila photoelectron angular distribution is a complex function which can not be sampled using
52// the inverse-transform method (James 1980). Instead a more general approach based on the one already
53// used to sample bremsstrahlung 2BN cross section (G4Generator2BN, Peralta, 2005) was used.
54//
55// M. Gavrila, "Relativistic K-Shell Photoeffect", Phys. Rev. 113, 514-526 (1959)
56// M. Gavrila, "Relativistic L-Shell Photoeffect", Phys. Rev. 124, 1132-1141 (1961)
57// F. James, Rept. on Prog. in Phys. 43, 1145 (1980)
58// L. Peralta et al., "A new low-energy bremsstrahlung generator for GEANT4", Radiat. Prot. Dosimetry. 116, 59-64 (2005)
59//
60//
61// -------------------------------------------------------------------
62//
63//
64
67#include "G4RotationMatrix.hh"
68#include "Randomize.hh"
69#include "G4Exp.hh"
70
72 :G4VEmAngularDistribution("AngularGenSauterGavrilaPolarized")
73{
74 const G4int arrayDim = 980;
75
76 //minimum electron beta parameter allowed
77 betaArray[0] = 0.02;
78 //beta step
79 betaArray[1] = 0.001;
80 //maximum index array for a and c tables
81 betaArray[2] = arrayDim - 1;
82
83 // read Majorant Surface Parameters. This are required in order to generate
84 //Gavrila angular photoelectron distribution
85 for(G4int level = 0; level < 2; level++){
86 char nameChar0[100] = "ftab0.dat"; // K-shell Majorant Surface Parameters
87 char nameChar1[100] = "ftab1.dat"; // L-shell Majorant Surface Parameters
88
89 G4String filename;
90 if(level == 0) filename = nameChar0;
91 if(level == 1) filename = nameChar1;
92
93 char* path = std::getenv("G4LEDATA");
94 if (!path)
95 {
96 G4String excep = "G4EMDataSet - G4LEDATA environment variable not set";
97 G4Exception("G4PhotoElectricAngularGeneratorPolarized::G4PhotoElectricAngularGeneratorPolarized",
98 "em0006",FatalException,"G4LEDATA environment variable not set");
99 return;
100 }
101
102 G4String pathString(path);
103 G4String dirFile = pathString + "/photoelectric_angular/" + filename;
104 std::ifstream infile(dirFile);
105 if (!infile.is_open())
106 {
107 G4String excep = "data file: " + dirFile + " not found";
108 G4Exception("G4PhotoElectricAngularGeneratorPolarized::G4PhotoElectricAngularGeneratorPolarized",
109 "em0003",FatalException,excep);
110 return;
111 }
112
113 // Read parameters into tables. The parameters are function of incident electron
114 // energy and shell level
115 G4float aRead=0,cRead=0, beta=0;
116 for(G4int i=0 ; i<arrayDim ;++i){
117 infile >> beta >> aRead >> cRead;
118 aMajorantSurfaceParameterTable[i][level] = aRead;
119 cMajorantSurfaceParameterTable[i][level] = cRead;
120 }
121 infile.close();
122 }
123}
124
125//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
126
128{}
129
130//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
131
134 const G4DynamicParticle* dp,
135 G4double eKinEnergy,
136 G4int shellId,
137 const G4Material*)
138{
139 // (shellId == 0) - K-shell - Polarized model for K-shell
140 // (shellId > 0) - L1-shell - Polarized model for L1 and higher shells
141
142 // Calculate Lorentz term (gamma) and beta parameters
143 G4double gamma = 1 + eKinEnergy/electron_mass_c2;
144 G4double beta = std::sqrt((gamma - 1)*(gamma + 1))/gamma;
145
146 const G4ThreeVector& direction = dp->GetMomentumDirection();
147 const G4ThreeVector& polarization = dp->GetPolarization();
148
149 G4double theta, phi = 0;
150 // Majorant surface parameters
151 // function of the outgoing electron kinetic energy
152 G4double aBeta = 0;
153 G4double cBeta = 0;
154
155 // For the outgoing kinetic energy
156 // find the current majorant surface parameters
158
159 // Generate pho and theta according to the shell level
160 // and beta parameter of the electron
161 PhotoElectronGeneratePhiAndTheta(shellId, beta, aBeta, cBeta, &phi, &theta);
162
163 // Determine the rotation matrix
164 const G4RotationMatrix rotation =
165 PhotoElectronRotationMatrix(direction, polarization);
166
167 // Compute final direction of the outgoing electron
169
170 return fLocalDirection;
171}
172
173//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
174
175void
177 G4int shellLevel, G4double beta, G4double aBeta, G4double cBeta,
178 G4double *pphi, G4double *ptheta) const
179{
180 G4double rand1, rand2, rand3 = 0;
181 G4double phi = 0;
182 G4double theta = 0;
183 G4double crossSectionValue = 0;
184 G4double crossSectionMajorantFunctionValue = 0;
185 G4double maxBeta = 0;
186
187 do {
188
189 rand1 = G4UniformRand();
190 rand2 = G4UniformRand();
191 rand3 = G4UniformRand();
192
193 phi=2*pi*rand1;
194
195 if(shellLevel == 0){
196 // Polarized Gavrila Cross-Section for K-shell (1959)
197 theta=std::sqrt(((G4Exp(rand2*std::log(1+cBeta*pi*pi)))-1)/cBeta);
198 crossSectionMajorantFunctionValue =
199 CrossSectionMajorantFunction(theta, cBeta);
200 crossSectionValue = DSigmaKshellGavrila1959(beta, theta, phi);
201 } else {
202 // Polarized Gavrila Cross-Section for other shells (L1-shell) (1961)
203 theta = std::sqrt(((G4Exp(rand2*std::log(1+cBeta*pi*pi)))-1)/cBeta);
204 crossSectionMajorantFunctionValue =
205 CrossSectionMajorantFunction(theta, cBeta);
206 crossSectionValue = DSigmaL1shellGavrila(beta, theta, phi);
207 }
208
209 maxBeta=rand3*aBeta*crossSectionMajorantFunctionValue;
210 if(crossSectionValue < 0.0) { crossSectionValue = maxBeta; }
211
212 } while(maxBeta > crossSectionValue || theta > CLHEP::pi);
213
214 *pphi = phi;
215 *ptheta = theta;
216}
217
218//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
219
222 G4double theta, G4double cBeta) const
223{
224 // Compute Majorant Function
225 G4double crossSectionMajorantFunctionValue = 0;
226 crossSectionMajorantFunctionValue = theta/(1+cBeta*theta*theta);
227 return crossSectionMajorantFunctionValue;
228}
229
230//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
231
234 G4double beta, G4double theta, G4double phi) const
235{
236 //Double differential K shell cross-section (Gavrila 1959)
237
238 G4double beta2 = beta*beta;
239 G4double oneBeta2 = 1 - beta2;
240 G4double sqrtOneBeta2 = std::sqrt(oneBeta2);
241 G4double oneBeta2_to_3_2 = std::pow(oneBeta2,1.5);
242 G4double cosTheta = std::cos(theta);
243 G4double sinTheta2 = std::sin(theta)*std::sin(theta);
244 G4double cosPhi2 = std::cos(phi)*std::cos(phi);
245 G4double oneBetaCosTheta = 1-beta*cosTheta;
246 G4double dsigma = 0;
247 G4double firstTerm = 0;
248 G4double secondTerm = 0;
249
250 firstTerm = sinTheta2*cosPhi2/std::pow(oneBetaCosTheta,4)-(1 - sqrtOneBeta2)/(2*oneBeta2) *
251 (sinTheta2 * cosPhi2)/std::pow(oneBetaCosTheta,3) + (1-sqrtOneBeta2)*
252 (1-sqrtOneBeta2)/(4*oneBeta2_to_3_2) * sinTheta2/std::pow(oneBetaCosTheta,3);
253
254 secondTerm = std::sqrt(1 - sqrtOneBeta2)/(std::pow(2.,3.5)*beta2*std::pow(oneBetaCosTheta,2.5)) *
255 (4*beta2/sqrtOneBeta2 * sinTheta2*cosPhi2/oneBetaCosTheta + 4*beta/oneBeta2 * cosTheta * cosPhi2
256 - 4*(1-sqrtOneBeta2)/oneBeta2 *(1+cosPhi2) - beta2 * (1-sqrtOneBeta2)/oneBeta2 * sinTheta2/oneBetaCosTheta
257 + 4*beta2*(1-sqrtOneBeta2)/oneBeta2_to_3_2 - 4*beta*(1-sqrtOneBeta2)*(1-sqrtOneBeta2)/oneBeta2_to_3_2 * cosTheta)
258 + (1-sqrtOneBeta2)/(4*beta2*oneBetaCosTheta*oneBetaCosTheta) * (beta/oneBeta2 - 2/oneBeta2 * cosTheta * cosPhi2 +
259 (1-sqrtOneBeta2)/oneBeta2_to_3_2 * cosTheta - beta * (1-sqrtOneBeta2)/oneBeta2_to_3_2);
260
261 dsigma = ( firstTerm*(1-pi*fine_structure_const/beta) + secondTerm*(pi*fine_structure_const) )*std::sin(theta);
262
263 return dsigma;
264}
265
266//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
267
270 G4double beta, G4double theta, G4double phi) const
271{
272 //Double differential L1 shell cross-section (Gavrila 1961)
273 G4double beta2 = beta*beta;
274 G4double oneBeta2 = 1-beta2;
275 G4double sqrtOneBeta2 = std::sqrt(oneBeta2);
276 G4double oneBeta2_to_3_2=std::pow(oneBeta2,1.5);
277 G4double cosTheta = std::cos(theta);
278 G4double sinTheta2 =std::sin(theta)*std::sin(theta);
279 G4double cosPhi2 = std::cos(phi)*std::cos(phi);
280 G4double oneBetaCosTheta = 1-beta*cosTheta;
281
282 G4double dsigma = 0;
283 G4double firstTerm = 0;
284 G4double secondTerm = 0;
285
286 firstTerm = sinTheta2*cosPhi2/std::pow(oneBetaCosTheta,4)-(1 - sqrtOneBeta2)/(2*oneBeta2)
287 * (sinTheta2 * cosPhi2)/std::pow(oneBetaCosTheta,3) + (1-sqrtOneBeta2)*
288 (1-sqrtOneBeta2)/(4*oneBeta2_to_3_2) * sinTheta2/std::pow(oneBetaCosTheta,3);
289
290 secondTerm = std::sqrt(1 - sqrtOneBeta2)/(std::pow(2.,3.5)*beta2*std::pow(oneBetaCosTheta,2.5)) *
291 (4*beta2/sqrtOneBeta2 * sinTheta2*cosPhi2/oneBetaCosTheta + 4*beta/oneBeta2 * cosTheta * cosPhi2
292 - 4*(1-sqrtOneBeta2)/oneBeta2 *(1+cosPhi2) - beta2 * (1-sqrtOneBeta2)/oneBeta2 * sinTheta2/oneBetaCosTheta
293 + 4*beta2*(1-sqrtOneBeta2)/oneBeta2_to_3_2 - 4*beta*(1-sqrtOneBeta2)*(1-sqrtOneBeta2)/oneBeta2_to_3_2 * cosTheta)
294 + (1-sqrtOneBeta2)/(4*beta2*oneBetaCosTheta*oneBetaCosTheta) * (beta/oneBeta2 - 2/oneBeta2 * cosTheta * cosPhi2 +
295 (1-sqrtOneBeta2)/oneBeta2_to_3_2*cosTheta - beta*(1-sqrtOneBeta2)/oneBeta2_to_3_2);
296
297 dsigma = ( firstTerm*(1-pi*fine_structure_const/beta) + secondTerm*(pi*fine_structure_const) )*std::sin(theta);
298
299 return dsigma;
300}
301
302//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
303
306 const G4ThreeVector& direction,
307 const G4ThreeVector& polarization)
308{
309 G4double mK = direction.mag();
310 G4double mS = polarization.mag();
311 G4ThreeVector polarization2 = polarization;
312 const G4double kTolerance = 1e-6;
313
314 if(!(polarization.isOrthogonal(direction,kTolerance)) || mS == 0){
315 G4ThreeVector d0 = direction.unit();
317 G4ThreeVector a0 = a1.unit();
318 G4double rand1 = G4UniformRand();
319 G4double angle = twopi*rand1;
320 G4ThreeVector b0 = d0.cross(a0);
322 c.setX(std::cos(angle)*(a0.x())+std::sin(angle)*b0.x());
323 c.setY(std::cos(angle)*(a0.y())+std::sin(angle)*b0.y());
324 c.setZ(std::cos(angle)*(a0.z())+std::sin(angle)*b0.z());
325 polarization2 = c.unit();
326 mS = polarization2.mag();
327 }else
328 {
329 if ( polarization.howOrthogonal(direction) != 0)
330 {
331 polarization2 = polarization
332 - polarization.dot(direction)/direction.dot(direction) * direction;
333 }
334 }
335
336 G4ThreeVector direction2 = direction/mK;
337 polarization2 = polarization2/mS;
338
339 G4ThreeVector y = direction2.cross(polarization2);
340
341 G4RotationMatrix R(polarization2,y,direction2);
342 return R;
343}
344
345//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
346
347void
349{
350 // This member function finds for a given shell and beta value
351 // of the outgoing electron the correct Majorant Surface parameters
352 G4double aBeta,cBeta;
353 G4double bMin,bStep;
354 G4int indexMax;
355 G4int level = 0;
356 if(shellId > 0) { level = 1; }
357
358 bMin = betaArray[0];
359 bStep = betaArray[1];
360 indexMax = (G4int)betaArray[2];
361 const G4double kBias = 1e-9;
362
363 G4int k = (G4int)((beta-bMin+kBias)/bStep);
364
365 if(k < 0)
366 k = 0;
367 if(k > indexMax)
368 k = indexMax;
369
370 if(k == 0)
372 else if(k==indexMax)
374 else{
376 aBeta = std::max(aBeta,aMajorantSurfaceParameterTable[k+1][level]);
377 }
378
379 if(k == 0)
381 else if(k == indexMax)
383 else{
385 cBeta = std::max(cBeta,cMajorantSurfaceParameterTable[k+1][level]);
386 }
387
388 *majorantSurfaceParameterA = aBeta;
389 *majorantSurfaceParameterC = cBeta;
390}
391
392//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
393
395{
396 //computes the photoelectron momentum unitary vector
397 G4double sint = std::sin(theta);
398 G4double px = std::cos(phi)*sint;
399 G4double py = std::sin(phi)*sint;
400 G4double pz = std::cos(theta);
401
402 G4ThreeVector samplingDirection(px,py,pz);
403
404 G4ThreeVector outgoingDirection = rotation*samplingDirection;
405 return outgoingDirection;
406}
407
408//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
409
411{
412 G4cout << "\n" << G4endl;
413 G4cout << "Polarized Photoelectric Angular Generator" << G4endl;
414 G4cout << "PhotoElectric Electron Angular Generator based on the general Gavrila photoelectron angular distribution" << G4endl;
415 G4cout << "Includes polarization effects for K and L1 atomic shells, according to Gavrilla (1959, 1961)." << G4endl;
416 G4cout << "For higher shells the L1 cross-section is used." << G4endl;
417 G4cout << "(see Physics Reference Manual) \n" << G4endl;
418}
419
420//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
421
424 const G4ThreeVector& a) const
425{
426 G4double dx = a.x();
427 G4double dy = a.y();
428 G4double dz = a.z();
429 G4double x = dx < 0.0 ? -dx : dx;
430 G4double y = dy < 0.0 ? -dy : dy;
431 G4double z = dz < 0.0 ? -dz : dz;
432 if (x < y) {
433 return x < z ? G4ThreeVector(-dy,dx,0) : G4ThreeVector(0,-dz,dy);
434 }else{
435 return y < z ? G4ThreeVector(dz,0,-dx) : G4ThreeVector(-dy,dx,0);
436 }
437}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:179
const G4double a0
static constexpr double twopi
Definition: G4SIunits.hh:56
static constexpr double pi
Definition: G4SIunits.hh:55
static const G4double angle[DIMMOTT]
CLHEP::Hep3Vector G4ThreeVector
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
Hep3Vector unit() const
double x() const
void setY(double)
double y() const
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
void setZ(double)
bool isOrthogonal(const Hep3Vector &v, double epsilon=tolerance) const
Definition: SpaceVector.cc:233
double mag() const
double howOrthogonal(const Hep3Vector &v) const
Definition: SpaceVector.cc:215
void setX(double)
const G4ThreeVector & GetMomentumDirection() const
const G4ThreeVector & GetPolarization() const
G4double DSigmaL1shellGavrila(G4double beta, G4double theta, G4double phi) const
void PhotoElectronGetMajorantSurfaceAandCParameters(G4int shellId, G4double beta, G4double *majorantSurfaceParameterA, G4double *majorantSurfaceParameterC) const
G4ThreeVector PerpendicularVector(const G4ThreeVector &a) const
G4ThreeVector PhotoElectronComputeFinalDirection(const G4RotationMatrix &rotation, G4double theta, G4double phi) const
G4double CrossSectionMajorantFunction(G4double theta, G4double cBeta) const
void PhotoElectronGeneratePhiAndTheta(G4int shellId, G4double beta, G4double aBeta, G4double cBeta, G4double *pphi, G4double *ptheta) const
G4RotationMatrix PhotoElectronRotationMatrix(const G4ThreeVector &direction, const G4ThreeVector &polarization)
G4ThreeVector & SampleDirection(const G4DynamicParticle *dp, G4double eKinEnergy, G4int shellId, const G4Material *mat=nullptr) override
G4double DSigmaKshellGavrila1959(G4double beta, G4double theta, G4double phi) const
static constexpr double pi
Definition: SystemOfUnits.h:55
T max(const T t1, const T t2)
brief Return the largest of the two arguments
float electron_mass_c2
Definition: hepunit.py:273
int fine_structure_const
Definition: hepunit.py:286