Geant4 Cross Reference |
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: G4BetheHeitlerModel.cc,v 1.9 2006/06/29 19:52:40 gunter Exp $ >> 27 // GEANT4 tag $Name: geant4-08-01-patch-01 $ 26 // 28 // 27 // ------------------------------------------- 29 // ------------------------------------------------------------------- 28 // 30 // 29 // GEANT4 Class file 31 // GEANT4 Class file 30 // 32 // 31 // 33 // 32 // File name: G4BetheHeitlerModel 34 // File name: G4BetheHeitlerModel 33 // 35 // 34 // Author: Vladimir Ivanchenko on base 36 // Author: Vladimir Ivanchenko on base of Michel Maire code 35 // 37 // 36 // Creation date: 15.03.2005 38 // Creation date: 15.03.2005 37 // 39 // 38 // Modifications by Vladimir Ivanchenko, Miche << 40 // Modifications: >> 41 // 18-04-05 Use G4ParticleChangeForGamma (V.Ivantchenko) >> 42 // 24-06-05 Increase number of bins to 200 (V.Ivantchenko) >> 43 // 16-11-05 replace shootBit() by G4UniformRand() mma >> 44 // 04-12-05 SetProposedKineticEnergy(0.) for the killed photon (mma) 39 // 45 // 40 // Class Description: 46 // Class Description: 41 // 47 // 42 // ------------------------------------------- 48 // ------------------------------------------------------------------- 43 // 49 // >> 50 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 51 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 44 52 45 #include "G4BetheHeitlerModel.hh" 53 #include "G4BetheHeitlerModel.hh" 46 #include "G4PhysicalConstants.hh" << 47 #include "G4SystemOfUnits.hh" << 48 #include "G4Electron.hh" 54 #include "G4Electron.hh" 49 #include "G4Positron.hh" 55 #include "G4Positron.hh" 50 #include "G4Gamma.hh" 56 #include "G4Gamma.hh" 51 #include "Randomize.hh" 57 #include "Randomize.hh" >> 58 #include "G4DataVector.hh" >> 59 #include "G4PhysicsLogVector.hh" 52 #include "G4ParticleChangeForGamma.hh" 60 #include "G4ParticleChangeForGamma.hh" 53 #include "G4Pow.hh" << 54 #include "G4Exp.hh" << 55 #include "G4ModifiedTsai.hh" << 56 #include "G4EmParameters.hh" << 57 #include "G4EmElementXS.hh" << 58 #include "G4AutoLock.hh" << 59 61 60 const G4int G4BetheHeitlerModel::gMaxZet = 120 << 62 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 61 std::vector<G4BetheHeitlerModel::ElementData*> << 62 63 63 namespace << 64 using namespace std; 64 { << 65 G4Mutex theBetheHMutex = G4MUTEX_INITIALIZER << 66 } << 67 65 68 G4BetheHeitlerModel::G4BetheHeitlerModel(const << 66 G4BetheHeitlerModel::G4BetheHeitlerModel(const G4ParticleDefinition*, 69 const << 67 const G4String& nam) 70 : G4VEmModel(nam), << 68 : G4VEmModel(nam), 71 fG4Calc(G4Pow::GetInstance()), fTheGamma(G4G << 69 theCrossSectionTable(0), 72 fTheElectron(G4Electron::Electron()), fThePo << 70 nbins(200) 73 fParticleChange(nullptr) << 74 { 71 { 75 SetAngularDistribution(new G4ModifiedTsai()) << 72 theGamma = G4Gamma::Gamma(); >> 73 thePositron = G4Positron::Positron(); >> 74 theElectron = G4Electron::Electron(); 76 } 75 } 77 76 >> 77 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 78 78 G4BetheHeitlerModel::~G4BetheHeitlerModel() 79 G4BetheHeitlerModel::~G4BetheHeitlerModel() 79 { 80 { 80 if (isFirstInstance) { << 81 if(theCrossSectionTable) { 81 for (auto const & ptr : gElementData) { de << 82 theCrossSectionTable->clearAndDestroy(); 82 gElementData.clear(); << 83 delete theCrossSectionTable; 83 } 84 } 84 delete fXSection; << 85 } 85 } 86 86 87 void G4BetheHeitlerModel::Initialise(const G4P << 87 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 88 const G4D << 88 >> 89 void G4BetheHeitlerModel::Initialise(const G4ParticleDefinition*, >> 90 const G4DataVector&) 89 { 91 { 90 if (!fParticleChange) { fParticleChange = Ge << 92 if(pParticleChange) >> 93 fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange); >> 94 else >> 95 fParticleChange = new G4ParticleChangeForGamma(); >> 96 >> 97 if(theCrossSectionTable) { >> 98 theCrossSectionTable->clearAndDestroy(); >> 99 delete theCrossSectionTable; >> 100 } 91 101 92 if (isFirstInstance || gElementData.empty()) << 102 const G4ElementTable* theElementTable = G4Element::GetElementTable(); 93 G4AutoLock l(&theBetheHMutex); << 103 size_t nvect = G4Element::GetNumberOfElements(); 94 if (gElementData.empty()) { << 104 theCrossSectionTable = new G4PhysicsTable(nvect); 95 isFirstInstance = true; << 105 G4PhysicsLogVector* ptrVector; 96 gElementData.resize(gMaxZet+1, nullptr); << 106 G4double emin = LowEnergyLimit(); 97 << 107 G4double emax = HighEnergyLimit(); 98 // EPICS2017 flag should be checked only << 108 G4double e, value; 99 useEPICS2017 = G4EmParameters::Instance( << 109 100 if (useEPICS2017) { << 110 for(size_t j=0; j<nvect ; j++) { 101 fXSection = new G4EmElementXS(1, 100, "convE << 111 102 } << 112 ptrVector = new G4PhysicsLogVector(emin, emax, nbins); >> 113 G4double Z = (*theElementTable)[j]->GetZ(); >> 114 G4int iz = G4int(Z); >> 115 indexZ[iz] = j; >> 116 >> 117 for(G4int i=0; i<nbins; i++) { >> 118 e = ptrVector->GetLowEdgeEnergy( i ) ; >> 119 value = ComputeCrossSectionPerAtom(theGamma, e, Z); >> 120 ptrVector->PutValue( i, value ); 103 } 121 } 104 // static data should be initialised only << 122 105 InitialiseElementData(); << 123 theCrossSectionTable->insert(ptrVector); 106 l.unlock(); << 107 } << 108 // element selectors should be initialised i << 109 if(IsMaster()) { << 110 InitialiseElementSelectors(p, cuts); << 111 } 124 } 112 } 125 } 113 126 114 void G4BetheHeitlerModel::InitialiseLocal(cons << 127 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 115 G4VE << 116 { << 117 SetElementSelectors(masterModel->GetElementS << 118 } << 119 128 >> 129 G4double G4BetheHeitlerModel::ComputeCrossSectionPerAtom( >> 130 const G4ParticleDefinition*, >> 131 G4double GammaEnergy, G4double Z, >> 132 G4double, G4double, G4double) 120 // Calculates the microscopic cross section in 133 // Calculates the microscopic cross section in GEANT4 internal units. 121 // A parametrized formula from L. Urban is use 134 // A parametrized formula from L. Urban is used to estimate 122 // the total cross section. 135 // the total cross section. 123 // It gives a good description of the data fro 136 // It gives a good description of the data from 1.5 MeV to 100 GeV. 124 // below 1.5 MeV: sigma=sigma(1.5MeV)*(GammaEn 137 // below 1.5 MeV: sigma=sigma(1.5MeV)*(GammaEnergy-2electronmass) 125 // *(GammaEn 138 // *(GammaEnergy-2electronmass) 126 G4double << 127 G4BetheHeitlerModel::ComputeCrossSectionPerAto << 128 << 129 << 130 { 139 { 131 G4double xSection = 0.0 ; << 140 static const G4double GammaEnergyLimit = 1.5*MeV; 132 // short versions << 141 G4double CrossSection = 0.0 ; 133 static const G4double kMC2 = CLHEP::electro << 142 if ( Z < 1. ) return CrossSection; 134 // zero cross section below the kinematical << 143 if ( GammaEnergy <= 2.0*electron_mass_c2 ) return CrossSection; 135 if (Z < 0.9 || gammaEnergy <= 2.0*kMC2) { re << 136 << 137 G4int iZ = G4lrint(Z); << 138 if (useEPICS2017 && iZ < 101) { << 139 return fXSection->GetXS(iZ, gammaEnergy); << 140 } << 141 144 142 // << 145 static const G4double 143 static const G4double gammaEnergyLimit = 1.5 << 146 a0= 8.7842e+2*microbarn, a1=-1.9625e+3*microbarn, a2= 1.2949e+3*microbarn, 144 // set coefficients a, b c << 147 a3=-2.0028e+2*microbarn, a4= 1.2575e+1*microbarn, a5=-2.8333e-1*microbarn; 145 static const G4double a0 = 8.7842e+2*CLHEP: << 148 146 static const G4double a1 = -1.9625e+3*CLHEP: << 149 static const G4double 147 static const G4double a2 = 1.2949e+3*CLHEP: << 150 b0=-1.0342e+1*microbarn, b1= 1.7692e+1*microbarn, b2=-8.2381 *microbarn, 148 static const G4double a3 = -2.0028e+2*CLHEP: << 151 b3= 1.3063 *microbarn, b4=-9.0815e-2*microbarn, b5= 2.3586e-3*microbarn; 149 static const G4double a4 = 1.2575e+1*CLHEP: << 152 150 static const G4double a5 = -2.8333e-1*CLHEP: << 153 static const G4double 151 << 154 c0=-4.5263e+2*microbarn, c1= 1.1161e+3*microbarn, c2=-8.6749e+2*microbarn, 152 static const G4double b0 = -1.0342e+1*CLHEP: << 155 c3= 2.1773e+2*microbarn, c4=-2.0467e+1*microbarn, c5= 6.5372e-1*microbarn; 153 static const G4double b1 = 1.7692e+1*CLHEP: << 156 154 static const G4double b2 = -8.2381 *CLHEP: << 157 G4double GammaEnergySave = GammaEnergy; 155 static const G4double b3 = 1.3063 *CLHEP: << 158 if (GammaEnergy < GammaEnergyLimit) GammaEnergy = GammaEnergyLimit ; 156 static const G4double b4 = -9.0815e-2*CLHEP: << 159 157 static const G4double b5 = 2.3586e-3*CLHEP: << 160 G4double X=log(GammaEnergy/electron_mass_c2), X2=X*X, X3=X2*X, X4=X3*X, X5=X4*X; 158 << 161 159 static const G4double c0 = -4.5263e+2*CLHEP: << 162 G4double F1 = a0 + a1*X + a2*X2 + a3*X3 + a4*X4 + a5*X5, 160 static const G4double c1 = 1.1161e+3*CLHEP: << 163 F2 = b0 + b1*X + b2*X2 + b3*X3 + b4*X4 + b5*X5, 161 static const G4double c2 = -8.6749e+2*CLHEP: << 164 F3 = c0 + c1*X + c2*X2 + c3*X3 + c4*X4 + c5*X5; 162 static const G4double c3 = 2.1773e+2*CLHEP: << 165 163 static const G4double c4 = -2.0467e+1*CLHEP: << 166 CrossSection = (Z + 1.)*(F1*Z + F2*Z*Z + F3); 164 static const G4double c5 = 6.5372e-1*CLHEP: << 167 165 // check low energy limit of the approximati << 168 if (GammaEnergySave < GammaEnergyLimit) { 166 G4double gammaEnergyOrg = gammaEnergy; << 169 167 if (gammaEnergy < gammaEnergyLimit) { gammaE << 170 X = (GammaEnergySave - 2.*electron_mass_c2) 168 // compute gamma energy variables << 171 / (GammaEnergyLimit - 2.*electron_mass_c2); 169 const G4double x = G4Log(gammaEnergy/kMC2); << 172 CrossSection *= X*X; 170 const G4double x2 = x *x; << 171 const G4double x3 = x2*x; << 172 const G4double x4 = x3*x; << 173 const G4double x5 = x4*x; << 174 // << 175 const G4double F1 = a0 + a1*x + a2*x2 + a3*x << 176 const G4double F2 = b0 + b1*x + b2*x2 + b3*x << 177 const G4double F3 = c0 + c1*x + c2*x2 + c3*x << 178 // compute the approximated cross section << 179 xSection = (Z + 1.)*(F1*Z + F2*Z*Z + F3); << 180 // check if we are below the limit of the ap << 181 if (gammaEnergyOrg < gammaEnergyLimit) { << 182 const G4double dum = (gammaEnergyOrg-2.*kM << 183 xSection *= dum*dum; << 184 } 173 } 185 // make sure that the cross section is never << 174 186 xSection = std::max(xSection, 0.); << 175 if (CrossSection < 0.) CrossSection = 0.; 187 return xSection; << 176 return CrossSection; 188 } 177 } 189 178 >> 179 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 180 >> 181 std::vector<G4DynamicParticle*>* G4BetheHeitlerModel::SampleSecondaries( >> 182 const G4MaterialCutsCouple* couple, >> 183 const G4DynamicParticle* aDynamicGamma, >> 184 G4double, >> 185 G4double) 190 // The secondaries e+e- energies are sampled u 186 // The secondaries e+e- energies are sampled using the Bethe - Heitler 191 // cross sections with Coulomb correction. 187 // cross sections with Coulomb correction. 192 // A modified version of the random number tec 188 // A modified version of the random number techniques of Butcher & Messel 193 // is used (Nuc Phys 20(1960),15). 189 // is used (Nuc Phys 20(1960),15). 194 // 190 // 195 // GEANT4 internal units. 191 // GEANT4 internal units. 196 // 192 // 197 // Note 1 : Effects due to the breakdown of th 193 // Note 1 : Effects due to the breakdown of the Born approximation at 198 // low energy are ignored. 194 // low energy are ignored. 199 // Note 2 : The differential cross section imp 195 // Note 2 : The differential cross section implicitly takes account of 200 // pair creation in both nuclear and 196 // pair creation in both nuclear and atomic electron fields. 201 // However triplet prodution is not g 197 // However triplet prodution is not generated. 202 void G4BetheHeitlerModel::SampleSecondaries(st << 203 co << 204 co << 205 G4 << 206 { 198 { 207 // set some constant values << 199 const G4Material* aMaterial = couple->GetMaterial(); 208 const G4double gammaEnergy = aDynamicGamm << 200 209 const G4double eps0 = CLHEP::elect << 201 G4double GammaEnergy = aDynamicGamma->GetKineticEnergy(); 210 // << 202 G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection(); 211 // check kinematical limit: gamma energy(Eg) << 203 212 if (eps0 > 0.5) { return; } << 204 G4double epsil ; 213 // << 205 G4double epsil0 = electron_mass_c2/GammaEnergy ; 214 // select target element of the material (pr << 206 if(epsil0 > 1.0) return 0; 215 const G4Element* anElement = SelectTargetAto << 207 216 aDyn << 208 // do it fast if GammaEnergy < 2. MeV 217 << 209 static const G4double Egsmall=2.*MeV; 218 // << 210 219 // get the random engine << 211 if (GammaEnergy < Egsmall) { 220 CLHEP::HepRandomEngine* rndmEngine = G4Rando << 212 221 // << 213 epsil = epsil0 + (0.5-epsil0)*G4UniformRand(); 222 // 'eps' is the total energy transferred to << 214 223 // gamma energy units Eg. Since the correspo << 224 // the kinematical limits for eps0=mc^2/Eg < << 225 // 1. 'eps' is sampled uniformly on the [eps << 226 // 2. otherwise, on the [eps_min, 0.5] inter << 227 G4double eps; << 228 // case 1. << 229 static const G4double Egsmall = 2.*CLHEP::Me << 230 if (gammaEnergy < Egsmall) { << 231 eps = eps0 + (0.5-eps0)*rndmEngine->flat() << 232 } else { 215 } else { 233 // case 2. << 216 // now comes the case with GammaEnergy >= 2. MeV 234 // get the Coulomb factor for the target e << 217 // select randomly one element constituing the material 235 // F(Z) = 8*ln(Z)/3 if Eg <= 50 << 218 const G4Element* anElement = SelectRandomAtom(aMaterial, theGamma, GammaEnergy); 236 // F(Z) = 8*ln(Z)/3 + 8*fc(Z) if Eg > 50 << 219 >> 220 // Extract Coulomb factor for this Element >> 221 G4double FZ = 8.*(anElement->GetIonisation()->GetlogZ3()); >> 222 if (GammaEnergy > 50.*MeV) FZ += 8.*(anElement->GetfCoulomb()); >> 223 >> 224 // limits of the screening variable >> 225 G4double screenfac = 136.*epsil0/(anElement->GetIonisation()->GetZ3()); >> 226 G4double screenmax = exp ((42.24 - FZ)/8.368) - 0.952 ; >> 227 G4double screenmin = min(4.*screenfac,screenmax); >> 228 >> 229 // limits of the energy sampling >> 230 G4double epsil1 = 0.5 - 0.5*sqrt(1. - screenmin/screenmax) ; >> 231 G4double epsilmin = max(epsil0,epsil1) , epsilrange = 0.5 - epsilmin; >> 232 237 // 233 // 238 // The screening variable 'delta(eps)' = 1 << 234 // sample the energy rate of the created electron (or positron) 239 // Due to the Coulomb correction, the DCS << 240 // kinematicaly allowed eps > eps0 values. << 241 // range with negative DCS, the minimum ep << 242 // max[eps0, epsp] with epsp is the soluti << 243 // with SF being the screening function (S << 244 // The solution is epsp = 0.5 - 0.5*sqrt[ << 245 // with deltap = Exp[(42.038-F(Z))/8.29]-0 << 246 // - when eps=eps_max = 0.5 => << 247 // - epsp = 0.5 - 0.5*sqrt[ 1 - delta_min/ << 248 // - and eps_min = max[eps0, epsp] << 249 static const G4double midEnergy = 50.*CLHE << 250 const G4int iZet = std::min(gMa << 251 const G4double deltaFactor = 136.*eps0/an << 252 G4double deltaMax = gElementData << 253 G4double FZ = 8.*anElement << 254 if (gammaEnergy > midEnergy) { << 255 FZ += 8.*(anElement->GetfCoulomb()) << 256 deltaMax = gElementData[iZet]->fDeltaMax << 257 } << 258 const G4double deltaMin = 4.*deltaFactor; << 259 // << 260 // compute the limits of eps << 261 const G4double epsp = 0.5 - 0.5*std::s << 262 const G4double epsMin = std::max(eps0,ep << 263 const G4double epsRange = 0.5 - epsMin; << 264 // 235 // 265 // sample the energy rate (eps) of the cre << 236 //G4double epsil, screenvar, greject ; 266 G4double F10, F20; << 237 G4double screenvar, greject ; 267 ScreenFunction12(deltaMin, F10, F20); << 238 268 F10 -= FZ; << 239 G4double F10 = ScreenFunction1(screenmin) - FZ; 269 F20 -= FZ; << 240 G4double F20 = ScreenFunction2(screenmin) - FZ; 270 const G4double NormF1 = std::max(F10 * e << 241 G4double NormF1 = max(F10*epsilrange*epsilrange,0.); 271 const G4double NormF2 = std::max(1.5 * F << 242 G4double NormF2 = max(1.5*F20,0.); 272 const G4double NormCond = NormF1/(NormF1 + << 243 273 // we will need 3 uniform random number fo << 274 G4double rndmv[3]; << 275 G4double greject = 0.; << 276 do { 244 do { 277 rndmEngine->flatArray(3, rndmv); << 245 if ( NormF1/(NormF1+NormF2) > G4UniformRand() ) { 278 if (NormCond > rndmv[0]) { << 246 epsil = 0.5 - epsilrange*pow(G4UniformRand(), 0.333333); 279 eps = 0.5 - epsRange * fG4Calc->A13(rn << 247 screenvar = screenfac/(epsil*(1-epsil)); 280 const G4double delta = deltaFactor/(ep << 248 greject = (ScreenFunction1(screenvar) - FZ)/F10; 281 greject = (ScreenFunction1(delta)-FZ)/ << 249 282 } else { 250 } else { 283 eps = epsMin + epsRange*rndmv[1]; << 251 epsil = epsilmin + epsilrange*G4UniformRand(); 284 const G4double delta = deltaFactor/(ep << 252 screenvar = screenfac/(epsil*(1-epsil)); 285 greject = (ScreenFunction2(delta)-FZ)/ << 253 greject = (ScreenFunction2(screenvar) - FZ)/F20; 286 } 254 } 287 // Loop checking, 03-Aug-2015, Vladimir << 255 288 } while (greject < rndmv[2]); << 256 } while( greject < G4UniformRand() ); 289 } // end of eps sampling << 257 >> 258 } // end of epsil sampling >> 259 >> 260 // >> 261 // fixe charges randomly 290 // 262 // 291 // select charges randomly << 263 292 G4double eTotEnergy, pTotEnergy; << 264 G4double ElectTotEnergy, PositTotEnergy; 293 if (rndmEngine->flat() > 0.5) { << 265 if (G4UniformRand() > 0.5) { 294 eTotEnergy = (1.-eps)*gammaEnergy; << 266 295 pTotEnergy = eps*gammaEnergy; << 267 ElectTotEnergy = (1.-epsil)*GammaEnergy; >> 268 PositTotEnergy = epsil*GammaEnergy; >> 269 296 } else { 270 } else { 297 pTotEnergy = (1.-eps)*gammaEnergy; << 271 298 eTotEnergy = eps*gammaEnergy; << 272 PositTotEnergy = (1.-epsil)*GammaEnergy; >> 273 ElectTotEnergy = epsil*GammaEnergy; 299 } 274 } >> 275 >> 276 // >> 277 // scattered electron (positron) angles. ( Z - axis along the parent photon) 300 // 278 // 301 // sample pair kinematics << 279 // universal distribution suggested by L. Urban 302 const G4double eKinEnergy = std::max(0.,eTot << 280 // (Geant3 manual (1993) Phys211), 303 const G4double pKinEnergy = std::max(0.,pTot << 281 // derived from Tsai distribution (Rev Mod Phys 49,421(1977)) >> 282 >> 283 G4double u; >> 284 const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ; >> 285 >> 286 if (9./(9.+d) >G4UniformRand()) u= - log(G4UniformRand()*G4UniformRand())/a1; >> 287 else u= - log(G4UniformRand()*G4UniformRand())/a2; >> 288 >> 289 G4double TetEl = u*electron_mass_c2/ElectTotEnergy; >> 290 G4double TetPo = u*electron_mass_c2/PositTotEnergy; >> 291 G4double Phi = twopi * G4UniformRand(); >> 292 G4double dxEl= sin(TetEl)*cos(Phi),dyEl= sin(TetEl)*sin(Phi),dzEl=cos(TetEl); >> 293 G4double dxPo=-sin(TetPo)*cos(Phi),dyPo=-sin(TetPo)*sin(Phi),dzPo=cos(TetPo); >> 294 304 // 295 // 305 G4ThreeVector eDirection, pDirection; << 296 // kinematic of the created pair 306 // 297 // 307 GetAngularDistribution()->SamplePairDirectio << 298 // the electron and positron are assumed to have a symetric 308 << 299 // angular distribution with respect to the Z axis along the parent photon. 309 << 300 310 // create G4DynamicParticle object for the p << 301 G4double ElectKineEnergy = max(0.,ElectTotEnergy - electron_mass_c2); 311 auto aParticle1= new G4DynamicParticle(fTheE << 302 312 // create G4DynamicParticle object for the p << 303 G4ThreeVector ElectDirection (dxEl, dyEl, dzEl); 313 auto aParticle2= new G4DynamicParticle(fTheP << 304 ElectDirection.rotateUz(GammaDirection); >> 305 >> 306 // create G4DynamicParticle object for the particle1 >> 307 G4DynamicParticle* aParticle1= new G4DynamicParticle( >> 308 theElectron,ElectDirection,ElectKineEnergy); >> 309 >> 310 // the e+ is always created (even with Ekine=0) for further annihilation. >> 311 >> 312 G4double PositKineEnergy = max(0.,PositTotEnergy - electron_mass_c2); >> 313 >> 314 G4ThreeVector PositDirection (dxPo, dyPo, dzPo); >> 315 PositDirection.rotateUz(GammaDirection); >> 316 >> 317 // create G4DynamicParticle object for the particle2 >> 318 G4DynamicParticle* aParticle2= new G4DynamicParticle( >> 319 thePositron,PositDirection,PositKineEnergy); >> 320 314 // Fill output vector 321 // Fill output vector >> 322 std::vector<G4DynamicParticle*>* fvect = new std::vector<G4DynamicParticle*>; 315 fvect->push_back(aParticle1); 323 fvect->push_back(aParticle1); 316 fvect->push_back(aParticle2); 324 fvect->push_back(aParticle2); >> 325 317 // kill incident photon 326 // kill incident photon 318 fParticleChange->SetProposedKineticEnergy(0. 327 fParticleChange->SetProposedKineticEnergy(0.); 319 fParticleChange->ProposeTrackStatus(fStopAnd 328 fParticleChange->ProposeTrackStatus(fStopAndKill); >> 329 >> 330 return fvect; 320 } 331 } 321 332 322 // should be called only by the master and at << 333 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 323 void G4BetheHeitlerModel::InitialiseElementDat << 334 324 { << 325 // create for all elements that are in the d << 326 auto elemTable = G4Element::GetElementTable( << 327 for (auto const & elem : *elemTable) { << 328 const G4int Z = elem->GetZasInt(); << 329 const G4int iz = std::min(gMaxZet, Z); << 330 if (nullptr == gElementData[iz]) { // crea << 331 G4double FZLow = 8.*elem->GetIonisat << 332 G4double FZHigh = FZLow + 8.*elem->Ge << 333 auto elD = new ElementData(); << 334 elD->fDeltaMaxLow = G4Exp((42.038 - FZL << 335 elD->fDeltaMaxHigh = G4Exp((42.038 - FZH << 336 gElementData[iz] = elD; << 337 } << 338 if (useEPICS2017 && Z < 101) { << 339 fXSection->Retrieve(Z); << 340 } << 341 } << 342 << 343 } << 344 335 345 336