Import Geant4 11.0.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2021-06-25 16:12:29 +02:00
parent c968e26a39
commit 6399a014b6
4200 changed files with 207479 additions and 237366 deletions
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
////////////////////////////////////////////////////////////////////////
// Cerenkov Radiation Class Implementation
////////////////////////////////////////////////////////////////////////
@@ -56,22 +54,26 @@
// > add protection against /0
// > G4MaterialPropertiesTable; new physics/tracking scheme
//
//
////////////////////////////////////////////////////////////////////////
#include "G4ios.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4Poisson.hh"
#include "G4EmProcessSubType.hh"
#include "G4LossTableManager.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ParticleDefinition.hh"
#include "G4OpticalParameters.hh"
#include "G4Cerenkov.hh"
#include "G4ios.hh"
#include "G4LossTableManager.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4MaterialPropertiesTable.hh"
#include "G4OpticalParameters.hh"
#include "G4OpticalPhoton.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleMomentum.hh"
#include "G4PhysicalConstants.hh"
#include "G4PhysicsFreeVector.hh"
#include "G4Poisson.hh"
#include "G4SystemOfUnits.hh"
#include "G4ThreeVector.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4Cerenkov::G4Cerenkov(const G4String& processName, G4ProcessType type)
: G4VProcess(processName, type)
@@ -98,6 +100,21 @@ G4Cerenkov::~G4Cerenkov()
}
}
void G4Cerenkov::ProcessDescription(std::ostream& out) const
{
out << "The Cerenkov effect simulates optical photons created by the\n";
out << "passage of charged particles through matter. Materials need\n";
out << "to have the property RINDEX (refractive index) defined.\n";
G4VProcess::DumpInfo();
G4OpticalParameters* params = G4OpticalParameters::Instance();
out << "Maximum beta change per step: " << params->GetCerenkovMaxBetaChange();
out << "Maximum photons per step: " << params->GetCerenkovMaxPhotonsPerStep();
out << "Track secondaries first: " << params->GetCerenkovTrackSecondariesFirst();
out << "Stack photons: " << params->GetCerenkovStackPhotons();
out << "Verbose level: " << params->GetCerenkovVerboseLevel();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4Cerenkov::IsApplicable(const G4ParticleDefinition& aParticleType)
{
@@ -134,33 +151,30 @@ void G4Cerenkov::BuildPhysicsTable(const G4ParticleDefinition&)
// loop over materials
for(G4int i = 0; i < numOfMaterials; ++i)
{
G4PhysicsOrderedFreeVector* aPhysicsOrderedFreeVector = 0;
G4PhysicsFreeVector* cerenkovIntegral = nullptr;
// Retrieve vector of refraction indices for the material
// from the material's optical properties table
G4Material* aMaterial = (*theMaterialTable)[i];
G4MaterialPropertiesTable* aMaterialPropertiesTable =
aMaterial->GetMaterialPropertiesTable();
G4MaterialPropertiesTable* MPT = aMaterial->GetMaterialPropertiesTable();
if(aMaterialPropertiesTable)
if(MPT)
{
aPhysicsOrderedFreeVector = new G4PhysicsOrderedFreeVector();
G4MaterialPropertyVector* theRefractionIndexVector =
aMaterialPropertiesTable->GetProperty(kRINDEX);
cerenkovIntegral = new G4PhysicsFreeVector();
G4MaterialPropertyVector* refractiveIndex = MPT->GetProperty(kRINDEX);
if(theRefractionIndexVector)
if(refractiveIndex)
{
// Retrieve the first refraction index in vector
// of (photon energy, refraction index) pairs
G4double currentRI = (*theRefractionIndexVector)[0];
G4double currentRI = (*refractiveIndex)[0];
if(currentRI > 1.0)
{
// Create first (photon energy, Cerenkov Integral) pair
G4double currentPM = theRefractionIndexVector->Energy(0);
G4double currentPM = refractiveIndex->Energy(0);
G4double currentCAI = 0.0;
aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCAI);
cerenkovIntegral->InsertValues(currentPM, currentCAI);
// Set previous values to current ones prior to loop
G4double prevPM = currentPM;
@@ -169,16 +183,15 @@ void G4Cerenkov::BuildPhysicsTable(const G4ParticleDefinition&)
// loop over all (photon energy, refraction index)
// pairs stored for this material
for(size_t ii = 1; ii < theRefractionIndexVector->GetVectorLength();
++ii)
for(size_t ii = 1; ii < refractiveIndex->GetVectorLength(); ++ii)
{
currentRI = (*theRefractionIndexVector)[ii];
currentPM = theRefractionIndexVector->Energy(ii);
currentRI = (*refractiveIndex)[ii];
currentPM = refractiveIndex->Energy(ii);
currentCAI = prevCAI + (currentPM - prevPM) * 0.5 *
(1.0 / (prevRI * prevRI) +
1.0 / (currentRI * currentRI));
aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCAI);
cerenkovIntegral->InsertValues(currentPM, currentCAI);
prevPM = currentPM;
prevCAI = currentCAI;
@@ -191,7 +204,7 @@ void G4Cerenkov::BuildPhysicsTable(const G4ParticleDefinition&)
// The Cerenkov integral for a given material will be inserted in
// thePhysicsTable according to the position of the material in
// the material table.
thePhysicsTable->insertAt(i, aPhysicsOrderedFreeVector);
thePhysicsTable->insertAt(i, cerenkovIntegral);
}
}
@@ -206,10 +219,6 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
// they are added to the particle change.
{
////////////////////////////////////////////////////
// Should we ensure that the material is dispersive?
////////////////////////////////////////////////////
aParticleChange.Initialize(aTrack);
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
@@ -233,8 +242,6 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
G4double charge = aParticle->GetDefinition()->GetPDGCharge();
G4double beta = (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta()) * 0.5;
// fNumPhotons = 0; // in PostStepGetPhysicalInteractionLength()
G4double MeanNumberOfPhotons =
GetAverageNumberOfPhotons(charge, beta, aMaterial, Rindex);
@@ -447,9 +454,8 @@ G4double G4Cerenkov::PostStepGetPhysicalInteractionLength(
particleType, kineticEnergy, couple);
G4double Step = Range - RangeMin;
// If the step is smaller than 1e-16 mm, it may happen that the particle
// If the step is smaller than 1e-15 mm, it may happen that the particle
// does not move. See bug 1992.
// 2019-03-11: change to 1e-15
if(Step < 1.e-15 * mm)
return StepLimit;
@@ -493,22 +499,21 @@ G4double G4Cerenkov::GetAverageNumberOfPhotons(
const G4double charge, const G4double beta, const G4Material* aMaterial,
G4MaterialPropertyVector* Rindex) const
// This routine computes the number of Cerenkov photons produced per
// GEANT4-unit (millimeter) in the current medium.
// ^^^^^^^^^^
// Geant4-unit (millimeter) in the current medium.
{
const G4double Rfact = 369.81 / (eV * cm);
constexpr G4double Rfact = 369.81 / (eV * cm);
if(beta <= 0.0)
return 0.0;
G4double BetaInverse = 1. / beta;
// Vectors used in computation of Cerenkov Angle Integral:
// - Refraction Indices for the current material
// - new G4PhysicsOrderedFreeVector allocated to hold CAI's
// - new G4PhysicsFreeVector allocated to hold CAI's
G4int materialIndex = aMaterial->GetIndex();
// Retrieve the Cerenkov Angle Integrals for this material
G4PhysicsOrderedFreeVector* CerenkovAngleIntegrals =
(G4PhysicsOrderedFreeVector*) ((*thePhysicsTable)(materialIndex));
G4PhysicsFreeVector* CerenkovAngleIntegrals =
(G4PhysicsFreeVector*) ((*thePhysicsTable)(materialIndex));
if(!(CerenkovAngleIntegrals->IsFilledVectorExist()))
return 0.0;
@@ -583,10 +588,9 @@ void G4Cerenkov::SetMaxNumPhotonsPerStep(const G4int NumPhotons)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4Cerenkov::DumpPhysicsTable() const
{
G4PhysicsOrderedFreeVector* v;
G4cout << "Dump Physics Table!" << G4endl;
for(size_t i = 0; i < thePhysicsTable->entries(); ++i)
{
v = (G4PhysicsOrderedFreeVector*) (*thePhysicsTable)[i];
v->DumpValues();
((G4PhysicsFreeVector*) (*thePhysicsTable)[i])->DumpValues();
}
}
File diff suppressed because it is too large Load Diff
@@ -23,99 +23,77 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
#include <complex>
#include "G4GammaXTRadiator.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
////////////////////////////////////////////////////////////////////////////
//
// Constructor, destructor
G4GammaXTRadiator::G4GammaXTRadiator(G4LogicalVolume* anEnvelope,
G4double alphaPlate,
G4double alphaGas,
G4Material* foilMat,G4Material* gasMat,
G4GammaXTRadiator::G4GammaXTRadiator(G4LogicalVolume* anEnvelope,
G4double alphaPlate, G4double alphaGas,
G4Material* foilMat, G4Material* gasMat,
G4double a, G4double b, G4int n,
const G4String& processName) :
G4VXTRenergyLoss(anEnvelope,foilMat,gasMat,a,b,n,processName)
const G4String& processName)
: G4VXTRenergyLoss(anEnvelope, foilMat, gasMat, a, b, n, processName)
{
G4cout<<"Gamma distributed X-ray TR radiator model is called"<<G4endl ;
G4cout << "Gamma distributed X-ray TR radiator model is called" << G4endl;
// Build energy and angular integral spectra of X-ray TR photons from
// a radiator
fAlphaPlate = alphaPlate ;
fAlphaGas = alphaGas ;
G4cout<<"fAlphaPlate = "<<fAlphaPlate<<" ; fAlphaGas = "<<fAlphaGas<<G4endl ;
// BuildTable() ;
fAlphaPlate = alphaPlate;
fAlphaGas = alphaGas;
G4cout << "fAlphaPlate = " << fAlphaPlate << " ; fAlphaGas = " << fAlphaGas
<< G4endl;
}
///////////////////////////////////////////////////////////////////////////
G4GammaXTRadiator::~G4GammaXTRadiator() {}
G4GammaXTRadiator::~G4GammaXTRadiator()
void G4GammaXTRadiator::ProcessDescription(std::ostream& out) const
{
;
out
<< "Rough approximation describing a radiator of X-ray transition "
"radiation.\n"
"Thicknesses of plates and gas gaps are distributed according to gamma\n"
"description.\n";
}
///////////////////////////////////////////////////////////////////////////
//
// Rough approximation for radiator interference factor for the case of
// fully GamDistr radiator. The plate and gas gap thicknesses are distributed
// according to exponent. The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in coresponding material.
G4double
G4GammaXTRadiator::GetStackFactor( G4double energy,
G4double gamma, G4double varAngle )
// fully GamDistr radiator. The plate and gas gap thicknesses are distributed
// according to exponent. The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in corresponding material.
G4double G4GammaXTRadiator::GetStackFactor(G4double energy, G4double gamma,
G4double varAngle)
{
G4double result, Za, Zb, Ma, Mb ;
Za = GetPlateFormationZone(energy,gamma,varAngle) ;
Zb = GetGasFormationZone(energy,gamma,varAngle) ;
G4double result, Za, Zb, Ma, Mb;
Ma = GetPlateLinearPhotoAbs(energy) ;
Mb = GetGasLinearPhotoAbs(energy) ;
Za = GetPlateFormationZone(energy, gamma, varAngle);
Zb = GetGasFormationZone(energy, gamma, varAngle);
Ma = GetPlateLinearPhotoAbs(energy);
Mb = GetGasLinearPhotoAbs(energy);
G4complex Ca(1.0+0.5*fPlateThick*Ma/fAlphaPlate,fPlateThick/Za/fAlphaPlate) ;
G4complex Cb(1.0+0.5*fGasThick*Mb/fAlphaGas,fGasThick/Zb/fAlphaGas) ;
G4complex Ca(1.0 + 0.5 * fPlateThick * Ma / fAlphaPlate,
fPlateThick / Za / fAlphaPlate);
G4complex Cb(1.0 + 0.5 * fGasThick * Mb / fAlphaGas,
fGasThick / Zb / fAlphaGas);
G4complex Ha = std::pow(Ca,-fAlphaPlate) ;
G4complex Hb = std::pow(Cb,-fAlphaGas) ;
G4complex H = Ha*Hb ;
G4complex Ha = std::pow(Ca, -fAlphaPlate);
G4complex Hb = std::pow(Cb, -fAlphaGas);
G4complex H = Ha * Hb;
G4complex F1 = (1.0 - Ha)*(1.0 - Hb )/(1.0 - H)
* G4double(fPlateNumber) ;
G4complex F1 = (1.0 - Ha) * (1.0 - Hb) / (1.0 - H) * G4double(fPlateNumber);
G4complex F2 = (1.0-Ha)*(1.0-Ha)*Hb/(1.0-H)/(1.0-H)
* (1.0 - std::pow(H,fPlateNumber)) ;
G4complex F2 = (1.0 - Ha) * (1.0 - Ha) * Hb / (1.0 - H) / (1.0 - H) *
(1.0 - std::pow(H, fPlateNumber));
G4complex R = (F1 + F2)*OneInterfaceXTRdEdx(energy,gamma,varAngle) ;
G4complex R = (F1 + F2) * OneInterfaceXTRdEdx(energy, gamma, varAngle);
result = 2.0*std::real(R) ;
return result ;
result = 2.0 * std::real(R);
return result;
}
//
//
////////////////////////////////////////////////////////////////////////////
@@ -23,235 +23,142 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
#include <complex>
#include "G4RegularXTRadiator.hh"
#include "G4PhysicalConstants.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
#include "G4PhysicalConstants.hh"
////////////////////////////////////////////////////////////////////////////
//
// Constructor, destructor
G4RegularXTRadiator::G4RegularXTRadiator(G4LogicalVolume *anEnvelope,
G4Material* foilMat,G4Material* gasMat,
G4double a, G4double b, G4int n,
const G4String& processName) :
G4VXTRenergyLoss(anEnvelope,foilMat,gasMat,a,b,n,processName)
G4RegularXTRadiator::G4RegularXTRadiator(G4LogicalVolume* anEnvelope,
G4Material* foilMat,
G4Material* gasMat, G4double a,
G4double b, G4int n,
const G4String& processName)
: G4VXTRenergyLoss(anEnvelope, foilMat, gasMat, a, b, n, processName)
{
G4cout<<"Regular X-ray TR radiator EM process is called"<<G4endl ;
G4cout << "Regular X-ray TR radiator EM process is called" << G4endl;
// Build energy and angular integral spectra of X-ray TR photons from
// a radiator
fAlphaPlate = 10000;
fAlphaGas = 1000;
G4cout<<"fAlphaPlate = "<<fAlphaPlate<<" ; fAlphaGas = "<<fAlphaGas<<G4endl ;
// BuildTable() ;
G4cout << "fAlphaPlate = " << fAlphaPlate << " ; fAlphaGas = " << fAlphaGas
<< G4endl;
}
///////////////////////////////////////////////////////////////////////////
G4RegularXTRadiator::~G4RegularXTRadiator() {}
G4RegularXTRadiator::~G4RegularXTRadiator()
void G4RegularXTRadiator::ProcessDescription(std::ostream& out) const
{
;
out << "Simulation of X-ray transition radiation generated by\n"
"relativistic charged particles crossing the interface between\n"
"two materials. Thicknesses of plates and gaps are fixed.\n";
}
///////////////////////////////////////////////////////////////////////////
//
//
G4double G4RegularXTRadiator::SpectralXTRdEdx(G4double energy)
{
G4double result, sum = 0., tmp, cof1, cof2, cofMin, cofPHC, theta2, theta2k;
G4double aMa, bMb ,sigma, dump;
G4double result, sum = 0., tmp, cof1, cof2, cofMin, cofPHC, theta2, theta2k;
G4double aMa, bMb, sigma, dump;
G4int k, kMax, kMin;
aMa = fPlateThick*GetPlateLinearPhotoAbs(energy);
bMb = fGasThick*GetGasLinearPhotoAbs(energy);
sigma = 0.5*(aMa + bMb);
dump = std::exp(-fPlateNumber*sigma);
if(verboseLevel > 2) G4cout<<" dump = "<<dump<<G4endl;
cofPHC = 4*pi*hbarc;
tmp = (fSigma1 - fSigma2)/cofPHC/energy;
cof1 = fPlateThick*tmp;
cof2 = fGasThick*tmp;
aMa = fPlateThick * GetPlateLinearPhotoAbs(energy);
bMb = fGasThick * GetGasLinearPhotoAbs(energy);
sigma = 0.5 * (aMa + bMb);
dump = std::exp(-fPlateNumber * sigma);
if(verboseLevel > 2)
G4cout << " dump = " << dump << G4endl;
cofPHC = 4 * pi * hbarc;
tmp = (fSigma1 - fSigma2) / cofPHC / energy;
cof1 = fPlateThick * tmp;
cof2 = fGasThick * tmp;
cofMin = energy*(fPlateThick + fGasThick)/fGamma/fGamma;
cofMin += (fPlateThick*fSigma1 + fGasThick*fSigma2)/energy;
cofMin = energy * (fPlateThick + fGasThick) / fGamma / fGamma;
cofMin += (fPlateThick * fSigma1 + fGasThick * fSigma2) / energy;
cofMin /= cofPHC;
theta2 = cofPHC/(energy*(fPlateThick + fGasThick));
// if (fGamma < 1200) kMin = G4int(cofMin); // 1200 ?
// else kMin = 1;
theta2 = cofPHC / (energy * (fPlateThick + fGasThick));
kMin = G4int(cofMin);
if (cofMin > kMin) kMin++;
if(cofMin > kMin)
kMin++;
// tmp = (fPlateThick + fGasThick)*energy*fMaxThetaTR;
// tmp /= cofPHC;
// kMax = G4int(tmp);
// if(kMax < 0) kMax = 0;
// kMax += kMin;
kMax = kMin + 49; // 19; // kMin + G4int(tmp);
// tmp /= fGamma;
// if( G4int(tmp) < kMin ) kMin = G4int(tmp);
kMax = kMin + 49;
if(verboseLevel > 2)
{
G4cout<<cof1<<" "<<cof2<<" "<<cofMin<<G4endl;
G4cout<<"kMin = "<<kMin<<"; kMax = "<<kMax<<G4endl;
}
for( k = kMin; k <= kMax; k++ )
{
tmp = pi*fPlateThick*(k + cof2)/(fPlateThick + fGasThick);
result = (k - cof1)*(k - cof1)*(k + cof2)*(k + cof2);
// tmp = std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
if( k == kMin && kMin == G4int(cofMin) )
G4cout << cof1 << " " << cof2 << " " << cofMin << G4endl;
G4cout << "kMin = " << kMin << "; kMax = " << kMax << G4endl;
}
for(k = kMin; k <= kMax; ++k)
{
tmp = pi * fPlateThick * (k + cof2) / (fPlateThick + fGasThick);
result = (k - cof1) * (k - cof1) * (k + cof2) * (k + cof2);
if(k == kMin && kMin == G4int(cofMin))
{
sum += 0.5*std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum +=
0.5 * std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
else
{
sum += std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum += std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
theta2k = std::sqrt(theta2*std::abs(k-cofMin));
theta2k = std::sqrt(theta2 * std::abs(k - cofMin));
if(verboseLevel > 2)
{
// G4cout<<"k = "<<k<<"; sqrt(theta2k) = "<<theta2k<<"; tmp = "<<std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result
// <<"; sum = "<<sum<<G4endl;
G4cout<<k<<" "<<theta2k<<" "<<std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result
<<" "<<sum<<G4endl;
}
{
G4cout << k << " " << theta2k << " "
<< std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result
<< " " << sum << G4endl;
}
}
result = 2*( cof1 + cof2 )*( cof1 + cof2 )*sum/energy;
// result *= ( 1 - std::exp(-0.5*fPlateNumber*sigma) )/( 1 - std::exp(-0.5*sigma) );
// fPlateNumber;
result *= ( 1 - dump + 2*dump*fPlateNumber );
/*
fEnergy = energy;
// G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral;
G4Integrator<G4TransparentRegXTRadiator,G4double(G4VXTRenergyLoss::*)(G4double)> integral;
tmp = integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.0,0.3*fMaxThetaTR) +
integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.3*fMaxThetaTR,0.6*fMaxThetaTR) +
integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.6*fMaxThetaTR,fMaxThetaTR) ;
result += tmp;
*/
result = 2 * (cof1 + cof2) * (cof1 + cof2) * sum / energy;
result *= (1 - dump + 2 * dump * fPlateNumber);
return result;
}
///////////////////////////////////////////////////////////////////////////
//
// Approximation for radiator interference factor for the case of
// fully Regular radiator. The plate and gas gap thicknesses are fixed .
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in coresponding material.
// fully Regular radiator. The plate and gas gap thicknesses are fixed.
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in corresponding material.
G4double
G4RegularXTRadiator::GetStackFactor( G4double energy,
G4double gamma, G4double varAngle )
G4double G4RegularXTRadiator::GetStackFactor(G4double energy, G4double gamma,
G4double varAngle)
{
// some gamma (10000/1000) like algorithm
G4double result, Za, Zb, Ma, Mb;
Za = GetPlateFormationZone(energy,gamma,varAngle);
Zb = GetGasFormationZone(energy,gamma,varAngle);
Za = GetPlateFormationZone(energy, gamma, varAngle);
Zb = GetGasFormationZone(energy, gamma, varAngle);
Ma = GetPlateLinearPhotoAbs(energy);
Mb = GetGasLinearPhotoAbs(energy);
G4complex Ca(1.0 + 0.5 * fPlateThick * Ma / fAlphaPlate,
fPlateThick / Za / fAlphaPlate);
G4complex Cb(1.0 + 0.5 * fGasThick * Mb / fAlphaGas,
fGasThick / Zb / fAlphaGas);
G4complex Ca(1.0+0.5*fPlateThick*Ma/fAlphaPlate,fPlateThick/Za/fAlphaPlate);
G4complex Cb(1.0+0.5*fGasThick*Mb/fAlphaGas,fGasThick/Zb/fAlphaGas);
G4complex Ha = std::pow(Ca, -fAlphaPlate);
G4complex Hb = std::pow(Cb, -fAlphaGas);
G4complex H = Ha * Hb;
G4complex Ha = std::pow(Ca,-fAlphaPlate);
G4complex Hb = std::pow(Cb,-fAlphaGas);
G4complex H = Ha*Hb;
G4complex F1 = (1.0 - Ha)*(1.0 - Hb )/(1.0 - H)
* G4double(fPlateNumber);
G4complex F1 = (1.0 - Ha) * (1.0 - Hb) / (1.0 - H) * G4double(fPlateNumber);
G4complex F2 = (1.0-Ha)*(1.0-Ha)*Hb/(1.0-H)/(1.0-H)
* (1.0 - std::pow(H,fPlateNumber));
G4complex F2 = (1.0 - Ha) * (1.0 - Ha) * Hb / (1.0 - H) / (1.0 - H) *
(1.0 - std::pow(H, fPlateNumber));
G4complex R = (F1 + F2)*OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = 2.0*std::real(R);
return result;
/*
// numerically stable but slow algorithm
G4complex R = (F1 + F2) * OneInterfaceXTRdEdx(energy, gamma, varAngle);
G4double result, Qa, Qb, Q, aZa, bZb, aMa, bMb; // , D;
aZa = fPlateThick/GetPlateFormationZone(energy,gamma,varAngle);
bZb = fGasThick/GetGasFormationZone(energy,gamma,varAngle);
aMa = fPlateThick*GetPlateLinearPhotoAbs(energy);
bMb = fGasThick*GetGasLinearPhotoAbs(energy);
Qa = std::exp(-aMa);
Qb = std::exp(-bMb);
Q = Qa*Qb;
G4complex Ha( std::exp(-0.5*aMa)*std::cos(aZa),
-std::exp(-0.5*aMa)*std::sin(aZa) );
G4complex Hb( std::exp(-0.5*bMb)*std::cos(bZb),
-std::exp(-0.5*bMb)*std::sin(bZb) );
G4complex H = Ha*Hb;
G4complex Hs = conj(H);
D = 1.0 /( (1 - std::sqrt(Q))*(1 - std::sqrt(Q)) +
4*std::sqrt(Q)*std::sin(0.5*(aZa+bZb))*std::sin(0.5*(aZa+bZb)) );
G4complex F1 = (1.0 - Ha)*(1.0 - Hb)*(1.0 - Hs)
* G4double(fPlateNumber)*D;
G4complex F2 = (1.0-Ha)*(1.0-Ha)*Hb*(1.0-Hs)*(1.0-Hs)
* (1.0 - std::pow(H,fPlateNumber)) * D*D;
G4complex R = (F1 + F2)*OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = 2.0 * std::real(R);
G4complex S(0.,0.), c(1.,0.);
G4int k;
for(k = 1; k < fPlateNumber; k++)
{
c *= H;
S += ( G4double(fPlateNumber) - G4double(k) )*c;
}
G4complex R = (2.- Ha - 1./Ha)*S + (1. - Ha)*G4double(fPlateNumber);
R *= OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = 2.0*std::real(R);
return result;
*/
return result;
}
//
//
////////////////////////////////////////////////////////////////////////////
@@ -22,8 +22,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
////////////////////////////////////////////////////////////////////////
// Scintillation Light Class Implementation
////////////////////////////////////////////////////////////////////////
@@ -62,20 +60,29 @@
// 2001-09-17, migration of Materials to pure STL (mma)
// 2003-06-03, V.Ivanchenko fix compilation warnings
//
//
////////////////////////////////////////////////////////////////////////
#include "G4ios.hh"
#include "globals.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4ParticleTypes.hh"
#include "G4EmProcessSubType.hh"
#include "G4OpticalParameters.hh"
#include "G4ScintillationTrackInformation.hh"
#include "G4Scintillation.hh"
#include "globals.hh"
#include "G4DynamicParticle.hh"
#include "G4EmProcessSubType.hh"
#include "G4Material.hh"
#include "G4MaterialPropertiesTable.hh"
#include "G4MaterialPropertyVector.hh"
#include "G4OpticalParameters.hh"
#include "G4ParticleMomentum.hh"
#include "G4ParticleTypes.hh"
#include "G4PhysicalConstants.hh"
#include "G4PhysicsFreeVector.hh"
#include "G4PhysicsTable.hh"
#include "G4Poisson.hh"
#include "G4ScintillationTrackInformation.hh"
#include "G4StepPoint.hh"
#include "G4SystemOfUnits.hh"
#include "G4ThreeVector.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4Scintillation::G4Scintillation(const G4String& processName,
G4ProcessType type)
@@ -83,8 +90,8 @@ G4Scintillation::G4Scintillation(const G4String& processName,
, fIntegralTable1(nullptr)
, fIntegralTable2(nullptr)
, fIntegralTable3(nullptr)
, fNumPhotons(0)
, fEmSaturation(nullptr)
, fNumPhotons(0)
{
SetProcessSubType(fScintillation);
@@ -120,6 +127,23 @@ G4Scintillation::~G4Scintillation()
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4Scintillation::ProcessDescription(std::ostream& out) const
{
out << "Scintillation simulates production of optical photons produced\n"
"by a high energy particle traversing matter.\n"
"Various material properties need to be defined.\n";
G4VRestDiscreteProcess::DumpInfo();
G4OpticalParameters* params = G4OpticalParameters::Instance();
out << "Track secondaries first: " << params->GetScintTrackSecondariesFirst();
out << "Finite rise time: " << params->GetScintFiniteRiseTime();
out << "Scintillation by particle type: " << params->GetScintByParticleType();
out << "Save track information: " << params->GetScintTrackInfo();
out << "Stack photons: " << params->GetScintStackPhotons();
out << "Verbose level: " << params->GetScintVerboseLevel();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4Scintillation::IsApplicable(const G4ParticleDefinition& aParticleType)
{
@@ -142,10 +166,7 @@ void G4Scintillation::Initialise()
G4OpticalParameters* params = G4OpticalParameters::Instance();
SetTrackSecondariesFirst(params->GetScintTrackSecondariesFirst());
SetFiniteRiseTime(params->GetScintFiniteRiseTime());
SetScintillationYieldFactor(params->GetScintYieldFactor());
SetScintillationExcitationRatio(params->GetScintExcitationRatio());
SetScintillationByParticleType(params->GetScintByParticleType());
SetEnhancedTimeConstants(params->GetScintEnhancedTimeConstants());
SetScintillationTrackInfo(params->GetScintTrackInfo());
SetStackPhotons(params->GetScintStackPhotons());
SetVerboseLevel(params->GetScintVerboseLevel());
@@ -186,9 +207,9 @@ void G4Scintillation::BuildPhysicsTable(const G4ParticleDefinition&)
for(size_t i = 0; i < numOfMaterials; ++i)
{
G4PhysicsOrderedFreeVector* vector1 = new G4PhysicsOrderedFreeVector();
G4PhysicsOrderedFreeVector* vector2 = new G4PhysicsOrderedFreeVector();
G4PhysicsOrderedFreeVector* vector3 = new G4PhysicsOrderedFreeVector();
G4PhysicsFreeVector* vector1 = new G4PhysicsFreeVector();
G4PhysicsFreeVector* vector2 = new G4PhysicsFreeVector();
G4PhysicsFreeVector* vector3 = new G4PhysicsFreeVector();
// Retrieve vector of scintillation wavelength intensity for
// the material from the material's optical properties table.
@@ -197,10 +218,7 @@ void G4Scintillation::BuildPhysicsTable(const G4ParticleDefinition&)
if(MPT)
{
// integral table 1 is either FASTCOMPONENT or SCINTILLATIONCOMPONENT1
G4MaterialPropertyVector* MPV = MPT->GetProperty(kFASTCOMPONENT);
if(!MPV)
MPV = MPT->GetProperty(kSCINTILLATIONCOMPONENT1);
G4MaterialPropertyVector* MPV = MPT->GetProperty(kSCINTILLATIONCOMPONENT1);
if(MPV)
{
// Retrieve the first intensity point in vector
@@ -236,7 +254,6 @@ void G4Scintillation::BuildPhysicsTable(const G4ParticleDefinition&)
}
}
// integral table 2 is SCINTILLATIONCOMPONENT2
MPV = MPT->GetProperty(kSCINTILLATIONCOMPONENT2);
if(MPV)
{
@@ -272,10 +289,7 @@ void G4Scintillation::BuildPhysicsTable(const G4ParticleDefinition&)
}
}
}
// integral table 3 is either SLOWCOMPONENT or SCINTILLATIONCOMPONENT3
MPV = MPT->GetProperty(kSLOWCOMPONENT);
if(!MPV)
MPV = MPT->GetProperty(kSCINTILLATIONCOMPONENT3);
MPV = MPT->GetProperty(kSCINTILLATIONCOMPONENT3);
if(MPV)
{
// Retrieve the first intensity point in vector
@@ -355,30 +369,14 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
G4int N_timeconstants = 1;
// only needed for old (two time constants) version
G4MaterialPropertyVector* Fast_Intensity = nullptr;
G4MaterialPropertyVector* Slow_Intensity = nullptr;
if(fEnhancedTimeConstants)
if(MPT->GetProperty(kSCINTILLATIONCOMPONENT3))
N_timeconstants = 3;
else if(MPT->GetProperty(kSCINTILLATIONCOMPONENT2))
N_timeconstants = 2;
else if(!(MPT->GetProperty(kSCINTILLATIONCOMPONENT1)))
{
if(MPT->GetProperty(kSCINTILLATIONCOMPONENT3))
N_timeconstants = 3;
else if(MPT->GetProperty(kSCINTILLATIONCOMPONENT2))
N_timeconstants = 2;
else if(!(MPT->GetProperty(kSCINTILLATIONCOMPONENT1)))
{
// no components were specified
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
}
else
{ // OLD METHOD
Fast_Intensity = MPT->GetProperty(kFASTCOMPONENT);
Slow_Intensity = MPT->GetProperty(kSLOWCOMPONENT);
if(!Fast_Intensity && !Slow_Intensity)
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
if(Fast_Intensity && Slow_Intensity)
N_timeconstants = 2;
// no components were specified
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
G4double ResolutionScale = MPT->GetConstProperty(kRESOLUTIONSCALE);
@@ -389,61 +387,37 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
G4double yield3 = 0.;
G4double sum_yields = 0.;
if(!fEnhancedTimeConstants)
{
// Scintillation depends on particle type, energy deposited
if(fScintillationByParticleType)
{
MeanNumberOfPhotons = GetScintillationYieldByParticleType(aTrack, aStep);
}
else
{
// The default linear scintillation process
// Units: [# scintillation photons / MeV]
MeanNumberOfPhotons =
MPT->GetConstProperty(kSCINTILLATIONYIELD) * fYieldFactor;
// Birk's correction via fEmSaturation and specifying scintillation by
// by particle type are physically mutually exclusive
if(fEmSaturation)
MeanNumberOfPhotons *=
(fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep));
else
MeanNumberOfPhotons *= TotalEnergyDeposit;
}
}
if(fScintillationByParticleType)
{
MeanNumberOfPhotons = GetScintillationYieldByParticleType(
aTrack, aStep, yield1, yield2, yield3);
}
else
{
if(fScintillationByParticleType)
{
MeanNumberOfPhotons = GetScintillationYieldByParticleType(
aTrack, aStep, yield1, yield2, yield3);
}
yield1 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD1)
? MPT->GetConstProperty(kSCINTILLATIONYIELD1)
: 1.;
yield2 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD2)
? MPT->GetConstProperty(kSCINTILLATIONYIELD2)
: 0.;
yield3 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD3)
? MPT->GetConstProperty(kSCINTILLATIONYIELD3)
: 0.;
// The default linear scintillation process
// Units: [# scintillation photons / MeV]
MeanNumberOfPhotons =
MPT->GetConstProperty(kSCINTILLATIONYIELD);
// Birk's correction via fEmSaturation and specifying scintillation by
// by particle type are physically mutually exclusive
if(fEmSaturation)
MeanNumberOfPhotons *=
(fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep));
else
{
yield1 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD1)
? MPT->GetConstProperty(kSCINTILLATIONYIELD1)
: 1.;
yield2 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD2)
? MPT->GetConstProperty(kSCINTILLATIONYIELD2)
: 0.;
yield3 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD3)
? MPT->GetConstProperty(kSCINTILLATIONYIELD3)
: 0.;
// The default linear scintillation process
// Units: [# scintillation photons / MeV]
MeanNumberOfPhotons =
MPT->GetConstProperty(kSCINTILLATIONYIELD) * fYieldFactor;
// Birk's correction via fEmSaturation and specifying scintillation by
// by particle type are physically mutually exclusive
if(fEmSaturation)
MeanNumberOfPhotons *=
(fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep));
else
MeanNumberOfPhotons *= TotalEnergyDeposit;
}
sum_yields = yield1 + yield2 + yield3;
MeanNumberOfPhotons *= TotalEnergyDeposit;
}
sum_yields = yield1 + yield2 + yield3;
if(MeanNumberOfPhotons > 10.)
{
@@ -473,134 +447,66 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
G4int materialIndex = aMaterial->GetIndex();
// Retrieve the Scintillation Integral for this material
// new G4PhysicsOrderedFreeVector allocated to hold CII's
size_t numPhot = fNumPhotons;
G4double scintTime = 0.;
G4double riseTime = 0.;
G4PhysicsOrderedFreeVector* scintIntegral = nullptr;
G4ScintillationType scintType = Slow;
// new G4PhysicsFreeVector allocated to hold CII's
size_t numPhot = fNumPhotons;
G4double scintTime = 0.;
G4double riseTime = 0.;
G4PhysicsFreeVector* scintIntegral = nullptr;
G4ScintillationType scintType = Slow;
for(G4int scnt = 0; scnt < N_timeconstants; ++scnt)
{
// Original method with FAST and SLOW
if(!fEnhancedTimeConstants)
// if there is 1 time constant it is #1, etc.
if(scnt == 0)
{
if(scnt == 0)
if(N_timeconstants == 1)
{
if(N_timeconstants == 1)
{
if(Fast_Intensity)
{
scintTime = MPT->GetConstProperty(kFASTTIMECONSTANT);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kFASTSCINTILLATIONRISETIME);
}
scintType = Fast;
scintIntegral =
(G4PhysicsOrderedFreeVector*) ((*fIntegralTable1)(materialIndex));
}
if(Slow_Intensity)
{
scintTime = MPT->GetConstProperty(kSLOWTIMECONSTANT);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kSLOWSCINTILLATIONRISETIME);
}
scintType = Slow;
scintIntegral =
(G4PhysicsOrderedFreeVector*) ((*fIntegralTable3)(materialIndex));
}
}
else
{ /// N_timeconstants != 1 and still scnt == 0
G4double yieldRatio = MPT->GetConstProperty(kYIELDRATIO);
if(fExcitationRatio == 1.0 || fExcitationRatio == 0.0)
{
numPhot = G4int(std::min(yieldRatio, 1.0) * fNumPhotons);
}
else
{
numPhot = G4int(std::min(fExcitationRatio, 1.0) * fNumPhotons);
}
scintTime = MPT->GetConstProperty(kFASTTIMECONSTANT);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kFASTSCINTILLATIONRISETIME);
}
scintType = Fast;
scintIntegral =
(G4PhysicsOrderedFreeVector*) ((*fIntegralTable1)(materialIndex));
}
numPhot = fNumPhotons;
}
else
{ // scnt != 0
numPhot = fNumPhotons - numPhot;
scintTime = MPT->GetConstProperty(kSLOWTIMECONSTANT);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kSLOWSCINTILLATIONRISETIME);
}
scintType = Slow;
scintIntegral =
(G4PhysicsOrderedFreeVector*) ((*fIntegralTable3)(materialIndex));
{
numPhot = yield1 / sum_yields * fNumPhotons;
}
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME1);
}
scintType = Fast;
scintIntegral =
(G4PhysicsFreeVector*) ((*fIntegralTable1)(materialIndex));
}
else
{ // fEnhancedTimeConstants == true
// in the new method, if there is 1 time constant it is #1, etc.
// Note: fExcitationRatio is not used
if(scnt == 0)
else if(scnt == 1)
{
// to be consistent with old version (due to double->int conversion)
if(N_timeconstants == 2)
{
if(N_timeconstants == 1)
{
numPhot = fNumPhotons;
}
else
{
numPhot = yield1 / sum_yields * fNumPhotons;
}
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME1);
}
scintType = Fast;
scintIntegral =
(G4PhysicsOrderedFreeVector*) ((*fIntegralTable1)(materialIndex));
numPhot = fNumPhotons - numPhot;
}
else if(scnt == 1)
else
{
// to be consistent with old version (due to double->int conversion)
if(N_timeconstants == 2)
{
numPhot = fNumPhotons - numPhot;
}
else
{
numPhot = yield2 / sum_yields * fNumPhotons;
}
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME2);
}
scintType = Medium;
scintIntegral =
(G4PhysicsOrderedFreeVector*) ((*fIntegralTable2)(materialIndex));
numPhot = yield2 / sum_yields * fNumPhotons;
}
else if(scnt == 2)
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
if(fFiniteRiseTime)
{
numPhot = yield3 / sum_yields * fNumPhotons;
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME3);
}
scintType = Slow;
scintIntegral =
(G4PhysicsOrderedFreeVector*) ((*fIntegralTable3)(materialIndex));
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME2);
}
scintType = Medium;
scintIntegral =
(G4PhysicsFreeVector*) ((*fIntegralTable2)(materialIndex));
}
else if(scnt == 2)
{
numPhot = yield3 / sum_yields * fNumPhotons;
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
if(fFiniteRiseTime)
{
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME3);
}
scintType = Slow;
scintIntegral =
(G4PhysicsFreeVector*) ((*fIntegralTable3)(materialIndex));
}
if(!scintIntegral)
@@ -739,137 +645,6 @@ G4double G4Scintillation::sample_time(G4double tau1, G4double tau2)
return -1.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4Scintillation::GetScintillationYieldByParticleType(
const G4Track& aTrack, const G4Step& aStep)
{
// Get the G4MaterialPropertyVector containing the scintillation
// yield as a function of the energy deposited and particle type
G4ParticleDefinition* pDef = aTrack.GetDynamicParticle()->GetDefinition();
G4MaterialPropertyVector* scintVector = nullptr;
G4MaterialPropertiesTable* MPT =
aTrack.GetMaterial()->GetMaterialPropertiesTable();
// Protons
if(pDef == G4Proton::ProtonDefinition())
scintVector = MPT->GetProperty(kPROTONSCINTILLATIONYIELD);
// Deuterons
else if(pDef == G4Deuteron::DeuteronDefinition())
scintVector = MPT->GetProperty(kDEUTERONSCINTILLATIONYIELD);
// Tritons
else if(pDef == G4Triton::TritonDefinition())
scintVector = MPT->GetProperty(kTRITONSCINTILLATIONYIELD);
// Alphas
else if(pDef == G4Alpha::AlphaDefinition())
scintVector = MPT->GetProperty(kALPHASCINTILLATIONYIELD);
// Ions (particles derived from G4VIon and G4Ions) and recoil ions
// below the production cut from neutrons after hElastic
else if(pDef->GetParticleType() == "nucleus" ||
pDef == G4Neutron::NeutronDefinition())
scintVector = MPT->GetProperty(kIONSCINTILLATIONYIELD);
// Electrons (must also
else if(pDef == G4Electron::ElectronDefinition() ||
pDef == G4Gamma::GammaDefinition())
scintVector = MPT->GetProperty(kELECTRONSCINTILLATIONYIELD);
// Default for particles not enumerated/listed above
// includes gamma to account for shell-binding energy
// attributed to gamma from standard photoelectric effect)
else
scintVector = MPT->GetProperty(kELECTRONSCINTILLATIONYIELD);
// Throw an exception if no scintillation yield vector is found
if(!scintVector)
{
G4ExceptionDescription ed;
ed << "\nG4Scintillation::PostStepDoIt(): "
<< "Request for scintillation yield for energy deposit and particle\n"
<< "type without correct entry in MaterialPropertiesTable.\n"
<< "ScintillationByParticleType requires at minimum that \n"
<< "ELECTRONSCINTILLATIONYIELD is set by the user\n"
<< G4endl;
G4String comments = "Missing MaterialPropertiesTable entry - No correct "
"entry in MaterialPropertiesTable";
G4Exception("G4Scintillation::PostStepDoIt", "Scint01", FatalException, ed,
comments);
}
///////////////////////////////////////
// Calculate the scintillation light //
///////////////////////////////////////
// To account for potential nonlinearity and scintillation photon
// density along the track, light (L) is produced according to:
// L_currentStep = L(PreStepKE) - L(PreStepKE - EDep)
G4double ScintillationYield = 0.;
G4double StepEnergyDeposit = aStep.GetTotalEnergyDeposit();
G4double PreStepKineticEnergy = aStep.GetPreStepPoint()->GetKineticEnergy();
if(PreStepKineticEnergy <= scintVector->GetMaxEnergy())
{
G4double Yield1 = scintVector->Value(PreStepKineticEnergy);
G4double Yield2 =
scintVector->Value(PreStepKineticEnergy - StepEnergyDeposit);
ScintillationYield = Yield1 - Yield2;
}
else
{
G4ExceptionDescription ed;
ed << "\nG4Scintillation::GetScintillationYieldByParticleType(): Request\n"
<< "for scintillation light yield above the available energy range\n"
<< "specified in G4MaterialPropertiesTable. A linear interpolation\n"
<< "will be performed to compute the scintillation light yield using\n"
<< "(L_max / E_max) as the photon yield per unit energy." << G4endl;
G4String cmt = "\nScintillation yield may be unphysical!\n";
G4Exception("G4Scintillation::GetScintillationYieldByParticleType()",
"Scint03", JustWarning, ed, cmt);
// Units: [# scintillation photons]
ScintillationYield = scintVector->GetMaxValue() /
scintVector->GetMaxEnergy() * StepEnergyDeposit;
}
#ifdef G4DEBUG_SCINTILLATION
// Increment track aggregators
ScintTrackYield += ScintillationYield;
ScintTrackEDep += StepEnergyDeposit;
G4cout << "\n--- G4Scintillation::GetScintillationYieldByParticleType() ---\n"
<< "--\n"
<< "-- Name = "
<< aTrack.GetParticleDefinition()->GetParticleName() << "\n"
<< "-- TrackID = " << aTrack.GetTrackID() << "\n"
<< "-- ParentID = " << aTrack.GetParentID() << "\n"
<< "-- Current KE = " << aTrack.GetKineticEnergy() / MeV
<< " MeV\n"
<< "-- Step EDep = " << aStep.GetTotalEnergyDeposit() / MeV
<< " MeV\n"
<< "-- Track EDep = " << ScintTrackEDep / MeV << " MeV\n"
<< "-- Vertex KE = " << aTrack.GetVertexKineticEnergy() / MeV
<< " MeV\n"
<< "-- Step yield = " << ScintillationYield << " photons\n"
<< "-- Track yield = " << ScintTrackYield << " photons\n"
<< G4endl;
// The track has terminated within or has left the scintillator volume
if((aTrack.GetTrackStatus() == fStopButAlive) or
(aStep.GetPostStepPoint()->GetStepStatus() == fGeomBoundary))
{
// Reset aggregators for the next track
ScintTrackEDep = 0.;
ScintTrackYield = 0.;
}
#endif
return ScintillationYield;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4Scintillation::GetScintillationYieldByParticleType(
const G4Track& aTrack, const G4Step& aStep, G4double& yield1,
@@ -1069,29 +844,25 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4Scintillation::DumpPhysicsTable() const
{
G4PhysicsOrderedFreeVector* v;
if(fIntegralTable1)
{
for(size_t i = 0; i < fIntegralTable1->entries(); ++i)
{
v = (G4PhysicsOrderedFreeVector*) (*fIntegralTable1)[i];
v->DumpValues();
((G4PhysicsFreeVector*) (*fIntegralTable1)[i])->DumpValues();
}
}
if(fIntegralTable2)
{
for(size_t i = 0; i < fIntegralTable2->entries(); ++i)
{
v = (G4PhysicsOrderedFreeVector*) (*fIntegralTable2)[i];
v->DumpValues();
((G4PhysicsFreeVector*) (*fIntegralTable2)[i])->DumpValues();
}
}
if(fIntegralTable3)
{
for(size_t i = 0; i < fIntegralTable3->entries(); ++i)
{
v = (G4PhysicsOrderedFreeVector*) (*fIntegralTable3)[i];
v->DumpValues();
((G4PhysicsFreeVector*) (*fIntegralTable3)[i])->DumpValues();
}
}
}
@@ -23,8 +23,6 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// Author : Valentin Libioulle valentin.libioulle@usherbrooke.ca (3IT - GRAMS)
//
@@ -23,198 +23,164 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
#include "G4StrawTubeXTRadiator.hh"
#include "G4Gamma.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
////////////////////////////////////////////////////////////////////////////
//
// Constructor, destructor
G4StrawTubeXTRadiator::G4StrawTubeXTRadiator(G4LogicalVolume *anEnvelope,
G4Material* foilMat,G4Material* gasMat,
G4double a, G4double b, G4Material* mediumMat,
G4bool unishut,
const G4String& processName) :
G4VXTRenergyLoss(anEnvelope,foilMat,gasMat,a,b,1,processName)
G4StrawTubeXTRadiator::G4StrawTubeXTRadiator(G4LogicalVolume* anEnvelope,
G4Material* foilMat,
G4Material* gasMat, G4double a,
G4double b, G4Material* mediumMat,
G4bool unishut,
const G4String& processName)
: G4VXTRenergyLoss(anEnvelope, foilMat, gasMat, a, b, 1, processName)
{
if(verboseLevel > 0)
G4cout<<"Straw tube X-ray TR radiator EM process is called"<<G4endl;
G4cout << "Straw tube X-ray TR radiator EM process is called" << G4endl;
if( unishut )
if(unishut)
{
fAlphaPlate = 1./3.;
fAlphaPlate = 1. / 3.;
fAlphaGas = 12.4;
if(verboseLevel > 0)
G4cout<<"straw uniform shooting: "<<"fAlphaPlate = "
<<fAlphaPlate<<" ; fAlphaGas = "<<fAlphaGas<<G4endl;
G4cout << "straw uniform shooting: "
<< "fAlphaPlate = " << fAlphaPlate
<< " ; fAlphaGas = " << fAlphaGas << G4endl;
}
else
{
fAlphaPlate = 0.5;
fAlphaGas = 5.;
if(verboseLevel > 0)
G4cout<<"straw isotropical shooting: "<<"fAlphaPlate = "
<<fAlphaPlate<<" ; fAlphaGas = "<<fAlphaGas<<G4endl;
G4cout << "straw isotropical shooting: "
<< "fAlphaPlate = " << fAlphaPlate
<< " ; fAlphaGas = " << fAlphaGas << G4endl;
}
// index of medium material
// index of medium material
fMatIndex3 = mediumMat->GetIndex();
if(verboseLevel > 0)
G4cout<<"medium material = "<<mediumMat->GetName()<<G4endl;
G4cout << "medium material = " << mediumMat->GetName() << G4endl;
// plasma energy squared for plate material
fSigma3 = fPlasmaCof*mediumMat->GetElectronDensity();
fSigma3 = fPlasmaCof * mediumMat->GetElectronDensity();
if(verboseLevel > 0)
G4cout<<"medium plasma energy = "<<std::sqrt(fSigma3)/eV<<" eV"<<G4endl;
G4cout << "medium plasma energy = " << std::sqrt(fSigma3) / eV << " eV"
<< G4endl;
// Compute cofs for preparation of linear photo absorption in external medium
ComputeMediumPhotoAbsCof();
// Build energy and angular integral spectra of X-ray TR photons from
// a radiator
// BuildTable();
}
///////////////////////////////////////////////////////////////////////////
G4StrawTubeXTRadiator::~G4StrawTubeXTRadiator() {}
G4StrawTubeXTRadiator::~G4StrawTubeXTRadiator()
void G4StrawTubeXTRadiator::ProcessDescription(std::ostream& out) const
{
out << "Simulation of forward X-ray transition radiation for the case of\n"
"a straw tube radiator.\n";
}
///////////////////////////////////////////////////////////////////////////
//
// Approximation for radiator interference factor for the case of
// straw tube radiator. The plate (window, straw wall) and gas (inside straw)
// gap thicknesses are gamma distributed.
// The mean values of the plate and gas gap thicknesses
// straw tube radiator. The plate (window, straw wall) and gas (inside straw)
// gap thicknesses are gamma distributed.
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zone.
G4double
G4StrawTubeXTRadiator::GetStackFactor( G4double energy,
G4double gamma, G4double varAngle )
G4double G4StrawTubeXTRadiator::GetStackFactor(G4double energy, G4double gamma,
G4double varAngle)
{
G4double result, L2, L3, M2, M3;
L2 = GetPlateFormationZone(energy,gamma,varAngle);
L3 = GetGasFormationZone(energy,gamma,varAngle);
L2 = GetPlateFormationZone(energy, gamma, varAngle);
L3 = GetGasFormationZone(energy, gamma, varAngle);
M2 = GetPlateLinearPhotoAbs(energy);
M3 = GetGasLinearPhotoAbs(energy);
G4complex C2(1.0 + 0.5*fPlateThick*M2/fAlphaPlate, fPlateThick/L2/fAlphaPlate);
G4complex C3(1.0 + 0.5*fGasThick*M3/fAlphaGas, fGasThick/L3/fAlphaGas);
G4complex C2(1.0 + 0.5 * fPlateThick * M2 / fAlphaPlate,
fPlateThick / L2 / fAlphaPlate);
G4complex C3(1.0 + 0.5 * fGasThick * M3 / fAlphaGas,
fGasThick / L3 / fAlphaGas);
G4complex H2 = std::pow(C2,-fAlphaPlate);
G4complex H3 = std::pow(C3,-fAlphaGas);
G4complex H = H2*H3;
G4complex H2 = std::pow(C2, -fAlphaPlate);
G4complex H3 = std::pow(C3, -fAlphaGas);
G4complex H = H2 * H3;
G4complex Z1 = GetMediumComplexFZ(energy,gamma,varAngle);
G4complex Z2 = GetPlateComplexFZ(energy,gamma,varAngle);
G4complex Z3 = GetGasComplexFZ(energy,gamma,varAngle);
G4complex Z1 = GetMediumComplexFZ(energy, gamma, varAngle);
G4complex Z2 = GetPlateComplexFZ(energy, gamma, varAngle);
G4complex Z3 = GetGasComplexFZ(energy, gamma, varAngle);
G4complex R = (Z1 - Z2) * (Z1 - Z2) * (1. - H2 * H) +
(Z2 - Z3) * (Z2 - Z3) * (1. - H3) +
2. * (Z1 - Z2) * (Z2 - Z3) * H2 * (1. - H3);
G4complex R = ( Z1 - Z2 )*( Z1 - Z2 )*( 1. - H2*H ) +
( Z2 - Z3 )*( Z2 - Z3 )*( 1. - H3 ) +
2.*( Z1 - Z2 )*( Z2 - Z3 )*H2*( 1. - H3 ) ;
result = 2.0*std::real(R)*(varAngle*energy/hbarc/hbarc);
return result;
result = 2.0 * std::real(R) * (varAngle * energy / hbarc / hbarc);
return result;
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////
// Calculates formation zone for external medium. Omega is energy !!!
G4double G4StrawTubeXTRadiator::GetMediumFormationZone( G4double omega ,
G4double gamma ,
G4double varAngle )
G4double G4StrawTubeXTRadiator::GetMediumFormationZone(G4double omega,
G4double gamma,
G4double varAngle)
{
G4double cof, lambda;
lambda = 1.0/gamma/gamma + varAngle + fSigma3/omega/omega;
cof = 2.0*hbarc/omega/lambda ;
return cof ;
lambda = 1.0 / gamma / gamma + varAngle + fSigma3 / omega / omega;
cof = 2.0 * hbarc / omega / lambda;
return cof;
}
//////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////
// Calculates complex formation zone for external medium. Omega is energy !!!
G4complex G4StrawTubeXTRadiator::GetMediumComplexFZ( G4double omega ,
G4double gamma ,
G4double varAngle )
G4complex G4StrawTubeXTRadiator::GetMediumComplexFZ(G4double omega,
G4double gamma,
G4double varAngle)
{
G4double cof, length,delta, real_v, image_v;
G4double cof, length, delta, real_v, image_v;
length = 0.5*GetMediumFormationZone(omega,gamma,varAngle);
delta = length*GetMediumLinearPhotoAbs(omega);
cof = 1.0/(1.0 + delta*delta);
length = 0.5 * GetMediumFormationZone(omega, gamma, varAngle);
delta = length * GetMediumLinearPhotoAbs(omega);
cof = 1.0 / (1.0 + delta * delta);
real_v = length*cof;
image_v = real_v*delta;
real_v = length * cof;
image_v = real_v * delta;
G4complex zone(real_v,image_v);
G4complex zone(real_v, image_v);
return zone;
}
////////////////////////////////////////////////////////////////////////
//
// Computes matrix of Sandia photo absorption cross section coefficients for
// medium material
void G4StrawTubeXTRadiator::ComputeMediumPhotoAbsCof()
void G4StrawTubeXTRadiator::ComputeMediumPhotoAbsCof()
{
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const G4Material* mat = (*theMaterialTable)[fMatIndex3];
fMediumPhotoAbsCof = mat->GetSandiaTable();
const G4Material* mat = (*theMaterialTable)[fMatIndex3];
fMediumPhotoAbsCof = mat->GetSandiaTable();
}
//////////////////////////////////////////////////////////////////////
//
// Returns the value of linear photo absorption coefficient (in reciprocal
// Returns the value of linear photo absorption coefficient (in reciprocal
// length) for medium for given energy of X-ray photon omega
G4double G4StrawTubeXTRadiator::GetMediumLinearPhotoAbs(G4double omega)
G4double G4StrawTubeXTRadiator::GetMediumLinearPhotoAbs(G4double omega)
{
G4double omega2, omega3, omega4;
G4double omega2, omega3, omega4;
omega2 = omega*omega;
omega3 = omega2*omega;
omega4 = omega2*omega2;
omega2 = omega * omega;
omega3 = omega2 * omega;
omega4 = omega2 * omega2;
const G4double* SandiaCof = fMediumPhotoAbsCof->GetSandiaCofForMaterial(omega);
const G4double* SandiaCof =
fMediumPhotoAbsCof->GetSandiaCofForMaterial(omega);
G4double cross = SandiaCof[0]/omega + SandiaCof[1]/omega2 +
SandiaCof[2]/omega3 + SandiaCof[3]/omega4;
G4double cross = SandiaCof[0] / omega + SandiaCof[1] / omega2 +
SandiaCof[2] / omega3 + SandiaCof[3] / omega4;
return cross;
}
//
//
////////////////////////////////////////////////////////////////////////////
@@ -23,42 +23,39 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
//
// History: first implementation,
// History: first implementation,
// 21-5-98 V.Grichine
// 28-05-01, V.Ivanchenko minor changes to provide ANSI -wall compilation
// 04.03.05, V.Grichine: get local field interface
// 28-05-01, V.Ivanchenko minor changes to provide ANSI -wall compilation
// 04.03.05, V.Grichine: get local field interface
// 18-05-06 H. Burkhardt: Energy spectrum from function rather than table
//
//
//
//
///////////////////////////////////////////////////////////////////////////
#include "G4SynchrotronRadiation.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4UnitsTable.hh"
#include "G4EmProcessSubType.hh"
#include "G4DipBustGenerator.hh"
#include "G4Electron.hh"
#include "G4EmProcessSubType.hh"
#include "G4Log.hh"
#include "G4LossTableManager.hh"
#include "G4Gamma.hh"
#include "G4PhysicalConstants.hh"
#include "G4PropagatorInField.hh"
#include "G4SystemOfUnits.hh"
#include "G4TransportationManager.hh"
#include "G4UnitsTable.hh"
///////////////////////////////////////////////////////////////////////
//
// Constructor
//
G4SynchrotronRadiation::G4SynchrotronRadiation(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
theGamma (G4Gamma::Gamma() )
G4ProcessType type)
: G4VDiscreteProcess(processName, type)
, theGamma(G4Gamma::Gamma())
{
G4TransportationManager* transportMgr =
G4TransportationManager* transportMgr =
G4TransportationManager::GetTransportationManager();
fFieldPropagator = transportMgr->GetPropagatorInField();
@@ -74,10 +71,7 @@ G4SynchrotronRadiation::G4SynchrotronRadiation(const G4String& processName,
}
/////////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4SynchrotronRadiation::~G4SynchrotronRadiation()
{
delete genAngle;
@@ -85,122 +79,115 @@ G4SynchrotronRadiation::~G4SynchrotronRadiation()
}
/////////////////////////////// METHODS /////////////////////////////////
//
void
G4SynchrotronRadiation::SetAngularGenerator(G4VEmAngularDistribution* p)
void G4SynchrotronRadiation::SetAngularGenerator(G4VEmAngularDistribution* p)
{
if(p != genAngle) {
if(p != genAngle)
{
delete genAngle;
genAngle = p;
}
}
G4bool
G4SynchrotronRadiation::IsApplicable(const G4ParticleDefinition& particle)
G4bool G4SynchrotronRadiation::IsApplicable(
const G4ParticleDefinition& particle)
{
return (particle.GetPDGCharge() != 0.0 && !particle.IsShortLived());
return (particle.GetPDGCharge() != 0.0 && !particle.IsShortLived());
}
/////////////////////////////////////////////////////////////////////////
//
// Production of synchrotron X-ray photon
// GEANT4 internal units.
//
G4double
G4SynchrotronRadiation::GetMeanFreePath(const G4Track& trackData,
G4double,
G4ForceCondition* condition)
// Geant4 internal units.
G4double G4SynchrotronRadiation::GetMeanFreePath(const G4Track& trackData,
G4double,
G4ForceCondition* condition)
{
// gives the MeanFreePath in GEANT4 internal units
// gives the MeanFreePath in Geant4 internal units
G4double MeanFreePath = DBL_MAX;
const G4DynamicParticle* aDynamicParticle = trackData.GetDynamicParticle();
*condition = NotForced;
G4double gamma = aDynamicParticle->GetTotalEnergy()/
aDynamicParticle->GetMass();
G4double gamma =
aDynamicParticle->GetTotalEnergy() / aDynamicParticle->GetMass();
G4double particleCharge = aDynamicParticle->GetDefinition()->GetPDGCharge();
if ( gamma < 1.0e3 || 0.0 == particleCharge) { MeanFreePath = DBL_MAX; }
if(gamma < 1.0e3 || 0.0 == particleCharge)
{
MeanFreePath = DBL_MAX;
}
else
{
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4bool fieldExertsForce = false;
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4bool fieldExertsForce = false;
G4FieldManager* fieldMgr =
fFieldPropagator->FindAndSetFieldManager(trackData.GetVolume());
G4FieldManager* fieldMgr =
fFieldPropagator->FindAndSetFieldManager(trackData.GetVolume());
if ( fieldMgr != nullptr )
if(fieldMgr != nullptr)
{
// If the field manager has no field, there is no field !
fieldExertsForce = ( fieldMgr->GetDetectorField() != nullptr );
fieldExertsForce = (fieldMgr->GetDetectorField() != nullptr);
}
if ( fieldExertsForce )
{
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[4], FieldValueVec[6];
if(fieldExertsForce)
{
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[4], FieldValueVec[6];
globPosVec[0] = globPosition.x();
globPosVec[1] = globPosition.y();
globPosVec[2] = globPosition.z();
globPosVec[3] = trackData.GetGlobalTime();
pField->GetFieldValue( globPosVec, FieldValueVec );
pField->GetFieldValue(globPosVec, FieldValueVec);
FieldValue = G4ThreeVector( FieldValueVec[0],
FieldValueVec[1],
FieldValueVec[2] );
FieldValue =
G4ThreeVector(FieldValueVec[0], FieldValueVec[1], FieldValueVec[2]);
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
G4double perpB = unitMcrossB.mag();
static const G4double fLambdaConst = std::sqrt(3.0)*eplus/
(2.5*fine_structure_const*c_light);
if( perpB > 0.0 )
static const G4double fLambdaConst =
std::sqrt(3.0) * eplus / (2.5 * fine_structure_const * c_light);
if(perpB > 0.0)
{
MeanFreePath =
fLambdaConst*aDynamicParticle->GetDefinition()->GetPDGMass()
/(perpB*particleCharge*particleCharge);
MeanFreePath = fLambdaConst *
aDynamicParticle->GetDefinition()->GetPDGMass() /
(perpB * particleCharge * particleCharge);
}
if(verboseLevel > 0 && FirstTime)
{
G4cout << "G4SynchrotronRadiation::GetMeanFreePath "
<< " for particle "
<< aDynamicParticle->GetDefinition()->GetParticleName()
<< ":" << '\n' //hbunew
<< " MeanFreePath = " << G4BestUnit(MeanFreePath, "Length")
<< G4endl;
<< " for particle "
<< aDynamicParticle->GetDefinition()->GetParticleName() << ":"
<< '\n'
<< " MeanFreePath = " << G4BestUnit(MeanFreePath, "Length")
<< G4endl;
if(verboseLevel > 1)
{
G4ThreeVector pvec = aDynamicParticle->GetMomentum();
G4double Btot = FieldValue.getR();
G4double ptot = pvec.getR();
G4double rho = ptot / (MeV * c_light * Btot );
// full bending radius
G4double Theta=unitMomentum.theta(FieldValue);
// angle between particle and field
G4cout << " B = " << Btot/tesla << " Tesla"
<< " perpB = " << perpB/tesla << " Tesla"
<< " Theta = " << Theta << " std::sin(Theta)="
<< std::sin(Theta) << '\n'
<< " ptot = " << G4BestUnit(ptot,"Energy")
<< " rho = " << G4BestUnit(rho,"Length")
<< G4endl;
G4double Btot = FieldValue.getR();
G4double ptot = pvec.getR();
G4double rho = ptot / (MeV * c_light * Btot);
// full bending radius
G4double Theta = unitMomentum.theta(FieldValue);
// angle between particle and field
G4cout << " B = " << Btot / tesla << " Tesla"
<< " perpB = " << perpB / tesla << " Tesla"
<< " Theta = " << Theta
<< " std::sin(Theta)=" << std::sin(Theta) << '\n'
<< " ptot = " << G4BestUnit(ptot, "Energy")
<< " rho = " << G4BestUnit(rho, "Length") << G4endl;
}
FirstTime=false;
FirstTime = false;
}
}
}
@@ -208,220 +195,229 @@ G4SynchrotronRadiation::GetMeanFreePath(const G4Track& trackData,
}
///////////////////////////////////////////////////////////////////////////////
//
//
G4VParticleChange*
G4SynchrotronRadiation::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData )
G4VParticleChange* G4SynchrotronRadiation::PostStepDoIt(
const G4Track& trackData, const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4DynamicParticle* aDynamicParticle = trackData.GetDynamicParticle();
G4double gamma = aDynamicParticle->GetTotalEnergy()/
(aDynamicParticle->GetDefinition()->GetPDGMass());
G4double gamma = aDynamicParticle->GetTotalEnergy() /
(aDynamicParticle->GetDefinition()->GetPDGMass());
G4double particleCharge = aDynamicParticle->GetDefinition()->GetPDGCharge();
if(gamma <= 1.0e3 || 0.0 == particleCharge)
if(gamma <= 1.0e3 || 0.0 == particleCharge)
{
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
return G4VDiscreteProcess::PostStepDoIt(trackData, stepData);
}
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4bool fieldExertsForce = false;
G4FieldManager* fieldMgr =
G4bool fieldExertsForce = false;
G4FieldManager* fieldMgr =
fFieldPropagator->FindAndSetFieldManager(trackData.GetVolume());
if ( fieldMgr != nullptr )
if(fieldMgr != nullptr)
{
// If the field manager has no field, there is no field !
fieldExertsForce = ( fieldMgr->GetDetectorField() != nullptr );
fieldExertsForce = (fieldMgr->GetDetectorField() != nullptr);
}
if ( fieldExertsForce )
if(fieldExertsForce)
{
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[4], FieldValueVec[6];
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[4], FieldValueVec[6];
globPosVec[0] = globPosition.x();
globPosVec[1] = globPosition.y();
globPosVec[2] = globPosition.z();
globPosVec[3] = trackData.GetGlobalTime();
pField->GetFieldValue( globPosVec, FieldValueVec );
FieldValue = G4ThreeVector( FieldValueVec[0],
FieldValueVec[1],
FieldValueVec[2] );
pField->GetFieldValue(globPosVec, FieldValueVec);
FieldValue =
G4ThreeVector(FieldValueVec[0], FieldValueVec[1], FieldValueVec[2]);
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
G4double perpB = unitMcrossB.mag();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
G4double perpB = unitMcrossB.mag();
if(perpB > 0.0)
{
// M-C of synchrotron photon energy
G4double energyOfSR =
GetRandomEnergySR(gamma,perpB,
aDynamicParticle->GetDefinition()->GetPDGMass());
G4double energyOfSR = GetRandomEnergySR(
gamma, perpB, aDynamicParticle->GetDefinition()->GetPDGMass());
// check against insufficient energy
if( energyOfSR <= 0.0 )
if(energyOfSR <= 0.0)
{
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
return G4VDiscreteProcess::PostStepDoIt(trackData, stepData);
}
G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
G4ThreeVector gammaDirection =
genAngle->SampleDirection(aDynamicParticle,
energyOfSR, 1, 0);
G4ThreeVector gammaDirection =
genAngle->SampleDirection(aDynamicParticle, energyOfSR, 1, 0);
G4ThreeVector gammaPolarization = FieldValue.cross(gammaDirection);
gammaPolarization = gammaPolarization.unit();
gammaPolarization = gammaPolarization.unit();
// create G4DynamicParticle object for the SR photon
G4DynamicParticle* aGamma= new G4DynamicParticle ( theGamma,
gammaDirection,
energyOfSR );
aGamma->SetPolarization( gammaPolarization.x(),
gammaPolarization.y(),
gammaPolarization.z() );
G4DynamicParticle* aGamma =
new G4DynamicParticle(theGamma, gammaDirection, energyOfSR);
aGamma->SetPolarization(gammaPolarization.x(), gammaPolarization.y(),
gammaPolarization.z());
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(aGamma);
// Update the incident particle
G4double newKinEnergy = kineticEnergy - energyOfSR;
if (newKinEnergy > 0.)
if(newKinEnergy > 0.)
{
aParticleChange.ProposeEnergy( newKinEnergy );
aParticleChange.ProposeEnergy(newKinEnergy);
}
else
{
aParticleChange.ProposeEnergy( 0. );
aParticleChange.ProposeEnergy(0.);
}
}
}
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
return G4VDiscreteProcess::PostStepDoIt(trackData, stepData);
}
///////////////////////////////////////////////////////////////////////////////
//
//
G4double G4SynchrotronRadiation::InvSynFracInt(G4double x)
// direct generation
{
// from 0 to 0.7
static const G4double aa1=0 ,aa2=0.7;
static const G4int ncheb1=27;
static const G4double cheb1[] =
{ 1.22371665676046468821,0.108956475422163837267,0.0383328524358594396134,0.00759138369340257753721,
0.00205712048644963340914,0.000497810783280019308661,0.000130743691810302187818,0.0000338168760220395409734,
8.97049680900520817728e-6,2.38685472794452241466e-6,6.41923109149104165049e-7,1.73549898982749277843e-7,
4.72145949240790029153e-8,1.29039866111999149636e-8,3.5422080787089834182e-9,9.7594757336403784905e-10,
2.6979510184976065731e-10,7.480422622550977077e-11,2.079598176402699913e-11,5.79533622220841193e-12,
1.61856011449276096e-12,4.529450993473807e-13,1.2698603951096606e-13,3.566117394511206e-14,1.00301587494091e-14,
2.82515346447219e-15,7.9680747949792e-16};
static constexpr G4double aa1 = 0;
static constexpr G4double aa2 = 0.7;
static constexpr G4int ncheb1 = 27;
static constexpr G4double cheb1[ncheb1] = {
1.22371665676046468821, 0.108956475422163837267,
0.0383328524358594396134, 0.00759138369340257753721,
0.00205712048644963340914, 0.000497810783280019308661,
0.000130743691810302187818, 0.0000338168760220395409734,
8.97049680900520817728e-6, 2.38685472794452241466e-6,
6.41923109149104165049e-7, 1.73549898982749277843e-7,
4.72145949240790029153e-8, 1.29039866111999149636e-8,
3.5422080787089834182e-9, 9.7594757336403784905e-10,
2.6979510184976065731e-10, 7.480422622550977077e-11,
2.079598176402699913e-11, 5.79533622220841193e-12,
1.61856011449276096e-12, 4.529450993473807e-13,
1.2698603951096606e-13, 3.566117394511206e-14,
1.00301587494091e-14, 2.82515346447219e-15,
7.9680747949792e-16
};
// from 0.7 to 0.9132260271183847
static const G4double aa3=0.9132260271183847;
static const G4int ncheb2=27;
static const G4double cheb2[] =
{ 1.1139496701107756,0.3523967429328067,0.0713849171926623,0.01475818043595387,0.003381255637322462,
0.0008228057599452224,0.00020785506681254216,0.00005390169253706556,0.000014250571923902464,3.823880733161044e-6,
1.0381966089136036e-6,2.8457557457837253e-7,7.86223332179956e-8,2.1866609342508474e-8,6.116186259857143e-9,
1.7191233618437565e-9,4.852755117740807e-10,1.3749966961763457e-10,3.908961987062447e-11,1.1146253766895824e-11,
3.1868887323415814e-12,9.134319791300977e-13,2.6211077371181566e-13,7.588643377757906e-14,2.1528376972619e-14,
6.030906040404772e-15,1.9549163926819867e-15};
// Chebyshev with exp/log scale
// a = -Log[1 - SynFracInt[1]]; b = -Log[1 - SynFracInt[7]];
static const G4double aa4=2.4444485538746025480,aa5=9.3830728608909477079;
static const G4int ncheb3=28;
static const G4double cheb3[] =
{ 1.2292683840435586977,0.160353449247864455879,-0.0353559911947559448721,0.00776901561223573936985,
-0.00165886451971685133259,0.000335719118906954279467,-0.0000617184951079161143187,9.23534039743246708256e-6,
-6.06747198795168022842e-7,-3.07934045961999778094e-7,1.98818772614682367781e-7,-8.13909971567720135413e-8,
2.84298174969641838618e-8,-9.12829766621316063548e-9,2.77713868004820551077e-9,-8.13032767247834023165e-10,
2.31128525568385247392e-10,-6.41796873254200220876e-11,1.74815310473323361543e-11,-4.68653536933392363045e-12,
1.24016595805520752748e-12,-3.24839432979935522159e-13,8.44601465226513952994e-14,-2.18647276044246803998e-14,
5.65407548745690689978e-15,-1.46553625917463067508e-15,3.82059606377570462276e-16,-1.00457896653436912508e-16};
static const G4double aa6=33.122936966163038145;
static const G4int ncheb4=27;
static const G4double cheb4[] =
{1.69342658227676741765,0.0742766400841232319225,-0.019337880608635717358,0.00516065527473364110491,
-0.00139342012990307729473,0.000378549864052022522193,-0.000103167085583785340215,0.0000281543441271412178337,
-7.68409742018258198651e-6,2.09543221890204537392e-6,-5.70493140367526282946e-7,1.54961164548564906446e-7,
-4.19665599629607704794e-8,1.13239680054166507038e-8,-3.04223563379021441863e-9,8.13073745977562957997e-10,
-2.15969415476814981374e-10,5.69472105972525594811e-11,-1.48844799572430829499e-11,3.84901514438304484973e-12,
-9.82222575944247161834e-13,2.46468329208292208183e-13,-6.04953826265982691612e-14,1.44055805710671611984e-14,
-3.28200813577388740722e-15,6.96566359173765367675e-16,-1.294122794852896275e-16};
static constexpr G4double aa3 = 0.9132260271183847;
static constexpr G4int ncheb2 = 27;
static constexpr G4double cheb2[ncheb2] = {
1.1139496701107756, 0.3523967429328067, 0.0713849171926623,
0.01475818043595387, 0.003381255637322462, 0.0008228057599452224,
0.00020785506681254216, 0.00005390169253706556, 0.000014250571923902464,
3.823880733161044e-6, 1.0381966089136036e-6, 2.8457557457837253e-7,
7.86223332179956e-8, 2.1866609342508474e-8, 6.116186259857143e-9,
1.7191233618437565e-9, 4.852755117740807e-10, 1.3749966961763457e-10,
3.908961987062447e-11, 1.1146253766895824e-11, 3.1868887323415814e-12,
9.134319791300977e-13, 2.6211077371181566e-13, 7.588643377757906e-14,
2.1528376972619e-14, 6.030906040404772e-15, 1.9549163926819867e-15
};
// Chebyshev with exp/log scale
// a = -Log[1 - SynFracInt[1]]; b = -Log[1 - SynFracInt[7]];
static constexpr G4double aa4 = 2.4444485538746025480;
static constexpr G4double aa5 = 9.3830728608909477079;
static constexpr G4int ncheb3 = 28;
static constexpr G4double cheb3[ncheb3] = {
1.2292683840435586977, 0.160353449247864455879,
-0.0353559911947559448721, 0.00776901561223573936985,
-0.00165886451971685133259, 0.000335719118906954279467,
-0.0000617184951079161143187, 9.23534039743246708256e-6,
-6.06747198795168022842e-7, -3.07934045961999778094e-7,
1.98818772614682367781e-7, -8.13909971567720135413e-8,
2.84298174969641838618e-8, -9.12829766621316063548e-9,
2.77713868004820551077e-9, -8.13032767247834023165e-10,
2.31128525568385247392e-10, -6.41796873254200220876e-11,
1.74815310473323361543e-11, -4.68653536933392363045e-12,
1.24016595805520752748e-12, -3.24839432979935522159e-13,
8.44601465226513952994e-14, -2.18647276044246803998e-14,
5.65407548745690689978e-15, -1.46553625917463067508e-15,
3.82059606377570462276e-16, -1.00457896653436912508e-16
};
static constexpr G4double aa6 = 33.122936966163038145;
static constexpr G4int ncheb4 = 27;
static constexpr G4double cheb4[ncheb4] = {
1.69342658227676741765, 0.0742766400841232319225,
-0.019337880608635717358, 0.00516065527473364110491,
-0.00139342012990307729473, 0.000378549864052022522193,
-0.000103167085583785340215, 0.0000281543441271412178337,
-7.68409742018258198651e-6, 2.09543221890204537392e-6,
-5.70493140367526282946e-7, 1.54961164548564906446e-7,
-4.19665599629607704794e-8, 1.13239680054166507038e-8,
-3.04223563379021441863e-9, 8.13073745977562957997e-10,
-2.15969415476814981374e-10, 5.69472105972525594811e-11,
-1.48844799572430829499e-11, 3.84901514438304484973e-12,
-9.82222575944247161834e-13, 2.46468329208292208183e-13,
-6.04953826265982691612e-14, 1.44055805710671611984e-14,
-3.28200813577388740722e-15, 6.96566359173765367675e-16,
-1.294122794852896275e-16
};
if(x<aa2) return x*x*x*Chebyshev(aa1,aa2,cheb1,ncheb1,x);
else if(x<aa3) return Chebyshev(aa2,aa3,cheb2,ncheb2,x);
else if(x<1-0.0000841363)
{ G4double y=-G4Log(1-x);
return y*Chebyshev(aa4,aa5,cheb3,ncheb3,y);
if(x < aa2)
return x * x * x * Chebyshev(aa1, aa2, cheb1, ncheb1, x);
else if(x < aa3)
return Chebyshev(aa2, aa3, cheb2, ncheb2, x);
else if(x < 1 - 0.0000841363)
{
G4double y = -G4Log(1 - x);
return y * Chebyshev(aa4, aa5, cheb3, ncheb3, y);
}
else
{ G4double y=-G4Log(1-x);
return y*Chebyshev(aa5,aa6,cheb4,ncheb4,y);
{
G4double y = -G4Log(1 - x);
return y * Chebyshev(aa5, aa6, cheb4, ncheb4, y);
}
}
G4double G4SynchrotronRadiation::GetRandomEnergySR(
G4double gamma, G4double perpB, G4double mass_c2)
G4double G4SynchrotronRadiation::GetRandomEnergySR(G4double gamma,
G4double perpB,
G4double mass_c2)
{
static const G4double fEnergyConst = 1.5*c_light*c_light*eplus*hbar_Planck;
G4double Ecr=fEnergyConst*gamma*gamma*perpB/mass_c2;
static const G4double fEnergyConst =
1.5 * c_light * c_light * eplus * hbar_Planck;
G4double Ecr = fEnergyConst * gamma * gamma * perpB / mass_c2;
if(verboseLevel > 0 && FirstTime1)
{
// mean and rms of photon energy
G4double Emean=8./(15.*std::sqrt(3.))*Ecr;
G4double E_rms=std::sqrt(211./675.)*Ecr;
G4int prec = G4cout.precision();
G4cout << "G4SynchrotronRadiation::GetRandomEnergySR :" << '\n'
<< std::setprecision(4)
<< " Ecr = " << G4BestUnit(Ecr,"Energy") << '\n'
<< " Emean = " << G4BestUnit(Emean,"Energy") << '\n'
<< " E_rms = " << G4BestUnit(E_rms,"Energy") << G4endl;
FirstTime1=false;
G4cout.precision(prec);
{
// mean and rms of photon energy
G4double Emean = 8. / (15. * std::sqrt(3.)) * Ecr;
G4double E_rms = std::sqrt(211. / 675.) * Ecr;
G4int prec = G4cout.precision();
G4cout << "G4SynchrotronRadiation::GetRandomEnergySR :" << '\n'
<< std::setprecision(4) << " Ecr = " << G4BestUnit(Ecr, "Energy")
<< '\n'
<< " Emean = " << G4BestUnit(Emean, "Energy") << '\n'
<< " E_rms = " << G4BestUnit(E_rms, "Energy") << G4endl;
FirstTime1 = false;
G4cout.precision(prec);
}
G4double energySR=Ecr*InvSynFracInt(G4UniformRand());
G4double energySR = Ecr * InvSynFracInt(G4UniformRand());
return energySR;
}
///////////////////////////////////////////////////////////////////////////////
//
//
void
G4SynchrotronRadiation::BuildPhysicsTable(const G4ParticleDefinition& part)
void G4SynchrotronRadiation::BuildPhysicsTable(const G4ParticleDefinition& part)
{
if(0 < verboseLevel && &part==G4Electron::Electron() ) PrintInfoDefinition();
if(0 < verboseLevel && &part == G4Electron::Electron())
ProcessDescription(G4cout);
// same for all particles, print only for one (electron)
}
///////////////////////////////////////////////////////////////////////////////
//
//
void G4SynchrotronRadiation::PrintInfoDefinition()
// not yet called, usually called from BuildPhysicsTable
void G4SynchrotronRadiation::ProcessDescription(std::ostream& out) const
{
G4String comments ="Incoherent Synchrotron Radiation\n";
G4cout << G4endl << GetProcessName() << ": " << comments
<< " good description for long magnets at all energies"
<< G4endl;
out << GetProcessName()
<< ": Incoherent Synchrotron Radiation\n"
"Good description for long magnets at all energies.\n";
}
///////////////////// end of G4SynchrotronRadiation.cc
@@ -23,11 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
//
// History: first implementation,
// 21-5-98 V.Grichine
@@ -35,650 +32,553 @@
// 04.03.05, V.Grichine: get local field interface
// 19-05-06, V.Ivanchenko rename from G4SynchrotronRadiation
//
//
///////////////////////////////////////////////////////////////////////////
#include "G4SynchrotronRadiationInMat.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4Integrator.hh"
#include "G4EmProcessSubType.hh"
#include "G4Field.hh"
#include "G4FieldManager.hh"
#include "G4Integrator.hh"
#include "G4PhysicalConstants.hh"
#include "G4PropagatorInField.hh"
#include "G4SystemOfUnits.hh"
////////////////////////////////////////////////////////////////////
//
// Constant for calculation of mean free path
//
const G4double
G4SynchrotronRadiationInMat::fLambdaConst = std::sqrt(3.0)*electron_mass_c2/
(2.5*fine_structure_const*eplus*c_light) ;
/////////////////////////////////////////////////////////////////////
//
// Constant for calculation of characterictic energy
//
const G4double
G4SynchrotronRadiationInMat::fEnergyConst = 1.5*c_light*c_light*eplus*hbar_Planck/
electron_mass_c2 ;
////////////////////////////////////////////////////////////////////
//
// Array of integral probability of synchrotron photons:
//
// the corresponding energy = 0.0001*i*i*(characteristic energy)
//
const G4double
G4SynchrotronRadiationInMat::fIntegralProbabilityOfSR[200] =
{
1.000000e+00, 9.428859e-01, 9.094095e-01, 8.813971e-01, 8.565154e-01,
8.337008e-01, 8.124961e-01, 7.925217e-01, 7.735517e-01, 7.554561e-01,
7.381233e-01, 7.214521e-01, 7.053634e-01, 6.898006e-01, 6.747219e-01,
6.600922e-01, 6.458793e-01, 6.320533e-01, 6.185872e-01, 6.054579e-01,
5.926459e-01, 5.801347e-01, 5.679103e-01, 5.559604e-01, 5.442736e-01,
5.328395e-01, 5.216482e-01, 5.106904e-01, 4.999575e-01, 4.894415e-01,
4.791351e-01, 4.690316e-01, 4.591249e-01, 4.494094e-01, 4.398800e-01,
4.305320e-01, 4.213608e-01, 4.123623e-01, 4.035325e-01, 3.948676e-01,
3.863639e-01, 3.780179e-01, 3.698262e-01, 3.617858e-01, 3.538933e-01,
3.461460e-01, 3.385411e-01, 3.310757e-01, 3.237474e-01, 3.165536e-01,
3.094921e-01, 3.025605e-01, 2.957566e-01, 2.890784e-01, 2.825237e-01,
2.760907e-01, 2.697773e-01, 2.635817e-01, 2.575020e-01, 2.515365e-01,
2.456834e-01, 2.399409e-01, 2.343074e-01, 2.287812e-01, 2.233607e-01,
2.180442e-01, 2.128303e-01, 2.077174e-01, 2.027040e-01, 1.977885e-01,
1.929696e-01, 1.882457e-01, 1.836155e-01, 1.790775e-01, 1.746305e-01,
1.702730e-01, 1.660036e-01, 1.618212e-01, 1.577243e-01, 1.537117e-01,
1.497822e-01, 1.459344e-01, 1.421671e-01, 1.384791e-01, 1.348691e-01,
1.313360e-01, 1.278785e-01, 1.244956e-01, 1.211859e-01, 1.179483e-01,
1.147818e-01, 1.116850e-01, 1.086570e-01, 1.056966e-01, 1.028026e-01,
9.997405e-02, 9.720975e-02, 9.450865e-02, 9.186969e-02, 8.929179e-02,
8.677391e-02, 8.431501e-02, 8.191406e-02, 7.957003e-02, 7.728192e-02,
7.504872e-02, 7.286944e-02, 7.074311e-02, 6.866874e-02, 6.664538e-02,
6.467208e-02, 6.274790e-02, 6.087191e-02, 5.904317e-02, 5.726079e-02,
5.552387e-02, 5.383150e-02, 5.218282e-02, 5.057695e-02, 4.901302e-02,
4.749020e-02, 4.600763e-02, 4.456450e-02, 4.315997e-02, 4.179325e-02,
4.046353e-02, 3.917002e-02, 3.791195e-02, 3.668855e-02, 3.549906e-02,
3.434274e-02, 3.321884e-02, 3.212665e-02, 3.106544e-02, 3.003452e-02,
2.903319e-02, 2.806076e-02, 2.711656e-02, 2.619993e-02, 2.531021e-02,
2.444677e-02, 2.360897e-02, 2.279620e-02, 2.200783e-02, 2.124327e-02,
2.050194e-02, 1.978324e-02, 1.908662e-02, 1.841151e-02, 1.775735e-02,
1.712363e-02, 1.650979e-02, 1.591533e-02, 1.533973e-02, 1.478250e-02,
1.424314e-02, 1.372117e-02, 1.321613e-02, 1.272755e-02, 1.225498e-02,
1.179798e-02, 1.135611e-02, 1.092896e-02, 1.051609e-02, 1.011712e-02,
9.731635e-03, 9.359254e-03, 8.999595e-03, 8.652287e-03, 8.316967e-03,
7.993280e-03, 7.680879e-03, 7.379426e-03, 7.088591e-03, 6.808051e-03,
6.537491e-03, 6.276605e-03, 6.025092e-03, 5.782661e-03, 5.549027e-03,
5.323912e-03, 5.107045e-03, 4.898164e-03, 4.697011e-03, 4.503336e-03,
4.316896e-03, 4.137454e-03, 3.964780e-03, 3.798649e-03, 3.638843e-03,
3.485150e-03, 3.337364e-03, 3.195284e-03, 3.058715e-03, 2.927469e-03,
2.801361e-03, 2.680213e-03, 2.563852e-03, 2.452110e-03, 2.344824e-03
const G4double G4SynchrotronRadiationInMat::fIntegralProbabilityOfSR[200] = {
1.000000e+00, 9.428859e-01, 9.094095e-01, 8.813971e-01, 8.565154e-01,
8.337008e-01, 8.124961e-01, 7.925217e-01, 7.735517e-01, 7.554561e-01,
7.381233e-01, 7.214521e-01, 7.053634e-01, 6.898006e-01, 6.747219e-01,
6.600922e-01, 6.458793e-01, 6.320533e-01, 6.185872e-01, 6.054579e-01,
5.926459e-01, 5.801347e-01, 5.679103e-01, 5.559604e-01, 5.442736e-01,
5.328395e-01, 5.216482e-01, 5.106904e-01, 4.999575e-01, 4.894415e-01,
4.791351e-01, 4.690316e-01, 4.591249e-01, 4.494094e-01, 4.398800e-01,
4.305320e-01, 4.213608e-01, 4.123623e-01, 4.035325e-01, 3.948676e-01,
3.863639e-01, 3.780179e-01, 3.698262e-01, 3.617858e-01, 3.538933e-01,
3.461460e-01, 3.385411e-01, 3.310757e-01, 3.237474e-01, 3.165536e-01,
3.094921e-01, 3.025605e-01, 2.957566e-01, 2.890784e-01, 2.825237e-01,
2.760907e-01, 2.697773e-01, 2.635817e-01, 2.575020e-01, 2.515365e-01,
2.456834e-01, 2.399409e-01, 2.343074e-01, 2.287812e-01, 2.233607e-01,
2.180442e-01, 2.128303e-01, 2.077174e-01, 2.027040e-01, 1.977885e-01,
1.929696e-01, 1.882457e-01, 1.836155e-01, 1.790775e-01, 1.746305e-01,
1.702730e-01, 1.660036e-01, 1.618212e-01, 1.577243e-01, 1.537117e-01,
1.497822e-01, 1.459344e-01, 1.421671e-01, 1.384791e-01, 1.348691e-01,
1.313360e-01, 1.278785e-01, 1.244956e-01, 1.211859e-01, 1.179483e-01,
1.147818e-01, 1.116850e-01, 1.086570e-01, 1.056966e-01, 1.028026e-01,
9.997405e-02, 9.720975e-02, 9.450865e-02, 9.186969e-02, 8.929179e-02,
8.677391e-02, 8.431501e-02, 8.191406e-02, 7.957003e-02, 7.728192e-02,
7.504872e-02, 7.286944e-02, 7.074311e-02, 6.866874e-02, 6.664538e-02,
6.467208e-02, 6.274790e-02, 6.087191e-02, 5.904317e-02, 5.726079e-02,
5.552387e-02, 5.383150e-02, 5.218282e-02, 5.057695e-02, 4.901302e-02,
4.749020e-02, 4.600763e-02, 4.456450e-02, 4.315997e-02, 4.179325e-02,
4.046353e-02, 3.917002e-02, 3.791195e-02, 3.668855e-02, 3.549906e-02,
3.434274e-02, 3.321884e-02, 3.212665e-02, 3.106544e-02, 3.003452e-02,
2.903319e-02, 2.806076e-02, 2.711656e-02, 2.619993e-02, 2.531021e-02,
2.444677e-02, 2.360897e-02, 2.279620e-02, 2.200783e-02, 2.124327e-02,
2.050194e-02, 1.978324e-02, 1.908662e-02, 1.841151e-02, 1.775735e-02,
1.712363e-02, 1.650979e-02, 1.591533e-02, 1.533973e-02, 1.478250e-02,
1.424314e-02, 1.372117e-02, 1.321613e-02, 1.272755e-02, 1.225498e-02,
1.179798e-02, 1.135611e-02, 1.092896e-02, 1.051609e-02, 1.011712e-02,
9.731635e-03, 9.359254e-03, 8.999595e-03, 8.652287e-03, 8.316967e-03,
7.993280e-03, 7.680879e-03, 7.379426e-03, 7.088591e-03, 6.808051e-03,
6.537491e-03, 6.276605e-03, 6.025092e-03, 5.782661e-03, 5.549027e-03,
5.323912e-03, 5.107045e-03, 4.898164e-03, 4.697011e-03, 4.503336e-03,
4.316896e-03, 4.137454e-03, 3.964780e-03, 3.798649e-03, 3.638843e-03,
3.485150e-03, 3.337364e-03, 3.195284e-03, 3.058715e-03, 2.927469e-03,
2.801361e-03, 2.680213e-03, 2.563852e-03, 2.452110e-03, 2.344824e-03
};
///////////////////////////////////////////////////////////////////////
//
// Constructor
//
G4SynchrotronRadiationInMat::G4SynchrotronRadiationInMat(const G4String& processName,
G4ProcessType type):G4VDiscreteProcess (processName, type),
LowestKineticEnergy (10.*keV),
theGamma (G4Gamma::Gamma() ),
theElectron ( G4Electron::Electron() ),
thePositron ( G4Positron::Positron() ),
fAlpha(0.0), fRootNumber(80),
fVerboseLevel( verboseLevel )
///////////////////////////////////////////////////////////////////////
// Constructor
G4SynchrotronRadiationInMat::G4SynchrotronRadiationInMat(
const G4String& processName, G4ProcessType type)
: G4VDiscreteProcess(processName, type)
, theGamma(G4Gamma::Gamma())
, theElectron(G4Electron::Electron())
, thePositron(G4Positron::Positron())
, LowestKineticEnergy(10. * keV)
, fAlpha(0.0)
, fRootNumber(80)
, fVerboseLevel(verboseLevel)
{
G4TransportationManager* transportMgr = G4TransportationManager::GetTransportationManager();
G4TransportationManager* transportMgr =
G4TransportationManager::GetTransportationManager();
fFieldPropagator = transportMgr->GetPropagatorInField();
SetProcessSubType(fSynchrotronRadiation);
CutInRange = GammaCutInKineticEnergyNow = ElectronCutInKineticEnergyNow =
PositronCutInKineticEnergyNow = ParticleCutInKineticEnergyNow = fKsi =
fPsiGamma = fEta = fOrderAngleK = 0.0;
CutInRange = GammaCutInKineticEnergyNow = ElectronCutInKineticEnergyNow =
PositronCutInKineticEnergyNow = ParticleCutInKineticEnergyNow = fKsi =
fPsiGamma = fEta = fOrderAngleK = 0.0;
}
/////////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4SynchrotronRadiationInMat::~G4SynchrotronRadiationInMat()
{}
G4SynchrotronRadiationInMat::~G4SynchrotronRadiationInMat() {}
G4bool
G4SynchrotronRadiationInMat::IsApplicable( const G4ParticleDefinition& particle )
G4bool G4SynchrotronRadiationInMat::IsApplicable(
const G4ParticleDefinition& particle)
{
return ( ( &particle == (const G4ParticleDefinition *)theElectron ) ||
( &particle == (const G4ParticleDefinition *)thePositron ));
return ((&particle == (const G4ParticleDefinition*) theElectron) ||
(&particle == (const G4ParticleDefinition*) thePositron));
}
G4double G4SynchrotronRadiationInMat::GetLambdaConst()
{
return fLambdaConst;
}
G4double G4SynchrotronRadiationInMat::GetLambdaConst() { return fLambdaConst; }
G4double G4SynchrotronRadiationInMat::GetEnergyConst() { return fEnergyConst; }
G4double G4SynchrotronRadiationInMat::GetEnergyConst()
{
return fEnergyConst;
}
/////////////////////////////// METHODS /////////////////////////////////
//
//
// Production of synchrotron X-ray photon
// GEANT4 internal units.
//
G4double
G4SynchrotronRadiationInMat::GetMeanFreePath( const G4Track& trackData,
G4double,
G4ForceCondition* condition)
// Geant4 internal units.
G4double G4SynchrotronRadiationInMat::GetMeanFreePath(
const G4Track& trackData, G4double, G4ForceCondition* condition)
{
// gives the MeanFreePath in GEANT4 internal units
G4double MeanFreePath;
const G4DynamicParticle* aDynamicParticle = trackData.GetDynamicParticle();
// G4Material* aMaterial = trackData.GetMaterial();
//G4bool isOutRange ;
*condition = NotForced ;
*condition = NotForced;
G4double gamma = aDynamicParticle->GetTotalEnergy()/
aDynamicParticle->GetMass();
G4double gamma =
aDynamicParticle->GetTotalEnergy() / aDynamicParticle->GetMass();
G4double particleCharge = aDynamicParticle->GetDefinition()->GetPDGCharge();
G4double KineticEnergy = aDynamicParticle->GetKineticEnergy();
if ( KineticEnergy < LowestKineticEnergy || gamma < 1.0e3 ) MeanFreePath = DBL_MAX;
if(KineticEnergy < LowestKineticEnergy || gamma < 1.0e3)
MeanFreePath = DBL_MAX;
else
{
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4FieldManager* fieldMgr = nullptr;
G4bool fieldExertsForce = false;
G4FieldManager* fieldMgr=nullptr;
G4bool fieldExertsForce = false;
if( (particleCharge != 0.0) )
if((particleCharge != 0.0))
{
fieldMgr = fFieldPropagator->FindAndSetFieldManager( trackData.GetVolume() );
fieldMgr =
fFieldPropagator->FindAndSetFieldManager(trackData.GetVolume());
if ( fieldMgr != nullptr )
if(fieldMgr != nullptr)
{
// If the field manager has no field, there is no field !
fieldExertsForce = ( fieldMgr->GetDetectorField() != nullptr );
fieldExertsForce = (fieldMgr->GetDetectorField() != nullptr);
}
}
if ( fieldExertsForce )
{
pField = fieldMgr->GetDetectorField() ;
G4ThreeVector globPosition = trackData.GetPosition();
if(fieldExertsForce)
{
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[4], FieldValueVec[6];
G4double globPosVec[4], FieldValueVec[6];
globPosVec[0] = globPosition.x();
globPosVec[1] = globPosition.y();
globPosVec[2] = globPosition.z();
globPosVec[3] = trackData.GetGlobalTime();
pField->GetFieldValue( globPosVec, FieldValueVec );
pField->GetFieldValue(globPosVec, FieldValueVec);
FieldValue = G4ThreeVector( FieldValueVec[0],
FieldValueVec[1],
FieldValueVec[2] );
FieldValue =
G4ThreeVector(FieldValueVec[0], FieldValueVec[1], FieldValueVec[2]);
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
G4double perpB = unitMcrossB.mag();
G4double beta = aDynamicParticle->GetTotalMomentum() /
(aDynamicParticle->GetTotalEnergy());
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum) ;
G4double perpB = unitMcrossB.mag() ;
G4double beta = aDynamicParticle->GetTotalMomentum()/
(aDynamicParticle->GetTotalEnergy() );
if( perpB > 0.0 ) MeanFreePath = fLambdaConst*beta/perpB;
else MeanFreePath = DBL_MAX;
if(perpB > 0.0)
MeanFreePath = fLambdaConst * beta / perpB;
else
MeanFreePath = DBL_MAX;
}
else MeanFreePath = DBL_MAX;
else
MeanFreePath = DBL_MAX;
}
if(fVerboseLevel > 0)
{
G4cout<<"G4SynchrotronRadiationInMat::MeanFreePath = "<<MeanFreePath/m<<" m"<<G4endl;
G4cout << "G4SynchrotronRadiationInMat::MeanFreePath = " << MeanFreePath / m
<< " m" << G4endl;
}
return MeanFreePath;
}
return MeanFreePath;
}
////////////////////////////////////////////////////////////////////////////////
//
//
G4VParticleChange*
G4SynchrotronRadiationInMat::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData )
G4VParticleChange* G4SynchrotronRadiationInMat::PostStepDoIt(
const G4Track& trackData, const G4Step& stepData)
{
aParticleChange.Initialize(trackData);
const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
const G4DynamicParticle* aDynamicParticle = trackData.GetDynamicParticle();
G4double gamma = aDynamicParticle->GetTotalEnergy()/
(aDynamicParticle->GetMass() );
G4double gamma =
aDynamicParticle->GetTotalEnergy() / (aDynamicParticle->GetMass());
if(gamma <= 1.0e3 )
if(gamma <= 1.0e3)
{
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
return G4VDiscreteProcess::PostStepDoIt(trackData, stepData);
}
G4double particleCharge = aDynamicParticle->GetDefinition()->GetPDGCharge();
G4ThreeVector FieldValue;
const G4Field* pField = nullptr ;
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4FieldManager* fieldMgr=nullptr;
G4bool fieldExertsForce = false;
G4FieldManager* fieldMgr = nullptr;
G4bool fieldExertsForce = false;
if( (particleCharge != 0.0) )
if((particleCharge != 0.0))
{
fieldMgr = fFieldPropagator->FindAndSetFieldManager( trackData.GetVolume() );
if ( fieldMgr != nullptr )
fieldMgr = fFieldPropagator->FindAndSetFieldManager(trackData.GetVolume());
if(fieldMgr != nullptr)
{
// If the field manager has no field, there is no field !
fieldExertsForce = ( fieldMgr->GetDetectorField() != nullptr );
fieldExertsForce = (fieldMgr->GetDetectorField() != nullptr);
}
}
if ( fieldExertsForce )
if(fieldExertsForce)
{
pField = fieldMgr->GetDetectorField() ;
G4ThreeVector globPosition = trackData.GetPosition() ;
G4double globPosVec[4], FieldValueVec[6] ;
globPosVec[0] = globPosition.x() ;
globPosVec[1] = globPosition.y() ;
globPosVec[2] = globPosition.z() ;
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[4], FieldValueVec[6];
globPosVec[0] = globPosition.x();
globPosVec[1] = globPosition.y();
globPosVec[2] = globPosition.z();
globPosVec[3] = trackData.GetGlobalTime();
pField->GetFieldValue( globPosVec, FieldValueVec ) ;
FieldValue = G4ThreeVector( FieldValueVec[0],
FieldValueVec[1],
FieldValueVec[2] );
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
G4double perpB = unitMcrossB.mag() ;
pField->GetFieldValue(globPosVec, FieldValueVec);
FieldValue =
G4ThreeVector(FieldValueVec[0], FieldValueVec[1], FieldValueVec[2]);
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
G4double perpB = unitMcrossB.mag();
if(perpB > 0.0)
{
// M-C of synchrotron photon energy
G4double energyOfSR = GetRandomEnergySR(gamma,perpB);
G4double energyOfSR = GetRandomEnergySR(gamma, perpB);
if(fVerboseLevel > 0)
{
G4cout<<"SR photon energy = "<<energyOfSR/keV<<" keV"<<G4endl;
G4cout << "SR photon energy = " << energyOfSR / keV << " keV" << G4endl;
}
// check against insufficient energy
if( energyOfSR <= 0.0 )
// check against insufficient energy
if(energyOfSR <= 0.0)
{
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
return G4VDiscreteProcess::PostStepDoIt(trackData, stepData);
}
G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
G4ParticleMomentum
particleDirection = aDynamicParticle->GetMomentumDirection();
G4ParticleMomentum particleDirection =
aDynamicParticle->GetMomentumDirection();
// M-C of its direction, simplified dipole busted approach
// G4double Teta = G4UniformRand()/gamma ; // Very roughly
G4double cosTheta, sinTheta, fcos, beta;
do
{
cosTheta = 1. - 2.*G4UniformRand();
fcos = (1 + cosTheta*cosTheta)*0.5;
}
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
while( fcos < G4UniformRand() );
do
{
cosTheta = 1. - 2. * G4UniformRand();
fcos = (1 + cosTheta * cosTheta) * 0.5;
}
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
while(fcos < G4UniformRand());
beta = std::sqrt(1. - 1./(gamma*gamma));
beta = std::sqrt(1. - 1. / (gamma * gamma));
cosTheta = (cosTheta + beta)/(1. + beta*cosTheta);
cosTheta = (cosTheta + beta) / (1. + beta * cosTheta);
if( cosTheta > 1. ) cosTheta = 1.;
if( cosTheta < -1. ) cosTheta = -1.;
if(cosTheta > 1.)
cosTheta = 1.;
if(cosTheta < -1.)
cosTheta = -1.;
sinTheta = std::sqrt(1. - cosTheta*cosTheta );
sinTheta = std::sqrt(1. - cosTheta * cosTheta);
G4double Phi = twopi * G4UniformRand() ;
G4double Phi = twopi * G4UniformRand();
G4double dirx = sinTheta*std::cos(Phi) ,
diry = sinTheta*std::sin(Phi) ,
dirz = cosTheta;
G4double dirx = sinTheta * std::cos(Phi);
G4double diry = sinTheta * std::sin(Phi);
G4double dirz = cosTheta;
G4ThreeVector gammaDirection(dirx, diry, dirz);
gammaDirection.rotateUz(particleDirection);
G4ThreeVector gammaDirection ( dirx, diry, dirz);
gammaDirection.rotateUz(particleDirection);
// polarization of new gamma
// G4double sx = std::cos(Teta)*std::cos(Phi);
// G4double sy = std::cos(Teta)*std::sin(Phi);
// G4double sz = -std::sin(Teta);
G4ThreeVector gammaPolarization = FieldValue.cross(gammaDirection);
gammaPolarization = gammaPolarization.unit();
// (sx, sy, sz);
// gammaPolarization.rotateUz(particleDirection);
gammaPolarization = gammaPolarization.unit();
// create G4DynamicParticle object for the SR photon
G4DynamicParticle* aGamma= new G4DynamicParticle ( G4Gamma::Gamma(),
gammaDirection,
energyOfSR );
aGamma->SetPolarization( gammaPolarization.x(),
gammaPolarization.y(),
gammaPolarization.z() );
G4DynamicParticle* aGamma =
new G4DynamicParticle(G4Gamma::Gamma(), gammaDirection, energyOfSR);
aGamma->SetPolarization(gammaPolarization.x(), gammaPolarization.y(),
gammaPolarization.z());
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(aGamma);
aParticleChange.AddSecondary(aGamma);
// Update the incident particle
G4double newKinEnergy = kineticEnergy - energyOfSR ;
if (newKinEnergy > 0.)
// Update the incident particle
G4double newKinEnergy = kineticEnergy - energyOfSR;
if(newKinEnergy > 0.)
{
aParticleChange.ProposeMomentumDirection( particleDirection );
aParticleChange.ProposeEnergy( newKinEnergy );
aParticleChange.ProposeLocalEnergyDeposit (0.);
}
aParticleChange.ProposeMomentumDirection(particleDirection);
aParticleChange.ProposeEnergy(newKinEnergy);
aParticleChange.ProposeLocalEnergyDeposit(0.);
}
else
{
aParticleChange.ProposeEnergy( 0. );
aParticleChange.ProposeLocalEnergyDeposit (0.);
G4double charge = aDynamicParticle->GetDefinition()->GetPDGCharge();
if (charge<0.)
{
aParticleChange.ProposeEnergy(0.);
aParticleChange.ProposeLocalEnergyDeposit(0.);
G4double charge = aDynamicParticle->GetDefinition()->GetPDGCharge();
if(charge < 0.)
{
aParticleChange.ProposeTrackStatus(fStopAndKill) ;
}
else
aParticleChange.ProposeTrackStatus(fStopAndKill);
}
else
{
aParticleChange.ProposeTrackStatus(fStopButAlive) ;
}
}
}
aParticleChange.ProposeTrackStatus(fStopButAlive);
}
}
}
else
{
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
return G4VDiscreteProcess::PostStepDoIt(trackData, stepData);
}
}
return G4VDiscreteProcess::PostStepDoIt(trackData,stepData);
}
return G4VDiscreteProcess::PostStepDoIt(trackData, stepData);
}
G4double
G4SynchrotronRadiationInMat::GetPhotonEnergy( const G4Track& trackData,
const G4Step& )
G4double G4SynchrotronRadiationInMat::GetPhotonEnergy(const G4Track& trackData,
const G4Step&)
{
G4int i ;
G4double energyOfSR = -1.0 ;
//G4Material* aMaterial=trackData.GetMaterial() ;
G4int i;
G4double energyOfSR = -1.0;
const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
const G4DynamicParticle* aDynamicParticle = trackData.GetDynamicParticle();
G4double gamma = aDynamicParticle->GetTotalEnergy()/
(aDynamicParticle->GetMass() ) ;
G4double gamma =
aDynamicParticle->GetTotalEnergy() / (aDynamicParticle->GetMass());
G4double particleCharge = aDynamicParticle->GetDefinition()->GetPDGCharge();
G4ThreeVector FieldValue;
const G4Field* pField = nullptr ;
G4ThreeVector FieldValue;
const G4Field* pField = nullptr;
G4FieldManager* fieldMgr=nullptr;
G4bool fieldExertsForce = false;
G4FieldManager* fieldMgr = nullptr;
G4bool fieldExertsForce = false;
if( (particleCharge != 0.0) )
if((particleCharge != 0.0))
{
fieldMgr = fFieldPropagator->FindAndSetFieldManager( trackData.GetVolume() );
if ( fieldMgr != nullptr )
fieldMgr = fFieldPropagator->FindAndSetFieldManager(trackData.GetVolume());
if(fieldMgr != nullptr)
{
// If the field manager has no field, there is no field !
fieldExertsForce = ( fieldMgr->GetDetectorField() != 0 );
fieldExertsForce = (fieldMgr->GetDetectorField() != nullptr);
}
}
if ( fieldExertsForce )
{
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[3], FieldValueVec[3];
if(fieldExertsForce)
{
pField = fieldMgr->GetDetectorField();
G4ThreeVector globPosition = trackData.GetPosition();
G4double globPosVec[3], FieldValueVec[3];
globPosVec[0] = globPosition.x();
globPosVec[1] = globPosition.y();
globPosVec[2] = globPosition.z();
pField->GetFieldValue( globPosVec, FieldValueVec );
FieldValue = G4ThreeVector( FieldValueVec[0],
FieldValueVec[1],
FieldValueVec[2] );
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum) ;
pField->GetFieldValue(globPosVec, FieldValueVec);
FieldValue =
G4ThreeVector(FieldValueVec[0], FieldValueVec[1], FieldValueVec[2]);
G4ThreeVector unitMomentum = aDynamicParticle->GetMomentumDirection();
G4ThreeVector unitMcrossB = FieldValue.cross(unitMomentum);
G4double perpB = unitMcrossB.mag();
if( perpB > 0.0 )
if(perpB > 0.0)
{
// M-C of synchrotron photon energy
G4double random = G4UniformRand() ;
for(i=0;i<200;i++)
G4double random = G4UniformRand();
for(i = 0; i < 200; ++i)
{
if(random >= fIntegralProbabilityOfSR[i]) break ;
if(random >= fIntegralProbabilityOfSR[i])
break;
}
energyOfSR = 0.0001*i*i*fEnergyConst*gamma*gamma*perpB ;
energyOfSR = 0.0001 * i * i * fEnergyConst * gamma * gamma * perpB;
// check against insufficient energy
if(energyOfSR <= 0.0)
{
return -1.0 ;
return -1.0;
}
//G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
//G4ParticleMomentum
//particleDirection = aDynamicParticle->GetMomentumDirection();
// Gamma production cut in this material
//G4double
//gammaEnergyCut = (G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
// SR photon has energy more than the current material cut
// M-C of its direction
//G4double Teta = G4UniformRand()/gamma ; // Very roughly
//G4double Phi = twopi * G4UniformRand() ;
}
}
else
{
return -1.0 ;
return -1.0;
}
}
return energyOfSR ;
}
return energyOfSR;
}
/////////////////////////////////////////////////////////////////////////////////
//
//
G4double G4SynchrotronRadiationInMat::GetRandomEnergySR(G4double gamma, G4double perpB)
G4double G4SynchrotronRadiationInMat::GetRandomEnergySR(G4double gamma,
G4double perpB)
{
G4int i, iMax;
G4int i;
static constexpr G4int iMax = 200;
G4double energySR, random, position;
iMax = 200;
random = G4UniformRand();
for( i = 0; i < iMax; i++ )
for(i = 0; i < iMax; ++i)
{
if( random >= fIntegralProbabilityOfSR[i] ) break;
if(random >= fIntegralProbabilityOfSR[i])
break;
}
if(i <= 0 ) position = G4UniformRand(); // 0.
else if( i>= iMax) position = G4double(iMax);
else position = i + G4UniformRand(); // -1
//
// it was in initial implementation:
// energyOfSR = 0.0001*i*i*fEnergyConst*gamma*gamma*perpB ;
if(i <= 0)
position = G4UniformRand();
else if(i >= iMax)
position = G4double(iMax);
else
position = i + G4UniformRand();
energySR = 0.0001*position*position*fEnergyConst*gamma*gamma*perpB;
energySR =
0.0001 * position * position * fEnergyConst * gamma * gamma * perpB;
if( energySR < 0. ) energySR = 0.;
if(energySR < 0.)
energySR = 0.;
return energySR;
}
/////////////////////////////////////////////////////////////////////////
//
// return
G4double G4SynchrotronRadiationInMat::GetProbSpectrumSRforInt( G4double t)
G4double G4SynchrotronRadiationInMat::GetProbSpectrumSRforInt(G4double t)
{
G4double result, hypCos2, hypCos=std::cosh(t);
G4double result, hypCos2, hypCos = std::cosh(t);
hypCos2 = hypCos*hypCos;
result = std::cosh(5.*t/3.)*std::exp(t-fKsi*hypCos); // fKsi > 0. !
hypCos2 = hypCos * hypCos;
result = std::cosh(5. * t / 3.) * std::exp(t - fKsi * hypCos); // fKsi > 0. !
result /= hypCos2;
return result;
}
///////////////////////////////////////////////////////////////////////////
//
// return the probability to emit SR photon with relative energy
// energy/energy_c >= ksi
// for ksi <= 0. P = 1., however the method works for ksi > 0 only!
G4double G4SynchrotronRadiationInMat::GetIntProbSR( G4double ksi)
G4double G4SynchrotronRadiationInMat::GetIntProbSR(G4double ksi)
{
if (ksi <= 0.) return 1.0;
fKsi = ksi; // should be > 0. !
if(ksi <= 0.)
return 1.0;
fKsi = ksi; // should be > 0. !
G4int n;
G4double result, a;
a = fAlpha; // always = 0.
n = fRootNumber; // around default = 80
a = fAlpha; // always = 0.
n = fRootNumber; // around default = 80
G4Integrator<G4SynchrotronRadiationInMat, G4double(G4SynchrotronRadiationInMat::*)(G4double)> integral;
G4Integrator<G4SynchrotronRadiationInMat,
G4double (G4SynchrotronRadiationInMat::*)(G4double)>
integral;
result = integral.Laguerre(this,
&G4SynchrotronRadiationInMat::GetProbSpectrumSRforInt, a, n);
result = integral.Laguerre(
this, &G4SynchrotronRadiationInMat::GetProbSpectrumSRforInt, a, n);
result *= 3./5./pi;
result *= 3. / 5. / pi;
return result;
}
/////////////////////////////////////////////////////////////////////////
//
// return an auxiliary function for K_5/3 integral representation
G4double G4SynchrotronRadiationInMat::GetProbSpectrumSRforEnergy( G4double t)
G4double G4SynchrotronRadiationInMat::GetProbSpectrumSRforEnergy(G4double t)
{
G4double result, hypCos=std::cosh(t);
result = std::cosh(5.*t/3.)*std::exp(t - fKsi*hypCos); // fKsi > 0. !
G4double result, hypCos = std::cosh(t);
result = std::cosh(5. * t / 3.) * std::exp(t - fKsi * hypCos); // fKsi > 0. !
result /= hypCos;
return result;
}
///////////////////////////////////////////////////////////////////////////
//
// return the probability to emit SR photon energy with relative energy
// energy/energy_c >= ksi
// for ksi <= 0. P = 1., however the method works for ksi > 0 only!
G4double G4SynchrotronRadiationInMat::GetEnergyProbSR( G4double ksi)
G4double G4SynchrotronRadiationInMat::GetEnergyProbSR(G4double ksi)
{
if (ksi <= 0.) return 1.0;
fKsi = ksi; // should be > 0. !
if(ksi <= 0.)
return 1.0;
fKsi = ksi; // should be > 0. !
G4int n;
G4double result, a;
a = fAlpha; // always = 0.
n = fRootNumber; // around default = 80
a = fAlpha; // always = 0.
n = fRootNumber; // around default = 80
G4Integrator<G4SynchrotronRadiationInMat, G4double(G4SynchrotronRadiationInMat::*)(G4double)> integral;
G4Integrator<G4SynchrotronRadiationInMat,
G4double (G4SynchrotronRadiationInMat::*)(G4double)>
integral;
result = integral.Laguerre(this,
&G4SynchrotronRadiationInMat::GetProbSpectrumSRforEnergy, a, n);
result = integral.Laguerre(
this, &G4SynchrotronRadiationInMat::GetProbSpectrumSRforEnergy, a, n);
result *= 9.*std::sqrt(3.)*ksi/8./pi;
result *= 9. * std::sqrt(3.) * ksi / 8. / pi;
return result;
}
/////////////////////////////////////////////////////////////////////////////
//
//
G4double G4SynchrotronRadiationInMat::GetIntegrandForAngleK( G4double t)
G4double G4SynchrotronRadiationInMat::GetIntegrandForAngleK(G4double t)
{
G4double result, hypCos=std::cosh(t);
result = std::cosh(fOrderAngleK*t)*std::exp(t - fEta*hypCos); // fEta > 0. !
G4double result, hypCos = std::cosh(t);
result =
std::cosh(fOrderAngleK * t) * std::exp(t - fEta * hypCos); // fEta > 0. !
result /= hypCos;
return result;
}
//////////////////////////////////////////////////////////////////////////
//
// Return K 1/3 or 2/3 for angular distribution
G4double G4SynchrotronRadiationInMat::GetAngleK( G4double eta)
G4double G4SynchrotronRadiationInMat::GetAngleK(G4double eta)
{
fEta = eta; // should be > 0. !
fEta = eta; // should be > 0. !
G4int n;
G4double result, a;
a = fAlpha; // always = 0.
n = fRootNumber; // around default = 80
a = fAlpha; // always = 0.
n = fRootNumber; // around default = 80
G4Integrator<G4SynchrotronRadiationInMat, G4double(G4SynchrotronRadiationInMat::*)(G4double)> integral;
G4Integrator<G4SynchrotronRadiationInMat,
G4double (G4SynchrotronRadiationInMat::*)(G4double)>
integral;
result = integral.Laguerre(this,
&G4SynchrotronRadiationInMat::GetIntegrandForAngleK, a, n);
result = integral.Laguerre(
this, &G4SynchrotronRadiationInMat::GetIntegrandForAngleK, a, n);
return result;
}
/////////////////////////////////////////////////////////////////////////
//
// Relative angle diff distribution for given fKsi, which is set externally
G4double G4SynchrotronRadiationInMat::GetAngleNumberAtGammaKsi( G4double gpsi)
G4double G4SynchrotronRadiationInMat::GetAngleNumberAtGammaKsi(G4double gpsi)
{
G4double result, funK, funK2, gpsi2 = gpsi*gpsi;
G4double result, funK, funK2, gpsi2 = gpsi * gpsi;
fPsiGamma = gpsi;
fEta = 0.5*fKsi*(1. + gpsi2)*std::sqrt(1. + gpsi2);
fOrderAngleK = 1./3.;
funK = GetAngleK(fEta);
funK2 = funK*funK;
fPsiGamma = gpsi;
fEta = 0.5 * fKsi * (1. + gpsi2) * std::sqrt(1. + gpsi2);
result = gpsi2*funK2/(1. + gpsi2);
fOrderAngleK = 1. / 3.;
funK = GetAngleK(fEta);
funK2 = funK * funK;
fOrderAngleK = 2./3.;
funK = GetAngleK(fEta);
funK2 = funK*funK;
result = gpsi2 * funK2 / (1. + gpsi2);
fOrderAngleK = 2. / 3.;
funK = GetAngleK(fEta);
funK2 = funK * funK;
result += funK2;
result *= (1. + gpsi2) * fKsi;
result += funK2;
result *= (1. + gpsi2)*fKsi;
return result;
}
///////////////////// end of G4SynchrotronRadiationInMat.cc
@@ -23,11 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// G4TransitionRadiation class -- implementation file
// GEANT 4 class implementation file --- Copyright CERN 1995
// CERN Geneva Switzerland
// For information related to this code, please, contact
// CERN, CN Division, ASD Group
@@ -36,195 +34,174 @@
// 2nd version 16.12.97 V. Grichine
// 3rd version 28.07.05, P.Gumplinger add G4ProcessType to constructor
#include <cmath>
//#include <cmath>
#include "G4TransitionRadiation.hh"
#include "G4Material.hh"
#include "G4EmProcessSubType.hh"
// Local constants
const G4int G4TransitionRadiation::fSympsonNumber = 100 ;
const G4int G4TransitionRadiation::fGammaNumber = 15 ;
const G4int G4TransitionRadiation::fPointNumber = 100 ;
///////////////////////////////////////////////////////////////////////
//
// Constructor for selected couple of materials
//
G4TransitionRadiation::
G4TransitionRadiation( const G4String& processName, G4ProcessType type )
G4TransitionRadiation::G4TransitionRadiation(const G4String& processName,
G4ProcessType type)
: G4VDiscreteProcess(processName, type)
{
SetProcessSubType(fTransitionRadiation);
fMatIndex1 = fMatIndex2 = 0;
fGamma = fEnergy = fVarAngle = fMinEnergy = fMaxEnergy = fMaxTheta = fSigma1 = fSigma2 = 0.0;
fGamma = fEnergy = fVarAngle = fMinEnergy = fMaxEnergy = fMaxTheta = 0.0;
fSigma1 = fSigma2 = 0.0;
}
//////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4TransitionRadiation::~G4TransitionRadiation() {}
G4TransitionRadiation::~G4TransitionRadiation()
{}
G4bool
G4TransitionRadiation::IsApplicable(const G4ParticleDefinition& aParticleType)
void G4TransitionRadiation::ProcessDescription(std::ostream& out) const
{
return ( aParticleType.GetPDGCharge() != 0.0 );
out << "Base class for simulation of x-ray transition radiation.\n";
}
G4double G4TransitionRadiation::GetMeanFreePath(const G4Track&,
G4double,
G4ForceCondition* condition)
G4bool G4TransitionRadiation::IsApplicable(
const G4ParticleDefinition& aParticleType)
{
return (aParticleType.GetPDGCharge() != 0.0);
}
G4double G4TransitionRadiation::GetMeanFreePath(const G4Track&, G4double,
G4ForceCondition* condition)
{
*condition = Forced;
return DBL_MAX; // so TR doesn't limit mean free path
return DBL_MAX; // so TR doesn't limit mean free path
}
G4VParticleChange* G4TransitionRadiation::PostStepDoIt(const G4Track&,
const G4Step&)
const G4Step&)
{
ClearNumberOfInteractionLengthLeft();
return &aParticleChange;
}
///////////////////////////////////////////////////////////////////
//
// Sympson integral of TR spectral-angle density over energy between
// the limits energy 1 and energy2 at fixed varAngle = 1 - std::cos(Theta)
G4double
G4TransitionRadiation::IntegralOverEnergy( G4double energy1,
G4double energy2,
G4double varAngle ) const
G4double G4TransitionRadiation::IntegralOverEnergy(G4double energy1,
G4double energy2,
G4double varAngle) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(energy2 - energy1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
G4int i;
G4double h, sumEven = 0.0, sumOdd = 0.0;
h = 0.5 * (energy2 - energy1) / fSympsonNumber;
for(i = 1; i < fSympsonNumber; i++)
{
sumEven += SpectralAngleTRdensity(energy1 + 2*i*h,varAngle) ;
sumOdd += SpectralAngleTRdensity(energy1 + (2*i - 1)*h,varAngle) ;
sumEven += SpectralAngleTRdensity(energy1 + 2 * i * h, varAngle);
sumOdd += SpectralAngleTRdensity(energy1 + (2 * i - 1) * h, varAngle);
}
sumOdd += SpectralAngleTRdensity(energy1 + (2*fSympsonNumber - 1)*h,varAngle) ;
return h*( SpectralAngleTRdensity(energy1,varAngle)
+ SpectralAngleTRdensity(energy2,varAngle)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
sumOdd +=
SpectralAngleTRdensity(energy1 + (2 * fSympsonNumber - 1) * h, varAngle);
return h *
(SpectralAngleTRdensity(energy1, varAngle) +
SpectralAngleTRdensity(energy2, varAngle) + 4.0 * sumOdd +
2.0 * sumEven) /
3.0;
}
///////////////////////////////////////////////////////////////////
//
// Sympson integral of TR spectral-angle density over energy between
// the limits varAngle1 and varAngle2 at fixed energy
G4double
G4TransitionRadiation::IntegralOverAngle( G4double energy,
G4double varAngle1,
G4double varAngle2 ) const
G4double G4TransitionRadiation::IntegralOverAngle(G4double energy,
G4double varAngle1,
G4double varAngle2) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(varAngle2 - varAngle1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
G4int i;
G4double h, sumEven = 0.0, sumOdd = 0.0;
h = 0.5 * (varAngle2 - varAngle1) / fSympsonNumber;
for(i = 1; i < fSympsonNumber; ++i)
{
sumEven += SpectralAngleTRdensity(energy,varAngle1 + 2*i*h) ;
sumOdd += SpectralAngleTRdensity(energy,varAngle1 + (2*i - 1)*h) ;
sumEven += SpectralAngleTRdensity(energy, varAngle1 + 2 * i * h);
sumOdd += SpectralAngleTRdensity(energy, varAngle1 + (2 * i - 1) * h);
}
sumOdd += SpectralAngleTRdensity(energy,varAngle1 + (2*fSympsonNumber - 1)*h) ;
sumOdd +=
SpectralAngleTRdensity(energy, varAngle1 + (2 * fSympsonNumber - 1) * h);
return h*( SpectralAngleTRdensity(energy,varAngle1)
+ SpectralAngleTRdensity(energy,varAngle2)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
return h *
(SpectralAngleTRdensity(energy, varAngle1) +
SpectralAngleTRdensity(energy, varAngle2) + 4.0 * sumOdd +
2.0 * sumEven) /
3.0;
}
///////////////////////////////////////////////////////////////////
//
// The number of transition radiation photons generated in the
// angle interval between varAngle1 and varAngle2
//
G4double G4TransitionRadiation::
AngleIntegralDistribution( G4double varAngle1,
G4double varAngle2 ) const
G4double G4TransitionRadiation::AngleIntegralDistribution(
G4double varAngle1, G4double varAngle2) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(varAngle2 - varAngle1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
G4int i;
G4double h, sumEven = 0.0, sumOdd = 0.0;
h = 0.5 * (varAngle2 - varAngle1) / fSympsonNumber;
for(i = 1; i < fSympsonNumber; ++i)
{
sumEven += IntegralOverEnergy(fMinEnergy,
fMinEnergy +0.3*(fMaxEnergy-fMinEnergy),
varAngle1 + 2*i*h)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1 + 2*i*h);
sumOdd += IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle1 + (2*i - 1)*h)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1 + (2*i - 1)*h) ;
sumEven += IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
varAngle1 + 2 * i * h) +
IntegralOverEnergy(fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
fMaxEnergy, varAngle1 + 2 * i * h);
sumOdd += IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
varAngle1 + (2 * i - 1) * h) +
IntegralOverEnergy(fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
fMaxEnergy, varAngle1 + (2 * i - 1) * h);
}
sumOdd += IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle1 + (2*fSympsonNumber - 1)*h)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1 + (2*fSympsonNumber - 1)*h) ;
sumOdd +=
IntegralOverEnergy(fMinEnergy, fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
varAngle1 + (2 * fSympsonNumber - 1) * h) +
IntegralOverEnergy(fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy), fMaxEnergy,
varAngle1 + (2 * fSympsonNumber - 1) * h);
return h*(IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle1)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1)
+ IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle2)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle2)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
return h *
(IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
varAngle1) +
IntegralOverEnergy(fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
fMaxEnergy, varAngle1) +
IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
varAngle2) +
IntegralOverEnergy(fMinEnergy + 0.3 * (fMaxEnergy - fMinEnergy),
fMaxEnergy, varAngle2) +
4.0 * sumOdd + 2.0 * sumEven) /
3.0;
}
///////////////////////////////////////////////////////////////////
//
// The number of transition radiation photons, generated in the
// energy interval between energy1 and energy2
//
G4double G4TransitionRadiation::
EnergyIntegralDistribution( G4double energy1,
G4double energy2 ) const
G4double G4TransitionRadiation::EnergyIntegralDistribution(
G4double energy1, G4double energy2) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(energy2 - energy1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
G4int i;
G4double h, sumEven = 0.0, sumOdd = 0.0;
h = 0.5 * (energy2 - energy1) / fSympsonNumber;
for(i = 1; i < fSympsonNumber; ++i)
{
sumEven += IntegralOverAngle(energy1 + 2*i*h,0.0,0.01*fMaxTheta )
+ IntegralOverAngle(energy1 + 2*i*h,0.01*fMaxTheta,fMaxTheta);
sumOdd += IntegralOverAngle(energy1 + (2*i - 1)*h,0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy1 + (2*i - 1)*h,0.01*fMaxTheta,fMaxTheta) ;
sumEven +=
IntegralOverAngle(energy1 + 2 * i * h, 0.0, 0.01 * fMaxTheta) +
IntegralOverAngle(energy1 + 2 * i * h, 0.01 * fMaxTheta, fMaxTheta);
sumOdd +=
IntegralOverAngle(energy1 + (2 * i - 1) * h, 0.0, 0.01 * fMaxTheta) +
IntegralOverAngle(energy1 + (2 * i - 1) * h, 0.01 * fMaxTheta, fMaxTheta);
}
sumOdd += IntegralOverAngle(energy1 + (2*fSympsonNumber - 1)*h,
0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy1 + (2*fSympsonNumber - 1)*h,
0.01*fMaxTheta,fMaxTheta) ;
sumOdd += IntegralOverAngle(energy1 + (2 * fSympsonNumber - 1) * h, 0.0,
0.01 * fMaxTheta) +
IntegralOverAngle(energy1 + (2 * fSympsonNumber - 1) * h,
0.01 * fMaxTheta, fMaxTheta);
return h*(IntegralOverAngle(energy1,0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy1,0.01*fMaxTheta,fMaxTheta)
+ IntegralOverAngle(energy2,0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy2,0.01*fMaxTheta,fMaxTheta)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
return h *
(IntegralOverAngle(energy1, 0.0, 0.01 * fMaxTheta) +
IntegralOverAngle(energy1, 0.01 * fMaxTheta, fMaxTheta) +
IntegralOverAngle(energy2, 0.0, 0.01 * fMaxTheta) +
IntegralOverAngle(energy2, 0.01 * fMaxTheta, fMaxTheta) +
4.0 * sumOdd + 2.0 * sumEven) /
3.0;
}
// end of G4TransitionRadiation implementation file --------------------------
@@ -23,215 +23,128 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
#include <complex>
#include "G4TransparentRegXTRadiator.hh"
#include "G4PhysicalConstants.hh"
#include "Randomize.hh"
#include "G4Integrator.hh"
#include "G4Gamma.hh"
////////////////////////////////////////////////////////////////////////////
//
// Constructor, destructor
G4TransparentRegXTRadiator::G4TransparentRegXTRadiator(G4LogicalVolume *anEnvelope,
G4Material* foilMat,G4Material* gasMat,
G4double a, G4double b, G4int n,
const G4String& processName) :
G4VXTRenergyLoss(anEnvelope,foilMat,gasMat,a,b,n,processName)
G4TransparentRegXTRadiator::G4TransparentRegXTRadiator(
G4LogicalVolume* anEnvelope, G4Material* foilMat, G4Material* gasMat,
G4double a, G4double b, G4int n, const G4String& processName)
: G4VXTRenergyLoss(anEnvelope, foilMat, gasMat, a, b, n, processName)
{
if(verboseLevel > 0)
G4cout<<"Regular transparent X-ray TR radiator EM process is called"<<G4endl;
G4cout << "Regular transparent X-ray TR radiator EM process is called"
<< G4endl;
// Build energy and angular integral spectra of X-ray TR photons from
// a radiator
fAlphaPlate = 10000;
fAlphaGas = 1000;
// BuildTable();
}
///////////////////////////////////////////////////////////////////////////
G4TransparentRegXTRadiator::~G4TransparentRegXTRadiator() {}
G4TransparentRegXTRadiator::~G4TransparentRegXTRadiator()
///////////////////////////////////////////////////////////////////////////
void G4TransparentRegXTRadiator::ProcessDescription(std::ostream& out) const
{
;
out << "Simulation of forward X-ray transition radiation generated by\n"
"relativistic charged particles crossing the interface between\n"
"two materials.\n";
}
///////////////////////////////////////////////////////////////////////////
//
//
G4double G4TransparentRegXTRadiator::SpectralXTRdEdx(G4double energy)
{
G4double result, sum = 0., tmp, cof1, cof2, cofMin, cofPHC, theta2, theta2k /*, aMa, bMb ,sigma*/;
G4double result, sum = 0., tmp, cof1, cof2, cofMin, cofPHC, theta2, theta2k;
G4int k, kMax, kMin;
//aMa = fPlateThick*GetPlateLinearPhotoAbs(energy);
//bMb = fGasThick*GetGasLinearPhotoAbs(energy);
//sigma = aMa + bMb;
cofPHC = 4*pi*hbarc;
tmp = (fSigma1 - fSigma2)/cofPHC/energy;
cof1 = fPlateThick*tmp;
cof2 = fGasThick*tmp;
cofPHC = 4. * pi * hbarc;
tmp = (fSigma1 - fSigma2) / cofPHC / energy;
cof1 = fPlateThick * tmp;
cof2 = fGasThick * tmp;
cofMin = energy*(fPlateThick + fGasThick)/fGamma/fGamma;
cofMin += (fPlateThick*fSigma1 + fGasThick*fSigma2)/energy;
cofMin = energy * (fPlateThick + fGasThick) / fGamma / fGamma;
cofMin += (fPlateThick * fSigma1 + fGasThick * fSigma2) / energy;
cofMin /= cofPHC;
theta2 = cofPHC/(energy*(fPlateThick + fGasThick));
// if (fGamma < 1200) kMin = G4int(cofMin); // 1200 ?
// else kMin = 1;
theta2 = cofPHC / (energy * (fPlateThick + fGasThick));
kMin = G4int(cofMin);
if (cofMin > kMin) kMin++;
if(cofMin > kMin)
kMin++;
// tmp = (fPlateThick + fGasThick)*energy*fMaxThetaTR;
// tmp /= cofPHC;
// kMax = G4int(tmp);
// if(kMax < 0) kMax = 0;
// kMax += kMin;
kMax = kMin + 49; // 19; // kMin + G4int(tmp);
// tmp /= fGamma;
// if( G4int(tmp) < kMin ) kMin = G4int(tmp);
kMax = kMin + 49;
if(verboseLevel > 2)
{
G4cout<<cof1<<" "<<cof2<<" "<<cofMin<<G4endl;
G4cout<<"kMin = "<<kMin<<"; kMax = "<<kMax<<G4endl;
}
for( k = kMin; k <= kMax; k++ )
{
tmp = pi*fPlateThick*(k + cof2)/(fPlateThick + fGasThick);
result = (k - cof1)*(k - cof1)*(k + cof2)*(k + cof2);
// tmp = std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
if( k == kMin && kMin == G4int(cofMin) )
G4cout << cof1 << " " << cof2 << " " << cofMin << G4endl;
G4cout << "kMin = " << kMin << "; kMax = " << kMax << G4endl;
}
for(k = kMin; k <= kMax; ++k)
{
tmp = pi * fPlateThick * (k + cof2) / (fPlateThick + fGasThick);
result = (k - cof1) * (k - cof1) * (k + cof2) * (k + cof2);
if(k == kMin && kMin == G4int(cofMin))
{
sum += 0.5*std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum +=
0.5 * std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
else
{
sum += std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum += std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
theta2k = std::sqrt(theta2*std::abs(k-cofMin));
theta2k = std::sqrt(theta2 * std::abs(k - cofMin));
if(verboseLevel > 2)
{
// G4cout<<"k = "<<k<<"; sqrt(theta2k) = "<<theta2k<<"; tmp = "<<std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result
// <<"; sum = "<<sum<<G4endl;
G4cout<<k<<" "<<theta2k<<" "<<std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result
<<" "<<sum<<G4endl;
}
{
G4cout << k << " " << theta2k << " "
<< std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result
<< " " << sum << G4endl;
}
}
result = 4.*( cof1 + cof2 )*( cof1 + cof2 )*sum/energy;
// result *= ( 1 - std::exp(-0.5*fPlateNumber*sigma) )/( 1 - std::exp(-0.5*sigma) );
// fPlateNumber;
result *= fPlateNumber; // *std::exp(-0.5*fPlateNumber*sigma);
// +1-std::exp(-0.5*fPlateNumber*sigma);
/*
fEnergy = energy;
// G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral;
G4Integrator<G4TransparentRegXTRadiator,G4double(G4VXTRenergyLoss::*)(G4double)> integral;
tmp = integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.0,0.3*fMaxThetaTR) +
integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.3*fMaxThetaTR,0.6*fMaxThetaTR) +
integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.6*fMaxThetaTR,fMaxThetaTR) ;
result += tmp;
*/
result = 4. * (cof1 + cof2) * (cof1 + cof2) * sum / energy;
result *= fPlateNumber;
return result;
}
///////////////////////////////////////////////////////////////////////////
//
// Approximation for radiator interference factor for the case of
// fully Regular radiator. The plate and gas gap thicknesses are fixed .
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in coresponding material.
G4double
G4TransparentRegXTRadiator::GetStackFactor( G4double energy,
G4double gamma, G4double varAngle )
// fully Regular radiator. The plate and gas gap thicknesses are fixed.
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in corresponding material.
G4double G4TransparentRegXTRadiator::GetStackFactor(G4double energy,
G4double gamma,
G4double varAngle)
{
/*
G4double result, Za, Zb, Ma, Mb, sigma;
Za = GetPlateFormationZone(energy,gamma,varAngle);
Zb = GetGasFormationZone(energy,gamma,varAngle);
Ma = GetPlateLinearPhotoAbs(energy);
Mb = GetGasLinearPhotoAbs(energy);
sigma = Ma*fPlateThick + Mb*fGasThick;
G4double result, Qa, Qb, Q, aZa, bZb, aMa, bMb, D, sigma;
G4complex Ca(1.0+0.5*fPlateThick*Ma/fAlphaPlate,fPlateThick/Za/fAlphaPlate);
G4complex Cb(1.0+0.5*fGasThick*Mb/fAlphaGas,fGasThick/Zb/fAlphaGas);
aZa = fPlateThick / GetPlateFormationZone(energy, gamma, varAngle);
bZb = fGasThick / GetGasFormationZone(energy, gamma, varAngle);
aMa = fPlateThick * GetPlateLinearPhotoAbs(energy);
bMb = fGasThick * GetGasLinearPhotoAbs(energy);
sigma = aMa * fPlateThick + bMb * fGasThick;
Qa = std::exp(-0.5 * aMa);
Qb = std::exp(-0.5 * bMb);
Q = Qa * Qb;
G4complex Ha = std::pow(Ca,-fAlphaPlate);
G4complex Hb = std::pow(Cb,-fAlphaGas);
G4complex H = Ha*Hb;
G4complex F1 = (1.0 - Ha)*(1.0 - Hb )/(1.0 - H)
* G4double(fPlateNumber) ;
G4complex F2 = (1.0-Ha)*(1.0-Ha)*Hb/(1.0-H)/(1.0-H)
* (1.0 - std::exp(-0.5*fPlateNumber*sigma)) ;
// *(1.0 - std::pow(H,fPlateNumber)) ;
G4complex R = (F1 + F2)*OneInterfaceXTRdEdx(energy,gamma,varAngle);
// G4complex R = F2*OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = 2.0*std::real(R);
return result;
*/
// numerically unstable result
G4double result, Qa, Qb, Q, aZa, bZb, aMa, bMb, D, sigma;
aZa = fPlateThick/GetPlateFormationZone(energy,gamma,varAngle);
bZb = fGasThick/GetGasFormationZone(energy,gamma,varAngle);
aMa = fPlateThick*GetPlateLinearPhotoAbs(energy);
bMb = fGasThick*GetGasLinearPhotoAbs(energy);
sigma = aMa*fPlateThick + bMb*fGasThick;
Qa = std::exp(-0.5*aMa);
Qb = std::exp(-0.5*bMb);
Q = Qa*Qb;
G4complex Ha( Qa*std::cos(aZa), -Qa*std::sin(aZa) );
G4complex Hb( Qb*std::cos(bZb), -Qb*std::sin(bZb) );
G4complex H = Ha*Hb;
G4complex Ha(Qa * std::cos(aZa), -Qa * std::sin(aZa));
G4complex Hb(Qb * std::cos(bZb), -Qb * std::sin(bZb));
G4complex H = Ha * Hb;
G4complex Hs = conj(H);
D = 1.0 /( (1 - Q)*(1 - Q) +
4*Q*std::sin(0.5*(aZa + bZb))*std::sin(0.5*(aZa + bZb)) );
G4complex F1 = (1.0 - Ha)*(1.0 - Hb)*(1.0 - Hs)
* G4double(fPlateNumber)*D;
G4complex F2 = (1.0 - Ha)*(1.0 - Ha)*Hb*(1.0 - Hs)*(1.0 - Hs)
// * (1.0 - std::pow(H,fPlateNumber)) * D*D;
* (1.0 - std::exp(-0.5*fPlateNumber*sigma)) * D*D;
G4complex R = (F1 + F2)*OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = 2.0*std::real(R);
return result;
D = 1.0 / ((1 - Q) * (1 - Q) +
4 * Q * std::sin(0.5 * (aZa + bZb)) * std::sin(0.5 * (aZa + bZb)));
G4complex F1 =
(1.0 - Ha) * (1.0 - Hb) * (1.0 - Hs) * G4double(fPlateNumber) * D;
G4complex F2 = (1.0 - Ha) * (1.0 - Ha) * Hb * (1.0 - Hs) * (1.0 - Hs) *
(1.0 - std::exp(-0.5 * fPlateNumber * sigma)) * D * D;
G4complex R = (F1 + F2) * OneInterfaceXTRdEdx(energy, gamma, varAngle);
result = 2.0 * std::real(R);
return result;
}
//
//
////////////////////////////////////////////////////////////////////////////
@@ -23,36 +23,32 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4VTransitionRadiation class -- implementation file
// GEANT 4 class implementation file --- Copyright CERN 1995
// CERN Geneva Switzerland
// History:
// 29.02.04 V.Ivanchenko create
// 28.07.05, P.Gumplinger add G4ProcessType to constructor
#include "G4VTransitionRadiation.hh"
#include "G4ParticleDefinition.hh"
#include "G4VTRModel.hh"
#include "G4Material.hh"
#include "G4Region.hh"
#include "G4TransportationManager.hh"
#include "G4EmProcessSubType.hh"
#include "G4LossTableManager.hh"
#include "G4Material.hh"
#include "G4ParticleDefinition.hh"
#include "G4Region.hh"
#include "G4TransportationManager.hh"
#include "G4VTRModel.hh"
///////////////////////////////////////////////////////////////////////
G4VTransitionRadiation::G4VTransitionRadiation( const G4String& processName,
G4ProcessType type )
: G4VDiscreteProcess(processName, type),
region(nullptr),
model(nullptr),
nSteps(0),
gammaMin(100.),
cosDThetaMax(std::cos(0.1))
G4VTransitionRadiation::G4VTransitionRadiation(const G4String& processName,
G4ProcessType type)
: G4VDiscreteProcess(processName, type)
, region(nullptr)
, model(nullptr)
, gammaMin(100.)
, cosDThetaMax(std::cos(0.1))
, nSteps(0)
{
SetProcessSubType(fTransitionRadiation);
Clear();
@@ -61,15 +57,21 @@ G4VTransitionRadiation::G4VTransitionRadiation( const G4String& processName,
}
///////////////////////////////////////////////////////////////////////
G4VTransitionRadiation::~G4VTransitionRadiation()
{
Clear();
theManager->DeRegister(this);
}
///////////////////////////////////////////////////////////////////////
void G4VTransitionRadiation::ProcessDescription(std::ostream& out) const
{
out << "Generic process of transition radiation.\n";
if(model)
model->PrintInfo();
}
///////////////////////////////////////////////////////////////////////
void G4VTransitionRadiation::Clear()
{
materials.clear();
@@ -79,112 +81,102 @@ void G4VTransitionRadiation::Clear()
}
///////////////////////////////////////////////////////////////////////
G4VParticleChange* G4VTransitionRadiation::PostStepDoIt(
const G4Track& track,
const G4Step& step)
G4VParticleChange* G4VTransitionRadiation::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
// Fill temporary vectors
const G4Material* material = track.GetMaterial();
G4double length = step.GetStepLength();
G4ThreeVector direction = track.GetMomentumDirection();
if(nSteps == 0) {
G4double length = step.GetStepLength();
G4ThreeVector direction = track.GetMomentumDirection();
if(nSteps == 0)
{
nSteps = 1;
materials.push_back(material);
steps.push_back(length);
const G4StepPoint* point = step.GetPreStepPoint();
startingPosition = point->GetPosition();
startingDirection = point->GetMomentumDirection();
G4bool valid = true;
startingPosition = point->GetPosition();
startingDirection = point->GetMomentumDirection();
G4bool valid = true;
G4ThreeVector n = G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking()->GetLocalExitNormal(&valid);
if(valid) normals.push_back(n);
else normals.push_back(direction);
} else {
if(material == materials[nSteps-1]) {
steps[nSteps-1] += length;
} else {
nSteps++;
->GetNavigatorForTracking()
->GetLocalExitNormal(&valid);
if(valid)
normals.push_back(n);
else
normals.push_back(direction);
}
else
{
if(material == materials[nSteps - 1])
{
steps[nSteps - 1] += length;
}
else
{
++nSteps;
materials.push_back(material);
steps.push_back(length);
G4bool valid = true;
G4bool valid = true;
G4ThreeVector n = G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking()->GetLocalExitNormal(&valid);
if(valid) normals.push_back(n);
else normals.push_back(direction);
->GetNavigatorForTracking()
->GetLocalExitNormal(&valid);
if(valid)
normals.push_back(n);
else
normals.push_back(direction);
}
}
// Check POstStepPoint condition
// Check PostStepPoint condition
if(track.GetTrackStatus() == fStopAndKill ||
track.GetVolume()->GetLogicalVolume()->GetRegion() != region ||
startingDirection.x()*direction.x() +
startingDirection.y()*direction.y() +
startingDirection.z()*direction.z() < cosDThetaMax)
startingDirection.x() * direction.x() +
startingDirection.y() * direction.y() +
startingDirection.z() * direction.z() <
cosDThetaMax)
{
if(model) {
model->GenerateSecondaries(*pParticleChange, materials, steps,
normals, startingPosition, track);
}
Clear();
if(model)
{
model->GenerateSecondaries(*pParticleChange, materials, steps, normals,
startingPosition, track);
}
Clear();
}
return pParticleChange;
}
///////////////////////////////////////////////////////////////////////
G4bool G4VTransitionRadiation::IsApplicable(
const G4ParticleDefinition& aParticle)
const G4ParticleDefinition& aParticle)
{
return ( aParticle.GetPDGCharge() != 0.0 );
return (aParticle.GetPDGCharge() != 0.0);
}
///////////////////////////////////////////////////////////////////////
void G4VTransitionRadiation::SetRegion(const G4Region* reg)
{
region = reg;
}
void G4VTransitionRadiation::SetRegion(const G4Region* reg) { region = reg; }
///////////////////////////////////////////////////////////////////////
void G4VTransitionRadiation::SetModel(G4VTRModel* mod)
{
model = mod;
}
void G4VTransitionRadiation::SetModel(G4VTRModel* mod) { model = mod; }
///////////////////////////////////////////////////////////////////////
void G4VTransitionRadiation::PrintInfoDefinition()
G4double G4VTransitionRadiation::GetMeanFreePath(const G4Track& track, G4double,
G4ForceCondition* condition)
{
if(model) model->PrintInfo();
}
///////////////////////////////////////////////////////////////////////
G4double G4VTransitionRadiation::GetMeanFreePath(
const G4Track& track, G4double,
G4ForceCondition* condition)
{
if(nSteps > 0) {
if(nSteps > 0)
{
*condition = StronglyForced;
} else {
}
else
{
*condition = NotForced;
if(track.GetKineticEnergy()/track.GetDefinition()->GetPDGMass() + 1.0 > gammaMin &&
track.GetVolume()->GetLogicalVolume()->GetRegion() == region) {
*condition = StronglyForced;
if(track.GetKineticEnergy() / track.GetDefinition()->GetPDGMass() + 1.0 >
gammaMin &&
track.GetVolume()->GetLogicalVolume()->GetRegion() == region)
{
*condition = StronglyForced;
}
}
return DBL_MAX; // so TR doesn't limit mean free path
return DBL_MAX; // so TR doesn't limit mean free path
}
///////////////////////////////////////////////////////////////////////
File diff suppressed because it is too large Load Diff
@@ -23,113 +23,84 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
#include <complex>
#include "G4XTRGammaRadModel.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
using namespace std;
////////////////////////////////////////////////////////////////////////////
//
// Constructor, destructor
G4XTRGammaRadModel::G4XTRGammaRadModel(G4LogicalVolume* anEnvelope,
G4double alphaPlate,
G4double alphaGas,
G4Material* foilMat,G4Material* gasMat,
G4double a, G4double b, G4int n,
const G4String& processName) :
G4VXTRenergyLoss(anEnvelope,foilMat,gasMat,a,b,n,processName)
G4double alphaPlate, G4double alphaGas,
G4Material* foilMat, G4Material* gasMat,
G4double a, G4double b, G4int n,
const G4String& processName)
: G4VXTRenergyLoss(anEnvelope, foilMat, gasMat, a, b, n, processName)
{
G4cout<<"Gamma distributed X-ray TR radiator model is called"<<G4endl ;
G4cout << "Gamma distributed X-ray TR radiator model is called" << G4endl;
// Build energy and angular integral spectra of X-ray TR photons from
// a radiator
fAlphaPlate = alphaPlate ;
fAlphaGas = alphaGas ;
G4cout<<"fAlphaPlate = "<<fAlphaPlate<<" ; fAlphaGas = "<<fAlphaGas<<G4endl ;
fAlphaPlate = alphaPlate;
fAlphaGas = alphaGas;
G4cout << "fAlphaPlate = " << fAlphaPlate << " ; fAlphaGas = " << fAlphaGas
<< G4endl;
fExitFlux = true;
// BuildTable() ;
}
///////////////////////////////////////////////////////////////////////////
G4XTRGammaRadModel::~G4XTRGammaRadModel() {}
G4XTRGammaRadModel::~G4XTRGammaRadModel()
void G4XTRGammaRadModel::ProcessDescription(std::ostream& out) const
{
;
out << "Rough model describing X-ray transition radiation. Thicknesses of "
"plates\n"
"and gas gaps are distributed according to gamma distributions.\n";
}
///////////////////////////////////////////////////////////////////////////
//
// Rough approximation for radiator interference factor for the case of
// fully GamDistr radiator. The plate and gas gap thicknesses are distributed
// according to exponent. The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// fully GamDistr radiator. The plate and gas gap thicknesses are distributed
// according to exponent. The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in coresponding material.
G4double
G4XTRGammaRadModel::GetStackFactor( G4double energy,
G4double gamma, G4double varAngle )
G4double G4XTRGammaRadModel::GetStackFactor(G4double energy, G4double gamma,
G4double varAngle)
{
G4double result, Qa, Qb, Q, Za, Zb, Ma, Mb ;
Za = GetPlateFormationZone(energy,gamma,varAngle) ;
Zb = GetGasFormationZone(energy,gamma,varAngle) ;
G4double result, Qa, Qb, Q, Za, Zb, Ma, Mb;
Ma = GetPlateLinearPhotoAbs(energy) ;
Mb = GetGasLinearPhotoAbs(energy) ;
Za = GetPlateFormationZone(energy, gamma, varAngle);
Zb = GetGasFormationZone(energy, gamma, varAngle);
Qa = ( 1.0 + fPlateThick*Ma/fAlphaPlate ) ;
Qa = std::pow(Qa,-fAlphaPlate) ;
Qb = ( 1.0 + fGasThick*Mb/fAlphaGas ) ;
Qb = std::pow(Qb,-fAlphaGas) ;
Q = Qa*Qb ;
Ma = GetPlateLinearPhotoAbs(energy);
Mb = GetGasLinearPhotoAbs(energy);
G4complex Ca(1.0+0.5*fPlateThick*Ma/fAlphaPlate,fPlateThick/Za/fAlphaPlate) ;
G4complex Cb(1.0+0.5*fGasThick*Mb/fAlphaGas,fGasThick/Zb/fAlphaGas) ;
Qa = (1.0 + fPlateThick * Ma / fAlphaPlate);
Qa = std::pow(Qa, -fAlphaPlate);
Qb = (1.0 + fGasThick * Mb / fAlphaGas);
Qb = std::pow(Qb, -fAlphaGas);
Q = Qa * Qb;
G4complex Ha = std::pow(Ca,-fAlphaPlate) ;
G4complex Hb = std::pow(Cb,-fAlphaGas) ;
G4complex H = Ha*Hb ;
G4complex Ca(1.0 + 0.5 * fPlateThick * Ma / fAlphaPlate,
fPlateThick / Za / fAlphaPlate);
G4complex Cb(1.0 + 0.5 * fGasThick * Mb / fAlphaGas,
fGasThick / Zb / fAlphaGas);
G4complex F1 = ( 0.5*(1+Qa)*(1.0+H) - Ha - Qa*Hb )/(1.0-H) ;
G4complex Ha = std::pow(Ca, -fAlphaPlate);
G4complex Hb = std::pow(Cb, -fAlphaGas);
G4complex H = Ha * Hb;
G4complex F2 = (1.0-Ha)*(Qa-Ha)*Hb/(1.0-H)/(Q-H) ;
G4complex F1 = (0.5 * (1 + Qa) * (1.0 + H) - Ha - Qa * Hb) / (1.0 - H);
F2 *= std::pow(Q,G4double(fPlateNumber)) - std::pow(H,fPlateNumber) ;
G4complex F2 = (1.0 - Ha) * (Qa - Ha) * Hb / (1.0 - H) / (Q - H);
result = ( 1. - std::pow(Q,G4double(fPlateNumber)) )/( 1. - Q ) ;
F2 *= std::pow(Q, G4double(fPlateNumber)) - std::pow(H, fPlateNumber);
G4complex stack = result*F1;
stack += F2;
stack *= 2.0*OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = (1. - std::pow(Q, G4double(fPlateNumber))) / (1. - Q);
result = std::real(stack);
G4complex stack = result * F1;
stack += F2;
stack *= 2.0 * OneInterfaceXTRdEdx(energy, gamma, varAngle);
// result *= 2.0*std::real(F1);
// result += 2.0*std::real(F2);
result = std::real(stack);
return result ;
return result;
}
//
//
////////////////////////////////////////////////////////////////////////////
@@ -23,216 +23,148 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
#include <complex>
#include "G4XTRRegularRadModel.hh"
#include "G4PhysicalConstants.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
using namespace std;
#include "G4PhysicalConstants.hh"
////////////////////////////////////////////////////////////////////////////
//
// Constructor, destructor
G4XTRRegularRadModel::G4XTRRegularRadModel(G4LogicalVolume *anEnvelope,
G4Material* foilMat,G4Material* gasMat,
G4double a, G4double b, G4int n,
const G4String& processName) :
G4VXTRenergyLoss(anEnvelope,foilMat,gasMat,a,b,n,processName)
G4XTRRegularRadModel::G4XTRRegularRadModel(G4LogicalVolume* anEnvelope,
G4Material* foilMat,
G4Material* gasMat, G4double a,
G4double b, G4int n,
const G4String& processName)
: G4VXTRenergyLoss(anEnvelope, foilMat, gasMat, a, b, n, processName)
{
G4cout<<" XTR Regular discrete radiator model is called"<<G4endl ;
G4cout << " XTR Regular discrete radiator model is called" << G4endl;
fExitFlux = true;
// Build energy and angular integral spectra of X-ray TR photons from
// a radiator
// BuildTable() ;
}
///////////////////////////////////////////////////////////////////////////
G4XTRRegularRadModel::~G4XTRRegularRadModel() {}
G4XTRRegularRadModel::~G4XTRRegularRadModel()
///////////////////////////////////////////////////////////////////////////
void G4XTRRegularRadModel::ProcessDescription(std::ostream& out) const
{
;
out << "Describes X-ray transition radiation with thickness of gaps and "
"plates\n"
"fixed.\n";
}
///////////////////////////////////////////////////////////////////////////
//
//
G4double G4XTRRegularRadModel::SpectralXTRdEdx(G4double energy)
{
G4double result, sum = 0., tmp, cof1, cof2, cofMin, cofPHC, theta2, theta2k;
G4double aMa, bMb ,sigma, dump;
static constexpr G4double cofPHC = 4. * pi * hbarc;
G4double result, sum = 0., tmp, cof1, cof2, cofMin, theta2, theta2k;
G4double aMa, bMb, sigma, dump;
G4int k, kMax, kMin;
aMa = fPlateThick*GetPlateLinearPhotoAbs(energy);
bMb = fGasThick*GetGasLinearPhotoAbs(energy);
sigma = 0.5*(aMa + bMb);
dump = std::exp(-fPlateNumber*sigma);
if(verboseLevel > 2) G4cout<<" dump = "<<dump<<G4endl;
cofPHC = 4*pi*hbarc;
tmp = (fSigma1 - fSigma2)/cofPHC/energy;
cof1 = fPlateThick*tmp;
cof2 = fGasThick*tmp;
aMa = fPlateThick * GetPlateLinearPhotoAbs(energy);
bMb = fGasThick * GetGasLinearPhotoAbs(energy);
sigma = 0.5 * (aMa + bMb);
dump = std::exp(-fPlateNumber * sigma);
if(verboseLevel > 2)
G4cout << " dump = " << dump << G4endl;
tmp = (fSigma1 - fSigma2) / cofPHC / energy;
cof1 = fPlateThick * tmp;
cof2 = fGasThick * tmp;
cofMin = energy*(fPlateThick + fGasThick)/fGamma/fGamma;
cofMin += (fPlateThick*fSigma1 + fGasThick*fSigma2)/energy;
cofMin = energy * (fPlateThick + fGasThick) / fGamma / fGamma;
cofMin += (fPlateThick * fSigma1 + fGasThick * fSigma2) / energy;
cofMin /= cofPHC;
theta2 = cofPHC/(energy*(fPlateThick + fGasThick));
// if (fGamma < 1200) kMin = G4int(cofMin); // 1200 ?
// else kMin = 1;
theta2 = cofPHC / (energy * (fPlateThick + fGasThick));
kMin = G4int(cofMin);
if (cofMin > kMin) kMin++;
if(cofMin > kMin)
kMin++;
// tmp = (fPlateThick + fGasThick)*energy*fMaxThetaTR;
// tmp /= cofPHC;
// kMax = G4int(tmp);
// if(kMax < 0) kMax = 0;
// kMax += kMin;
kMax = kMin + 49; // 19; // kMin + G4int(tmp);
// tmp /= fGamma;
// if( G4int(tmp) < kMin ) kMin = G4int(tmp);
kMax = kMin + 49;
if(verboseLevel > 2)
{
G4cout<<cof1<<" "<<cof2<<" "<<cofMin<<G4endl;
G4cout<<"kMin = "<<kMin<<"; kMax = "<<kMax<<G4endl;
}
for( k = kMin; k <= kMax; k++ )
{
tmp = pi*fPlateThick*(k + cof2)/(fPlateThick + fGasThick);
result = (k - cof1)*(k - cof1)*(k + cof2)*(k + cof2);
// tmp = std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
if( k == kMin && kMin == G4int(cofMin) )
G4cout << cof1 << " " << cof2 << " " << cofMin << G4endl;
G4cout << "kMin = " << kMin << "; kMax = " << kMax << G4endl;
}
for(k = kMin; k <= kMax; ++k)
{
tmp = pi * fPlateThick * (k + cof2) / (fPlateThick + fGasThick);
result = (k - cof1) * (k - cof1) * (k + cof2) * (k + cof2);
if(k == kMin && kMin == G4int(cofMin))
{
sum += 0.5*std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum +=
0.5 * std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
else
{
sum += std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum += std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
theta2k = std::sqrt(theta2*std::abs(k-cofMin));
theta2k = std::sqrt(theta2 * std::abs(k - cofMin));
if(verboseLevel > 2)
{
// G4cout<<"k = "<<k<<"; sqrt(theta2k) = "<<theta2k<<"; tmp = "<<std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result
// <<"; sum = "<<sum<<G4endl;
G4cout<<k<<" "<<theta2k<<" "<<std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result
<<" "<<sum<<G4endl;
}
{
G4cout << k << " " << theta2k << " "
<< std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result
<< " " << sum << G4endl;
}
}
result = 2*( cof1 + cof2 )*( cof1 + cof2 )*sum/energy;
// result *= ( 1 - std::exp(-0.5*fPlateNumber*sigma) )/( 1 - std::exp(-0.5*sigma) );
// fPlateNumber;
result *= dump*( -1 + dump + 2*fPlateNumber );
/*
fEnergy = energy;
// G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral;
G4Integrator<G4TransparentRegXTRadiator,G4double(G4VXTRenergyLoss::*)(G4double)> integral;
tmp = integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.0,0.3*fMaxThetaTR) +
integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.3*fMaxThetaTR,0.6*fMaxThetaTR) +
integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
0.6*fMaxThetaTR,fMaxThetaTR) ;
result += tmp;
*/
result = 2 * (cof1 + cof2) * (cof1 + cof2) * sum / energy;
result *= dump * (-1 + dump + 2 * fPlateNumber);
return result;
}
///////////////////////////////////////////////////////////////////////////
//
// Approximation for radiator interference factor for the case of
// fully Regular radiator. The plate and gas gap thicknesses are fixed .
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in coresponding material.
G4double
G4XTRRegularRadModel::GetStackFactor( G4double energy,
G4double gamma, G4double varAngle )
// fully Regular radiator. The plate and gas gap thicknesses are fixed.
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in corresponding material.
G4double G4XTRRegularRadModel::GetStackFactor(G4double energy, G4double gamma,
G4double varAngle)
{
G4double result, Qa, Qb, Q, aZa, bZb, aMa, bMb, I2 ;
aZa = fPlateThick/GetPlateFormationZone(energy,gamma,varAngle) ;
bZb = fGasThick/GetGasFormationZone(energy,gamma,varAngle) ;
G4double aZa = fPlateThick / GetPlateFormationZone(energy, gamma, varAngle);
G4double bZb = fGasThick / GetGasFormationZone(energy, gamma, varAngle);
aMa = fPlateThick*GetPlateLinearPhotoAbs(energy) ;
bMb = fGasThick*GetGasLinearPhotoAbs(energy) ;
G4double aMa = fPlateThick * GetPlateLinearPhotoAbs(energy);
G4double bMb = fGasThick * GetGasLinearPhotoAbs(energy);
Qa = std::exp(-aMa) ;
Qb = std::exp(-bMb) ;
Q = Qa*Qb ;
G4double Qa = std::exp(-aMa);
G4double Qb = std::exp(-bMb);
G4double Q = Qa * Qb;
// G4complex Ca(1.0+0.5*fPlateThick*Ma,fPlateThick/Za) ;
// G4complex Cb(1.0+0.5*fGasThick*Mb,fGasThick/Zb) ;
G4complex Ha(std::exp(-0.5 * aMa) * std::cos(aZa),
-std::exp(-0.5 * aMa) * std::sin(aZa));
G4complex Ha( std::exp(-0.5*aMa)*std::cos(aZa),
-std::exp(-0.5*aMa)*std::sin(aZa) ) ;
G4complex Hb( std::exp(-0.5*bMb)*std::cos(bZb),
-std::exp(-0.5*bMb)*std::sin(bZb) ) ;
G4complex Hb(std::exp(-0.5 * bMb) * std::cos(bZb),
-std::exp(-0.5 * bMb) * std::sin(bZb));
G4complex H = Ha*Hb ;
G4complex H = Ha * Hb;
G4complex Hs = std::conj(H);
G4complex Hs = std::conj(H) ;
G4complex F2 = (1.0 - Ha) * (Qa - Ha) * Hb * (1.0 - Hs) * (Q - Hs);
F2 *= std::pow(Q, G4double(fPlateNumber)) - std::pow(H, fPlateNumber);
// G4complex F1 = ( 0.5*(1+Qa)*(1+H) - Ha - Qa*Hb )/(1-H) ;
G4double result = (1. - std::pow(Q, G4double(fPlateNumber))) / (1. - Q);
result *= (1. - Qa) * (1. + Qa - 2. * std::sqrt(Qa) * std::cos(aZa));
result /= (1. - std::sqrt(Q)) * (1. - std::sqrt(Q)) +
4. * std::sqrt(Q) * std::sin(0.5 * (aZa + bZb)) *
std::sin(0.5 * (aZa + bZb));
G4complex F2 = (1.0-Ha)*(Qa-Ha)*Hb*(1.0-Hs)*(Q-Hs) ;
G4double I2 = 1.;
I2 /= (1. - std::sqrt(Q)) * (1. - std::sqrt(Q)) +
4. * std::sqrt(Q) * std::sin(0.5 * (aZa + bZb)) *
std::sin(0.5 * (aZa + bZb));
F2 *= std::pow(Q,G4double(fPlateNumber)) - std::pow(H,fPlateNumber) ;
I2 /= Q * ((std::sqrt(Q) - std::cos(aZa + bZb)) *
(std::sqrt(Q) - std::cos(aZa + bZb)) +
std::sin(aZa + bZb) * std::sin(aZa + bZb));
result = ( 1. - std::pow(Q,G4double(fPlateNumber)) )/( 1. - Q ) ;
G4complex stack = 2. * I2 * F2;
stack += result;
stack *= OneInterfaceXTRdEdx(energy, gamma, varAngle);
result *= (1. - Qa)*(1. + Qa - 2.*std::sqrt(Qa)*std::cos(aZa)) ;
result /= (1. - std::sqrt(Q))*(1. - std::sqrt(Q)) +
4.*std::sqrt(Q)*std::sin(0.5*(aZa+bZb))*std::sin(0.5*(aZa+bZb)) ;
I2 = 1.; // 2.0*std::real(F2) ;
I2 /= (1. - std::sqrt(Q))*(1. - std::sqrt(Q)) +
4.*std::sqrt(Q)*std::sin(0.5*(aZa+bZb))*std::sin(0.5*(aZa+bZb)) ;
I2 /= Q*( (std::sqrt(Q)-std::cos(aZa+bZb))*(std::sqrt(Q)-std::cos(aZa+bZb)) +
std::sin(aZa+bZb)*std::sin(aZa+bZb) ) ;
G4complex stack = 2.*I2*F2;
stack += result;
stack *= OneInterfaceXTRdEdx(energy,gamma,varAngle);
// result += I2 ;
result = std::real(stack);
return result ;
return std::real(stack);
}
//
//
////////////////////////////////////////////////////////////////////////////
@@ -23,51 +23,40 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
#include <complex>
#include "G4XTRTransparentRegRadModel.hh"
#include "G4PhysicalConstants.hh"
#include "Randomize.hh"
#include "G4Integrator.hh"
#include "G4Gamma.hh"
////////////////////////////////////////////////////////////////////////////
//
// Constructor, destructor
G4XTRTransparentRegRadModel::G4XTRTransparentRegRadModel(G4LogicalVolume *anEnvelope,
G4Material* foilMat,G4Material* gasMat,
G4double a, G4double b, G4int n,
const G4String& processName) :
G4VXTRenergyLoss(anEnvelope,foilMat,gasMat,a,b,n,processName)
G4XTRTransparentRegRadModel::G4XTRTransparentRegRadModel(
G4LogicalVolume* anEnvelope, G4Material* foilMat, G4Material* gasMat,
G4double a, G4double b, G4int n, const G4String& processName)
: G4VXTRenergyLoss(anEnvelope, foilMat, gasMat, a, b, n, processName)
{
G4cout<<"Regular transparent X-ray TR radiator EM process is called"<<G4endl;
G4cout << "Regular transparent X-ray TR radiator EM process is called"
<< G4endl;
// Build energy and angular integral spectra of X-ray TR photons from
// a radiator
fExitFlux = true;
fAlphaPlate = 10000;
fAlphaGas = 1000;
// BuildTable();
}
///////////////////////////////////////////////////////////////////////////
G4XTRTransparentRegRadModel::~G4XTRTransparentRegRadModel() {}
G4XTRTransparentRegRadModel::~G4XTRTransparentRegRadModel()
///////////////////////////////////////////////////////////////////////////
void G4XTRTransparentRegRadModel::ProcessDescription(std::ostream& out) const
{
;
out << "Process describing radiator of X-ray transition radiation.\n";
}
///////////////////////////////////////////////////////////////////////////
//
//
G4double G4XTRTransparentRegRadModel::SpectralXTRdEdx(G4double energy)
{
G4double result, sum = 0., tmp, cof1, cof2, cofMin, cofPHC,aMa, bMb, sigma;
static constexpr G4double cofPHC = 4. * pi * hbarc;
G4double result, sum = 0., tmp, cof1, cof2, cofMin, aMa, bMb, sigma;
G4int k, kMax, kMin;
aMa = GetPlateLinearPhotoAbs(energy);
@@ -82,133 +71,71 @@ G4double G4XTRTransparentRegRadModel::SpectralXTRdEdx(G4double energy)
bMb *= fGasThick;
sigma = aMa + bMb;
cofPHC = 4.*pi*hbarc;
tmp = (fSigma1 - fSigma2)/cofPHC/energy;
cof1 = fPlateThick*tmp;
cof2 = fGasThick*tmp;
cofMin = energy*(fPlateThick + fGasThick)/fGamma/fGamma;
cofMin += (fPlateThick*fSigma1 + fGasThick*fSigma2)/energy;
tmp = (fSigma1 - fSigma2) / cofPHC / energy;
cof1 = fPlateThick * tmp;
cof2 = fGasThick * tmp;
cofMin = energy * (fPlateThick + fGasThick) / fGamma / fGamma;
cofMin += (fPlateThick * fSigma1 + fGasThick * fSigma2) / energy;
cofMin /= cofPHC;
// if (fGamma < 1200) kMin = G4int(cofMin); // 1200 ?
// else kMin = 1;
kMin = G4int(cofMin);
if (cofMin > kMin) kMin++;
if(cofMin > kMin)
kMin++;
// tmp = (fPlateThick + fGasThick)*energy*fMaxThetaTR;
// tmp /= cofPHC;
// kMax = G4int(tmp);
// if(kMax < 0) kMax = 0;
// kMax += kMin;
kMax = kMin + 19;
kMax = kMin + 19; // 5; // 9; // kMin + G4int(tmp);
// tmp /= fGamma;
// if( G4int(tmp) < kMin ) kMin = G4int(tmp);
// G4cout<<"kMin = "<<kMin<<"; kMax = "<<kMax<<G4endl;
for( k = kMin; k <= kMax; k++ )
for(k = kMin; k <= kMax; k++)
{
tmp = pi*fPlateThick*(k + cof2)/(fPlateThick + fGasThick);
result = (k - cof1)*(k - cof1)*(k + cof2)*(k + cof2);
tmp = pi * fPlateThick * (k + cof2) / (fPlateThick + fGasThick);
result = (k - cof1) * (k - cof1) * (k + cof2) * (k + cof2);
if( k == kMin && kMin == G4int(cofMin) )
if(k == kMin && kMin == G4int(cofMin))
{
sum += 0.5*std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum +=
0.5 * std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
else
{
sum += std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
sum += std::sin(tmp) * std::sin(tmp) * std::abs(k - cofMin) / result;
}
// G4cout<<"k = "<<k<<"; sum = "<<sum<<G4endl;
}
result = 4.*( cof1 + cof2 )*( cof1 + cof2 )*sum/energy;
result *= ( 1. - std::exp(-fPlateNumber*sigma) )/( 1. - std::exp(-sigma) );
result = 4. * (cof1 + cof2) * (cof1 + cof2) * sum / energy;
result *= (1. - std::exp(-fPlateNumber * sigma)) / (1. - std::exp(-sigma));
return result;
}
///////////////////////////////////////////////////////////////////////////
//
// Approximation for radiator interference factor for the case of
// fully Regular radiator. The plate and gas gap thicknesses are fixed .
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in coresponding material.
G4double
G4XTRTransparentRegRadModel::GetStackFactor( G4double energy,
G4double gamma, G4double varAngle )
// fully Regular radiator. The plate and gas gap thicknesses are fixed.
// The mean values of the plate and gas gap thicknesses
// are supposed to be about XTR formation zones but much less than
// mean absorption length of XTR photons in corresponding material.
G4double G4XTRTransparentRegRadModel::GetStackFactor(G4double energy,
G4double gamma,
G4double varAngle)
{
/*
G4double result, Za, Zb, Ma, Mb, sigma;
Za = GetPlateFormationZone(energy,gamma,varAngle);
Zb = GetGasFormationZone(energy,gamma,varAngle);
Ma = GetPlateLinearPhotoAbs(energy);
Mb = GetGasLinearPhotoAbs(energy);
sigma = Ma*fPlateThick + Mb*fGasThick;
G4double aZa = fPlateThick / GetPlateFormationZone(energy, gamma, varAngle);
G4double bZb = fGasThick / GetGasFormationZone(energy, gamma, varAngle);
G4double aMa = fPlateThick * GetPlateLinearPhotoAbs(energy);
G4double bMb = fGasThick * GetGasLinearPhotoAbs(energy);
G4double sigma = aMa * fPlateThick + bMb * fGasThick;
G4double Qa = std::exp(-0.5 * aMa);
G4double Qb = std::exp(-0.5 * bMb);
G4double Q = Qa * Qb;
G4complex Ca(1.0+0.5*fPlateThick*Ma/fAlphaPlate,fPlateThick/Za/fAlphaPlate);
G4complex Cb(1.0+0.5*fGasThick*Mb/fAlphaGas,fGasThick/Zb/fAlphaGas);
G4complex Ha = std::pow(Ca,-fAlphaPlate);
G4complex Hb = std::pow(Cb,-fAlphaGas);
G4complex H = Ha*Hb;
G4complex F1 = (1.0 - Ha)*(1.0 - Hb )/(1.0 - H)
* G4double(fPlateNumber) ;
G4complex F2 = (1.0-Ha)*(1.0-Ha)*Hb/(1.0-H)/(1.0-H)
* (1.0 - std::exp(-0.5*fPlateNumber*sigma)) ;
// *(1.0 - std::pow(H,fPlateNumber)) ;
G4complex R = (F1 + F2)*OneInterfaceXTRdEdx(energy,gamma,varAngle);
// G4complex R = F2*OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = 2.0*std::real(R);
return result;
*/
// numerically unstable result
G4double result, Qa, Qb, Q, aZa, bZb, aMa, bMb, D, sigma;
aZa = fPlateThick/GetPlateFormationZone(energy,gamma,varAngle);
bZb = fGasThick/GetGasFormationZone(energy,gamma,varAngle);
aMa = fPlateThick*GetPlateLinearPhotoAbs(energy);
bMb = fGasThick*GetGasLinearPhotoAbs(energy);
sigma = aMa*fPlateThick + bMb*fGasThick;
Qa = std::exp(-0.5*aMa);
Qb = std::exp(-0.5*bMb);
Q = Qa*Qb;
G4complex Ha( Qa*std::cos(aZa), -Qa*std::sin(aZa) );
G4complex Hb( Qb*std::cos(bZb), -Qb*std::sin(bZb) );
G4complex H = Ha*Hb;
G4complex Ha(Qa * std::cos(aZa), -Qa * std::sin(aZa));
G4complex Hb(Qb * std::cos(bZb), -Qb * std::sin(bZb));
G4complex H = Ha * Hb;
G4complex Hs = conj(H);
D = 1.0 /( (1. - Q)*(1. - Q) +
4.*Q*std::sin(0.5*(aZa + bZb))*std::sin(0.5*(aZa + bZb)) );
G4complex F1 = (1.0 - Ha)*(1.0 - Hb)*(1.0 - Hs)
* G4double(fPlateNumber)*D;
G4complex F2 = (1.0 - Ha)*(1.0 - Ha)*Hb*(1.0 - Hs)*(1.0 - Hs)
// * (1.0 - std::pow(H,fPlateNumber)) * D*D;
* (1.0 - std::exp(-0.5*fPlateNumber*sigma)) * D*D;
G4complex R = (F1 + F2)*OneInterfaceXTRdEdx(energy,gamma,varAngle);
result = 2.0*std::real(R);
return result;
G4double D =
1.0 / ((1. - Q) * (1. - Q) +
4. * Q * std::sin(0.5 * (aZa + bZb)) * std::sin(0.5 * (aZa + bZb)));
G4complex F1 =
(1.0 - Ha) * (1.0 - Hb) * (1.0 - Hs) * G4double(fPlateNumber) * D;
G4complex F2 = (1.0 - Ha) * (1.0 - Ha) * Hb * (1.0 - Hs) * (1.0 - Hs) *
(1.0 - std::exp(-0.5 * fPlateNumber * sigma)) * D * D;
G4complex R = (F1 + F2) * OneInterfaceXTRdEdx(energy, gamma, varAngle);
return 2.0 * std::real(R);
}
//
//
////////////////////////////////////////////////////////////////////////////