17 m_speed(SpeedOfLight * m_bg / sqrt(1. + m_bg * m_bg)),
26 m_datafile(
"SiM0invw.inv"),
29 m_isInitialised(false),
36 const double t0,
const double dx0,
const double dy0,
42 <<
" Sensor is not defined.\n";
48 if (!m_isInitialised) {
49 if (!LoadCrossSectionTable(m_datafile)) {
51 <<
" Cross-section table could not be loaded.\n";
54 m_isInitialised =
true;
61 <<
" No medium at initial position.\n";
67 if (medium->
GetName() !=
"Si") {
69 <<
" Medium at initial position is not silicon.\n";
77 <<
" Medium at initial position is not ionisable.\n";
89 const double d = sqrt(dx0 * dx0 + dy0 * dy0 + dz0 * dz0);
103 m_speed = SpeedOfLight *
GetBeta();
104 SelectCrossSectionTable();
112 double& tcls,
int& n,
double& e,
double& extra) {
114 if (!m_isInitialised || !m_isInMedium)
return false;
132 m_isInMedium =
false;
134 std::cout <<
m_className <<
"::GetCluster: Particle left the medium.\n";
140 m_isInMedium =
false;
142 std::cout <<
m_className <<
"::GetCluster: Particle left the medium.\n";
148 const int j = int(u);
150 e = 0. + u * m_cdf[0][m_iCdf];
151 }
else if (j >= m_nCdfEntries) {
152 e = m_cdf[m_nCdfEntries - 1][m_iCdf];
154 e = m_cdf[j - 1][m_iCdf] +
155 (u - j) * (m_cdf[j][m_iCdf] - m_cdf[j - 1][m_iCdf]);
163 const int nEntries = 38;
165 const double tabBg[nEntries] = {
166 0.316, 0.398, 0.501, 0.631, 0.794, 1.000, 1.259, 1.585,
167 1.995, 2.512, 3.162, 3.981, 5.012, 6.310, 7.943, 10.000,
168 12.589, 15.849, 19.953, 25.119, 31.623, 39.811, 50.119, 63.096,
169 79.433, 100.000, 125.893, 158.489, 199.526, 251.189, 316.228, 398.107,
170 501.187, 630.958, 794.329, 1000.000, 1258.926, 1584.894};
172 const double tabImfp[nEntries] = {
173 30.32496, 21.14965, 15.06555, 11.05635, 8.43259, 6.72876, 5.63184,
174 4.93252, 4.49174, 4.21786, 4.05090, 3.95186, 3.89531, 3.86471,
175 3.84930, 3.84226, 3.83952, 3.83887, 3.83912, 3.83970, 3.84035,
176 3.84095, 3.84147, 3.84189, 3.84223, 3.84249, 3.84269, 3.84283,
177 3.84293, 3.84300, 3.84304, 3.84308, 3.84310, 3.84311, 3.84312,
178 3.84313, 3.84313, 3.84314};
182 if (m_bg < tabBg[0]) {
184 std::cerr <<
m_className <<
"::GetClusterDensity:\n"
185 <<
" Bg is below the tabulated range.\n";
187 return tabImfp[0] * 1.e4;
188 }
else if (m_bg > tabBg[nEntries - 1]) {
189 return tabImfp[nEntries - 1] * 1.e4;
194 int iUp = nEntries - 1;
195 while (iUp - iLow > 1) {
196 const int iM = (iUp + iLow) >> 1;
197 if (m_bg >= tabBg[iM]) {
204 if (fabs(m_bg - tabBg[iLow]) < 1.e-6 * (tabBg[iUp] - tabBg[iLow])) {
205 return tabImfp[iLow] * 1.e4;
207 if (fabs(m_bg - tabBg[iUp]) < 1.e-6 * (tabBg[iUp] - tabBg[iLow])) {
208 return tabImfp[iUp] * 1.e4;
212 const double logX0 = log(tabBg[iLow]);
213 const double logX1 = log(tabBg[iUp]);
214 const double logY0 = log(tabImfp[iLow]);
215 const double logY1 = log(tabImfp[iUp]);
216 double d = logY0 + (log(m_bg) - logX0) * (logY1 - logY0) / (logX1 - logX0);
217 return 1.e4 * exp(d);
222 const unsigned int nEntries = 51;
224 const double tabBg[nEntries] = {
225 0.316, 0.398, 0.501, 0.631, 0.794, 1.000, 1.259,
226 1.585, 1.995, 2.512, 3.162, 3.981, 5.012, 6.310,
227 7.943, 10.000, 12.589, 15.849, 19.953, 25.119, 31.623,
228 39.811, 50.119, 63.096, 79.433, 100.000, 125.893, 158.489,
229 199.526, 251.189, 316.228, 398.107, 501.187, 630.958, 794.329,
230 1000.000, 1258.926, 1584.894, 1995.263, 2511.888, 3162.280, 3981.074,
231 5011.875, 6309.578, 7943.287, 10000.010, 12589.260, 15848.940, 19952.640,
232 25118.880, 31622.800};
234 const double tabdEdx[nEntries] = {
235 2443.71800, 1731.65600, 1250.93400, 928.69920, 716.37140, 578.28850,
236 490.83670, 437.33820, 406.58490, 390.95170, 385.29000, 386.12000,
237 391.07730, 398.53930, 407.39420, 416.90860, 426.63010, 436.30240,
238 445.78980, 455.02530, 463.97370, 472.61410, 480.92980, 488.90240,
239 496.51900, 503.77130, 510.65970, 517.19570, 523.39830, 529.29120,
240 534.90670, 540.27590, 545.42880, 550.39890, 555.20800, 559.88820,
241 564.45780, 568.93850, 573.34700, 577.69140, 581.99010, 586.25090,
242 590.47720, 594.68660, 598.86880, 603.03510, 607.18890, 611.33250,
243 615.46810, 619.59740, 623.72150};
247 if (m_bg < tabBg[0]) {
249 std::cerr <<
m_className <<
"::GetStoppingPower:\n";
250 std::cerr <<
" Bg is below the tabulated range.\n";
252 return tabdEdx[0] * 1.e4;
253 }
else if (m_bg > tabBg[nEntries - 1]) {
254 return tabdEdx[nEntries - 1] * 1.e4;
259 int iUp = nEntries - 1;
261 while (iUp - iLow > 1) {
262 iM = (iUp + iLow) >> 1;
263 if (m_bg >= tabBg[iM]) {
271 std::cout <<
m_className <<
"::GetStoppingPower:\n";
272 std::cout <<
" Bg = " << m_bg <<
"\n";
273 std::cout <<
" Interpolating between " << tabBg[iLow] <<
" and "
274 << tabBg[iUp] <<
"\n";
277 if (fabs(m_bg - tabBg[iLow]) < 1.e-6 * (tabBg[iUp] - tabBg[iLow])) {
278 return tabdEdx[iLow] * 1.e4;
280 if (fabs(m_bg - tabBg[iUp]) < 1.e-6 * (tabBg[iUp] - tabBg[iLow])) {
281 return tabdEdx[iUp] * 1.e4;
285 const double logX0 = log(tabBg[iLow]);
286 const double logX1 = log(tabBg[iUp]);
287 const double logY0 = log(tabdEdx[iLow]);
288 const double logY1 = log(tabdEdx[iUp]);
290 logY0 + (log(m_bg) - logX0) * (logY1 - logY0) / (logX1 - logX0);
291 return 1.e4 * exp(dedx);
294bool TrackBichsel::LoadCrossSectionTable(
const std::string& filename) {
296 const int nRows = 10000;
297 const int nBlocks = 2;
298 const int nColumns = 5;
300 const int iSwitch = 99999;
303 char* pPath = getenv(
"GARFIELD_HOME");
305 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
306 std::cerr <<
" Environment variable GARFIELD_HOME is not set.\n";
309 std::string filepath = pPath;
310 filepath = filepath +
"/Data/" + filename;
313 std::ifstream infile;
314 infile.open(filepath.c_str(), std::ios::in);
317 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
318 std::cerr <<
" Error opening file " << filename <<
".\n";
323 m_cdf.assign(nRows, std::vector<double>(nBlocks * nColumns, 0.));
326 std::istringstream data;
330 double val[nColumns];
334 while (!infile.eof() && !infile.fail()) {
336 std::getline(infile, line);
338 line.erase(line.begin(),
339 std::find_if(line.begin(), line.end(),
340 not1(std::ptr_fun<int, int>(isspace))));
342 if (line[0] ==
'#' || line[0] ==
'*' || (line[0] ==
'/' && line[1] ==
'/'))
346 data >> dummy1 >> dummy2;
347 for (
int j = 0; j < nColumns; ++j) data >> val[j];
349 if (dummy1 == iSwitch) {
351 if (iBlock >= nBlocks)
break;
355 }
else if (dummy1 != iRow + 1) {
356 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
357 std::cerr <<
" Error reading file " << filename <<
".\n";
358 std::cerr <<
" Expected entry " << iRow + 1 <<
", got entry " << dummy1
365 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
366 std::cerr <<
" Table in file is longer than expected.\n";
371 for (
int j = nColumns; j--;) m_cdf[iRow][nColumns * iBlock + j] = val[j];
376 std::cerr << m_className <<
"::LoadCrossSectionTable:\n";
377 std::cerr <<
" Error reading file " << filename <<
".\n";
385 std::cout <<
m_className <<
"::LoadCrossSectionTable:\n";
386 std::cout <<
" Input file: " << filename << std::endl;
387 std::cout <<
" Successfully loaded cross-section table from file.\n";
389 m_nCdfEntries = nRows;
393void TrackBichsel::SelectCrossSectionTable() {
395 const unsigned int nTables = 10;
396 const double tabBg[nTables] = {0.31623, 1.00000, 3.16228, 10.00000,
397 31.62278, 100.00000, 316.22780, 1000.00000,
398 3162.27800, 10000.00000};
400 bool gotValue =
false;
402 for (
unsigned int i = 0; i < nTables - 1; ++i) {
403 double split =
exp(0.5 * (log(tabBg[i]) + log(tabBg[i + 1])));
410 if (!gotValue) m_iCdf = nTables - 1;
413 std::cout <<
m_className <<
"::SelectCrossSectionTable:\n";
414 std::cout <<
" Requested value: bg = " << m_bg <<
"\n";
415 std::cout <<
" Used table: bg = " << tabBg[m_iCdf] <<
"\n";
Abstract base class for media.
const std::string & GetName() const
bool GetMedium(const double x, const double y, const double z, Medium *&medium)
Get the medium at (x, y, z).
virtual double GetStoppingPower()
Get the stopping power (mean energy loss [eV] per cm).
virtual bool GetCluster(double &xcls, double &ycls, double &zcls, double &tcls, int &n, double &e, double &extra)
virtual double GetClusterDensity()
virtual bool NewTrack(const double x0, const double y0, const double z0, const double t0, const double dx0, const double dy0, const double dz0)
TrackBichsel()
Constructor.
double GetBetaGamma() const
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
void RndmDirection(double &dx, double &dy, double &dz, const double length=1.)
Draw a random (isotropic) direction vector.
double RndmUniformPos()
Draw a random number uniformly distributed in the range (0, 1).
DoubleAc exp(const DoubleAc &f)