69 fGammaCutInKineticEnergy(nullptr),
71 fAngleDistrTable(nullptr),
72 fEnergyDistrTable(nullptr),
73 fPlatePhotoAbsCof(nullptr),
74 fGasPhotoAbsCof(nullptr),
75 fAngleForEnergyTable(nullptr)
107 fPlasmaCof = 4.0*pi*fine_structure_const*hbarc*hbarc*hbarc/electron_mass_c2;
109 fCofTR = fine_structure_const/pi;
115 G4cout<<
"### G4VXTRenergyLoss: the number of TR radiator plates = "
119 G4Exception(
"G4VXTRenergyLoss::G4VXTRenergyLoss()",
"VXTRELoss01",
207 G4double lambda, sigma, kinEnergy, mass, gamma;
208 G4double charge, chargeSq, massRatio, TkinScaled;
219 gamma = 1.0 + kinEnergy/mass;
225 if ( std::fabs( gamma -
fGamma ) < 0.05*gamma ) lambda =
fLambda;
229 chargeSq = charge*charge;
230 massRatio = proton_mass_c2/mass;
231 TkinScaled = kinEnergy*massRatio;
233 for(iTkin = 0; iTkin <
fTotBin; iTkin++)
235 if( TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
break;
239 if(iTkin == 0) lambda =
DBL_MAX;
244 sigma = (*(*fEnergyDistrTable)(iPlace))(0)*chargeSq;
251 W1 = (E2 - TkinScaled)*W;
252 W2 = (TkinScaled - E1)*W;
253 sigma = ( (*(*fEnergyDistrTable)(iPlace ))(0)*W1 +
258 else lambda = 1./sigma;
280 "XTR initialisation for neutral particle ?!" );
288 G4cout<<
"Build angle for energy distribution according the current radiator"
302 G4int iTkin, iTR, iPlace;
328 G4cout<<
"Lorentz Factor"<<
"\t"<<
"XTR photon number"<<
G4endl;
331 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
338 GetLowEdgeEnergy(iTkin)/proton_mass_c2);
351 for( iTR =
fBinTR - 2; iTR >= 0; iTR-- )
355 energySum += radiatorCof*
fCofTR*integral.Legendre10(
381 G4cout<<
"total time for build X-ray TR energy loss tables = "
426 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
430 GetLowEdgeEnergy(iTkin)/proton_mass_c2);
441 for( iTR = 0; iTR <
fBinTR; iTR++ )
451 for( i =
fBinTR - 2; i >= 0; i-- )
455 angleSum += integral.Legendre10(
460 angleVector ->
PutValue(i, angleSum);
471 G4cout<<
"total time for build X-ray TR angle for energy loss tables = "
504 G4cout<<
"Lorentz Factor"<<
"\t"<<
"XTR photon number"<<
G4endl;
507 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
511 GetLowEdgeEnergy(iTkin)/proton_mass_c2);
525 for( iTR = 0; iTR <
fBinTR; iTR++ )
544 G4cout<<
"total time for build XTR angle for given energy tables = "
558 G4double theta=0., result, tmp=0., cof1, cof2, cofMin, cofPHC, angleSum = 0.;
559 G4int iTheta, k, kMin;
563 cofPHC = 4.*pi*hbarc;
572 kMin =
G4int(cofMin);
573 if (cofMin > kMin) kMin++;
579 G4cout<<
"n-1 = "<<n-1<<
"; theta = "
582 <<
"; angleSum = "<<angleSum<<
G4endl;
586 for( iTheta = n - 1; iTheta >= 1; iTheta-- )
589 k = iTheta - 1 + kMin;
593 result = (k - cof1)*(k - cof1)*(k + cof2)*(k + cof2);
595 tmp = std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
597 if( k == kMin && kMin ==
G4int(cofMin) )
601 else if(iTheta == n-1);
610 G4cout<<
"iTheta = "<<iTheta<<
"; k = "<<k<<
"; theta = "
611 <<std::sqrt(theta)*
fGamma<<
"; tmp = "
613 <<
"; angleSum = "<<angleSum<<
G4endl;
615 angleVector->
PutValue( iTheta, theta, angleSum );
624 G4cout<<
"iTheta = "<<iTheta<<
"; theta = "
625 <<std::sqrt(theta)*
fGamma<<
"; tmp = "
627 <<
"; angleSum = "<<angleSum<<
G4endl;
629 angleVector->
PutValue( iTheta, theta, angleSum );
640 G4int iTkin, iTR, iPlace;
660 G4cout<<
"Lorentz Factor"<<
"\t"<<
"XTR photon number"<<
G4endl;
663 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
667 GetLowEdgeEnergy(iTkin)/proton_mass_c2);
689 for( iTR =
fBinTR - 2; iTR >= 0; iTR-- )
692 angleSum += radiatorCof*
fCofTR*integral.Legendre96(
697 angleVector ->
PutValue(iTR,angleSum);
715 G4cout<<
"total time for build X-ray TR angle tables = "
733 G4double energyTR, theta,theta2, phi, dirX, dirY, dirZ;
740 G4cout<<
"Start of G4VXTRenergyLoss::PostStepDoIt "<<
G4endl;
741 G4cout<<
"name of current material = "
748 G4cout<<
"Go out from G4VXTRenergyLoss::PostStepDoIt: wrong volume "<<
G4endl;
761 G4double gamma = 1.0 + kinEnergy/mass;
767 G4double massRatio = proton_mass_c2/mass;
768 G4double TkinScaled = kinEnergy*massRatio;
773 for( iTkin = 0; iTkin <
fTotBin; iTkin++ )
775 if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
break;
783 G4cout<<
"Go out from G4VXTRenergyLoss::PostStepDoIt:iTkin = "<<iTkin<<
G4endl;
803 if( theta2 > 0.) theta = std::sqrt(theta2);
806 else theta = std::fabs(G4RandGauss::shoot(0.0,pi/gamma));
810 if( theta >= 0.1 ) theta = 0.1;
816 dirX = std::sin(theta)*std::cos(phi);
817 dirY = std::sin(theta)*std::sin(phi);
818 dirZ = std::cos(theta);
825 directionTR, energyTR);
843 G4cout<<
"distance to exit = "<<distance/mm<<
" mm"<<
G4endl;
846 startTime += distance/c_light;
879 * (varAngle*energy/hbarc/hbarc);
893 if(result < 0.0) result = 0.0;
906 G4double lim[8] = { 0.0, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0 };
932 for( i = 0; i < iMax-1; i++ )
951 if(result < 0) result = 0.0;
964 G4double sum = 0., tmp1, tmp2, tmp=0., cof1, cof2, cofMin, cofPHC, energy1, energy2;
965 G4int k, kMax, kMin, i;
967 cofPHC = twopi*hbarc;
974 cofMin = std::sqrt(cof1*cof2);
977 kMin =
G4int(cofMin);
978 if (cofMin > kMin) kMin++;
984 for( k = kMin; k <= kMax; k++ )
987 tmp2 = std::sqrt(tmp1*tmp1-cof1*cof2);
988 energy1 = (tmp1+tmp2)/cof1;
989 energy2 = (tmp1-tmp2)/cof1;
991 for(i = 0; i < 2; i++)
999 tmp2 = std::sin(tmp1);
1000 tmp = energy1*tmp2*tmp2;
1003 tmp *= (tmp1-tmp2)*(tmp1-tmp2);
1004 tmp1 = cof1/(4.*hbarc) - cof2/(4.*hbarc*energy1*energy1);
1005 tmp2 = std::abs(tmp1);
1007 if(tmp2 > 0.) tmp /= tmp2;
1016 tmp2 = std::sin(tmp1);
1017 tmp = energy2*tmp2*tmp2;
1020 tmp *= (tmp1-tmp2)*(tmp1-tmp2);
1021 tmp1 = cof1/(4.*hbarc) - cof2/(4.*hbarc*energy2*energy2);
1022 tmp2 = std::abs(tmp1);
1024 if(tmp2 > 0.) tmp /= tmp2;
1033 result /= hbarc*hbarc;
1055 lambda = 1.0/gamma/gamma + varAngle +
fSigma1/omega/omega;
1056 cof = 2.0*hbarc/omega/lambda;
1068 G4double cof, length,delta, real_v, image_v;
1072 cof = 1.0/(1.0 + delta*delta);
1074 real_v = length*cof;
1075 image_v = real_v*delta;
1107 omega2 = omega*omega;
1108 omega3 = omega2*omega;
1109 omega4 = omega2*omega2;
1112 G4double cross = SandiaCof[0]/omega + SandiaCof[1]/omega2 +
1113 SandiaCof[2]/omega3 + SandiaCof[3]/omega4;
1127 lambda = 1.0/gamma/gamma + varAngle +
fSigma2/omega/omega;
1128 cof = 2.0*hbarc/omega/lambda;
1141 G4double cof, length,delta, real_v, image_v;
1145 cof = 1.0/(1.0 + delta*delta);
1147 real_v = length*cof;
1148 image_v = real_v*delta;
1178 omega2 = omega*omega;
1179 omega3 = omega2*omega;
1180 omega4 = omega2*omega2;
1183 G4double cross = SandiaCof[0]/omega + SandiaCof[1]/omega2 +
1184 SandiaCof[2]/omega3 + SandiaCof[3]/omega4;
1208 std::ofstream outPlate(
"plateZmu.dat", std::ios::out );
1209 outPlate.setf( std::ios::scientific, std::ios::floatfield );
1214 varAngle = 1/gamma/gamma;
1219 omega = (1.0 + i)*keV;
1246 std::ofstream outGas(
"gasZmu.dat", std::ios::out );
1247 outGas.setf( std::ios::scientific, std::ios::floatfield );
1251 varAngle = 1/gamma/gamma;
1256 omega = (1.0 + i)*keV;
1271 G4int i, numberOfElements;
1272 G4double xSection = 0., nowZ, sumZ = 0.;
1275 numberOfElements = (*theMaterialTable)[
fMatIndex1]->GetNumberOfElements();
1277 for( i = 0; i < numberOfElements; i++ )
1279 nowZ = (*theMaterialTable)[
fMatIndex1]->GetElement(i)->GetZ();
1284 xSection *= (*theMaterialTable)[
fMatIndex1]->GetElectronDensity();
1295 G4int i, numberOfElements;
1296 G4double xSection = 0., nowZ, sumZ = 0.;
1299 numberOfElements = (*theMaterialTable)[
fMatIndex2]->GetNumberOfElements();
1301 for( i = 0; i < numberOfElements; i++ )
1303 nowZ = (*theMaterialTable)[
fMatIndex2]->GetElement(i)->GetZ();
1308 xSection *= (*theMaterialTable)[
fMatIndex2]->GetElectronDensity();
1320 if ( Z < 0.9999 )
return CrossSection;
1321 if ( GammaEnergy < 0.1*keV )
return CrossSection;
1322 if ( GammaEnergy > (100.*GeV/Z) )
return CrossSection;
1324 static const G4double a = 20.0 , b = 230.0 , c = 440.0;
1327 d1= 2.7965e-1*barn, d2=-1.8300e-1*barn, d3= 6.7527 *barn, d4=-1.9798e+1*barn,
1328 e1= 1.9756e-5*barn, e2=-1.0205e-2*barn, e3=-7.3913e-2*barn, e4= 2.7079e-2*barn,
1329 f1=-3.9178e-7*barn, f2= 6.8241e-5*barn, f3= 6.0480e-5*barn, f4= 3.0274e-4*barn;
1331 G4double p1Z = Z*(d1 + e1*Z + f1*Z*Z), p2Z = Z*(d2 + e2*Z + f2*Z*Z),
1332 p3Z = Z*(d3 + e3*Z + f3*Z*Z), p4Z = Z*(d4 + e4*Z + f4*Z*Z);
1335 if (Z < 1.5) T0 = 40.0*keV;
1337 G4double X = std::max(GammaEnergy, T0) / electron_mass_c2;
1338 CrossSection = p1Z*std::log(1.+2.*X)/X
1339 + (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
1343 if (GammaEnergy < T0)
1346 X = (T0+dT0) / electron_mass_c2;
1347 G4double sigma = p1Z*std::log(1.+2.*X)/X
1348 + (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
1349 G4double c1 = -T0*(sigma-CrossSection)/(CrossSection*dT0);
1351 if (Z > 1.5) c2 = 0.375-0.0556*std::log(Z);
1352 G4double y = std::log(GammaEnergy/T0);
1353 CrossSection *= std::exp(-y*(c1+c2*y));
1356 return CrossSection;
1374 G4double formationLength1, formationLength2;
1375 formationLength1 = 1.0/
1379 formationLength2 = 1.0/
1383 return (varAngle/energy)*(formationLength1 - formationLength2)
1384 *(formationLength1 - formationLength2);
1454 std::ofstream outEn(
"numberE.dat", std::ios::out );
1455 outEn.setf( std::ios::scientific, std::ios::floatfield );
1457 std::ofstream outAng(
"numberAng.dat", std::ios::out );
1458 outAng.setf( std::ios::scientific, std::ios::floatfield );
1460 for(iTkin=0;iTkin<
fTotBin;iTkin++)
1463 GetLowEdgeEnergy(iTkin)/proton_mass_c2);
1464 numberE = (*(*fEnergyDistrTable)(iTkin))(0);
1467 G4cout<<gamma<<
"\t\t"<<numberE<<
"\t"
1470 outEn<<gamma<<
"\t\t"<<numberE<<
G4endl;
1482 G4int iTransfer, iPlace;
1493 for(iTransfer=0;;iTransfer++)
1504 W1 = (E2 - scaledTkin)*W;
1505 W2 = (scaledTkin - E1)*W;
1507 position =( (*(*fEnergyDistrTable)(iPlace))(0)*W1 +
1512 for(iTransfer=0;;iTransfer++)
1522 if(transfer < 0.0 ) transfer = 0.0;
1539 result = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1543 y1 = (*(*fEnergyDistrTable)(iPlace))(iTransfer-1);
1544 y2 = (*(*fEnergyDistrTable)(iPlace))(iTransfer);
1546 x1 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
1547 x2 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1549 if ( x1 == x2 ) result = x2;
1572 if (iTkin ==
fTotBin) iTkin--;
1576 for( iTR = 0; iTR <
fBinTR; iTR++ )
1578 if( energyXTR < fXTREnergyVector->GetLowEdgeEnergy(iTR) )
break;
1580 if (iTR ==
fBinTR) iTR--;
1584 for( iAngle = 0;; iAngle++)
1603 if( iTransfer == 0 )
1605 result = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1609 y1 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer-1);
1610 y2 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer);
1612 x1 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
1613 x2 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1615 if ( x1 == x2 ) result = x2;
1621 result = x1 + (
position - y1)*(x2 - x1)/(y2 - y1);
G4double condition(const G4ErrorSymMatrix &m)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::vector< G4Material * > G4MaterialTable
std::complex< G4double > G4complex
G4GLOB_DLL std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
G4VSolid * GetSolid() const
G4Material * GetMaterial() const
G4SandiaTable * GetSandiaTable() const
G4double GetElectronDensity() const
static G4MaterialTable * GetMaterialTable()
const G4String & GetName() const
void AddSecondary(G4Track *aSecondary)
void ProposeEnergy(G4double finalEnergy)
virtual void Initialize(const G4Track &)
G4double GetPDGMass() const
G4double GetPDGCharge() const
void PutValue(std::size_t index, G4double energy, G4double dValue)
void insertAt(std::size_t, G4PhysicsVector *)
G4double GetLowEdgeEnergy(std::size_t binNumber) const
void PutValue(std::size_t index, G4double theValue)
G4double GetSandiaCofForMaterial(G4int, G4int) const
const G4VTouchable * GetTouchable() const
G4double GetGlobalTime() const
const G4ThreeVector & GetPosition() const
const G4TouchableHandle & GetTouchableHandle() const
G4StepPoint * GetPostStepPoint() const
G4double GetUserElapsed() const
G4VPhysicalVolume * GetVolume() const
void SetTouchableHandle(const G4TouchableHandle &apValue)
const G4DynamicParticle * GetDynamicParticle() const
void SetParentID(const G4int aValue)
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
void SetNumberOfSecondaries(G4int totSecondaries)
G4LogicalVolume * GetLogicalVolume() const
void SetProcessSubType(G4int)
G4VParticleChange * pParticleChange
const G4String & GetProcessName() const
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const =0
virtual const G4ThreeVector & GetTranslation(G4int depth=0) const =0
virtual const G4RotationMatrix * GetRotation(G4int depth=0) const =0
G4double GetPlateLinearPhotoAbs(G4double)
G4double AngleSpectralXTRdEdx(G4double energy)
G4double XTRNAngleDensity(G4double varAngle)
G4PhysicsTable * fEnergyDistrTable
void ComputeGasPhotoAbsCof()
G4double GetAngleXTR(G4int iTR, G4double position, G4int iAngle)
virtual G4bool IsApplicable(const G4ParticleDefinition &) override
G4PhysicsTable * fAngleForEnergyTable
G4PhysicsLogVector * fProtonEnergyVector
G4PhysicsLogVector * fXTREnergyVector
G4double GetGasFormationZone(G4double, G4double, G4double)
G4SandiaTable * fPlatePhotoAbsCof
G4double OneBoundaryXTRNdensity(G4double energy, G4double gamma, G4double varAngle) const
G4PhysicsFreeVector * GetAngleVector(G4double energy, G4int n)
G4PhysicsTable * fAngleDistrTable
G4double GetRandomAngle(G4double energyXTR, G4int iTkin)
G4complex GetPlateComplexFZ(G4double, G4double, G4double)
virtual void BuildPhysicsTable(const G4ParticleDefinition &) override
G4complex OneInterfaceXTRdEdx(G4double energy, G4double gamma, G4double varAngle)
virtual G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition) override
G4double GetXTRenergy(G4int iPlace, G4double position, G4int iTransfer)
G4VXTRenergyLoss(G4LogicalVolume *anEnvelope, G4Material *, G4Material *, G4double, G4double, G4int, const G4String &processName="XTRenergyLoss", G4ProcessType type=fElectromagnetic)
void BuildGlobalAngleTable()
G4double XTRNAngleSpectralDensity(G4double energy)
G4double SpectralAngleXTRdEdx(G4double varAngle)
G4double GetXTRrandomEnergy(G4double scaledTkin, G4int iTkin)
G4SandiaTable * fGasPhotoAbsCof
void GetPlateZmuProduct()
void BuildAngleForEnergyBank()
G4LogicalVolume * fEnvelope
std::vector< G4PhysicsTable * > fAngleBank
virtual ~G4VXTRenergyLoss()
virtual G4double SpectralXTRdEdx(G4double energy)
G4double GetComptonPerAtom(G4double, G4double)
void GetNumberOfPhotons()
G4double GetGasCompton(G4double)
G4double XTRNSpectralAngleDensity(G4double varAngle)
void ComputePlatePhotoAbsCof()
G4double GetPlateFormationZone(G4double, G4double, G4double)
G4double GetGasLinearPhotoAbs(G4double)
G4double XTRNSpectralDensity(G4double energy)
virtual G4double GetStackFactor(G4double energy, G4double gamma, G4double varAngle)
G4ParticleDefinition * fPtrGamma
virtual G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
G4ParticleChange fParticleChange
G4complex GetGasComplexFZ(G4double, G4double, G4double)
G4double GetPlateCompton(G4double)
G4double AngleXTRdEdx(G4double varAngle)