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
172 ,material->getDouble(
"DENSITY")*(CLHEP::gram / CLHEP::cm3)
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");
193 G4double PlasmaCof(4.0*
M_PI*CLHEP::fine_structure_const*CLHEP::hbarc*CLHEP::hbarc*CLHEP::hbarc/CLHEP::electron_mass_c2);
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()
200 <<
"; plasma energy : " <<
m_WplasmaFoil/CLHEP::eV <<
" eV");
202 <<
"; plasma energy : " <<
m_WplasmaGas/CLHEP::eV <<
" eV");
226 ATH_MSG_DEBUG (
"Constructor TRTTransitionRadiation::Initialize() DONE!" );
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());
276 G4double Gamma(1.0 + KineticEnergy/ParticleMass);
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;
316 G4double StepLength(aStep.GetStepLength());
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.);
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();
417 ATH_MSG_VERBOSE (
" Photon generated with energy : " << Ephot/CLHEP::keV
418 <<
" keV; position: ( " << pos.x()/CLHEP::cm <<
" cm, "
419 << pos.y()/CLHEP::cm <<
" cm, " << pos.z()/CLHEP::cm <<
" cm )" );
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();
427 X = sin(Theta)*cos(Phi);
428 Y = sin(Theta)*sin(Phi);
431 TRPhotonDirection.set(X,Y,Z);
432 TRPhotonDirection.rotateUz( ParticleDirection );
433 TRPhotonDirection.unit();
436 TRPhoton =
new G4DynamicParticle( G4Gamma::Gamma(),
439 aParticleChange.AddSecondary( TRPhoton );
443 aParticleChange.ProposeEnergy( KineticEnergy-Esum );
446 <<
"Number of TR photons generated: " << NumberOfPhotonsGenerated );
448 return &aParticleChange;
544 const G4double & Gamma,
546 const G4double & d1 )
const {
547 G4double phimax = 4.*
M_PI;
548 G4double ginv2 = 1./(Gamma*Gamma);
549 G4double tau = d2/d1;
551 G4double mom = omega/CLHEP::hbarc;
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);
565 G4double p0 = mom*d1*(xi1sq-xi2sq)/(4.*
M_PI);
566 G4double pmin = p0 +
a*(1.+tau)/(2.*
M_PI);
567 G4double
ymax = tau*phimax;
568 G4double pmax = p0 +
ymax*(1.+tau)/(2.*
M_PI);
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;
605 return ( sum*4.*2.*CLHEP::fine_structure_const/(1.+tau));