90G4double G4GoudsmitSaundersonMscModel::ener[] = {-1.};
91G4double G4GoudsmitSaundersonMscModel::TCSE[103][106] ;
92G4double G4GoudsmitSaundersonMscModel::FTCSE[103][106] ;
93G4double G4GoudsmitSaundersonMscModel::TCSP[103][106] ;
94G4double G4GoudsmitSaundersonMscModel::FTCSP[103][106] ;
98 :
G4VMscModel(nam),lowKEnergy(0.1*keV),highKEnergy(100.*TeV)
100 currentKinEnergy=currentRange=skindepth=par1=par2=par3
101 =zPathLength=truePathLength
102 =tausmall=taulim=tlimit=charge=lambdalimit=tPathLength=lambda0=lambda1
104 currentMaterialIndex = -1;
106 fr=0.02,rangeinit=0.,masslimite=0.6*MeV,
107 particle=0;tausmall=1.e-16;taulim=1.e-6;tlimit=1.e10*mm;
108 tlimitmin=10.e-6*mm;geombig=1.e50*mm;geommin=1.e-3*mm,tgeom=geombig;
109 tlimitminfix=1.e-6*mm;stepmin=tlimitminfix;lambdalimit=1.*mm;smallstep=1.e10;
111 inside=
false;insideskin=
false;
118 G4cout <<
"### G4GoudsmitSaundersonMscModel loading ELSEPA data" <<
G4endl;
119 LoadELSEPAXSections();
131 skindepth=
skin*stepmin;
143 if(kinEnergy<lowKEnergy) kinEnergy=lowKEnergy;
144 if(kinEnergy>highKEnergy)kinEnergy=highKEnergy;
147 CalculateIntegrals(p,Z,kinEnergy,cs0,cs);
158 if((kineticEnergy <= 0.0) || (tPathLength <= tlimitminfix)||
164 if (tPathLength > currentRange*
dtrl) {
165 eloss = kineticEnergy -
166 GetEnergy(particle,currentRange-tPathLength,currentCouple);
168 eloss = tPathLength*
GetDEDX(particle,kineticEnergy,currentCouple);
177 kineticEnergy -= 0.5*eloss;
187 for(
G4int i=0;i<nelm;i++)
189 CalculateIntegrals(particle,(*theElementVector)[i]->GetZ(),kineticEnergy,s0,s1);
190 lambda0 += (theAtomNumDensityVector[i]*s0);
192 if(lambda0>0.0) lambda0 =1./lambda0;
197 if(lambda1>0.0) { g1 = lambda0/lambda1; }
202 for(
G4int i=0;i<1000;++i)
204 logx0=std::log(1.+1./x0);
205 x1 = x0-(x0*((1.+x0)*logx0-1.0)-g1*0.5)/( (1.+2.*x0)*logx0-2.0);
208 if(x1 < 0.0) { x1 = 0.5*x0; }
209 else if(x1 > 2*x0) { x1 = 2*x0; }
210 else if(x1 < 0.5*x0) { x1 = 0.5*x0; }
211 delta = std::fabs( x1 - x0 );
213 if(delta < 1.0e-3*x1) {
break;}
219 if(lambda0>0.0) { lambdan=tPathLength/lambda0; }
228 G4double cosTheta1,sinTheta1,cosTheta2,sinTheta2;
229 G4double cosPhi1=1.0,sinPhi1=0.0,cosPhi2=1.0,sinPhi2=0.0;
230 G4double us=0.0,vs=0.0,ws=1.0,wss=0.,x_coord=0.0,y_coord=0.0,z_coord=1.0;
237 else if((epsilon1<((1.+lambdan)*expn))||(lambdan<1.))
240 xi= 2.*scrA*xi/(1.-xi + scrA);
244 wss=std::sqrt(xi*(2.-xi));
253 SampleCosineTheta(0.5*lambdan,scrA,cosTheta1,sinTheta1);
259 SampleCosineTheta(0.5*lambdan,scrA,cosTheta2,sinTheta2);
265 us = sinTheta2*(cosTheta1*cosPhi1*cosPhi2 - sinPhi1*sinPhi2) + cosTheta2*sinTheta1*cosPhi1;
266 vs = sinTheta2*(cosTheta1*sinPhi1*cosPhi2 + cosPhi1*sinPhi2) + cosTheta2*sinTheta1*sinPhi1;
267 ws = cosTheta1*cosTheta2 - sinTheta1*sinTheta2*cosPhi2;
274 }
while((fabs(ws)>1.)&&(i<20));
275 if(i>=19)ws=cos(sqrtA);
276 wss=std::sqrt((1.-ws*ws));
277 us=wss*std::cos(phi1);
278 vs=wss*std::sin(phi1);
284 newDirection.
rotateUz(oldDirection);
288 if(Qn1<0.02) { z_coord = 1.0 - Qn1*(0.5 - Qn1/6.); }
289 else { z_coord = (1.-std::exp(-Qn1))/Qn1; }
290 G4double rr = zPathLength*std::sqrt((1.- z_coord*z_coord)/(1.-ws*ws));
296 z_coord *= zPathLength;
314G4GoudsmitSaundersonMscModel::SampleCosineTheta(
G4double lambdan,
G4double scrA,
319 if(scrA < 10.) { Qn1 *= scrA*((1.+scrA)*log(1.+1./scrA)-1.); }
320 else { Qn1*= (1.0 - 0.5/scrA - 0.5/(scrA*scrA)) ; }
327 }
while(tet*r1*r1>sin(tet));
337 sint=sqrt(xi*(2.-xi));
352 if(kineticE<lowKEnergy)kineticE=lowKEnergy;
353 if(kineticE>highKEnergy)kineticE=highKEnergy;
358 if(iZ > 103) iZ = 103;
361 for(
G4int i=0;i<105;i++)
363 if((logE>=ener[i])&&(logE<ener[i+1])){enerInd=i;
break;}
372 y1=TCSE[iZ-1][enerInd];
373 y2=TCSE[iZ-1][enerInd+1];
374 acoeff=(y2-y1)/(x2*x2-x1*x1);
375 bcoeff=y2-acoeff*x2*x2;
376 Sig0=acoeff*logE*logE+bcoeff;
377 Sig0 =std::exp(Sig0);
378 y1=FTCSE[iZ-1][enerInd];
379 y2=FTCSE[iZ-1][enerInd+1];
380 acoeff=(y2-y1)/(x2*x2-x1*x1);
381 bcoeff=y2-acoeff*x2*x2;
382 Sig1=acoeff*logE*logE+bcoeff;
391 Sig0=(y2-y1)*(logE-x1)/(x2-x1)+y1;
395 Sig1=(y2-y1)*(logE-x1)/(x2-x1)+y1;
401 if(kinEnergy<=1.0e+9)
405 y1=TCSP[iZ-1][enerInd];
406 y2=TCSP[iZ-1][enerInd+1];
407 acoeff=(y2-y1)/(x2*x2-x1*x1);
408 bcoeff=y2-acoeff*x2*x2;
409 Sig0=acoeff*logE*logE+bcoeff;
410 Sig0 =std::exp(Sig0);
411 y1=FTCSP[iZ-1][enerInd];
412 y2=FTCSP[iZ-1][enerInd+1];
413 acoeff=(y2-y1)/(x2*x2-x1*x1);
414 bcoeff=y2-acoeff*x2*x2;
415 Sig1=acoeff*logE*logE+bcoeff;
424 Sig0=(y2-y1)*(logE-x1)/(x2-x1)+y1;
425 Sig0 =std::exp(Sig0);
428 Sig1=(y2-y1)*(logE-x1)/(x2-x1)+y1;
456 tPathLength = currentMinimalStep;
462 currentMaterialIndex = currentCouple->
GetIndex();
464 currentRange =
GetRange(particle,currentKinEnergy,currentCouple);
469 if(inside || tPathLength < tlimitminfix) {
472 if(tPathLength > currentRange) tPathLength = currentRange;
474 G4double presafety = sp->GetSafety();
482 if(currentRange < presafety)
496 if(currentRange <= presafety)
507 rangeinit = currentRange;
508 if(firstStep) smallstep = 1.e10;
513 G4double rat = currentKinEnergy/MeV ;
514 rat = 1.e-3/(rat*(10.+rat)) ;
516 stepmin = rat*lambda1;
517 skindepth =
skin*stepmin;
519 tlimitmin = 10.*stepmin;
520 if(tlimitmin < tlimitminfix) tlimitmin = tlimitminfix;
525 if((geomlimit < geombig) && (geomlimit > geommin))
543 if(tlimit < tlimitmin) tlimit = tlimitmin;
545 if(tlimit > tgeom) tlimit = tgeom;
551 if((tPathLength < tlimit) && (tPathLength < presafety) &&
552 (smallstep >=
skin) && (tPathLength < geomlimit-0.999*skindepth))
561 else if(geomlimit < geombig)
563 if(geomlimit > skindepth)
565 if(tlimit > geomlimit-0.999*skindepth)
566 tlimit = geomlimit-0.999*skindepth;
571 if(tlimit > stepmin) tlimit = stepmin;
575 if(tlimit < stepmin) tlimit = stepmin;
577 if(tPathLength > tlimit) tPathLength = tlimit;
586 if((stepStatus !=
fGeomBoundary) && (presafety < tlimitminfix))
590 if(currentRange < presafety)
598 rangeinit = currentRange;
601 if(mass < masslimite)
603 if(lambda1 > currentRange)
605 if(lambda1 > lambdalimit)
606 fr *= 0.75+0.25*lambda1/lambdalimit;
610 G4double rat = currentKinEnergy/MeV ;
611 rat = 1.e-3/(rat*(10.+rat)) ;
612 tlimitmin = 10.*lambda1*rat;
613 if(tlimitmin < tlimitminfix) tlimitmin = tlimitminfix;
616 tlimit = fr*rangeinit;
622 if(tlimit < tlimitmin) tlimit = tlimitmin;
624 if(tPathLength > tlimit) tPathLength = tlimit;
632 if (currentRange > lambda1) tlimit =
facrange*currentRange;
635 if(tlimit < tlimitmin) tlimit = tlimitmin;
636 if(tPathLength > tlimit) tPathLength = tlimit;
653 zPathLength = tPathLength;
656 if(tPathLength < tlimitminfix) {
return zPathLength; }
660 if(tPathLength > currentRange)
661 { tPathLength = currentRange; }
663 G4double tau = tPathLength/lambda1 ;
665 if ((tau <= tausmall) || insideskin) {
666 zPathLength = tPathLength;
667 if(zPathLength > lambda1) { zPathLength = lambda1; }
672 if (tPathLength < currentRange*
dtrl) {
673 if(tau < taulim) zmean = tPathLength*(1.-0.5*tau) ;
674 else zmean = lambda1*(1.-exp(-tau));
675 }
else if(currentKinEnergy < mass || tPathLength == currentRange) {
676 par1 = 1./currentRange ;
677 par2 = 1./(par1*lambda1) ;
679 if(tPathLength < currentRange)
680 zmean = (1.-exp(par3*log(1.-tPathLength/currentRange)))/(par1*par3) ;
682 zmean = 1./(par1*par3) ;
688 par1 = (lambda1-lambda11)/(lambda1*tPathLength) ;
689 par2 = 1./(par1*lambda1) ;
691 zmean = (1.-exp(par3*log(lambda11/lambda1)))/(par1*par3) ;
694 zPathLength = zmean ;
701 if (tPathLength > stepmin && zt < ztmax) {
704 if(zt >= 0.333333333) {
706 G4double cz = 0.5*(3.*zt-1.)/(1.-zt) ;
712 grej = exp(cz*log(u/u0))*(1.-u)/(1.-u0) ;
719 zPathLength = tPathLength*u ;
722 if(zPathLength > lambda1) zPathLength = lambda1;
734 if(geomStepLength == zPathLength && tPathLength <= currentRange)
738 zPathLength = geomStepLength;
739 tPathLength = geomStepLength;
740 if(geomStepLength < tlimitminfix)
return tPathLength;
743 if((geomStepLength > lambda1*tausmall) && !insideskin)
746 tPathLength = -lambda1*log(1.-geomStepLength/lambda1) ;
749 if(par1*par3*geomStepLength < 1.)
750 tPathLength = (1.-exp(log(1.-par1*par3*geomStepLength)/par3))/par1 ;
752 tPathLength = currentRange;
755 if(tPathLength < geomStepLength) tPathLength = geomStepLength;
764void G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()
766 G4String filename =
"XSECTIONS.dat";
768 char* path = getenv(
"G4LEDATA");
771 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
"em0006",
773 "Environment variable G4LEDATA not defined");
778 G4String dirFile = pathString +
"/msc_GS/" + filename;
780 infile = fopen(dirFile,
"r");
784 ed <<
"Data file <" + dirFile +
"> is not opened!" <<
G4endl;
785 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
792 for(
G4int i=0 ; i<106 ;i++){
793 if(1 == fscanf(infile,
"%f\t",&aRead)) {
794 if(aRead > 0.0) { aRead = log(aRead); }
795 else { aRead = 0.0; }
798 ed <<
"Error reading <" + dirFile +
"> loop #1 i= " << i <<
G4endl;
799 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
805 for(
G4int j=0;j<103;j++){
806 for(
G4int i=0;i<106;i++){
807 if(1 == fscanf(infile,
"%f\t",&aRead)) {
808 if(aRead > 0.0) { aRead = log(aRead); }
809 else { aRead = 0.0; }
812 ed <<
"Error reading <" + dirFile +
"> loop #2 j= " << j
813 <<
"; i= " << i <<
G4endl;
814 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
821 for(
G4int j=0;j<103;j++){
822 for(
G4int i=0;i<106;i++){
823 if(1 == fscanf(infile,
"%f\t",&aRead)) {
824 if(aRead > 0.0) { aRead = log(aRead); }
825 else { aRead = 0.0; }
828 ed <<
"Error reading <" + dirFile +
"> loop #3 j= " << j
829 <<
"; i= " << i <<
G4endl;
830 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
837 for(
G4int j=0;j<103;j++){
838 for(
G4int i=0;i<106;i++){
839 if(1 == fscanf(infile,
"%f\t",&aRead)) {
840 if(aRead > 0.0) { aRead = log(aRead); }
841 else { aRead = 0.0; }
844 ed <<
"Error reading <" + dirFile +
"> loop #4 j= " << j
845 <<
"; i= " << i <<
G4endl;
846 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
853 for(
G4int j=0;j<103;j++){
854 for(
G4int i=0;i<106;i++){
855 if(1 == fscanf(infile,
"%f\t",&aRead)) {
856 if(aRead > 0.0) { aRead = log(aRead); }
857 else { aRead = 0.0; }
860 ed <<
"Error reading <" + dirFile +
"> loop #5 j= " << j
861 <<
"; i= " << i <<
G4endl;
862 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
std::vector< G4Element * > G4ElementVector
G4DLLIMPORT std::ostream G4cout
void set(double x, double y, double z)
Hep3Vector & rotateUz(const Hep3Vector &)
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Electron * Electron()
virtual G4double ComputeTruePathLengthLimit(const G4Track &track, G4double ¤tMinimalStep)
G4GoudsmitSaundersonMscModel(const G4String &nam="GoudsmitSaunderson")
void StartTracking(G4Track *)
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
virtual G4double ComputeTrueStepLength(G4double geomStepLength)
virtual G4ThreeVector & SampleScattering(const G4DynamicParticle *, G4double safety)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *particle, G4double KineticEnergy, G4double AtomicNumber, G4double, G4double, G4double)
virtual G4double ComputeGeomPathLength(G4double truePathLength)
virtual ~G4GoudsmitSaundersonMscModel()
G4double SampleTheta(G4double, G4double, G4double)
static G4LossTableManager * Instance()
const G4Material * GetMaterial() const
const G4ElementVector * GetElementVector() const
size_t GetNumberOfElements() const
const G4double * GetVecNbOfAtomsPerVolume() const
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
static G4Positron * Positron()
G4StepPoint * GetPreStepPoint() const
const G4DynamicParticle * GetDynamicParticle() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
const G4Step * GetStep() const
void SetCurrentCouple(const G4MaterialCutsCouple *)
G4double GetDEDX(const G4ParticleDefinition *part, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
G4double ComputeGeomLimit(const G4Track &, G4double &presafety, G4double limit)
G4double GetTransportMeanFreePath(const G4ParticleDefinition *part, G4double kinEnergy)
G4double GetEnergy(const G4ParticleDefinition *part, G4double range, const G4MaterialCutsCouple *couple)
G4double GetRange(const G4ParticleDefinition *part, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
G4double ComputeSafety(const G4ThreeVector &position, G4double limit)
G4MscStepLimitType steppingAlgorithm
G4ParticleChangeForMSC * GetParticleChangeForMSC(const G4ParticleDefinition *p=0)
G4double ConvertTrueToGeom(G4double &tLength, G4double &gLength)
G4ThreeVector fDisplacement
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
std::ostringstream G4ExceptionDescription