Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Track.cc
Go to the documentation of this file.
1#include <iostream>
2#include <algorithm>
3#include <cctype>
4
7#include "Garfield/Sensor.hh"
8#include "Garfield/Track.hh"
10
11namespace Garfield {
12
13Track::Track(const std::string& name) : m_mass(MuonMass) {
14 m_className = "Track" + name;
15 SetBetaGamma(3.);
16}
17
18void Track::SetParticle(const std::string& part) {
19 std::string id = part;
20 std::transform(id.begin(), id.end(), id.begin(),
21 [](unsigned char c) -> unsigned char {
22 return std::toupper(c);
23 });
24 m_isElectron = false;
25 if (id == "ELECTRON" || id == "E-") {
26 m_q = -1;
27 m_mass = ElectronMass;
28 m_spin = 1;
29 m_isElectron = true;
30 m_particleName = "e-";
31 } else if (id == "POSITRON" || id == "E+") {
32 m_q = 1;
33 m_mass = ElectronMass;
34 m_spin = 1;
35 m_particleName = "e+";
36 } else if (id == "MUON" || id == "MU" || id == "MU-") {
37 m_q = -1;
38 m_mass = MuonMass;
39 m_spin = 1;
40 m_particleName = "mu-";
41 } else if (id == "MU+") {
42 m_q = 1;
43 m_mass = MuonMass;
44 m_spin = 1;
45 m_particleName = "mu+";
46 } else if (id == "PION" || id == "PI" || id == "PI-") {
47 m_q = -1;
48 m_mass = 139.57018e6;
49 m_spin = 0;
50 m_particleName = "pi-";
51 } else if (id == "PI+") {
52 m_q = 1;
53 m_mass = 139.57018e6;
54 m_spin = 0;
55 m_particleName = "pi+";
56 } else if (id == "KAON" || id == "K" || id == "K-") {
57 m_q = -1;
58 m_mass = 493.677e6;
59 m_spin = 0;
60 m_particleName = "K-";
61 } else if (id == "K+") {
62 m_q = 1;
63 m_mass = 493.677e6;
64 m_spin = 0;
65 m_particleName = "K+";
66 } else if (id == "PROTON" || id == "P") {
67 m_q = 1;
68 m_mass = ProtonMass;
69 m_spin = 1;
70 m_particleName = "p";
71 } else if (id == "ANTI-PROTON" || id == "ANTIPROTON" ||
72 id == "P-BAR" || id == "PBAR") {
73 m_q = -1;
74 m_mass = ProtonMass;
75 m_spin = 1;
76 m_particleName = "pbar";
77 } else if (id == "DEUTERON" || id == "D") {
78 m_q = 1;
79 m_mass = 1875.612793e6;
80 m_spin = 2;
81 m_particleName = "d";
82 } else if (id == "ALPHA") {
83 m_q = 2;
84 m_mass = 3.727379240e9;
85 m_spin = 0;
86 m_particleName = "alpha";
87 } else {
88 std::cerr << m_className << "::SetParticle:\n"
89 << " Particle " << part << " is not defined.\n";
90 }
91}
92
93void Track::SetEnergy(const double e) {
94 if (e <= m_mass) {
95 std::cerr << m_className << "::SetEnergy:\n"
96 << " Particle energy must be greater than the mass.\n";
97 return;
98 }
99
100 m_energy = e;
101 const double gamma = m_energy / m_mass;
102 m_beta2 = 1. - 1. / (gamma * gamma);
103 m_isChanged = true;
104}
105
106void Track::SetBetaGamma(const double bg) {
107 if (bg <= 0.) {
108 std::cerr << m_className << "::SetBetaGamma:\n"
109 << " Particle speed must be greater than zero.\n";
110 return;
111 }
112
113 const double bg2 = bg * bg;
114 m_energy = m_mass * sqrt(1. + bg2);
115 m_beta2 = bg2 / (1. + bg2);
116 m_isChanged = true;
117}
118
119void Track::SetBeta(const double beta) {
120 if (beta <= 0. || beta >= 1.) {
121 std::cerr << m_className << "::SetBeta:\n"
122 << " Beta must be between zero and one.\n";
123 return;
124 }
125
126 m_beta2 = beta * beta;
127 m_energy = m_mass * sqrt(1. / (1. - m_beta2));
128 m_isChanged = true;
129}
130
131void Track::SetGamma(const double gamma) {
132 if (gamma <= 1.) {
133 std::cerr << m_className << "::SetGamma:\n"
134 << " Gamma must be greater than one.\n";
135 return;
136 }
137
138 m_energy = m_mass * gamma;
139 m_beta2 = 1. - 1. / (gamma * gamma);
140 m_isChanged = true;
141}
142
143void Track::SetMomentum(const double p) {
144 if (p <= 0.) {
145 std::cerr << m_className << "::SetMomentum:\n"
146 << " Particle momentum must be greater than zero.\n";
147 return;
148 }
149
150 m_energy = sqrt(m_mass * m_mass + p * p);
151 const double bg = p / m_mass;
152 m_beta2 = bg * bg / (1. + bg * bg);
153 m_isChanged = true;
154}
155
156void Track::SetKineticEnergy(const double ekin) {
157 if (ekin <= 0.) {
158 std::cerr << m_className << "::SetKineticEnergy:\n"
159 << " Kinetic energy must be greater than zero.\n";
160 return;
161 }
162
163 m_energy = m_mass + ekin;
164 const double gamma = 1. + ekin / m_mass;
165 m_beta2 = 1. - 1. / (gamma * gamma);
166 m_isChanged = true;
167}
168
170 if (!s) {
171 std::cerr << m_className << "::SetSensor: Null pointer.\n";
172 return;
173 }
174
175 m_sensor = s;
176}
177
179 if (!view) {
180 std::cerr << m_className << "::EnablePlotting: Null pointer.\n";
181 return;
182 }
183 m_viewer = view;
184}
185
187 m_viewer = nullptr;
188}
189
190void Track::PlotNewTrack(const double x0, const double y0, const double z0) {
191 if (!m_viewer) return;
192 m_viewer->NewChargedParticleTrack(1, m_plotId, x0, y0, z0);
193}
194
195void Track::PlotCluster(const double x0, const double y0, const double z0) {
196 if (m_viewer) m_viewer->AddTrackPoint(m_plotId, x0, y0, z0);
197}
198
199std::array<double, 3> Track::StepBfield(const double dt,
200 const double qoverm, const double vmag, double bx, double by, double bz,
201 std::array<double, 3>& dir) {
202
203 double bmag = sqrt(bx * bx + by * by + bz * bz);
204 if (bmag < Garfield::Small) {
205 const double step = vmag * dt;
206 return {step * dir[0], step * dir[1], step * dir[2]};
207 }
208 std::array<std::array<double, 3>, 3> rot = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
209
210 bx /= bmag;
211 by /= bmag;
212 bz /= bmag;
213 const double bt = by * by + bz * bz;
214 if (bt > Garfield::Small) {
215 const double btInv = 1. / bt;
216 rot[0][0] = bx;
217 rot[0][1] = by;
218 rot[0][2] = bz;
219 rot[1][0] = -by;
220 rot[2][0] = -bz;
221 rot[1][1] = (bx * by * by + bz * bz) * btInv;
222 rot[2][2] = (bx * bz * bz + by * by) * btInv;
223 rot[1][2] = rot[2][1] = (bx - 1.) * by * bz * btInv;
224 } else if (bx < 0.) {
225 // B field is anti-parallel to x.
226 rot[0][0] = -1.;
227 rot[1][1] = -1.;
228 }
229 bmag *= Garfield::Tesla2Internal;
230 const double omega = qoverm * Garfield::OmegaCyclotronOverB * bmag *
231 Garfield::ElectronMass;
232 const double cphi = cos(omega * dt);
233 const double sphi = sin(omega * dt);
234
235 // Rotate the initial direction vector to the local frame.
236 std::array<double, 3> v0;
237 v0[0] = rot[0][0] * dir[0] + rot[0][1] * dir[1] + rot[0][2] * dir[2];
238 v0[1] = rot[1][0] * dir[0] + rot[1][1] * dir[1] + rot[1][2] * dir[2];
239 v0[2] = rot[2][0] * dir[0] + rot[2][1] * dir[1] + rot[2][2] * dir[2];
240
241 // Calculate the new direction in the local frame.
242 std::array<double, 3> v1;
243 v1[0] = v0[0];
244 v1[1] = v0[1] * cphi + v0[2] * sphi;
245 v1[2] = v0[2] * cphi - v0[1] * sphi;
246
247 // Rotate the direction vector back to the global frame.
248 dir[0] = rot[0][0] * v1[0] + rot[1][0] * v1[1] + rot[2][0] * v1[2];
249 dir[1] = rot[0][1] * v1[0] + rot[1][1] * v1[1] + rot[2][1] * v1[2];
250 dir[2] = rot[0][2] * v1[0] + rot[1][2] * v1[1] + rot[2][2] * v1[2];
251
252 // Calculate the new position in the local frame...
253 const double rho = vmag / omega;
254 const double u = vmag * v0[0] * dt;
255 const double v = rho * (v0[1] * sphi + v0[2] * (1. - cphi));
256 const double w = rho * (v0[2] * sphi - v0[1] * (1. - cphi));
257 // .... and in the global frame.
258 std::array<double, 3> pos;
259 pos[0] = rot[0][0] * u + rot[1][0] * v + rot[2][0] * w;
260 pos[1] = rot[0][1] * u + rot[1][1] * v + rot[2][1] * w;
261 pos[2] = rot[0][2] * u + rot[1][2] * v + rot[2][2] * w;
262 return pos;
263}
264
265}
size_t m_plotId
Definition Track.hh:122
void DisablePlotting()
Switch off plotting.
Definition Track.cc:186
void EnablePlotting(ViewDrift *viewer)
Switch on plotting.
Definition Track.cc:178
Sensor * m_sensor
Definition Track.hh:114
void SetBetaGamma(const double bg)
Set the relative momentum of the particle.
Definition Track.cc:106
void SetSensor(Sensor *s)
Set the sensor through which to transport the particle.
Definition Track.cc:169
bool m_isElectron
Definition Track.hh:111
bool m_isChanged
Definition Track.hh:116
void SetKineticEnergy(const double ekin)
Set the kinetic energy of the particle.
Definition Track.cc:156
static std::array< double, 3 > StepBfield(const double dt, const double qoverm, const double vmag, double bx, double by, double bz, std::array< double, 3 > &dir)
Definition Track.cc:199
void SetMomentum(const double p)
Set the particle momentum.
Definition Track.cc:143
virtual void SetParticle(const std::string &part)
Definition Track.cc:18
ViewDrift * m_viewer
Definition Track.hh:118
std::string m_particleName
Definition Track.hh:112
void PlotCluster(const double x0, const double y0, const double z0)
Definition Track.cc:195
double m_beta2
Definition Track.hh:110
std::string m_className
Definition Track.hh:104
void SetEnergy(const double e)
Set the particle energy.
Definition Track.cc:93
void SetGamma(const double gamma)
Set the Lorentz factor of the particle.
Definition Track.cc:131
double m_mass
Definition Track.hh:108
Track()=delete
Default constructor.
void SetBeta(const double beta)
Set the speed ( ) of the particle.
Definition Track.cc:119
double m_energy
Definition Track.hh:109
void PlotNewTrack(const double x0, const double y0, const double z0)
Definition Track.cc:190
Visualize drift lines and tracks.
Definition ViewDrift.hh:19