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

Generate tracks using Heed++. More...

#include <TrackHeed.hh>

+ Inheritance diagram for Garfield::TrackHeed:

Public Member Functions

 TrackHeed ()
 Constructor.
 
virtual ~TrackHeed ()
 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)
 
bool GetCluster (double &xcls, double &ycls, double &zcls, double &tcls, int &ne, int &ni, double &e, double &extra)
 
bool GetElectron (const unsigned int i, double &x, double &y, double &z, double &t, double &e, double &dx, double &dy, double &dz)
 
bool GetIon (const unsigned int i, double &x, double &y, double &z, double &t) const
 
virtual double GetClusterDensity ()
 
virtual double GetStoppingPower ()
 Get the stopping power (mean energy loss [eV] per cm).
 
double GetW () const
 
double GetFanoFactor () const
 
void TransportDeltaElectron (const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &nel, int &ni)
 
void TransportDeltaElectron (const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &nel)
 
void TransportPhoton (const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &nel, int &ni)
 
void TransportPhoton (const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &nel)
 
void EnableElectricField ()
 
void DisableElectricField ()
 
void EnableMagneticField ()
 
void DisableMagneticField ()
 
void EnableDeltaElectronTransport ()
 
void DisableDeltaElectronTransport ()
 
void EnablePhotonReabsorption ()
 
void DisablePhotonReabsorption ()
 
void EnablePhotoAbsorptionCrossSectionOutput ()
 
void DisablePhotoAbsorptionCrossSectionOutput ()
 
void SetEnergyMesh (const double e0, const double e1, const int nsteps)
 
void SetParticleUser (const double m, const double z)
 
- Public Member Functions inherited from Garfield::Track
 Track ()
 Constructor.
 
virtual ~Track ()
 Destructor.
 
virtual void SetParticle (const std::string &part)
 Set the type of particle.
 
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
 
double GetBetaGamma () const
 
double GetBeta () const
 
double GetGamma () const
 
double GetMomentum () const
 
double GetKineticEnergy () const
 
double GetCharge () const
 Get the charge of the projectile.
 
double GetMass () const
 Get the mass [eV / c2] of the projectile.
 
void SetSensor (Sensor *s)
 
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)
 
void DisablePlotting ()
 
void EnableDebugging ()
 
void DisableDebugging ()
 

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
 
double m_q
 
int m_spin
 
double m_mass
 
double m_energy
 
double m_beta2
 
bool m_isElectron
 
std::string m_particleName
 
Sensorm_sensor
 
bool m_isChanged
 
bool m_usePlotting
 
ViewDriftm_viewer
 
bool m_debug
 
int m_plotId
 

Detailed Description

Generate tracks using Heed++.

Definition at line 37 of file TrackHeed.hh.

Constructor & Destructor Documentation

◆ TrackHeed()

Garfield::TrackHeed::TrackHeed ( )

Constructor.

Definition at line 60 of file TrackHeed.cc.

61 : m_ready(false),
62 m_hasActiveTrack(false),
63 m_mediumDensity(-1.),
64 m_mediumName(""),
65 m_usePhotonReabsorption(true),
66 m_usePacsOutput(false),
67 m_doDeltaTransport(true),
68 m_matter(NULL),
69 m_gas(NULL),
70 m_material(NULL),
71 m_atPacs(NULL),
72 m_molPacs(NULL),
73 m_emin(2.e-6),
74 m_emax(2.e-1),
75 m_nEnergyIntervals(200),
76 m_energyMesh(NULL),
77 m_transferCs(NULL),
78 m_elScat(NULL),
79 m_lowSigma(NULL),
80 m_pairProd(NULL),
81 m_deltaCs(NULL),
82 m_chamber(NULL),
83 m_lX(0.),
84 m_lY(0.),
85 m_lZ(0.),
86 m_cX(0.),
87 m_cY(0.),
88 m_cZ(0.) {
89
90 m_className = "TrackHeed";
91 m_conductionElectrons.reserve(1000);
92 m_conductionIons.reserve(1000);
93}
std::string m_className
Definition: Track.hh:80

◆ ~TrackHeed()

Garfield::TrackHeed::~TrackHeed ( )
virtual

Destructor.

Definition at line 95 of file TrackHeed.cc.

95 {
96
97 if (m_matter) delete m_matter;
98 if (m_gas) delete m_gas;
99 if (m_material) delete m_material;
100 if (m_atPacs) delete m_atPacs;
101 if (m_molPacs) delete m_molPacs;
102 if (m_energyMesh) delete m_energyMesh;
103 if (m_transferCs) delete m_transferCs;
104 if (m_elScat) delete m_elScat;
105 if (m_lowSigma) delete m_lowSigma;
106 if (m_pairProd) delete m_pairProd;
107 if (m_deltaCs) delete m_deltaCs;
108 if (m_chamber) delete m_chamber;
109}

Member Function Documentation

◆ DisableDeltaElectronTransport()

void Garfield::TrackHeed::DisableDeltaElectronTransport ( )
inline

Definition at line 100 of file TrackHeed.hh.

100{ m_doDeltaTransport = false; }

◆ DisableElectricField()

void Garfield::TrackHeed::DisableElectricField ( )

Definition at line 848 of file TrackHeed.cc.

848{ m_fieldMap.UseEfield(false); }
void UseEfield(const bool flag)
Definition: HeedFieldMap.h:25

◆ DisableMagneticField()

void Garfield::TrackHeed::DisableMagneticField ( )

Definition at line 850 of file TrackHeed.cc.

850{ m_fieldMap.UseBfield(false); }
void UseBfield(const bool flag)
Definition: HeedFieldMap.h:26

◆ DisablePhotoAbsorptionCrossSectionOutput()

void Garfield::TrackHeed::DisablePhotoAbsorptionCrossSectionOutput ( )
inline

Definition at line 106 of file TrackHeed.hh.

106{ m_usePacsOutput = false; }

◆ DisablePhotonReabsorption()

void Garfield::TrackHeed::DisablePhotonReabsorption ( )
inline

Definition at line 103 of file TrackHeed.hh.

103{ m_usePhotonReabsorption = false; }

◆ EnableDeltaElectronTransport()

void Garfield::TrackHeed::EnableDeltaElectronTransport ( )
inline

Definition at line 99 of file TrackHeed.hh.

99{ m_doDeltaTransport = true; }

Referenced by GarfieldPhysics::InitializePhysics().

◆ EnableElectricField()

void Garfield::TrackHeed::EnableElectricField ( )

Definition at line 847 of file TrackHeed.cc.

847{ m_fieldMap.UseEfield(true); }

◆ EnableMagneticField()

void Garfield::TrackHeed::EnableMagneticField ( )

Definition at line 849 of file TrackHeed.cc.

849{ m_fieldMap.UseBfield(true); }

◆ EnablePhotoAbsorptionCrossSectionOutput()

void Garfield::TrackHeed::EnablePhotoAbsorptionCrossSectionOutput ( )
inline

Definition at line 105 of file TrackHeed.hh.

105{ m_usePacsOutput = true; }

◆ EnablePhotonReabsorption()

void Garfield::TrackHeed::EnablePhotonReabsorption ( )
inline

Definition at line 102 of file TrackHeed.hh.

102{ m_usePhotonReabsorption = true; }

◆ GetCluster() [1/2]

bool Garfield::TrackHeed::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 327 of file TrackHeed.cc.

328 {
329
330 int ni = 0;
331 return GetCluster(xcls, ycls, zcls, tcls, n, ni, e, extra);
332}
virtual bool GetCluster(double &xcls, double &ycls, double &zcls, double &tcls, int &n, double &e, double &extra)
Definition: TrackHeed.cc:327

Referenced by GarfieldPhysics::DoIt(), and GetCluster().

◆ GetCluster() [2/2]

bool Garfield::TrackHeed::GetCluster ( double &  xcls,
double &  ycls,
double &  zcls,
double &  tcls,
int &  ne,
int &  ni,
double &  e,
double &  extra 
)

Definition at line 334 of file TrackHeed.cc.

336 {
337
338 // Initialise and reset.
339 xcls = ycls = zcls = tcls = 0.;
340 extra = 0.;
341 ne = ni = 0;
342 e = 0.;
343
344 m_deltaElectrons.clear();
345 m_conductionElectrons.clear();
346 m_conductionIons.clear();
347
348 // Make sure NewTrack has been called successfully.
349 if (!m_ready) {
350 std::cerr << m_className << "::GetCluster:\n"
351 << " Track has not been initialized. Call NewTrack first.\n";
352 return false;
353 }
354
355 std::vector<Heed::gparticle*>::const_iterator end = m_particleBank.end();
356 if (m_bankIterator == end) {
357 std::cerr << m_className << "::GetCluster:\n"
358 << " There are no more clusters on this track.\n";
359 return false;
360 }
361
362 // Look for the next cluster (i. e. virtual photon) in the list.
363 Heed::HeedPhoton* virtualPhoton = NULL;
364 for (; m_bankIterator != end; ++m_bankIterator) {
365 // Convert the particle to a (virtual) photon.
366 virtualPhoton = dynamic_cast<Heed::HeedPhoton*>(*m_bankIterator);
367 if (!virtualPhoton) {
368 std::cerr << m_className << "::GetCluster:\n"
369 << " Particle is not a virtual photon. Program bug!\n";
370 // Try the next element.
371 continue;
372 }
373
374 // Get the location of the interaction (convert from mm to cm
375 // and shift with respect to bounding box center).
376 xcls = virtualPhoton->currpos.pt.v.x * 0.1 + m_cX;
377 ycls = virtualPhoton->currpos.pt.v.y * 0.1 + m_cY;
378 zcls = virtualPhoton->currpos.pt.v.z * 0.1 + m_cZ;
379 tcls = virtualPhoton->currpos.time;
380 // Skip clusters outside the drift area or outside the active medium.
381 if (!IsInside(xcls, ycls, zcls)) continue;
382 // Add the first ion (at the position of the cluster).
383 m_conductionIons.push_back(
384 Heed::HeedCondElectron(virtualPhoton->currpos.pt, tcls));
385 ++m_bankIterator;
386 break;
387 }
388
389 // Stop if we did not find a virtual photon.
390 if (m_bankIterator == end || !virtualPhoton) return false;
391 // Plot the cluster, if requested.
392 if (m_usePlotting) PlotCluster(xcls, ycls, zcls);
393
394 std::vector<Heed::gparticle*> secondaries;
395 // Transport the virtual photon.
396 virtualPhoton->fly(secondaries);
397 // Get the transferred energy (convert from MeV to eV).
398 e = virtualPhoton->energy * 1.e6;
399
400 while (!secondaries.empty()) {
401 std::vector<Heed::gparticle*> newSecondaries;
402 // Loop over the secondaries.
403 std::vector<Heed::gparticle*>::iterator it;
404 std::vector<Heed::gparticle*>::const_iterator send = secondaries.end();
405 for (it = secondaries.begin(); it != send; ++it) {
406 // Check if it is a delta electron.
407 Heed::HeedDeltaElectron* delta = dynamic_cast<Heed::HeedDeltaElectron*>(*it);
408 if (delta) {
409 extra += delta->curr_kin_energy * 1.e6;
410 const double x = delta->currpos.pt.v.x * 0.1 + m_cX;
411 const double y = delta->currpos.pt.v.y * 0.1 + m_cY;
412 const double z = delta->currpos.pt.v.z * 0.1 + m_cZ;
413 if (!IsInside(x, y, z)) continue;
414 if (m_doDeltaTransport) {
415 // Transport the delta electron.
416 delta->fly(newSecondaries);
417 // Add the conduction electrons and ions to the list.
418 m_conductionElectrons.insert(m_conductionElectrons.end(),
419 delta->conduction_electrons.begin(),
420 delta->conduction_electrons.end());
421 m_conductionIons.insert(m_conductionIons.end(),
422 delta->conduction_ions.begin(),
423 delta->conduction_ions.end());
424 } else {
425 // Add the delta electron to the list, for later use.
426 deltaElectron newDeltaElectron;
427 newDeltaElectron.x = delta->currpos.pt.v.x * 0.1 + m_cX;
428 newDeltaElectron.y = delta->currpos.pt.v.y * 0.1 + m_cY;
429 newDeltaElectron.z = delta->currpos.pt.v.z * 0.1 + m_cZ;
430 newDeltaElectron.t = delta->currpos.time;
431 newDeltaElectron.e = delta->curr_kin_energy * 1.e6;
432 newDeltaElectron.dx = delta->currpos.dir.x;
433 newDeltaElectron.dy = delta->currpos.dir.y;
434 newDeltaElectron.dz = delta->currpos.dir.z;
435 m_deltaElectrons.push_back(newDeltaElectron);
436 }
437 continue;
438 }
439 // Check if it is a real photon.
440 Heed::HeedPhoton* photon = dynamic_cast<Heed::HeedPhoton*>(*it);
441 if (!photon) {
442 std::cerr << m_className << "::GetCluster:\n"
443 << " Particle is neither an electron nor a photon.\n";
444 }
445 extra += photon->energy * 1.e6;
446 const double x = photon->currpos.pt.v.x * 0.1 + m_cX;
447 const double y = photon->currpos.pt.v.y * 0.1 + m_cY;
448 const double z = photon->currpos.pt.v.z * 0.1 + m_cZ;
449 if (!IsInside(x, y, z)) continue;
450 // Transport the photon.
451 if (m_usePhotonReabsorption) photon->fly(newSecondaries);
452 }
453 for (it = secondaries.begin(); it != secondaries.end(); ++it) {
454 if (*it) delete *it;
455 }
456 secondaries.clear();
457 secondaries.swap(newSecondaries);
458 }
459 // Get the total number of electrons produced in this step.
460 ne = m_doDeltaTransport ? m_conductionElectrons.size() : m_deltaElectrons.size();
461 ni = m_conductionIons.size();
462 return true;
463}
void PlotCluster(const double x0, const double y0, const double z0)
Definition: Track.cc:221
bool m_usePlotting
Definition: Track.hh:94
std::vector< HeedCondElectron > conduction_electrons
std::vector< HeedCondElectron > conduction_ions
double energy
Photon energy [MeV].
Definition: HeedPhoton.h:37
stvpoint currpos
Definition: gparticle.h:177
virtual void fly(std::vector< gparticle * > &secondaries)
Transport the particle.
Definition: gparticle.h:225
double curr_kin_energy
Definition: mparticle.h:32
vec v
Definition: vec.h:376
vfloat time
Definition: gparticle.h:47
vec dir
Unit vector, in the first system in the tree.
Definition: gparticle.h:25
point pt
Coordinates in the first system in the tree.
Definition: gparticle.h:23
vfloat x
Definition: vec.h:203
vfloat z
Definition: vec.h:203
vfloat y
Definition: vec.h:203

◆ GetClusterDensity()

double Garfield::TrackHeed::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 293 of file TrackHeed.cc.

293 {
294
295 if (!m_ready) {
296 std::cerr << m_className << "::GetClusterDensity:\n"
297 << " Track has not been initialized.\n";
298 return 0.;
299 }
300
301 if (!m_transferCs) {
302 std::cerr << m_className << "::GetClusterDensity:\n"
303 << " Ionisation cross-section is not available.\n";
304 return 0.;
305 }
306
307 return m_transferCs->quanC;
308}
double quanC
Integrated (ionization) cross-section.
Definition: EnTransfCS.h:70

◆ GetElectron()

bool Garfield::TrackHeed::GetElectron ( const unsigned int  i,
double &  x,
double &  y,
double &  z,
double &  t,
double &  e,
double &  dx,
double &  dy,
double &  dz 
)

Retrieve the properties of a conduction or delta electron in the current cluster.

Parameters
iindex of the electron
x,y,zcoordinates of the electron
ttime
ekinetic energy (only meaningful for delta-electrons)
dx,dy,dzdirection vector (only meaningful for delta-electrons)

Definition at line 465 of file TrackHeed.cc.

467 {
468
469 // Make sure NewTrack has successfully been called.
470 if (!m_ready) {
471 std::cerr << m_className << "::GetElectron:\n"
472 << " Track has not been initialized. Call NewTrack first.\n";
473 return false;
474 }
475
476 if (m_doDeltaTransport) {
477 // Make sure an electron with this number exists.
478 if (i >= m_conductionElectrons.size()) {
479 std::cerr << m_className << "::GetElectron: Index out of range.\n";
480 return false;
481 }
482
483 x = m_conductionElectrons[i].ptloc.v.x * 0.1 + m_cX;
484 y = m_conductionElectrons[i].ptloc.v.y * 0.1 + m_cY;
485 z = m_conductionElectrons[i].ptloc.v.z * 0.1 + m_cZ;
486 t = m_conductionElectrons[i].time;
487 e = 0.;
488 dx = dy = dz = 0.;
489
490 } else {
491 // Make sure a delta electron with this number exists.
492 if (i >= m_deltaElectrons.size()) {
493 std::cerr << m_className << "::GetElectron:\n"
494 << " Delta electron number out of range.\n";
495 return false;
496 }
497
498 x = m_deltaElectrons[i].x;
499 y = m_deltaElectrons[i].y;
500 z = m_deltaElectrons[i].z;
501 t = m_deltaElectrons[i].t;
502 e = m_deltaElectrons[i].e;
503 dx = m_deltaElectrons[i].dx;
504 dy = m_deltaElectrons[i].dy;
505 dz = m_deltaElectrons[i].dz;
506 }
507 return true;
508}

Referenced by GarfieldPhysics::DoIt().

◆ GetFanoFactor()

double Garfield::TrackHeed::GetFanoFactor ( ) const

Definition at line 1271 of file TrackHeed.cc.

1271{ return m_matter->F; }
double F
Fano factor.
Definition: HeedMatterDef.h:39

◆ GetIon()

bool Garfield::TrackHeed::GetIon ( const unsigned int  i,
double &  x,
double &  y,
double &  z,
double &  t 
) const

Retrieve the properties of an ion in the current cluster.

Parameters
iindex of the ion
x,y,zcoordinates of the ion
ttime

Definition at line 510 of file TrackHeed.cc.

511 {
512
513 // Make sure a "conduction" ion with this number exists.
514 if (i >= m_conductionIons.size()) {
515 std::cerr << m_className << "::GetIon: Index out of range.\n";
516 return false;
517 }
518
519 x = m_conductionIons[i].ptloc.v.x * 0.1 + m_cX;
520 y = m_conductionIons[i].ptloc.v.y * 0.1 + m_cY;
521 z = m_conductionIons[i].ptloc.v.z * 0.1 + m_cZ;
522 t = m_conductionIons[i].time;
523 return true;
524}

◆ GetStoppingPower()

double Garfield::TrackHeed::GetStoppingPower ( )
virtual

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

Reimplemented from Garfield::Track.

Definition at line 310 of file TrackHeed.cc.

310 {
311
312 if (!m_ready) {
313 std::cerr << m_className << "::GetStoppingPower:\n"
314 << " Track has not been initialized.\n";
315 return 0.;
316 }
317
318 if (!m_transferCs) {
319 std::cerr << m_className << "::GetStoppingPower:\n"
320 << " Ionisation cross-section is not available.\n";
321 return 0.;
322 }
323
324 return m_transferCs->meanC1 * 1.e6;
325}

◆ GetW()

double Garfield::TrackHeed::GetW ( ) const

Definition at line 1270 of file TrackHeed.cc.

1270{ return m_matter->W * 1.e6; }
double W
Mean work per pair production, MeV.
Definition: HeedMatterDef.h:38

Referenced by GarfieldPhysics::DoIt().

◆ NewTrack()

bool Garfield::TrackHeed::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 111 of file TrackHeed.cc.

113 {
114
115 m_hasActiveTrack = false;
116 m_ready = false;
117
118 // Make sure the sensor has been set.
119 if (!m_sensor) {
120 std::cerr << m_className << "::NewTrack:\n"
121 << " Sensor is not defined.\n";
122 return false;
123 }
124
125 // Get the bounding box.
126 double xmin = 0., ymin = 0., zmin = 0.;
127 double xmax = 0., ymax = 0., zmax = 0.;
128 if (!m_sensor->GetArea(xmin, ymin, zmin, xmax, ymax, zmax)) {
129 std::cerr << m_className << "::NewTrack:\n"
130 << " Drift area is not set.\n";
131 return false;
132 }
133 // Check if the bounding box has changed.
134 const double lx = fabs(xmax - xmin);
135 const double ly = fabs(ymax - ymin);
136 const double lz = fabs(zmax - zmin);
137 if (m_debug) {
138 std::cout << m_className << "::NewTrack:\n"
139 << " Bounding box dimensions:\n"
140 << " x: " << lx << " cm\n"
141 << " y: " << ly << " cm\n"
142 << " z: " << lz << " cm\n";
143 }
144 if (fabs(lx - m_lX) > Small || fabs(ly - m_lY) > Small || fabs(lz - m_lZ) > Small) {
145 m_lX = lx;
146 m_lY = ly;
147 m_lZ = lz;
148 m_isChanged = true;
149 }
150 // Update the center of the bounding box.
151 if (std::isinf(xmin) || std::isinf(xmax)) {
152 m_cX = 0.;
153 } else {
154 m_cX = 0.5 * (xmin + xmax);
155 }
156 if (std::isinf(ymin) || std::isinf(ymax)) {
157 m_cY = 0.;
158 } else {
159 m_cY = 0.5 * (ymin + ymax);
160 }
161 if (std::isinf(zmin) || std::isinf(zmax)) {
162 m_cZ = 0.;
163 } else {
164 m_cZ = 0.5 * (zmin + zmax);
165 }
166 if (m_debug) {
167 std::cout << m_className << "::NewTrack:\n"
168 << " Center of bounding box:\n"
169 << " x: " << m_cX << " cm\n"
170 << " y: " << m_cY << " cm\n"
171 << " z: " << m_cZ << " cm\n";
172 }
173
174 m_fieldMap.SetSensor(m_sensor);
175 m_fieldMap.SetCentre(m_cX, m_cY, m_cZ);
176
177 // Make sure the initial position is inside an ionisable medium.
178 Medium* medium = NULL;
179 if (!m_sensor->GetMedium(x0, y0, z0, medium)) {
180 std::cerr << m_className << "::NewTrack:\n"
181 << " No medium at initial position.\n";
182 return false;
183 } else if (!medium->IsIonisable()) {
184 std::cerr << m_className << "::NewTrack:\n"
185 << " Medium at initial position is not ionisable.\n";
186 return false;
187 }
188
189 // Check if the medium has changed since the last call.
190 if (medium->GetName() != m_mediumName ||
191 fabs(medium->GetMassDensity() - m_mediumDensity) > 1.e-9) {
192 m_isChanged = true;
193 }
194
195 // If medium, particle or bounding box have changed,
196 // update the cross-sections.
197 if (m_isChanged) {
198 if (!Setup(medium)) return false;
199 m_isChanged = false;
200 m_mediumName = medium->GetName();
201 m_mediumDensity = medium->GetMassDensity();
202 }
203
204 ClearParticleBank();
205
206 m_deltaElectrons.clear();
207 m_conductionElectrons.clear();
208 m_conductionIons.clear();
209
210 // Check the direction vector.
211 double dx = dx0, dy = dy0, dz = dz0;
212 const double d = sqrt(dx * dx + dy * dy + dz * dz);
213 if (d < Small) {
214 if (m_debug) {
215 std::cout << m_className << "::NewTrack:\n"
216 << " Direction vector has zero norm.\n"
217 << " Initial direction is randomized.\n";
218 }
219 // Null vector. Sample the direction isotropically.
220 RndmDirection(dx, dy, dz);
221 } else {
222 // Normalise the direction vector.
223 dx /= d;
224 dy /= d;
225 dz /= d;
226 }
227 Heed::vec velocity(dx, dy, dz);
228 velocity = velocity * Heed::CLHEP::c_light * GetBeta();
229
230 if (m_debug) {
231 std::cout << m_className << "::NewTrack:\n Track starts at ("
232 << x0 << ", " << y0 << ", " << z0 << ") at time " << t0 << "\n"
233 << " Direction: (" << dx << ", " << dy << ", " << dz << ")\n";
234 }
235
236 // Initial position (shift with respect to bounding box center and
237 // convert from cm to mm).
238 Heed::point p0((x0 - m_cX) * 10., (y0 - m_cY) * 10., (z0 - m_cZ) * 10.);
239
240 // Setup the particle.
242 if (m_particleName == "e-") {
243 particleType = &Heed::electron_def;
244 } else if (m_particleName == "e+") {
245 particleType = &Heed::positron_def;
246 } else if (m_particleName == "mu-") {
247 particleType = &Heed::muon_minus_def;
248 } else if (m_particleName == "mu+") {
249 particleType = &Heed::muon_plus_def;
250 } else if (m_particleName == "pi-") {
251 particleType = &Heed::pi_minus_meson_def;
252 } else if (m_particleName == "pi+") {
253 particleType = &Heed::pi_plus_meson_def;
254 } else if (m_particleName == "K-") {
255 particleType = &Heed::K_minus_meson_def;
256 } else if (m_particleName == "K+") {
257 particleType = &Heed::K_plus_meson_def;
258 } else if (m_particleName == "p") {
259 particleType = &Heed::proton_def;
260 } else if (m_particleName == "pbar") {
261 particleType = &Heed::anti_proton_def;
262 } else if (m_particleName == "d") {
263 particleType = &Heed::deuteron_def;
264 } else if (m_particleName == "alpha") {
265 particleType = &Heed::alpha_particle_def;
266 } else if (m_particleName == "exotic") {
267 // User defined particle
270 particleType = &Heed::user_particle_def;
271 } else {
272 // Not a predefined particle, use muon definition.
273 if (m_q > 0.) {
274 particleType = &Heed::muon_minus_def;
275 } else {
276 particleType = &Heed::muon_plus_def;
277 }
278 }
279
280 Heed::HeedParticle particle(m_chamber, p0, velocity, t0,
281 particleType, &m_fieldMap);
282 // Transport the particle.
283 particle.fly(m_particleBank);
284 m_bankIterator = m_particleBank.begin();
285 m_hasActiveTrack = true;
286 m_ready = true;
287
288 // Plot the new track.
289 if (m_usePlotting) PlotNewTrack(x0, y0, z0);
290 return true;
291}
bool GetMedium(const double x, const double y, const double z, Medium *&medium)
Get the medium at (x, y, z).
Definition: Sensor.cc:150
bool GetArea(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Return the current user area.
Definition: Sensor.cc:237
Sensor * m_sensor
Definition: Track.hh:90
bool m_debug
Definition: Track.hh:97
double GetBeta() const
Definition: Track.hh:40
bool m_isChanged
Definition: Track.hh:92
double m_q
Definition: Track.hh:82
std::string m_particleName
Definition: Track.hh:88
double m_mass
Definition: Track.hh:84
void PlotNewTrack(const double x0, const double y0, const double z0)
Definition: Track.cc:214
void SetSensor(Garfield::Sensor *sensor)
Definition: HeedFieldMap.h:19
void SetCentre(const double x, const double y, const double z)
Definition: HeedFieldMap.h:20
void set_mass(const double m)
void set_charge(const double z)
Point.
Definition: vec.h:374
Definition: vec.h:186
void RndmDirection(double &dx, double &dy, double &dz, const double length=1.)
Draw a random (isotropic) direction vector.
Definition: Random.hh:106
particle_def pi_minus_meson_def("pi_minus_meson", "pi-", 139.56755 *MeV/c_squared, -eplus, 0, 0, 0.0, spin_def(1.0, -1.0))
Definition: particle_def.h:125
particle_def pi_plus_meson_def("pi_plus_meson", "pi+", 139.56755 *MeV/c_squared, eplus, 0, 0, 0.0, spin_def(1.0, 1.0))
Definition: particle_def.h:123
particle_def muon_minus_def("muon_minus", "mu-", 105.658367 *MeV/c_squared, electron_charge, 1, 0, 0.5, spin_def(0.0, 0.0))
Definition: particle_def.h:112
particle_def alpha_particle_def("alpha_particle", "alpha", 3727.417 *MeV/c_squared, 2 *eplus, 0, 4, 0.0, spin_def(0.0, 0.0))
Definition: particle_def.h:131
particle_def anti_proton_def("", "p-", proton_def)
Definition: particle_def.h:115
particle_def deuteron_def("deuteron", "dtr", 1875.613 *MeV/c_squared, eplus, 0, 2, 0.0, spin_def(0.0, 0.0))
Definition: particle_def.h:130
particle_def proton_def("proton", "p+", proton_mass_c2/c_squared, eplus, 0, 1, 0.5, spin_def(0.5, 0.5))
Definition: particle_def.h:114
particle_def K_minus_meson_def("K_minus_meson_def", "K-", K_plus_meson_def)
Definition: particle_def.h:128
particle_def K_plus_meson_def("K_plus_meson_def", "K+", 493.677 *MeV/c_squared, 1, 0, 0, 0.0, spin_def(0.5, -0.5))
Definition: particle_def.h:127
particle_def user_particle_def("user_particle", "X", 139.56755 *MeV/c_squared, eplus, 0, 0, 0.0, spin_def(0.0, 0.0))
Definition: particle_def.h:134
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615
particle_def muon_plus_def("muon_plus", "mu+", muon_minus_def)
Definition: particle_def.h:113
particle_def positron_def("positron", "e+", electron_def)
Definition: particle_def.h:111
particle_def electron_def("electron", "e-", electron_mass_c2/c_squared, electron_charge, 1, 0, 0.5, spin_def(0.0, 0.0))
Definition: particle_def.h:110
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

Referenced by GarfieldPhysics::DoIt().

◆ SetEnergyMesh()

void Garfield::TrackHeed::SetEnergyMesh ( const double  e0,
const double  e1,
const int  nsteps 
)

Definition at line 852 of file TrackHeed.cc.

853 {
854
855 if (fabs(e1 - e0) < Small) {
856 std::cerr << m_className << "::SetEnergyMesh:\n";
857 std::cerr << " Invalid energy range:\n";
858 std::cerr << " " << e0 << " < E [eV] < " << e1 << "\n";
859 return;
860 }
861
862 if (nsteps <= 0) {
863 std::cerr << m_className << "::SetEnergyMesh:\n";
864 std::cerr << " Number of intervals must be > 0.\n";
865 return;
866 }
867
868 m_emin = std::min(e0, e1);
869 m_emax = std::max(e0, e1);
870 m_emin *= 1.e-6;
871 m_emax *= 1.e-6;
872 m_nEnergyIntervals = nsteps;
873}

◆ SetParticleUser()

void Garfield::TrackHeed::SetParticleUser ( const double  m,
const double  z 
)

Definition at line 875 of file TrackHeed.cc.

875 {
876
877 if (fabs(z) < Small) {
878 std::cerr << m_className << "::SetParticleUser:\n"
879 << " Particle cannot have zero charge.\n";
880 return;
881 }
882 if (m < Small) {
883 std::cerr << m_className << "::SetParticleUser:\n"
884 << " Particle mass must be greater than zero.\n";
885 }
886 m_q = z;
887 m_mass = m;
888 m_isElectron = false;
889 m_spin = 0;
890 m_particleName = "exotic";
891}
bool m_isElectron
Definition: Track.hh:87

◆ TransportDeltaElectron() [1/2]

void Garfield::TrackHeed::TransportDeltaElectron ( const double  x0,
const double  y0,
const double  z0,
const double  t0,
const double  e0,
const double  dx0,
const double  dy0,
const double  dz0,
int &  nel 
)

Definition at line 526 of file TrackHeed.cc.

530 {
531 int ni = 0;
532 return TransportDeltaElectron(x0, y0, z0, t0, e0, dx0, dy0, dz0, nel, ni);
533}
void TransportDeltaElectron(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &nel, int &ni)
Definition: TrackHeed.cc:535

◆ TransportDeltaElectron() [2/2]

void Garfield::TrackHeed::TransportDeltaElectron ( const double  x0,
const double  y0,
const double  z0,
const double  t0,
const double  e0,
const double  dx0,
const double  dy0,
const double  dz0,
int &  nel,
int &  ni 
)

Definition at line 535 of file TrackHeed.cc.

539 {
540
541 nel = 0;
542 ni = 0;
543
544 // Check if delta electron transport was disabled.
545 if (!m_doDeltaTransport) {
546 std::cerr << m_className << "::TransportDeltaElectron:\n"
547 << " Delta electron transport has been switched off.\n";
548 return;
549 }
550
551
552 // Make sure the sensor has been set.
553 if (!m_sensor) {
554 std::cerr << m_className << "::TransportDeltaElectron:\n"
555 << " Sensor is not defined.\n";
556 m_ready = false;
557 return;
558 }
559
560 // Get the bounding box.
561 double xmin, ymin, zmin;
562 double xmax, ymax, zmax;
563 if (!m_sensor->GetArea(xmin, ymin, zmin, xmax, ymax, zmax)) {
564 std::cerr << m_className << "::TransportDeltaElectron:\n"
565 << " Drift area is not set.\n";
566 m_ready = false;
567 return;
568 }
569 // Check if the bounding box has changed.
570 bool update = false;
571 const double lx = fabs(xmax - xmin);
572 const double ly = fabs(ymax - ymin);
573 const double lz = fabs(zmax - zmin);
574 if (fabs(lx - m_lX) > Small || fabs(ly - m_lY) > Small || fabs(lz - m_lZ) > Small) {
575 m_lX = lx;
576 m_lY = ly;
577 m_lZ = lz;
578 m_isChanged = true;
579 update = true;
580 m_hasActiveTrack = false;
581 }
582 // Update the center of the bounding box.
583 m_cX = 0.5 * (xmin + xmax);
584 m_cY = 0.5 * (ymin + ymax);
585 m_cZ = 0.5 * (zmin + zmax);
586
587 m_fieldMap.SetSensor(m_sensor);
588 m_fieldMap.SetCentre(m_cX, m_cY, m_cZ);
589
590 // Make sure the initial position is inside an ionisable medium.
591 Medium* medium = NULL;
592 if (!m_sensor->GetMedium(x0, y0, z0, medium)) {
593 std::cerr << m_className << "::TransportDeltaElectron:\n"
594 << " No medium at initial position.\n";
595 return;
596 } else if (!medium->IsIonisable()) {
597 std::cerr << "TrackHeed:TransportDeltaElectron:\n"
598 << " Medium at initial position is not ionisable.\n";
599 m_ready = false;
600 return;
601 }
602
603 // Check if the medium has changed since the last call.
604 if (medium->GetName() != m_mediumName ||
605 fabs(medium->GetMassDensity() - m_mediumDensity) > 1.e-9) {
606 m_isChanged = true;
607 update = true;
608 m_ready = false;
609 m_hasActiveTrack = false;
610 }
611
612 // If medium or bounding box have changed, update the "chamber".
613 if (update) {
614 if (!Setup(medium)) return;
615 m_ready = true;
616 m_mediumName = medium->GetName();
617 m_mediumDensity = medium->GetMassDensity();
618 }
619
620 m_deltaElectrons.clear();
621 m_conductionElectrons.clear();
622 m_conductionIons.clear();
623
624 // Initial position (shift with respect to bounding box center and
625 // convert from cm to mm).
626 Heed::point p0((x0 - m_cX) * 10., (y0 - m_cY) * 10., (z0 - m_cZ) * 10.);
627
628 // Make sure the kinetic energy is positive.
629 if (e0 <= 0.) {
630 // Just create a conduction electron on the spot.
631 m_conductionElectrons.push_back(Heed::HeedCondElectron(p0, t0));
632 nel = 1;
633 return;
634 }
635
636 // Check the direction vector.
637 double dx = dx0, dy = dy0, dz = dz0;
638 const double d = sqrt(dx * dx + dy * dy + dz * dz);
639 if (d <= 0.) {
640 // Null vector. Sample the direction isotropically.
641 RndmDirection(dx, dy, dz);
642 } else {
643 // Normalise the direction vector.
644 dx /= d;
645 dy /= d;
646 dz /= d;
647 }
648 Heed::vec velocity(dx, dy, dz);
649
650 // Calculate the speed for the given kinetic energy.
651 const double gamma = 1. + e0 / ElectronMass;
652 const double beta = sqrt(1. - 1. / (gamma * gamma));
653 double speed = Heed::CLHEP::c_light * beta;
654 velocity = velocity * speed;
655
656 // Transport the electron.
657 std::vector<Heed::gparticle*> secondaries;
658 Heed::HeedDeltaElectron delta(m_chamber, p0, velocity, t0, 0, &m_fieldMap);
659 delta.fly(secondaries);
660 ClearBank(secondaries);
661
662 m_conductionElectrons.swap(delta.conduction_electrons);
663 m_conductionIons.swap(delta.conduction_ions);
664 nel = m_conductionElectrons.size();
665 ni = m_conductionIons.size();
666}

Referenced by GarfieldPhysics::DoIt(), and TransportDeltaElectron().

◆ TransportPhoton() [1/2]

void Garfield::TrackHeed::TransportPhoton ( const double  x0,
const double  y0,
const double  z0,
const double  t0,
const double  e0,
const double  dx0,
const double  dy0,
const double  dz0,
int &  nel 
)

Definition at line 668 of file TrackHeed.cc.

671 {
672 int ni = 0;
673 TransportPhoton(x0, y0, z0, t0, e0, dx0, dy0, dz0, nel, ni);
674}
void TransportPhoton(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &nel, int &ni)
Definition: TrackHeed.cc:676

◆ TransportPhoton() [2/2]

void Garfield::TrackHeed::TransportPhoton ( const double  x0,
const double  y0,
const double  z0,
const double  t0,
const double  e0,
const double  dx0,
const double  dy0,
const double  dz0,
int &  nel,
int &  ni 
)

Definition at line 676 of file TrackHeed.cc.

680 {
681
682 nel = 0;
683 ni = 0;
684
685 // Make sure the energy is positive.
686 if (e0 <= 0.) {
687 std::cerr << m_className << "::TransportPhoton:\n"
688 << " Photon energy must be positive.\n";
689 return;
690 }
691
692 // Make sure the sensor has been set.
693 if (!m_sensor) {
694 std::cerr << m_className << "::TransportPhoton:\n"
695 << " Sensor is not defined.\n";
696 m_ready = false;
697 return;
698 }
699
700 // Get the bounding box.
701 double xmin, ymin, zmin;
702 double xmax, ymax, zmax;
703 if (!m_sensor->GetArea(xmin, ymin, zmin, xmax, ymax, zmax)) {
704 std::cerr << m_className << "::TransportPhoton:\n"
705 << " Drift area is not set.\n";
706 m_ready = false;
707 return;
708 }
709 // Check if the bounding box has changed.
710 bool update = false;
711 const double lx = fabs(xmax - xmin);
712 const double ly = fabs(ymax - ymin);
713 const double lz = fabs(zmax - zmin);
714 if (fabs(lx - m_lX) > Small || fabs(ly - m_lY) > Small || fabs(lz - m_lZ) > Small) {
715 m_lX = lx;
716 m_lY = ly;
717 m_lZ = lz;
718 m_isChanged = true;
719 update = true;
720 m_hasActiveTrack = false;
721 }
722 // Update the center of the bounding box.
723 m_cX = 0.5 * (xmin + xmax);
724 m_cY = 0.5 * (ymin + ymax);
725 m_cZ = 0.5 * (zmin + zmax);
726
727 m_fieldMap.SetSensor(m_sensor);
728 m_fieldMap.SetCentre(m_cX, m_cY, m_cZ);
729
730 // Make sure the initial position is inside an ionisable medium.
731 Medium* medium = NULL;
732 if (!m_sensor->GetMedium(x0, y0, z0, medium)) {
733 std::cerr << m_className << "::TransportPhoton:\n"
734 << " No medium at initial position.\n";
735 return;
736 } else if (!medium->IsIonisable()) {
737 std::cerr << "TrackHeed:TransportPhoton:\n"
738 << " Medium at initial position is not ionisable.\n";
739 m_ready = false;
740 return;
741 }
742
743 // Check if the medium has changed since the last call.
744 if (medium->GetName() != m_mediumName ||
745 fabs(medium->GetMassDensity() - m_mediumDensity) > 1.e-9) {
746 m_isChanged = true;
747 update = true;
748 m_ready = false;
749 }
750
751 // If medium or bounding box have changed, update the "chamber".
752 if (update) {
753 if (!Setup(medium)) return;
754 m_ready = true;
755 m_mediumName = medium->GetName();
756 m_mediumDensity = medium->GetMassDensity();
757 }
758
759 // Delete the particle bank.
760 // Clusters from the current track will be lost.
761 m_hasActiveTrack = false;
762 ClearParticleBank();
763 m_deltaElectrons.clear();
764 m_conductionElectrons.clear();
765 m_conductionIons.clear();
766
767 // Check the direction vector.
768 double dx = dx0, dy = dy0, dz = dz0;
769 const double d = sqrt(dx * dx + dy * dy + dz * dz);
770 if (d <= 0.) {
771 // Null vector. Sample the direction isotropically.
772 RndmDirection(dx, dy, dz);
773 } else {
774 // Normalise the direction vector.
775 dx /= d;
776 dy /= d;
777 dz /= d;
778 }
779 Heed::vec velocity(dx, dy, dz);
780 velocity = velocity * Heed::CLHEP::c_light;
781
782 // Initial position (shift with respect to bounding box center and
783 // convert from cm to mm).
784 Heed::point p0((x0 - m_cX) * 10., (y0 - m_cY) * 10., (z0 - m_cZ) * 10.);
785
786 // Create and transport the photon.
787 Heed::HeedPhoton photon(m_chamber, p0, velocity, t0, 0, e0 * 1.e-6,
788 &m_fieldMap);
789 ClearParticleBank();
790 std::vector<Heed::gparticle*> secondaries;
791 photon.fly(secondaries);
792
793 while (!secondaries.empty()) {
794 std::vector<Heed::gparticle*> newSecondaries;
795 // Loop over the particle bank and look for daughter particles.
796 std::vector<Heed::gparticle*>::iterator it;
797 for (it = secondaries.begin(); it != secondaries.end(); ++it) {
798 // Check if it is a delta electron.
799 Heed::HeedDeltaElectron* delta = dynamic_cast<Heed::HeedDeltaElectron*>(*it);
800 if (delta) {
801 if (m_doDeltaTransport) {
802 // Transport the delta electron.
803 delta->fly(newSecondaries);
804 // Add the conduction electrons to the list.
805 m_conductionElectrons.insert(m_conductionElectrons.end(),
806 delta->conduction_electrons.begin(),
807 delta->conduction_electrons.end());
808 m_conductionIons.insert(m_conductionIons.end(),
809 delta->conduction_ions.begin(),
810 delta->conduction_ions.end());
811 } else {
812 // Add the delta electron to the list, for later use.
813 deltaElectron newDeltaElectron;
814 newDeltaElectron.x = delta->currpos.pt.v.x * 0.1 + m_cX;
815 newDeltaElectron.y = delta->currpos.pt.v.y * 0.1 + m_cY;
816 newDeltaElectron.z = delta->currpos.pt.v.z * 0.1 + m_cZ;
817 newDeltaElectron.t = delta->currpos.time;
818 newDeltaElectron.e = delta->curr_kin_energy * 1.e6;
819 newDeltaElectron.dx = delta->currpos.dir.x;
820 newDeltaElectron.dy = delta->currpos.dir.y;
821 newDeltaElectron.dz = delta->currpos.dir.z;
822 m_deltaElectrons.push_back(newDeltaElectron);
823 }
824 continue;
825 }
826 // Check if it is a fluorescence photon.
827 Heed::HeedPhoton* fluorescencePhoton = dynamic_cast<Heed::HeedPhoton*>(*it);
828 if (!fluorescencePhoton) {
829 std::cerr << m_className << "::TransportPhoton:\n"
830 << " Unknown secondary particle.\n";
831 ClearBank(secondaries);
832 ClearBank(newSecondaries);
833 return;
834 }
835 fluorescencePhoton->fly(newSecondaries);
836 }
837 secondaries.swap(newSecondaries);
838 ClearBank(newSecondaries);
839 }
840
841 // Get the total number of electrons produced in this step.
842 nel = m_doDeltaTransport ? m_conductionElectrons.size() :
843 m_deltaElectrons.size();
844 ni = m_conductionIons.size();
845}

Referenced by GarfieldPhysics::DoIt(), and TransportPhoton().


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