15 #include "CLHEP/Random/RandGaussZiggurat.h"
28 #include "G4DynamicParticle.hh"
30 #include "G4Material.hh"
31 #include "G4Element.hh"
32 #include "G4EmProcessSubType.hh"
33 #include "G4ProcessType.hh"
35 #include "Randomize.hh"
38 #include "CLHEP/Random/RandPoisson.h"
49 G4VDiscreteProcess(processName,fElectromagnetic),
51 m_XMLhandler(nullptr),m_xmlfilename(xmlfilename),
52 m_MinEnergyTR(0.0),m_MaxEnergyTR(0.0),m_NumBins(0),m_WplasmaGas(0.0),
53 m_WplasmaFoil(0.0),m_GammaMin(0.0),m_EkinMin(0.0),m_Ey(nullptr),m_Sr(nullptr),
54 m_om(nullptr),m_Omg(nullptr),m_sigmaGas(nullptr),m_sigmaFoil(nullptr)
59 SetProcessSubType( fTransitionRadiation );
65 ATH_MSG_DEBUG (
"##### Constructor TRTTransitionRadiation done" );
83 ATH_MSG_DEBUG(
" New Radiator parameters being defined for TR process");
95 ATH_MSG_DEBUG (
"Constructor TRTTransitionRadiation::Initialize()" );
110 G4Material* g4mat_Gas{
nullptr};
111 G4Material* g4mat_FoilMaterial{
nullptr};
112 std::string errorMessage;
115 ISvcLocator *svcLocator = Gaudi::svcLocator();
116 SmartIF<StoreGateSvc>
detStore{svcLocator->service(
"DetectorStore")};
118 errorMessage =
"Can not access Detector Store";
120 throw std::runtime_error(errorMessage);
124 if(materialManager) {
126 g4mat_Gas = geo2g4_material_fact.
Build(materialManager->
getMaterial(
"trt::CO2"));
127 g4mat_FoilMaterial = geo2g4_material_fact.
Build(materialManager->
getMaterial(
"trt::CH2"));
134 ATH_MSG_INFO(
"GeoModel Material is not available. Construct TR materials using IRDBAccessSvc interface");
135 SmartIF<IGeoDbTagSvc> geoDbTagSvc{svcLocator->service(
"GeoDbTagSvc")};
137 errorMessage =
"Can not access GeoDbTagSvc";
139 throw std::runtime_error(errorMessage);
143 SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service(geoDbTagSvc->getParamSvcName())};
145 errorMessage =
"Can not access " + geoDbTagSvc->getParamSvcName();
147 throw std::runtime_error(errorMessage);
150 std::map<std::string,int> materialComponentsMap;
151 std::map<std::string,G4Material*> materialMap;
152 IRDBRecordset_ptr materialsRec = pAccessSvc->getRecordsetPtr(
"TRMaterials",
"",
"");
155 std::string
key = material->getString(
"NAME");
156 auto mapIt = materialComponentsMap.find(
key);
157 if (mapIt == materialComponentsMap.end()) {
158 materialComponentsMap.emplace(
key,1);
161 materialComponentsMap.at(
key) = mapIt->second + 1;
166 std::string
key = material->getString(
"NAME");
167 G4Material* g4Material{
nullptr};
168 if(materialMap.find(
key)==materialMap.end()) {
169 auto itNElements = materialComponentsMap.find(
key);
170 if (itNElements==materialComponentsMap.end())
continue;
171 g4Material =
new G4Material(
key
173 ,itNElements->second);
174 materialMap.emplace(
key,g4Material);
177 g4Material = materialMap.at(
key);
180 G4Element* g4Element = G4Element::GetElement(material->getString(
"ELEMENT_NAME"));
182 errorMessage =
"Wrong name for element " + material->getString(
"ELEMENT_NAME")
183 +
" found in the description of material " +
key;
185 throw std::runtime_error(errorMessage);
187 g4Material->AddElement(g4Element,(G4int)material->getInt(
"N"));
189 g4mat_Gas = materialMap.at(
"CO2");
190 g4mat_FoilMaterial = materialMap.at(
"CH2");
196 m_WplasmaFoil = sqrt( PlasmaCof * g4mat_FoilMaterial->GetElectronDensity() );
197 m_WplasmaGas = sqrt( PlasmaCof * g4mat_Gas->GetElectronDensity() );
199 ATH_MSG_DEBUG(
"Foil material : " << g4mat_FoilMaterial->GetName()
226 ATH_MSG_DEBUG (
"Constructor TRTTransitionRadiation::Initialize() DONE!" );
238 return ( std::abs(
particle.GetPDGCharge())>std::numeric_limits<double>::epsilon() && std::abs(
particle.GetPDGMass())>std::numeric_limits<double>::epsilon() ) ;
249 const G4DynamicParticle *aParticle(aTrack.GetDynamicParticle());
250 if(std::abs(aParticle->GetDefinition()->GetPDGCharge())< std::numeric_limits<double>::epsilon() ||
251 std::abs(aParticle->GetDefinition()->GetPDGMass())<std::numeric_limits<double>::epsilon() ) {
263 const G4Step& aStep ) {
264 aParticleChange.Initialize(aTrack);
267 const G4DynamicParticle *aParticle(aTrack.GetDynamicParticle());
268 G4double KineticEnergy(aParticle->GetKineticEnergy());
272 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
275 G4double
ParticleMass(aParticle->GetDefinition()->GetPDGMass());
280 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
283 G4double FoilThickness(0.);
284 G4double GasThickness(0.);
288 std::vector<TRTRadiatorParameters>::const_iterator currentRadiator(
m_radiators.begin());
289 const std::vector<TRTRadiatorParameters>::const_iterator endOfRadiators(
m_radiators.end());
290 while(currentRadiator!=endOfRadiators) {
291 if ( currentRadiator->GetLogicalVolume() ==
292 aTrack.GetVolume()->GetLogicalVolume() ) {
293 FoilThickness = currentRadiator->GetFoilThickness();
294 GasThickness = currentRadiator->GetGasThickness();
295 BEflag = currentRadiator->GetBEflag();
301 if ( currentRadiator == endOfRadiators ) {
302 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
306 << currentRadiator->GetLogicalVolume()->GetName() );
308 G4ThreeVector ParticleDirection(aParticle->GetMomentumDirection());
311 G4double costh(std::abs(ParticleDirection[2]));
312 FoilThickness /= costh;
313 GasThickness /= costh;
317 G4int FoilsTraversed(
static_cast<G4int
>(
StepLength/(FoilThickness+GasThickness)+0.5));
323 if ( FoilsTraversed == 0 ) {
325 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
328 G4double Gy(0.), Gmany(0.), Neff(0.);
338 #ifdef ARTRU // Formulas from Artru
367 G4double Sph_org(Sph);
370 G4double tempLog10Gamma(log10(
Gamma));
371 G4double pHT_dEdxData = -0.001 + 0.0005*tempLog10Gamma;
372 G4double pHT_TRData = 0.15/(1.0 +
exp(-(tempLog10Gamma - 3.3)/0.27));
373 G4double pHT_dEdxMC = -0.0031 + 0.00016*tempLog10Gamma;
374 G4double pHT_TRMC = 0.1289/(1.0 +
exp(-(tempLog10Gamma - 3.01)/0.1253));
376 G4double fudge =
std::min(2.0,(pHT_dEdxData+pHT_TRData)/( pHT_dEdxMC+pHT_TRMC));
382 G4long NumberOfPhotonsGenerated(CLHEP::RandPoisson::shoot(Sph));
388 <<
", Gamma = " <<
Gamma
390 <<
", Nph = " << NumberOfPhotonsGenerated );
392 if ( NumberOfPhotonsGenerated <= 0 ) {
394 <<
"No photons generated." );
396 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
400 aParticleChange.SetNumberOfSecondaries( NumberOfPhotonsGenerated );
401 G4StepPoint *pPostStepPoint(aStep.GetPostStepPoint());
402 G4ThreeVector x0(pPostStepPoint->GetPosition());
404 G4double Esum(0.), XRannu(0.), Ephot(0.), Theta(0.),
Phi(0.),
407 G4ThreeVector
pos(0),TRPhotonDirection(0);
409 for( G4int
i(0);
i<NumberOfPhotonsGenerated; ++
i ) {
410 XRannu = CLHEP::RandFlat::shoot();
415 pos = pPostStepPoint->GetPosition();
422 Theta = std::abs( CLHEP::RandGaussZiggurat::shoot( 0.0,
M_PI/
Gamma ) );
423 if( Theta >= 0.1 ) Theta = 0.1;
425 Phi = (2.*
M_PI)*CLHEP::RandFlat::shoot();
431 TRPhotonDirection.set(
X,
Y,
Z);
432 TRPhotonDirection.rotateUz( ParticleDirection );
433 TRPhotonDirection.unit();
439 aParticleChange.AddSecondary( TRPhoton );
443 aParticleChange.ProposeEnergy( KineticEnergy-Esum );
446 <<
"Number of TR photons generated: " << NumberOfPhotonsGenerated );
448 return &aParticleChange;
452 const G4double & sigFoil,
453 const G4double & GasThickness,
454 const G4double & FoilThickness,
455 const G4int & FoilsTraversed )
const {
456 if ( FoilsTraversed <= 0 )
459 G4double C1 = sigGas * GasThickness*FoilsTraversed;
460 G4double C2 = sigFoil*FoilThickness*FoilsTraversed;
462 G4double W1 =
exp(-C1);
463 G4double W2 =
exp(-C2);
465 return FoilsTraversed * (1-W1*W2)/(C1+C2);
469 const G4double & sigFoil,
470 const G4double & GasThickness,
471 const G4double & FoilThickness,
472 const G4int & FoilsTraversed )
const {
473 if ( FoilsTraversed <= 0 )
476 G4double
sigma = FoilThickness*sigFoil + GasThickness*sigGas;
477 G4double xNF = FoilsTraversed;
488 const G4double &
Gamma,
489 const G4double & Al1,
490 const G4double & Al2 )
const {
494 G4double Al = Al1 + Al2;
502 G4double om12 = (om1*om1-om2*om2)/PhotonEnergy;
503 G4double oms = (Al1*om1*om1+Al2*om2*om2)/Al;
504 G4double Ao = 0.5*Al1*om12*CK;
505 G4double Bo = 0.5*Al2*om12*CK;
506 G4double ro = sqrt(oms)/
Gamma;
507 G4double co = 0.5*(PhotonEnergy/(
Gamma*
Gamma)+oms/PhotonEnergy);
508 G4double
cc = co*Al*CK;
509 G4double cb =
M_PI*Al2/Al;
510 G4int i1 =
static_cast<G4int
>(1.0+(ro>co?ro:co)*Al*CK);
511 G4int i2 =
static_cast<G4int
>(
Gamma*ro*Al*CK);
521 for(G4int
i(i1);
i<=i2; ++
i) {
524 S = (
static_cast<G4double
>(
i)-
cc)*(
sin(cb*(
static_cast<G4double
>(
i)-Ao))/((
static_cast<G4double
>(
i)-Ao)*(
static_cast<G4double
>(
i)+Bo)))*
525 (
sin(cb*(
static_cast<G4double
>(
i)-Ao))/((
static_cast<G4double
>(
i)-Ao)*(
static_cast<G4double
>(
i)+Bo)));
530 if( (So<Sx)&&(So<=
S) ) {
531 if( Sm1<eps*Smx )
break;
544 const G4double &
Gamma,
546 const G4double &
d1 )
const {
547 G4double phimax = 4.*
M_PI;
549 G4double tau =
d2/
d1;
556 G4double xi1sq = xi1*xi1;
557 G4double xi2sq = xi2*xi2;
559 G4double Z1 = 2./(
mom*(ginv2+xi1sq));
560 G4double Z2 = 2./(
mom*(ginv2+xi2sq));
563 G4double V =
d1*(1./Z1-1./Z2);
566 G4double pmin =
p0 +
a*(1.+tau)/(2.*
M_PI);
567 G4double
ymax = tau*phimax;
570 G4int ipmin = (
int)pmin+1;
571 G4int ipmax = (
int)pmax;
574 G4double y0 = -0.5*
mom*
d1*(xi1sq-xi2sq)/(1+tau);
575 G4double
dy = (2.*
M_PI)/(1+tau);
583 for ( G4int
ip(ipmin);
ip<=ipmax; ++
ip ) {
588 term = (1./
y-1./(
y+V))*
sin(0.5*(
y+V));
596 tx = (
tx>term) ?
tx : term;
600 if (
t2 > 0. &&
t1 > term &&
t1 >
t2 ) {
601 if (
t1 < 0.0001*
sum )
break;
639 K =
static_cast<G4int
>((K1+K2)/2);
648 G4double X2(
A[K1+1]);
650 G4double xfinter((
F[K1]*(
X-X2)+
F[K1+1]*(X1-
X))/(X1-X2));
659 const G4double & PhotonEnergy )
const {
661 const G4double *SandiaCof(
Material->GetSandiaTable()->GetSandiaCofForMaterial(PhotonEnergy));
663 const G4double Energy2(PhotonEnergy*PhotonEnergy);
664 const G4double Energy3(PhotonEnergy*Energy2);
665 const G4double Energy4(Energy2*Energy2);
667 return ( SandiaCof[0]/PhotonEnergy +
668 SandiaCof[1]/Energy2 +
669 SandiaCof[2]/Energy3 +
670 SandiaCof[3]/Energy4 );