19#include "BDSComptonScatteringEngine.hh"
22#include "G4Electron.hh"
24#include "G4RandomDirection.hh"
25#include "Randomize.hh"
27#include "CLHEP/Units/PhysicalConstants.h"
28#include "CLHEP/Units/SystemOfUnits.h"
31BDSComptonScatteringEngine::BDSComptonScatteringEngine():
37BDSComptonScatteringEngine::~BDSComptonScatteringEngine()
40void BDSComptonScatteringEngine::SetParticle(G4int partIDIn)
43 if (std::abs(partID) == 11)
44 {particleMass = G4Electron::ElectronDefinition()->GetPDGMass();}
45 else if (partID == 2212)
46 {particleMass = G4Proton::ProtonDefinition()->GetPDGMass();}
48 particleRadius = (CLHEP::e_squared) / (4 * CLHEP::pi * CLHEP::epsilon0 * particleMass);
52G4double BDSComptonScatteringEngine::CrossSection(G4double photonEnergyIn, G4int partIn)
55 G4double e1 = photonEnergyIn / particleMass;
57 G4double crossSectionThomson = (8.0/3.0)*CLHEP::pi*particleRadius*particleRadius;
59 G4double p1 = ((1 + e1) / std::pow(e1,3)) * ( 2*e1 * (1 + e1) / (1 + 2*e1) - std::log(1 + 2*e1));
60 G4double p2 = (1. / (2*e1)) * std::log(1 + 2*e1);
61 G4double p3 = (1 + 3*e1) / std::pow((1 + 2*e1), 2);
62 G4double ratio = 0.75*(p1 + p2 - p3);
63 G4double crossSection = crossSectionThomson*ratio;
68void BDSComptonScatteringEngine::PerformCompton(
const G4ThreeVector& boost,G4int partIn)
71 G4double theta = MCMCTheta();
72 G4double scatteredGammaEnergy = ScatteredEnergy(theta);
73 G4double phi = MCPhi(theta,scatteredGammaEnergy);
74 G4ThreeVector scatteredGammaUnitVector(std::sin(theta)*std::cos(phi), std::sin(theta)*std::sin(phi), std::cos(theta));
75 if(incomingGamma.x()<=1e9&&incomingGamma.y()<=1e9)
77 scatteredGammaUnitVector.rotate(0,CLHEP::pi,0);
81 G4RotationMatrix* rot = CalculateRotation();
82 scatteredGammaUnitVector.transform(*rot);
84 scatteredGamma.setVect(scatteredGammaUnitVector * scatteredGammaEnergy);
85 scatteredGamma.setE(scatteredGammaEnergy);
86 G4ThreeVector scatteredElectronVector(incomingGamma.vect()-scatteredGamma.vect());
87 scatteredElectron.setE(incomingGamma.e()+incomingElectron.e()-scatteredGammaEnergy);
88 scatteredElectron.setVect(scatteredElectronVector);
89 scatteredElectron.boost(boost);
90 scatteredGamma.boost(boost);
93G4double BDSComptonScatteringEngine::MCMCTheta()
95 G4double theta = std::acos(1-2*G4UniformRand());
96 G4double KNTheta = KleinNishinaDifferential(theta);
97 G4double KNMax = KleinNishinaDifferential(0);
98 G4double KNRandom = G4UniformRand()*KNMax;
100 return KNTheta > KNRandom ? theta : MCMCTheta();
103G4double BDSComptonScatteringEngine::KleinNishinaDifferential(G4double theta)
105 G4double E0 = incomingGamma.e();
106 G4double Ep = E0 / (1.0+(E0/particleMass) * (1.0-std::cos(theta)) );
107 return 0.5 * particleRadius * particleRadius * (Ep/E0) * (Ep/E0) * ((Ep/E0)+(E0/Ep)-std::sin(theta)*std::sin(theta));
111G4RotationMatrix* BDSComptonScatteringEngine::CalculateRotation()
113 G4ThreeVector theoryIncomingPhoton (0,0,1);
114 G4ThreeVector crossProduct = theoryIncomingPhoton.cross(incomingGamma.vect().unit());
115 G4double dotProduct = theoryIncomingPhoton.dot(incomingGamma.vect().unit());
116 G4double multiplier = 1.0/(1.0+dotProduct);
117 G4RotationMatrix* identity =
new G4RotationMatrix;
118 G4ThreeVector vrow1 (1, -1*crossProduct.z(),crossProduct.y());
119 G4ThreeVector vrow2 (crossProduct.z(),1,-1.0*crossProduct.x());
120 G4ThreeVector vrow3 (-1.0*crossProduct.y(), crossProduct.x(),1);
121 G4ThreeVector v2row1 (multiplier*(-crossProduct.y()*crossProduct.y()-crossProduct.z()*crossProduct.z()), multiplier*crossProduct.x()*crossProduct.y(),multiplier*crossProduct.x()*crossProduct.z());
122 G4ThreeVector v2row2 (multiplier*crossProduct.x()*crossProduct.y(),multiplier*(-crossProduct.x()*crossProduct.x()-crossProduct.z()*crossProduct.z()),multiplier*crossProduct.y()*crossProduct.z());
123 G4ThreeVector v2row3 (multiplier*crossProduct.x()*crossProduct.z(), multiplier*crossProduct.y()*crossProduct.z(),multiplier*(-crossProduct.x()*crossProduct.x()-crossProduct.y()*crossProduct.y()));
124 identity->setRows(vrow1+v2row1,vrow2+v2row2,vrow3+v2row3);
127G4double BDSComptonScatteringEngine::ScatteredEnergy(G4double theta)
129 return incomingGamma.e()/(1+(incomingGamma.e()/particleMass)*(1-std::cos(theta)));
132G4double BDSComptonScatteringEngine::MCPhi(G4double theta, G4double scatteredEnergy)
134 G4double maxPhiVal = PolarizationCrossSectionMaxPhi(theta,scatteredEnergy);
135 G4double maxCrossSec1 = PolarizationCrossSectionPhi(theta, maxPhiVal,scatteredEnergy);
136 G4double maxCrossSec2 = PolarizationCrossSectionPhi(theta, maxPhiVal+CLHEP::pi,scatteredEnergy);
137 G4double maxCrossSec;
138 if(maxCrossSec1>=maxCrossSec2)
139 {maxCrossSec=maxCrossSec1;}
141 {maxCrossSec=maxCrossSec2;}
142 G4double phi = CLHEP::twopi*G4UniformRand();
143 G4double randCrossSecPhi = PolarizationCrossSectionPhi(theta, phi, scatteredEnergy);
144 G4double randCrossSec = maxCrossSec*G4UniformRand();
145 return randCrossSecPhi > randCrossSec ? phi : MCPhi(theta, scatteredEnergy);
148G4double BDSComptonScatteringEngine::PolarizationCrossSectionPhi(G4double theta, G4double phi, G4double Ep)
150 G4double E0=incomingGamma.e();
151 G4double constants = ((particleRadius*particleRadius)/2.0)*(Ep/E0)*(Ep/E0);
152 G4double first = 1.0+std::cos(theta)*std::cos(theta)+(E0-Ep)*(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 (Ep*std::sin(theta)*(incomingElectronPolarization.p1()*std::cos(phi)+incomingElectronPolarization.p2()*std::sin(phi))
156 +incomingElectronPolarization.p3()*std::cos(theta)*(E0+Ep));
157 return constants*(first+second+third);
161G4double BDSComptonScatteringEngine::PolarizationCrossSectionMaxPhi(G4double theta ,G4double Ep)
163 G4double numer = -incomingGammaPolarization.p3()*(1.0-std::cos(theta))*Ep*std::sin(theta)*incomingElectronPolarization.p2() -
164 std::sin(theta)*std::sin(theta)*incomingGammaPolarization.p2();
165 G4double denom = std::sin(theta)*std::sin(theta)*incomingGammaPolarization.p1()+
166 incomingGammaPolarization.p3()*(1.0-std::cos(theta))*Ep*std::sin(theta)*incomingElectronPolarization.p1();
167 G4double phiVal = std::atan(numer/denom);