10#include "TDatabasePDG.h"
14#include "FairLogger.h"
24const Double_t BmnSsdPhysics::fgkSiCharge = 14.;
25const Double_t BmnSsdPhysics::fgkSiDensity = 2.336;
26const Double_t BmnSsdPhysics::fgkProtonMass = 0.938272081;
32BmnSsdPhysics::BmnSsdPhysics()
46 LOG(info) <<
"Instantiating SSD Physics... ";
47 ReadDataTablesStoppingPower();
48 ReadDataTablesLandauWidth();
51 SetUrbanParameters(fgkSiCharge);
66 Double_t vBias, Double_t vFd,
72 if ( z < 0. || z >
d ) {
73 LOG(error) <<
"SsdPhysics: z coordinate " << z
74 <<
" not inside sensor (d = " <<
d <<
")"
78 if ( temperature < 0. ) {
79 LOG(error) <<
"SsdPhysics: illegal temperature value "
86 Double_t diffConst = 8.61733e-5 * temperature;
91 if ( chargeType == 0 ) {
92 tau = 0.5 *
d *
d / vFd
93 *
log( ( vBias + ( 1. - 2. * z /
d ) * vFd ) / ( vBias - vFd ) );
95 else if ( chargeType == 1 ) {
96 tau = -0.5 *
d *
d / vFd
97 *
log( 1. - 2. * vFd * z /
d / ( vBias + vFd ) );
100 LOG(error) <<
"SsdPhysics: Illegal charge type " << chargeType
105 return sqrt(2. * diffConst * tau);
113 Double_t dZ, Double_t z) {
114 return ( vBias + vFd * (2. * z / dZ - 1.) ) / dZ;
122 Double_t dedx)
const {
125 Double_t gamma = (eKin + mass) / mass;
126 Double_t beta2 = 1. - 1. / ( gamma * gamma );
129 Double_t xAux = 2. * mass * beta2 * gamma * gamma;
132 Double_t sigma1 = dedx * fUrbanF1 / fUrbanE1
133 * ( TMath::Log(xAux / fUrbanE1) - beta2 )
134 / ( TMath::Log(xAux / fUrbanI) - beta2 )
136 Double_t sigma2 = dedx * fUrbanF2 / fUrbanE2
137 * ( TMath::Log(xAux / fUrbanE2) - beta2 )
138 / ( TMath::Log(xAux / fUrbanI) - beta2 )
140 Double_t sigma3 = dedx * fUrbanEmax * fUrbanR
141 / ( fUrbanI * ( fUrbanEmax + fUrbanI ) )
142 / TMath::Log( (fUrbanEmax + fUrbanI) / fUrbanI );
146 Int_t n1 = gRandom->Poisson( sigma1 * dz );
147 Int_t n2 = gRandom->Poisson( sigma2 * dz );
148 Int_t n3 = gRandom->Poisson( sigma3 * dz );
151 Double_t eLossIon = 0.;
152 for (Int_t j = 1; j <= n3; j++) {
153 Double_t uni = gRandom->Uniform(1.);
155 / ( 1. - uni * fUrbanEmax / ( fUrbanEmax + fUrbanI ) );
159 return (n1 * fUrbanE1 + n2 * fUrbanE2 + eLossIon);
176Double_t BmnSsdPhysics::InterpolateDataTable(Double_t eEquiv,
177 map<Double_t, Double_t>& table) {
179 std::map<Double_t, Double_t>::iterator it = table.lower_bound(eEquiv);
183 if ( it == table.begin() )
return it->second;
186 if ( it == table.end() )
return (--it)->second;
189 Double_t e2 = it->first;
190 Double_t v2 = it->second;
192 Double_t e1 = it->first;
193 Double_t v1 = it->second;
194 return ( v1 + ( eEquiv - e1 ) * ( v2 - v1 ) / ( e2 - e1 ) );
205 return InterpolateDataTable(mostProbableCharge, fLandauWidth);
214 Double_t charge = 0.;
218 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pid);
219 if ( particle ) charge = particle->Charge() / 3.;
222 else if ( pid > 1000000000 && pid < 1010000000 ) {
223 Int_t myPid = pid / 10000;
224 charge = Double_t( myPid - ( myPid / 1000 ) * 1000 );
239 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pid);
240 if ( particle ) mass = particle->Mass();
243 else if ( pid > 1000000000 && pid < 1010000000 ) {
244 Int_t myPid = pid - 1e9;
245 myPid -= (myPid / 10000 ) * 10000;
246 mass = Double_t( myPid / 10 );
256void BmnSsdPhysics::ReadDataTablesLandauWidth() {
261 TString dir = gSystem->Getenv(
"VMCWORKDIR");
262 TString errFileName = dir +
"/parameters/ssd/LandauWidthTable.txt";
268 inFile.open(errFileName);
269 if ( inFile.is_open() ) {
273 if ( inFile.eof() )
break;
274 fLandauWidth[q] = err;
277 LOG(info) <<
"SsdPhysics: " << setw(5) << right
278 << fLandauWidth.size() <<
" values read from "
282 LOG(fatal) <<
"SsdPhysics: Could not read from " << errFileName
291void BmnSsdPhysics::ReadDataTablesStoppingPower() {
300 TString dir = gSystem->Getenv(
"VMCWORKDIR");
301 TString eFileName = dir +
"/parameters/ssd/dEdx_Si_e.txt";
302 TString pFileName = dir +
"/parameters/ssd/dEdx_Si_p.txt";
308 inFile.open(eFileName);
309 if ( inFile.is_open() ) {
313 if ( inFile.eof() )
break;
316 fStoppingElectron[e] = dedx;
319 LOG(info) <<
"SsdPhysics: " << setw(5) << right
320 << fStoppingElectron.size() <<
" values read from "
324 LOG(fatal) <<
"SsdPhysics: Could not read from " << eFileName
328 inFile.open(pFileName);
329 if ( inFile.is_open() ) {
333 if ( inFile.eof() )
break;
336 fStoppingProton[e] = dedx;
339 LOG(info) <<
"SsdPhysics: " << setw(5) << right
340 << fStoppingProton.size() <<
" values read from "
344 LOG(fatal) <<
"SsdPhysics: Could not read from " << pFileName
353void BmnSsdPhysics::SetUrbanParameters(Double_t z) {
356 fUrbanI = 1.6e-8 * TMath::Power(z, 0.9);
367 fUrbanF1 = 1. - 2. / z;
371 fUrbanE2= 1.e-8 * z * z;
373 = TMath::Power(fUrbanI / TMath::Power(fUrbanE2, fUrbanF2), 1./fUrbanF1);
379 LOG(info) <<
"SsdPhysics: Urban parameters for z = " << z <<
" :"
381 LOG(info) <<
"I = " << fUrbanI*1.e9 <<
" eV, Emax = " << fUrbanEmax*1.e9
382 <<
" eV, E1 = " << fUrbanE1*1.e9 <<
" eV, E2 = "
383 << fUrbanE2*1.e9 <<
" eV, f1 = " << fUrbanF1 <<
", f2 = "
384 << fUrbanF2 <<
", r = " << fUrbanR;
395 if ( mass < 0. )
return 0.;
397 Bool_t isElectron = ( pid == 11 || pid == -11 );
412 Double_t stopPower = -1.;
414 stopPower = InterpolateDataTable(energy, fStoppingElectron);
416 Double_t eEquiv = energy * fgkProtonMass / mass;
417 stopPower = InterpolateDataTable(eEquiv, fStoppingProton);
421 stopPower *= fgkSiDensity;
424 if ( ! isElectron ) stopPower *= ( charge * charge );
const Float_t d
Z-ccordinate of the first GEM-station.
friend F32vec4 sqrt(const F32vec4 &a)
friend F32vec4 log(const F32vec4 &a)
Auxiliary class for simulating physics processes in Silicon.
static Double_t ParticleMass(Int_t pid)
static Double_t ParticleCharge(Int_t pid)
Double_t StoppingPower(Double_t eKin, Int_t pid)
static Double_t DiffusionWidth(Double_t z, Double_t d, Double_t vBias, Double_t vFd, Double_t temperature, Int_t chargeType)
static Double_t ElectricField(Double_t vBias, Double_t vFd, Double_t dZ, Double_t z)
Double_t EnergyLoss(Double_t dz, Double_t mass, Double_t eKin, Double_t dedx) const
Double_t LandauWidth(Double_t mostProbableCharge)
static BmnSsdPhysics * Instance()