Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Garfield::TrackSrim Class Reference

#include <TrackSrim.hh>

+ Inheritance diagram for Garfield::TrackSrim:

Classes

struct  Cluster
 

Public Member Functions

 TrackSrim ()
 Default constructor.
 
 TrackSrim (Sensor *sensor)
 Constructor.
 
virtual ~TrackSrim ()
 Destructor.
 
bool ReadFile (const std::string &file)
 Load data from a SRIM file.
 
void Print ()
 Print the energy loss table.
 
void PlotEnergyLoss ()
 
void PlotRange ()
 Plot the projected range as function of the projectile energy.
 
void PlotStraggling ()
 
void SetModel (const int m)
 
int GetModel () const
 Get the fluctuation model.
 
void SetTargetClusterSize (const int n)
 Specify how many electrons should be grouped to a cluster.
 
int GetTargetClusterSize () const
 Retrieve the target cluster size.
 
void SetClustersMaximum (const int n)
 Set the max. number of clusters on a track.
 
int GetClustersMaximum () const
 Retrieve the max. number of clusters on a track.
 
void SetWorkFunction (const double w)
 Set the W value [eV].
 
double GetWorkFunction () const
 Get the W value [eV].
 
void SetFanoFactor (const double f)
 Set the Fano factor.
 
void UnsetFanoFactor ()
 Use the default Fano factor.
 
double GetFanoFactor () const
 Get the Fano factor.
 
void SetDensity (const double density)
 Set the density [g/cm3] of the target medium.
 
double GetDensity () const
 Get the density [g/cm3] of the target medium.
 
void SetAtomicMassNumbers (const double a, const double z)
 Set A and Z of the target medium.
 
void GetAtomicMassMumbers (double &a, double &z) const
 Get A and Z of the target medium.
 
void EnableTransverseStraggling (const bool on=true)
 Simulate transverse straggling (default: on).
 
void EnableLongitudinalStraggling (const bool on=true)
 Simulate longitudinal straggling (default: off).
 
bool NewTrack (const double x0, const double y0, const double z0, const double t0, const double dx0, const double dy0, const double dz0) override
 
bool GetCluster (double &xc, double &yc, double &zc, double &tc, int &nc, double &ec, double &extra) override
 
const std::vector< Cluster > & GetClusters () const
 
- Public Member Functions inherited from Garfield::Track
 Track ()=delete
 Default constructor.
 
 Track (const std::string &name)
 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 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.
 

Protected Member Functions

double Xi (const double x, const double beta2, const double edens) const
 
double DedxEM (const double e) const
 
double DedxHD (const double e) const
 
bool PreciseLoss (const double step, const double estart, double &deem, double &dehd) const
 
bool EstimateRange (const double ekin, const double step, double &stpmax) const
 
bool SmallestStep (const double ekin, const double edens, double de, double step, double &stpmin)
 
MediumGetMedium (const std::array< double, 3 > &x) const
 
double Terminate (const std::array< double, 3 > &x0, const std::array< double, 3 > &v0, const double step0) const
 
double TerminateBfield (const std::array< double, 3 > &x0, const std::array< double, 3 > &v0, const double dt0, const double vmag) const
 
double RndmEnergyLoss (const double ekin, const double de, const double step, const double edens) const
 
- 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

bool m_useTransStraggle = true
 Include transverse straggling.
 
bool m_useLongStraggle = false
 Include longitudinal straggling.
 
bool m_chargeset = false
 Has the charge been defined?
 
double m_qion = 1.
 Charge of the projectile.
 
double m_mion = -1.
 Mass [MeV] of the projectile.
 
double m_rho = -1.
 Mass density [g/cm3] of the target.
 
double m_work = -1.
 Work function [eV] of the target.
 
bool m_fset = false
 Has the Fano factor been set?
 
double m_fano = -1.
 Fano factor [-] of the target.
 
double m_a = -1.
 Effective A of the target.
 
double m_z = -1.
 Effective Z of the target.
 
int m_maxclusters = -1
 Maximum number of clusters allowed (infinite if 0)
 
std::vector< double > m_ekin
 Energy in energy loss table [MeV].
 
std::vector< double > m_emloss
 EM energy loss [MeV cm2/g].
 
std::vector< double > m_hdloss
 Hadronic energy loss [MeV cm2/g].
 
std::vector< double > m_range
 Projected range [cm].
 
std::vector< double > m_transstraggle
 Transverse straggling [cm].
 
std::vector< double > m_longstraggle
 Longitudinal straggling [cm].
 
size_t m_currcluster = 0
 Index of the next cluster to be returned.
 
unsigned int m_model = 4
 
int m_nsize = -1
 Targeted cluster size.
 
std::vector< Clusterm_clusters
 
- 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 = 1.
 
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
 

Additional Inherited Members

- Static Protected Member Functions inherited from Garfield::Track
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)
 

Detailed Description

Generate tracks based on SRIM energy loss, range and straggling tables.

Definition at line 11 of file TrackSrim.hh.

Constructor & Destructor Documentation

◆ TrackSrim() [1/2]

Garfield::TrackSrim::TrackSrim ( )
inline

Default constructor.

Definition at line 14 of file TrackSrim.hh.

14: TrackSrim(nullptr) {}
TrackSrim()
Default constructor.
Definition TrackSrim.hh:14

Referenced by TrackSrim().

◆ TrackSrim() [2/2]

Garfield::TrackSrim::TrackSrim ( Sensor * sensor)

Constructor.

Definition at line 75 of file TrackSrim.cc.

75 : Track("Srim") {
76 m_sensor = sensor;
77}
Sensor * m_sensor
Definition Track.hh:114
Track()=delete
Default constructor.

◆ ~TrackSrim()

virtual Garfield::TrackSrim::~TrackSrim ( )
inlinevirtual

Destructor.

Definition at line 18 of file TrackSrim.hh.

18{}

Member Function Documentation

◆ DedxEM()

double Garfield::TrackSrim::DedxEM ( const double e) const
protected

Definition at line 443 of file TrackSrim.cc.

443 {
444 return Interpolate(e, m_ekin, m_emloss);
445}
std::vector< double > m_emloss
EM energy loss [MeV cm2/g].
Definition TrackSrim.hh:131
std::vector< double > m_ekin
Energy in energy loss table [MeV].
Definition TrackSrim.hh:129

Referenced by NewTrack(), and PreciseLoss().

◆ DedxHD()

double Garfield::TrackSrim::DedxHD ( const double e) const
protected

Definition at line 447 of file TrackSrim.cc.

447 {
448 return Interpolate(e, m_ekin, m_hdloss);
449}
std::vector< double > m_hdloss
Hadronic energy loss [MeV cm2/g].
Definition TrackSrim.hh:133

Referenced by NewTrack(), and PreciseLoss().

◆ EnableLongitudinalStraggling()

void Garfield::TrackSrim::EnableLongitudinalStraggling ( const bool on = true)
inline

Simulate longitudinal straggling (default: off).

Definition at line 83 of file TrackSrim.hh.

83 {
85 }
bool m_useLongStraggle
Include longitudinal straggling.
Definition TrackSrim.hh:105

◆ EnableTransverseStraggling()

void Garfield::TrackSrim::EnableTransverseStraggling ( const bool on = true)
inline

Simulate transverse straggling (default: on).

Definition at line 79 of file TrackSrim.hh.

79 {
81 }
bool m_useTransStraggle
Include transverse straggling.
Definition TrackSrim.hh:103

◆ EstimateRange()

bool Garfield::TrackSrim::EstimateRange ( const double ekin,
const double step,
double & stpmax ) const
protected

Definition at line 534 of file TrackSrim.cc.

535 {
536 // Find distance over which the ion just does not lose all its energy
537 // ekin : Kinetic energy [MeV]
538 // step : Step length as guessed [cm]
539 // stpmax : Maximum step
540 // SRMDEZ
541
542 const std::string hdr = m_className + "::EstimateRange: ";
543 // Initial estimate
544 stpmax = step;
545
546 // Find the energy loss expected for the present step length.
547 double st1 = step;
548 double deem = 0., dehd = 0.;
549 PreciseLoss(st1, ekin, deem, dehd);
550 double de1 = deem + dehd;
551 // Do nothing if this is ok
552 if (de1 < ekin) {
553 if (m_debug) std::cout << " Initial step OK.\n";
554 return true;
555 }
556 // Find a smaller step for which the energy loss is less than EKIN.
557 double st2 = 0.5 * step;
558 double de2 = de1;
559 const unsigned int nMaxIter = 20;
560 for (unsigned int iter = 0; iter < nMaxIter; ++iter) {
561 // See where we stand
562 PreciseLoss(st2, ekin, deem, dehd);
563 de2 = deem + dehd;
564 // Below the kinetic energy: done
565 if (de2 < ekin) break;
566 // Not yet below the kinetic energy: new iteration.
567 st1 = st2;
568 de1 = de2;
569 st2 *= 0.5;
570 }
571 if (de2 >= ekin) {
572 std::cerr << hdr << "\n Did not find a smaller step in " << nMaxIter
573 << " iterations. Abandoned.\n";
574 stpmax = 0.5 * (st1 + st2);
575 return false;
576 }
577 if (m_debug) {
578 printf(" Step 1 = %g cm, dE 1 = %g MeV\n", st1, de1 - ekin);
579 printf(" Step 2 = %g cm, dE 2 = %g MeV\n", st2, de2 - ekin);
580 }
581 // Now perform a bisection
582 for (unsigned int iter = 0; iter < nMaxIter; ++iter) {
583 // Avoid division by zero.
584 if (de2 == de1) {
585 if (m_debug) {
586 std::cerr << " Bisection failed due to equal energy loss for "
587 << "two step sizes. Abandoned.\n";
588 }
589 stpmax = 0.5 * (st1 + st2);
590 return false;
591 }
592 // Estimate step to give total energy loss.
593 double st3;
594 if ((fabs(de1 - ekin) < 0.01 * fabs(de2 - de1)) ||
595 (fabs(de1 - ekin) > 0.99 * fabs(de2 - de1))) {
596 st3 = 0.5 * (st1 + st2);
597 } else {
598 st3 = st1 - (st2 - st1) * (de1 - ekin) / (de2 - de1);
599 }
600 // See how well we are doing.
601 PreciseLoss(st3, ekin, deem, dehd);
602 const double de3 = deem + dehd;
603 if (m_debug) {
604 std::printf(" Step 1 = %g cm, dE 1 = %g MeV\n", st1, de1 - ekin);
605 std::printf(" Step 2 = %g cm, dE 2 = %g MeV\n", st2, de2 - ekin);
606 std::printf(" Step 3 = %g cm, dE 3 = %g MeV\n", st3, de3 - ekin);
607 }
608 // Update the estimates above and below.
609 if (de3 > ekin) {
610 st1 = st3;
611 de1 = de3;
612 } else {
613 st2 = st3;
614 de2 = de3;
615 }
616 // See whether we've converged.
617 if (fabs(de3 - ekin) < 1e-3 * (fabs(de3) + fabs(ekin)) ||
618 fabs(st1 - st2) < 1e-3 * (fabs(st1) + fabs(st2))) {
619 stpmax = st1 - (st2 - st1) * (de1 - ekin) / (de2 - de1);
620 return true;
621 }
622 }
623 if (m_debug) {
624 std::cout << " Bisection did not converge in " << nMaxIter
625 << " steps. Abandoned.\n";
626 }
627 stpmax = st1 - (st2 - st1) * (de1 - ekin) / (de2 - de1);
628 return false;
629}
bool PreciseLoss(const double step, const double estart, double &deem, double &dehd) const
Definition TrackSrim.cc:460
std::string m_className
Definition Track.hh:104
DoubleAc fabs(const DoubleAc &f)
Definition DoubleAc.h:615

Referenced by NewTrack().

◆ GetAtomicMassMumbers()

void Garfield::TrackSrim::GetAtomicMassMumbers ( double & a,
double & z ) const
inline

Get A and Z of the target medium.

Definition at line 73 of file TrackSrim.hh.

73 {
74 a = m_a;
75 z = m_z;
76 }
double m_z
Effective Z of the target.
Definition TrackSrim.hh:124
double m_a
Effective A of the target.
Definition TrackSrim.hh:122

◆ GetCluster()

bool Garfield::TrackSrim::GetCluster ( double & xc,
double & yc,
double & zc,
double & tc,
int & nc,
double & ec,
double & extra )
overridevirtual

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

Parameters
xc,yc,zccoordinates of the collision
tctime of the collision
ncnumber of electrons produced
ecdeposited energy
extraadditional information (not always implemented)

Implements Garfield::Track.

Definition at line 1328 of file TrackSrim.cc.

1329 {
1330 if (m_debug) {
1331 std::cout << m_className << "::GetCluster: Cluster " << m_currcluster
1332 << " of " << m_clusters.size() << "\n";
1333 }
1334 // Stop if we have exhausted the list of clusters.
1335 if (m_currcluster >= m_clusters.size()) return false;
1336
1337 const auto& cluster = m_clusters[m_currcluster];
1338 xcls = cluster.x;
1339 ycls = cluster.y;
1340 zcls = cluster.z;
1341 tcls = cluster.t;
1342
1343 n = cluster.n;
1344 e = cluster.energy;
1345 extra = cluster.kinetic;
1346 // Move to next cluster
1347 ++m_currcluster;
1348 return true;
1349}
std::vector< Cluster > m_clusters
Definition TrackSrim.hh:148
size_t m_currcluster
Index of the next cluster to be returned.
Definition TrackSrim.hh:142

◆ GetClusters()

const std::vector< Cluster > & Garfield::TrackSrim::GetClusters ( ) const
inline

Definition at line 99 of file TrackSrim.hh.

99{ return m_clusters; }

◆ GetClustersMaximum()

int Garfield::TrackSrim::GetClustersMaximum ( ) const
inline

Retrieve the max. number of clusters on a track.

Definition at line 48 of file TrackSrim.hh.

48{ return m_maxclusters; }
int m_maxclusters
Maximum number of clusters allowed (infinite if 0)
Definition TrackSrim.hh:127

◆ GetDensity()

double Garfield::TrackSrim::GetDensity ( ) const
inline

Get the density [g/cm3] of the target medium.

Definition at line 66 of file TrackSrim.hh.

66{ return m_rho; }
double m_rho
Mass density [g/cm3] of the target.
Definition TrackSrim.hh:114

◆ GetFanoFactor()

double Garfield::TrackSrim::GetFanoFactor ( ) const
inline

Get the Fano factor.

Definition at line 62 of file TrackSrim.hh.

62{ return m_fano; }
double m_fano
Fano factor [-] of the target.
Definition TrackSrim.hh:120

◆ GetMedium()

Medium * Garfield::TrackSrim::GetMedium ( const std::array< double, 3 > & x) const
protected

Definition at line 631 of file TrackSrim.cc.

631 {
632 Medium* medium = m_sensor->GetMedium(x[0], x[1], x[2]);
633 if (medium && medium->IsIonisable() && m_sensor->IsInArea(x[0], x[1], x[2])) {
634 return medium;
635 }
636 return nullptr;
637}

Referenced by NewTrack(), Terminate(), and TerminateBfield().

◆ GetModel()

int Garfield::TrackSrim::GetModel ( ) const
inline

Get the fluctuation model.

Definition at line 38 of file TrackSrim.hh.

38{ return m_model; }
unsigned int m_model
Definition TrackSrim.hh:145

◆ GetTargetClusterSize()

int Garfield::TrackSrim::GetTargetClusterSize ( ) const
inline

Retrieve the target cluster size.

Definition at line 43 of file TrackSrim.hh.

43{ return m_nsize; }
int m_nsize
Targeted cluster size.
Definition TrackSrim.hh:147

◆ GetWorkFunction()

double Garfield::TrackSrim::GetWorkFunction ( ) const
inline

Get the W value [eV].

Definition at line 53 of file TrackSrim.hh.

53{ return m_work; }
double m_work
Work function [eV] of the target.
Definition TrackSrim.hh:116

◆ NewTrack()

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

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

Implements Garfield::Track.

Definition at line 639 of file TrackSrim.cc.

641 {
642 // Generates electrons for a SRIM track
643 // SRMGEN
644 const std::string hdr = m_className + "::NewTrack: ";
645
646 // Verify that a sensor has been set.
647 if (!m_sensor) {
648 std::cerr << hdr << "Sensor is not defined.\n";
649 return false;
650 }
651
652 // Make sure the initial position is inside an ionisable medium.
653 Medium* medium = GetMedium({x0, y0, z0});
654 if (!medium) {
655 std::cerr << hdr << "No valid medium at initial position.\n";
656 return false;
657 }
658 // Get the W value of the medium (unless it has been set explicitly
659 // by the user).
660 double w = m_work < Small ? medium->GetW() : m_work;
661 if (w < Small) {
662 std::cerr << hdr << "Work function not defined.\n";
663 return false;
664 }
665 // Get the Fano factor
666 double fano = m_fset ? m_fano : medium->GetFanoFactor();
667 fano = std::max(fano, 0.);
668
669 // Compute the electron (number) density of the target.
670 double edens = 0.;
671 if (m_a > 0. && m_z > 0. && m_rho > 0.) {
672 edens = m_z * m_rho / (AtomicMassUnit * m_a);
673 } else {
674 edens = medium->GetNumberDensity() * medium->GetAtomicNumber();
675 if (m_rho > 0.) {
676 edens *= m_rho / medium->GetMassDensity();
677 }
678 }
679 if (edens < Small) {
680 std::cerr << hdr << "Invalid target density.\n";
681 return false;
682 }
683
684 // Normalise and store the direction.
685 const double normdir = sqrt(dx0 * dx0 + dy0 * dy0 + dz0 * dz0);
686 std::array<double, 3> v = {dx0, dy0, dz0};
687 if (normdir < Small) {
688 if (m_debug) {
689 std::cout << hdr << "Direction vector has zero norm.\n"
690 << " Initial direction is randomized.\n";
691 }
692 // Null vector. Sample the direction isotropically.
693 RndmDirection(v[0], v[1], v[2]);
694 } else {
695 // Normalise the direction vector.
696 v[0] /= normdir;
697 v[1] /= normdir;
698 v[2] /= normdir;
699 }
700
701 // Make sure all necessary parameters have been set.
702 if (m_mion < Small) {
703 std::cerr << hdr << "Particle mass not set.\n";
704 return false;
705 } else if (!m_chargeset) {
706 std::cerr << hdr << "Particle charge not set.\n";
707 return false;
708 } else if (m_energy < Small) {
709 std::cerr << hdr << "Initial particle energy not set.\n";
710 return false;
711 }
712
713 // Check the initial energy (in MeV).
714 const double ekin0 = 1.e-6 * GetKineticEnergy();
715 if (ekin0 < 1.e-14 * m_mion || ekin0 < 1.e-6 * w) {
716 std::cerr << hdr << "Initial kinetic energy E = " << ekin0
717 << " MeV such that beta2 = 0 or E << W; particle stopped.\n";
718 return true;
719 }
720
721 // Get an upper limit for the track length.
722 const double tracklength = 10 * Interpolate(ekin0, m_ekin, m_range);
723
724 // Header of debugging output.
725 if (m_debug) {
726 std::cout << hdr << "Track generation with the following parameters:\n";
727 const unsigned int nTable = m_ekin.size();
728 printf(" Table size %u\n", nTable);
729 printf(" Particle kin. energy %g MeV\n", ekin0);
730 printf(" Particle mass %g MeV\n", 1.e-6 * m_mion);
731 printf(" Particle charge %g\n", m_qion);
732 printf(" Work function %g eV\n", w);
733 printf(" Fano factor %g\n", fano);
734 printf(" Long. straggling: %d\n", m_useLongStraggle);
735 printf(" Trans. straggling: %d\n", m_useTransStraggle);
736 printf(" Cluster size %d\n", m_nsize);
737 }
738
739 // Plot.
740 if (m_viewer) PlotNewTrack(x0, y0, z0);
741
742 // Reset the cluster count.
743 m_currcluster = 0;
744 m_clusters.clear();
745
746 // Initial situation: starting position
747 std::array<double, 3> x = {x0, y0, z0};
748 double t = t0;
749 // Store the energy [MeV].
750 double ekin = ekin0;
751 // Total distance covered
752 double dsum = 0.0;
753 // Pool of unused energy
754 double epool = 0.0;
755
756 // Loop generating clusters
757 int iter = 0;
758 while (iter < m_maxclusters || m_maxclusters < 0) {
759 if (m_debug) printf(" Iteration %d. Ekin = %g MeV.\n", iter, ekin);
760 // Work out the energy loss per cm at the start of the step.
761 const double dedxem = DedxEM(ekin) * m_rho;
762 const double dedxhd = DedxHD(ekin) * m_rho;
763 // Find the step size for which we get approximately the
764 // requested number of clusters or cluster size.
765 double step = 0.;
766 double eloss = 0.;
767 if (m_nsize > 0) {
768 step = m_nsize * 1.e-6 * w / dedxem;
769 } else {
770 const double ncls = m_maxclusters > 0 ? 0.5 * m_maxclusters : 100;
771 step = ekin0 / (ncls * (dedxem + dedxhd));
772 }
773 if (m_debug) printf(" Estimated step size: %g cm\n", step);
774 bool finish = false;
775 // Truncate if this step exceeds the length.
776 if (dsum + step > tracklength) {
777 step = tracklength - dsum;
778 if (m_debug) printf(" Truncating step to %g cm.\n", step);
779 finish = true;
780 }
781 // Make an accurate integration of the energy loss over the step.
782 double deem = 0., dehd = 0.;
783 PreciseLoss(step, ekin, deem, dehd);
784 double stpmax = tracklength - dsum;
785 // If the energy loss exceeds the particle energy, truncate the step.
786 if (deem + dehd > ekin) {
787 EstimateRange(ekin, step, stpmax);
788 step = stpmax;
789 PreciseLoss(step, ekin, deem, dehd);
790 deem = ekin * deem / (dehd + deem);
791 dehd = ekin - deem;
792 finish = true;
793 if (m_debug) std::cout << " Track length reached.\n";
794 }
795 if (m_debug) {
796 std::cout << " Maximum step size set to " << stpmax << " cm.\n";
797 }
798 // Ensure that this is larger than the minimum modelable step size.
799 double stpmin;
800 if (!SmallestStep(ekin, edens, deem, step, stpmin)) {
801 std::cerr << hdr << "Failure computing the minimum step size.\n"
802 << " Clustering abandoned.\n";
803 return false;
804 }
805 if (stpmin > stpmax) {
806 // No way to find a suitable step size: use fixed energy loss.
807 if (m_debug) {
808 std::cout << " Min. step > max. step; depositing all energy.\n";
809 }
810 if (deem + dehd > ekin) {
811 eloss = ekin - dehd;
812 } else {
813 eloss = deem;
814 }
815 finish = true;
816 } else if (step < stpmin) {
817 // If needed enlarge the step size.
818 if (m_debug) std::cout << " Enlarging step size.\n";
819 step = stpmin;
820 PreciseLoss(step, ekin, deem, dehd);
821 if (deem + dehd > ekin) {
822 if (m_debug) std::cout << " Excess loss. Recomputing max. step.\n";
823 EstimateRange(ekin, step, stpmax);
824 step = stpmax;
825 PreciseLoss(step, ekin, deem, dehd);
826 deem = ekin * deem / (dehd + deem);
827 dehd = ekin - deem;
828 eloss = deem;
829 } else {
830 eloss = RndmEnergyLoss(ekin, deem, step, edens);
831 }
832 } else {
833 // Draw an actual energy loss for such a step.
834 if (m_debug) std::cout << " Step size ok.\n";
835 eloss = RndmEnergyLoss(ekin, deem, step, edens);
836 }
837 // Ensure we are neither below 0 nor above the total energy.
838 if (eloss < 0) {
839 if (m_debug) std::cout << " Truncating negative energy loss.\n";
840 eloss = 0;
841 } else if (eloss > ekin - dehd) {
842 if (m_debug) std::cout << " Excess energy loss, using mean.\n";
843 if (deem + dehd > ekin) {
844 eloss = ekin - dehd;
845 finish = true;
846 } else {
847 eloss = deem;
848 }
849 }
850 if (m_debug) {
851 std::cout << " Step length = " << step << " cm.\n"
852 << " Mean loss = " << deem << " MeV.\n"
853 << " Actual loss = " << eloss << " MeV.\n";
854 }
855 // Get the particle velocity.
856 const double rk = 1.e6 * ekin / m_mion;
857 const double gamma = 1. + rk;
858 const double beta2 = rk > 1.e-5 ? 1. - 1. / (gamma * gamma) : 2. * rk;
859 const double vmag = sqrt(beta2) * SpeedOfLight;
860 // Compute the timestep.
861 const double dt = vmag > 0. ? step / vmag : 0.;
862 // Compute the endpoint of this step.
863 std::array<double, 3> x1 = x;
864 std::array<double, 3> v1 = v;
865 if (m_sensor->HasMagneticField()) {
866 double bx = 0., by = 0., bz = 0.;
867 int status = 0;
868 m_sensor->MagneticField(x[0], x[1], x[2], bx, by, bz, status);
869 const double qoverm = m_qion / m_mion;
870 std::array<double, 3> d = StepBfield(dt, qoverm, vmag, bx, by, bz, v1);
871 x1[0] = x[0] + d[0];
872 x1[1] = x[1] + d[1];
873 x1[2] = x[2] + d[2];
874 } else {
875 x1[0] = x[0] + step * v[0];
876 x1[1] = x[1] + step * v[1];
877 x1[2] = x[2] + step * v[2];
878 }
879 // Is the endpoint in an ionisable medium and inside the active area?
880 if (!GetMedium(x1)) {
881 if (!m_sensor->HasMagneticField()) {
882 step = Terminate(x, v, step);
883 } else {
884 step = TerminateBfield(x, v, dt, vmag);
885 }
886 PreciseLoss(step, ekin, deem, dehd);
887 if (deem + dehd > ekin) {
888 if (m_debug) std::cout << " Excess loss.\n";
889 deem = ekin * deem / (dehd + deem);
890 dehd = ekin - deem;
891 }
892 eloss = RndmEnergyLoss(ekin, deem, step, edens);
893 if (eloss > ekin - dehd) eloss = deem;
894 finish = true;
895 }
896 // Add a cluster.
897 Cluster cluster;
898 cluster.x = x[0];
899 cluster.y = x[1];
900 cluster.z = x[2];
901 cluster.t = t;
902 if (fano < Small) {
903 // No fluctuations.
904 cluster.n = int((eloss + epool) / (1.e-6 * w));
905 cluster.energy = w * cluster.n;
906 } else {
907 double ecl = 1.e6 * (eloss + epool);
908 cluster.n = 0;
909 cluster.energy = 0.0;
910 while (true) {
911 // if (cluster.energy < 100) printf("ec = %g\n", cluster.energy);
912 const double ernd1 = RndmHeedWF(w, fano);
913 if (ernd1 > ecl) break;
914 cluster.n++;
915 cluster.energy += ernd1;
916 ecl -= ernd1;
917 }
918 if (m_debug) {
919 std::cout << " EM + pool: " << 1.e6 * (eloss + epool)
920 << " eV, W: " << w
921 << " eV, E/w: " << (eloss + epool) / (1.e-6 * w)
922 << ", n: " << cluster.n << ".\n";
923 }
924 }
925 cluster.kinetic = ekin;
926 epool += eloss - 1.e-6 * cluster.energy;
927 if (m_debug) {
928 std::cout << " Adding cluster " << m_clusters.size() << " at ("
929 << cluster.x << ", " << cluster.y << ", " << cluster.z
930 << "), e = " << cluster.energy << ", n = " << cluster.n
931 << ".\n"
932 << " Pool = " << epool << " MeV.\n";
933 }
934 m_clusters.push_back(std::move(cluster));
935 if (m_viewer) PlotCluster(x[0], x[1], x[2]);
936
937 // Keep track of the length and energy
938 dsum += step;
939 ekin -= eloss + dehd;
940 if (finish) {
941 // Stop if the flag is raised.
942 if (m_debug) std::cout << " Finishing flag raised.\n";
943 break;
944 } else if (ekin < ekin0 * 1.e-9) {
945 // No energy left.
946 if (m_debug) std::cout << " Energy exhausted.\n";
947 break;
948 }
949 // Update time, position and direction.
950 t += dt;
951 x = x1;
952 v = v1;
953 // Get the projected range and straggling.
954 const double prange = Interpolate(ekin, m_ekin, m_range);
955 const double strlat = m_useTransStraggle ?
956 Interpolate(ekin, m_ekin, m_transstraggle) : 0.;
957 const double strlon = m_useLongStraggle ?
958 Interpolate(ekin, m_ekin, m_longstraggle) : 0.;
959 // Draw scattering distances
960 const double scale = sqrt(step / prange);
961 const double sigt1 = RndmGaussian(0., scale * strlat);
962 const double sigt2 = RndmGaussian(0., scale * strlat);
963 const double sigl = RndmGaussian(0., scale * strlon);
964 if (m_debug) {
965 printf(" Sigma longitudinal: %g cm\n", sigl);
966 printf(" Sigma transverse: %g, %g cm\n", sigt1, sigt2);
967 }
968 // Rotation angles to bring z-axis in line
969 double theta, phi;
970 if (v[0] * v[0] + v[2] * v[2] <= 0) {
971 if (v[1] < 0) {
972 theta = -HalfPi;
973 } else if (v[1] > 0) {
974 theta = +HalfPi;
975 } else {
976 std::cerr << hdr << "Zero step length; clustering abandoned.\n";
977 return false;
978 }
979 phi = 0;
980 } else {
981 phi = atan2(v[0], v[2]);
982 theta = atan2(v[1], sqrt(v[0] * v[0] + v[2] * v[2]));
983 }
984 // Update the position.
985 const double cp = cos(phi);
986 const double ct = cos(theta);
987 const double sp = sin(phi);
988 const double st = sin(theta);
989 x[0] += +cp * sigt1 - sp * st * sigt2 + sp * ct * sigl;
990 x[1] += +ct * sigt2 + st * sigl;
991 x[2] += -sp * sigt1 - cp * st * sigt2 + cp * ct * sigl;
992 medium = GetMedium(x);
993 if (!medium) break;
994 // Update the W value (unless it is set explicitly).
995 if (m_work < Small) w = medium->GetW();
996 if (w < Small) {
997 std::cerr << hdr << "W value in medium " << medium->GetName()
998 << " is not defined.\n";
999 break;
1000 }
1001 // Next cluster
1002 iter++;
1003 }
1004 if (iter == m_maxclusters) {
1005 std::cerr << hdr << "Exceeded maximum number of clusters.\n";
1006 }
1007 return true;
1008 // finished generating
1009}
std::vector< double > m_longstraggle
Longitudinal straggling [cm].
Definition TrackSrim.hh:139
double m_qion
Charge of the projectile.
Definition TrackSrim.hh:110
std::vector< double > m_range
Projected range [cm].
Definition TrackSrim.hh:135
double DedxHD(const double e) const
Definition TrackSrim.cc:447
bool EstimateRange(const double ekin, const double step, double &stpmax) const
Definition TrackSrim.cc:534
bool m_chargeset
Has the charge been defined?
Definition TrackSrim.hh:108
Medium * GetMedium(const std::array< double, 3 > &x) const
Definition TrackSrim.cc:631
double RndmEnergyLoss(const double ekin, const double de, const double step, const double edens) const
double m_mion
Mass [MeV] of the projectile.
Definition TrackSrim.hh:112
std::vector< double > m_transstraggle
Transverse straggling [cm].
Definition TrackSrim.hh:137
double Terminate(const std::array< double, 3 > &x0, const std::array< double, 3 > &v0, const double step0) const
bool m_fset
Has the Fano factor been set?
Definition TrackSrim.hh:118
double DedxEM(const double e) const
Definition TrackSrim.cc:443
bool SmallestStep(const double ekin, const double edens, double de, double step, double &stpmin)
double TerminateBfield(const std::array< double, 3 > &x0, const std::array< double, 3 > &v0, const double dt0, const double vmag) const
double GetKineticEnergy() const
Return the kinetic energy of the projectile.
Definition Track.hh:62
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
ViewDrift * m_viewer
Definition Track.hh:118
void PlotCluster(const double x0, const double y0, const double z0)
Definition Track.cc:195
double m_energy
Definition Track.hh:109
void PlotNewTrack(const double x0, const double y0, const double z0)
Definition Track.cc:190
double RndmHeedWF(const double w, const double f)
Definition Random.cc:699
void RndmDirection(double &dx, double &dy, double &dz, const double length=1.)
Draw a random (isotropic) direction vector.
Definition Random.hh:128
double RndmGaussian()
Draw a Gaussian random variate with mean zero and standard deviation one.
Definition Random.hh:24
DoubleAc cos(const DoubleAc &f)
Definition DoubleAc.cpp:432
DoubleAc sin(const DoubleAc &f)
Definition DoubleAc.cpp:384
DoubleAc sqrt(const DoubleAc &f)
Definition DoubleAc.cpp:314

◆ PlotEnergyLoss()

void Garfield::TrackSrim::PlotEnergyLoss ( )

Plot the electromagnetic, hadronic, and total energy loss as function of the projectile energy.

Definition at line 320 of file TrackSrim.cc.

320 {
321
322 const unsigned int nPoints = m_ekin.size();
323 std::vector<double> yE;
324 std::vector<double> yH;
325 std::vector<double> yT;
326 for (unsigned int i = 0; i < nPoints; ++i) {
327 const double em = m_emloss[i] * m_rho;
328 const double hd = m_hdloss[i] * m_rho;
329 yE.push_back(em);
330 yH.push_back(hd);
331 yT.push_back(em + hd);
332 }
333 const double xmin = *std::min_element(std::begin(m_ekin), std::end(m_ekin));
334 const double xmax = *std::max_element(std::begin(m_ekin), std::end(m_ekin));
335 const double ymax = *std::max_element(std::begin(yT), std::end(yT));
336 // Prepare a plot frame.
337 const std::string name = ViewBase::FindUnusedCanvasName("cSRIM");
338 TCanvas* celoss = new TCanvas(name.c_str(), "Energy loss");
339 celoss->SetLogx();
340 celoss->SetGridx();
341 celoss->SetGridy();
342 celoss->DrawFrame(xmin, 0., xmax, 1.05 * ymax, ";Ion energy [MeV];Energy loss [MeV/cm]");
343
344 // Make a graph for the 3 curves to plot.
345 TGraph gr;
346 gr.SetLineStyle(kSolid);
347 gr.SetLineWidth(2);
348 gr.SetMarkerStyle(21);
349 gr.SetLineColor(kBlue + 1);
350 gr.SetMarkerColor(kBlue + 1);
351 gr.DrawGraph(nPoints, m_ekin.data(), yE.data(), "plsame");
352
353 gr.SetLineColor(kGreen + 2);
354 gr.SetMarkerColor(kGreen + 2);
355 gr.DrawGraph(nPoints, m_ekin.data(), yH.data(), "plsame");
356
357 gr.SetLineColor(kOrange - 3);
358 gr.SetMarkerColor(kOrange - 3);
359 gr.DrawGraph(nPoints, m_ekin.data(), yT.data(), "plsame");
360
361 TLatex label;
362 double xLabel = 0.4 * xmax;
363 double yLabel = 0.9 * ymax;
364 label.SetTextColor(kBlue + 1);
365 label.SetText(xLabel, yLabel, "EM energy loss");
366 label.DrawLatex(xLabel, yLabel, "EM energy loss");
367 yLabel -= 1.5 * label.GetYsize();
368 label.SetTextColor(kGreen + 2);
369 label.DrawLatex(xLabel, yLabel, "HD energy loss");
370 yLabel -= 1.5 * label.GetYsize();
371 label.SetTextColor(kOrange - 3);
372 label.DrawLatex(xLabel, yLabel, "Total energy loss");
373 celoss->Update();
374}
static std::string FindUnusedCanvasName(const std::string &s)
Find an unused canvas name.
Definition ViewBase.cc:337

◆ PlotRange()

void Garfield::TrackSrim::PlotRange ( )

Plot the projected range as function of the projectile energy.

Definition at line 376 of file TrackSrim.cc.

376 {
377
378 const double xmin = *std::min_element(std::begin(m_ekin), std::end(m_ekin));
379 const double xmax = *std::max_element(std::begin(m_ekin), std::end(m_ekin));
380 const double ymax = *std::max_element(std::begin(m_range), std::end(m_range));
381
382 // Prepare a plot frame.
383 const std::string name = ViewBase::FindUnusedCanvasName("cSRIM");
384 TCanvas* crange = new TCanvas(name.c_str(), "Range");
385 crange->SetLogx();
386 crange->SetGridx();
387 crange->SetGridy();
388 crange->DrawFrame(xmin, 0., xmax, 1.05 * ymax, ";Ion energy [MeV];Projected range [cm]");
389 // Make a graph.
390 TGraph gr;
391 gr.SetLineColor(kOrange - 3);
392 gr.SetMarkerColor(kOrange - 3);
393 gr.SetLineStyle(kSolid);
394 gr.SetLineWidth(2);
395 gr.SetMarkerStyle(21);
396 gr.DrawGraph(m_ekin.size(), m_ekin.data(), m_range.data(), "plsame");
397 crange->Update();
398}

◆ PlotStraggling()

void Garfield::TrackSrim::PlotStraggling ( )

Plot the transverse and longitudinal straggling as function of the projectile energy.

Definition at line 400 of file TrackSrim.cc.

400 {
401
402 const double xmin = *std::min_element(std::begin(m_ekin), std::end(m_ekin));
403 const double xmax = *std::max_element(std::begin(m_ekin), std::end(m_ekin));
404 const double ymax = std::max(*std::max_element(std::begin(m_longstraggle),
405 std::end(m_longstraggle)),
406 *std::max_element(std::begin(m_transstraggle),
407 std::end(m_transstraggle)));
408 // Prepare a plot frame.
409 const std::string name = ViewBase::FindUnusedCanvasName("cSRIM");
410 TCanvas* cstraggle = new TCanvas(name.c_str(), "Straggling");
411 cstraggle->SetLogx();
412 cstraggle->SetGridx();
413 cstraggle->SetGridy();
414 cstraggle->DrawFrame(xmin, 0., xmax, 1.05 * ymax, ";Ion energy [MeV];Straggling [cm]");
415
416 // Make a graph for the 2 curves to plot.
417 const unsigned int nPoints = m_ekin.size();
418 TGraph gr;
419 gr.SetLineStyle(kSolid);
420 gr.SetLineWidth(2);
421 gr.SetMarkerStyle(21);
422
423 gr.SetLineColor(kOrange - 3);
424 gr.SetMarkerColor(kOrange - 3);
425 gr.DrawGraph(nPoints, m_ekin.data(), m_longstraggle.data(), "plsame");
426
427 gr.SetLineColor(kGreen + 2);
428 gr.SetMarkerColor(kGreen + 2);
429 gr.DrawGraph(nPoints, m_ekin.data(), m_transstraggle.data(), "plsame");
430
431 TLatex label;
432 double xLabel = 1.2 * xmin;
433 double yLabel = 0.9 * ymax;
434 label.SetTextColor(kOrange - 3);
435 label.SetText(xLabel, yLabel, "Longitudinal");
436 label.DrawLatex(xLabel, yLabel, "Longitudinal");
437 yLabel -= 1.5 * label.GetYsize();
438 label.SetTextColor(kGreen + 2);
439 label.DrawLatex(xLabel, yLabel, "Transverse");
440 cstraggle->Update();
441}

◆ PreciseLoss()

bool Garfield::TrackSrim::PreciseLoss ( const double step,
const double estart,
double & deem,
double & dehd ) const
protected

Definition at line 460 of file TrackSrim.cc.

461 {
462 // SRMRKS
463
464 // Debugging
465 if (m_debug) printf(" Integrating energy losses over %g cm.\n", step);
466 // Precision aimed for.
467 const double eps = 1.0e-2;
468 // Number of intervals.
469 unsigned int ndiv = 1;
470 // Loop until precision achieved
471 const unsigned int nMaxIter = 10;
472 bool converged = false;
473 for (unsigned int iter = 0; iter < nMaxIter; ++iter) {
474 double e4 = estart;
475 double e2 = estart;
476 deem = 0.;
477 dehd = 0.;
478 // Compute rk2 and rk4 over the number of sub-divisions
479 const double s = m_rho * step / ndiv;
480 for (unsigned int i = 0; i < ndiv; i++) {
481 // rk2: initial point
482 const double de21 = s * (DedxEM(e2) + DedxHD(e2));
483 // Mid-way point
484 const double em22 = s * DedxEM(e2 - 0.5 * de21);
485 const double hd22 = s * DedxHD(e2 - 0.5 * de21);
486 // Trace the rk2 energy
487 e2 -= em22 + hd22;
488 // rk4: initial point
489 const double em41 = s * DedxEM(e4);
490 const double hd41 = s * DedxHD(e4);
491 const double de41 = em41 + hd41;
492 // Mid-way point
493 const double em42 = s * DedxEM(e4 - 0.5 * de41);
494 const double hd42 = s * DedxHD(e4 - 0.5 * de41);
495 const double de42 = em42 + hd42;
496 // Second mid-point estimate
497 const double em43 = s * DedxEM(e4 - 0.5 * de42);
498 const double hd43 = s * DedxHD(e4 - 0.5 * de42);
499 const double de43 = em43 + hd43;
500 // End point estimate
501 const double em44 = s * DedxEM(e4 - de43);
502 const double hd44 = s * DedxHD(e4 - de43);
503 const double de44 = em44 + hd44;
504 // Store the energy loss terms (according to rk4)
505 deem += (em41 + em44) / 6. + (em42 + em43) / 3.;
506 dehd += (hd41 + hd44) / 6. + (hd42 + hd43) / 3.;
507 // Store the new energy computed with rk4
508 e4 -= (de41 + de44) / 6. + (de42 + de43) / 3.;
509 }
510 if (m_debug) {
511 printf(" Iteration %u has %u division(s). Losses:\n", iter, ndiv);
512 printf(" de4 = %12g, de2 = %12g MeV\n", estart - e2, estart - e4);
513 printf(" em4 = %12g, hd4 = %12g MeV\n", deem, dehd);
514 }
515 // Compare the two estimates
516 if (fabs(e2 - e4) > eps * (fabs(e2) + fabs(e4) + fabs(estart))) {
517 // Repeat with twice the number of steps.
518 ndiv *= 2;
519 } else {
520 converged = true;
521 break;
522 }
523 }
524
525 if (!converged) {
526 std::cerr << m_className << "::PreciseLoss: "
527 << "No convergence achieved integrating energy loss.\n";
528 } else if (m_debug) {
529 std::cout << " Convergence at eps = " << eps << ".\n";
530 }
531 return converged;
532}

Referenced by EstimateRange(), and NewTrack().

◆ Print()

void Garfield::TrackSrim::Print ( )

Print the energy loss table.

Definition at line 287 of file TrackSrim.cc.

287 {
288 std::cout << "TrackSrim::Print:\n SRIM energy loss table\n\n"
289 << " Energy EM Loss HD loss Range "
290 << "l straggle t straggle\n"
291 << " [MeV] [MeV/cm] [MeV/cm] [cm] "
292 << " [cm] [cm]\n\n";
293 const unsigned int nPoints = m_emloss.size();
294 for (unsigned int i = 0; i < nPoints; ++i) {
295 printf("%10g %10g %10g %10g %10g %10g\n", m_ekin[i],
296 m_emloss[i] * m_rho, m_hdloss[i] * m_rho, m_range[i],
298 }
299 std::cout << "\n";
300 if (m_work > 0.) {
301 std::printf(" Work function: %g eV\n", m_work);
302 } else {
303 std::cout << " Work function: automatic\n";
304 }
305 if (m_fset) {
306 std::printf(" Fano factor: %g\n", m_fano);
307 } else {
308 std::cout << " Fano factor: automatic\n";
309 }
310 printf(" Ion charge: %g\n", m_qion);
311 printf(" Mass: %g MeV\n", 1.e-6 * m_mion);
312 printf(" Density: %g g/cm3\n", m_rho);
313 if (m_a > 0. && m_z > 0.) {
314 std::printf(" A, Z: %g, %g\n", m_a, m_z);
315 } else {
316 std::cout << " A, Z: automatic\n";
317 }
318}

◆ ReadFile()

bool Garfield::TrackSrim::ReadFile ( const std::string & file)

Load data from a SRIM file.

Definition at line 79 of file TrackSrim.cc.

79 {
80 // SRMREA
81
82 const std::string hdr = m_className + "::ReadFile:\n ";
83 // Open the material list.
84 std::ifstream fsrim(file);
85 if (!fsrim) {
86 std::cerr << hdr << "Could not open SRIM file " << file
87 << " for reading.\n The file perhaps does not exist.\n";
88 return false;
89 }
90 unsigned int nread = 0;
91
92 // Read the header
93 if (m_debug) {
94 std::cout << hdr << "SRIM header records from file " << file << "\n";
95 }
96 constexpr size_t size = 100;
97 char line[size];
98 while (fsrim.getline(line, size, '\n')) {
99 nread++;
100 if (strstr(line, "SRIM version") != NULL) {
101 if (m_debug) std::cout << "\t" << line << "\n";
102 } else if (strstr(line, "Calc. date") != NULL) {
103 if (m_debug) std::cout << "\t" << line << "\n";
104 } else if (strstr(line, "Ion =") != NULL) {
105 break;
106 }
107 }
108
109 // Identify the ion
110 char* token = nullptr;
111 token = strtok(line, " []=");
112 token = strtok(nullptr, " []=");
113 token = strtok(nullptr, " []=");
114 // Set the ion charge.
115 if (token) {
116 m_qion = std::atof(token);
117 m_chargeset = true;
118 }
119 token = strtok(nullptr, " []=");
120 token = strtok(nullptr, " []=");
121 token = strtok(nullptr, " []=");
122 // Set the ion mass (convert amu to eV).
123 m_mion = std::atof(token) * AtomicMassUnitElectronVolt;
124
125 // Find the target density
126 if (!fsrim.getline(line, size, '\n')) {
127 std::cerr << hdr << "Premature EOF looking for target density (line "
128 << nread << ").\n";
129 return false;
130 }
131 nread++;
132 if (!fsrim.getline(line, size, '\n')) {
133 std::cerr << hdr << "Premature EOF looking for target density (line "
134 << nread << ").\n";
135 return false;
136 }
137 nread++;
138 const bool pre2013 = (strstr(line, "Target Density") != NULL);
139 token = strtok(line, " ");
140 token = strtok(NULL, " ");
141 token = strtok(NULL, " ");
142 if (pre2013) token = strtok(NULL, " ");
143 SetDensity(std::atof(token));
144
145 // Check the stopping units
146 while (fsrim.getline(line, size, '\n')) {
147 nread++;
148 if (strstr(line, "Stopping Units") == NULL) continue;
149 if (strstr(line, "Stopping Units = MeV / (mg/cm2)") != NULL ||
150 strstr(line, "Stopping Units = MeV/(mg/cm2)") != NULL) {
151 if (m_debug) {
152 std::cout << hdr << "Stopping units: MeV / (mg/cm2) as expected.\n";
153 }
154 break;
155 }
156 std::cerr << hdr << "Unknown stopping units. Aborting (line " << nread
157 << ").\n";
158 return false;
159 }
160
161 // Skip to the table
162 while (fsrim.getline(line, size, '\n')) {
163 nread++;
164 if (strstr(line, "-----------") != NULL) break;
165 }
166
167 // Read the table line by line
168 m_ekin.clear();
169 m_emloss.clear();
170 m_hdloss.clear();
171 m_range.clear();
172 m_transstraggle.clear();
173 m_longstraggle.clear();
174 unsigned int ntable = 0;
175 while (fsrim.getline(line, size, '\n')) {
176 nread++;
177 if (strstr(line, "-----------") != NULL) break;
178 // Energy
179 token = strtok(line, " ");
180 m_ekin.push_back(atof(token));
181 token = strtok(NULL, " ");
182 if (strcmp(token, "eV") == 0) {
183 m_ekin[ntable] *= 1.0e-6;
184 } else if (strcmp(token, "keV") == 0) {
185 m_ekin[ntable] *= 1.0e-3;
186 } else if (strcmp(token, "GeV") == 0) {
187 m_ekin[ntable] *= 1.0e3;
188 } else if (strcmp(token, "MeV") != 0) {
189 std::cerr << hdr << "Unknown energy unit " << token << "; aborting\n";
190 return false;
191 }
192 // EM loss
193 token = strtok(NULL, " ");
194 m_emloss.push_back(atof(token));
195 // HD loss
196 token = strtok(NULL, " ");
197 m_hdloss.push_back(atof(token));
198 // Projected range
199 token = strtok(NULL, " ");
200 m_range.push_back(atof(token));
201 token = strtok(NULL, " ");
202 if (strcmp(token, "A") == 0) {
203 m_range[ntable] *= 1.0e-8;
204 } else if (strcmp(token, "um") == 0) {
205 m_range[ntable] *= 1.0e-4;
206 } else if (strcmp(token, "mm") == 0) {
207 m_range[ntable] *= 1.0e-1;
208 } else if (strcmp(token, "m") == 0) {
209 m_range[ntable] *= 1.0e2;
210 } else if (strcmp(token, "km") == 0) {
211 m_range[ntable] *= 1.0e5;
212 } else if (strcmp(token, "cm") != 0) {
213 std::cerr << hdr << "Unknown distance unit " << token << "; aborting\n";
214 return false;
215 }
216 // Longitudinal straggling
217 token = strtok(NULL, " ");
218 m_longstraggle.push_back(atof(token));
219 token = strtok(NULL, " ");
220 if (strcmp(token, "A") == 0) {
221 m_longstraggle[ntable] *= 1.0e-8;
222 } else if (strcmp(token, "um") == 0) {
223 m_longstraggle[ntable] *= 1.0e-4;
224 } else if (strcmp(token, "mm") == 0) {
225 m_longstraggle[ntable] *= 1.0e-1;
226 } else if (strcmp(token, "m") == 0) {
227 m_longstraggle[ntable] *= 1.0e2;
228 } else if (strcmp(token, "km") == 0) {
229 m_longstraggle[ntable] *= 1.0e5;
230 } else if (strcmp(token, "cm") != 0) {
231 std::cerr << hdr << "Unknown distance unit " << token << "; aborting\n";
232 return false;
233 }
234 // Transverse straggling
235 token = strtok(NULL, " ");
236 m_transstraggle.push_back(atof(token));
237 token = strtok(NULL, " ");
238 if (strcmp(token, "A") == 0) {
239 m_transstraggle[ntable] *= 1.0e-8;
240 } else if (strcmp(token, "um") == 0) {
241 m_transstraggle[ntable] *= 1.0e-4;
242 } else if (strcmp(token, "mm") == 0) {
243 m_transstraggle[ntable] *= 1.0e-1;
244 } else if (strcmp(token, "m") == 0) {
245 m_transstraggle[ntable] *= 1.0e2;
246 } else if (strcmp(token, "km") == 0) {
247 m_transstraggle[ntable] *= 1.0e5;
248 } else if (strcmp(token, "cm") != 0) {
249 std::cerr << hdr << "Unknown distance unit " << token << "; aborting\n";
250 return false;
251 }
252
253 // Increment table line counter
254 ++ntable;
255 }
256
257 // Find the scaling factor and convert to MeV/cm
258 double scale = -1.;
259 while (fsrim.getline(line, size, '\n')) {
260 nread++;
261 if (strstr(line, "=============") != NULL) {
262 break;
263 } else if (strstr(line, "MeV / (mg/cm2)") != NULL ||
264 strstr(line, "MeV/(mg/cm2)") != NULL) {
265 token = strtok(line, " ");
266 scale = std::atof(token);
267 }
268 }
269 if (scale < 0) {
270 std::cerr << hdr << "Did not find stopping unit scaling; aborting.\n";
271 return false;
272 }
273 scale *= 1.e3;
274 for (unsigned int i = 0; i < ntable; ++i) {
275 m_emloss[i] *= scale;
276 m_hdloss[i] *= scale;
277 }
278
279 // Seems to have worked
280 if (m_debug) {
281 std::cout << hdr << "Successfully read " << file << "(" << nread
282 << " lines).\n";
283 }
284 return true;
285}
void SetDensity(const double density)
Set the density [g/cm3] of the target medium.
Definition TrackSrim.hh:64

◆ RndmEnergyLoss()

double Garfield::TrackSrim::RndmEnergyLoss ( const double ekin,
const double de,
const double step,
const double edens ) const
protected

Definition at line 1229 of file TrackSrim.cc.

1230 {
1231 // RNDDE - Generates a random energy loss.
1232 // VARIABLES : EKIN : Kinetic energy [MeV]
1233 // DE : Mean energy loss over the step [MeV]
1234 // STEP : Step length [cm]
1235 // BETA2 : Velocity-squared
1236 // GAMMA : Projectile gamma
1237 // EMAX : Maximum energy transfer per collision [MeV]
1238 // XI : Rutherford term [MeV]
1239 // FCONST : Proportionality constant
1240 // EMASS : Electron mass [MeV]
1241
1242 const std::string hdr = "TrackSrim::RndmEnergyLoss: ";
1243 // Check correctness.
1244 if (ekin <= 0 || de <= 0 || step <= 0) {
1245 std::cerr << hdr << "Input parameters not valid.\n Ekin = " << ekin
1246 << " MeV, dE = " << de << " MeV, step length = " << step
1247 << " cm.\n";
1248 return 0.;
1249 } else if (m_mion <= 0 || fabs(m_qion) <= 0) {
1250 std::cerr << hdr << "Track parameters not valid.\n Mass = "
1251 << m_mion << " MeV, charge = " << m_qion << ".\n";
1252 return 0.;
1253 } else if (edens <= 0.) {
1254 std::cerr << hdr << "Target parameters not valid.\n"
1255 << " electron density = " << edens << " / cm3.\n";
1256 return 0.;
1257 }
1258 // Basic kinematic parameters
1259 const double rkin = 1.e6 * ekin / m_mion;
1260 const double gamma = 1. + rkin;
1261 const double beta2 = rkin > 1.e-5 ? 1. - 1. / (gamma * gamma) : 2. * rkin;
1262
1263 // Compute maximum energy transfer
1264 const double rm = ElectronMass / m_mion;
1265 const double emax = 2 * ElectronMass * 1.e-6 * beta2 * gamma * gamma /
1266 (1. + 2 * gamma * rm + rm * rm);
1267 // Compute the Rutherford term.
1268 const double xi = Xi(step, beta2, edens);
1269 // Compute the scaling parameter
1270 const double rkappa = xi / emax;
1271 // Debugging output.
1272 if (m_debug) {
1273 PrintSettings(hdr, de, step, ekin, beta2, gamma, edens,
1274 m_qion, m_mion, emax, xi, rkappa);
1275 }
1276 double rndde = de;
1278 // No fluctuations.
1279 if (m_debug) std::cout << " Fixed energy loss.\n";
1280 } else if (m_model == 1) {
1281 // Landau distribution
1282 if (m_debug) std::cout << " Landau imposed.\n";
1283 const double xlmean = -(log(rkappa) + beta2 + 1. - Gamma);
1284 rndde += xi * (RndmLandau() - xlmean);
1285 } else if (m_model == 2) {
1286 // Vavilov distribution, ensure we are in range.
1287 if (m_debug) std::cout << " Vavilov imposed.\n";
1288 if (rkappa > 0.01 && rkappa < 12) {
1289 const double xvav = RndmVavilov(rkappa, beta2);
1290 rndde += xi * (xvav + log(rkappa) + beta2 + (1 - Gamma));
1291 }
1292 } else if (m_model == 3) {
1293 // Gaussian model
1294 if (m_debug) std::cout << " Gaussian imposed.\n";
1295 rndde += RndmGaussian(0., sqrt(xi * emax * (1 - 0.5 * beta2)));
1296 } else if (rkappa < 0.05) {
1297 // Combined model: for low kappa, use the landau distribution.
1298 if (m_debug) std::cout << " Landau automatic.\n";
1299 const double xlmean = -(log(rkappa) + beta2 + (1 - Gamma));
1300 const double par[] = {0.50884, 1.26116, 0.0346688, 1.46314,
1301 0.15088e-2, 1.00324, -0.13049e-3};
1302 const double xlmax = par[0] + par[1] * xlmean + par[2] * xlmean * xlmean +
1303 par[6] * xlmean * xlmean * xlmean +
1304 (par[3] + xlmean * par[4]) * exp(par[5] * xlmean);
1305 double xlan = RndmLandau();
1306 for (unsigned int iter = 0; iter < 100; ++iter) {
1307 if (xlan < xlmax) break;
1308 xlan = RndmLandau();
1309 }
1310 rndde += xi * (xlan - xlmean);
1311 } else if (rkappa < 5) {
1312 // For medium kappa, use the Vavilov distribution.
1313 if (m_debug) std::cout << " Vavilov fast automatic.\n";
1314 const double xvav = RndmVavilov(rkappa, beta2);
1315 rndde += xi * (xvav + log(rkappa) + beta2 + (1 - Gamma));
1316 } else {
1317 // And for large kappa, use the Gaussian values.
1318 if (m_debug) std::cout << " Gaussian automatic.\n";
1319 rndde = RndmGaussian(de, sqrt(xi * emax * (1 - 0.5 * beta2)));
1320 }
1321 // Debugging output
1322 if (m_debug) {
1323 std::cout << " Energy loss generated = " << rndde << " MeV.\n";
1324 }
1325 return rndde;
1326}
double Xi(const double x, const double beta2, const double edens) const
Definition TrackSrim.cc:451
double RndmVavilov(const double rkappa, const double beta2)
Draw a random number from a Vavilov distribution.
Definition Random.cc:300
double RndmLandau()
Draw a random number from a Landau distribution.
Definition Random.cc:104
DoubleAc exp(const DoubleAc &f)
Definition DoubleAc.cpp:377

Referenced by NewTrack().

◆ SetAtomicMassNumbers()

void Garfield::TrackSrim::SetAtomicMassNumbers ( const double a,
const double z )
inline

Set A and Z of the target medium.

Definition at line 68 of file TrackSrim.hh.

68 {
69 m_a = a;
70 m_z = z;
71 }

◆ SetClustersMaximum()

void Garfield::TrackSrim::SetClustersMaximum ( const int n)
inline

Set the max. number of clusters on a track.

Definition at line 46 of file TrackSrim.hh.

46{ m_maxclusters = n; }

◆ SetDensity()

void Garfield::TrackSrim::SetDensity ( const double density)
inline

Set the density [g/cm3] of the target medium.

Definition at line 64 of file TrackSrim.hh.

64{ m_rho = density; }

Referenced by ReadFile().

◆ SetFanoFactor()

void Garfield::TrackSrim::SetFanoFactor ( const double f)
inline

Set the Fano factor.

Definition at line 55 of file TrackSrim.hh.

55 {
56 m_fano = f;
57 m_fset = true;
58 }

◆ SetModel()

void Garfield::TrackSrim::SetModel ( const int m)
inline

Set the fluctuation model (0 = none, 1 = Landau, 2 = Vavilov, 3 = Gaussian, 4 = Combined). By default, the combined model (4) is used.

Definition at line 36 of file TrackSrim.hh.

36{ m_model = m; }

◆ SetTargetClusterSize()

void Garfield::TrackSrim::SetTargetClusterSize ( const int n)
inline

Specify how many electrons should be grouped to a cluster.

Definition at line 41 of file TrackSrim.hh.

41{ m_nsize = n; }

◆ SetWorkFunction()

void Garfield::TrackSrim::SetWorkFunction ( const double w)
inline

Set the W value [eV].

Definition at line 51 of file TrackSrim.hh.

51{ m_work = w; }

◆ SmallestStep()

bool Garfield::TrackSrim::SmallestStep ( const double ekin,
const double edens,
double de,
double step,
double & stpmin )
protected

Definition at line 1057 of file TrackSrim.cc.

1058 {
1059 // Determines the smallest step size for which there is little
1060 // or no risk of finding negative energy fluctuations.
1061 // SRMMST
1062
1063 const std::string hdr = m_className + "::SmallestStep: ";
1064 constexpr double expmax = 30;
1065
1066 // By default, assume the step is right.
1067 stpmin = step;
1068 // Check correctness.
1069 if (ekin <= 0 || de <= 0 || step <= 0) {
1070 std::cerr << hdr << "Input parameters not valid.\n Ekin = " << ekin
1071 << " MeV, dE = " << de << " MeV, step length = " << step
1072 << " cm.\n";
1073 return false;
1074 } else if (m_mion <= 0 || fabs(m_qion) <= 0) {
1075 std::cerr << hdr
1076 << "Track parameters not valid.\n Mass = " << 1.e-6 * m_mion
1077 << " MeV, charge = " << m_qion << ".\n";
1078 return false;
1079 } else if (edens <= 0) {
1080 std::cerr << hdr << "Target parameters not valid.\n"
1081 << " electron density = " << edens << " / cm3.\n";
1082 return false;
1083 }
1084
1085 // Basic kinematic parameters
1086 const double rkin = 1.e6 * ekin / m_mion;
1087 const double gamma = 1. + rkin;
1088 const double beta2 = rkin > 1.e-5 ? 1. - 1. / (gamma * gamma) : 2. * rkin;
1089
1090 // Compute the maximum energy transfer [MeV]
1091 const double rm = ElectronMass / m_mion;
1092 const double emax = 2 * ElectronMass * 1.e-6 * beta2 * gamma * gamma /
1093 (1. + 2 * gamma * rm + rm * rm);
1094 // Compute the Rutherford term.
1095 double xi = Xi(step, beta2, edens);
1096 // Compute the scaling parameter
1097 double rkappa = xi / emax;
1098 // Step size and energy loss
1099 double denow = de;
1100 double stpnow = step;
1101 constexpr unsigned int nMaxIter = 10;
1102 for (unsigned int iter = 0; iter < nMaxIter; ++iter) {
1103 bool retry = false;
1104 // Debugging output.
1105 if (m_debug) {
1106 PrintSettings(hdr, denow, stpnow, ekin, beta2, gamma, edens,
1107 m_qion, m_mion, emax, xi, rkappa);
1108 }
1109 double xinew = xi;
1110 double rknew = rkappa;
1112 // No fluctuations: any step is permitted
1113 stpmin = stpnow;
1114 } else if (m_model == 1) {
1115 // Landau distribution
1116 constexpr double xlmin = -3.;
1117 const double exponent = -xlmin - 1. + Gamma - beta2 - denow / xi;
1118 const double rklim = exponent < -expmax ? 0. : exp(exponent);
1119 stpmin = stpnow * (rklim / rkappa);
1120 if (m_debug) {
1121 std::cout << " Landau distribution is imposed (kappa_min = "
1122 << rklim << ", d_min = " << stpmin << " cm).\n";
1123 }
1124 } else if (m_model == 2) {
1125 // Vavilov distribution, ensure we're in range.
1126 const double xlmin = StepVavilov(rkappa);
1127 const double exponent = -xlmin - 1. + Gamma - beta2 - denow / xi;
1128 const double rklim = exponent < -expmax ? 0. : exp(exponent);
1129 stpmin = stpnow * (rklim / rkappa);
1130 xinew = Xi(stpmin, beta2, edens);
1131 rknew = xinew / emax;
1132 if (m_debug) {
1133 std::cout << " Vavilov distribution is imposed (kappa_min = "
1134 << rklim << ", d_min = " << stpmin << " cm, kappa_new = "
1135 << rknew << ", xi_new = " << xinew << " MeV).\n";
1136 }
1137 if (stpmin > stpnow * 1.1) {
1138 if (m_debug) std::cout << " Step size increase. New pass.\n";
1139 retry = true;
1140 }
1141 } else if (m_model == 3) {
1142 // Gaussian model
1143 const double sigma2 = xi * emax * (1 - 0.5 * beta2);
1144 stpmin = stpnow * 16 * sigma2 / (denow * denow);
1145 if (m_debug) {
1146 const double sigmaMin2 = Xi(stpmin, beta2, edens) * emax * (1 - 0.5 * beta2);
1147 std::cout << " Gaussian distribution is imposed, d_min = "
1148 << stpmin << " cm, sigma/mu (old) = "
1149 << sqrt(sigma2) / de << ", sigma/mu (min) = "
1150 << sqrt(sigmaMin2) / (stpmin * denow / stpnow) << ".\n";
1151 }
1152 } else if (rkappa < 0.05) {
1153 // Combined model: for low kappa, use the Landau distribution.
1154 constexpr double xlmin = -3.;
1155 const double exponent = -xlmin - 1. + Gamma - beta2 - denow / xi;
1156 const double rklim = exponent < -expmax ? 0. : exp(exponent);
1157 stpmin = stpnow * (rklim / rkappa);
1158 xinew = Xi(stpmin, beta2, edens);
1159 rknew = xinew / emax;
1160 if (m_debug) {
1161 std::cout << " Landau distribution automatic (kappa_min = "
1162 << rklim << ", d_min = " << stpmin << " cm).\n";
1163 }
1164 if (rknew > 0.05 || stpmin > stpnow * 1.1) {
1165 retry = true;
1166 if (m_debug) {
1167 std::cout << " Model change or step increase. New pass.\n";
1168 }
1169 }
1170 } else if (rkappa < 5) {
1171 // For medium kappa, use the Vavilov distribution
1172 const double xlmin = StepVavilov(rkappa);
1173 const double exponent = -xlmin - 1. + Gamma - beta2 - denow / xi;
1174 const double rklim = exponent < -expmax ? 0. : exp(exponent);
1175 stpmin = stpnow * (rklim / rkappa);
1176 xinew = Xi(stpmin, beta2, edens);
1177 rknew = xinew / emax;
1178 if (m_debug) {
1179 std::cout << " Vavilov distribution automatic (kappa_min = "
1180 << rklim << ", d_min = " << stpmin << " cm, kappa_new = "
1181 << rknew << ", xi_new = " << xinew << " MeV).\n";
1182 }
1183 if (rknew > 5 || stpmin > stpnow * 1.1) {
1184 retry = true;
1185 if (m_debug) {
1186 std::cout << " Model change or step increase. New pass.\n";
1187 }
1188 }
1189 } else {
1190 // And for large kappa, use the Gaussian values.
1191 const double sigma2 = xi * emax * (1 - 0.5 * beta2);
1192 stpmin = stpnow * 16 * sigma2 / (denow * denow);
1193 if (m_debug) {
1194 const double sigmaMin2 = Xi(stpmin, beta2, edens) * emax * (1 - 0.5 * beta2);
1195 std::cout << " Gaussian distribution automatic, d_min = "
1196 << stpmin << " cm, sigma/mu (old) = "
1197 << sqrt(sigma2) / de << ", sigma/mu (min) = "
1198 << sqrt(sigmaMin2) / (stpmin * denow / stpnow) << ".\n";
1199 }
1200 }
1201 // See whether we should do another pass.
1202 if (stpnow > stpmin) {
1203 if (m_debug) {
1204 std::cout << " Step size ok, minimum: " << stpmin << " cm\n";
1205 }
1206 break;
1207 }
1208 if (!retry) {
1209 if (m_debug) {
1210 std::cerr << " Step size must be increased to " << stpmin
1211 << "cm.\n";
1212 }
1213 break;
1214 }
1215 // New iteration
1216 rkappa = rknew;
1217 xi = xinew;
1218 denow *= stpmin / stpnow;
1219 stpnow = stpmin;
1220 if (m_debug) std::cout << " Iteration " << iter << "\n";
1221 if (iter == nMaxIter - 1) {
1222 // Need interation, but ran out of tries
1223 std::cerr << hdr << "No convergence reached on step size.\n";
1224 }
1225 }
1226 return true;
1227}

Referenced by NewTrack().

◆ Terminate()

double Garfield::TrackSrim::Terminate ( const std::array< double, 3 > & x0,
const std::array< double, 3 > & v0,
const double step0 ) const
protected

Definition at line 1011 of file TrackSrim.cc.

1013 {
1014 double step = 0.;
1015 std::array<double, 3> x1 = x0;
1016 double s = step0;
1017 const double tol = std::max(1.e-6 * step0, 1.e-6);
1018 while (s > tol) {
1019 s *= 0.5;
1020 const std::array<double, 3> x2 = {x1[0] + s * v0[0], x1[1] + s * v0[1],
1021 x1[2] + s * v0[2]};
1022 if (GetMedium(x2)) {
1023 x1 = x2;
1024 step += s;
1025 }
1026 }
1027 return step;
1028}

Referenced by NewTrack().

◆ TerminateBfield()

double Garfield::TrackSrim::TerminateBfield ( const std::array< double, 3 > & x0,
const std::array< double, 3 > & v0,
const double dt0,
const double vmag ) const
protected

Definition at line 1030 of file TrackSrim.cc.

1032 {
1033
1034 const double qoverm = m_qion / m_mion;
1035 double dt = 0.;
1036 std::array<double, 3> x1 = x0;
1037 std::array<double, 3> v1 = v0;
1038 double s = dt0;
1039 const double tol = std::max(1.e-6 * dt0, 1.e-6);
1040 while (s > tol) {
1041 s *= 0.5;
1042 double bx = 0., by = 0., bz = 0.;
1043 int status = 0;
1044 m_sensor->MagneticField(x1[0], x1[1], x1[2], bx, by, bz, status);
1045 std::array<double, 3> v2 = v1;
1046 std::array<double, 3> d = StepBfield(s, qoverm, vmag, bx, by, bz, v2);
1047 std::array<double, 3> x2 = {x1[0] + d[0], x1[1] + d[1], x1[2] + d[2]};
1048 if (GetMedium(x2)) {
1049 x1 = x2;
1050 v1 = v2;
1051 dt += s;
1052 }
1053 }
1054 return dt * vmag;
1055}

Referenced by NewTrack().

◆ UnsetFanoFactor()

void Garfield::TrackSrim::UnsetFanoFactor ( )
inline

Use the default Fano factor.

Definition at line 60 of file TrackSrim.hh.

60{ m_fset = false; }

◆ Xi()

double Garfield::TrackSrim::Xi ( const double x,
const double beta2,
const double edens ) const
protected

Definition at line 451 of file TrackSrim.cc.

452 {
453
454 constexpr double fconst = 1.e-6 * TwoPi * (
455 FineStructureConstant * FineStructureConstant * HbarC * HbarC) /
456 ElectronMass;
457 return fconst * m_qion * m_qion * edens * x / beta2;
458}

Referenced by RndmEnergyLoss(), and SmallestStep().

Member Data Documentation

◆ m_a

double Garfield::TrackSrim::m_a = -1.
protected

Effective A of the target.

Definition at line 122 of file TrackSrim.hh.

Referenced by GetAtomicMassMumbers(), NewTrack(), Print(), and SetAtomicMassNumbers().

◆ m_chargeset

bool Garfield::TrackSrim::m_chargeset = false
protected

Has the charge been defined?

Definition at line 108 of file TrackSrim.hh.

Referenced by NewTrack(), and ReadFile().

◆ m_clusters

std::vector<Cluster> Garfield::TrackSrim::m_clusters
protected

Definition at line 148 of file TrackSrim.hh.

Referenced by GetCluster(), GetClusters(), and NewTrack().

◆ m_currcluster

size_t Garfield::TrackSrim::m_currcluster = 0
protected

Index of the next cluster to be returned.

Definition at line 142 of file TrackSrim.hh.

Referenced by GetCluster(), and NewTrack().

◆ m_ekin

std::vector<double> Garfield::TrackSrim::m_ekin
protected

Energy in energy loss table [MeV].

Definition at line 129 of file TrackSrim.hh.

Referenced by DedxEM(), DedxHD(), NewTrack(), PlotEnergyLoss(), PlotRange(), PlotStraggling(), Print(), and ReadFile().

◆ m_emloss

std::vector<double> Garfield::TrackSrim::m_emloss
protected

EM energy loss [MeV cm2/g].

Definition at line 131 of file TrackSrim.hh.

Referenced by DedxEM(), PlotEnergyLoss(), Print(), and ReadFile().

◆ m_fano

double Garfield::TrackSrim::m_fano = -1.
protected

Fano factor [-] of the target.

Definition at line 120 of file TrackSrim.hh.

Referenced by GetFanoFactor(), NewTrack(), Print(), and SetFanoFactor().

◆ m_fset

bool Garfield::TrackSrim::m_fset = false
protected

Has the Fano factor been set?

Definition at line 118 of file TrackSrim.hh.

Referenced by NewTrack(), Print(), SetFanoFactor(), and UnsetFanoFactor().

◆ m_hdloss

std::vector<double> Garfield::TrackSrim::m_hdloss
protected

Hadronic energy loss [MeV cm2/g].

Definition at line 133 of file TrackSrim.hh.

Referenced by DedxHD(), PlotEnergyLoss(), Print(), and ReadFile().

◆ m_longstraggle

std::vector<double> Garfield::TrackSrim::m_longstraggle
protected

Longitudinal straggling [cm].

Definition at line 139 of file TrackSrim.hh.

Referenced by NewTrack(), PlotStraggling(), Print(), and ReadFile().

◆ m_maxclusters

int Garfield::TrackSrim::m_maxclusters = -1
protected

Maximum number of clusters allowed (infinite if 0)

Definition at line 127 of file TrackSrim.hh.

Referenced by GetClustersMaximum(), NewTrack(), and SetClustersMaximum().

◆ m_mion

double Garfield::TrackSrim::m_mion = -1.
protected

Mass [MeV] of the projectile.

Definition at line 112 of file TrackSrim.hh.

Referenced by NewTrack(), Print(), ReadFile(), RndmEnergyLoss(), SmallestStep(), and TerminateBfield().

◆ m_model

unsigned int Garfield::TrackSrim::m_model = 4
protected

Fluctuation model (0 = none, 1 = Landau, 2 = Vavilov, 3 = Gaussian, 4 = Combined)

Definition at line 145 of file TrackSrim.hh.

Referenced by GetModel(), RndmEnergyLoss(), SetModel(), and SmallestStep().

◆ m_nsize

int Garfield::TrackSrim::m_nsize = -1
protected

Targeted cluster size.

Definition at line 147 of file TrackSrim.hh.

Referenced by GetTargetClusterSize(), NewTrack(), and SetTargetClusterSize().

◆ m_qion

double Garfield::TrackSrim::m_qion = 1.
protected

Charge of the projectile.

Definition at line 110 of file TrackSrim.hh.

Referenced by NewTrack(), Print(), ReadFile(), RndmEnergyLoss(), SmallestStep(), TerminateBfield(), and Xi().

◆ m_range

std::vector<double> Garfield::TrackSrim::m_range
protected

Projected range [cm].

Definition at line 135 of file TrackSrim.hh.

Referenced by NewTrack(), PlotRange(), Print(), and ReadFile().

◆ m_rho

double Garfield::TrackSrim::m_rho = -1.
protected

Mass density [g/cm3] of the target.

Definition at line 114 of file TrackSrim.hh.

Referenced by GetDensity(), NewTrack(), PlotEnergyLoss(), PreciseLoss(), Print(), and SetDensity().

◆ m_transstraggle

std::vector<double> Garfield::TrackSrim::m_transstraggle
protected

Transverse straggling [cm].

Definition at line 137 of file TrackSrim.hh.

Referenced by NewTrack(), PlotStraggling(), Print(), and ReadFile().

◆ m_useLongStraggle

bool Garfield::TrackSrim::m_useLongStraggle = false
protected

Include longitudinal straggling.

Definition at line 105 of file TrackSrim.hh.

Referenced by EnableLongitudinalStraggling(), and NewTrack().

◆ m_useTransStraggle

bool Garfield::TrackSrim::m_useTransStraggle = true
protected

Include transverse straggling.

Definition at line 103 of file TrackSrim.hh.

Referenced by EnableTransverseStraggling(), and NewTrack().

◆ m_work

double Garfield::TrackSrim::m_work = -1.
protected

Work function [eV] of the target.

Definition at line 116 of file TrackSrim.hh.

Referenced by GetWorkFunction(), NewTrack(), Print(), and SetWorkFunction().

◆ m_z

double Garfield::TrackSrim::m_z = -1.
protected

Effective Z of the target.

Definition at line 124 of file TrackSrim.hh.

Referenced by GetAtomicMassMumbers(), NewTrack(), Print(), and SetAtomicMassNumbers().


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