18#include "BDSComptonScatteringEngine.hh"
21#include "G4Electron.hh"
23#include "G4RandomDirection.hh"
24#include "Randomize.hh"
26#include "CLHEP/Units/PhysicalConstants.h"
27#include "CLHEP/Units/SystemOfUnits.h"
30BDSComptonScatteringEngine::BDSComptonScatteringEngine():
36BDSComptonScatteringEngine::~BDSComptonScatteringEngine()
39void BDSComptonScatteringEngine::SetParticle(G4int partIDIn)
42 if (std::abs(partID) == 11)
43 {particleMass = G4Electron::ElectronDefinition()->GetPDGMass();}
44 else if (partID == 2212)
45 {particleMass = G4Proton::ProtonDefinition()->GetPDGMass();}
47 particleRadius = (CLHEP::e_squared) / (4 * CLHEP::pi * CLHEP::epsilon0 * particleMass);
51G4double BDSComptonScatteringEngine::CrossSection(G4double photonEnergyIn, G4int partIn)
54 G4double e1 = photonEnergyIn / particleMass;
56 G4double crossSectionThomson = (8.0/3.0)*CLHEP::pi*particleRadius*particleRadius;
58 G4double p1 = ((1 + e1) / std::pow(e1,3)) * ( 2*e1 * (1 + e1) / (1 + 2*e1) - std::log(1 + 2*e1));
59 G4double p2 = (1. / (2*e1)) * std::log(1 + 2*e1);
60 G4double p3 = (1 + 3*e1) / std::pow((1 + 2*e1), 2);
61 G4double ratio = 0.75*(p1 + p2 - p3);
62 G4double crossSection = crossSectionThomson*ratio;
67void BDSComptonScatteringEngine::PerformCompton(
const G4ThreeVector& boost,G4int partIn)
70 G4double theta = MCMCTheta();
71 G4double scatteredGammaEnergy = ScatteredEnergy(theta);
72 G4double phi = MCPhi(theta,scatteredGammaEnergy);
73 G4ThreeVector scatteredGammaUnitVector(std::sin(theta)*std::cos(phi), std::sin(theta)*std::sin(phi), std::cos(theta));
74 if(incomingGamma.x()<=1e9&&incomingGamma.y()<=1e9)
76 scatteredGammaUnitVector.rotate(0,CLHEP::pi,0);
80 G4RotationMatrix* rot = CalculateRotation();
81 scatteredGammaUnitVector.transform(*rot);
83 scatteredGamma.setVect(scatteredGammaUnitVector * scatteredGammaEnergy);
84 scatteredGamma.setE(scatteredGammaEnergy);
85 G4ThreeVector scatteredElectronVector(incomingGamma.vect()-scatteredGamma.vect());
86 scatteredElectron.setE(incomingGamma.e()+incomingElectron.e()-scatteredGammaEnergy);
87 scatteredElectron.setVect(scatteredElectronVector);
88 scatteredElectron.boost(boost);
89 scatteredGamma.boost(boost);
92G4double BDSComptonScatteringEngine::MCMCTheta()
94 G4double theta = std::acos(1-2*G4UniformRand());
95 G4double KNTheta = KleinNishinaDifferential(theta);
96 G4double KNMax = KleinNishinaDifferential(0);
97 G4double KNRandom = G4UniformRand()*KNMax;
99 return KNTheta > KNRandom ? theta : MCMCTheta();
102G4double BDSComptonScatteringEngine::KleinNishinaDifferential(G4double theta)
104 G4double E0 = incomingGamma.e();
105 G4double Ep = E0 / (1.0+(E0/particleMass) * (1.0-std::cos(theta)) );
106 return 0.5 * particleRadius * particleRadius * (Ep/E0) * (Ep/E0) * ((Ep/E0)+(E0/Ep)-std::sin(theta)*std::sin(theta));
110G4RotationMatrix* BDSComptonScatteringEngine::CalculateRotation()
112 G4ThreeVector theoryIncomingPhoton (0,0,1);
113 G4ThreeVector crossProduct = theoryIncomingPhoton.cross(incomingGamma.vect().unit());
114 G4double dotProduct = theoryIncomingPhoton.dot(incomingGamma.vect().unit());
115 G4double multiplier = 1.0/(1.0+dotProduct);
116 G4RotationMatrix* identity =
new G4RotationMatrix;
117 G4ThreeVector vrow1 (1, -1*crossProduct.z(),crossProduct.y());
118 G4ThreeVector vrow2 (crossProduct.z(),1,-1.0*crossProduct.x());
119 G4ThreeVector vrow3 (-1.0*crossProduct.y(), crossProduct.x(),1);
120 G4ThreeVector v2row1 (multiplier*(-crossProduct.y()*crossProduct.y()-crossProduct.z()*crossProduct.z()), multiplier*crossProduct.x()*crossProduct.y(),multiplier*crossProduct.x()*crossProduct.z());
121 G4ThreeVector v2row2 (multiplier*crossProduct.x()*crossProduct.y(),multiplier*(-crossProduct.x()*crossProduct.x()-crossProduct.z()*crossProduct.z()),multiplier*crossProduct.y()*crossProduct.z());
122 G4ThreeVector v2row3 (multiplier*crossProduct.x()*crossProduct.z(), multiplier*crossProduct.y()*crossProduct.z(),multiplier*(-crossProduct.x()*crossProduct.x()-crossProduct.y()*crossProduct.y()));
123 identity->setRows(vrow1+v2row1,vrow2+v2row2,vrow3+v2row3);
126G4double BDSComptonScatteringEngine::ScatteredEnergy(G4double theta)
128 return incomingGamma.e()/(1+(incomingGamma.e()/particleMass)*(1-std::cos(theta)));
131G4double BDSComptonScatteringEngine::MCPhi(G4double theta, G4double scatteredEnergy)
133 G4double maxPhiVal = PolarizationCrossSectionMaxPhi(theta,scatteredEnergy);
134 G4double maxCrossSec1 = PolarizationCrossSectionPhi(theta, maxPhiVal,scatteredEnergy);
135 G4double maxCrossSec2 = PolarizationCrossSectionPhi(theta, maxPhiVal+CLHEP::pi,scatteredEnergy);
136 G4double maxCrossSec;
137 if(maxCrossSec1>=maxCrossSec2)
138 {maxCrossSec=maxCrossSec1;}
140 {maxCrossSec=maxCrossSec2;}
141 G4double phi = CLHEP::twopi*G4UniformRand();
142 G4double randCrossSecPhi = PolarizationCrossSectionPhi(theta, phi, scatteredEnergy);
143 G4double randCrossSec = maxCrossSec*G4UniformRand();
144 return randCrossSecPhi > randCrossSec ? phi : MCPhi(theta, scatteredEnergy);
147G4double BDSComptonScatteringEngine::PolarizationCrossSectionPhi(G4double theta, G4double phi, G4double Ep)
149 G4double E0=incomingGamma.e()/particleMass;
150 G4double Ep1 = Ep/particleMass;
151 G4double constants = ((particleRadius*particleRadius)/2.0)*(Ep1/E0)*(Ep1/E0);
152 G4double first = 1.0+std::cos(theta)*std::cos(theta)+(E0-Ep1)*(1.0-std::cos(theta));
153 G4double second = std::sin(theta)*std::sin(theta)*(incomingGammaPolarization.p1()*std::cos(phi)+incomingGammaPolarization.p2()*std::sin(phi));
154 G4double third = -1.0*incomingGammaPolarization.p3()*(1.0-std::cos(theta))*
155 (Ep1*std::sin(theta)*(incomingElectronPolarization.p1()*std::cos(phi)+incomingElectronPolarization.p2()*std::sin(phi))
156 +incomingElectronPolarization.p3()*std::cos(theta)*(E0+Ep1));
157 return constants*(first+second+third);
161G4double BDSComptonScatteringEngine::PolarizationCrossSectionMaxPhi(G4double theta ,G4double Ep)
163 G4double Ep1 = Ep/particleMass;
164 G4double numer = -incomingGammaPolarization.p3()*(1.0-std::cos(theta))*Ep1*std::sin(theta)*incomingElectronPolarization.p2() -
165 std::sin(theta)*std::sin(theta)*incomingGammaPolarization.p2();
166 G4double denom = std::sin(theta)*std::sin(theta)*incomingGammaPolarization.p1()+
167 incomingGammaPolarization.p3()*(1.0-std::cos(theta))*Ep1*std::sin(theta)*incomingElectronPolarization.p1();
168 G4double phiVal = std::atan2(numer, denom);