- Timestamp:
- Apr 6, 2009, 12:21:12 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/source/processes/electromagnetic/standard/src/G4eCoulombScatteringModel.cc
r819 r961 24 24 // ******************************************************************** 25 25 // 26 // $Id: G4eCoulombScatteringModel.cc,v 1. 40 2008/01/07 08:32:01vnivanch Exp $27 // GEANT4 tag $Name: geant4-09-0 1-patch-02 $26 // $Id: G4eCoulombScatteringModel.cc,v 1.59 2008/10/22 18:39:29 vnivanch Exp $ 27 // GEANT4 tag $Name: geant4-09-02-ref-02 $ 28 28 // 29 29 // ------------------------------------------------------------------- … … 44 44 // 19.08.06 V.Ivanchenko add inline function ScreeningParameter 45 45 // 09.10.07 V.Ivanchenko reorganized methods, add cut dependence in scattering off e- 46 // 09.06.08 V.Ivanchenko add SelectIsotope and sampling of the recoil ion 46 47 // 47 48 // Class Description: … … 61 62 #include "G4Positron.hh" 62 63 #include "G4Proton.hh" 64 #include "G4ParticleTable.hh" 63 65 64 66 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... … … 66 68 using namespace std; 67 69 68 G4eCoulombScatteringModel::G4eCoulombScatteringModel( 69 G4double thetaMin, G4double thetaMax, G4bool build, 70 G4double tlim, const G4String& nam) 70 G4eCoulombScatteringModel::G4eCoulombScatteringModel(const G4String& nam) 71 71 : G4VEmModel(nam), 72 cosThetaMin(cos(thetaMin)), 73 cosThetaMax(cos(thetaMax)), 74 q2Limit(tlim), 75 theCrossSectionTable(0), 76 lowKEnergy(keV), 77 highKEnergy(TeV), 72 cosThetaMin(1.0), 73 cosThetaMax(-1.0), 74 q2Limit(TeV*TeV), 78 75 alpha2(fine_structure_const*fine_structure_const), 79 76 faclim(100.0), 80 nbins(12),81 nmax(100),82 buildTable(build),83 77 isInitialised(false) 84 78 { 85 79 fNistManager = G4NistManager::Instance(); 80 theParticleTable = G4ParticleTable::GetParticleTable(); 86 81 theElectron = G4Electron::Electron(); 87 82 thePositron = G4Positron::Positron(); 88 83 theProton = G4Proton::Proton(); 84 currentMaterial = 0; 85 currentElement = 0; 89 86 a0 = alpha2*electron_mass_c2*electron_mass_c2/(0.885*0.885); 90 87 G4double p0 = electron_mass_c2*classic_electr_radius; 91 88 coeff = twopi*p0*p0; 92 89 constn = 6.937e-6/(MeV*MeV); 93 tkin = targetZ = targetA =mom2 = DBL_MIN;90 tkin = targetZ = mom2 = DBL_MIN; 94 91 elecXSection = nucXSection = 0.0; 92 recoilThreshold = DBL_MAX; 95 93 ecut = DBL_MAX; 96 94 particle = 0; 97 for(size_t j=0; j<100; j++) {index[j] = -1;} 95 currentCouple = 0; 96 for(size_t j=0; j<100; j++) { 97 FF[j] = 0.0; 98 } 98 99 } 99 100 … … 101 102 102 103 G4eCoulombScatteringModel::~G4eCoulombScatteringModel() 103 { 104 if(theCrossSectionTable) { 105 theCrossSectionTable->clearAndDestroy(); 106 delete theCrossSectionTable; 107 } 108 } 104 {} 109 105 110 106 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 111 107 112 108 void G4eCoulombScatteringModel::Initialise(const G4ParticleDefinition* p, 113 const G4DataVector&) 114 { 115 // G4cout << "!!! G4eCoulombScatteringModel::Initialise for " 116 // << p->GetParticleName() << " cos(TetMin)= " << cosThetaMin 117 // << " cos(TetMax)= " << cosThetaMax <<G4endl; 109 const G4DataVector& cuts) 110 { 111 SetupParticle(p); 112 currentCouple = 0; 113 elecXSection = nucXSection = 0.0; 114 tkin = targetZ = mom2 = DBL_MIN; 115 ecut = etag = DBL_MAX; 116 cosThetaMin = cos(PolarAngleLimit()); 117 currentCuts = &cuts; 118 //G4cout << "!!! G4eCoulombScatteringModel::Initialise for " 119 // << p->GetParticleName() << " cos(TetMin)= " << cosThetaMin 120 // << " cos(TetMax)= " << cosThetaMax <<G4endl; 118 121 if(!isInitialised) { 119 122 isInitialised = true; … … 124 127 else 125 128 fParticleChange = new G4ParticleChangeForGamma(); 126 } else { 127 return; 128 } 129 130 if(p->GetParticleType() == "nucleus") buildTable = false; 131 if(!buildTable) return; 132 133 // Compute log cross section table per atom 134 if(!theCrossSectionTable) theCrossSectionTable = new G4PhysicsTable(); 135 136 nbins = 2*G4int(log10(highKEnergy/lowKEnergy)); 137 } 138 139 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 140 141 G4double G4eCoulombScatteringModel::ComputeCrossSectionPerAtom( 142 const G4ParticleDefinition* p, 143 G4double kinEnergy, 144 G4double Z, G4double A, 145 G4double cutEnergy, G4double) 146 { 147 if(p == particle && kinEnergy == tkin && Z == targetZ && 148 A == targetA && cutEnergy == ecut) return nucXSection; 149 150 //G4cout << "### G4eCoulombScatteringModel::ComputeCrossSectionPerAtom for " 151 // << p->GetParticleName() << " Z= " << Z << " A= " << A 152 // << " e= " << kinEnergy << G4endl; 153 154 nucXSection = ComputeElectronXSectionPerAtom(p,kinEnergy,Z,A,cutEnergy); 155 156 // nuclear cross section 157 if(theCrossSectionTable) { 158 G4bool b; 159 G4int iz = G4int(Z); 160 G4int idx = index[iz]; 161 162 // compute table for given Z 163 if(-1 == idx) { 164 idx = theCrossSectionTable->size(); 165 index[iz] = idx; 166 G4PhysicsLogVector* ptrVector 167 = new G4PhysicsLogVector(lowKEnergy, highKEnergy, nbins); 168 // G4cout << "New vector Z= " << iz << " A= " << A << " idx= " << idx << G4endl; 169 G4double e, value; 170 for(G4int i=0; i<=nbins; i++) { 171 e = ptrVector->GetLowEdgeEnergy( i ) ; 172 value = CalculateCrossSectionPerAtom(p, e, Z, A); 173 ptrVector->PutValue( i, log(value) ); 174 } 175 theCrossSectionTable->push_back(ptrVector); 176 } 177 178 // take value from the table 179 nucXSection += 180 std::exp((((*theCrossSectionTable)[idx]))->GetValue(kinEnergy, b)); 181 182 // compute value from scratch 183 } else nucXSection += CalculateCrossSectionPerAtom(p, kinEnergy, Z, A); 184 185 // G4cout << " cross(bn)= " << nucXSection/barn << G4endl; 186 187 if(nucXSection < 0.0) nucXSection = 0.0; 188 return nucXSection; 189 } 190 191 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 192 193 G4double G4eCoulombScatteringModel::ComputeElectronXSectionPerAtom( 194 const G4ParticleDefinition* p, 195 G4double kinEnergy, 196 G4double Z, 197 G4double A, 198 G4double cutEnergy) 199 { 200 if(p == particle && kinEnergy == tkin && Z == targetZ && 201 cutEnergy == ecut) return elecXSection; 129 } 130 if(mass < GeV && particle->GetParticleType() != "nucleus") { 131 InitialiseElementSelectors(p,cuts); 132 } 133 } 134 135 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 136 137 void G4eCoulombScatteringModel::ComputeMaxElectronScattering(G4double cutEnergy) 138 { 202 139 ecut = cutEnergy; 203 elecXSection = 0.0;204 SetupParticle(p);205 G4double ekin = std::max(keV, kinEnergy);206 //G4double ekin = kinEnergy;207 SetupTarget(Z, A, ekin);208 209 140 G4double tmax = tkin; 210 if(p == theElectron) tmax *= 0.5;211 else if(p != thePositron) {141 cosTetMaxElec = 1.0; 142 if(mass > MeV) { 212 143 G4double ratio = electron_mass_c2/mass; 213 144 G4double tau = tkin/mass; 214 145 tmax = 2.0*electron_mass_c2*tau*(tau + 2.)/ 215 146 (1.0 + 2.0*ratio*(tau + 1.0) + ratio*ratio); 216 } 217 218 cosTetMaxElec = cosTetMaxNuc; 219 G4double t = std::min(cutEnergy, tmax); 220 G4double mom21 = t*(t + 2.0*electron_mass_c2); 221 G4double t1 = tkin - t; 222 if(t1 > 0.0) { 223 G4double mom22 = t1*(t1 + 2.0*mass); 224 G4double ctm = (mom2 + mom22 - mom21)*0.5/sqrt(mom2*mom22); 225 if(ctm > cosTetMaxElec && ctm <= 1.0) cosTetMaxElec = ctm; 226 } 227 228 if(cosTetMaxElec < cosThetaMin) { 229 G4double x1 = 1.0 - cosThetaMin + screenZ; 230 G4double x2 = 1.0 - cosTetMaxElec + screenZ; 231 elecXSection = coeff*Z*chargeSquare*invbeta2* 232 (cosThetaMin - cosTetMaxElec)/(x1*x2*mom2); 233 } 234 // G4cout << "cut= " << ecut << " e= " << tkin 235 // << " croosE(barn)= " << elecXSection/barn 236 // << " cosEl= " << cosTetMaxElec << " costmin= " << cosThetaMin << G4endl; 237 return elecXSection; 238 } 239 240 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 241 242 G4double G4eCoulombScatteringModel::CalculateCrossSectionPerAtom( 243 const G4ParticleDefinition* p, 244 G4double kinEnergy, 245 G4double Z, G4double A) 246 { 247 G4double cross = 0.0; 147 cosTetMaxElec = 1.0 - std::min(cutEnergy, tmax)*electron_mass_c2/mom2; 148 } else { 149 150 if(particle == theElectron) tmax *= 0.5; 151 G4double t = std::min(cutEnergy, tmax); 152 G4double mom21 = t*(t + 2.0*electron_mass_c2); 153 G4double t1 = tkin - t; 154 //G4cout << "tkin= " << tkin << " t= " << t << " t1= " << t1 << G4endl; 155 if(t1 > 0.0) { 156 G4double mom22 = t1*(t1 + 2.0*mass); 157 G4double ctm = (mom2 + mom22 - mom21)*0.5/sqrt(mom2*mom22); 158 //G4cout << "ctm= " << ctm << G4endl; 159 if(ctm < 1.0) cosTetMaxElec = ctm; 160 } 161 } 162 } 163 164 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 165 166 G4double G4eCoulombScatteringModel::ComputeCrossSectionPerAtom( 167 const G4ParticleDefinition* p, 168 G4double kinEnergy, 169 G4double Z, G4double, 170 G4double cutEnergy, G4double) 171 { 172 //G4cout << "### G4eCoulombScatteringModel::ComputeCrossSectionPerAtom for " 173 // << p->GetParticleName()<<" Z= "<<Z<<" e(MeV)= "<< kinEnergy/MeV << G4endl; 174 G4double xsec = 0.0; 248 175 SetupParticle(p); 249 G4double ekin = std::max(keV, kinEnergy); 250 //G4double ekin = kinEnergy; 251 SetupTarget(Z, A, ekin); 252 253 if(cosTetMaxNuc < cosThetaMin) { 254 G4double x1 = 1.0 - cosThetaMin; 255 G4double x2 = 1.0 - cosTetMaxNuc; 256 G4double x3 = cosThetaMin - cosTetMaxNuc; 257 G4double z1 = x1 + screenZ; 258 G4double z2 = x2 + screenZ; 259 G4double d = 1.0/formfactA - screenZ; 260 G4double d1 = 1.0 - formfactA*screenZ; 261 G4double zn1= x1 + d; 262 G4double zn2= x2 + d; 263 cross = coeff*Z*Z*chargeSquare*invbeta2 264 *(x3/(z1*z2) + x3/(zn1*zn2) + 265 2.0*std::log(z1*zn2/(z2*zn1))/d) / (mom2*d1*d1); 266 } 176 G4double ekin = std::max(lowEnergyLimit, kinEnergy); 177 SetupKinematic(ekin, cutEnergy); 178 if(cosTetMaxNuc < cosTetMinNuc) { 179 SetupTarget(Z, ekin); 180 xsec = CrossSectionPerAtom(); 181 } 182 /* 183 G4cout << "e(MeV)= " << ekin/MeV << "cosTetMinNuc= " << cosTetMinNuc 184 << " cosTetMaxNuc= " << cosTetMaxNuc 185 << " cosTetMaxElec= " << cosTetMaxElec 186 << " screenZ= " << screenZ 187 << " formfactA= " << formfactA 188 << " cosTetMaxHad= " << cosTetMaxHad << G4endl; 189 */ 190 return xsec; 191 } 192 193 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 194 195 G4double G4eCoulombScatteringModel::CrossSectionPerAtom() 196 { 197 // This method needs initialisation before be called 198 199 G4double fac = coeff*targetZ*chargeSquare*invbeta2/mom2; 200 elecXSection = 0.0; 201 nucXSection = 0.0; 202 203 G4double x = 1.0 - cosTetMinNuc; 204 G4double x1 = x + screenZ; 205 206 if(cosTetMaxElec2 < cosTetMinNuc) { 207 elecXSection = fac*(cosTetMinNuc - cosTetMaxElec2)/ 208 (x1*(1.0 - cosTetMaxElec2 + screenZ)); 209 nucXSection = elecXSection; 210 } 211 212 //G4cout << "XS tkin(MeV)= " << tkin<<" xs= " <<nucXSection 213 // << " costmax= " << cosTetMaxNuc2 214 // << " costmin= " << cosTetMinNuc << " Z= " << targetZ <<G4endl; 215 if(cosTetMaxNuc2 < cosTetMinNuc) { 216 G4double s = screenZ*formfactA; 217 G4double z1 = 1.0 - cosTetMaxNuc2 + screenZ; 218 G4double d = (1.0 - s)/formfactA; 219 //G4cout <<"x1= "<<x1<<" z1= " <<z1<<" s= "<<s << " d= " <<d <<G4endl; 220 if(d < 0.2*x1) { 221 G4double x2 = x1*x1; 222 G4double z2 = z1*z1; 223 x = (1.0/(x1*x2) - 1.0/(z1*z2) - d*1.5*(1.0/(x2*x2) - 1.0/(z2*z2)))/ 224 (3.0*formfactA*formfactA); 225 } else { 226 G4double x2 = x1 + d; 227 G4double z2 = z1 + d; 228 x = (1.0 + 2.0*s)*((cosTetMinNuc - cosTetMaxNuc2)*(1.0/(x1*z1) + 1.0/(x2*z2)) - 229 2.0*log(z1*x2/(z2*x1))/d); 230 } 231 nucXSection += fac*targetZ*x; 232 } 233 234 //G4cout<<" cross(bn)= "<<nucXSection/barn<<" xsElec(bn)= "<<elecXSection/barn 235 // << " Asc= " << screenZ << G4endl; 267 236 268 // G4cout << "CalculateCrossSectionPerAtom: e(MeV)= " << tkin 269 // << " cross(b)= " << cross/barn << " ctmin= " << cosThetaMin 270 // << " ctmax= " << cosTetMaxNuc << G4endl; 271 272 return cross; 237 return nucXSection; 273 238 } 274 239 … … 276 241 277 242 void G4eCoulombScatteringModel::SampleSecondaries( 278 std::vector<G4DynamicParticle*>* ,243 std::vector<G4DynamicParticle*>* fvect, 279 244 const G4MaterialCutsCouple* couple, 280 245 const G4DynamicParticle* dp, 281 246 G4double cutEnergy, 282 G4double maxEnergy) 283 { 284 const G4Material* aMaterial = couple->GetMaterial(); 285 const G4ParticleDefinition* p = dp->GetDefinition(); 247 G4double) 248 { 286 249 G4double kinEnergy = dp->GetKineticEnergy(); 287 288 // Select atom and setup 289 SetupParticle(p); 290 const G4Element* elm = 291 SelectRandomAtom(aMaterial,p,kinEnergy,cutEnergy,maxEnergy); 292 G4double Z = elm->GetZ(); 293 G4double A = elm->GetN(); 294 295 G4double cross = 296 ComputeCrossSectionPerAtom(p,kinEnergy,Z,A,cutEnergy,maxEnergy); 297 298 G4double costm = cosTetMaxNuc; 250 if(kinEnergy <= DBL_MIN) return; 251 DefineMaterial(couple); 252 SetupParticle(dp->GetDefinition()); 253 G4double ekin = std::max(lowEnergyLimit, kinEnergy); 254 SetupKinematic(ekin, cutEnergy); 255 //G4cout << "G4eCoulombScatteringModel::SampleSecondaries e(MeV)= " 256 // << kinEnergy << " " << particle->GetParticleName() << G4endl; 257 258 // Choose nucleus 259 currentElement = SelectRandomAtom(couple,particle,ekin,cutEnergy,ekin); 260 261 SetupTarget(currentElement->GetZ(),ekin); 262 263 G4double cost = SampleCosineTheta(); 264 G4double z1 = 1.0 - cost; 265 if(z1 < 0.0) return; 266 267 G4double sint = sqrt(z1*(1.0 + cost)); 268 269 //G4cout<<"## Sampled sint= " << sint << " Z= " << targetZ 270 // << " screenZ= " << screenZ << " cn= " << formfactA << G4endl; 271 272 G4double phi = twopi * G4UniformRand(); 273 274 G4ThreeVector direction = dp->GetMomentumDirection(); 275 G4ThreeVector newDirection(cos(phi)*sint,sin(phi)*sint,cost); 276 newDirection.rotateUz(direction); 277 278 fParticleChange->ProposeMomentumDirection(newDirection); 279 280 // recoil sampling assuming a small recoil 281 // and first order correction to primary 4-momentum 282 if(lowEnergyLimit < kinEnergy) { 283 G4int ia = SelectIsotopeNumber(currentElement); 284 G4double Trec = z1*mom2/(amu_c2*G4double(ia)); 285 G4double th = 286 std::min(recoilThreshold, 287 targetZ*currentElement->GetIonisation()->GetMeanExcitationEnergy()); 288 289 if(Trec > th) { 290 G4int iz = G4int(targetZ); 291 G4ParticleDefinition* ion = theParticleTable->FindIon(iz, ia, 0, iz); 292 Trec = z1*mom2/ion->GetPDGMass(); 293 if(Trec < kinEnergy) { 294 G4ThreeVector dir = (direction - newDirection).unit(); 295 G4DynamicParticle* newdp = new G4DynamicParticle(ion, dir, Trec); 296 fvect->push_back(newdp); 297 fParticleChange->SetProposedKineticEnergy(kinEnergy - Trec); 298 } 299 } 300 } 301 302 return; 303 } 304 305 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 306 307 G4double G4eCoulombScatteringModel::SampleCosineTheta() 308 { 309 G4double costm = cosTetMaxNuc2; 299 310 G4double formf = formfactA; 300 if(G4UniformRand()*cross < elecXSection) { 301 costm = cosTetMaxElec; 311 G4double prob = 0.0; 312 G4double xs = CrossSectionPerAtom(); 313 if(xs > 0.0) prob = elecXSection/xs; 314 315 // scattering off e or A? 316 if(G4UniformRand() < prob) { 317 costm = cosTetMaxElec2; 302 318 formf = 0.0; 303 319 } 320 304 321 /* 305 G4cout << " G4eCoul...SampleSecondaries: e(MeV)= " << tkin322 G4cout << "SampleCost: e(MeV)= " << tkin 306 323 << " ctmin= " << cosThetaMin 307 324 << " ctmaxN= " << cosTetMaxNuc 308 325 << " ctmax= " << costm 309 << " Z= " << Z << " A= " << A 310 << " cross= " << cross/barn << " crossE= " << elecXSection/barn 326 << " Z= " << targetZ << " A= " << targetA 311 327 << G4endl; 312 328 */ 313 if(costm >= cosT hetaMin) return;314 315 G4double x1 = 1. - cosT hetaMin+ screenZ;316 G4double x2 = 1. - costm ;317 G4double x3 = cosT hetaMin- costm;318 G4double grej, z,z1;329 if(costm >= cosTetMinNuc) return 2.0; 330 331 G4double x1 = 1. - cosTetMinNuc + screenZ; 332 G4double x2 = 1. - costm + screenZ; 333 G4double x3 = cosTetMinNuc - costm; 334 G4double grej, z1; 319 335 do { 320 z = G4UniformRand()*x3; 321 z1 = (x1*x2 - screenZ*z)/(x1 + z); 322 if(z1 < 0.0) z1 = 0.0; 323 else if(z1 > 2.0) z1 = 2.0; 336 z1 = x1*x2/(x1 + G4UniformRand()*x3) - screenZ; 324 337 grej = 1.0/(1.0 + formf*z1); 325 338 } while ( G4UniformRand() > grej*grej ); 326 327 G4double cost = 1.0 - z1; 328 G4double sint= sqrt(z1*(2.0 - z1)); 329 /* 330 if(sint > 0.1) 331 G4cout<<"## SampleSecondaries: e(MeV)= " << kinEnergy 332 << " sint= " << sint << " Z= " << Z << " screenZ= " << screenZ 333 << " cn= " << formf 334 << G4endl; 335 */ 336 G4double phi = twopi * G4UniformRand(); 337 338 G4ThreeVector direction = dp->GetMomentumDirection(); 339 G4ThreeVector newDirection(cos(phi)*sint,sin(phi)*sint,cost); 340 newDirection.rotateUz(direction); 341 342 fParticleChange->ProposeMomentumDirection(newDirection); 343 344 return; 345 } 346 347 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 348 349 339 340 //G4cout << "z= " << z1 << " cross= " << nucXSection/barn 341 // << " crossE= " << elecXSection/barn << G4endl; 342 343 return 1.0 - z1; 344 } 345 346 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 347 348
Note: See TracChangeset
for help on using the changeset viewer.