65 , fGammaCutInKineticEnergy(nullptr)
66 , fAngleDistrTable(nullptr)
67 , fEnergyDistrTable(nullptr)
68 , fAngleForEnergyTable(nullptr)
69 , fPlatePhotoAbsCof(nullptr)
70 , fGasPhotoAbsCof(nullptr)
109 G4cout <<
"### G4VXTRenergyLoss: the number of TR radiator plates = "
113 G4Exception(
"G4VXTRenergyLoss::G4VXTRenergyLoss()",
"VXTRELoss01",
146 G4cout <<
"plate plasma energy = " << std::sqrt(
fSigma1) / eV <<
" eV"
152 G4cout <<
"gas plasma energy = " << std::sqrt(
fSigma2) / eV <<
" eV"
186 out <<
"Base class for 'fast' parameterisation model describing X-ray "
188 "radiation. Angular distribution is very rough.\n";
204 G4double lambda, sigma, kinEnergy, mass, gamma;
205 G4double charge, chargeSq, massRatio, TkinScaled;
217 gamma = 1.0 + kinEnergy / mass;
223 if(std::fabs(gamma -
fGamma) < 0.05 * gamma)
228 chargeSq = charge * charge;
229 massRatio = proton_mass_c2 / mass;
230 TkinScaled = kinEnergy * massRatio;
232 for(iTkin = 0; iTkin <
fTotBin; ++iTkin)
234 if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
245 sigma = (*(*fEnergyDistrTable)(iPlace))(0) * chargeSq;
252 W1 = (E2 - TkinScaled) *
W;
253 W2 = (TkinScaled - E1) *
W;
254 sigma = ((*(*fEnergyDistrTable)(iPlace))(0) * W1 +
266 G4cout <<
" lambda = " << lambda / mm <<
" mm" <<
G4endl;
280 G4Exception(
"G4VXTRenergyLoss::BuildPhysicsTable",
"Notification",
281 JustWarning,
"XTR initialisation for neutral particle ?!");
290 <<
"Build angle for energy distribution according the current radiator"
301 G4int iTkin, iTR, iPlace;
332 G4cout <<
"Lorentz Factor"
334 <<
"XTR photon number" <<
G4endl;
337 for(iTkin = 0; iTkin <
fTotBin; ++iTkin)
350 energyVector->PutValue(
fBinTR - 1, energySum);
352 for(iTR =
fBinTR - 2; iTR >= 0; --iTR)
356 energySum += radiatorCof *
fCofTR *
362 energyVector->GetLowEdgeEnergy(iTR),
363 energyVector->GetLowEdgeEnergy(iTR + 1));
365 energyVector->PutValue(iTR, energySum /
fTotalDist);
380 G4cout <<
"total time for build X-ray TR energy loss tables = "
427 for(iTkin = 0; iTkin <
fTotBin; ++iTkin)
439 for(iTR = 0; iTR <
fBinTR; ++iTR)
442 fEnergy = energyVector->GetLowEdgeEnergy(iTR);
449 angleVector->PutValue(
fBinTR - 1, angleSum);
451 for(i =
fBinTR - 2; i >= 0; --i)
457 angleVector->GetLowEdgeEnergy(i),
458 angleVector->GetLowEdgeEnergy(i + 1));
460 angleVector->PutValue(i, angleSum);
471 G4cout <<
"total time for build X-ray TR angle for energy loss tables = "
507 for(iTkin = 0; iTkin <
fTotBin; ++iTkin)
524 for(iTR = 0; iTR <
fBinTR; ++iTR)
539 G4cout <<
"total time for build XTR angle for given energy tables = "
551 G4double theta = 0., result, tmp = 0., cof1, cof2, cofMin, cofPHC,
553 G4int iTheta, k, kMin;
557 cofPHC = 4. * pi * hbarc;
566 kMin =
G4int(cofMin);
572 G4cout <<
"n-1 = " << n - 1
574 <<
"; tmp = " << 0. <<
"; angleSum = " << angleSum <<
G4endl;
577 for(iTheta = n - 1; iTheta >= 1; --iTheta)
579 k = iTheta - 1 + kMin;
581 result = (k - cof1) * (k - cof1) * (k + cof2) * (k + cof2);
582 tmp = std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
584 if(k == kMin && kMin ==
G4int(cofMin))
589 else if(iTheta == n - 1)
599 G4cout <<
"iTheta = " << iTheta <<
"; k = " << k
600 <<
"; theta = " << std::sqrt(theta) *
fGamma <<
"; tmp = " << tmp
601 <<
"; angleSum = " << angleSum <<
G4endl;
603 angleVector->PutValue(iTheta, theta, angleSum);
613 G4cout <<
"iTheta = " << iTheta <<
"; theta = " << std::sqrt(theta) *
fGamma
614 <<
"; tmp = " << tmp <<
"; angleSum = " << angleSum <<
G4endl;
616 angleVector->PutValue(iTheta, theta, angleSum);
626 G4int iTkin, iTR, iPlace;
650 G4cout <<
"Lorentz Factor"
652 <<
"XTR photon number" <<
G4endl;
655 for(iTkin = 0; iTkin <
fTotBin; ++iTkin)
680 angleVector->PutValue(
fBinTR - 1, angleSum);
682 for(iTR =
fBinTR - 2; iTR >= 0; --iTR)
684 angleSum += radiatorCof *
fCofTR *
686 angleVector->GetLowEdgeEnergy(iTR),
687 angleVector->GetLowEdgeEnergy(iTR + 1));
689 angleVector->PutValue(iTR, angleSum);
703 G4cout <<
"total time for build X-ray TR angle tables = "
718 G4double energyTR, theta, theta2, phi, dirX, dirY, dirZ;
724 G4cout <<
"Start of G4VXTRenergyLoss::PostStepDoIt " <<
G4endl;
725 G4cout <<
"name of current material = "
733 G4cout <<
"Go out from G4VXTRenergyLoss::PostStepDoIt: wrong volume "
746 G4double gamma = 1.0 + kinEnergy / mass;
752 G4double massRatio = proton_mass_c2 / mass;
753 G4double TkinScaled = kinEnergy * massRatio;
758 for(iTkin = 0; iTkin <
fTotBin; ++iTkin)
760 if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
768 G4cout <<
"Go out from G4VXTRenergyLoss::PostStepDoIt:iTkin = " << iTkin
781 G4cout <<
"energyTR = " << energyTR / keV <<
" keV" <<
G4endl;
787 theta = std::sqrt(theta2);
792 theta = std::fabs(G4RandGauss::shoot(0.0, pi / gamma));
799 dirX = std::sin(theta) * std::cos(phi);
800 dirY = std::sin(theta) * std::sin(phi);
801 dirZ = std::cos(theta);
828 G4cout <<
"distance to exit = " << distance / mm <<
" mm" <<
G4endl;
831 startTime += distance / c_light;
858 G4complex zOut = (Z1 - Z2) * (Z1 - Z2) * (varAngle * energy / hbarc / hbarc);
877 static constexpr G4int iMax = 8;
880 G4double lim[iMax] = { 0.0, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0 };
882 for(i = 0; i < iMax; ++i)
890 for(i = 0; i < iMax - 1; ++i)
892 angleSum += integral.Legendre96(
914 G4double sum = 0., tmp1, tmp2, tmp = 0., cof1, cof2, cofMin, cofPHC, energy1,
916 G4int k, kMax, kMin, i;
918 cofPHC = twopi * hbarc;
923 cofMin = std::sqrt(cof1 * cof2);
926 kMin =
G4int(cofMin);
932 for(k = kMin; k <= kMax; ++k)
935 tmp2 = std::sqrt(tmp1 * tmp1 - cof1 * cof2);
936 energy1 = (tmp1 + tmp2) / cof1;
937 energy2 = (tmp1 - tmp2) / cof1;
939 for(i = 0; i < 2; ++i)
949 tmp2 = std::sin(tmp1);
950 tmp = energy1 * tmp2 * tmp2;
955 tmp *= (tmp1 - tmp2) * (tmp1 - tmp2);
956 tmp1 = cof1 / (4. * hbarc) - cof2 / (4. * hbarc * energy1 * energy1);
957 tmp2 = std::abs(tmp1);
972 tmp2 = std::sin(tmp1);
973 tmp = energy2 * tmp2 * tmp2;
978 tmp *= (tmp1 - tmp2) * (tmp1 - tmp2);
979 tmp1 = cof1 / (4. * hbarc) - cof2 / (4. * hbarc * energy2 * energy2);
980 tmp2 = std::abs(tmp1);
991 result /= hbarc * hbarc;
1002 lambda = 1.0 / gamma / gamma + varAngle +
fSigma1 / omega / omega;
1003 cof = 2.0 * hbarc / omega / lambda;
1012 G4double cof, length, delta, real_v, image_v;
1016 cof = 1.0 / (1.0 + delta * delta);
1018 real_v = length * cof;
1019 image_v = real_v * delta;
1044 omega2 = omega * omega;
1045 omega3 = omega2 * omega;
1046 omega4 = omega2 * omega2;
1049 G4double cross = SandiaCof[0] / omega + SandiaCof[1] / omega2 +
1050 SandiaCof[2] / omega3 + SandiaCof[3] / omega4;
1060 lambda = 1.0 / gamma / gamma + varAngle +
fSigma2 / omega / omega;
1061 cof = 2.0 * hbarc / omega / lambda;
1070 G4double cof, length, delta, real_v, image_v;
1074 cof = 1.0 / (1.0 + delta * delta);
1076 real_v = length * cof;
1077 image_v = real_v * delta;
1101 omega2 = omega * omega;
1102 omega3 = omega2 * omega;
1103 omega4 = omega2 * omega2;
1106 G4double cross = SandiaCof[0] / omega + SandiaCof[1] / omega2 +
1107 SandiaCof[2] / omega3 + SandiaCof[3] / omega4;
1125 std::ofstream outPlate(
"plateZmu.dat", std::ios::out);
1126 outPlate.setf(std::ios::scientific, std::ios::floatfield);
1131 varAngle = 1 / gamma / gamma;
1133 G4cout <<
"energy, keV" <<
"\t" <<
"Zmu for plate" <<
G4endl;
1134 for(i = 0; i < 100; ++i)
1136 omega = (1.0 + i) * keV;
1138 G4cout << omega / keV <<
"\t"
1141 outPlate << omega / keV <<
"\t\t"
1162 std::ofstream outGas(
"gasZmu.dat", std::ios::out);
1163 outGas.setf(std::ios::scientific, std::ios::floatfield);
1167 varAngle = 1 / gamma / gamma;
1169 G4cout <<
"energy, keV" <<
"\t" <<
"Zmu for gas" <<
G4endl;
1170 for(i = 0; i < 100; ++i)
1172 omega = (1.0 + i) * keV;
1177 outGas << omega / keV <<
"\t\t"
1187 G4int i, numberOfElements;
1188 G4double xSection = 0., nowZ, sumZ = 0.;
1191 numberOfElements = (
G4int)(*theMaterialTable)[
fMatIndex1]->GetNumberOfElements();
1193 for(i = 0; i < numberOfElements; ++i)
1195 nowZ = (*theMaterialTable)[
fMatIndex1]->GetElement(i)->GetZ();
1200 xSection *= (*theMaterialTable)[
fMatIndex1]->GetElectronDensity();
1208 G4int i, numberOfElements;
1209 G4double xSection = 0., nowZ, sumZ = 0.;
1212 numberOfElements = (
G4int)(*theMaterialTable)[
fMatIndex2]->GetNumberOfElements();
1214 for(i = 0; i < numberOfElements; ++i)
1216 nowZ = (*theMaterialTable)[
fMatIndex2]->GetElement(i)->GetZ();
1221 xSection *= (*theMaterialTable)[
fMatIndex2]->GetElectronDensity();
1232 return CrossSection;
1233 if(GammaEnergy < 0.1 * keV)
1234 return CrossSection;
1235 if(GammaEnergy > (100. * GeV /
Z))
1236 return CrossSection;
1238 static constexpr G4double a = 20.0;
1239 static constexpr G4double b = 230.0;
1240 static constexpr G4double c = 440.0;
1242 static constexpr G4double d1 = 2.7965e-1 * barn, d2 = -1.8300e-1 * barn,
1243 d3 = 6.7527 * barn, d4 = -1.9798e+1 * barn,
1244 e1 = 1.9756e-5 * barn, e2 = -1.0205e-2 * barn,
1245 e3 = -7.3913e-2 * barn, e4 = 2.7079e-2 * barn,
1246 f1 = -3.9178e-7 * barn, f2 = 6.8241e-5 * barn,
1247 f3 = 6.0480e-5 * barn, f4 = 3.0274e-4 * barn;
1258 G4double X = std::max(GammaEnergy, T0) / electron_mass_c2;
1260 p1Z * std::log(1. + 2. * X) / X +
1261 (p2Z + p3Z * X + p4Z * X * X) / (1. + a * X + b * X * X + c * X * X * X);
1264 if(GammaEnergy < T0)
1267 X = (T0 + dT0) / electron_mass_c2;
1269 p1Z * std::log(1. + 2. * X) / X +
1270 (p2Z + p3Z * X + p4Z * X * X) / (1. + a * X + b * X * X + c * X * X * X);
1271 G4double c1 = -T0 * (sigma - CrossSection) / (CrossSection * dT0);
1274 c2 = 0.375 - 0.0556 * std::log(
Z);
1275 G4double y = std::log(GammaEnergy / T0);
1276 CrossSection *= std::exp(-y * (c1 + c2 * y));
1278 return CrossSection;
1292 G4double formationLength1, formationLength2;
1294 1.0 / (1.0 / (gamma * gamma) +
fSigma1 / (energy * energy) + varAngle);
1296 1.0 / (1.0 / (gamma * gamma) +
fSigma2 / (energy * energy) + varAngle);
1297 return (varAngle / energy) * (formationLength1 - formationLength2) *
1298 (formationLength1 - formationLength2);
1355 std::ofstream outEn(
"numberE.dat", std::ios::out);
1356 outEn.setf(std::ios::scientific, std::ios::floatfield);
1358 std::ofstream outAng(
"numberAng.dat", std::ios::out);
1359 outAng.setf(std::ios::scientific, std::ios::floatfield);
1361 for(iTkin = 0; iTkin <
fTotBin; ++iTkin)
1365 numberE = (*(*fEnergyDistrTable)(iTkin))(0);
1367 G4cout << gamma <<
"\t\t" << numberE <<
"\t" <<
G4endl;
1369 outEn << gamma <<
"\t\t" << numberE <<
G4endl;
1379 G4int iTransfer, iPlace;
1388 for(iTransfer = 0;; ++iTransfer)
1399 W = 1.0 / (E2 - E1);
1400 W1 = (E2 - scaledTkin) *
W;
1401 W2 = (scaledTkin - E1) *
W;
1403 position = ((*(*fEnergyDistrTable)(iPlace))(0) * W1 +
1407 for(iTransfer = 0;; ++iTransfer)
1429 result = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1433 y1 = (*(*fEnergyDistrTable)(iPlace))(iTransfer - 1);
1434 y2 = (*(*fEnergyDistrTable)(iPlace))(iTransfer);
1436 x1 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer - 1);
1437 x2 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1467 for(iTR = 0; iTR <
fBinTR; ++iTR)
1469 if(energyXTR < fXTREnergyVector->GetLowEdgeEnergy(iTR))
1478 for(iAngle = 0;; ++iAngle)
1497 if( iTransfer == 0 )
1500 result = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1504 y1 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer - 1);
1505 y2 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer);
1507 x1 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer - 1);
1508 x2 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1510 if(x1 == x2) result = x2;
1516 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 Initialize(const G4Track &) override
void ProposeEnergy(G4double finalEnergy)
G4double GetPDGMass() const
G4double GetPDGCharge() const
static G4int GetModelID(const G4int modelIndex)
void insertAt(std::size_t, G4PhysicsVector *)
G4double GetLowEdgeEnergy(const std::size_t index) const
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
static constexpr G4double fMaxProtonTkin
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
static constexpr G4double fCofTR
void GetPlateZmuProduct()
void BuildAngleForEnergyBank()
G4LogicalVolume * fEnvelope
std::vector< G4PhysicsTable * > fAngleBank
static constexpr G4double fPlasmaCof
virtual ~G4VXTRenergyLoss()
virtual G4double SpectralXTRdEdx(G4double energy)
G4double GetComptonPerAtom(G4double, G4double)
void GetNumberOfPhotons()
static constexpr G4double fMinProtonTkin
G4double GetGasCompton(G4double)
G4double XTRNSpectralAngleDensity(G4double varAngle)
virtual void ProcessDescription(std::ostream &) const override
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)