90 G4double G4GoudsmitSaundersonMscModel::ener[] = {-1.};
91 G4double G4GoudsmitSaundersonMscModel::TCSE[103][106] ;
92 G4double G4GoudsmitSaundersonMscModel::FTCSE[103][106] ;
93 G4double G4GoudsmitSaundersonMscModel::TCSP[103][106] ;
94 G4double G4GoudsmitSaundersonMscModel::FTCSP[103][106] ;
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);
157 G4double kineticEnergy = currentKinEnergy;
159 if((kineticEnergy <= 0.0) || (tPathLength <= tlimitminfix)||
165 if (tPathLength > currentRange*
dtrl) {
166 eloss = kineticEnergy -
167 GetEnergy(particle,currentRange-tPathLength,currentCouple);
169 eloss = tPathLength*
GetDEDX(particle,kineticEnergy,currentCouple);
178 kineticEnergy -= 0.5*eloss;
188 for(
G4int i=0;i<nelm;i++)
190 CalculateIntegrals(particle,(*theElementVector)[i]->GetZ(),kineticEnergy,
s0,s1);
191 lambda0 += (theAtomNumDensityVector[i]*
s0);
193 if(lambda0>0.0) lambda0 =1./lambda0;
198 if(lambda1>0.0) { g1 = lambda0/lambda1; }
203 for(
G4int i=0;i<1000;++i)
205 logx0=std::log(1.+1./x0);
206 x1 = x0-(x0*((1.+x0)*logx0-1.0)-g1*0.5)/( (1.+2.*x0)*logx0-2.0);
209 if(x1 < 0.0) { x1 = 0.5*x0; }
210 else if(x1 > 2*x0) { x1 = 2*x0; }
211 else if(x1 < 0.5*x0) { x1 = 0.5*x0; }
212 delta = std::fabs( x1 - x0 );
214 if(delta < 1.0e-3*x1) {
break;}
220 if(lambda0>0.0) { lambdan=tPathLength/lambda0; }
229 G4double cosTheta1,sinTheta1,cosTheta2,sinTheta2;
230 G4double cosPhi1=1.0,sinPhi1=0.0,cosPhi2=1.0,sinPhi2=0.0;
231 G4double us=0.0,vs=0.0,ws=1.0,wss=0.,x_coord=0.0,y_coord=0.0,z_coord=1.0;
238 else if((epsilon1<((1.+lambdan)*expn))||(lambdan<1.))
241 xi= 2.*scrA*xi/(1.-xi + scrA);
245 wss=std::sqrt(xi*(2.-xi));
254 SampleCosineTheta(0.5*lambdan,scrA,cosTheta1,sinTheta1);
260 SampleCosineTheta(0.5*lambdan,scrA,cosTheta2,sinTheta2);
266 us = sinTheta2*(cosTheta1*cosPhi1*cosPhi2 - sinPhi1*sinPhi2) + cosTheta2*sinTheta1*cosPhi1;
267 vs = sinTheta2*(cosTheta1*sinPhi1*cosPhi2 + cosPhi1*sinPhi2) + cosTheta2*sinTheta1*sinPhi1;
268 ws = cosTheta1*cosTheta2 - sinTheta1*sinTheta2*cosPhi2;
275 }
while((fabs(ws)>1.)&&(i<20));
276 if(i>=19)ws=cos(sqrtA);
277 wss=std::sqrt((1.-ws*ws));
278 us=wss*std::cos(phi1);
279 vs=wss*std::sin(phi1);
285 newDirection.
rotateUz(oldDirection);
289 if(Qn1<0.02) { z_coord = 1.0 - Qn1*(0.5 - Qn1/6.); }
290 else { z_coord = (1.-std::exp(-Qn1))/Qn1; }
291 G4double rr = zPathLength*std::sqrt((1.- z_coord*z_coord)/(1.-ws*ws));
297 z_coord *= zPathLength;
315 G4GoudsmitSaundersonMscModel::SampleCosineTheta(
G4double lambdan,
G4double scrA,
320 if(scrA < 10.) { Qn1 *= scrA*((1.+scrA)*log(1.+1./scrA)-1.); }
321 else { Qn1*= (1.0 - 0.5/scrA - 0.5/(scrA*scrA)) ; }
328 }
while(tet*r1*r1>sin(tet));
338 sint=sqrt(xi*(2.-xi));
353 if(kineticE<lowKEnergy)kineticE=lowKEnergy;
354 if(kineticE>highKEnergy)kineticE=highKEnergy;
359 if(iZ > 103) iZ = 103;
362 for(
G4int i=0;i<105;i++)
364 if((logE>=ener[i])&&(logE<ener[i+1])){enerInd=i;
break;}
373 y1=TCSE[iZ-1][enerInd];
374 y2=TCSE[iZ-1][enerInd+1];
375 acoeff=(y2-
y1)/(x2*x2-x1*x1);
376 bcoeff=y2-acoeff*x2*
x2;
377 Sig0=acoeff*logE*logE+bcoeff;
378 Sig0 =std::exp(Sig0);
379 y1=FTCSE[iZ-1][enerInd];
380 y2=FTCSE[iZ-1][enerInd+1];
381 acoeff=(y2-
y1)/(x2*x2-x1*x1);
382 bcoeff=y2-acoeff*x2*
x2;
383 Sig1=acoeff*logE*logE+bcoeff;
392 Sig0=(y2-
y1)*(logE-x1)/(x2-
x1)+y1;
396 Sig1=(y2-
y1)*(logE-x1)/(x2-
x1)+y1;
402 if(kinEnergy<=1.0e+9)
406 y1=TCSP[iZ-1][enerInd];
407 y2=TCSP[iZ-1][enerInd+1];
408 acoeff=(y2-
y1)/(x2*x2-x1*x1);
409 bcoeff=y2-acoeff*x2*
x2;
410 Sig0=acoeff*logE*logE+bcoeff;
411 Sig0 =std::exp(Sig0);
412 y1=FTCSP[iZ-1][enerInd];
413 y2=FTCSP[iZ-1][enerInd+1];
414 acoeff=(y2-
y1)/(x2*x2-x1*x1);
415 bcoeff=y2-acoeff*x2*
x2;
416 Sig1=acoeff*logE*logE+bcoeff;
425 Sig0=(y2-
y1)*(logE-x1)/(x2-
x1)+y1;
426 Sig0 =std::exp(Sig0);
429 Sig1=(y2-
y1)*(logE-x1)/(x2-
x1)+y1;
457 tPathLength = currentMinimalStep;
463 currentMaterialIndex = currentCouple->
GetIndex();
465 currentRange =
GetRange(particle,currentKinEnergy,currentCouple);
470 if(inside || tPathLength < tlimitminfix) {
473 if(tPathLength > currentRange) tPathLength = currentRange;
483 if(currentRange < presafety)
497 if(currentRange <= presafety)
508 rangeinit = currentRange;
509 if(firstStep) smallstep = 1.e10;
515 rat = 1.e-3/(rat*(10.+rat)) ;
517 stepmin = rat*lambda1;
518 skindepth =
skin*stepmin;
520 tlimitmin = 10.*stepmin;
521 if(tlimitmin < tlimitminfix) tlimitmin = tlimitminfix;
526 if((geomlimit < geombig) && (geomlimit > geommin))
544 if(tlimit < tlimitmin) tlimit = tlimitmin;
546 if(tlimit > tgeom) tlimit = tgeom;
552 if((tPathLength < tlimit) && (tPathLength < presafety) &&
553 (smallstep >=
skin) && (tPathLength < geomlimit-0.999*skindepth))
562 else if(geomlimit < geombig)
564 if(geomlimit > skindepth)
566 if(tlimit > geomlimit-0.999*skindepth)
567 tlimit = geomlimit-0.999*skindepth;
572 if(tlimit > stepmin) tlimit = stepmin;
576 if(tlimit < stepmin) tlimit = stepmin;
578 if(tPathLength > tlimit) tPathLength = tlimit;
587 if((stepStatus !=
fGeomBoundary) && (presafety < tlimitminfix))
591 if(currentRange < presafety)
599 rangeinit = currentRange;
602 if(mass < masslimite)
604 if(lambda1 > currentRange)
606 if(lambda1 > lambdalimit)
607 fr *= 0.75+0.25*lambda1/lambdalimit;
612 rat = 1.e-3/(rat*(10.+rat)) ;
613 tlimitmin = 10.*lambda1*rat;
614 if(tlimitmin < tlimitminfix) tlimitmin = tlimitminfix;
617 tlimit = fr*rangeinit;
623 if(tlimit < tlimitmin) tlimit = tlimitmin;
625 if(tPathLength > tlimit) tPathLength = tlimit;
633 if (currentRange > lambda1) tlimit =
facrange*currentRange;
636 if(tlimit < tlimitmin) tlimit = tlimitmin;
637 if(tPathLength > tlimit) tPathLength = tlimit;
654 zPathLength = tPathLength;
657 if(tPathLength < tlimitminfix) {
return zPathLength; }
661 if(tPathLength > currentRange)
662 { tPathLength = currentRange; }
664 G4double tau = tPathLength/lambda1 ;
666 if ((tau <= tausmall) || insideskin) {
667 zPathLength = tPathLength;
668 if(zPathLength > lambda1) { zPathLength = lambda1; }
673 if (tPathLength < currentRange*
dtrl) {
674 if(tau < taulim) zmean = tPathLength*(1.-0.5*tau) ;
675 else zmean = lambda1*(1.-exp(-tau));
676 }
else if(currentKinEnergy < mass || tPathLength == currentRange) {
677 par1 = 1./currentRange ;
678 par2 = 1./(par1*lambda1) ;
680 if(tPathLength < currentRange)
681 zmean = (1.-exp(par3*log(1.-tPathLength/currentRange)))/(par1*par3) ;
683 zmean = 1./(par1*par3) ;
689 par1 = (lambda1-lambda11)/(lambda1*tPathLength) ;
690 par2 = 1./(par1*lambda1) ;
692 zmean = (1.-exp(par3*log(lambda11/lambda1)))/(par1*par3) ;
695 zPathLength = zmean ;
702 if (tPathLength > stepmin && zt < ztmax) {
705 if(zt >= 0.333333333) {
707 G4double cz = 0.5*(3.*zt-1.)/(1.-zt) ;
713 grej = exp(cz*log(u/u0))*(1.-u)/(1.-u0) ;
720 zPathLength = tPathLength*u ;
723 if(zPathLength > lambda1) zPathLength = lambda1;
735 if(geomStepLength == zPathLength && tPathLength <= currentRange)
739 zPathLength = geomStepLength;
740 tPathLength = geomStepLength;
741 if(geomStepLength < tlimitminfix)
return tPathLength;
744 if((geomStepLength > lambda1*tausmall) && !insideskin)
747 tPathLength = -lambda1*log(1.-geomStepLength/lambda1) ;
750 if(par1*par3*geomStepLength < 1.)
751 tPathLength = (1.-exp(log(1.-par1*par3*geomStepLength)/par3))/par1 ;
753 tPathLength = currentRange;
756 if(tPathLength < geomStepLength) tPathLength = geomStepLength;
765 void G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()
767 G4String filename =
"XSECTIONS.dat";
769 char* path = getenv(
"G4LEDATA");
772 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
"em0006",
774 "Environment variable G4LEDATA not defined");
779 G4String dirFile = pathString +
"/msc_GS/" + filename;
780 FILE *infile = fopen(dirFile,
"r");
784 ed <<
"Data file <" + dirFile +
"> is not opened!";
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;
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
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
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
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
862 G4Exception(
"G4GoudsmitSaundersonMscModel::LoadELSEPAXSections()",
void set(double x, double y, double z)
G4GoudsmitSaundersonMscModel(const G4String &nam="GoudsmitSaunderson")
virtual G4double ComputeTrueStepLength(G4double geomStepLength)
static G4LossTableManager * Instance()
std::vector< G4Element * > G4ElementVector
std::ostringstream G4ExceptionDescription
G4double GetKineticEnergy() const
const G4DynamicParticle * GetDynamicParticle() const
G4StepStatus GetStepStatus() const
G4double ConvertTrueToGeom(G4double &tLength, G4double &gLength)
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
G4double SampleTheta(G4double, G4double, G4double)
G4ParticleDefinition * GetDefinition() const
const G4Step * GetStep() const
const G4ElementVector * GetElementVector() const
G4StepPoint * GetPreStepPoint() const
G4double GetEnergy(const G4ParticleDefinition *part, G4double range, const G4MaterialCutsCouple *couple)
void StartTracking(G4Track *)
virtual G4double ComputeTruePathLengthLimit(const G4Track &track, G4double ¤tMinimalStep)
const G4double * GetVecNbOfAtomsPerVolume() const
G4GLOB_DLL std::ostream G4cout
const G4ThreeVector & GetPosition() const
G4double GetRange(const G4ParticleDefinition *part, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
G4ParticleChangeForMSC * GetParticleChangeForMSC(const G4ParticleDefinition *p=0)
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
Hep3Vector & rotateUz(const Hep3Vector &)
G4double ComputeGeomLimit(const G4Track &, G4double &presafety, G4double limit)
G4ThreeVector fDisplacement
G4double GetTransportMeanFreePath(const G4ParticleDefinition *part, G4double kinEnergy)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4double ComputeSafety(const G4ThreeVector &position, G4double limit)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
static G4Positron * Positron()
G4double GetDEDX(const G4ParticleDefinition *part, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
void SetCurrentCouple(const G4MaterialCutsCouple *)
virtual ~G4GoudsmitSaundersonMscModel()
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *particle, G4double KineticEnergy, G4double AtomicNumber, G4double, G4double, G4double)
G4double GetSafety() const
G4MscStepLimitType steppingAlgorithm
static G4Electron * Electron()
size_t GetNumberOfElements() const
virtual G4ThreeVector & SampleScattering(const G4ThreeVector &, G4double safety)
const G4Material * GetMaterial() const
virtual G4double ComputeGeomPathLength(G4double truePathLength)