47 #include "G4VParticleChange.hh" 70 fGammaCutInKineticEnergy(0),
76 fAngleForEnergyTable(0)
113 G4cout<<
"### G4VXTRenergyLoss: the number of TR radiator plates = " 117 G4Exception(
"G4VXTRenergyLoss::G4VXTRenergyLoss()",
"VXTRELoss01",
207 G4double charge, chargeSq, massRatio, TkinScaled;
210 *condition = NotForced;
218 gamma = 1.0 + kinEnergy/mass;
224 if ( std::fabs( gamma -
fGamma ) < 0.05*gamma ) lambda =
fLambda;
228 chargeSq = charge*charge;
230 TkinScaled = kinEnergy*massRatio;
232 for(iTkin = 0; iTkin <
fTotBin; iTkin++)
234 if( TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
break;
238 if(iTkin == 0) lambda =
DBL_MAX;
243 sigma = (*(*fEnergyDistrTable)(iPlace))(0)*chargeSq;
250 W1 = (E2 - TkinScaled)*W;
251 W2 = (TkinScaled - E1)*W;
252 sigma = ( (*(*fEnergyDistrTable)(iPlace ))(0)*W1 +
257 else lambda = 1./sigma;
279 "XTR initialisation for neutral particle ?!" );
287 G4cout<<
"Build angle for energy distribution according the current radiator" 301 G4int iTkin, iTR, iPlace;
327 G4cout<<
"Lorentz Factor"<<
"\t"<<
"XTR photon number"<<
G4endl;
330 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
350 for( iTR =
fBinTR - 2; iTR >= 0; iTR-- )
380 G4cout<<
"total time for build X-ray TR energy loss tables = " 425 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
440 for( iTR = 0; iTR <
fBinTR; iTR++ )
448 angleVector ->
PutValue(fBinTR - 1, angleSum);
450 for( i = fBinTR - 2; i >= 0; i-- )
459 angleVector ->
PutValue(i, angleSum);
470 G4cout<<
"total time for build X-ray TR angle for energy loss tables = " 503 G4cout<<
"Lorentz Factor"<<
"\t"<<
"XTR photon number"<<
G4endl;
506 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
524 for( iTR = 0; iTR <
fBinTR; iTR++ )
543 G4cout<<
"total time for build XTR angle for given energy tables = " 557 G4double theta=0., result,
tmp=0., cof1, cof2, cofMin, cofPHC, angleSum = 0.;
571 kMin =
G4int(cofMin);
572 if (cofMin > kMin) kMin++;
578 G4cout<<
"n-1 = "<<n-1<<
"; theta = " 581 <<
"; angleSum = "<<angleSum<<
G4endl;
585 for( iTheta = n - 1; iTheta >= 1; iTheta-- )
588 k = iTheta- 1 +
kMin;
592 result = (k - cof1)*(k - cof1)*(k + cof2)*(k + cof2);
594 tmp = std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
596 if( k == kMin && kMin ==
G4int(cofMin) )
600 else if(iTheta == n-1);
605 theta = std::abs(k-cofMin)*cofPHC/energy/(fPlateThick +
fGasThick);
609 G4cout<<
"iTheta = "<<iTheta<<
"; k = "<<k<<
"; theta = " 610 <<std::sqrt(theta)*
fGamma<<
"; tmp = " 612 <<
"; angleSum = "<<angleSum<<
G4endl;
614 angleVector->
PutValue( iTheta, theta, angleSum );
623 G4cout<<
"iTheta = "<<iTheta<<
"; theta = " 624 <<std::sqrt(theta)*
fGamma<<
"; tmp = " 626 <<
"; angleSum = "<<angleSum<<
G4endl;
628 angleVector->
PutValue( iTheta, theta, angleSum );
639 G4int iTkin, iTR, iPlace;
659 G4cout<<
"Lorentz Factor"<<
"\t"<<
"XTR photon number"<<
G4endl;
662 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
688 for( iTR =
fBinTR - 2; iTR >= 0; iTR-- )
696 angleVector ->
PutValue(iTR,angleSum);
714 G4cout<<
"total time for build X-ray TR angle tables = " 729 const G4Step& aStep )
732 G4double energyTR, theta,theta2, phi, dirX, dirY, dirZ;
739 G4cout<<
"Start of G4VXTRenergyLoss::PostStepDoIt "<<
G4endl;
740 G4cout<<
"name of current material = " 741 <<aTrack.GetVolume()->GetLogicalVolume()->GetMaterial()->GetName()<<
G4endl;
743 if( aTrack.GetVolume()->GetLogicalVolume() !=
fEnvelope )
747 G4cout<<
"Go out from G4VXTRenergyLoss::PostStepDoIt: wrong volume "<<
G4endl;
753 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
760 G4double gamma = 1.0 + kinEnergy/mass;
767 G4double TkinScaled = kinEnergy*massRatio;
770 G4double startTime = pPostStepPoint->GetGlobalTime();
772 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
774 if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
break;
782 G4cout<<
"Go out from G4VXTRenergyLoss::PostStepDoIt:iTkin = "<<iTkin<<
G4endl;
800 if(theta2 > 0.) theta = std::sqrt(theta2);
807 if( theta >= 0.1 ) theta = 0.1;
813 dirX = std::sin(theta)*std::cos(phi);
814 dirY = std::sin(theta)*std::sin(phi);
815 dirZ = std::cos(theta);
822 directionTR, energyTR);
830 const G4RotationMatrix* rotM = pPostStepPoint->GetTouchable()->GetRotation();
831 G4ThreeVector transl = pPostStepPoint->GetTouchable()->GetTranslation();
842 position += distance*directionTR;
845 G4Track* aSecondaryTrack =
new G4Track( aPhotonTR,
846 startTime, position );
847 aSecondaryTrack->SetTouchableHandle(
848 aStep.GetPostStepPoint()->GetTouchableHandle());
849 aSecondaryTrack->SetParentID( aTrack.GetTrackID() );
890 if(result < 0.0) result = 0.0;
903 G4double lim[8] = { 0.0, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0 };
929 for( i = 0; i < iMax-1; i++ )
948 if(result < 0) result = 0.0;
961 G4double sum = 0., tmp1, tmp2,
tmp=0., cof1, cof2, cofMin, cofPHC, energy1, energy2;
971 cofMin = std::sqrt(cof1*cof2);
974 kMin =
G4int(cofMin);
975 if (cofMin > kMin) kMin++;
981 for( k = kMin; k <=
kMax; k++ )
984 tmp2 = std::sqrt(tmp1*tmp1-cof1*cof2);
985 energy1 = (tmp1+tmp2)/cof1;
986 energy2 = (tmp1-tmp2)/cof1;
988 for(i = 0; i < 2; i++)
995 tmp2 = std::sin(tmp1);
996 tmp = energy1*tmp2*tmp2;
998 tmp1 = hbarc*energy1/( energy1*energy1*(1./
fGamma/
fGamma + varAngle) + fSigma2 );
999 tmp *= (tmp1-tmp2)*(tmp1-tmp2);
1000 tmp1 = cof1/(4*
hbarc) - cof2/(4*hbarc*energy1*energy1);
1001 tmp2 = std::abs(tmp1);
1002 if(tmp2 > 0.) tmp /= tmp2;
1010 tmp2 = std::sin(tmp1);
1011 tmp = energy2*tmp2*tmp2;
1013 tmp1 = hbarc*energy2/( energy2*energy2*(1./
fGamma/
fGamma + varAngle) + fSigma2 );
1014 tmp *= (tmp1-tmp2)*(tmp1-tmp2);
1015 tmp1 = cof1/(4*
hbarc) - cof2/(4*hbarc*energy2*energy2);
1016 tmp2 = std::abs(tmp1);
1017 if(tmp2 > 0.) tmp /= tmp2;
1026 result /= hbarc*
hbarc;
1048 lambda = 1.0/gamma/gamma + varAngle +
fSigma1/omega/omega;
1061 G4double cof, length,delta, real_v, image_v;
1065 cof = 1.0/(1.0 + delta*delta);
1067 real_v = length*cof;
1068 image_v = real_v*delta;
1100 omega2 = omega*omega;
1101 omega3 = omega2*omega;
1102 omega4 = omega2*omega2;
1105 G4double cross = SandiaCof[0]/omega + SandiaCof[1]/omega2 +
1106 SandiaCof[2]/omega3 + SandiaCof[3]/omega4;
1120 lambda = 1.0/gamma/gamma + varAngle +
fSigma2/omega/omega;
1134 G4double cof, length,delta, real_v, image_v;
1138 cof = 1.0/(1.0 + delta*delta);
1140 real_v = length*cof;
1141 image_v = real_v*delta;
1171 omega2 = omega*omega;
1172 omega3 = omega2*omega;
1173 omega4 = omega2*omega2;
1176 G4double cross = SandiaCof[0]/omega + SandiaCof[1]/omega2 +
1177 SandiaCof[2]/omega3 + SandiaCof[3]/omega4;
1201 std::ofstream outPlate(
"plateZmu.dat", std::ios::out );
1202 outPlate.setf( std::ios::scientific, std::ios::floatfield );
1207 varAngle = 1/gamma/gamma;
1212 omega = (1.0 + i)*
keV;
1239 std::ofstream outGas(
"gasZmu.dat", std::ios::out );
1240 outGas.setf( std::ios::scientific, std::ios::floatfield );
1244 varAngle = 1/gamma/gamma;
1249 omega = (1.0 + i)*
keV;
1264 G4int i, numberOfElements;
1265 G4double xSection = 0., nowZ, sumZ = 0.;
1268 numberOfElements = (*theMaterialTable)[
fMatIndex1]->GetNumberOfElements();
1270 for( i = 0; i < numberOfElements; i++ )
1272 nowZ = (*theMaterialTable)[
fMatIndex1]->GetElement(i)->GetZ();
1277 xSection *= (*theMaterialTable)[
fMatIndex1]->GetElectronDensity();
1288 G4int i, numberOfElements;
1289 G4double xSection = 0., nowZ, sumZ = 0.;
1292 numberOfElements = (*theMaterialTable)[
fMatIndex2]->GetNumberOfElements();
1294 for( i = 0; i < numberOfElements; i++ )
1296 nowZ = (*theMaterialTable)[
fMatIndex2]->GetElement(i)->GetZ();
1301 xSection *= (*theMaterialTable)[
fMatIndex2]->GetElectronDensity();
1313 if ( Z < 0.9999 )
return CrossSection;
1314 if ( GammaEnergy < 0.1*
keV )
return CrossSection;
1315 if ( GammaEnergy > (100.*
GeV/Z) )
return CrossSection;
1317 static const G4double a = 20.0 ,
b = 230.0 ,
c = 440.0;
1324 G4double p1Z = Z*(d1 + e1*Z + f1*Z*
Z), p2Z = Z*(d2 + e2*Z + f2*Z*Z),
1325 p3Z = Z*(d3 + e3*Z + f3*Z*
Z), p4Z = Z*(d4 + e4*Z + f4*Z*Z);
1328 if (Z < 1.5) T0 = 40.0*
keV;
1331 CrossSection = p1Z*std::log(1.+2.*X)/X
1332 + (p2Z + p3Z*X + p4Z*X*
X)/(1. + a*X +
b*X*X +
c*X*X*X);
1336 if (GammaEnergy < T0)
1340 G4double sigma = p1Z*std::log(1.+2*X)/X
1341 + (p2Z + p3Z*X + p4Z*X*
X)/(1. + a*X +
b*X*X +
c*X*X*X);
1342 G4double c1 = -T0*(sigma-CrossSection)/(CrossSection*dT0);
1344 if (Z > 1.5) c2 = 0.375-0.0556*std::log(Z);
1346 CrossSection *= std::exp(-y*(c1+c2*y));
1349 return CrossSection;
1367 G4double formationLength1, formationLength2;
1368 formationLength1 = 1.0/
1372 formationLength2 = 1.0/
1376 return (varAngle/energy)*(formationLength1 - formationLength2)
1377 *(formationLength1 - formationLength2);
1447 std::ofstream outEn(
"numberE.dat", std::ios::out );
1448 outEn.setf( std::ios::scientific, std::ios::floatfield );
1450 std::ofstream outAng(
"numberAng.dat", std::ios::out );
1451 outAng.setf( std::ios::scientific, std::ios::floatfield );
1453 for(iTkin=0;iTkin<
fTotBin;iTkin++)
1457 numberE = (*(*fEnergyDistrTable)(iTkin))(0);
1460 G4cout<<gamma<<
"\t\t"<<numberE<<
"\t" 1463 outEn<<gamma<<
"\t\t"<<numberE<<
G4endl;
1475 G4int iTransfer, iPlace;
1486 for(iTransfer=0;;iTransfer++)
1497 W1 = (E2 - scaledTkin)*W;
1498 W2 = (scaledTkin - E1)*W;
1500 position =( (*(*fEnergyDistrTable)(iPlace))(0)*W1 +
1505 for(iTransfer=0;;iTransfer++)
1515 if(transfer < 0.0 ) transfer = 0.0;
1532 result = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1536 y1 = (*(*fEnergyDistrTable)(iPlace))(iTransfer-1);
1537 y2 = (*(*fEnergyDistrTable)(iPlace))(iTransfer);
1539 x1 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
1540 x2 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1542 if ( x1 == x2 ) result =
x2;
1565 if (iTkin ==
fTotBin) iTkin--;
1569 for( iTR = 0; iTR <
fBinTR; iTR++ )
1571 if( energyXTR < fXTREnergyVector->GetLowEdgeEnergy(iTR) )
break;
1573 if (iTR == fBinTR) iTR--;
1575 position = (*(*fAngleForEnergyTable)(iTR))(0)*
G4UniformRand();
1577 for(iAngle = 0;;iAngle++)
1598 result = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1602 y1 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer-1);
1603 y2 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer);
1605 x1 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
1606 x2 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1608 if ( x1 == x2 ) result =
x2;
1614 result = x1 + (position -
y1)*(x2 - x1)/(y2 -
y1);
G4double condition(const G4ErrorSymMatrix &m)
G4double Legendre10(T &typeT, F f, G4double a, G4double b)
G4double GetXTRrandomEnergy(G4double scaledTkin, G4int iTkin)
G4PhysicsTable * fEnergyDistrTable
ThreeVector shoot(const G4int Ap, const G4int Af)
void ComputeGasPhotoAbsCof()
G4double GetGasFormationZone(G4double, G4double, G4double)
G4double Legendre96(T &typeT, F f, G4double a, G4double b)
void PutValue(size_t binNumber, G4double binValue, G4double dataValue)
G4double GetPlateLinearPhotoAbs(G4double)
G4double XTRNSpectralDensity(G4double energy)
G4double GetSandiaCofForMaterial(G4int, G4int) const
G4LogicalVolume * fEnvelope
G4double GetPlateCompton(G4double)
G4double GetGasLinearPhotoAbs(G4double)
static G4MaterialTable * GetMaterialTable()
std::vector< G4Material * > G4MaterialTable
static G4double angle[DIM]
G4double GetPlateFormationZone(G4double, G4double, G4double)
G4double GetComptonPerAtom(G4double, G4double)
G4complex GetPlateComplexFZ(G4double, G4double, G4double)
G4double GetLowEdgeEnergy(size_t binNumber) const
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
const G4String & GetProcessName() const
G4double GetKineticEnergy() const
std::complex< G4double > G4complex
void GetNumberOfPhotons()
G4GLOB_DLL std::ostream G4cout
G4PhysicsLogVector * fProtonEnergyVector
G4double GetXTRenergy(G4int iPlace, G4double position, G4int iTransfer)
void BuildGlobalAngleTable()
Hep3Vector & rotateUz(const Hep3Vector &)
static const double twopi
void BuildAngleForEnergyBank()
void PutValue(size_t index, G4double theValue)
void BuildPhysicsTable(const G4ParticleDefinition &)
void SetProcessSubType(G4int)
G4double OneBoundaryXTRNdensity(G4double energy, G4double gamma, G4double varAngle) const
G4double XTRNSpectralAngleDensity(G4double varAngle)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4PhysicsFreeVector * GetAngleVector(G4double energy, G4int n)
G4SandiaTable * fGasPhotoAbsCof
G4double GetUserElapsed() const
G4double GetAngleXTR(G4int iTR, G4double position, G4int iAngle)
G4double GetElectronDensity() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetPDGMass() const
virtual ~G4VXTRenergyLoss()
G4double SpectralAngleXTRdEdx(G4double varAngle)
virtual G4double SpectralXTRdEdx(G4double energy)
G4bool IsApplicable(const G4ParticleDefinition &)
G4VParticleChange * pParticleChange
G4PhysicsLogVector * fXTREnergyVector
G4SandiaTable * GetSandiaTable() const
G4VXTRenergyLoss(G4LogicalVolume *anEnvelope, G4Material *, G4Material *, G4double, G4double, G4int, const G4String &processName="XTRenergyLoss", G4ProcessType type=fElectromagnetic)
std::vector< G4PhysicsTable * > fAngleBank
void insertAt(size_t, G4PhysicsVector *)
G4double GetRandomAngle(G4double energyXTR, G4int iTkin)
G4complex OneInterfaceXTRdEdx(G4double energy, G4double gamma, G4double varAngle)
G4PhysicsTable * fAngleForEnergyTable
G4ParticleDefinition * GetDefinition() const
G4double GetGasCompton(G4double)
G4PhysicsTable * fAngleDistrTable
G4SandiaTable * fPlatePhotoAbsCof
G4double XTRNAngleDensity(G4double varAngle)
G4complex GetGasComplexFZ(G4double, G4double, G4double)
G4ParticleDefinition * fPtrGamma
G4ParticleChange fParticleChange
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition)
const G4String & GetName() const
G4double XTRNAngleSpectralDensity(G4double energy)
void ComputePlatePhotoAbsCof()
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
G4double GetPDGCharge() const
G4VSolid * GetSolid() const
static const G4double dT0
G4double AngleSpectralXTRdEdx(G4double energy)
void GetPlateZmuProduct()
virtual G4double GetStackFactor(G4double energy, G4double gamma, G4double varAngle)
G4double AngleXTRdEdx(G4double varAngle)