120 G4bool G4GoudsmitSaundersonMscModel::fgIsUseAccurate = 
true;
 
  122 G4bool G4GoudsmitSaundersonMscModel::fgIsOptimizationOn = 
true;
 
  128   currentMaterialIndex = -1;
 
  130   lambdalimit   = 1.*
mm ;
 
  142   currentKinEnergy = 0.0;
 
  145   tlimitminfix2 = 1.*
nm;
 
  156   fIsUsePWATotalXsecData = 
false;
 
  164   fTheTrueStepLenght    = 0.;
 
  165   fTheTransportDistance = 0.;
 
  166   fTheZPathLenght       = 0.;
 
  167   fTheDisplacementVector.
set(0.,0.,0.);
 
  168   fTheNewDirection.
set(0.,0.,1.);
 
  170   fIsEverythingWasDone  = 
false;
 
  171   fIsMultipleSacettring = 
false;
 
  172   fIsSingleScattering   = 
false;
 
  173   fIsEndedUpOnBoundary  = 
false;
 
  174   fIsNoScatteringInMSC  = 
false;
 
  175   fIsNoDisplace         = 
false;
 
  176   fIsInsideSkin         = 
false;
 
  177   fIsWasOnBoundary      = 
false;
 
  178   fIsFirstRealStep      = 
false;
 
  183   rndmEngineMod = G4Random::getTheEngine();
 
  197       delete fgPWAXsecTable;
 
  231     if(fIsUsePWATotalXsecData) {
 
  250   if(efEnergy<lowKEnergy) efEnergy=lowKEnergy;
 
  251   if(efEnergy>highKEnergy)efEnergy=highKEnergy;
 
  261   if(fIsUsePWATotalXsecData) {
 
  269     for(
G4int i=0;i<nelm;i++){
 
  270       int zet    = 
G4lrint((*theElementVector)[i]->GetZ());
 
  272       int indx   = (
G4int)(1.5 + charge*1.5); 
 
  275       indx   = (
G4int)(2.5 + charge*1.5); 
 
  277       fLambda0 += (theAtomNumDensityVector[i]*elxsec);
 
  278       fLambda1 += (theAtomNumDensityVector[i]*t1xsec);
 
  280     if(fLambda0>0.0) { fLambda0 =1./fLambda0; }
 
  281     if(fLambda1>0.0) { fLambda1 =1./fLambda1; }
 
  285     if(fLambda1>0.0) { fG1 = fLambda0/fLambda1; }
 
  292     if(efEnergy<0.001) efEnergy = 0.001;
 
  302     fG1      = 2.0*fScrA*((1.0+fScrA)*
G4Log(1.0/fScrA+1.0)-1.0);
 
  303     fLambda1 = fLambda0/fG1;
 
  315   if(efEnergy<lowKEnergy) efEnergy=lowKEnergy;
 
  316   if(efEnergy>highKEnergy)efEnergy=highKEnergy;
 
  326   if(fIsUsePWATotalXsecData) {
 
  334     for(
G4int i=0;i<nelm;i++){
 
  335       int zet    = 
G4lrint((*theElementVector)[i]->GetZ());
 
  337       int indx   = (
G4int)(2.5 + charge*1.5); 
 
  339       lambda1 += (theAtomNumDensityVector[i]*t1xsec);
 
  341     if(lambda1>0.0) { lambda1 =1./lambda1; }
 
  347     if(efEnergy<0.001) efEnergy = 0.001;
 
  357     g1      = 2.0*scrA*((1.0+scrA)*
G4Log(1.0/scrA+1.0)-1.0);
 
  358     lambda1 = lambda0/g1;
 
  369   tlimit = tgeom = rangeinit = geombig;
 
  386   currentMaterialIndex = currentCouple->
GetIndex();
 
  388   currentRange = 
GetRange(particle,currentKinEnergy,currentCouple);
 
  399   fTheTrueStepLenght    = currentMinimalStep;
 
  400   fTheTransportDistance = currentMinimalStep;
 
  401   fTheZPathLenght       = currentMinimalStep;  
 
  402   fTheDisplacementVector.
set(0.,0.,0.);
 
  403   fTheNewDirection.
set(0.,0.,1.);
 
  406   fIsEverythingWasDone  = 
false;
 
  408   fIsMultipleSacettring = 
false;
 
  410   fIsSingleScattering   = 
false;
 
  412   fIsNoScatteringInMSC  = 
false;
 
  415   fIsNoDisplace = 
false;
 
  425   distance *= (1.20-fZeff*(1.62e-2-9.22e-5*fZeff));
 
  436   if( fgIsOptimizationOn && (distance < presafety) ) {
 
  438      fIsMultipleSacettring = 
true;
 
  439      fIsNoDisplace = 
true;
 
  456           fIsWasOnBoundary = 
true;
 
  459        skindepth = 
skin*fLambda0;
 
  462        fIsInsideSkin = 
false;
 
  468        if( (stepStatus == 
fGeomBoundary) || (presafety < skindepth) || (fTheTrueStepLenght < skindepth)){
 
  470          if( (stepStatus == 
fGeomBoundary) || (presafety < skindepth))
 
  471            fIsInsideSkin = 
true;
 
  483          if(sslimit < fTheTrueStepLenght) {
 
  484            fTheTrueStepLenght  = sslimit;
 
  485            fIsSingleScattering = 
true;
 
  489           fTheZPathLenght     = fTheTrueStepLenght;
 
  493           fIsEverythingWasDone = 
true;
 
  501          fIsMultipleSacettring = 
true;
 
  505          fIsFirstRealStep = 
false;
 
  509          if(fIsWasOnBoundary && !fIsInsideSkin){
 
  511              fIsWasOnBoundary = 
false;
 
  512              fIsFirstRealStep = 
true;
 
  522          if(firstStep || fIsFirstRealStep){
 
  523            rangeinit = currentRange;
 
  534            if(geomlimit < geombig){
 
  538                if((1.-geomlimit/fLambda1) > 0.)
 
  539                  geomlimit = -fLambda1*
G4Log(1.-geomlimit/fLambda1);
 
  567          if(geomlimit < geombig)
 
  568            tlimit = 
std::min(tlimit, geomlimit-0.999*skindepth);
 
  571          if(firstStep || fIsFirstRealStep) {
 
  572             fTheTrueStepLenght = 
std::min(fTheTrueStepLenght, Randomizetlimit());
 
  574            fTheTrueStepLenght = 
std::min(fTheTrueStepLenght, tlimit);
 
  579     geomlimit = presafety;
 
  582     skindepth = 
skin*fLambda0;
 
  588     if( (stepStatus == 
fGeomBoundary) || (presafety < skindepth) || (fTheTrueStepLenght < skindepth)){
 
  600       if(sslimit < fTheTrueStepLenght) {
 
  601         fTheTrueStepLenght  = sslimit;
 
  602         fIsSingleScattering = 
true;
 
  606        fTheZPathLenght     = fTheTrueStepLenght;
 
  610        fIsEverythingWasDone = 
true;
 
  615       fIsMultipleSacettring = 
true;
 
  616       fIsEverythingWasDone  = 
true;
 
  623       if(fTheTrueStepLenght > presafety)
 
  624         fTheTrueStepLenght = 
std::min(fTheTrueStepLenght, presafety);
 
  630       fTheTrueStepLenght = 
std::min(fTheTrueStepLenght, fLambda1*0.4);
 
  643     fIsMultipleSacettring = 
true;
 
  650       if( (distance < presafety) && (fgIsOptimizationOn)) {
 
  651         fIsNoDisplace = 
true;
 
  655           rangeinit = currentRange;
 
  671           fTheTrueStepLenght = 
std::min(fTheTrueStepLenght, Randomizetlimit());
 
  673           fTheTrueStepLenght = 
std::min(fTheTrueStepLenght, tlimit);
 
  682   if(fIsEverythingWasDone){
 
  683     if(fIsSingleScattering){
 
  688       sinPhi = std::sin(phi);
 
  689       cosPhi = std::cos(phi);
 
  690       fTheNewDirection.
set(sint*cosPhi,sint*sinPhi,cost);
 
  691     } 
else if(fIsMultipleSacettring){
 
  715   if(!fIsEverythingWasDone) {
 
  718      fTheTrueStepLenght = 
std::min(fTheTrueStepLenght,currentRange);
 
  721      fTheZPathLenght = fTheTrueStepLenght;
 
  724      if(fTheTrueStepLenght < tlimitminfix2) 
return fTheZPathLenght;
 
  726      G4double tau = fTheTrueStepLenght/fLambda1;
 
  728      if (tau <= tausmall) {
 
  729        fTheZPathLenght = 
std::min(fTheTrueStepLenght, fLambda1);
 
  730      } 
else  if (fTheTrueStepLenght < currentRange*
dtrl) {
 
  731        if(tau < taulim) fTheZPathLenght = fTheTrueStepLenght*(1.-0.5*tau) ;
 
  732        else             fTheZPathLenght = fLambda1*(1.-
G4Exp(-tau));
 
  733      } 
else if(currentKinEnergy < mass || fTheTrueStepLenght == currentRange)  {
 
  734        par1 = 1./currentRange ;     
 
  735        par2 = 1./(par1*fLambda1) ;  
 
  737        if(fTheTrueStepLenght < currentRange) {
 
  738            fTheZPathLenght = 1./(par1*par3) * (1.-std::pow(1.-par1*fTheTrueStepLenght,par3));
 
  740          fTheZPathLenght = 1./(par1*par3);
 
  744       G4double rfin = 
std::max(currentRange-fTheTrueStepLenght, 0.01*currentRange);
 
  746       G4double lambda1 = GetTransportMeanFreePathOnly(particle,T1);
 
  748       par1 = (fLambda1-lambda1)/(fLambda1*fTheTrueStepLenght);  
 
  749       par2 = 1./(par1*fLambda1);
 
  752       fTheZPathLenght = 1./(par1*par3) * (1.-g4calc->
powA(1.-par1*fTheTrueStepLenght,par3));
 
  755   fTheZPathLenght = 
std::min(fTheZPathLenght, fLambda1);
 
  757  return fTheZPathLenght;
 
  764   fIsEndedUpOnBoundary = 
false;
 
  767   if(geomStepLength == fTheZPathLenght) {
 
  768     return fTheTrueStepLenght;
 
  774   fIsEndedUpOnBoundary = 
true; 
 
  776   fTheZPathLenght = geomStepLength;
 
  779   if(fIsEverythingWasDone && !fIsMultipleSacettring) {
 
  780     fTheTrueStepLenght = geomStepLength;
 
  781     return fTheTrueStepLenght;
 
  785   if(geomStepLength < tlimitminfix2) {
 
  786     fTheTrueStepLenght = geomStepLength;
 
  790     if(geomStepLength > fLambda1*tausmall ) {
 
  792         tlength = -fLambda1*
G4Log(1.-geomStepLength/fLambda1) ;
 
  794        if(par1*par3*geomStepLength < 1.) {
 
  796            tlength = (1.-g4calc->
powA( 1.-par1*par3*geomStepLength,1./par3))/par1;
 
  798           tlength = currentRange;
 
  801      if(tlength < geomStepLength)   { tlength = geomStepLength; }
 
  802      else if(tlength > fTheTrueStepLenght) { tlength = geomStepLength; }
 
  804     fTheTrueStepLenght = tlength;
 
  806   return fTheTrueStepLenght;
 
  814       fTheNewDirection.
rotateUz(oldDirection);
 
  817       return fTheDisplacementVector;
 
  819       if(fIsEndedUpOnBoundary) {
 
  821         return fTheDisplacementVector;
 
  822       } 
else if(fIsEverythingWasDone) {
 
  824         if(fIsSingleScattering) {
 
  825           fTheNewDirection.
rotateUz(oldDirection);
 
  828           return fTheDisplacementVector;
 
  832         if(fIsMultipleSacettring && !fIsNoScatteringInMSC){
 
  833              fTheNewDirection.
rotateUz(oldDirection);
 
  834              fTheDisplacementVector.
rotateUz(oldDirection);
 
  840         return fTheDisplacementVector;
 
  850    if(!fIsNoScatteringInMSC) {
 
  851       fTheNewDirection.
rotateUz(oldDirection);
 
  854         fTheDisplacementVector.
rotateUz(oldDirection);
 
  856    return fTheDisplacementVector;
 
  863     G4double dum0  = 2.0*fScrA*rand1/(1.0 - rand1 + fScrA);
 
  865     if(dum0 < 0.0)       dum0 = 0.0;
 
  866     else if(dum0 > 2.0 ) dum0 = 2.0;
 
  869     sint = std::sqrt(dum0*(2.0 - dum0));
 
  875   fIsNoScatteringInMSC = 
false;
 
  877   G4double kineticEnergy = currentKinEnergy;
 
  883     eloss = kineticEnergy -
 
  884       GetEnergy(particle,currentRange-fTheTrueStepLenght,currentCouple);
 
  898   G4double efStep   = fTheTrueStepLenght;
 
  900   G4double kineticEnergy0 = kineticEnergy;
 
  901   if(fgIsUseAccurate) {    
 
  902      kineticEnergy -= 0.5*eloss;  
 
  907      eps0   = eloss/kineticEnergy0; 
 
  908      epsm   = eloss/kineticEnergy;  
 
  910       efEnergy       = kineticEnergy * (1. - epsm*epsm*(6.+10.*tau+5.*tau2)/(24.*tau2+48.*tau+72.));
 
  911       G4double dum  = 0.166666*(4.+tau*(6.+tau*(7.+tau*(4.+tau))))*
 
  912                      (epsm/((tau+1.)*(tau+2.)))*(epsm/((tau+1.)*(tau+2.)));
 
  913       efStep =fTheTrueStepLenght*(1.-dum);
 
  915       kineticEnergy -= 0.5*eloss;  
 
  916       efEnergy       = kineticEnergy;
 
  917       G4double factor = 1./(1. + 0.9784671*kineticEnergy); 
 
  918       eps0= eloss/kineticEnergy0;
 
  919       epsm= eps0/(1.-0.5*eps0);
 
  920       G4double temp   = 0.3*(1. - factor*(1. - 0.333333*factor))*eps0*eps0;
 
  921       efStep = fTheTrueStepLenght*(1. + temp);
 
  930   if(fLambda0>0.0) { lambdan=efStep/fLambda0; }
 
  931   if(lambdan<=1.0e-12) {
 
  932       if(fIsEverythingWasDone)
 
  933         fTheZPathLenght = fTheTrueStepLenght;
 
  934     fIsNoScatteringInMSC = 
true;
 
  939   if(!fIsUsePWATotalXsecData)  
 
  940     lambdan = lambdan/(1.+fScrA);
 
  947   G4double cosTheta1 =1.0,sinTheta1 =0.0, cosTheta2 =1.0, sinTheta2 =0.0;
 
  948   G4double cosPhi1=1.0,sinPhi1=0.0, cosPhi2 =1.0, sinPhi2 =0.0;
 
  949   G4double uss=0.0,vss=0.0,wss=1.0,x_coord=0.0,y_coord=0.0,z_coord=1.0;
 
  957     cosTheta1 = 1.-2.*vrand[0];
 
  958     sinTheta1 = std::sqrt((1.-cosTheta1)*(1.+cosTheta1));
 
  959     cosTheta2 = 1.-2.*vrand[1];
 
  960     sinTheta2 = std::sqrt((1.-cosTheta2)*(1.+cosTheta2));
 
  963      fgGSTable->
Sampling(0.5*lambdan, 0.5*Qn1, fScrA, cosTheta1, sinTheta1);
 
  964      fgGSTable->
Sampling(0.5*lambdan, 0.5*Qn1, fScrA, cosTheta2, sinTheta2);
 
  965      if(cosTheta1 + cosTheta2 == 2.) { 
 
  966         if(fIsEverythingWasDone)
 
  967            fTheZPathLenght = fTheTrueStepLenght;
 
  968         fIsNoScatteringInMSC = 
true;
 
  976   sinPhi1 = std::sin(phi1);
 
  977   cosPhi1 = std::cos(phi1);
 
  979   sinPhi2 = std::sin(phi2);
 
  980   cosPhi2 = std::cos(phi2);
 
  983   u2  = sinTheta2*cosPhi2;
 
  984   v2  = sinTheta2*sinPhi2;
 
  985   G4double u2p = cosTheta1*u2 + sinTheta1*cosTheta2;
 
  986   uss  = u2p*cosPhi1 - v2*sinPhi1;
 
  987   vss  = u2p*sinPhi1 + v2*cosPhi1;
 
  988   wss  = cosTheta1*cosTheta2 - sinTheta1*u2;
 
  991   fTheNewDirection.
set(uss,vss,wss);
 
  995   if(fIsNoDisplace && fIsEverythingWasDone)
 
  996     fTheZPathLenght = fTheTrueStepLenght;
 
 1004   if(fgIsUseAccurate) {
 
 1007      if(Qn1<0.7) par = 1.;
 
 1008      else if (Qn1<7.0) par = -0.031376*Qn1+1.01356;
 
 1015      G4double gamma  = 6.0*fScrA*(1.0 + fScrA)*(loga*(1.0 + 2.0*fScrA) - 2.0)/fG1;
 
 1023      G4double delta  = 0.9082483-(0.1020621-0.0263747*gamma)*Qn1;
 
 1027      G4double temp  = (2.0+tau*temp1)/((tau+1.0)*temp1);
 
 1029      temp = temp - (tau+1.0)/((tau+2.0)*(loga*(1.0+fScrA)-1.0));
 
 1032      delta = delta + 0.40824829*(eps0*(tau+1.0)/((tau+2.0)*
 
 1033              (loga*(1.0+fScrA)-1.0)*(loga*(1.0+2.0*fScrA)-2.0)) - 0.25*temp*temp);
 
 1040      G4double ut   = b*sinTheta1*cosPhi1 + c*(cosPhi1*u2 - sinPhi1*w1v2) + eta1*uss*temp1;
 
 1041      G4double vt   = b*sinTheta1*sinPhi1 + c*(sinPhi1*u2 + cosPhi1*w1v2) + eta1*vss*temp1;
 
 1042      G4double wt   = eta1*(1+temp) +       b*cosTheta1 +  c*cosTheta2    + eta1*wss*temp1;
 
 1051      x_coord = ut*fTheTrueStepLenght;
 
 1052      y_coord = vt*fTheTrueStepLenght;
 
 1053      z_coord = wt*fTheTrueStepLenght;
 
 1055      if(fIsEverythingWasDone){
 
 1059        G4double transportDistance  = std::sqrt(x_coord*x_coord+y_coord*y_coord+z_coord*z_coord);
 
 1061        if(transportDistance>fTheTrueStepLenght)
 
 1062           transportDistance = fTheTrueStepLenght;
 
 1063        fTheZPathLenght = transportDistance;
 
 1067      fTheDisplacementVector.
set(x_coord,y_coord,z_coord-fTheZPathLenght);
 
 1074      if(fIsEverythingWasDone){
 
 1078           zz = 1.0 - Qn1*(0.5 - Qn1*(0.166666667 - 0.041666667*Qn1)); 
 
 1080           zz = (1.-
G4Exp(-Qn1))/Qn1;
 
 1085         zz = fTheZPathLenght/fTheTrueStepLenght;
 
 1088      G4double rr = (1.-zz*zz)/(1.-wss*wss); 
 
 1089      if(rr >= 0.25) rr = 0.25;            
 
 1090      G4double rperp = fTheTrueStepLenght*std::sqrt(rr);  
 
 1091      x_coord  = rperp*uss;
 
 1092      y_coord  = rperp*vss;
 
 1093      z_coord  = zz*fTheTrueStepLenght;
 
 1095      if(fIsEverythingWasDone){
 
 1096        G4double transportDistance = std::sqrt(x_coord*x_coord + y_coord*y_coord + z_coord*z_coord);
 
 1097        fTheZPathLenght = transportDistance;
 
 1100      fTheDisplacementVector.
set(x_coord,y_coord,z_coord- fTheZPathLenght);
 
void set(double x, double y, double z)
 
static G4Pow * GetInstance()
 
G4GoudsmitSaundersonMscModel(const G4String &nam="GoudsmitSaunderson")
 
virtual G4double ComputeTrueStepLength(G4double geomStepLength)
 
G4double powA(G4double A, G4double y) const 
 
G4IonisParamMat * GetIonisation() const 
 
static G4LossTableManager * Instance()
 
static constexpr double mm
 
std::vector< G4Element * > G4ElementVector
 
G4double GetKineticEnergy() const 
 
const G4DynamicParticle * GetDynamicParticle() const 
 
G4StepStatus GetStepStatus() const 
 
G4double ConvertTrueToGeom(G4double &tLength, G4double &gLength)
 
const G4MaterialCutsCouple * GetMaterialCutsCouple() const 
 
G4ParticleDefinition * GetDefinition() const 
 
const G4Step * GetStep() const 
 
G4double ComputeSafety(const G4ThreeVector &position, G4double limit=DBL_MAX)
 
const G4ElementVector * GetElementVector() const 
 
G4double GetZeffective() const 
 
G4int GetPWATotalXsecEnergyBinIndex(G4double energy) const 
 
const G4PWATotalXsecZ * GetPWATotalXsecForZet(G4int Z) 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 
 
void SingleScattering(G4double &cost, G4double &sint)
 
const G4ThreeVector & GetPosition() const 
 
G4double GetRange(const G4ParticleDefinition *part, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
 
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
 
Hep3Vector & rotateUz(const Hep3Vector &)
 
void Sampling(G4double, G4double, G4double, G4double &, G4double &)
 
G4double ComputeGeomLimit(const G4Track &, G4double &presafety, G4double limit)
 
G4double G4Log(G4double x)
 
G4double G4Exp(G4double initial_x)
Exponential Function double precision. 
 
G4ParticleChangeForMSC * GetParticleChangeForMSC(const G4ParticleDefinition *p=nullptr)
 
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
 
G4double GetMoliereXc2(G4int matindx)
 
T max(const T t1, const T t2)
brief Return the largest of the two arguments 
 
static constexpr double nm
 
void SetCurrentCouple(const G4MaterialCutsCouple *)
 
virtual ~G4GoudsmitSaundersonMscModel()
 
G4double GetMoliereBc(G4int matindx)
 
T min(const T t1, const T t2)
brief Return the smallest of the two arguments 
 
static constexpr double GeV
 
G4double GetSafety() const 
 
G4MscStepLimitType steppingAlgorithm
 
size_t GetNumberOfElements() const 
 
G4double GetTransportMeanFreePath(const G4ParticleDefinition *, G4double)
 
virtual G4ThreeVector & SampleScattering(const G4ThreeVector &, G4double safety)
 
virtual void flatArray(const int size, double *vect)=0
 
static constexpr double keV
 
G4double GetScreeningParam(G4double)
 
static constexpr double twopi
 
const G4Material * GetMaterial() const 
 
virtual G4double ComputeGeomPathLength(G4double truePathLength)