Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/standard/src/G4PairProductionRelModel.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /processes/electromagnetic/standard/src/G4PairProductionRelModel.cc (Version 11.3.0) and /processes/electromagnetic/standard/src/G4PairProductionRelModel.cc (Version 9.3.p2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
                                                   >>  26 // $Id: G4PairProductionRelModel.cc,v 1.3 2009/05/15 17:12:33 vnivanch Exp $
                                                   >>  27 // GEANT4 tag $Name: geant4-09-03-patch-02 $
 26 //                                                 28 //
 27 // -------------------------------------------     29 // -------------------------------------------------------------------
 28 //                                                 30 //
 29 // GEANT4 Class file                               31 // GEANT4 Class file
 30 //                                                 32 //
 31 //                                                 33 //
 32 // File name:     G4PairProductionRelModel         34 // File name:     G4PairProductionRelModel
 33 //                                                 35 //
 34 // Author:        Andreas Schaelicke               36 // Author:        Andreas Schaelicke
 35 //                                                 37 //
 36 // Creation date: 02.04.2009                       38 // Creation date: 02.04.2009
 37 //                                                 39 //
 38 // Modifications:                                  40 // Modifications:
 39 // 20.03.17 Change LPMconstant such that it gi << 
 40 //          that consistent to Migdal's one; f << 
 41 //          computation; suppression is consis << 
 42 //          brem. model (F.Hariri)             << 
 43 // 28-05-18 New version with improved screenin << 
 44 //          LPM function approximation, effici << 
 45 //          Corrected call to selecting target << 
 46 //          (M. Novak)                         << 
 47 //                                                 41 //
 48 // Class Description:                              42 // Class Description:
 49 //                                                 43 //
 50 // Main References:                                44 // Main References:
 51 //  J.W.Motz et.al., Rev. Mod. Phys. 41 (1969)     45 //  J.W.Motz et.al., Rev. Mod. Phys. 41 (1969) 581.
 52 //  S.Klein,  Rev. Mod. Phys. 71 (1999) 1501.      46 //  S.Klein,  Rev. Mod. Phys. 71 (1999) 1501.
 53 //  T.Stanev et.al., Phys. Rev. D25 (1982) 129     47 //  T.Stanev et.al., Phys. Rev. D25 (1982) 1291.
 54 //  M.L.Ter-Mikaelian, High-energy Electromagn <<  48 //  M.L.Ter-Mikaelian, High-energy Electromagnetic Processes in Condensed Media, Wiley, 1972.
 55 //                     Wiley, 1972.            << 
 56 //                                                 49 //
 57 // -------------------------------------------     50 // -------------------------------------------------------------------
                                                   >>  51 //
                                                   >>  52 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
                                                   >>  53 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 58                                                    54 
 59 #include "G4PairProductionRelModel.hh"             55 #include "G4PairProductionRelModel.hh"
 60 #include "G4PhysicalConstants.hh"              << 
 61 #include "G4SystemOfUnits.hh"                  << 
 62 #include "G4Gamma.hh"                              56 #include "G4Gamma.hh"
 63 #include "G4Electron.hh"                           57 #include "G4Electron.hh"
 64 #include "G4Positron.hh"                           58 #include "G4Positron.hh"
                                                   >>  59 
 65 #include "G4ParticleChangeForGamma.hh"             60 #include "G4ParticleChangeForGamma.hh"
 66 #include "G4LossTableManager.hh"                   61 #include "G4LossTableManager.hh"
 67 #include "G4ModifiedTsai.hh"                   << 
 68 #include "G4Exp.hh"                            << 
 69 #include "G4Pow.hh"                            << 
 70 #include "G4AutoLock.hh"                       << 
 71                                                << 
 72 const G4int G4PairProductionRelModel::gMaxZet  << 
 73                                                << 
 74 // LPM constant: \alpha(mc^2)^2/(4\pi*\hbar c) << 
 75 const G4double G4PairProductionRelModel::gLPMc << 
 76   CLHEP::fine_structure_const*CLHEP::electron_ << 
 77   /(4.*CLHEP::pi*CLHEP::hbarc);                << 
 78                                                << 
 79 // abscissas and weights of an 8 point Gauss-L << 
 80 // for numerical integration on [0,1]          << 
 81 const G4double G4PairProductionRelModel::gXGL[ << 
 82   1.98550718e-02, 1.01666761e-01, 2.37233795e- << 
 83   5.91717321e-01, 7.62766205e-01, 8.98333239e- << 
 84 };                                             << 
 85 const G4double G4PairProductionRelModel::gWGL[ << 
 86   5.06142681e-02, 1.11190517e-01, 1.56853323e- << 
 87   1.81341892e-01, 1.56853323e-01, 1.11190517e- << 
 88 };                                             << 
 89                                                << 
 90 // elastic and inelatic radiation logarithms f << 
 91 // Thomas-Fermi model doesn't work): computed  << 
 92 const G4double G4PairProductionRelModel::gFelL << 
 93   0.0, 5.3104, 4.7935, 4.7402, 4.7112, 4.6694, << 
 94 };                                             << 
 95 const G4double G4PairProductionRelModel::gFine << 
 96   0.0, 5.9173, 5.6125, 5.5377, 5.4728, 5.4174, << 
 97 };                                             << 
 98                                                << 
 99 // constant cross section factor               << 
100 const G4double G4PairProductionRelModel::gXSec << 
101   4.*CLHEP::fine_structure_const*CLHEP::classi << 
102   *CLHEP::classic_electr_radius;               << 
103                                                << 
104 // gamma energy limit above which LPM suppress << 
105 // fIsUseLPMCorrection flag is true)           << 
106 const G4double G4PairProductionRelModel::gEgLP << 
107                                                << 
108 // special data structure per element i.e. per << 
109 std::vector<G4PairProductionRelModel::ElementD << 
110                                                << 
111 // LPM supression functions evaluated at initi << 
112 G4PairProductionRelModel::LPMFuncs G4PairProdu << 
113                                                    62 
114 namespace                                      << 
115 {                                              << 
116   G4Mutex thePairProdRelMutex = G4MUTEX_INITIA << 
117 }                                              << 
118                                                    63 
119 // CTR                                         <<  64 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
                                                   >>  65 
                                                   >>  66 using namespace std;
                                                   >>  67 
                                                   >>  68 
                                                   >>  69 const G4double G4PairProductionRelModel::facFel = log(184.15);
                                                   >>  70 const G4double G4PairProductionRelModel::facFinel = log(1194.); // 1440.
                                                   >>  71 
                                                   >>  72 const G4double G4PairProductionRelModel::preS1 = 1./(184.15*184.15);
                                                   >>  73 const G4double G4PairProductionRelModel::logTwo = log(2.);
                                                   >>  74 
                                                   >>  75 const G4double G4PairProductionRelModel::xgi[]={ 0.0199, 0.1017, 0.2372, 0.4083,
                                                   >>  76               0.5917, 0.7628, 0.8983, 0.9801 };
                                                   >>  77 const G4double G4PairProductionRelModel::wgi[]={ 0.0506, 0.1112, 0.1569, 0.1813,
                                                   >>  78               0.1813, 0.1569, 0.1112, 0.0506 };
                                                   >>  79 const G4double G4PairProductionRelModel::Fel_light[]  = {0., 5.31  , 4.79  , 4.74 ,  4.71} ;
                                                   >>  80 const G4double G4PairProductionRelModel::Finel_light[] = {0., 6.144 , 5.621 , 5.805 , 5.924} ;
                                                   >>  81 
                                                   >>  82 
                                                   >>  83 
120 G4PairProductionRelModel::G4PairProductionRelM     84 G4PairProductionRelModel::G4PairProductionRelModel(const G4ParticleDefinition*,
121                                                <<  85            const G4String& nam)
122   : G4VEmModel(nam), fIsUseLPMCorrection(true) <<  86   : G4VEmModel(nam),
123   fLPMEnergy(0.), fG4Calc(G4Pow::GetInstance() <<  87     theCrossSectionTable(0),
124   fTheElectron(G4Electron::Electron()), fThePo <<  88     nbins(10),
125   fParticleChange(nullptr)                     <<  89     fLPMconstant(fine_structure_const*electron_mass_c2*electron_mass_c2/(4.*pi*hbarc)*0.5),
126 {                                              <<  90     fLPMflag(true),
127   // gamma energy below which the parametrized <<  91     lpmEnergy(0.),
128   fParametrizedXSectionThreshold = 30.0*CLHEP: <<  92     use_completescreening(false)
129   // gamma energy below the Coulomb correction <<  93 {
130   fCoulombCorrectionThreshold    = 50.0*CLHEP: <<  94   fParticleChange = 0;
131   // set angular generator used in the final s <<  95   theGamma    = G4Gamma::Gamma();
132   SetAngularDistribution(new G4ModifiedTsai()) <<  96   thePositron = G4Positron::Positron();
                                                   >>  97   theElectron = G4Electron::Electron();
                                                   >>  98 
                                                   >>  99   nist = G4NistManager::Instance();  
                                                   >> 100 
133 }                                                 101 }
134                                                   102 
135 // DTR                                         << 103 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
                                                   >> 104 
136 G4PairProductionRelModel::~G4PairProductionRel    105 G4PairProductionRelModel::~G4PairProductionRelModel()
137 {                                                 106 {
138   if (isFirstInstance) {                       << 107   if(theCrossSectionTable) {
139     // clear ElementData container             << 108     theCrossSectionTable->clearAndDestroy();
140     for (auto const & ptr : gElementData) { de << 109     delete theCrossSectionTable;
141     gElementData.clear();                      << 110   }
142     // clear LPMFunctions (if any)             << 111 }
143     if (fIsUseLPMCorrection) {                 << 112 
144       gLPMFuncs.fLPMFuncG.clear();             << 113 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
145       gLPMFuncs.fLPMFuncPhi.clear();           << 114 
146       gLPMFuncs.fIsInitialized = false;        << 115 void G4PairProductionRelModel::Initialise(const G4ParticleDefinition*,
                                                   >> 116             const G4DataVector&)
                                                   >> 117 {
                                                   >> 118   fParticleChange = GetParticleChangeForGamma();
                                                   >> 119 
                                                   >> 120   if(theCrossSectionTable) {
                                                   >> 121     theCrossSectionTable->clearAndDestroy();
                                                   >> 122     delete theCrossSectionTable;
                                                   >> 123   }
                                                   >> 124 
                                                   >> 125   const G4ElementTable* theElementTable = G4Element::GetElementTable();
                                                   >> 126   size_t nvect = G4Element::GetNumberOfElements();
                                                   >> 127   theCrossSectionTable = new G4PhysicsTable(nvect);
                                                   >> 128   G4PhysicsLogVector* ptrVector;
                                                   >> 129   G4double emin = LowEnergyLimit();
                                                   >> 130   G4double emax = HighEnergyLimit();
                                                   >> 131   G4int n = nbins*G4int(log10(emax/emin));
                                                   >> 132   G4bool spline = G4LossTableManager::Instance()->SplineFlag(); 
                                                   >> 133   G4double e, value;
                                                   >> 134 
                                                   >> 135   for(size_t j=0; j<nvect ; j++) { 
                                                   >> 136 
                                                   >> 137     ptrVector  = new G4PhysicsLogVector(emin, emax, n);
                                                   >> 138     ptrVector->SetSpline(spline);
                                                   >> 139     G4double Z = (*theElementTable)[j]->GetZ();
                                                   >> 140     G4VEmModel::SetCurrentElement((*theElementTable)[j]);
                                                   >> 141     G4int   iz = G4int(Z);
                                                   >> 142     indexZ[iz] = j;
                                                   >> 143  
                                                   >> 144     for(G4int i=0; i<nbins; i++) {
                                                   >> 145       e = ptrVector->GetLowEdgeEnergy( i ) ;
                                                   >> 146       value = ComputeCrossSectionPerAtom(theGamma, e, Z);  
                                                   >> 147       ptrVector->PutValue( i, value );
147     }                                             148     }
                                                   >> 149 
                                                   >> 150     theCrossSectionTable->insert(ptrVector);
148   }                                               151   }
149 }                                                 152 }
150                                                   153 
151 void G4PairProductionRelModel::Initialise(cons << 154 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
152                                           cons << 155 /*
                                                   >> 156 G4double G4PairProductionRelModel::ComputeRelXSectionPerAtom(G4double k, G4double Z)
153 {                                                 157 {
154   if(nullptr == fParticleChange) { fParticleCh << 
155                                                   158 
156   if (isFirstInstance || gElementData.empty()) << 159   G4double cross = 0.0;
157     // init element data and LPM funcs         << 160   
158     G4AutoLock l(&thePairProdRelMutex);        << 161 
159     if (gElementData.empty()) {                << 162 
160       isFirstInstance = true;                  << 163 
161       gElementData.resize(gMaxZet+1, nullptr); << 164 }
162     }                                          << 165 */
163     // static data should be initialised only  << 166 
164     InitialiseElementData();                   << 167 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
165     if (fIsUseLPMCorrection) {                 << 168 
166       InitLPMFunctions();                      << 169 G4double G4PairProductionRelModel::ComputeXSectionPerAtom(G4double totalEnergy, G4double Z)
                                                   >> 170 {
                                                   >> 171   G4double cross = 0.0;
                                                   >> 172 
                                                   >> 173   // number of intervals and integration step 
                                                   >> 174   G4double vcut = electron_mass_c2/totalEnergy ;
                                                   >> 175 
                                                   >> 176   // limits by the screening variable
                                                   >> 177   G4double dmax = DeltaMax();
                                                   >> 178   G4double dmin = min(DeltaMin(totalEnergy),dmax);
                                                   >> 179   G4double vcut1 = 0.5 - 0.5*sqrt(1. - dmin/dmax) ;
                                                   >> 180   vcut = max(vcut, vcut1);
                                                   >> 181 
                                                   >> 182 
                                                   >> 183   G4double vmax = 0.5;
                                                   >> 184   G4int n = 1;  // needs optimisation
                                                   >> 185 
                                                   >> 186   G4double delta = (vmax - vcut)*totalEnergy/G4double(n);
                                                   >> 187 
                                                   >> 188   G4double e0 = vcut*totalEnergy;
                                                   >> 189   G4double xs; 
                                                   >> 190 
                                                   >> 191   // simple integration
                                                   >> 192   for(G4int l=0; l<n; l++,e0 += delta) {
                                                   >> 193     for(G4int i=0; i<8; i++) {
                                                   >> 194 
                                                   >> 195       G4double eg = (e0 + xgi[i]*delta);
                                                   >> 196       if (fLPMflag && totalEnergy>100.*GeV) 
                                                   >> 197   xs = ComputeRelDXSectionPerAtom(eg,totalEnergy,Z);
                                                   >> 198       else
                                                   >> 199   xs = ComputeDXSectionPerAtom(eg,totalEnergy,Z);
                                                   >> 200       cross += wgi[i]*xs;
                                                   >> 201 
167     }                                             202     }
168     l.unlock();                                << 
169   }                                               203   }
170   // element selectors should be initialised i << 204 
171   if (IsMaster()) {                            << 205   cross *= delta*2.;
172     InitialiseElementSelectors(p, cuts);       << 206 
                                                   >> 207   return cross;
                                                   >> 208 }
                                                   >> 209 
                                                   >> 210 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
                                                   >> 211 
                                                   >> 212 G4double 
                                                   >> 213 G4PairProductionRelModel::ComputeDXSectionPerAtom(G4double eplusEnergy, 
                                                   >> 214               G4double totalEnergy, 
                                                   >> 215               G4double /*Z*/)
                                                   >> 216 {
                                                   >> 217   // most simple case - complete screening:
                                                   >> 218 
                                                   >> 219   //  dsig/dE+ = 4 * alpha * Z**2 * r0**2 / k
                                                   >> 220   //     * [ (y**2 + (1-y**2) + 2/3*y*(1-y) ) * ( log (183 * Z**-1/3)  + 1/9 * y*(1-y) ]
                                                   >> 221   // y = E+/k
                                                   >> 222   G4double yp=eplusEnergy/totalEnergy;
                                                   >> 223   G4double ym=1.-yp;
                                                   >> 224 
                                                   >> 225   G4double cross = 0.;
                                                   >> 226   if (use_completescreening) 
                                                   >> 227     cross = (yp*yp + ym*ym + 2./3.*ym*yp)*(Fel - fCoulomb) + 1./9.*yp*ym;
                                                   >> 228   else {
                                                   >> 229     G4double delta = 0.25*DeltaMin(totalEnergy)/(yp*ym);
                                                   >> 230     cross = (yp*yp + ym*ym)*(0.25*Phi1(delta) - lnZ/3. - fCoulomb)
                                                   >> 231       + 2./3.*ym*yp*(0.25*Phi2(delta) - lnZ/3. - fCoulomb);
173   }                                               232   }
                                                   >> 233   return cross/totalEnergy;
                                                   >> 234 
174 }                                                 235 }
                                                   >> 236 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
175                                                   237 
176 void G4PairProductionRelModel::InitialiseLocal << 238 G4double 
177                                                << 239 G4PairProductionRelModel::ComputeRelDXSectionPerAtom(G4double eplusEnergy, 
178 {                                              << 240                  G4double totalEnergy, 
179   SetElementSelectors(masterModel->GetElementS << 241                  G4double /*Z*/)
180 }                                              << 242 {
181                                                << 243   // most simple case - complete screening:
182 G4double G4PairProductionRelModel::ComputeXSec << 244 
183                                                << 245   //  dsig/dE+ = 4 * alpha * Z**2 * r0**2 / k
184 {                                              << 246   //     * [ (y**2 + (1-y**2) + 2/3*y*(1-y) ) * ( log (183 * Z**-1/3)  + 1/9 * y*(1-y) ]
185   G4double xSection = 0.0;                     << 247   // y = E+/k
186   // check if LPM suppression needs to be used << 248   G4double yp=eplusEnergy/totalEnergy;
187   const G4bool   isLPM  = (fIsUseLPMCorrection << 249   G4double ym=1.-yp;
188   // determine the kinematical limits (taken i << 250 
189   // the way in which the Coulomb correction i << 251   CalcLPMFunctions(totalEnergy,eplusEnergy); // gamma
190   const G4int    iz     = std::min(gMaxZet, G4 << 252 
191   const G4double eps0   = CLHEP::electron_mass << 253   G4double cross = 0.;
192   // Coulomb correction is always included in  << 254   if (use_completescreening) 
193   // that this DCS is only used to get the int << 255     cross = xiLPM*(2./3.*phiLPM*(yp*yp + ym*ym) + gLPM)*(Fel - fCoulomb);
194   const G4double dmax   = gElementData[iz]->fD << 256   else {
195   const G4double dmin   = 4.*eps0*gElementData << 257     G4double delta = 0.25*DeltaMin(totalEnergy)/(yp*ym);
196   const G4double eps1   = 0.5 - 0.5*std::sqrt( << 258     cross = (1./3.*gLPM + 2./3.*phiLPM)*(yp*yp + ym*ym)
197   const G4double epsMin = std::max(eps0, eps1) << 259                              *(0.25*Phi1(delta) - lnZ/3. - fCoulomb) 
198   const G4double epsMax = 0.5; // DCS is symme << 260            + 2./3.*gLPM*ym*yp*(0.25*Phi2(delta) - lnZ/3. - fCoulomb);
199   // let Et be the total energy transferred to << 261     cross *= xiLPM;
200   // the [Et-min, Et-max] interval will be div << 
201   // with width of dInterv = (Et-max - Et-min) << 
202   // be done in each sub-inteval using the xi  << 
203   // that is in [0,1]. The 8-point GL q. is us << 
204   const G4int    numSub = 2;                   << 
205   const G4double dInterv= (epsMax - epsMin)*ga << 
206   G4double minEti       = epsMin*gammaEnergy;  << 
207   for (G4int i = 0; i < numSub; ++i) {         << 
208     for (G4int ngl = 0; ngl < 8; ++ngl) {      << 
209       const G4double Et = (minEti + gXGL[ngl]* << 
210       const G4double xs = isLPM ? ComputeRelDX << 
211                                 : ComputeDXSec << 
212       xSection += gWGL[ngl]*xs;                << 
213     }                                          << 
214     // update minimum Et of the sub-inteval    << 
215     minEti += dInterv;                         << 
216   }                                               262   }
217   // apply corrections of variable transformat << 263   return cross/totalEnergy;
218   xSection = std::max(2.*xSection*dInterv, 0.) << 264 
219   return xSection;                             << 
220 }                                              << 
221                                                << 
222 // DCS WITHOUT LPM SUPPRESSION                 << 
223 // Computes DCS value for a given target eleme << 
224 // total energy transferred to one of the e-/e << 
225 // The constant factor 4 \alpha r_0^2 Z (Z +\e << 
226 // the returned value will be differential in  << 
227 // the eps=Et/Eg. The computed part of the DCS << 
228 // NORMAL CASE: DEFAULT STTING (i.e. fIsUseCom << 
229 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = (eps^2+ << 
230 // + 2*eps(1-eps)*[phi2(d)/4-ln(Z)/3-fc]/3 whe << 
231 // screening variable d=d(eps)=136Z^(-1/3)eps0 << 
232 // COMPLETE SCREENING (when d(eps) approx-equa << 
233 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = (eps^2+ << 
234 // -eps(1-eps)/9 where Lel=phi1(0)/4-ln(Z)/3 i << 
235 // logarithm, fc is the Coulomb correction and << 
236 // phi1(0)/4-1/6-ln(Z)/3 = Lel-1/6 (due to phi << 
237 G4double G4PairProductionRelModel::ComputeDXSe << 
238                                                << 
239                                                << 
240 {                                              << 
241   G4double xSection = 0.;                      << 
242   const G4int    iz   = std::min(gMaxZet, G4lr << 
243   const G4double eps  = pEnergy/gammaEnergy;   << 
244   const G4double epsm = 1.-eps;                << 
245   const G4double dum  = eps*epsm;              << 
246   if (fIsUseCompleteScreening) {               << 
247     // complete screening:                     << 
248     const G4double Lel   = gElementData[iz]->f << 
249     const G4double fc    = gElementData[iz]->f << 
250     xSection = (eps*eps + epsm*epsm + 2.*dum/3 << 
251   } else {                                     << 
252     // normal case:                            << 
253     const G4double eps0  = CLHEP::electron_mas << 
254     const G4double fc    = gElementData[iz]->f << 
255     const G4double lnZ13 = gElementData[iz]->f << 
256     const G4double delta = gElementData[iz]->f << 
257     G4double phi1, phi2;                       << 
258     ComputePhi12(delta, phi1, phi2);           << 
259     xSection =  (eps*eps + epsm*epsm)*(0.25*ph << 
260                + 2.*dum*(0.25*phi2-lnZ13-fc)/3 << 
261   }                                            << 
262   // non-const. part of the DCS differential i << 
263   // ds/dEt=ds/deps deps/dEt with deps/dEt=1/E << 
264   return std::max(xSection, 0.0)/gammaEnergy;  << 
265 }                                              << 
266                                                << 
267 // DCS WITH POSSIBLE LPM SUPPRESSION           << 
268 // Computes DCS value for a given target eleme << 
269 // total energy transferred to one of the e-/e << 
270 // For a given Z, the LPM suppression will dep << 
271 // LMP-Energy. This will determine the suppres << 
272 // pression functions xi(s), fi(s) and G(s).   << 
273 // The constant factor 4 \alpha r_0^2 Z (Z +\e << 
274 // the returned value will be differential in  << 
275 // the eps=Et/Eg. The computed part of the DCS << 
276 // NORMAL CASE: DEFAULT STTING (i.e. fIsUseCom << 
277 // ds/deps(Et,Eg,Z)=ds/deps(eps,Z) = xi(s)*{ ( << 
278 // *[phi1(d)/4-ln(Z)/3-fc] + 2*eps(1-eps)*G(s) << 
279 // the universal (in the TF model) screening v << 
280 // /[eps*(1-eps)] with eps0=mc^2/Eg.           << 
281 // COMPLETE SCREENING (when d(eps) approx-equa << 
282 // ds/deps(Et,Eg,Z) = ds/deps(eps,Z) = xi(s)*{ << 
283 // *(1-eps)/3)*2fi(s)/3 + G(s)/3] - eps(1-eps) << 
284 // Note, that when the LPM suppression is abse << 
285 // the normal and the complete screening DCS g << 
286 G4double G4PairProductionRelModel::ComputeRelD << 
287                                                << 
288                                                << 
289 {                                              << 
290   G4double xSection = 0.;                      << 
291   const G4int    iz   = std::min(gMaxZet, G4lr << 
292   const G4double eps  = pEnergy/gammaEnergy;   << 
293   const G4double epsm = 1.-eps;                << 
294   const G4double dum  = eps*epsm;              << 
295   // evaluate LPM suppression functions        << 
296   G4double fXiS, fGS, fPhiS;                   << 
297   ComputeLPMfunctions(fXiS, fGS, fPhiS, eps, g << 
298   if (fIsUseCompleteScreening) {               << 
299     // complete screening:                     << 
300     const G4double Lel   = gElementData[iz]->f << 
301     const G4double fc    = gElementData[iz]->f << 
302     xSection = (Lel-fc)*((eps*eps+epsm*epsm)*2 << 
303   } else {                                     << 
304     // normal case:                            << 
305     const G4double eps0  = CLHEP::electron_mas << 
306     const G4double fc    = gElementData[iz]->f << 
307     const G4double lnZ13 = gElementData[iz]->f << 
308     const G4double delta = gElementData[iz]->f << 
309     G4double phi1, phi2;                       << 
310     ComputePhi12(delta, phi1, phi2);           << 
311     xSection =  (eps*eps + epsm*epsm)*(2.*fPhi << 
312                + 2.*dum*fGS*(0.25*phi2-lnZ13-f << 
313   }                                            << 
314   // non-const. part of the DCS differential i << 
315   // ds/dEt=ds/deps deps/dEt with deps/dEt=1/E << 
316   return std::max(fXiS*xSection, 0.0)/gammaEne << 
317 }                                                 265 }
318                                                   266 
319 G4double                                       << 267 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
320 G4PairProductionRelModel::ComputeCrossSectionP << 268 
321       G4double gammaEnergy, G4double Z, G4doub << 269 void  G4PairProductionRelModel::CalcLPMFunctions(G4double k, G4double eplus)
322 {                                                 270 {
323   G4double crossSection = 0.0 ;                << 271   // *** calculate lpm variable s & sprime ***
324   // check kinematical limit                   << 272   // Klein eqs. (78) & (79)
325   if ( gammaEnergy <= 2.0*electron_mass_c2 ) { << 273   G4double sprime = sqrt(0.125*k*lpmEnergy/(eplus*(k-eplus)));
326   // compute the atomic cross section either b << 274 
327   // or by numerically integrationg the DCS (w << 275   G4double s1 = preS1*z23;
328   if ( gammaEnergy < fParametrizedXSectionThre << 276   G4double logS1 = 2./3.*lnZ-2.*facFel;
329     // using the parametrized cross sections ( << 277   G4double logTS1 = logTwo+logS1;
330     crossSection = ComputeParametrizedXSection << 278 
331   } else {                                     << 279   xiLPM = 2.;
332     // by numerical integration of the DCS:    << 280 
333     // Computes the cross section with or with << 281   if (sprime>1) 
334     // settings (by default with if the gamma  << 282     xiLPM = 1.;
335     // and using or not using complete sreenin << 283   else if (sprime>sqrt(2.)*s1) {
336     // Only the dependent part is computed in  << 284     G4double h  = log(sprime)/logTS1;
337     // i.e. the result must be multiplied here << 285     xiLPM = 1+h-0.08*(1-h)*(1-sqr(1-h))/logTS1;
338     crossSection = ComputeXSectionPerAtom(gamm << 286   }
339     // apply the constant factors:             << 287 
340     // - eta(Z) is a correction to account int << 288   G4double s = sprime/sqrt(xiLPM); 
341     // - gXSecFactor = 4 \alpha r_0^2          << 289 //   G4cout<<"k="<<k<<" y="<<eplus/k<<G4endl;
342     const G4int iz     = std::min(gMaxZet, G4l << 290 //   G4cout<<"s="<<s<<G4endl;
343     const G4double eta = gElementData[iz]->fEt << 291   
344     crossSection      *= gXSecFactor*Z*(Z+eta) << 292   // *** calculate supression functions phi and G ***
                                                   >> 293   // Klein eqs. (77)
                                                   >> 294   G4double s2=s*s;
                                                   >> 295   G4double s3=s*s2;
                                                   >> 296   G4double s4=s2*s2;
                                                   >> 297 
                                                   >> 298   if (s<0.1) {
                                                   >> 299     // high suppression limit
                                                   >> 300     phiLPM = 6.*s - 18.84955592153876*s2 + 39.47841760435743*s3 
                                                   >> 301       - 57.69873135166053*s4;
                                                   >> 302     gLPM = 37.69911184307752*s2 - 236.8705056261446*s3 + 807.7822389*s4;
                                                   >> 303   }
                                                   >> 304   else if (s<1.9516) {
                                                   >> 305     // intermediate suppression
                                                   >> 306     // using eq.77 approxim. valid s<2.      
                                                   >> 307     phiLPM = 1.-exp(-6.*s*(1.+(3.-pi)*s)
                                                   >> 308     +s3/(0.623+0.795*s+0.658*s2));
                                                   >> 309     if (s<0.415827397755) {
                                                   >> 310       // using eq.77 approxim. valid 0.07<s<2
                                                   >> 311       G4double psiLPM = 1-exp(-4*s-8*s2/(1+3.936*s+4.97*s2-0.05*s3+7.50*s4));
                                                   >> 312       gLPM = 3*psiLPM-2*phiLPM;
                                                   >> 313     }
                                                   >> 314     else {
                                                   >> 315       // using alternative parametrisiation
                                                   >> 316       G4double pre = -0.16072300849123999 + s*3.7550300067531581 + s2*-1.7981383069010097 
                                                   >> 317   + s3*0.67282686077812381 + s4*-0.1207722909879257;
                                                   >> 318       gLPM = tanh(pre);
                                                   >> 319     }
345   }                                               320   }
346   // final protection                          << 321   else {
347   return std::max(crossSection, 0.);           << 322     // low suppression limit valid s>2.
                                                   >> 323     phiLPM = 1. - 0.0119048/s4;
                                                   >> 324     gLPM = 1. - 0.0230655/s4;
                                                   >> 325   }
                                                   >> 326 
                                                   >> 327   // *** make sure suppression is smaller than 1 ***
                                                   >> 328   // *** caused by Migdal approximation in xi    ***
                                                   >> 329   if (xiLPM*phiLPM>1. || s>0.57)  xiLPM=1./phiLPM;
348 }                                                 330 }
349                                                   331 
350 void G4PairProductionRelModel::SetupForMateria << 332 
351                                                << 333 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
                                                   >> 334 
                                                   >> 335 G4double 
                                                   >> 336 G4PairProductionRelModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
                                                   >> 337                  G4double gammaEnergy, G4double Z,
                                                   >> 338                  G4double, G4double, G4double)
352 {                                                 339 {
353   fLPMEnergy = mat->GetRadlen()*gLPMconstant;  << 340   //  static const G4double gammaEnergyLimit = 1.5*MeV;
                                                   >> 341   G4double crossSection = 0.0 ;
                                                   >> 342   if ( Z < 1. ) return crossSection;
                                                   >> 343   if ( gammaEnergy <= 2.0*electron_mass_c2 ) return crossSection;
                                                   >> 344 
                                                   >> 345   SetCurrentElement(Z);
                                                   >> 346   // choose calculator according to parameters and switches
                                                   >> 347   // in the moment only one calculator:
                                                   >> 348   crossSection=ComputeXSectionPerAtom(gammaEnergy,Z);
                                                   >> 349 
                                                   >> 350   G4double xi = Finel/(Fel - fCoulomb); // inelastic contribution
                                                   >> 351   crossSection*=4.*Z*(Z+xi)*fine_structure_const*classic_electr_radius*classic_electr_radius;
                                                   >> 352 
                                                   >> 353   return crossSection;
354 }                                                 354 }
355                                                   355 
356 void                                           << 356 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
                                                   >> 357 
                                                   >> 358 void 
357 G4PairProductionRelModel::SampleSecondaries(st    359 G4PairProductionRelModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
358                                             co << 360               const G4MaterialCutsCouple* couple,
359                                             co << 361               const G4DynamicParticle* aDynamicGamma,
360                                             G4 << 362               G4double,
361                                             G4 << 363               G4double)
362 // The secondaries e+e- energies are sampled u    364 // The secondaries e+e- energies are sampled using the Bethe - Heitler
363 // cross sections with Coulomb correction.        365 // cross sections with Coulomb correction.
364 // A modified version of the random number tec    366 // A modified version of the random number techniques of Butcher & Messel
365 // is used (Nuc Phys 20(1960),15).                367 // is used (Nuc Phys 20(1960),15).
366 //                                                368 //
367 // GEANT4 internal units.                         369 // GEANT4 internal units.
368 //                                                370 //
369 // Note 1 : Effects due to the breakdown of th    371 // Note 1 : Effects due to the breakdown of the Born approximation at
370 //          low energy are ignored.               372 //          low energy are ignored.
371 // Note 2 : The differential cross section imp << 373 // Note 2 : The differential cross section implicitly takes account of 
372 //          pair creation in both nuclear and     374 //          pair creation in both nuclear and atomic electron fields.
373 //          However triplet prodution is not g    375 //          However triplet prodution is not generated.
374 {                                                 376 {
375   const G4Material* mat         = couple->GetM << 377   const G4Material* aMaterial = couple->GetMaterial();
376   const G4double    gammaEnergy = aDynamicGamm << 378 
377   const G4double    eps0        = CLHEP::elect << 379   G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
378   //                                           << 380   G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection();
379   // check kinematical limit: gamma energy(Eg) << 381 
380   // (but the model should be used at higher e << 382   G4double epsil ;
381   if (eps0 > 0.5) { return; }                  << 383   G4double epsil0 = electron_mass_c2/GammaEnergy ;
382   //                                           << 384   if(epsil0 > 1.0) return;
383   // select target atom of the material        << 385 
384   const G4Element* anElement = SelectTargetAto << 386   // do it fast if GammaEnergy < 2. MeV
385                                          aDyna << 387   static const G4double Egsmall=2.*MeV;
386   CLHEP::HepRandomEngine* rndmEngine = G4Rando << 388 
387   //                                           << 389   // select randomly one element constituing the material
388   // 'eps' is the total energy transferred to  << 390   const G4Element* anElement = SelectRandomAtom(aMaterial, theGamma, GammaEnergy);
389   // gamma energy units Eg. Since the correspo << 391 
390   // the kinematical limits for eps0=mc^2/Eg < << 392   if (GammaEnergy < Egsmall) {
391   // 1. 'eps' is sampled uniformly on the [eps << 393 
392   // 2. otherwise, on the [eps_min, 0.5] inter << 394     epsil = epsil0 + (0.5-epsil0)*G4UniformRand();
393   G4double eps;                                << 395 
394   // case 1.                                   << 
395   static const G4double Egsmall = 2.*CLHEP::Me << 
396   if (gammaEnergy < Egsmall) {                 << 
397     eps = eps0 + (0.5-eps0)*rndmEngine->flat() << 
398   } else {                                        396   } else {
399   // case 2.                                   << 397     // now comes the case with GammaEnergy >= 2. MeV
400     // get the Coulomb factor for the target e << 398 
401     // F(Z) = 8*ln(Z)/3           if Eg <= 50  << 399     // Extract Coulomb factor for this Element
402     // F(Z) = 8*ln(Z)/3 + 8*fc(Z) if Eg  > 50  << 400     G4double FZ = 8.*(anElement->GetIonisation()->GetlogZ3());
                                                   >> 401     if (GammaEnergy > 50.*MeV) FZ += 8.*(anElement->GetfCoulomb());
                                                   >> 402 
                                                   >> 403     // limits of the screening variable
                                                   >> 404     G4double screenfac = 136.*epsil0/(anElement->GetIonisation()->GetZ3());
                                                   >> 405     G4double screenmax = exp ((42.24 - FZ)/8.368) - 0.952 ;
                                                   >> 406     G4double screenmin = min(4.*screenfac,screenmax);
                                                   >> 407 
                                                   >> 408     // limits of the energy sampling
                                                   >> 409     G4double epsil1 = 0.5 - 0.5*sqrt(1. - screenmin/screenmax) ;
                                                   >> 410     G4double epsilmin = max(epsil0,epsil1) , epsilrange = 0.5 - epsilmin;
                                                   >> 411 
403     //                                            412     //
404     // The screening variable 'delta(eps)' = 1 << 413     // sample the energy rate of the created electron (or positron)
405     // Due to the Coulomb correction, the DCS  << 
406     // kinematicaly allowed eps > eps0 values. << 
407     // range with negative DCS, the minimum ep << 
408     // max[eps0, epsp] with epsp is the soluti << 
409     // with SF being the screening function (S << 
410     // The solution is epsp = 0.5 - 0.5*sqrt[  << 
411     // with deltap = Exp[(42.038-F(Z))/8.29]-0 << 
412     // - when eps=eps_max = 0.5            =>  << 
413     // - epsp = 0.5 - 0.5*sqrt[ 1 - delta_min/ << 
414     // - and eps_min = max[eps0, epsp]         << 
415     const G4int    iZet        = std::min(gMax << 
416     const G4double deltaFactor = gElementData[ << 
417     const G4double deltaMin    = 4.*deltaFacto << 
418     G4double       deltaMax    = gElementData[ << 
419     G4double       FZ          = 8.*gElementDa << 
420     if ( gammaEnergy > fCoulombCorrectionThres << 
421       FZ      += 8.*gElementData[iZet]->fCoulo << 
422       deltaMax = gElementData[iZet]->fDeltaMax << 
423     }                                          << 
424     // compute the limits of eps               << 
425     const G4double epsp        = 0.5 - 0.5*std << 
426     const G4double epsMin      = std::max(eps0 << 
427     const G4double epsRange    = 0.5 - epsMin; << 
428     //                                            414     //
429     // sample the energy rate (eps) of the cre << 415     //G4double epsil, screenvar, greject ;
430     G4double F10, F20;                         << 416     G4double  screenvar, greject ;
431     ScreenFunction12(deltaMin, F10, F20);      << 417 
432     F10 -= FZ;                                 << 418     G4double F10 = ScreenFunction1(screenmin) - FZ;
433     F20 -= FZ;                                 << 419     G4double F20 = ScreenFunction2(screenmin) - FZ;
434     const G4double NormF1   = std::max(F10 * e << 420     G4double NormF1 = max(F10*epsilrange*epsilrange,0.); 
435     const G4double NormF2   = std::max(1.5 * F << 421     G4double NormF2 = max(1.5*F20,0.);
436     const G4double NormCond = NormF1/(NormF1 + << 422 
437     // check if LPM correction is active       << 
438     const G4bool isLPM = (fIsUseLPMCorrection  << 
439     fLPMEnergy = mat->GetRadlen()*gLPMconstant << 
440     // we will need 3 uniform random number fo << 
441     G4double rndmv[3];                         << 
442     G4double greject = 0.;                     << 
443     do {                                          423     do {
444       rndmEngine->flatArray(3, rndmv);         << 424       if ( NormF1/(NormF1+NormF2) > G4UniformRand() ) {
445       if (NormCond > rndmv[0]) {               << 425   epsil = 0.5 - epsilrange*pow(G4UniformRand(), 0.333333);
446         eps = 0.5 - epsRange * fG4Calc->A13(rn << 426   screenvar = screenfac/(epsil*(1-epsil));
447         const G4double delta = deltaFactor/(ep << 427   if (fLPMflag && GammaEnergy>100.*GeV) {
448         if (isLPM) {                           << 428     CalcLPMFunctions(GammaEnergy,GammaEnergy*epsil);
449           G4double lpmXiS, lpmGS, lpmPhiS, phi << 429     greject = xiLPM*((gLPM+2.*phiLPM)*Phi1(screenvar) - gLPM*Phi2(screenvar) - phiLPM*FZ)/F10;
450           ComputePhi12(delta, phi1, phi2);     << 430   }
451           ComputeLPMfunctions(lpmXiS, lpmGS, l << 431   else {
452           greject = lpmXiS*((2.*lpmPhiS+lpmGS) << 432     greject = (ScreenFunction1(screenvar) - FZ)/F10;
453         } else {                               << 433   }
454           greject = (ScreenFunction1(delta)-FZ << 434               
455         }                                      << 435       } else { 
456       } else {                                 << 436   epsil = epsilmin + epsilrange*G4UniformRand();
457         eps = epsMin + epsRange*rndmv[1];      << 437   screenvar = screenfac/(epsil*(1-epsil));
458         const G4double delta = deltaFactor/(ep << 438   if (fLPMflag && GammaEnergy>100.*GeV) {
459         if (isLPM) {                           << 439     CalcLPMFunctions(GammaEnergy,GammaEnergy*epsil);
460           G4double lpmXiS, lpmGS, lpmPhiS, phi << 440     greject = xiLPM*((0.5*gLPM+phiLPM)*Phi1(screenvar) + 0.5*gLPM*Phi2(screenvar) - 0.5*(gLPM+phiLPM)*FZ)/F20;
461           ComputePhi12(delta, phi1, phi2);     << 441   }
462           ComputeLPMfunctions(lpmXiS, lpmGS, l << 442   else {
463           greject = lpmXiS*( (lpmPhiS+0.5*lpmG << 443     greject = (ScreenFunction2(screenvar) - FZ)/F20;
464                              -0.5*(lpmGS+lpmPh << 444   }
465         } else {                               << 
466           greject = (ScreenFunction2(delta)-FZ << 
467         }                                      << 
468       }                                           445       }
469       // Loop checking, 03-Aug-2015, Vladimir  << 446 
470     } while (greject < rndmv[2]);              << 447     } while( greject < G4UniformRand() );
471     //  end of eps sampling                    << 448 
472   }                                            << 449   }   //  end of epsil sampling
                                                   >> 450    
473   //                                              451   //
474   // select charges randomly                   << 452   // fixe charges randomly
475   G4double eTotEnergy, pTotEnergy;             << 453   //
476   if (rndmEngine->flat() > 0.5) {              << 454 
477     eTotEnergy = (1.-eps)*gammaEnergy;         << 455   G4double ElectTotEnergy, PositTotEnergy;
478     pTotEnergy = eps*gammaEnergy;              << 456   if (G4UniformRand() > 0.5) {
                                                   >> 457 
                                                   >> 458     ElectTotEnergy = (1.-epsil)*GammaEnergy;
                                                   >> 459     PositTotEnergy = epsil*GammaEnergy;
                                                   >> 460      
479   } else {                                        461   } else {
480     pTotEnergy = (1.-eps)*gammaEnergy;         << 462     
481     eTotEnergy = eps*gammaEnergy;              << 463     PositTotEnergy = (1.-epsil)*GammaEnergy;
                                                   >> 464     ElectTotEnergy = epsil*GammaEnergy;
482   }                                               465   }
                                                   >> 466 
483   //                                              467   //
484   // sample pair kinematics                    << 468   // scattered electron (positron) angles. ( Z - axis along the parent photon)
485   //                                           << 
486   const G4double eKinEnergy = std::max(0.,eTot << 
487   const G4double pKinEnergy = std::max(0.,pTot << 
488   //                                              469   //
489   G4ThreeVector eDirection, pDirection;        << 470   //  universal distribution suggested by L. Urban 
                                                   >> 471   // (Geant3 manual (1993) Phys211),
                                                   >> 472   //  derived from Tsai distribution (Rev Mod Phys 49,421(1977))
                                                   >> 473 
                                                   >> 474   G4double u;
                                                   >> 475   const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ;
                                                   >> 476 
                                                   >> 477   if (9./(9.+d) >G4UniformRand()) u= - log(G4UniformRand()*G4UniformRand())/a1;
                                                   >> 478   else                            u= - log(G4UniformRand()*G4UniformRand())/a2;
                                                   >> 479 
                                                   >> 480   G4double TetEl = u*electron_mass_c2/ElectTotEnergy;
                                                   >> 481   G4double TetPo = u*electron_mass_c2/PositTotEnergy;
                                                   >> 482   G4double Phi  = twopi * G4UniformRand();
                                                   >> 483   G4double dxEl= sin(TetEl)*cos(Phi),dyEl= sin(TetEl)*sin(Phi),dzEl=cos(TetEl);
                                                   >> 484   G4double dxPo=-sin(TetPo)*cos(Phi),dyPo=-sin(TetPo)*sin(Phi),dzPo=cos(TetPo);
                                                   >> 485    
490   //                                              486   //
491   GetAngularDistribution()->SamplePairDirectio << 487   // kinematic of the created pair
492              eKinEnergy, pKinEnergy, eDirectio << 488   //
493   // create G4DynamicParticle object for the p << 489   // the electron and positron are assumed to have a symetric
494   auto aParticle1 = new G4DynamicParticle(fThe << 490   // angular distribution with respect to the Z axis along the parent photon.
                                                   >> 491 
                                                   >> 492   G4double ElectKineEnergy = max(0.,ElectTotEnergy - electron_mass_c2);
                                                   >> 493 
                                                   >> 494   G4ThreeVector ElectDirection (dxEl, dyEl, dzEl);
                                                   >> 495   ElectDirection.rotateUz(GammaDirection);   
                                                   >> 496 
                                                   >> 497   // create G4DynamicParticle object for the particle1  
                                                   >> 498   G4DynamicParticle* aParticle1= new G4DynamicParticle(
                                                   >> 499          theElectron,ElectDirection,ElectKineEnergy);
                                                   >> 500   
                                                   >> 501   // the e+ is always created (even with Ekine=0) for further annihilation.
                                                   >> 502 
                                                   >> 503   G4double PositKineEnergy = max(0.,PositTotEnergy - electron_mass_c2);
                                                   >> 504 
                                                   >> 505   G4ThreeVector PositDirection (dxPo, dyPo, dzPo);
                                                   >> 506   PositDirection.rotateUz(GammaDirection);   
                                                   >> 507 
                                                   >> 508   // create G4DynamicParticle object for the particle2 
                                                   >> 509   G4DynamicParticle* aParticle2= new G4DynamicParticle(
                                                   >> 510                       thePositron,PositDirection,PositKineEnergy);
495                                                   511 
496   // create G4DynamicParticle object for the p << 
497   auto aParticle2 = new G4DynamicParticle(fThe << 
498   // Fill output vector                           512   // Fill output vector
499   fvect->push_back(aParticle1);                   513   fvect->push_back(aParticle1);
500   fvect->push_back(aParticle2);                   514   fvect->push_back(aParticle2);
                                                   >> 515 
501   // kill incident photon                         516   // kill incident photon
502   fParticleChange->SetProposedKineticEnergy(0.    517   fParticleChange->SetProposedKineticEnergy(0.);
503   fParticleChange->ProposeTrackStatus(fStopAnd << 518   fParticleChange->ProposeTrackStatus(fStopAndKill);   
504 }                                              << 
505                                                << 
506 // should be called only by the master and at  << 
507 void G4PairProductionRelModel::InitialiseEleme << 
508 {                                              << 
509   // create for all elements that are in the d << 
510   auto elemTable = G4Element::GetElementTable( << 
511   for (auto const & elem : *elemTable) {       << 
512     const G4int iz = std::min(gMaxZet, elem->G << 
513     if (nullptr == gElementData[iz]) { // crea << 
514       const G4double logZ13 = elem->GetIonisat << 
515       const G4double Z13    = elem->GetIonisat << 
516       const G4double fc     = elem->GetfCoulom << 
517       const G4double FZLow  = 8.*logZ13;       << 
518       const G4double FZHigh = 8.*(logZ13 + fc) << 
519       G4double       Fel;                      << 
520       G4double       Finel;                    << 
521       if (iz<5) {  // use data from Dirac-Fock << 
522         Fel   = gFelLowZet[iz];                << 
523         Finel = gFinelLowZet[iz];              << 
524       } else {     // use the results of the T << 
525         Fel   = G4Log(184.)  -    logZ13;      << 
526         Finel = G4Log(1194.) - 2.*logZ13;      << 
527       }                                        << 
528       auto elD             = new ElementData() << 
529       elD->fLogZ13         = logZ13;           << 
530       elD->fCoulomb        = fc;               << 
531       elD->fLradEl         = Fel;              << 
532       elD->fDeltaFactor    = 136./Z13;         << 
533       elD->fDeltaMaxLow    = G4Exp((42.038 - F << 
534       elD->fDeltaMaxHigh   = G4Exp((42.038 - F << 
535       elD->fEtaValue       = Finel/(Fel-fc);   << 
536       elD->fLPMVarS1Cond   = std::sqrt(2.)*Z13 << 
537       elD->fLPMILVarS1Cond = 1./G4Log(elD->fLP << 
538       gElementData[iz]   = elD;                << 
539     }                                          << 
540   }                                            << 
541 }                                              << 
542                                                << 
543 // s goes up to 2 with ds = 0.01 be default    << 
544 void G4PairProductionRelModel::InitLPMFunction << 
545   if (!gLPMFuncs.fIsInitialized) {             << 
546     const G4int num = gLPMFuncs.fSLimit*gLPMFu << 
547     gLPMFuncs.fLPMFuncG.resize(num);           << 
548     gLPMFuncs.fLPMFuncPhi.resize(num);         << 
549     for (G4int i=0; i<num; ++i) {              << 
550       const G4double sval = i/gLPMFuncs.fISDel << 
551       ComputeLPMGsPhis(gLPMFuncs.fLPMFuncG[i], << 
552     }                                          << 
553     gLPMFuncs.fIsInitialized = true;           << 
554   }                                            << 
555 }                                              << 
556                                                << 
557 // used only at initialisation time            << 
558 void G4PairProductionRelModel::ComputeLPMGsPhi << 
559   if (varShat < 0.01) {                        << 
560     funcPhiS = 6.0*varShat*(1.0-CLHEP::pi*varS << 
561     funcGS   = 12.0*varShat-2.0*funcPhiS;      << 
562   } else {                                     << 
563     const G4double varShat2 = varShat*varShat; << 
564     const G4double varShat3 = varShat*varShat2 << 
565     const G4double varShat4 = varShat2*varShat << 
566     if (varShat < 0.415827397755) { // Stanev  << 
567       funcPhiS = 1.0-G4Exp( -6.0*varShat*(1.0+ << 
568                            + varShat3/(0.623+0 << 
569       // 1-\exp \left\{-4s-\frac{8s^2}{1+3.936 << 
570       const G4double funcPsiS = 1.0-G4Exp( -4. << 
571                      + 3.936*varShat+4.97*varS << 
572       // G(s) = 3 \psi(s) - 2 \phi(s)          << 
573       funcGS = 3.0*funcPsiS - 2.0*funcPhiS;    << 
574     } else if (varShat < 1.55) {               << 
575       funcPhiS = 1.0-G4Exp( -6.0*varShat*(1.0+ << 
576                            + varShat3/(0.623+0 << 
577       const G4double dum0  = -0.16072300849123 << 
578                              -1.79813830690100 << 
579                              +0.67282686077812 << 
580                              -0.12077229098792 << 
581       funcGS = std::tanh(dum0);                << 
582     } else {                                   << 
583       funcPhiS = 1.0-0.01190476/varShat4;      << 
584       if (varShat < 1.9156) {                  << 
585         const G4double dum0 = -0.1607230084912 << 
586                               -1.7981383069010 << 
587                               +0.6728268607781 << 
588                               -0.1207722909879 << 
589         funcGS = std::tanh(dum0);              << 
590       } else {                                 << 
591         funcGS   = 1.0-0.0230655/varShat4;     << 
592       }                                        << 
593     }                                          << 
594   }                                            << 
595 }                                                 519 }
596                                                   520 
597 // used at run-time to get some pre-computed L << 521 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
598 void G4PairProductionRelModel::GetLPMFunctions << 
599                                                << 
600                                                << 
601   if (sval < gLPMFuncs.fSLimit) {              << 
602     G4double     val = sval*gLPMFuncs.fISDelta << 
603     const G4int ilow = (G4int)val;             << 
604     val    -= ilow;                            << 
605     lpmGs   =  (gLPMFuncs.fLPMFuncG[ilow+1]-gL << 
606              + gLPMFuncs.fLPMFuncG[ilow];      << 
607     lpmPhis =  (gLPMFuncs.fLPMFuncPhi[ilow+1]- << 
608              + gLPMFuncs.fLPMFuncPhi[ilow];    << 
609   } else {                                     << 
610     G4double ss = sval*sval;                   << 
611     ss *= ss;                                  << 
612     lpmPhis = 1.0-0.01190476/ss;               << 
613     lpmGs   = 1.0-0.0230655/ss;                << 
614   }                                            << 
615 }                                              << 
616                                                   522 
617 void G4PairProductionRelModel::ComputeLPMfunct << 
618                  G4double &funcGS, G4double &f << 
619                  const G4double egamma, const  << 
620 {                                              << 
621   //  1. y = E_+/E_{\gamma} with E_+ being the << 
622   //                        to one of the e-/e << 
623   //  s' = \sqrt{ \frac{1}{8} \frac{1}{y(1-y)} << 
624   const G4double varSprime = std::sqrt(0.125*f << 
625   const G4double condition = gElementData[izet << 
626   funcXiS = 2.0;                               << 
627   if (varSprime > 1.0) {                       << 
628     funcXiS = 1.0;                             << 
629   } else if (varSprime > condition) {          << 
630     const G4double dum = gElementData[izet]->f << 
631     const G4double funcHSprime = G4Log(varSpri << 
632     funcXiS =  1.0 + funcHSprime               << 
633              - 0.08*(1.0-funcHSprime)*funcHSpr << 
634   }                                            << 
635   //  2. s=\frac{s'}{\sqrt{\xi(s')}}           << 
636   const G4double varShat = varSprime / std::sq << 
637   GetLPMFunctions(funcGS, funcPhiS, varShat);  << 
638   // MAKE SURE SUPPRESSION IS SMALLER THAN 1:  << 
639   if (funcXiS * funcPhiS > 1. || varShat > 0.5 << 
640     funcXiS = 1. / funcPhiS;                   << 
641   }                                            << 
642 }                                              << 
643                                                   523 
644 // Calculates the microscopic cross section in << 524 void G4PairProductionRelModel::SetupForMaterial(const G4ParticleDefinition*,
645 // G4BetheHeitlerModel and should be used belo << 525             const G4Material* mat, G4double)
646 // from the cross section data above 80-90 GeV << 526 {
647 // Parametrized formula (L. Urban) is used to  << 527   lpmEnergy = mat->GetRadlen()*fLPMconstant;
648 // given numerically in the table of [Hubbell, << 528   //  G4cout<<" lpmEnergy="<<lpmEnergy<<G4endl;
649 // Overbo: "Pair, Triplet, and Total Atomic Cr << 
650 // Coefficients) for 1 MeV‐100 GeV Photons i << 
651 // physical and chemical reference data 9.4 (1 << 
652 //                                             << 
653 // The formula gives a good approximation of t << 
654 // below 1.5 MeV: sigma=sigma(1.5MeV)*(GammaEn << 
655 //                                   *(GammaEn << 
656 G4double                                       << 
657 G4PairProductionRelModel::ComputeParametrizedX << 
658                                                << 
659 {                                              << 
660   G4double xSection = 0.0 ;                    << 
661   // short versions                            << 
662   static const G4double kMC2  = CLHEP::electro << 
663   // zero cross section below the kinematical  << 
664   if (Z < 0.9 || gammaE <= 2.0*kMC2) { return  << 
665   //                                           << 
666   static const G4double gammaEnergyLimit = 1.5 << 
667   // set coefficients a, b c                   << 
668   static const G4double a0 =  8.7842e+2*CLHEP: << 
669   static const G4double a1 = -1.9625e+3*CLHEP: << 
670   static const G4double a2 =  1.2949e+3*CLHEP: << 
671   static const G4double a3 = -2.0028e+2*CLHEP: << 
672   static const G4double a4 =  1.2575e+1*CLHEP: << 
673   static const G4double a5 = -2.8333e-1*CLHEP: << 
674                                                << 
675   static const G4double b0 = -1.0342e+1*CLHEP: << 
676   static const G4double b1 =  1.7692e+1*CLHEP: << 
677   static const G4double b2 = -8.2381   *CLHEP: << 
678   static const G4double b3 =  1.3063   *CLHEP: << 
679   static const G4double b4 = -9.0815e-2*CLHEP: << 
680   static const G4double b5 =  2.3586e-3*CLHEP: << 
681                                                << 
682   static const G4double c0 = -4.5263e+2*CLHEP: << 
683   static const G4double c1 =  1.1161e+3*CLHEP: << 
684   static const G4double c2 = -8.6749e+2*CLHEP: << 
685   static const G4double c3 =  2.1773e+2*CLHEP: << 
686   static const G4double c4 = -2.0467e+1*CLHEP: << 
687   static const G4double c5 =  6.5372e-1*CLHEP: << 
688   // check low energy limit of the approximati << 
689   G4double gammaEnergyOrg = gammaE;            << 
690   if (gammaE < gammaEnergyLimit) { gammaE = ga << 
691   // compute gamma energy variables            << 
692   const G4double x  = G4Log(gammaE/kMC2);      << 
693   const G4double x2 = x *x;                    << 
694   const G4double x3 = x2*x;                    << 
695   const G4double x4 = x3*x;                    << 
696   const G4double x5 = x4*x;                    << 
697   //                                           << 
698   const G4double F1 = a0 + a1*x + a2*x2 + a3*x << 
699   const G4double F2 = b0 + b1*x + b2*x2 + b3*x << 
700   const G4double F3 = c0 + c1*x + c2*x2 + c3*x << 
701   // compute the approximated cross section    << 
702   xSection = (Z + 1.)*(F1*Z + F2*Z*Z + F3);    << 
703   // check if we are below the limit of the ap << 
704   if (gammaEnergyOrg < gammaEnergyLimit) {     << 
705     const G4double dum = (gammaEnergyOrg-2.*kM << 
706     xSection *= dum*dum;                       << 
707   }                                            << 
708   return xSection;                             << 
709 }                                                 529 }
710                                                   530 
711                                                << 531 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
712                                                   532