Changeset 1315 for trunk/source/processes/electromagnetic/standard/src/G4GoudsmitSaundersonMscModel.cc
- Timestamp:
- Jun 18, 2010, 11:42:07 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/source/processes/electromagnetic/standard/src/G4GoudsmitSaundersonMscModel.cc
r1228 r1315 24 24 // ******************************************************************** 25 25 // 26 // $Id: G4GoudsmitSaundersonMscModel.cc,v 1.2 0 2009/12/16 17:50:11 gunterExp $27 // GEANT4 tag $Name: geant4-09-0 3$26 // $Id: G4GoudsmitSaundersonMscModel.cc,v 1.24 2010/05/17 15:11:30 vnivanch Exp $ 27 // GEANT4 tag $Name: geant4-09-04-beta-cand-01 $ 28 28 // 29 29 // ------------------------------------------------------------------- … … 51 51 // assuming the case of lambdan<1 as single scattering regime 52 52 // tuning theta sampling for theta below the screening angle 53 // 08.02.2010 O.Kadri: bugfix in compound xsection calculation and small angle computation 54 // adding a rejection condition to hard collision angular sampling 55 // ComputeTruePathLengthLimit was taken from G4WentzelVIModel 56 // 26.03.2010 O.Kadri: direct xsection calculation not inverse of the inverse 57 // angular sampling without large angle rejection method 58 // longitudinal displacement is computed exactly from <z> 59 // 12.05.2010 O.Kadri: exchange between target and projectile has as a condition the particle type (e-/e-) 60 // some cleanup to minimize time consuming (adding lamdan12 & Qn12, changing the error to 1.0e-12 for scrA) 53 61 // 54 62 // … … 60 68 //Ref.4:Bielajew et al.,".....", NIMB 173 (2001) 332-343; 61 69 //Ref.5:F. Salvat et al.,"ELSEPA--Dirac partial ...molecules", Comp.Phys.Comm.165 (2005) pp 157-190; 62 //Ref.6:G4UrbanMscModel G4_v9.1Ref09; 63 //Ref.7:G4eCoulombScatteringModel G4_v9.1Ref09. 64 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 65 70 //Ref.6:G4UrbanMscModel G4 9.2; 71 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 66 72 #include "G4GoudsmitSaundersonMscModel.hh" 67 73 #include "G4GoudsmitSaundersonTable.hh" … … 77 83 #include "G4PhysicsTable.hh" 78 84 #include "Randomize.hh" 79 #include "G4Poisson.hh"80 85 81 86 using namespace std; … … 128 133 G4double kineticEnergy,G4double Z, G4double, G4double, G4double) 129 134 { 130 //Build cross section table : Taken from Ref.7131 135 G4double cs=0.0; 132 136 G4double kinEnergy = kineticEnergy; … … 134 138 if(kinEnergy>highKEnergy)kinEnergy=highKEnergy; 135 139 136 G4double value0,value1;137 CalculateIntegrals(p,Z,kinEnergy, value0,value1);140 G4double cs0; 141 CalculateIntegrals(p,Z,kinEnergy,cs0,cs); 138 142 139 if(value1 > 0.0) cs = 1./value1;140 141 143 return cs; 142 144 } … … 148 150 { 149 151 G4double kineticEnergy = dynParticle->GetKineticEnergy(); 150 if((kineticEnergy <= 0.0) || (tPathLength <= tlimitminfix)) return ; 151 152 G4double cosTheta1,sinTheta1,cosTheta2,sinTheta2; 153 G4double phi1,phi2,cosPhi1=1.0,sinPhi1=0.0,cosPhi2=1.0,sinPhi2=0.0; 154 G4double q1,Gamma,Eta,delta,nu,nu0,nu1,nu2; 152 if((kineticEnergy <= 0.0) || (tPathLength <= tlimitminfix)|| 153 (tPathLength/tausmall < lambda1)) return ; 155 154 156 155 /////////////////////////////////////////// 157 // Effective energy and path-length from Eq. 4.7.15+16 of Ref.4156 // Effective energy 158 157 G4double eloss = theManager->GetEnergy(particle,tPathLength,currentCouple); 159 if(eloss>0.5*kineticEnergy)eloss=kineticEnergy-eloss;//exchange possibility between target atomic e- and incident particle 158 if(eloss>0.5*kineticEnergy) 159 {if((dynParticle->GetCharge())==-eplus)eloss=kineticEnergy-eloss;//exchange between target and projectile if they are electrons 160 else eloss=0.5*kineticEnergy; 161 } 160 162 G4double ee = kineticEnergy - 0.5*eloss; 161 163 G4double ttau = ee/electron_mass_c2; … … 166 168 kineticEnergy *= (1 - cst1); 167 169 /////////////////////////////////////////// 168 // additivity rule for mixture and compound xsection calculation170 // additivity rule for mixture and compound xsection's 169 171 const G4Material* mat = currentCouple->GetMaterial(); 172 const G4ElementVector* theElementVector = mat->GetElementVector(); 173 const G4double* theAtomNumDensityVector = mat->GetVecNbOfAtomsPerVolume(); 170 174 G4int nelm = mat->GetNumberOfElements(); 171 const G4ElementVector* theElementVector = mat->GetElementVector(); 172 const G4double* theFraction = mat->GetFractionVector(); 173 G4double atomPerVolume = mat->GetTotNbOfAtomsPerVolume(); 174 G4double llambda0=0.,llambda1=0.; 175 G4double s0,s1; 176 lambda0=0.; 175 177 for(G4int i=0;i<nelm;i++) 176 { 177 G4double l0,l1; 178 CalculateIntegrals(particle,(*theElementVector)[i]->GetZ(),kineticEnergy,l0,l1); 179 llambda0 += (theFraction[i]/l0); 180 llambda1 += (theFraction[i]/l1); 178 { 179 CalculateIntegrals(particle,(*theElementVector)[i]->GetZ(),kineticEnergy,s0,s1); 180 lambda0 += (theAtomNumDensityVector[i]*s0); 181 181 } 182 if(llambda0>DBL_MIN) llambda0 =1./llambda0; 183 if(llambda1>DBL_MIN) llambda1 =1./llambda1; 182 if(lambda0>DBL_MIN) lambda0 =1./lambda0; 183 184 // Newton-Raphson root's finding method of scrA from: 185 // Sig1(PWA)/Sig0(PWA)=g1=2*scrA*((1+scrA)*log(1+1/scrA)-1) 184 186 G4double g1=0.0; 185 if(l lambda1>DBL_MIN) g1 = llambda0/llambda1;186 187 G4double x1,x0;188 x0=g1/2.;187 if(lambda1>DBL_MIN) g1 = lambda0/lambda1; 188 189 G4double logx0,x1,delta; 190 G4double x0=g1/2.; 189 191 do 190 192 { 191 x1 = x0-(x0*((1.+x0)*log(1.+1./x0)-1.0)-g1/2.)/( (1.+2.*x0)*log(1.+1./x0)-2.0);// x1=x0-f(x0)/f'(x0) 193 logx0=std::log(1.+1./x0); 194 x1 = x0-(x0*((1.+x0)*logx0-1.0)-g1/2.)/( (1.+2.*x0)*logx0-2.0); 192 195 delta = std::abs( x1 - x0 ); 193 x0 = x1; // new approximation becomes the old approximation for the next iteration194 } while (delta > 1 e-10);196 x0 = x1; 197 } while (delta > 1.0e-12); 195 198 G4double scrA = x1; 196 199 197 G4double us=0.0,vs=0.0,ws=1.0,x_coord=0.0,y_coord=0.0,z_coord=1.0;198 200 G4double lambdan=0.; 199 G4bool mscatt=false,noscatt=false; 200 201 if(llambda0>0.)lambdan=atomPerVolume*tPathLength/llambda0; 202 if((lambdan<=1.0e-12))return; 203 201 202 if(lambda0>0.)lambdan=tPathLength/lambda0; 203 if(lambdan<=1.0e-12)return; 204 G4double lambdan12=0.5*lambdan; 205 Qn1 = lambdan *g1;//2.* lambdan *scrA*((1.+scrA)*log(1.+1./scrA)-1.); 206 Qn12 = 0.5*Qn1; 207 208 G4double cosTheta1,sinTheta1,cosTheta2,sinTheta2; 209 G4double cosPhi1=1.0,sinPhi1=0.0,cosPhi2=1.0,sinPhi2=0.0; 210 G4double us=0.0,vs=0.0,ws=1.0,wss=0.,x_coord=0.0,y_coord=0.0,z_coord=1.0; 211 204 212 G4double epsilon1=G4UniformRand(); 205 G4double expn = exp(-lambdan); 206 if((epsilon1<expn)||insideskin)// no scattering 207 {noscatt=true;} 208 else if((epsilon1<((1.+lambdan)*expn)||(lambdan<1.))) 209 { 210 mscatt=false; 211 ws=G4UniformRand(); 212 ws= 1.-2.*scrA*ws/(1.-ws + scrA); 213 if(acos(ws)<sqrt(scrA))//small angle approximation for theta less than screening angle 214 {G4int i=0; 215 do{i++; 216 ws=1.+0.5*atomPerVolume*tPathLength*log(G4UniformRand())/llambda1; 217 }while((fabs(ws)>1.)&&(i<20));//i<20 to avoid time consuming during the run 218 if(i==19)ws=cos(sqrt(scrA)); 219 } 220 G4double phi0=twopi*G4UniformRand(); 221 us=sqrt(1.-ws*ws)*cos(phi0); 222 vs=sqrt(1.-ws*ws)*sin(phi0); 223 G4double rr=G4UniformRand(); 224 x_coord=(rr*us); 225 y_coord=(rr*vs); 226 z_coord=((1.-rr)+rr*ws); 227 } 228 else 229 { 230 mscatt=true; 213 G4double expn = std::exp(-lambdan); 214 if(epsilon1<expn)// no scattering 215 {return;} 216 else if((epsilon1<((1.+lambdan)*expn))||(lambdan<1.))//single scattering (Rutherford DCS's) 217 { 218 219 G4double xi=G4UniformRand(); 220 xi= 2.*scrA*xi/(1.-xi + scrA); 221 if(xi<0.)xi=0.; 222 else if(xi>2.)xi=2.; 223 ws=1.-xi; 224 wss=std::sqrt(xi*(2.-xi)); 225 G4double phi0=CLHEP::twopi*G4UniformRand(); 226 us=wss*cos(phi0); 227 vs=wss*sin(phi0); 228 } 229 else // multiple scattering 230 { 231 231 // Ref.2 subsection 4.4 "The best solution found" 232 232 // Sample first substep scattering angle 233 SampleCosineTheta( 0.5*lambdan,scrA,cosTheta1,sinTheta1);234 phi1 =twopi*G4UniformRand();233 SampleCosineTheta(lambdan12,scrA,cosTheta1,sinTheta1); 234 G4double phi1 = CLHEP::twopi*G4UniformRand(); 235 235 cosPhi1 = cos(phi1); 236 236 sinPhi1 = sin(phi1); 237 237 238 238 // Sample second substep scattering angle 239 SampleCosineTheta( 0.5*lambdan,scrA,cosTheta2,sinTheta2);240 phi2 =twopi*G4UniformRand();239 SampleCosineTheta(lambdan12,scrA,cosTheta2,sinTheta2); 240 G4double phi2 = CLHEP::twopi*G4UniformRand(); 241 241 cosPhi2 = cos(phi2); 242 242 sinPhi2 = sin(phi2); 243 243 244 // Scattering direction244 // Overall scattering direction 245 245 us = sinTheta2*(cosTheta1*cosPhi1*cosPhi2 - sinPhi1*sinPhi2) + cosTheta2*sinTheta1*cosPhi1; 246 246 vs = sinTheta2*(cosTheta1*sinPhi1*cosPhi2 + cosPhi1*sinPhi2) + cosTheta2*sinTheta1*sinPhi1; 247 247 ws = cosTheta1*cosTheta2 - sinTheta1*sinTheta2*cosPhi2; 248 G4double sqrtA=sqrt(scrA); 249 if(acos(ws)<sqrtA)//small angle approximation for theta less than screening angle 250 { 251 G4int i=0; 252 do{i++; 253 ws=1.+Qn12*log(G4UniformRand()); 254 }while((fabs(ws)>1.)&&(i<20));//i<20 to avoid time consuming during the run 255 if(i>=19)ws=cos(sqrtA); 256 257 wss=std::sqrt((1.-ws)*(1.0+ws)); 258 us=wss*cos(phi1); 259 vs=wss*sin(phi1); 260 } 248 261 } 249 262 … … 253 266 fParticleChange->ProposeMomentumDirection(newDirection); 254 267 255 if((safety > tlimitminfix)&&(latDisplasment)) 256 { 257 258 if(mscatt) 259 { 260 if(scrA<DBL_MIN)scrA=DBL_MIN; 261 if(llambda1<DBL_MIN)llambda1=DBL_MIN; 262 q1 = 2.*scrA*((1. + scrA)*log(1. + 1./scrA) - 1.); 263 if(q1<DBL_MIN)q1=DBL_MIN; 264 Gamma = 6.*scrA*(1. + scrA)*((1. + 2.*scrA)*log(1. + 1./scrA) - 2.)/q1; 265 Eta = atomPerVolume*tPathLength/llambda1; 266 delta = 0.90824829 - Eta*(0.102062073-Gamma*0.026374715); 267 268 nu = G4UniformRand(); 269 nu = std::sqrt(nu); 270 nu0 = (1.0 - nu)/2.; 271 nu1 = nu*delta; 272 nu2 = nu*(1.0-delta); 273 x_coord=(nu1*sinTheta1*cosPhi1+nu2*sinTheta2*(cosPhi1*cosPhi2-cosTheta1*sinPhi1*sinPhi2)+nu0*us); 274 y_coord=(nu1*sinTheta1*sinPhi1+nu2*sinTheta2*(sinPhi1*cosPhi2+cosTheta1*cosPhi1*sinPhi2)+nu0*vs); 275 z_coord=(nu0+nu1*cosTheta1+nu2*cosTheta2+ nu0*ws) ; 276 } 277 268 if((safety > tlimitminfix)&&latDisplasment) 269 { 270 if(Qn1<0.02)// corresponding to error less than 1% in the exact formula of <z> 271 z_coord = 1.0 - Qn1*(0.5 - Qn1/6.); 272 else z_coord = (1.-std::exp(-Qn1))/Qn1; 273 274 G4double rr=std::sqrt((1.- z_coord*z_coord)/(1.-ws*ws)); 275 x_coord = rr*us; 276 y_coord = rr*vs; 278 277 // displacement is computed relatively to the end point 279 if(!noscatt)z_coord -= 1.0;//for noscatt zcoord z_coord !=0.280 G4double rr =sqrt(x_coord*x_coord+y_coord*y_coord+z_coord*z_coord);278 z_coord -= 1.0; 279 rr = std::sqrt(x_coord*x_coord+y_coord*y_coord+z_coord*z_coord); 281 280 G4double r = rr*zPathLength; 282 281 /* … … 287 286 << G4endl; 288 287 */ 288 if(tPathLength<=zPathLength)return; 289 289 if(r > tlimitminfix) { 290 290 291 G4ThreeVector latDirection(x_coord/rr,y_coord/rr,z_coord/rr);292 latDirection.rotateUz(oldDirection);293 294 ComputeDisplacement(fParticleChange, latDirection, r, safety);291 G4ThreeVector Direction(x_coord/rr,y_coord/rr,z_coord/rr); 292 Direction.rotateUz(oldDirection); 293 294 ComputeDisplacement(fParticleChange, Direction, r, safety); 295 295 } 296 296 } … … 303 303 G4double &cost, G4double &sint) 304 304 { 305 G4double u,Qn1,r1,tet;306 305 G4double xi=0.; 307 Qn1=2.* lambdan *scrA*((1.+scrA)*log(1.+1./scrA)-1.); 308 309 if (Qn1<0.001)xi=-0.5*Qn1*log(G4UniformRand()); 310 else if(Qn1>0.5)xi=2.*G4UniformRand();//isotropic distribution 311 else 312 { 313 // procedure described by Benedito in Ref.1 306 307 if (Qn12<0.001) 308 {G4double r1,tet; 314 309 do{ 315 r1=G4UniformRand(); 316 u=GSTable->SampleTheta(lambdan,scrA,G4UniformRand()); 317 xi = 2.*u; 318 tet=acos(1.-xi); 310 r1=G4UniformRand(); 311 xi=-Qn12*log(G4UniformRand()); 312 tet=acos(1.-xi); 319 313 }while(tet*r1*r1>sin(tet)); 320 } 314 } 315 else if(Qn12>0.5)xi=2.*G4UniformRand(); 316 else xi=2.*(GSTable->SampleTheta(lambdan,scrA,G4UniformRand())); 317 321 318 322 319 if(xi<0.)xi=0.; 323 if(xi>2.)xi=2.; 320 else if(xi>2.)xi=2.; 321 324 322 cost=(1. - xi); 325 323 sint=sqrt(xi*(2.-xi)); … … 333 331 void 334 332 G4GoudsmitSaundersonMscModel::CalculateIntegrals(const G4ParticleDefinition* p,G4double Z, 335 G4double kinEnergy,G4double & Lam0,336 G4double & Lam1)333 G4double kinEnergy,G4double &Sig0, 334 G4double &Sig1) 337 335 { 338 G4double summ00=0.0;339 G4double summ10=0.0;340 336 G4double x1,x2,y1,y2,acoeff,bcoeff; 341 337 G4double kineticE = kinEnergy; … … 343 339 if(kineticE>highKEnergy)kineticE=highKEnergy; 344 340 kineticE /= eV; 345 G4double logE= log(kineticE);341 G4double logE=std::log(kineticE); 346 342 347 343 G4int iZ = G4int(Z); … … 349 345 350 346 G4int enerInd=0; 351 for(G4int i= 1;i<106;i++)347 for(G4int i=0;i<105;i++) 352 348 { 353 349 if((logE>=ener[i])&&(logE<ener[i+1])){enerInd=i;break;} … … 364 360 acoeff=(y2-y1)/(x2*x2-x1*x1); 365 361 bcoeff=y2-acoeff*x2*x2; 366 summ00=acoeff*logE*logE+bcoeff;367 summ00 =exp(summ00);362 Sig0=acoeff*logE*logE+bcoeff; 363 Sig0 =std::exp(Sig0); 368 364 y1=FTCSE[iZ-1][enerInd]; 369 365 y2=FTCSE[iZ-1][enerInd+1]; 370 366 acoeff=(y2-y1)/(x2*x2-x1*x1); 371 367 bcoeff=y2-acoeff*x2*x2; 372 summ10=acoeff*logE*logE+bcoeff;373 summ10 =exp(summ10);368 Sig1=acoeff*logE*logE+bcoeff; 369 Sig1=std::exp(Sig1); 374 370 } 375 371 else //Interpolation of the form y=ax+b … … 379 375 y1=TCSE[iZ-1][104]; 380 376 y2=TCSE[iZ-1][105]; 381 summ00=(y2-y1)*(logE-x1)/(x2-x1)+y1;382 summ00 =exp(summ00);377 Sig0=(y2-y1)*(logE-x1)/(x2-x1)+y1; 378 Sig0=std::exp(Sig0); 383 379 y1=FTCSE[iZ-1][104]; 384 380 y2=FTCSE[iZ-1][105]; 385 summ10=(y2-y1)*(logE-x1)/(x2-x1)+y1;386 summ10 =exp(summ10);381 Sig1=(y2-y1)*(logE-x1)/(x2-x1)+y1; 382 Sig1=std::exp(Sig1); 387 383 } 388 384 } … … 397 393 acoeff=(y2-y1)/(x2*x2-x1*x1); 398 394 bcoeff=y2-acoeff*x2*x2; 399 summ00=acoeff*logE*logE+bcoeff;400 summ00 =exp(summ00);395 Sig0=acoeff*logE*logE+bcoeff; 396 Sig0 =std::exp(Sig0); 401 397 y1=FTCSP[iZ-1][enerInd]; 402 398 y2=FTCSP[iZ-1][enerInd+1]; 403 399 acoeff=(y2-y1)/(x2*x2-x1*x1); 404 400 bcoeff=y2-acoeff*x2*x2; 405 summ10=acoeff*logE*logE+bcoeff;406 summ10 =exp(summ10);401 Sig1=acoeff*logE*logE+bcoeff; 402 Sig1=std::exp(Sig1); 407 403 } 408 404 else … … 412 408 y1=TCSP[iZ-1][104]; 413 409 y2=TCSP[iZ-1][105]; 414 summ00=(y2-y1)*(logE-x1)/(x2-x1)+y1;415 summ00 =exp(summ00);410 Sig0=(y2-y1)*(logE-x1)/(x2-x1)+y1; 411 Sig0 =std::exp(Sig0); 416 412 y1=FTCSP[iZ-1][104]; 417 413 y2=FTCSP[iZ-1][105]; 418 summ10=(y2-y1)*(logE-x1)/(x2-x1)+y1;419 summ10 =exp(summ10);414 Sig1=(y2-y1)*(logE-x1)/(x2-x1)+y1; 415 Sig1=std::exp(Sig1); 420 416 } 421 417 } 422 418 423 summ00 *=barn; 424 summ10 *=barn; 425 426 Lam0=1./((1.+1./Z)*summ00); 427 Lam1=1./((1.+1./Z)*summ10); 428 429 } 430 431 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 432 //t->g->t step transformations taken from Ref.6 419 Sig0 *= barn; 420 Sig1 *= barn; 421 422 } 423 424 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 425 //t->g->t step transformations taken from Ref.6 433 426 434 427 G4double … … 635 628 636 629 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 637 630 // taken from Ref.6 638 631 G4double G4GoudsmitSaundersonMscModel::ComputeGeomPathLength(G4double) 639 632 { … … 688 681 if(samplez) { 689 682 690 const G4double ztmax = 0.99 , onethird = 1./3.;683 const G4double ztmax = 0.99; 691 684 G4double zt = zmean/tPathLength ; 692 685 … … 694 687 695 688 G4double u,cz1; 696 if(zt >= onethird) {689 if(zt >= 0.333333333) { 697 690 698 691 G4double cz = 0.5*(3.*zt-1.)/(1.-zt) ; … … 719 712 720 713 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 721 714 // taken from Ref.6 722 715 G4double 723 716 G4GoudsmitSaundersonMscModel::ComputeTrueStepLength(G4double geomStepLength)
Note: See TracChangeset
for help on using the changeset viewer.