Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4BetheHeitler5DModel.cc
이 파일의 문서화 페이지로 가기
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // $Id: G4BetheHeitler5DModel.cc $
27 //
28 // -------------------------------------------------------------------
29 //
30 // GEANT4 Class file
31 //
32 //
33 // File name: G4BetheHeitler5DModel
34 //
35 // Authors:
36 // Igor Semeniouk and Denis Bernard,
37 // LLR, Ecole polytechnique & CNRS/IN2P3, 91128 Palaiseau, France
38 //
39 // Acknowledgement of the support of the French National Research Agency
40 // (ANR-13-BS05-0002).
41 //
42 // Reference: arXiv:1802.08253 [hep-ph]
43 //
44 // Class Description:
45 //
46 // Generates the conversion of a high-energy photon to an e+e- pair, either in the field of an
47 // atomic electron (triplet) or nucleus (nuclear).
48 // Samples the five-dimensional (5D) differential cross-section analytical expression:
49 // . Non polarized conversion:
50 // H.A. Bethe, W. Heitler, Proc. R. Soc. Lond. Ser. A 146 (1934) 83.
51 // . Polarized conversion:
52 // T. H. Berlin and L. Madansky, Phys. Rev. 78 (1950) 623,
53 // M. M. May, Phys. Rev. 84 (1951) 265,
54 // J. M. Jauch and F. Rohrlich, The theory of photons and electrons, 1976.
55 //
56 // All the above expressions are named "Bethe-Heitler" here.
57 //
58 // Bethe & Heitler, put in Feynman diagram parlance, compute only the two dominant diagrams of
59 // the first order Born development, which is an excellent approximation for nuclear conversion
60 // and for high-energy triplet conversion.
61 //
62 // Only the linear polarisation of the incoming photon takes part in these expressions.
63 // The circular polarisation of the incoming photon does not (take part) and no polarisation
64 // is transfered to the final leptons.
65 //
66 // In case conversion takes place in the field of an isolated nucleus or electron, the bare
67 // Bethe-Heitler expression is used.
68 //
69 // In case the nucleus or the electron are part of an atom, the screening of the target field
70 // by the other electrons of the atom is described by a simple form factor, function of q2:
71 // . nuclear: N.F. Mott, H.S.W. Massey, The Theory of Atomic Collisions, 1934.
72 // . triplet: J.A. Wheeler and W.E. Lamb, Phys. Rev. 55 (1939) 858.
73 //
74 // The nuclear form factor that affects the probability of very large-q2 events, is not considered.
75 //
76 // In principle the code is valid from threshold, that is from 2 * m_e c^2 for nuclear and from
77 // 4 * m_e c^2 for triplet, up to infinity, while in pratice the divergence of the differential
78 // cross section at small q2 and, at high-energy, at small polar angle, make it break down at
79 // some point that depends on machine precision.
80 //
81 // Very-high-energy LPM suppression effects in the normalized differential cross-section
82 // are not considered.
83 //
84 // The 5D differential cross section is sampled without any high-energy nor small
85 // angle approximation(s).
86 // The generation is strictly energy-momentum conserving when all particles in the final state
87 // are taken into account, that is, including the recoiling target.
88 // (In contrast with the BH expressions taken at face values, for which the electron energy is
89 // taken to be EMinus = GammaEnergy - EPlus)
90 //
91 // Tests include the examination of 1D distributions: see TestEm15
92 //
93 // Total cross sections are not computed (we inherit from other classes).
94 // We just convert a photon on a target when asked to do so.
95 //
96 // Pure nuclear, pure triplet and 1/Z triplet/nuclear mixture can be generated.
97 //
98 // -------------------------------------------------------------------
99 
100 #include "G4BetheHeitler5DModel.hh"
101 #include "G4EmParameters.hh"
102 
103 #include "G4PhysicalConstants.hh"
104 #include "G4SystemOfUnits.hh"
105 #include "G4Electron.hh"
106 #include "G4Positron.hh"
107 #include "G4Gamma.hh"
108 #include "G4IonTable.hh"
109 #include "G4NucleiProperties.hh"
110 
111 #include "Randomize.hh"
113 #include "G4Pow.hh"
114 #include "G4Log.hh"
115 #include "G4Exp.hh"
116 
117 #include "G4LorentzVector.hh"
118 #include "G4ThreeVector.hh"
119 
120 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
121 
123  const G4String& nam)
124  : G4BetheHeitlerModel(pd, nam), fVerbose(1), fConversionType(0), iraw(false)
125 {
127  // Verbosity levels: ( Can redefine as needed, but some consideration )
128  // 0 = nothing
129  // > 2 print results
130  // > 4 print photon direction & polarisation
131 }
132 
133 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
134 
136 {}
137 
138 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
139 
141  const G4DataVector& vec)
142 {
144 
146  // place to initialise model parameters
147  fVerbose = theManager->Verbose();
148  fConversionType = theManager->GetConversionType();
150  // iraw :
151  // true : isolated electron or nucleus.
152  // false : inside atom -> screening form factor
153  iraw = theManager->OnIsolated();
154  // G4cout << "BH5DModel::Initialise verbose " << fVerbose
155  // << " isolated " << iraw << " ctype "<< fConversionType << G4endl;
156 }
157 
158 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
159 
160 void
162  const G4LorentzVector& q,
163  G4LorentzVector& res) const
164 {
165 // p : 4-vector which will be boosted
166 // q : 4-vector of new origin in the old coordinates
167  const G4double pq = p.x()*q.x() + p.y()*q.y() + p.z()*q.z();
168  const G4double qq = q.x()*q.x() + q.y()*q.y() + q.z()*q.z();
169  const G4double mass = std::sqrt(q.t()*q.t()-qq);
170  const G4double lf = ((q.t()-mass)*pq/qq+p.t())/mass;
171  res.setX(p.x()+q.x()*lf);
172  res.setY(p.y()+q.y()*lf);
173  res.setZ(p.z()+q.z()*lf);
174  res.setT((p.t()*q.t()+pq)/mass);
175 }
176 
177 
178 // assuming that q.x=q.y=0.0
179 void
181  const G4double qz,
182  const G4double qt,
183  const G4double lffac,
184  const G4double imass,
185  G4LorentzVector& res) const
186 {
187 // p : 4-vector which will be boosted
188 // q : 4-vector of new origin in the old coordinates
189  const G4double pq = p.z()*qz;
190  const G4double lf = (lffac*pq+p.t())*imass;
191  res.setZ(p.z()+qz*lf);
192  res.setT((p.t()*qt+pq)*imass);
193 }
194 
195 
196 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
197 
199  G4double Z,
200  G4double e,
201  G4double loge) const
202 {
203  const G4double Q = e/par[9];
204  return par[0] * G4Exp((par[2]+loge*par[4])*loge)
205  / (par[1]+ G4Exp(par[3]*loge)+G4Exp(par[5]*loge))
206  * (1+par[7]*G4Exp(par[8]*G4Log(Z))*Q/(1+Q));
207 }
208 
209 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
210 void
211 
212 G4BetheHeitler5DModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
213  const G4MaterialCutsCouple* couple,
214  const G4DynamicParticle* aDynamicGamma,
216 {
217  // MeV
218  static const G4double ElectronMass = CLHEP::electron_mass_c2;
219  static const G4double ElectronMass2 = ElectronMass*ElectronMass;
220  static const G4double alpha0 = CLHEP::fine_structure_const;
221  // mm
222  static const G4double r0 = CLHEP::classic_electr_radius;
223  // mbarn
224  static const G4double r02 = r0*r0*1.e+25;
225  static const G4double twoPi = CLHEP::twopi;
226  static const G4double factor = alpha0 * r02 / (twoPi*twoPi);
227  static const G4double factor1 = 2.66134007899/(8.*alpha0*ElectronMass);
228  //
229  static const G4double PairInvMassMin = 2.*ElectronMass;
230  //
231  static const G4double nu[10] = { 0.0227436, 0.0582046, 3.0322675, 2.8275065,
232  -0.0034004, 1.1212766, 1.8989468, 68.3492750,
233  0.0211186, 14.4 };
234  static const G4double tr[10] = { 0.0332350, 4.3942537, 2.8515925, 2.6351695,
235  -0.0031510, 1.5737305, 1.8104647, 20.6434021,
236  -0.0272586, 28.9};
237  //
238  static const G4double para[3][2] = { {11., -16.},{-1.17, -2.95},{-2., -0.5} };
239  //
240  static const G4double correctionIndex = 1.4;
241  //
242  const G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
243  const G4double GammaEnergy2 = GammaEnergy*GammaEnergy;
244  // do nothing below the threshold
245  if ( GammaEnergy <= LowEnergyLimit()) { return; }
246  // Will not be true tot cross section = 0
247  if ( GammaEnergy <= 2.0*ElectronMass) { return; }
248  //
249  const G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection();
250  G4ThreeVector GammaPolarization = aDynamicGamma->GetPolarization();
251  // The protection polarization perpendicular to the direction vector,
252  // as it done in G4LivermorePolarizedGammaConversionModel,
253  // assuming Direction is unitary vector
254  // (projection to plane) p_proj = p - (p o d)/(d o d) x d
255  if ( GammaPolarization.howOrthogonal(GammaDirection) != 0) {
256  GammaPolarization -= GammaPolarization.dot(GammaDirection) * GammaDirection;
257  }
258  // End of Protection
259  //
260  const G4double GammaPolarizationMag = GammaPolarization.mag();
262  // target element
263  // select randomly one element constituting the material
264  const G4Element* anElement = SelectRandomAtom(couple, fTheGamma, GammaEnergy);
265  // Atomic number
266  const G4int Z = anElement->GetZasInt();
267  const G4int A = SelectIsotopeNumber(anElement);
268  const G4double iZ13 = 1./anElement->GetIonisation()->GetZ3();
269  const G4double targetMass = G4NucleiProperties::GetNuclearMass(A, Z);
270  //
271  CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
272  //
273  // itriplet : true -- triplet, false -- nuclear.
274  G4bool itriplet = false;
275  if (fConversionType == 1) {
276  itriplet = false;
277  } else if (fConversionType == 2) {
278  itriplet = true;
279  if ( GammaEnergy <= 4.0*ElectronMass ) return;
280  } else if ( GammaEnergy > 4.0*ElectronMass ) {
281  // choose triplet or nuclear from a triplet/nuclear=1/Z
282  // total cross section ratio.
283  // approximate at low energies !
284  if(rndmEngine->flat()*(Z+1) < 1.) {
285  itriplet = true;
286  }
287  }
288  //
289  const G4double RecoilMass = itriplet ? ElectronMass : targetMass;
290  const G4double RecoilMass2 = RecoilMass*RecoilMass;
291  const G4double sCMS = 2.*RecoilMass*GammaEnergy + RecoilMass2;
292  const G4double sCMSPlusRM2 = sCMS + RecoilMass2;
293  const G4double sqrts = std::sqrt(sCMS);
294  const G4double isqrts2 = 1./(2.*sqrts);
295  //
296  const G4double PairInvMassMax = sqrts-RecoilMass;
297  const G4double PairInvMassRange = PairInvMassMax/PairInvMassMin;
298  // use exact expression:
299  const G4double lnPairInvMassRange = G4Log(PairInvMassRange);
300  // initial state. Defines z axis of "0" frame as along photon propagation.
301  // create 4-vectors: gamma0 + target0 and CMS=gamma0+target0
302  // Since CMS(0., 0., GammaEnergy, GammaEnergy+RecoilMass) set some constants
303  // for the special boost that makes use of the form of CMS 4-vector
304  const G4double CMSqz = GammaEnergy;
305  const G4double CMSt = GammaEnergy+RecoilMass;
306  const G4double iCMSmass = 1./std::sqrt(RecoilMass*(RecoilMass+2.*GammaEnergy));
307  const G4double CMSfact = (CMSt-1./iCMSmass)/(CMSqz*CMSqz);
308  // maximum value of pdf
309  const G4double EffectiveZ = iraw ? 0.5 : Z;
310  const G4double Threshold = itriplet ? 4.*ElectronMass : 2.*ElectronMass;
311  const G4double AvailableEnergy = GammaEnergy - Threshold;
312  const G4double LogAvailableEnergy = G4Log(AvailableEnergy);
313  //
314  const G4double MaxDiffCross = itriplet
315  ? MaxDiffCrossSection(tr, EffectiveZ, AvailableEnergy, LogAvailableEnergy)
316  : MaxDiffCrossSection(nu, EffectiveZ, AvailableEnergy, LogAvailableEnergy);
317  //
318  // 50% safety marging factor
319  const G4double ymax = 1.5 * MaxDiffCross;
320  // x1 bounds
321  const G4double xu1 = (LogAvailableEnergy > para[2][0])
322  ? para[0][0] + para[1][0]*LogAvailableEnergy
323  : para[0][0] + para[2][0]*para[1][0];
324  const G4double xl1 = (LogAvailableEnergy > para[2][1])
325  ? para[0][1] + para[1][1]*LogAvailableEnergy
326  : para[0][1] + para[2][1]*para[1][1];
327  //
328  G4LorentzVector Recoil0;
329  G4LorentzVector Positron0;
330  G4LorentzVector Electron0;
331  G4LorentzVector Recoil1;
332  G4LorentzVector Positron1;
333  G4LorentzVector Electron1;
334  G4LorentzVector Positron2;
335  G4LorentzVector Electron2;
336  G4LorentzVector Pair1;
337  G4double pdf = 0.;
338  // START Sampling
339  do {
340  G4double X1;
341  G4double rndmv2[2];
342  G4double cond1;
343  do {
344  rndmEngine->flatArray(2, rndmv2);
345  X1 = rndmv2[0];
346  cond1 = G4Exp(correctionIndex*G4Log(X1));
347  } while (cond1 < rndmv2[1]);
348 
349  const G4double x0 = G4Exp(xl1 + (xu1 - xl1)*rndmEngine->flat());
350  const G4double dum0 = 1./(1.+x0);
351  const G4double cosTheta = (x0-1.)*dum0;
352  const G4double sinTheta = std::sqrt(4.*x0)*dum0;
353 
354  const G4double PairInvMass = PairInvMassMin*G4Exp(X1*X1*lnPairInvMassRange);
355 
356  G4double rndmv3[3];
357  rndmEngine->flatArray(3, rndmv3);
358  //--------------------------------------------------------------------------
359  // const G4double ThetaLept = pi*rndmv3[0];
360  // const G4double cosThetaLept = std::cos(ThetaLept);
361  // const G4double sinThetaLept = std::sin(ThetaLept);
362  //
363  // const G4double PhiLept = twoPi*rndmv3[1]-pi;
364  // const G4double cosPhiLept = std::cos(PhiLept);
365  // const G4double sinPhiLept = std::sin(PhiLept);
366  //
367  // const G4double Phi = twoPi*rndmv3[2]-pi;
368  // const G4double cosPhi = std::cos(Phi);
369  // const G4double sinPhi = std::sin(Phi);
370  //---------------------------------------------------------------------------
371  // cos and sin theta-lepton
372  const G4double cosThetaLept = std::cos(pi*rndmv3[0]);
373  // sin(ThetaLept) is always in [0,+1] if ThetaLept is in [0,pi]
374  const G4double sinThetaLept = std::sqrt((1.-cosThetaLept)*(1.+cosThetaLept));
375  // cos and sin phi-lepton
376  const G4double cosPhiLept = std::cos(twoPi*rndmv3[1]-pi);
377  const G4double dumx0 = std::sqrt((1.-cosPhiLept)*(1.+cosPhiLept));
378  // sin(PhiLept) is in [-1,0] if PhiLept in [-pi,0) and
379  // is in [0,+1] if PhiLept in [0,+pi]
380  const G4double sinPhiLept = (rndmv3[1]<0.5) ? -1.*dumx0 : dumx0;
381  // cos and sin phi
382  const G4double cosPhi = std::cos(twoPi*rndmv3[2]-pi);
383  const G4double dumx1 = std::sqrt((1.-cosPhi)*(1.+cosPhi));
384  const G4double sinPhi = (rndmv3[2]<0.5) ? -1.*dumx1 : dumx1;
385 
386  // frames:
387  // 0 : the laboratory Lorentz frame, axes along photon direction and polarisation
388  // 1 : the center-of-mass Lorentz frame
389  // 2 : the pair Lorentz frame
390  // 3 : the laboratory Lorentz frame, Geant4 axes definition
391 
392  // in the center-of-mass frame
393  const G4double RecEnergyCMS = (sCMSPlusRM2-PairInvMass*PairInvMass)*isqrts2;
394  const G4double LeptonEnergy2 = PairInvMass*0.5;
395  const G4double thePRecoil = std::sqrt( (RecEnergyCMS-RecoilMass)
396  *(RecEnergyCMS+RecoilMass));
397  Recoil1.setX( thePRecoil*sinTheta*cosPhi);
398  Recoil1.setY( thePRecoil*sinTheta*sinPhi);
399  Recoil1.setZ( thePRecoil*cosTheta);
400  Recoil1.setT( RecEnergyCMS);
401  Pair1.setX (-Recoil1.x());
402  Pair1.setY (-Recoil1.y());
403  Pair1.setZ (-Recoil1.z());
404  Pair1.setT ( RecEnergyCMS);
405  // in the pair frame
406  const G4double thePLepton = std::sqrt( (LeptonEnergy2-ElectronMass)
407  *(LeptonEnergy2+ElectronMass));
408  Positron2.setX( thePLepton*sinThetaLept*cosPhiLept);
409  Positron2.setY( thePLepton*sinThetaLept*sinPhiLept);
410  Positron2.setZ( thePLepton*cosThetaLept);
411  Positron2.setT( LeptonEnergy2);
412  Electron2.setX(-Positron2.x());
413  Electron2.setY(-Positron2.y());
414  Electron2.setZ(-Positron2.z());
415  Electron2.setT( LeptonEnergy2);
416  // back to the center-of-mass frame
417  Pair1.setT(sqrts-RecEnergyCMS);
418 
419  // Normalisation of final state phase space:
420  // Section 47 of Particle Data Group, Chin. Phys. C, 40, 100001 (2016)
421  const G4double Norme = Recoil1.vect().mag() * Positron2.vect().mag();
422  //
423  BoostG4LorentzVector(Positron2, Pair1, Positron1);
424  BoostG4LorentzVector(Electron2, Pair1, Electron1);
425  //
426  // back to the laboratory frame (make use of the CMS(0,0,Eg,Eg+RM)) form
427  Recoil0.setX(Recoil1.x());
428  Recoil0.setY(Recoil1.y());
429  BoostG4LorentzVector(Recoil1 , CMSqz, CMSt, CMSfact, iCMSmass, Recoil0);
430  //
431  Positron0.setX(Positron1.x());
432  Positron0.setY(Positron1.y());
433  BoostG4LorentzVector(Positron1, CMSqz, CMSt, CMSfact, iCMSmass, Positron0);
434  //
435  Electron0.setX(Electron1.x());
436  Electron0.setY(Electron1.y());
437  BoostG4LorentzVector(Electron1, CMSqz, CMSt, CMSfact, iCMSmass, Electron0);
438  //
439  // Jacobian factors
440  const G4double Jacob0 = x0*dum0*dum0;
441  const G4double Jacob1 = 2.*X1*lnPairInvMassRange*PairInvMass;
442  const G4double Jacob2 = std::abs(sinThetaLept);
443 
444  // Normalisation of final state phase space:
445  // Section 47 of Particle Data Group, Chin. Phys. C, 40, 100001 (2016)
446 // G4double Norme = Recoil1.vect().mag() * Positron2.vect().mag();
447 
448  const G4double EPlus = Positron0.t();
449  const G4double PPlus = Positron0.vect().mag();
450  const G4double sinThetaPlus = Positron0.vect().perp()/PPlus;
451  const G4double cosThetaPlus = Positron0.vect().cosTheta();
452 
453  const G4double pPX = Positron0.x();
454  const G4double pPY = Positron0.y();
455  const G4double dum1 = 1./std::sqrt( pPX*pPX + pPY*pPY );
456  const G4double cosPhiPlus = pPX*dum1;
457  const G4double sinPhiPlus = pPY*dum1;
458 
459  // denominators:
460  // the two cancelling leading terms for forward emission at high energy, removed
461  const G4double elMassCTP = ElectronMass*cosThetaPlus;
462  const G4double ePlusSTP = EPlus*sinThetaPlus;
463  const G4double DPlus = (elMassCTP*elMassCTP + ePlusSTP*ePlusSTP)
464  /(EPlus + PPlus*cosThetaPlus);
465 
466  const G4double EMinus = Electron0.t();
467  const G4double PMinus = Electron0.vect().mag();
468  const G4double sinThetaMinus = Electron0.vect().perp()/PMinus;
469  const G4double cosThetaMinus = Electron0.vect().cosTheta();
470 
471  const G4double ePX = Electron0.x();
472  const G4double ePY = Electron0.y();
473  const G4double dum2 = 1./std::sqrt( ePX*ePX + ePY*ePY );
474  const G4double cosPhiMinus = ePX*dum2;
475  const G4double sinPhiMinus = ePY*dum2;
476 
477  const G4double elMassCTM = ElectronMass*cosThetaMinus;
478  const G4double eMinSTM = EMinus*sinThetaMinus;
479  const G4double DMinus = (elMassCTM*elMassCTM + eMinSTM*eMinSTM)
480  /(EMinus + PMinus*cosThetaMinus);
481 
482  // cos(phiMinus-PhiPlus)
483  const G4double cosdPhi = cosPhiPlus*cosPhiMinus + sinPhiPlus*sinPhiMinus;
484  const G4double PRec = Recoil0.vect().mag();
485  const G4double q2 = PRec*PRec;
486  const G4double BigPhi = -ElectronMass2 / (GammaEnergy*GammaEnergy2 * q2*q2);
487 
488  G4double FormFactor = 1.;
489  if (!iraw) {
490  if (itriplet) {
491  const G4double qun = factor1*iZ13*iZ13;
492  const G4double nun = qun * PRec;
493  if (nun < 1.) {
494  FormFactor = (nun < 0.01) ? (13.8-55.4*std::sqrt(nun))*nun
495  : std::sqrt(1-(nun-1)*(nun-1));
496  } // else FormFactor = 1 by default
497  } else {
498  const G4double dum3 = 217.*PRec*iZ13;
499  const G4double AFF = 1./(1. + dum3*dum3);
500  FormFactor = (1.-AFF)*(1-AFF);
501  }
502  } // else FormFactor = 1 by default
503  //
504  G4double betheheitler;
505  if (GammaPolarizationMag==0.) {
506  const G4double pPlusSTP = PPlus*sinThetaPlus;
507  const G4double pMinusSTM = PMinus*sinThetaMinus;
508  const G4double pPlusSTPperDP = pPlusSTP/DPlus;
509  const G4double pMinusSTMperDM = pMinusSTM/DMinus;
510  const G4double dunpol = BigPhi*(
511  pPlusSTPperDP *pPlusSTPperDP *(4.*EMinus*EMinus-q2)
512  + pMinusSTMperDM*pMinusSTMperDM*(4.*EPlus*EPlus - q2)
513  + 2.*pPlusSTPperDP*pMinusSTMperDM*cosdPhi
514  *(4.*EPlus*EMinus + q2 - 2.*GammaEnergy2)
515  - 2.*GammaEnergy2*(pPlusSTP*pPlusSTP+pMinusSTM*pMinusSTM)/(DMinus*DPlus));
516  betheheitler = dunpol * factor;
517  } else {
518  const G4double pPlusSTP = PPlus*sinThetaPlus;
519  const G4double pMinusSTM = PMinus*sinThetaMinus;
520  const G4double pPlusSTPCPPperDP = pPlusSTP*cosPhiPlus/DPlus;
521  const G4double pMinusSTMCPMperDM = pMinusSTM*cosPhiMinus/DMinus;
522  const G4double caa = 2.*(EPlus*pMinusSTMCPMperDM+EMinus*pPlusSTPCPPperDP);
523  const G4double cbb = pMinusSTMCPMperDM-pPlusSTPCPPperDP;
524  const G4double ccc = (pPlusSTP*pPlusSTP + pMinusSTM*pMinusSTM
525  +2.*pPlusSTP*pMinusSTM*cosdPhi)/ (DMinus*DPlus);
526  const G4double dtot= 2.*BigPhi*( caa*caa - q2*cbb*cbb - GammaEnergy2*ccc);
527  betheheitler = dtot * factor;
528  }
529  //
530  const G4double cross = Norme * Jacob0 * Jacob1 * Jacob2 * betheheitler
531  * FormFactor * RecoilMass / sqrts;
532  pdf = cross * (xu1 - xl1) / cond1;
533  } while ( pdf < ymax * rndmEngine->flat() );
534  // END of Sampling
535  //
536  if ( fVerbose > 2 ) {
537  G4double recul = std::sqrt(Recoil0.x()*Recoil0.x()+Recoil0.y()*Recoil0.y()
538  +Recoil0.z()*Recoil0.z());
539  G4cout << "BetheHeitler5DModel GammaEnergy= " << GammaEnergy
540  << " PDF= " << pdf << " ymax= " << ymax
541  << " recul= " << recul << G4endl;
542  }
543  // back to Geant4 system
544  if ( fVerbose > 4 ) {
545  G4cout << "BetheHeitler5DModel GammaDirection " << GammaDirection << G4endl;
546  G4cout << "BetheHeitler5DModel GammaPolarization " << GammaPolarization << G4endl;
547  }
548  //
549  if (GammaPolarizationMag == 0.0) {
550  G4ThreeVector axis(1.,0.,0.);
551  G4ThreeVector perp = GammaDirection.cross(axis);
552  if (perp.mag() == 0) {
553  axis.set(0.,1.,0.);
554  perp = GammaDirection.cross(axis);
555  }
556  perp = perp / perp.mag();
557  G4ThreeVector perperp = GammaDirection.cross(perp);
558  perperp = perperp / perperp.mag();
559  // rotation
560  G4ThreeVector Rot = Recoil0.x()*perp + Recoil0.y()*perperp
561  + Recoil0.z()*GammaDirection;
562  Recoil0.setVect(Rot);
563  Rot = Positron0.x()*perp + Positron0.y()*perperp
564  + Positron0.z()*GammaDirection;
565  Positron0.setVect(Rot);
566  Rot = Electron0.x()*perp + Electron0.y()*perperp
567  + Electron0.z()*GammaDirection;
568  Electron0.setVect(Rot);
569  } else {
570  // The unit norm vector that is orthogonal to the two others
571  G4ThreeVector yGrec = GammaDirection.cross(GammaPolarization);
572  // rotation
573  G4ThreeVector Rot = Recoil0.x()*GammaPolarization + Recoil0.y()*yGrec
574  + Recoil0.z()*GammaDirection;
575  Recoil0.setVect(Rot);
576  Rot = Positron0.x()*GammaPolarization + Positron0.y()*yGrec
577  + Positron0.z()*GammaDirection;
578  Positron0.setVect(Rot);
579  Rot = Electron0.x()*GammaPolarization + Electron0.y()*yGrec
580  + Electron0.z()*GammaDirection;
581  Electron0.setVect(Rot);
582  }
583  //
584  if ( fVerbose > 2 ) {
585  G4cout << "BetheHeitler5DModel Recoil0 " << Recoil0.x() << " " << Recoil0.y() << " " << Recoil0.z()
586  << " " << Recoil0.t() << " " << G4endl;
587  G4cout << "BetheHeitler5DModel Positron0 " << Positron0.x() << " " << Positron0.y() << " "
588  << Positron0.z() << " " << Positron0.t() << " " << G4endl;
589  G4cout << "BetheHeitler5DModel Electron0 " << Electron0.x() << " " << Electron0.y() << " "
590  << Electron0.z() << " " << Electron0.t() << " " << G4endl;
591  }
592  //
593  // create G4DynamicParticle object for the particle1 (electron)
594  G4DynamicParticle* aParticle1 = new G4DynamicParticle(fTheElectron,Electron0);
595  // create G4DynamicParticle object for the particle2 (positron)
596  G4DynamicParticle* aParticle2 = new G4DynamicParticle(fThePositron,Positron0);
597  // create G4DynamicParticle object for the particle3 ( recoil )
598  G4DynamicParticle* aParticle3;
599  G4ParticleDefinition* RecoilPart;
600  if (itriplet) {
601  // triplet
602  RecoilPart = fTheElectron;
603  } else{
604  RecoilPart = theIonTable->GetIon(Z, A, 0);
605  }
606  aParticle3 = new G4DynamicParticle(RecoilPart,Recoil0);
607  // Fill output vector
608  fvect->push_back(aParticle1);
609  fvect->push_back(aParticle2);
610  fvect->push_back(aParticle3);
611  // kill incident photon
614 }
615 
616 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void set(double x, double y, double z)
void SampleSecondaries(std::vector< G4DynamicParticle * > *fvect, const G4MaterialCutsCouple *couple, const G4DynamicParticle *aDynamicGamma, G4double, G4double) final
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:183
double perp() const
static G4IonTable * GetIonTable()
Definition: G4IonTable.hh:78
#define G4endl
Definition: G4ios.hh:61
G4int SelectIsotopeNumber(const G4Element *)
Definition: G4VEmModel.cc:335
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * fTheGamma
const char * p
Definition: xmltok.h:285
G4int GetConversionType() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
virtual void flatArray(const int size, double *vect)=0
double dot(const Hep3Vector &) const
void setVect(const Hep3Vector &)
const G4Element * SelectRandomAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.hh:552
G4BetheHeitler5DModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="BetheHeitler5D")
static constexpr double classic_electr_radius
G4double G4Log(G4double x)
Definition: G4Log.hh:230
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:616
Float_t Z
double G4double
Definition: G4Types.hh:76
bool G4bool
Definition: G4Types.hh:79
TString part[npart]
Definition: Style.C:32
virtual double flat()=0
Double_t X1
static constexpr double electron_mass_c2
G4double GetZ3() const
G4double MaxDiffCrossSection(const G4double *par, G4double eZ, G4double e, G4double loge) const
double A(double temperature)
double cosTheta() const
static G4double GetNuclearMass(const G4double A, const G4double Z)
void BoostG4LorentzVector(const G4LorentzVector &p, const G4LorentzVector &q, G4LorentzVector &res) const
double howOrthogonal(const Hep3Vector &v) const
Definition: SpaceVector.cc:219
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &) final
G4int Verbose() const
G4int GetZasInt() const
Definition: G4Element.hh:132
const G4double twoPi
Hep3Vector cross(const Hep3Vector &) const
static constexpr double twopi
Definition: SystemOfUnits.h:55
double mag() const
G4ParticleChangeForGamma * fParticleChange
const G4ThreeVector & GetPolarization() const
int G4int
Definition: G4Types.hh:78
G4IonisParamElm * GetIonisation() const
Definition: G4Element.hh:199
G4double GetKineticEnergy() const
G4GLOB_DLL std::ostream G4cout
G4ParticleDefinition * fThePositron
G4ParticleDefinition * fTheElectron
Hep3Vector vect() const
static double Q[]
static constexpr double pi
Definition: G4SIunits.hh:75
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
Definition: G4IonTable.cc:504
static constexpr double fine_structure_const
void ProposeTrackStatus(G4TrackStatus status)
double flat()
Definition: G4AblaRandom.cc:48
bool OnIsolated() const
static G4EmParameters * Instance()