54 #include "G4eBremsstrahlungRelModel95.hh"
55 #include "G4Electron.hh"
56 #include "G4Positron.hh"
58 #include "Randomize.hh"
59 #include "G4Material.hh"
60 #include "G4Element.hh"
61 #include "G4ElementVector.hh"
62 #include "G4ProductionCutsTable.hh"
63 #include "G4ParticleChangeForLoss.hh"
64 #include "G4LossTableManager.hh"
65 #include "G4ModifiedTsai.hh"
69 const G4double G4eBremsstrahlungRelModel95::xgi[]={ 0.0199, 0.1017, 0.2372, 0.4083,
70 0.5917, 0.7628, 0.8983, 0.9801 };
71 const G4double G4eBremsstrahlungRelModel95::wgi[]={ 0.0506, 0.1112, 0.1569, 0.1813,
72 0.1813, 0.1569, 0.1112, 0.0506 };
73 const G4double G4eBremsstrahlungRelModel95::Fel_light[] = {0., 5.31 , 4.79 , 4.74 , 4.71} ;
74 const G4double G4eBremsstrahlungRelModel95::Finel_light[] = {0., 6.144 , 5.621 , 5.805 , 5.924} ;
78 G4eBremsstrahlungRelModel95::G4eBremsstrahlungRelModel95(
const G4ParticleDefinition*
p,
82 bremFactor(fine_structure_const*classic_electr_radius*classic_electr_radius*16./3.),
84 fMigdalConstant(classic_electr_radius*electron_Compton_length*electron_Compton_length*4.0*
pi),
85 fLPMconstant(fine_structure_const*electron_mass_c2*electron_mass_c2/(4.*
pi*hbarc)*0.5),
86 fXiLPM(0), fPhiLPM(0), fGLPM(0),
87 use_completescreening(
true),isInitialised(
false)
92 lowKinEnergy = 0.1*GeV;
93 SetLowEnergyLimit(lowKinEnergy);
95 nist = G4NistManager::Instance();
98 SetAngularDistribution(
new G4ModifiedTsai());
100 particleMass = kinEnergy = totalEnergy = currentZ = z13 = z23 = lnZ = Fel
101 = Finel = fCoulomb = fMax = densityFactor = densityCorr = lpmEnergy
102 = xiLPM = phiLPM = gLPM = klpm =
kp = 0.0;
104 energyThresholdLPM = 1.e39;
106 InitialiseConstants();
107 if(p) { SetParticle(p); }
112 void G4eBremsstrahlungRelModel95::InitialiseConstants()
114 facFel =
log(184.15);
115 facFinel =
log(1194.);
117 preS1 = 1./(184.15*184.15);
123 G4eBremsstrahlungRelModel95::~G4eBremsstrahlungRelModel95()
129 void G4eBremsstrahlungRelModel95::SetParticle(
const G4ParticleDefinition* p)
132 particleMass = p->GetPDGMass();
133 if(p == G4Electron::Electron()) {
isElectron =
true; }
139 void G4eBremsstrahlungRelModel95::SetupForMaterial(
const G4ParticleDefinition*,
140 const G4Material* mat,
141 G4double kineticEnergy)
143 densityFactor = mat->GetElectronDensity()*fMigdalConstant;
144 lpmEnergy = mat->GetRadlen()*fLPMconstant;
148 energyThresholdLPM=
sqrt(densityFactor)*lpmEnergy;
150 energyThresholdLPM=1.e39;
153 kinEnergy = kineticEnergy;
154 totalEnergy = kineticEnergy + particleMass;
155 densityCorr = densityFactor*totalEnergy*totalEnergy;
158 klpm=totalEnergy*totalEnergy/lpmEnergy;
166 void G4eBremsstrahlungRelModel95::Initialise(
const G4ParticleDefinition* p,
167 const G4DataVector&
cuts)
169 if(p) { SetParticle(p); }
171 lowKinEnergy = LowEnergyLimit();
175 InitialiseElementSelectors(p, cuts);
177 if(isInitialised) {
return; }
178 fParticleChange = GetParticleChangeForLoss();
179 isInitialised =
true;
184 G4double G4eBremsstrahlungRelModel95::ComputeDEDXPerVolume(
185 const G4Material* material,
186 const G4ParticleDefinition* p,
187 G4double kineticEnergy,
190 if(!particle) { SetParticle(p); }
191 if(kineticEnergy < lowKinEnergy) {
return 0.0; }
193 if(cut == 0.0) {
return 0.0; }
195 SetupForMaterial(particle, material,kineticEnergy);
197 const G4ElementVector* theElementVector = material->GetElementVector();
198 const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
203 for (
size_t i=0;
i<material->GetNumberOfElements();
i++) {
205 G4VEmModel::SetCurrentElement((*theElementVector)[
i]);
206 SetCurrentElement((*theElementVector)[
i]->GetZ());
208 dedx += theAtomicNumDensityVector[
i]*currentZ*currentZ*ComputeBremLoss(cut);
218 G4double G4eBremsstrahlungRelModel95::ComputeBremLoss(G4double cut)
223 G4double vcut = cut/totalEnergy;
224 G4int
n = (G4int)(20*vcut) + 3;
225 G4double
delta = vcut/G4double(n);
231 for(G4int
l=0;
l<
n;
l++) {
233 for(G4int
i=0;
i<8;
i++) {
235 G4double eg = (e0 + xgi[
i]*
delta)*totalEnergy;
237 if(totalEnergy > energyThresholdLPM) {
238 xs = ComputeRelDXSectionPerAtom(eg);
240 xs = ComputeDXSectionPerAtom(eg);
242 loss += wgi[
i]*xs/(1.0 + densityCorr/(eg*eg));
247 loss *= delta*totalEnergy;
254 G4double G4eBremsstrahlungRelModel95::ComputeCrossSectionPerAtom(
255 const G4ParticleDefinition* p,
256 G4double kineticEnergy,
257 G4double
Z, G4double,
261 if(!particle) { SetParticle(p); }
262 if(kineticEnergy < lowKinEnergy) {
return 0.0; }
263 G4double cut =
std::min(cutEnergy, kineticEnergy);
266 if(cut >= tmax) {
return 0.0; }
268 SetCurrentElement(Z);
270 G4double
cross = ComputeXSectionPerAtom(cut);
273 if(tmax < kinEnergy) { cross -= ComputeXSectionPerAtom(tmax); }
275 cross *= Z*Z*bremFactor;
283 G4double G4eBremsstrahlungRelModel95::ComputeXSectionPerAtom(G4double cut)
285 G4double cross = 0.0;
288 G4double vcut =
log(cut/totalEnergy);
289 G4double vmax =
log(kinEnergy/totalEnergy);
290 G4int n = (G4int)(0.45*(vmax - vcut)) + 4;
292 G4double delta = (vmax - vcut)/G4double(n);
298 for(G4int
l=0;
l<
n;
l++) {
300 for(G4int
i=0;
i<8;
i++) {
302 G4double eg =
exp(e0 + xgi[
i]*delta)*totalEnergy;
304 if(totalEnergy > energyThresholdLPM) {
305 xs = ComputeRelDXSectionPerAtom(eg);
307 xs = ComputeDXSectionPerAtom(eg);
309 cross += wgi[
i]*xs/(1.0 + densityCorr/(eg*eg));
320 void G4eBremsstrahlungRelModel95::CalcLPMFunctions(G4double
k)
324 G4double sprime =
sqrt(0.125*k*lpmEnergy/(totalEnergy*(totalEnergy-k)));
326 G4double s1 = preS1*z23;
327 G4double logS1 = 2./3.*lnZ-2.*facFel;
328 G4double logTS1 = logTwo+logS1;
334 else if (sprime>
sqrt(2.)*s1) {
335 G4double
h =
log(sprime)/logTS1;
336 xiLPM = 1+h-0.08*(1-
h)*(1-
sqr(1-h))/logTS1;
339 G4double
s = sprime/
sqrt(xiLPM);
344 s = s * (1 + (densityCorr/k2) );
349 if (
s<=s1) xiLPM = 2.;
350 else if ( (s1<
s) && (
s<=1) ) xiLPM = 1. +
log(
s)/logS1;
361 phiLPM = 6.*s - 18.84955592153876*s2 + 39.47841760435743*s3
362 - 57.69873135166053*s4;
363 gLPM = 37.69911184307752*s2 - 236.8705056261446*s3 + 807.7822389*s4;
368 phiLPM = 1.-
exp(-6.*s*(1.+(3.-
pi)*s)
369 +s3/(0.623+0.795*s+0.658*s2));
370 if (s<0.415827397755) {
372 G4double psiLPM = 1-
exp(-4*s-8*s2/(1+3.936*s+4.97*s2-0.05*s3+7.50*s4));
373 gLPM = 3*psiLPM-2*phiLPM;
377 G4double pre = -0.16072300849123999 + s*3.7550300067531581 + s2*-1.7981383069010097
378 + s3*0.67282686077812381 + s4*-0.1207722909879257;
384 phiLPM = 1. - 0.0119048/s4;
385 gLPM = 1. - 0.0230655/s4;
390 if (xiLPM*phiLPM>1. || s>0.57) { xiLPM=1./phiLPM; }
396 G4double G4eBremsstrahlungRelModel95::ComputeRelDXSectionPerAtom(G4double gammaEnergy)
401 if(gammaEnergy < 0.0) {
return 0.0; }
403 G4double
y = gammaEnergy/totalEnergy;
404 G4double y2 = y*y*.25;
405 G4double yone2 = (1.-y+2.*y2);
411 CalcLPMFunctions(gammaEnergy);
413 G4double mainLPM = xiLPM*(y2 * gLPM + yone2*phiLPM) * ( (Fel-fCoulomb) + Finel/currentZ );
414 G4double secondTerm = (1.-
y)/12.*(1.+1./currentZ);
416 G4double cross = mainLPM+secondTerm;
422 G4double G4eBremsstrahlungRelModel95::ComputeDXSectionPerAtom(G4double gammaEnergy)
429 if(gammaEnergy < 0.0) {
return 0.0; }
431 G4double y = gammaEnergy/totalEnergy;
433 G4double
main=0.,secondTerm=0.;
435 if (use_completescreening|| currentZ<5) {
437 main = (3./4.*y*y - y + 1.) * ( (Fel-fCoulomb) + Finel/currentZ );
438 secondTerm = (1.-
y)/12.*(1.+1./currentZ);
442 G4double
dd=100.*electron_mass_c2*y/(totalEnergy-gammaEnergy);
445 G4double phi1=Phi1(gg,currentZ), phi1m2=Phi1M2(gg,currentZ);
446 G4double psi1=Psi1(eps,currentZ), psi1m2=Psi1M2(eps,currentZ);
448 main = (3./4.*y*y - y + 1.) * ( (0.25*phi1-1./3.*lnZ-fCoulomb) + (0.25*psi1-2./3.*lnZ)/currentZ );
449 secondTerm = (1.-
y)/8.*(phi1m2+psi1m2/currentZ);
451 G4double cross = main+secondTerm;
457 void G4eBremsstrahlungRelModel95::SampleSecondaries(
458 std::vector<G4DynamicParticle*>* vdp,
459 const G4MaterialCutsCouple* couple,
460 const G4DynamicParticle* dp,
464 G4double kineticEnergy = dp->GetKineticEnergy();
465 if(kineticEnergy < lowKinEnergy) {
return; }
466 G4double cut =
std::min(cutEnergy, kineticEnergy);
467 G4double emax =
std::min(maxEnergy, kineticEnergy);
468 if(cut >= emax) {
return; }
470 SetupForMaterial(particle, couple->GetMaterial(), kineticEnergy);
472 const G4Element*
elm =
473 SelectRandomAtom(couple,particle,kineticEnergy,cut,emax);
474 SetCurrentElement(elm->GetZ());
476 kinEnergy = kineticEnergy;
477 totalEnergy = kineticEnergy + particleMass;
478 densityCorr = densityFactor*totalEnergy*totalEnergy;
479 G4ThreeVector direction = dp->GetMomentumDirection();
483 if(totalEnergy < energyThresholdLPM) { highe =
false; }
485 G4double xmin =
log(cut*cut + densityCorr);
486 G4double xmax =
log(emax*emax + densityCorr);
487 G4double gammaEnergy,
f,
x;
490 x =
exp(xmin + G4UniformRand()*(xmax - xmin)) - densityCorr;
491 if(x < 0.0) { x = 0.0; }
492 gammaEnergy =
sqrt(x);
493 if(highe) { f = ComputeRelDXSectionPerAtom(gammaEnergy); }
494 else { f = ComputeDXSectionPerAtom(gammaEnergy); }
497 G4cout <<
"### G4eBremsstrahlungRelModel95 Warning: Majoranta exceeded! "
498 << f <<
" > " << fMax
499 <<
" Egamma(MeV)= " << gammaEnergy
500 <<
" Ee(MeV)= " << kineticEnergy
505 }
while (f < fMax*G4UniformRand());
511 G4double
theta = GetAngularDistribution()->PolarAngle(totalEnergy,
512 totalEnergy-gammaEnergy,
515 G4double sint =
sin(theta);
516 G4double
phi = twopi * G4UniformRand();
517 G4ThreeVector gammaDirection(sint*
cos(phi),sint*
sin(phi),
cos(theta));
518 gammaDirection.rotateUz(direction);
521 G4DynamicParticle*
g =
new G4DynamicParticle(theGamma,gammaDirection,
525 G4double totMomentum =
sqrt(kineticEnergy*(totalEnergy + electron_mass_c2));
526 G4ThreeVector
dir = totMomentum*direction - gammaEnergy*gammaDirection;
527 direction = dir.unit();
530 G4double finalE = kineticEnergy - gammaEnergy;
533 if(gammaEnergy > SecondaryThreshold()) {
534 fParticleChange->ProposeTrackStatus(fStopAndKill);
535 fParticleChange->SetProposedKineticEnergy(0.0);
536 G4DynamicParticle* el =
537 new G4DynamicParticle(const_cast<G4ParticleDefinition*>(particle),
543 fParticleChange->SetProposedMomentumDirection(direction);
544 fParticleChange->SetProposedKineticEnergy(finalE);
const double Z[kNumberCalorimeter]
Sin< T >::type sin(const T &t)
Geom::Theta< T > theta() const
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
int main(int argc, char **argv)
bool isElectron(const Candidate &part)
Cos< T >::type cos(const T &t)
static const double tmax[3]
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Square< F >::type sqr(const F &f)
Basic3DVector cross(const Basic3DVector &v) const
Vector product, or "cross" product, with a vector of same type.