Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Garfield::TrackBichsel Class Reference

#include <TrackBichsel.hh>

+ Inheritance diagram for Garfield::TrackBichsel:

Public Member Functions

 TrackBichsel ()
 Constructor.
 
virtual ~TrackBichsel ()
 Destructor.
 
virtual bool NewTrack (const double x0, const double y0, const double z0, const double t0, const double dx0, const double dy0, const double dz0)
 
virtual bool GetCluster (double &xcls, double &ycls, double &zcls, double &tcls, int &n, double &e, double &extra)
 
virtual double GetClusterDensity ()
 
virtual double GetStoppingPower ()
 Get the stopping power (mean energy loss [eV] per cm).
 
void SetDataFile (const std::string &filename)
 
- Public Member Functions inherited from Garfield::Track
 Track ()
 Constructor.
 
virtual ~Track ()
 Destructor.
 
virtual void SetParticle (const std::string &part)
 
void SetEnergy (const double e)
 Set the particle energy.
 
void SetBetaGamma (const double bg)
 Set the relative momentum of the particle.
 
void SetBeta (const double beta)
 Set the speed ( $\beta = v/c$) of the particle.
 
void SetGamma (const double gamma)
 Set the Lorentz factor of the particle.
 
void SetMomentum (const double p)
 Set the particle momentum.
 
void SetKineticEnergy (const double ekin)
 Set the kinetic energy of the particle.
 
double GetEnergy () const
 Return the particle energy.
 
double GetBetaGamma () const
 Return the $\beta\gamma$ of the projectile.
 
double GetBeta () const
 Return the speed ( $\beta = v/c$) of the projectile.
 
double GetGamma () const
 Return the Lorentz factor of the projectile.
 
double GetMomentum () const
 Return the particle momentum.
 
double GetKineticEnergy () const
 Return the kinetic energy of the projectile.
 
double GetCharge () const
 Get the charge of the projectile.
 
double GetMass () const
 Get the mass [eV / c2] of the projectile.
 
void SetSensor (Sensor *s)
 Set the sensor through which to transport the particle.
 
virtual bool NewTrack (const double x0, const double y0, const double z0, const double t0, const double dx0, const double dy0, const double dz0)=0
 
virtual bool GetCluster (double &xcls, double &ycls, double &zcls, double &tcls, int &n, double &e, double &extra)=0
 
virtual double GetClusterDensity ()
 
virtual double GetStoppingPower ()
 Get the stopping power (mean energy loss [eV] per cm).
 
void EnablePlotting (ViewDrift *viewer)
 Switch on plotting.
 
void DisablePlotting ()
 Switch off plotting.
 
void EnableDebugging ()
 Switch on debugging messages.
 
void DisableDebugging ()
 Switch off debugging messages.
 

Additional Inherited Members

- Protected Member Functions inherited from Garfield::Track
void PlotNewTrack (const double x0, const double y0, const double z0)
 
void PlotCluster (const double x0, const double y0, const double z0)
 
- Protected Attributes inherited from Garfield::Track
std::string m_className = "Track"
 
double m_q = -1.
 
int m_spin = 1
 
double m_mass
 
double m_energy = 0.
 
double m_beta2
 
bool m_isElectron = false
 
std::string m_particleName = "mu-"
 
Sensorm_sensor = nullptr
 
bool m_isChanged = true
 
ViewDriftm_viewer = nullptr
 
bool m_debug = false
 
size_t m_plotId = 0
 

Detailed Description

Generate tracks using differential cross-sections for silicon computed by Hans Bichsel. References:

Definition at line 14 of file TrackBichsel.hh.

Constructor & Destructor Documentation

◆ TrackBichsel()

Garfield::TrackBichsel::TrackBichsel ( )

Constructor.

Definition at line 17 of file TrackBichsel.cc.

18 : Track(), m_speed(SpeedOfLight * m_bg / sqrt(1. + m_bg * m_bg)) {
19 m_className = "TrackBichsel";
20}
std::string m_className
Definition: Track.hh:102
Track()
Constructor.
Definition: Track.cc:13
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

◆ ~TrackBichsel()

virtual Garfield::TrackBichsel::~TrackBichsel ( )
inlinevirtual

Destructor.

Definition at line 19 of file TrackBichsel.hh.

19{}

Member Function Documentation

◆ GetCluster()

bool Garfield::TrackBichsel::GetCluster ( double &  xcls,
double &  ycls,
double &  zcls,
double &  tcls,
int &  n,
double &  e,
double &  extra 
)
virtual

Get the next "cluster" (ionising collision of the charged particle).

Parameters
xcls,ycls,zclscoordinates of the collision
tclstime of the collision
nnumber of electrons produced
edeposited energy
extraadditional information (not always implemented)

Implements Garfield::Track.

Definition at line 96 of file TrackBichsel.cc.

97 {
98 if (!m_isInitialised || !m_isInMedium) return false;
99
100 const double d = -log(RndmUniformPos()) / m_imfp;
101 m_x += m_dx * d;
102 m_y += m_dy * d;
103 m_z += m_dz * d;
104 m_t += d / m_speed;
105
106 xcls = m_x;
107 ycls = m_y;
108 zcls = m_z;
109 tcls = m_t;
110 n = 0;
111 e = 0.;
112 extra = 0.;
113
114 Medium* medium;
115 if (!m_sensor->GetMedium(m_x, m_y, m_z, medium)) {
116 m_isInMedium = false;
117 if (m_debug) {
118 std::cout << m_className << "::GetCluster: Particle left the medium.\n";
119 }
120 return false;
121 }
122
123 if (medium->GetName() != "Si" || !medium->IsIonisable()) {
124 m_isInMedium = false;
125 if (m_debug) {
126 std::cout << m_className << "::GetCluster: Particle left the medium.\n";
127 }
128 return false;
129 }
130
131 const double u = m_nCdfEntries * RndmUniform();
132 const int j = int(u);
133 if (j == 0) {
134 e = 0. + u * m_cdf[0][m_iCdf];
135 } else if (j >= m_nCdfEntries) {
136 e = m_cdf[m_nCdfEntries - 1][m_iCdf];
137 } else {
138 e = m_cdf[j - 1][m_iCdf] +
139 (u - j) * (m_cdf[j][m_iCdf] - m_cdf[j - 1][m_iCdf]);
140 }
141
142 return true;
143}
bool GetMedium(const double x, const double y, const double z, Medium *&medium)
Get the medium at (x, y, z).
Definition: Sensor.cc:159
Sensor * m_sensor
Definition: Track.hh:112
bool m_debug
Definition: Track.hh:118
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
Definition: Random.hh:14
double RndmUniformPos()
Draw a random number uniformly distributed in the range (0, 1).
Definition: Random.hh:17

◆ GetClusterDensity()

double Garfield::TrackBichsel::GetClusterDensity ( )
virtual

Get the cluster density (number of ionizing collisions per cm or inverse mean free path for ionization).

Reimplemented from Garfield::Track.

Definition at line 145 of file TrackBichsel.cc.

145 {
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}};
160
161 if (m_isChanged) m_bg = GetBetaGamma();
162
163 if (m_bg < tabBg.front()) {
164 if (m_debug) {
165 std::cerr << m_className << "::GetClusterDensity:\n"
166 << " Bg is below the tabulated range.\n";
167 }
168 return tabImfp.front() * 1.e4;
169 } else if (m_bg > tabBg.back()) {
170 return tabImfp.back() * 1.e4;
171 }
172
173 // Locate the requested energy in the table.
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;
184
185 // Log-log interpolation
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);
192}
double GetBetaGamma() const
Return the of the projectile.
Definition: Track.hh:52
bool m_isChanged
Definition: Track.hh:114
DoubleAc exp(const DoubleAc &f)
Definition: DoubleAc.cpp:377
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

Referenced by NewTrack().

◆ GetStoppingPower()

double Garfield::TrackBichsel::GetStoppingPower ( )
virtual

Get the stopping power (mean energy loss [eV] per cm).

Reimplemented from Garfield::Track.

Definition at line 194 of file TrackBichsel.cc.

194 {
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}};
216
217 if (m_isChanged) m_bg = GetBetaGamma();
218
219 if (m_bg < tabBg.front()) {
220 if (m_debug) {
221 std::cerr << m_className << "::GetStoppingPower:\n"
222 << " Bg is below the tabulated range.\n";
223 }
224 return tabdEdx.front() * 1.e4;
225 } else if (m_bg > tabBg.back()) {
226 return tabdEdx.back() * 1.e4;
227 }
228
229 // Locate the requested energy in the table.
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;
235 if (m_debug) {
236 std::cout << m_className << "::GetStoppingPower:\n"
237 << " Bg = " << m_bg << "\n"
238 << " Interpolating between " << x0 << " and " << x1 << "\n";
239 }
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;
245
246 // Log-log interpolation
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);
253}

◆ NewTrack()

bool Garfield::TrackBichsel::NewTrack ( const double  x0,
const double  y0,
const double  z0,
const double  t0,
const double  dx0,
const double  dy0,
const double  dz0 
)
virtual

Calculate a new track starting from (x0, y0, z0) at time t0 in direction (dx0, dy0, dz0).

Implements Garfield::Track.

Definition at line 22 of file TrackBichsel.cc.

24 {
25 // Make sure a sensor has been defined.
26 if (!m_sensor) {
27 std::cerr << m_className << "::NewTrack: Sensor is not defined.\n";
28 m_isInMedium = false;
29 return false;
30 }
31
32 // If not yet done, load the cross-section table from file.
33 if (!m_isInitialised) {
34 if (!LoadCrossSectionTable(m_datafile)) {
35 std::cerr << m_className << "::NewTrack:\n"
36 << " Cross-section table could not be loaded.\n";
37 return false;
38 }
39 m_isInitialised = true;
40 }
41
42 // Make sure we are inside a medium.
43 Medium* medium;
44 if (!m_sensor->GetMedium(x0, y0, z0, medium)) {
45 std::cerr << m_className << "::NewTrack:\n"
46 << " No medium at initial position.\n";
47 m_isInMedium = false;
48 return false;
49 }
50
51 // Check if the medium is silicon.
52 if (medium->GetName() != "Si") {
53 std::cerr << m_className << "::NewTrack:\n"
54 << " Medium at initial position is not silicon.\n";
55 m_isInMedium = false;
56 return false;
57 }
58
59 // Check if primary ionisation has been enabled.
60 if (!medium->IsIonisable()) {
61 std::cerr << m_className << "::NewTrack:\n"
62 << " Medium at initial position is not ionisable.\n";
63 m_isInMedium = false;
64 return false;
65 }
66
67 m_isInMedium = true;
68 m_x = x0;
69 m_y = y0;
70 m_z = z0;
71 m_t = t0;
72
73 // Normalise the direction vector.
74 const double d = sqrt(dx0 * dx0 + dy0 * dy0 + dz0 * dz0);
75 if (d < Small) {
76 // In case of a null vector, choose a random direction.
77 RndmDirection(m_dx, m_dy, m_dz);
78 } else {
79 m_dx = dx0 / d;
80 m_dy = dy0 / d;
81 m_dz = dz0 / d;
82 }
83
84 // If the particle properties have changed, update the cross-section table.
85 if (m_isChanged) {
86 m_bg = GetBetaGamma();
87 m_imfp = GetClusterDensity();
88 m_speed = SpeedOfLight * GetBeta();
89 SelectCrossSectionTable();
90 m_isChanged = false;
91 }
92
93 return true;
94}
virtual double GetClusterDensity()
double GetBeta() const
Return the speed ( ) of the projectile.
Definition: Track.hh:54
void RndmDirection(double &dx, double &dy, double &dz, const double length=1.)
Draw a random (isotropic) direction vector.
Definition: Random.hh:107

◆ SetDataFile()

void Garfield::TrackBichsel::SetDataFile ( const std::string &  filename)
inline

Definition at line 30 of file TrackBichsel.hh.

30{ m_datafile = filename; }

The documentation for this class was generated from the following files: