43 if (particle !=
"electron" && particle !=
"e" && particle !=
"e-") {
44 std::cerr <<
className <<
"::SetParticle:\n";
45 std::cerr <<
" Only electrons can be transported.\n";
50 const double t0,
const double dx0,
51 const double dy0,
const double dz0) {
57 std::cerr <<
className <<
"::NewTrack:\n";
58 std::cerr <<
" Sensor is not defined.\n";
65 std::cerr <<
className <<
"::NewTrack:\n";
66 std::cerr <<
" No medium at initial position.\n";
70 std::cerr <<
className <<
"::NewTrack:\n";
71 std::cerr <<
" Medium at initial position is not ionisable.\n";
76 if (!medium->
IsGas()) {
77 std::cerr <<
className <<
"::NewTrack:\n";
78 std::cerr <<
" Medium at initial position is not a gas.\n";
82 if (!SetupGas(medium)) {
83 std::cerr <<
className <<
"::NewTrack:\n";
84 std::cerr <<
" Properties of medium " << medium->
GetName()
85 <<
" are not available.\n";
89 if (!UpdateCrossSection()) {
90 std::cerr <<
className <<
"::NewTrack:\n";
91 std::cerr <<
" Cross-sections could not be calculated.\n";
101 const double dd =
sqrt(dx0 * dx0 + dy0 * dy0 + dz0 * dz0);
104 std::cout <<
className <<
"::NewTrack:\n";
105 std::cout <<
" Direction vector has zero norm.\n";
106 std::cout <<
" Initial direction is randomized.\n";
109 const double stheta =
sqrt(1. - ctheta * ctheta);
111 dx =
cos(phi) * stheta;
112 dy =
sin(phi) * stheta;
126 double& tcls,
int& ncls,
double& edep,
136 std::cerr <<
className <<
"::GetCluster:\n";
137 std::cerr <<
" Track not initialized.\n";
138 std::cerr <<
" Call NewTrack first.\n";
160 if (medium->
GetName() != mediumName ||
172 for (
int i = 0; i < nComponents; ++i) {
181 const double e0 = ElectronMass * (
sqrt(1. / (1. -
beta2)) - 1.);
182 double esec = components[iComponent].wSplit *
183 tan(
RndmUniform() * atan((e0 - components[iComponent].ethr) /
184 (2. * components[iComponent].wSplit)));
185 esec = components[iComponent].wSplit *
186 pow(esec / components[iComponent].wSplit, 0.9524);
188 electrons.resize(nElectrons);
189 electrons[0].energy = esec;
190 electrons[0].x = xcls;
191 electrons[0].y = ycls;
192 electrons[0].z = zcls;
203 std::cerr <<
className <<
"::GetClusterDensity:\n";
204 std::cerr <<
" Track has not been initialized.\n";
209 std::cerr <<
className <<
"::GetClusterDensity:\n";
210 std::cerr <<
" Mean free path is not available.\n";
220 std::cerr <<
className <<
"::GetStoppingPower:\n";
221 std::cerr <<
" Track has not been initialised.\n";
225 const double prefactor = 4 * Pi *
pow(HbarC / ElectronMass, 2);
226 const double lnBg2 = log(
beta2 / (1. -
beta2));
230 const double e0 = ElectronMass * (
sqrt(1. / (1. -
beta2)) - 1.);
231 for (
int i = nComponents; i--;) {
234 mediumDensity * components[i].fraction * (prefactor /
beta2) *
235 (components[i].m2Ion * (lnBg2 -
beta2) + components[i].cIon);
236 const double ew = (e0 - components[i].ethr) / (2 * components[i].wSplit);
239 (components[i].wSplit / (2 * atan(ew))) * log(1. + ew * ew);
240 dedx += cmean * emean;
246bool TrackElectron::SetupGas(
Medium* gas) {
252 std::cerr <<
className <<
"::SetupGas:\n";
253 std::cerr <<
" Medium is not defined.\n";
259 if (nComponents <= 0) {
260 std::cerr <<
className <<
"::SetupGas:\n";
261 std::cerr <<
" Medium composition is not defined.\n";
265 components.resize(nComponents);
271 for (
int i = nComponents; i--;) {
272 std::string gasname =
"";
275 components[i].fraction =
frac;
276 components[i].p = 0.;
277 if (gasname ==
"CF4") {
278 components[i].m2Ion = 7.2;
279 components[i].cIon = 93.;
280 components[i].x0Dens = 1.;
281 components[i].x1Dens = 0.;
282 components[i].cDens = 0.;
283 components[i].aDens = 0.;
284 components[i].mDens = 0.;
285 components[i].ethr = 15.9;
286 components[i].wSplit = 19.5;
287 }
else if (gasname ==
"Ar") {
288 components[i].m2Ion = 3.593;
289 components[i].cIon = 39.7;
290 components[i].x0Dens = 1.7635;
291 components[i].x1Dens = 4.4855;
292 components[i].cDens = 11.9480;
293 components[i].aDens = 0.19714;
294 components[i].mDens = 2.9618;
295 components[i].ethr = 15.75961;
296 components[i].wSplit = 15.;
297 }
else if (gasname ==
"He") {
298 components[i].m2Ion = 0.489;
299 components[i].cIon = 5.5;
300 components[i].x0Dens = 2.2017;
301 components[i].x1Dens = 3.6122;
302 components[i].cDens = 11.1393;
303 components[i].aDens = 0.13443;
304 components[i].mDens = 5.8347;
305 components[i].ethr = 24.58739;
306 components[i].wSplit = 10.5;
307 }
else if (gasname ==
"He-3") {
308 components[i].m2Ion = 0.489;
309 components[i].cIon = 5.5;
310 components[i].x0Dens = 2.2017;
311 components[i].x1Dens = 3.6122;
312 components[i].cDens = 11.1393;
313 components[i].aDens = 0.13443;
314 components[i].mDens = 5.8347;
315 components[i].ethr = 24.58739;
316 components[i].wSplit = 10.5;
317 }
else if (gasname ==
"Ne") {
318 components[i].m2Ion = 1.69;
319 components[i].cIon = 17.8;
320 components[i].x0Dens = 2.0735;
321 components[i].x1Dens = 4.6421;
322 components[i].cDens = 11.9041;
323 components[i].aDens = 0.08064;
324 components[i].mDens = 3.5771;
325 components[i].ethr = 21.56454;
326 components[i].wSplit = 19.5;
327 }
else if (gasname ==
"Kr") {
328 components[i].m2Ion = 5.5;
329 components[i].cIon = 56.9;
330 components[i].x0Dens = 1.7158;
331 components[i].x1Dens = 5.0748;
332 components[i].cDens = 12.5115;
333 components[i].aDens = 0.07446;
334 components[i].mDens = 3.4051;
335 components[i].ethr = 13.996;
336 components[i].wSplit = 21.;
337 }
else if (gasname ==
"Xe") {
338 components[i].m2Ion = 8.04;
339 components[i].cIon = 75.25;
340 components[i].x0Dens = 1.5630;
341 components[i].x1Dens = 4.7371;
342 components[i].cDens = 12.7281;
343 components[i].aDens = 0.23314;
344 components[i].mDens = 2.7414;
345 components[i].ethr = 12.129843;
346 components[i].wSplit = 23.7;
347 }
else if (gasname ==
"CH4") {
348 components[i].m2Ion = 3.75;
349 components[i].cIon = 42.5;
350 components[i].x0Dens = 1.6263;
351 components[i].x1Dens = 3.9716;
352 components[i].cDens = 9.5243;
353 components[i].aDens = 0.09253;
354 components[i].mDens = 3.6257;
355 components[i].ethr = 12.65;
356 components[i].wSplit = 8.;
357 }
else if (gasname ==
"iC4H10") {
358 components[i].m2Ion = 15.5;
359 components[i].cIon = 160.;
360 components[i].x0Dens = 1.3788;
361 components[i].x1Dens = 3.7524;
362 components[i].cDens = 8.5633;
363 components[i].aDens = 0.10852;
364 components[i].mDens = 3.4884;
365 components[i].ethr = 10.67;
366 components[i].wSplit = 7.;
367 }
else if (gasname ==
"CO2") {
368 components[i].m2Ion = 5.6;
369 components[i].cIon = 57.91;
370 components[i].x0Dens = 1.6294;
371 components[i].x1Dens = 4.1825;
372 components[i].aDens = 0.11768;
373 components[i].mDens = 3.3227;
374 components[i].ethr = 13.777;
375 components[i].wSplit = 13.;
376 }
else if (gasname ==
"N2") {
377 components[i].m2Ion = 3.35;
378 components[i].cIon = 38.1;
379 components[i].x0Dens = 1.7378;
380 components[i].x1Dens = 4.1323;
381 components[i].cDens = 10.5400;
382 components[i].aDens = 0.15349;
383 components[i].mDens = 3.2125;
384 components[i].ethr = 15.581;
385 components[i].wSplit = 13.8;
387 std::cerr <<
className <<
"::SetupGas:\n";
388 std::cerr <<
" Cross-section for " << gasname
389 <<
" is not available.\n";
402bool TrackElectron::UpdateCrossSection() {
404 const double prefactor = 4 * Pi *
pow(HbarC / ElectronMass, 2);
405 const double lnBg2 = log(
beta2 / (1. -
beta2));
407 const double eta = mediumDensity / LoschmidtNumber;
408 const double x = 0.5 * (lnBg2 + log(eta)) / log(10.);
410 for (
int i = nComponents; i--;) {
412 if (components[i].x0Dens < components[i].x1Dens &&
413 x >= components[i].x0Dens) {
414 delta = 2 * log(10.) * x - components[i].cDens;
415 if (x < components[i].x1Dens) {
416 delta += components[i].aDens *
417 pow(components[i].x1Dens - x, components[i].mDens);
421 (components[i].fraction * prefactor /
beta2) *
422 (components[i].m2Ion * (lnBg2 -
beta2 - delta) + components[i].cIon);
423 components[i].p = cs;
428 std::cerr <<
className <<
"::UpdateCrossSection:\n";
429 std::cerr <<
" Total cross-section <= 0.\n";
433 mfp = 1. / (csSum * mediumDensity);
435 for (
int i = 0; i < nComponents; ++i) {
436 components[i].p /= csSum;
437 if (i > 0) components[i].p += components[i - 1].p;
DoubleAc cos(const DoubleAc &f)
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc sqrt(const DoubleAc &f)
DoubleAc sin(const DoubleAc &f)
virtual double GetNumberDensity() const
virtual void GetComponent(const unsigned int &i, std::string &label, double &f)
unsigned int GetNumberOfComponents() const
virtual bool IsGas() const
std::string GetName() const
bool IsInArea(const double x, const double y, const double z)
bool GetMedium(const double x, const double y, const double z, Medium *&medium)
double GetClusterDensity()
bool NewTrack(const double x0, const double y0, const double z0, const double t0, const double dx0, const double dy0, const double dz0)
bool GetCluster(double &xcls, double &ycls, double &zcls, double &tcls, int &ncls, double &ecls, double &extra)
void SetParticle(std::string particle)
double GetStoppingPower()
void SetBetaGamma(const double bg)