56static const G4double sqrte = std::sqrt(std::exp(1.));
63 Rc(
CLHEP::elm_coupling / Mmuon),
64 LimitEnergy(5. * Mmuon),
65 LowestEnergyLimit(2. * Mmuon),
66 HighestEnergyLimit(1e12 *
CLHEP::GeV),
87 return (&part == theGamma);
98 for (
auto const& mat : *table) {
99 std::size_t n = mat->GetNumberOfElements();
100 nelm = std::max(nelm, n);
102 temp.resize(nelm, 0);
104 if (Energy5DLimit > 0.0 &&
nullptr != f5Dmodel) {
134 if(GammaEnergy <= LowestEnergyLimit) {
return DBL_MAX; }
142 if(e < LimitEnergy) {
143 G4double y = (e - LowestEnergyLimit)/(LimitEnergy - LowestEnergyLimit);
150 SIGMA += NbOfAtomsPerVolume[i] * fact *
153 return (SIGMA > 0.0) ? 1./SIGMA :
DBL_MAX;
177 if(Egam <= LowestEnergyLimit) {
return 0.0; }
181 G4double PowThres, Ecor,
B, Dn, Zthird, Winfty, WMedAppr, Wsatur, sigfac;
189 Dn = 1.54 * nist->
GetA27(Z);
191 Zthird = 1. / nist->
GetZ13(Z);
192 Winfty =
B * Zthird * Mmuon / (Dn * electron_mass_c2);
193 WMedAppr = 1. / (4. * Dn * sqrte * Mmuon);
194 Wsatur = Winfty / WMedAppr;
195 sigfac = 4. * fine_structure_const * Z * Z * Rc * Rc;
196 PowThres = 1.479 + 0.00799 * Dn;
197 Ecor = -18. + 4347. / (
B * Zthird);
201 G4Exp(
G4Log(1. - 4. * Mmuon / Egam) * PowThres)
204 G4double CrossSection = 7. / 9. * sigfac *
G4Log(1. + WMedAppr * CorFuc * Eg);
205 CrossSection *= CrossSecFactor;
214 if (fac < 0.0)
return;
215 CrossSecFactor = fac;
217 G4cout <<
"The cross section for GammaConversionToMuons is artificially "
218 <<
"increased by the CrossSecFactor=" << CrossSecFactor <<
G4endl;
237 if (Egam <= LowestEnergyLimit) {
247 if (Egam <= Energy5DLimit) {
248 std::vector<G4DynamicParticle*> fvect;
258 const G4Element* anElement = SelectRandomAtom(aDynamicGamma, aMaterial);
274 G4double Winfty =
B * Zthird * Mmuon / (Dn * electron_mass_c2);
278 G4double C2Term2 = electron_mass_c2 / (183. * Zthird * Mmuon);
280 G4double GammaMuonInv = Mmuon / Egam;
283 G4double xmin = (Egam <= LimitEnergy) ? 0.5 : 0.5 - std::sqrt(0.25 - GammaMuonInv);
287 G4double sBZ = sqrte *
B * Zthird / electron_mass_c2;
289 1. /
G4Log(Winfty * (1. + 2. * Ds2 * GammaMuonInv) / (1. + 2. * sBZ * Mmuon * GammaMuonInv));
295 const G4int nmax = 1000;
303 xPM = xPlus * xMinus;
304 G4double del = Mmuon * Mmuon / (2. * Egam * xPM);
305 W = Winfty * (1. + Ds2 * del / Mmuon) / (1. + sBZ * del);
307 result = (xxp > 0.) ? xxp *
G4Log(
W) * LogWmaxInv : 0.0;
309 G4cout <<
"G4GammaConversionToMuons::PostStepDoIt WARNING:"
310 <<
" in dSigxPlusGen, result=" << result <<
" > 1" <<
G4endl;
313 if(nn >= nmax) {
break; }
324 G4double a3 = (GammaMuonInv / (2. * xPM));
331 G4double f1_max=-(1.-xPM)*(2.*b1+(a21+a33)*
G4Log(a33/a21))/(2*b3);
333 G4double thetaPlus,thetaMinus,phiHalf;
343 if(std::abs(b1)<0.0001*a34) {
345 f1=(1.-2.*xPM+4.*xPM*t*(1.-t))/(12.*a34*a34*a34*a34);
348 f1=-(1.-2.*xPM+4.*xPM*t*(1.-t))*(2.*b1+(a22+a34)*
G4Log(a34/a22))/(2*b3);
350 if (f1 < 0.0 || f1 > f1_max) {
351 G4cout <<
"G4GammaConversionToMuons::PostStepDoIt WARNING:"
352 <<
"outside allowed range f1=" << f1
353 <<
" is set to zero, a34 = "<< a34 <<
" a22 = "<<a22<<
"."
357 if(nn > nmax) {
break; }
361 G4double f2_max=1.-2.*xPM*(1.-4.*t*(1.-t));
367 f2=1.-2.*xPM+4.*xPM*t*(1.-t)*(1.+std::cos(2.*psi));
368 if(f2<0 || f2> f2_max) {
369 G4cout <<
"G4GammaConversionToMuons::PostStepDoIt WARNING:"
370 <<
"outside allowed range f2=" << f2 <<
" is set to zero" <<
G4endl;
373 if(nn >= nmax) {
break; }
378 G4double C2Term1=GammaMuonInv/(2.*xPM*t);
379 G4double C22 = C2Term1*C2Term1+C2Term2*C2Term2;
387 G4double xiHalf=0.5*rho*std::cos(psi);
388 phiHalf=0.5*rho/u*std::sin(psi);
390 thetaPlus =GammaMuonInv*(u+xiHalf)/xPlus;
391 thetaMinus=GammaMuonInv*(u-xiHalf)/xMinus;
395 if(std::abs(thetaPlus)>pi) { thetaPlus = 0.0; }
396 if(std::abs(thetaMinus)>pi) { thetaMinus = 0.0; }
400 }
while ( std::abs(thetaPlus)>pi || std::abs(thetaMinus) >pi);
409 G4ThreeVector MuPlusDirection ( std::sin(thetaPlus) *std::cos(phi0+phiHalf),
410 std::sin(thetaPlus) *std::sin(phi0+phiHalf), std::cos(thetaPlus) );
411 G4ThreeVector MuMinusDirection (-std::sin(thetaMinus)*std::cos(phi0-phiHalf),
412 -std::sin(thetaMinus) *std::sin(phi0-phiHalf), std::cos(thetaMinus) );
414 MuPlusDirection.
rotateUz(GammaDirection);
415 MuMinusDirection.
rotateUz(GammaDirection);
418 auto aParticle1 =
new G4DynamicParticle(theMuonPlus, MuPlusDirection, EPlus - Mmuon);
421 auto aParticle2 =
new G4DynamicParticle(theMuonMinus, MuMinusDirection, EMinus - Mmuon);
429const G4Element* G4GammaConversionToMuons::SelectRandomAtom(
437 const G4Element* elm = (*theElementVector)[0];
439 if (NumberOfElements > 1) {
444 for (std::size_t i=0; i<NumberOfElements; ++i) {
445 elm = (*theElementVector)[i];
450 for (std::size_t i=0; i<NumberOfElements; ++i) {
452 elm = (*theElementVector)[i];
464 G4String comments =
"gamma->mu+mu- Bethe Heitler process, SubType= ";
466 G4cout <<
" good cross section parametrization from "
467 <<
G4BestUnit(LowestEnergyLimit,
"Energy") <<
" to " << HighestEnergyLimit / GeV
468 <<
" GeV for all Z." <<
G4endl;
469 G4cout <<
" cross section factor: " << CrossSecFactor <<
G4endl;
G4double B(G4double temperature)
std::vector< const G4Element * > G4ElementVector
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
G4GLOB_DLL std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *fvect, const G4MaterialCutsCouple *couple, const G4DynamicParticle *aDynamicGamma, G4double, G4double) override
void SetLeptonPair(const G4ParticleDefinition *p1, const G4ParticleDefinition *p2)
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
static G4EmParameters * Instance()
G4double MaxEnergyFor5DMuPair() const
G4double ComputeMeanFreePath(G4double GammaEnergy, const G4Material *aMaterial)
G4double ComputeCrossSectionPerAtom(G4double GammaEnergy, G4int Z)
G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition) override
void PrintInfoDefinition()
void SetCrossSecFactor(G4double fac)
~G4GammaConversionToMuons() override
G4bool IsApplicable(const G4ParticleDefinition &) override
G4double GetCrossSectionPerAtom(const G4DynamicParticle *aDynamicGamma, const G4Element *anElement)
void BuildPhysicsTable(const G4ParticleDefinition &) override
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
G4GammaConversionToMuons(const G4String &processName="GammaToMuPair", G4ProcessType type=fElectromagnetic)
static G4LossTableManager * Instance()
void DeRegister(G4VEnergyLossProcess *p)
void Register(G4VEnergyLossProcess *p)
const G4ElementVector * GetElementVector() const
const G4double * GetVecNbOfAtomsPerVolume() const
static G4MaterialTable * GetMaterialTable()
std::size_t GetNumberOfElements() const
G4double GetA27(G4int Z) const
G4double GetZ13(G4double Z) const
static G4NistManager * Instance()
void AddSecondary(G4Track *aSecondary)
void Initialize(const G4Track &) override
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
G4Material * GetMaterial() const
const G4DynamicParticle * GetDynamicParticle() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
void ProposeTrackStatus(G4TrackStatus status)
G4ParticleChange aParticleChange
void SetProcessSubType(G4int)
G4int GetProcessSubType() const
const G4String & GetProcessName() const