242{
243
244 static const G4double ElectronMass = CLHEP::electron_mass_c2;
245
247 const G4double LeptonMass2 = LeptonMass*LeptonMass;
248
249 static const G4double alpha0 = CLHEP::fine_structure_const;
250
251 static const G4double r0 = CLHEP::classic_electr_radius;
252
253 static const G4double r02 = r0*r0*1.e+25;
256
257 static const G4double factor1 = 2.66134007899/(8.*alpha0*ElectronMass);
258
259 G4double PairInvMassMin = 2.*LeptonMass;
260 G4double TrThreshold = 2.0 * ( (LeptonMass2)/ElectronMass + LeptonMass);
261
262
264
265 { 0.0227436, 0.0582046, 3.0322675, 2.8275065, -0.0034004,
266 1.1212766, 1.8989468, 68.3492750, 0.0211186, 14.4},
267
268 {0.67810E-06, 0.86037E+05, 2.0008395, 1.6739719, -0.0057279,
269 1.4222, 0.0, 263230.0, 0.0521, 51.1338}
270 };
272
273 { 0.0332350, 4.3942537, 2.8515925, 2.6351695, -0.0031510,
274 1.5737305, 1.8104647, 20.6434021, -0.0272586, 28.9},
275
276 {0.10382E-03, 0.14408E+17, 4.1368679, 3.2662121, -0.0163091,
277 0.0000, 0.0, 0.0, 0.0000, 1.0000}
278 };
279
280 static const G4double para[2][3][2] = {
281
282 { {11., -16.},{-1.17, -2.95},{-2., -0.5} },
283
284 { {17.5, 1.},{-1.17, -2.95},{2., 6.} }
285 };
286
287 static const G4double correctionIndex = 1.4;
288
290
291 if ( GammaEnergy <= PairInvMassMin) { return; }
292
293 const G4double GammaEnergy2 = GammaEnergy*GammaEnergy;
294
295
299
300
301
302
303
305 GammaPolarization -= GammaPolarization.
dot(GammaDirection) * GammaDirection;
306 }
307
308
309 const G4double GammaPolarizationMag = GammaPolarization.
mag();
310
311
312
313
316
321
322 const G4double NuThreshold = 2.0 * ( (LeptonMass2)/targetMass + LeptonMass);
323
324 if ( GammaEnergy <= NuThreshold) { return; }
325
327
328
330 if (fConversionType == 1) {
331 itriplet = false;
332 } else if (fConversionType == 2) {
333 itriplet = true;
334 if ( GammaEnergy <= TrThreshold ) return;
335 } else if ( GammaEnergy > TrThreshold ) {
336
337
338
339 if(rndmEngine->
flat()*(Z+1) < 1.) {
340 itriplet = true;
341 }
342 }
343
344
345 const G4double RecoilMass = itriplet ? ElectronMass : targetMass;
346 const G4double RecoilMass2 = RecoilMass*RecoilMass;
347 const G4double sCMS = 2.*RecoilMass*GammaEnergy + RecoilMass2;
348 const G4double sCMSPlusRM2 = sCMS + RecoilMass2;
349 const G4double sqrts = std::sqrt(sCMS);
350 const G4double isqrts2 = 1./(2.*sqrts);
351
352 const G4double PairInvMassMax = sqrts-RecoilMass;
353 const G4double PairInvMassRange = PairInvMassMax/PairInvMassMin;
355
356
357
359
360
361 const G4double EffectiveZ = iraw ? 0.5 : Z;
362 const G4double Threshold = itriplet ? TrThreshold : NuThreshold;
363 const G4double AvailableEnergy = GammaEnergy - Threshold;
365
366 const G4double MaxDiffCross = itriplet
367 ? MaxDiffCrossSection(tr[fConvMode],
368 EffectiveZ, AvailableEnergy, LogAvailableEnergy)
369 : MaxDiffCrossSection(nu[fConvMode],
370 EffectiveZ, AvailableEnergy, LogAvailableEnergy);
371
372
373 const G4double ymax = 1.5 * MaxDiffCross;
374
375 const G4double xu1 = (LogAvailableEnergy > para[fConvMode][2][0])
376 ? para[fConvMode][0][0] +
377 para[fConvMode][1][0]*LogAvailableEnergy
378 : para[fConvMode][0][0] +
379 para[fConvMode][2][0]*para[fConvMode][1][0];
380 const G4double xl1 = (LogAvailableEnergy > para[fConvMode][2][1])
381 ? para[fConvMode][0][1] +
382 para[fConvMode][1][1]*LogAvailableEnergy
383 : para[fConvMode][0][1] +
384 para[fConvMode][2][1]*para[fConvMode][1][1];
385
390
392 const G4double corrFac = 1.0/(correctionIndex + 1.0);
396 G4double betheheitler, sinTheta, cosTheta, dum0;
397
398 do {
399
401
402
403
404
405
406
407
408 z0 = (rndmv6[0] > logLowLim) ?
G4Log(rndmv6[0])*corrFac : expLowLim;
410 z1 = xl1 + (xu1 - xl1)*rndmv6[1];
411 if (z1 > expLowLim) {
413 dum0 = 1.0/(1.0 + x0);
414 x1 = dum0*x0;
415 cosTheta = -1.0 + 2.0*x1;
416 sinTheta = 2*std::sqrt(x1*(1.0 - x1));
417 } else {
418 x0 = 0.0;
419 dum0 = 1.0;
420 cosTheta = -1.0;
421 sinTheta = 0.0;
422 }
423
424 z2 = X1*X1*lnPairInvMassRange;
425 const G4double PairInvMass = PairInvMassMin*((z2 > 1.e-3) ?
G4Exp(z2) : 1 + z2 + 0.5*z2*z2);
426
427
428 const G4double cosThetaLept = std::cos(pi*rndmv6[2]);
429
430 const G4double sinThetaLept = std::sqrt((1.-cosThetaLept)*(1.+cosThetaLept));
431
432 const G4double cosPhiLept = std::cos(twoPi*rndmv6[3]-pi);
433
434
435 const G4double sinPhiLept = std::copysign(std::sqrt((1.-cosPhiLept)*(1.+cosPhiLept)),rndmv6[3]-0.5);
436
437 const G4double cosPhi = std::cos(twoPi*rndmv6[4]-pi);
438 const G4double sinPhi = std::copysign(std::sqrt((1.-cosPhi)*(1.+cosPhi)),rndmv6[4]-0.5);
439
440
441
442
443
444
445
446
447
448
449
450 const G4double RecEnergyCMS = (sCMSPlusRM2-PairInvMass*PairInvMass)*isqrts2;
451 const G4double LeptonEnergy2 = PairInvMass*0.5;
452
453
454 G4double abp = std::max((2.0*GammaEnergy*RecoilMass -
455 PairInvMass*PairInvMass + 2.0*PairInvMass*RecoilMass)*
456 (2.0*GammaEnergy*RecoilMass -
457 PairInvMass*PairInvMass - 2.0*PairInvMass*RecoilMass),0.0);
458
459 G4double thePRecoil = std::sqrt(abp) * isqrts2;
460
461
462 Recoil.
set( thePRecoil*sinTheta*cosPhi,
463 thePRecoil*sinTheta*sinPhi,
464 thePRecoil*cosTheta,
465 RecEnergyCMS);
466
467
468 const G4double thePLepton = std::sqrt( (LeptonEnergy2-LeptonMass)
469 *(LeptonEnergy2+LeptonMass));
470
471 LeptonPlus.
set(thePLepton*sinThetaLept*cosPhiLept,
472 thePLepton*sinThetaLept*sinPhiLept,
473 thePLepton*cosThetaLept,
474 LeptonEnergy2);
475
476 LeptonMinus.
set(-LeptonPlus.
x(),
479 LeptonEnergy2);
480
481
482
483
484
486
487
488
489
493
494 LeptonPlus.
boost(pair2cms);
495 LeptonMinus.
boost(pair2cms);
496
497
498
500 LeptonPlus.
boostZ(betaCMS);
501 LeptonMinus.
boostZ(betaCMS);
502
503
504 const G4double Jacob0 = x0*dum0*dum0;
505 const G4double Jacob1 = 2.*X1*lnPairInvMassRange*PairInvMass;
506 const G4double Jacob2 = std::abs(sinThetaLept);
507
512
515 const G4double dum1 = 1./std::sqrt( pPX*pPX + pPY*pPY );
516 const G4double cosPhiPlus = pPX*dum1;
517 const G4double sinPhiPlus = pPY*dum1;
518
519
520
521 const G4double elMassCTP = LeptonMass*cosThetaPlus;
522 const G4double ePlusSTP = EPlus*sinThetaPlus;
523 const G4double DPlus = (elMassCTP*elMassCTP + ePlusSTP*ePlusSTP)
524 /(EPlus + PPlus*cosThetaPlus);
525
530
533 const G4double dum2 = 1./std::sqrt( ePX*ePX + ePY*ePY );
534 const G4double cosPhiMinus = ePX*dum2;
535 const G4double sinPhiMinus = ePY*dum2;
536
537 const G4double elMassCTM = LeptonMass*cosThetaMinus;
538 const G4double eMinSTM = EMinus*sinThetaMinus;
539 const G4double DMinus = (elMassCTM*elMassCTM + eMinSTM*eMinSTM)
540 /(EMinus + PMinus*cosThetaMinus);
541
542
543 const G4double cosdPhi = cosPhiPlus*cosPhiMinus + sinPhiPlus*sinPhiMinus;
546
547 const G4double BigPhi = -LeptonMass2 / (GammaEnergy*GammaEnergy2 * q2*q2);
548
550 if (!iraw) {
551 if (itriplet) {
552 const G4double qun = factor1*iZ13*iZ13;
554 if (nun < 1.) {
555 FormFactor = (nun < 0.01) ? (13.8-55.4*std::sqrt(nun))*nun
556 : std::sqrt(1-(nun-1)*(nun-1));
557 }
558 } else {
559 const G4double dum3 = 217.*PRec*iZ13;
560 const G4double AFF = 1./(1. + dum3*dum3);
561 FormFactor = (1.-AFF)*(1-AFF);
562 }
563 }
564
565 if (GammaPolarizationMag==0.) {
566 const G4double pPlusSTP = PPlus*sinThetaPlus;
567 const G4double pMinusSTM = PMinus*sinThetaMinus;
568 const G4double pPlusSTPperDP = pPlusSTP/DPlus;
569 const G4double pMinusSTMperDM = pMinusSTM/DMinus;
571 pPlusSTPperDP *pPlusSTPperDP *(4.*EMinus*EMinus-q2)
572 + pMinusSTMperDM*pMinusSTMperDM*(4.*EPlus*EPlus - q2)
573 + 2.*pPlusSTPperDP*pMinusSTMperDM*cosdPhi
574 *(4.*EPlus*EMinus + q2 - 2.*GammaEnergy2)
575 - 2.*GammaEnergy2*(pPlusSTP*pPlusSTP+pMinusSTM*pMinusSTM)/(DMinus*DPlus));
576 betheheitler = dunpol * factor;
577 } else {
578 const G4double pPlusSTP = PPlus*sinThetaPlus;
579 const G4double pMinusSTM = PMinus*sinThetaMinus;
580 const G4double pPlusSTPCPPperDP = pPlusSTP*cosPhiPlus/DPlus;
581 const G4double pMinusSTMCPMperDM = pMinusSTM*cosPhiMinus/DMinus;
582 const G4double caa = 2.*(EPlus*pMinusSTMCPMperDM+EMinus*pPlusSTPCPPperDP);
583 const G4double cbb = pMinusSTMCPMperDM-pPlusSTPCPPperDP;
584 const G4double ccc = (pPlusSTP*pPlusSTP + pMinusSTM*pMinusSTM
585 +2.*pPlusSTP*pMinusSTM*cosdPhi)/ (DMinus*DPlus);
586 const G4double dtot= 2.*BigPhi*( caa*caa - q2*cbb*cbb - GammaEnergy2*ccc);
587 betheheitler = dtot * factor;
588 }
589
590 const G4double cross = Norme * Jacob0 * Jacob1 * Jacob2 * betheheitler
591 * FormFactor * RecoilMass / sqrts;
592 pdf = cross * (xu1 - xl1) /
G4Exp(correctionIndex*
G4Log(X1));
593 } while ( pdf < ymax * rndmv6[5] );
594
595
596 if ( fVerbose > 2 ) {
597 G4double recul = std::sqrt(Recoil.
x()*Recoil.
x()+Recoil.
y()*Recoil.
y()
598 +Recoil.
z()*Recoil.
z());
599 G4cout <<
"BetheHeitler5DModel GammaEnergy= " << GammaEnergy
600 << " PDF= " << pdf << " ymax= " << ymax
601 <<
" recul= " << recul <<
G4endl;
602 }
603
604
605
606 if ( fVerbose > 4 ) {
607 G4cout <<
"BetheHeitler5DModel GammaDirection " << GammaDirection <<
G4endl;
608 G4cout <<
"BetheHeitler5DModel GammaPolarization " << GammaPolarization <<
G4endl;
609 G4cout <<
"BetheHeitler5DModel GammaEnergy " << GammaEnergy <<
G4endl;
610 G4cout <<
"BetheHeitler5DModel Conv "
611 << (itriplet ?
"triplet" :
"nucl") <<
G4endl;
612 }
613
614 if (GammaPolarizationMag == 0.0) {
615
617 } else {
618
619 GammaPolarization /= GammaPolarizationMag;
620 }
621
622
624
625
627
631
632 if ( fVerbose > 2 ) {
633 G4cout <<
"BetheHeitler5DModel Recoil " << Recoil.
x() <<
" " << Recoil.
y() <<
" " << Recoil.
z()
634 <<
" " << Recoil.
t() <<
" " <<
G4endl;
635 G4cout <<
"BetheHeitler5DModel LeptonPlus " << LeptonPlus.
x() <<
" " << LeptonPlus.
y() <<
" "
636 << LeptonPlus.
z() <<
" " << LeptonPlus.
t() <<
" " <<
G4endl;
637 G4cout <<
"BetheHeitler5DModel LeptonMinus " << LeptonMinus.
x() <<
" " << LeptonMinus.
y() <<
" "
638 << LeptonMinus.
z() <<
" " << LeptonMinus.
t() <<
" " <<
G4endl;
639 }
640
641
644
645
647 if (itriplet) {
648
650 } else{
651 RecoilPart = theIonTable->
GetIon(Z,
A, 0);
652 }
654
655
656 fvect->push_back(aParticle1);
657 fvect->push_back(aParticle2);
658 fvect->push_back(aParticle3);
659
660
663}
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
CLHEP::HepLorentzVector G4LorentzVector
G4GLOB_DLL std::ostream G4cout
Hep3Vector orthogonal() const
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
double howOrthogonal(const Hep3Vector &v) const
Hep3Vector boostVector() const
HepLorentzVector & boost(double, double, double)
HepLorentzVector & boostZ(double beta)
void set(double x, double y, double z, double t)
HepLorentzVector & transform(const HepRotation &)
virtual void flatArray(const int size, double *vect)=0
const G4ThreeVector & GetMomentumDirection() const
G4double GetLogKineticEnergy() const
G4double GetKineticEnergy() const
const G4ThreeVector & GetPolarization() const
G4IonisParamElm * GetIonisation() const
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
static G4double GetNuclearMass(const G4double A, const G4double Z)
G4ParticleDefinition * fTheGamma
G4ParticleChangeForGamma * fParticleChange
void SetProposedKineticEnergy(G4double proposedKinEnergy)
G4int SelectIsotopeNumber(const G4Element *) const
const G4Element * SelectTargetAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double logKineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
void ProposeTrackStatus(G4TrackStatus status)