18 :
Track(), m_speed(SpeedOfLight * m_bg / sqrt(1. + m_bg * m_bg)) {
23 const double t0,
const double dx0,
const double dy0,
27 std::cerr <<
m_className <<
"::NewTrack: Sensor is not defined.\n";
33 if (!m_isInitialised) {
34 if (!LoadCrossSectionTable(m_datafile)) {
36 <<
" Cross-section table could not be loaded.\n";
39 m_isInitialised =
true;
46 <<
" No medium at initial position.\n";
52 if (medium->
GetName() !=
"Si") {
54 <<
" Medium at initial position is not silicon.\n";
62 <<
" Medium at initial position is not ionisable.\n";
74 const double d = sqrt(dx0 * dx0 + dy0 * dy0 + dz0 * dz0);
88 m_speed = SpeedOfLight *
GetBeta();
89 SelectCrossSectionTable();
97 double& tcls,
int& n,
double& e,
double& extra) {
98 if (!m_isInitialised || !m_isInMedium)
return false;
116 m_isInMedium =
false;
118 std::cout <<
m_className <<
"::GetCluster: Particle left the medium.\n";
124 m_isInMedium =
false;
126 std::cout <<
m_className <<
"::GetCluster: Particle left the medium.\n";
132 const int j = int(u);
134 e = 0. + u * m_cdf[0][m_iCdf];
135 }
else if (j >= m_nCdfEntries) {
136 e = m_cdf[m_nCdfEntries - 1][m_iCdf];
138 e = m_cdf[j - 1][m_iCdf] +
139 (u - j) * (m_cdf[j][m_iCdf] - m_cdf[j - 1][m_iCdf]);
146 constexpr unsigned int nEntries = 38;
147 constexpr std::array<double, nEntries> tabBg = {
148 {0.316, 0.398, 0.501, 0.631, 0.794, 1.000, 1.259, 1.585,
149 1.995, 2.512, 3.162, 3.981, 5.012, 6.310, 7.943, 10.000,
150 12.589, 15.849, 19.953, 25.119, 31.623, 39.811, 50.119, 63.096,
151 79.433, 100.000, 125.893, 158.489, 199.526, 251.189, 316.228, 398.107,
152 501.187, 630.958, 794.329, 1000.000, 1258.926, 1584.894}};
153 constexpr std::array<double, nEntries> tabImfp = {
154 {30.32496, 21.14965, 15.06555, 11.05635, 8.43259, 6.72876, 5.63184,
155 4.93252, 4.49174, 4.21786, 4.05090, 3.95186, 3.89531, 3.86471,
156 3.84930, 3.84226, 3.83952, 3.83887, 3.83912, 3.83970, 3.84035,
157 3.84095, 3.84147, 3.84189, 3.84223, 3.84249, 3.84269, 3.84283,
158 3.84293, 3.84300, 3.84304, 3.84308, 3.84310, 3.84311, 3.84312,
159 3.84313, 3.84313, 3.84314}};
163 if (m_bg < tabBg.front()) {
165 std::cerr <<
m_className <<
"::GetClusterDensity:\n"
166 <<
" Bg is below the tabulated range.\n";
168 return tabImfp.front() * 1.e4;
169 }
else if (m_bg > tabBg.back()) {
170 return tabImfp.back() * 1.e4;
174 const auto it1 = std::upper_bound(tabBg.cbegin(), tabBg.cend(), m_bg);
175 if (it1 == tabBg.cbegin())
return 1.e4 * tabImfp.front();
176 const auto it0 = std::prev(it1);
177 const double x0 = *it0;
178 const double x1 = *it1;
179 const double y0 = tabImfp[it0 - tabBg.cbegin()];
180 const double y1 = tabImfp[it1 - tabBg.cbegin()];
181 const double tol = 1.e-6 * (x1 - x0);
182 if (fabs(m_bg - x0) < tol)
return y0 * 1.e4;
183 if (fabs(m_bg - x1) < tol)
return y1 * 1.e4;
186 const double lnx0 = log(x0);
187 const double lnx1 = log(x1);
188 const double lny0 = log(y0);
189 const double lny1 = log(y1);
190 const double d = lny0 + (log(m_bg) - lnx0) * (lny1 - lny0) / (lnx1 - lnx0);
191 return 1.e4 * exp(d);
195 constexpr unsigned int nEntries = 51;
196 constexpr std::array<double, nEntries> tabBg = {
197 {0.316, 0.398, 0.501, 0.631, 0.794, 1.000,
198 1.259, 1.585, 1.995, 2.512, 3.162, 3.981,
199 5.012, 6.310, 7.943, 10.000, 12.589, 15.849,
200 19.953, 25.119, 31.623, 39.811, 50.119, 63.096,
201 79.433, 100.000, 125.893, 158.489, 199.526, 251.189,
202 316.228, 398.107, 501.187, 630.958, 794.329, 1000.000,
203 1258.926, 1584.894, 1995.263, 2511.888, 3162.280, 3981.074,
204 5011.875, 6309.578, 7943.287, 10000.010, 12589.260, 15848.940,
205 19952.640, 25118.880, 31622.800}};
206 constexpr std::array<double, nEntries> tabdEdx = {
207 {2443.71800, 1731.65600, 1250.93400, 928.69920, 716.37140, 578.28850,
208 490.83670, 437.33820, 406.58490, 390.95170, 385.29000, 386.12000,
209 391.07730, 398.53930, 407.39420, 416.90860, 426.63010, 436.30240,
210 445.78980, 455.02530, 463.97370, 472.61410, 480.92980, 488.90240,
211 496.51900, 503.77130, 510.65970, 517.19570, 523.39830, 529.29120,
212 534.90670, 540.27590, 545.42880, 550.39890, 555.20800, 559.88820,
213 564.45780, 568.93850, 573.34700, 577.69140, 581.99010, 586.25090,
214 590.47720, 594.68660, 598.86880, 603.03510, 607.18890, 611.33250,
215 615.46810, 619.59740, 623.72150}};
219 if (m_bg < tabBg.front()) {
221 std::cerr <<
m_className <<
"::GetStoppingPower:\n"
222 <<
" Bg is below the tabulated range.\n";
224 return tabdEdx.front() * 1.e4;
225 }
else if (m_bg > tabBg.back()) {
226 return tabdEdx.back() * 1.e4;
230 const auto it1 = std::upper_bound(tabBg.cbegin(), tabBg.cend(), m_bg);
231 if (it1 == tabBg.cbegin())
return 1.e4 * tabdEdx.front();
232 const auto it0 = std::prev(it1);
233 const double x0 = *it0;
234 const double x1 = *it1;
236 std::cout <<
m_className <<
"::GetStoppingPower:\n"
237 <<
" Bg = " << m_bg <<
"\n"
238 <<
" Interpolating between " << x0 <<
" and " << x1 <<
"\n";
240 const double y0 = tabdEdx[it0 - tabBg.cbegin()];
241 const double y1 = tabdEdx[it1 - tabBg.cbegin()];
242 const double tol = 1.e-6 * (x1 - x0);
243 if (fabs(m_bg - x0) < tol)
return y0 * 1.e4;
244 if (fabs(m_bg - x1) < tol)
return y1 * 1.e4;
247 const double lnx0 = log(x0);
248 const double lnx1 = log(x1);
249 const double lny0 = log(y0);
250 const double lny1 = log(y1);
251 const double dedx = lny0 + (log(m_bg) - lnx0) * (lny1 - lny0) / (lnx1 - lnx0);
252 return 1.e4 * exp(dedx);
255bool TrackBichsel::LoadCrossSectionTable(
const std::string& filename) {
256 const int nRows = 10000;
257 const int nBlocks = 2;
258 const int nColumns = 5;
260 const int iSwitch = 99999;
263 char* pPath = getenv(
"GARFIELD_HOME");
265 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
266 std::cerr <<
" Environment variable GARFIELD_HOME is not set.\n";
269 std::string filepath = pPath;
270 filepath = filepath +
"/Data/" + filename;
273 std::ifstream infile;
274 infile.open(filepath.c_str(), std::ios::in);
277 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
278 std::cerr <<
" Error opening file " << filename <<
".\n";
283 m_cdf.assign(nRows, std::vector<double>(nBlocks * nColumns, 0.));
286 std::istringstream data;
290 double val[nColumns];
294 while (!infile.eof() && !infile.fail()) {
296 std::getline(infile, line);
299 if (line.empty())
continue;
301 if (line[0] ==
'#' || line[0] ==
'*' || (line[0] ==
'/' && line[1] ==
'/'))
305 data >> dummy1 >> dummy2;
306 for (
int j = 0; j < nColumns; ++j) data >> val[j];
308 if (dummy1 == iSwitch) {
310 if (iBlock >= nBlocks)
break;
314 }
else if (dummy1 != iRow + 1) {
315 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
316 std::cerr <<
" Error reading file " << filename <<
".\n";
317 std::cerr <<
" Expected entry " << iRow + 1 <<
", got entry " << dummy1
324 std::cerr <<
m_className <<
"::LoadCrossSectionTable:\n";
325 std::cerr <<
" Table in file is longer than expected.\n";
330 for (
int j = nColumns; j--;) m_cdf[iRow][nColumns * iBlock + j] = val[j];
335 std::cerr << m_className <<
"::LoadCrossSectionTable:\n";
336 std::cerr <<
" Error reading file " << filename <<
".\n";
344 std::cout <<
m_className <<
"::LoadCrossSectionTable:\n";
345 std::cout <<
" Input file: " << filename << std::endl;
346 std::cout <<
" Successfully loaded cross-section table from file.\n";
348 m_nCdfEntries = nRows;
352void TrackBichsel::SelectCrossSectionTable() {
353 constexpr unsigned int nTables = 10;
354 const double tabBg[nTables] = {0.31623, 1.00000, 3.16228, 10.00000,
355 31.62278, 100.00000, 316.22780, 1000.00000,
356 3162.27800, 10000.00000};
358 bool gotValue =
false;
360 for (
unsigned int i = 0; i < nTables - 1; ++i) {
361 double split =
exp(0.5 * (log(tabBg[i]) + log(tabBg[i + 1])));
368 if (!gotValue) m_iCdf = nTables - 1;
371 std::cout <<
m_className <<
"::SelectCrossSectionTable:\n";
372 std::cout <<
" Requested value: bg = " << m_bg <<
"\n";
373 std::cout <<
" Used table: bg = " << tabBg[m_iCdf] <<
"\n";
Abstract base class for media.
const std::string & GetName() const
Get the medium name/identifier.
bool IsIonisable() const
Is charge deposition by charged particles/photon enabled in this medium?
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.
Abstract base class for track generation.
double GetBetaGamma() const
Return the of the projectile.
double GetBeta() const
Return the speed ( ) of the projectile.
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
void ltrim(std::string &line)
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)