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 g4Material =
new G4Material(
key
172 ,itNElements->second);
173 materialMap.emplace(
key,g4Material);
176 g4Material = materialMap.at(
key);
179 G4Element* g4Element = G4Element::GetElement(material->getString(
"ELEMENT_NAME"));
181 errorMessage =
"Wrong name for element " + material->getString(
"ELEMENT_NAME")
182 +
" found in the description of material " +
key;
184 throw std::runtime_error(errorMessage);
186 g4Material->AddElement(g4Element,(G4int)material->getInt(
"N"));
188 g4mat_Gas = materialMap.at(
"CO2");
189 g4mat_FoilMaterial = materialMap.at(
"CH2");
195 m_WplasmaFoil = sqrt( PlasmaCof * g4mat_FoilMaterial->GetElectronDensity() );
196 m_WplasmaGas = sqrt( PlasmaCof * g4mat_Gas->GetElectronDensity() );
198 ATH_MSG_DEBUG(
"Foil material : " << g4mat_FoilMaterial->GetName()
225 ATH_MSG_DEBUG (
"Constructor TRTTransitionRadiation::Initialize() DONE!" );
237 return ( std::abs(
particle.GetPDGCharge())>std::numeric_limits<double>::epsilon() && std::abs(
particle.GetPDGMass())>std::numeric_limits<double>::epsilon() ) ;
248 const G4DynamicParticle *aParticle(aTrack.GetDynamicParticle());
249 if(std::abs(aParticle->GetDefinition()->GetPDGCharge())< std::numeric_limits<double>::epsilon() ||
250 std::abs(aParticle->GetDefinition()->GetPDGMass())<std::numeric_limits<double>::epsilon() ) {
262 const G4Step& aStep ) {
263 aParticleChange.Initialize(aTrack);
266 const G4DynamicParticle *aParticle(aTrack.GetDynamicParticle());
267 G4double KineticEnergy(aParticle->GetKineticEnergy());
271 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
274 G4double
ParticleMass(aParticle->GetDefinition()->GetPDGMass());
279 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
282 G4double FoilThickness(0.);
283 G4double GasThickness(0.);
287 std::vector<TRTRadiatorParameters>::const_iterator currentRadiator(
m_radiators.begin());
288 const std::vector<TRTRadiatorParameters>::const_iterator endOfRadiators(
m_radiators.end());
289 while(currentRadiator!=endOfRadiators) {
290 if ( currentRadiator->GetLogicalVolume() ==
291 aTrack.GetVolume()->GetLogicalVolume() ) {
292 FoilThickness = currentRadiator->GetFoilThickness();
293 GasThickness = currentRadiator->GetGasThickness();
294 BEflag = currentRadiator->GetBEflag();
300 if ( currentRadiator == endOfRadiators ) {
301 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
305 << currentRadiator->GetLogicalVolume()->GetName() );
307 G4ThreeVector ParticleDirection(aParticle->GetMomentumDirection());
310 G4double costh(std::abs(ParticleDirection[2]));
311 FoilThickness /= costh;
312 GasThickness /= costh;
316 G4int FoilsTraversed(
static_cast<G4int
>(
StepLength/(FoilThickness+GasThickness)+0.5));
322 if ( FoilsTraversed == 0 ) {
324 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
327 G4double Gy(0.), Gmany(0.), Neff(0.);
337 #ifdef ARTRU // Formulas from Artru
366 G4double Sph_org(Sph);
369 G4double tempLog10Gamma(log10(
Gamma));
370 G4double pHT_dEdxData = -0.001 + 0.0005*tempLog10Gamma;
371 G4double pHT_TRData = 0.15/(1.0 +
exp(-(tempLog10Gamma - 3.3)/0.27));
372 G4double pHT_dEdxMC = -0.0031 + 0.00016*tempLog10Gamma;
373 G4double pHT_TRMC = 0.1289/(1.0 +
exp(-(tempLog10Gamma - 3.01)/0.1253));
375 G4double fudge =
std::min(2.0,(pHT_dEdxData+pHT_TRData)/( pHT_dEdxMC+pHT_TRMC));
381 G4long NumberOfPhotonsGenerated(CLHEP::RandPoisson::shoot(Sph));
387 <<
", Gamma = " <<
Gamma
389 <<
", Nph = " << NumberOfPhotonsGenerated );
391 if ( NumberOfPhotonsGenerated <= 0 ) {
393 <<
"No photons generated." );
395 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
399 aParticleChange.SetNumberOfSecondaries( NumberOfPhotonsGenerated );
400 G4StepPoint *pPostStepPoint(aStep.GetPostStepPoint());
401 G4ThreeVector x0(pPostStepPoint->GetPosition());
403 G4double Esum(0.), XRannu(0.), Ephot(0.), Theta(0.),
Phi(0.),
406 G4ThreeVector
pos(0),TRPhotonDirection(0);
408 for( G4int
i(0);
i<NumberOfPhotonsGenerated; ++
i ) {
409 XRannu = CLHEP::RandFlat::shoot();
414 pos = pPostStepPoint->GetPosition();
421 Theta = std::abs( CLHEP::RandGaussZiggurat::shoot( 0.0,
M_PI/
Gamma ) );
422 if( Theta >= 0.1 ) Theta = 0.1;
424 Phi = (2.*
M_PI)*CLHEP::RandFlat::shoot();
430 TRPhotonDirection.set(
X,
Y,
Z);
431 TRPhotonDirection.rotateUz( ParticleDirection );
432 TRPhotonDirection.unit();
438 aParticleChange.AddSecondary( TRPhoton );
442 aParticleChange.ProposeEnergy( KineticEnergy-Esum );
445 <<
"Number of TR photons generated: " << NumberOfPhotonsGenerated );
447 return &aParticleChange;
451 const G4double & sigFoil,
452 const G4double & GasThickness,
453 const G4double & FoilThickness,
454 const G4int & FoilsTraversed )
const {
455 if ( FoilsTraversed <= 0 )
458 G4double C1 = sigGas * GasThickness*FoilsTraversed;
459 G4double C2 = sigFoil*FoilThickness*FoilsTraversed;
461 G4double W1 =
exp(-C1);
462 G4double W2 =
exp(-C2);
464 return FoilsTraversed * (1-W1*W2)/(C1+C2);
468 const G4double & sigFoil,
469 const G4double & GasThickness,
470 const G4double & FoilThickness,
471 const G4int & FoilsTraversed )
const {
472 if ( FoilsTraversed <= 0 )
475 G4double
sigma = FoilThickness*sigFoil + GasThickness*sigGas;
476 G4double xNF = FoilsTraversed;
487 const G4double &
Gamma,
488 const G4double & Al1,
489 const G4double & Al2 )
const {
493 G4double Al = Al1 + Al2;
501 G4double om12 = (om1*om1-om2*om2)/PhotonEnergy;
502 G4double oms = (Al1*om1*om1+Al2*om2*om2)/Al;
503 G4double Ao = 0.5*Al1*om12*CK;
504 G4double Bo = 0.5*Al2*om12*CK;
505 G4double ro = sqrt(oms)/
Gamma;
506 G4double co = 0.5*(PhotonEnergy/(
Gamma*
Gamma)+oms/PhotonEnergy);
507 G4double
cc = co*Al*CK;
508 G4double cb =
M_PI*Al2/Al;
509 G4int i1 =
static_cast<G4int
>(1.0+(ro>co?ro:co)*Al*CK);
510 G4int i2 =
static_cast<G4int
>(
Gamma*ro*Al*CK);
520 for(G4int
i(i1);
i<=i2; ++
i) {
523 S = (
static_cast<G4double
>(
i)-
cc)*(
sin(cb*(
static_cast<G4double
>(
i)-Ao))/((
static_cast<G4double
>(
i)-Ao)*(
static_cast<G4double
>(
i)+Bo)))*
524 (
sin(cb*(
static_cast<G4double
>(
i)-Ao))/((
static_cast<G4double
>(
i)-Ao)*(
static_cast<G4double
>(
i)+Bo)));
529 if( (So<Sx)&&(So<=
S) ) {
530 if( Sm1<eps*Smx )
break;
543 const G4double &
Gamma,
545 const G4double &
d1 )
const {
546 G4double phimax = 4.*
M_PI;
548 G4double tau =
d2/
d1;
555 G4double xi1sq = xi1*xi1;
556 G4double xi2sq = xi2*xi2;
558 G4double Z1 = 2./(
mom*(ginv2+xi1sq));
559 G4double Z2 = 2./(
mom*(ginv2+xi2sq));
562 G4double V =
d1*(1./Z1-1./Z2);
565 G4double pmin =
p0 +
a*(1.+tau)/(2.*
M_PI);
566 G4double
ymax = tau*phimax;
569 G4int ipmin = (
int)pmin+1;
570 G4int ipmax = (
int)pmax;
573 G4double y0 = -0.5*
mom*
d1*(xi1sq-xi2sq)/(1+tau);
574 G4double
dy = (2.*
M_PI)/(1+tau);
582 for ( G4int
ip(ipmin);
ip<=ipmax; ++
ip ) {
587 term = (1./
y-1./(
y+V))*
sin(0.5*(
y+V));
595 tx = (
tx>term) ?
tx : term;
599 if (
t2 > 0. &&
t1 > term &&
t1 >
t2 ) {
600 if (
t1 < 0.0001*
sum )
break;
638 K =
static_cast<G4int
>((K1+K2)/2);
647 G4double X2(
A[K1+1]);
649 G4double xfinter((
F[K1]*(
X-X2)+
F[K1+1]*(X1-
X))/(X1-X2));
658 const G4double & PhotonEnergy )
const {
660 const G4double *SandiaCof(
Material->GetSandiaTable()->GetSandiaCofForMaterial(PhotonEnergy));
662 const G4double Energy2(PhotonEnergy*PhotonEnergy);
663 const G4double Energy3(PhotonEnergy*Energy2);
664 const G4double Energy4(Energy2*Energy2);
666 return ( SandiaCof[0]/PhotonEnergy +
667 SandiaCof[1]/Energy2 +
668 SandiaCof[2]/Energy3 +
669 SandiaCof[3]/Energy4 );