ATLAS Offline Software
MaterialInteraction.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // MaterialInteraction.cxx, (c) ATLAS Detector software
9 
10 #include <cmath>
11 #include "CxxUtils/inline_hints.h"
12 
55 namespace {
56 
57 constexpr double s_me = Trk::ParticleMasses::mass[Trk::electron];
58 
59 //The following were repeated in the code.
60 //Now moved to helpers, lets keep the same
61 //semantics as before for all builds.
62 
63 // mean excitation energy --> I
65 double
66 MeanExcitationEnergy(const Trk::Material& mat) {
67  // 16 eV * Z**0.9 - bring to MeV
68  return 16.e-6 * std::pow(mat.averageZ(), 0.9);
69 }
70 
72 double
73 DensityEffect(const double zOverAtimesRho, const double eta,
74  const double gamma, const double I) {
75 
76  // density effect. Done for gamma > 10 ( p > 1GeV for muons)
77  // see ATLASRECTS-3144 and ATLASRECTS-7586
78  // for possible issues
79  if (gamma > 10.) {
80  // PDG 2022 Table 34.1
81  double eplasma = 28.816e-6 * std::sqrt(1000. * zOverAtimesRho);
82  // PDG 2022 Eq. 34.6
83  //2. * std::log(eplasma / I) + std::log(eta2) - 1.
84  //applying logarithmic identities becomes
85  // 2*(log(eplasma/I) + log(eta)) = 2*log(eplasma*eta/I)
86  return 2. * std::log(eplasma*eta / I) - 1.;
87  }
88  return 0;
89 }
90 
92 double
93 KAZ(const double zOverAtimesRho) {
94  // K/A*Z = 0.5 * 30.7075MeV/(g/mm2) * Z/A * rho[g/mm3]
95  return 0.5 * 30.7075 * zOverAtimesRho;
96 }
97 
99 double
100 LandauMPV(const double kazL, const double eta2, const double I,
101  const double beta, const double delta) {
102  // PDG 2022 Eq 34.12
103  // then apply logarithmic identity
104  // log(2. * s_me * eta2 / I) + log(kazL / I) = log(2. * s_me* eta2 * kazL/(I*I))
105  return -kazL * (std::log(2. * s_me * eta2*kazL/(I*I)) + 0.2 -
106  (beta * beta) - delta);
107 }
108 
109 } // namespace
110 
119  double& sigma, double& kazL) {
120 
121  sigma = 0.;
122  kazL = 0.;
123  if (mat.averageZ() < 1) {
124  return 0.;
125  }
126  const double m = Trk::ParticleMasses::mass[particle];
127  const double mfrac = s_me / m;
128  const double E = std::sqrt(p * p + m * m);
129  const double beta = p / E;
130  const double gamma = E / m;
131  const double I = MeanExcitationEnergy(mat);
132  const double zOverAtimesRho = mat.zOverAtimesRho();
133  double kaz = KAZ(zOverAtimesRho);
134  double Ionization = 0.;
135 
136  if (particle == Trk::electron) {
137  // for electrons use slightly different BetheBloch adaption
138  // see Stampfer, et al, "Track Fitting With Energy Loss", Comp. Pyhs. Comm.
139  // 79 (1994), 157-164
140  Ionization = -kaz * (2. * log(2. * s_me / I) + 3. * log(gamma) - 1.95);
141  // sigmaL --> FWHM of Landau
142  sigma = 4 * kaz;
143  } else {
144  const double eta = beta * gamma;
145  const double eta2 = eta*eta;
146  const double delta = DensityEffect(zOverAtimesRho, eta, gamma, I);
147  // tmax - cut off energy
148  const double tMax =
149  2. * eta2 * s_me / (1. + 2. * gamma * mfrac + mfrac * mfrac);
150  // divide by beta^2 for non-electrons
151  kaz /= beta * beta;
152  // PDG 2022 Eq 34.5
153  Ionization = -kaz * (std::log(2. * s_me * eta2 * tMax / (I * I)) -
154  2. * (beta * beta) - delta);
155  // The MPV is path lenght dependent, here we set pathlenght = 1 (mm)
156  // so kazL = kaz
157  const double MPV = LandauMPV(kaz, eta2, I, beta, delta);
158  constexpr double factor = (1. / 3.59524);
159  sigma = -(Ionization - MPV) * factor;
160  kazL = kaz * factor;
161  }
162  return Ionization;
163 }
164 
166  const Trk::MaterialProperties& mat, double beta, double gamma,
169  return 0.;
170  }
171 
172  if (mat.averageZ() == 0. || mat.zOverAtimesRho() == 0.) {
173  return 0.;
174  }
175  const double iPot = 16.e-6 * std::pow(mat.averageZ(), 0.9);
176  const double m = Trk::ParticleMasses::mass[particle];
177  const double zOverAtimesRho = mat.zOverAtimesRho();
178  double kaz = KAZ(mat.zOverAtimesRho());
179 
180  if (particle != Trk::electron) {
181  const double eta = beta * gamma;
182  const double eta2 = eta*eta;
183  double delta = DensityEffect(zOverAtimesRho, eta, gamma, iPot);
184  // mass fraction
185  double mfrac = s_me / m;
186  // tmax - cut off energy
187  double tMax = 2. * eta2 * s_me / (1. + 2. * gamma * mfrac + mfrac * mfrac);
188  // divide by beta^2 for non-electrons
189  kaz /= beta * beta;
190  // return PDG 2022 Eq 34.5
191  return kaz * (std::log(2. * s_me * eta2 * tMax / (iPot * iPot)) -
192  2. * (beta * beta) - delta);
193  }
194  // for electrons use slightly different BetheBloch adaption
195  // see Stampfer, et al, "Track Fitting With Energy Loss", Comp. Pyhs. Comm. 79
196  // (1994), 157-164
197  return kaz * (2. * std::log(2. * s_me / iPot) + 3. * std::log(gamma) - 1.95);
198 }
199 
207  double& sigma, double& kazL, double path) {
208 
209  const double m = Trk::ParticleMasses::mass[particle];
210  const double E = std::sqrt(p * p + m * m);
211  const double beta = p / E;
212  const double gamma = E / m;
213  const double I = MeanExcitationEnergy(mat);
214  const double zOverAtimesRho = mat.zOverAtimesRho();
215  double kaz = KAZ(zOverAtimesRho);
216  const double eta = beta * gamma;
217  const double eta2 = eta*eta;
218  const double delta = DensityEffect(zOverAtimesRho, eta, gamma, I);
219  // divide by beta^2 for non-electrons
220  kaz /= beta * beta;
221  kazL = kaz * path;
222  const double MPV = LandauMPV(kazL, eta2, I, beta, delta);
223  sigma = 0.424 * 4. * kazL; // 0.424 FWHM to sigma
224 
225  return MPV;
226 }
227 
231  double& sigma) {
232  sigma = 0.;
233  if (mat.x0() == 0.)
234  return 0.;
235 
236  // preparation of kinetic constants
237  const double m = Trk::ParticleMasses::mass[particle];
238  const double mfrac = s_me / m;
239  const double E = sqrt(p * p + m * m);
240 
241  // Bremsstrahlung - Bethe-Heitler
242  double Radiation = -E * mfrac * mfrac;
243  // sigma the rms of steep exponential
244  sigma = -Radiation;
245 
246  // Add e+e- pair production and photonuclear effect for muons at energies
247  // above 8 GeV
248  // Radiation gives mean Eloss including the long tail from 'catastrophic'
249  // Eloss sigma the rms of steep exponential
250  // For the parametrization see section 2.3 of Ref [4]
251  if ((particle == Trk::muon) && (E > 8000.)) {
252  if (E < 1.e6) {
253  Radiation += 0.5345 - 6.803e-5 * E - 2.278e-11 * E * E +
254  9.899e-18 * E * E * E; // E below 1 TeV
255  sigma += (0.1828 - 3.966e-3 * std::sqrt(E) + 2.151e-5 * E); // idem
256  } else {
257  Radiation += 2.986 - 9.253e-5 * E; // E above 1 TeV
258  sigma += 17.73 + 2.409e-5 * (E - 1000000.); // idem
259  }
260  }
261  sigma = sigma / mat.x0();
262 
263  return Radiation / mat.x0();
264 }
265 
267  const Trk::MaterialProperties& mat, double initialE,
270  return 0.;
271  }
272  double mfrac = (s_me / Trk::ParticleMasses::mass[particle]);
273  mfrac *= mfrac;
274  return initialE / mat.x0() * mfrac;
275 }
276 
278 double Trk::MaterialInteraction::sigmaMS(double dInX0, double p, double beta) {
279 
280  if (dInX0 == 0. || p == 0. || beta == 0.) {
281  return 0.;
282  }
283  // Improved (See [5] Lynch & Dahl) Highland formula
284  // projected sigma_s PDG 2022 34.16
285  return 13.6 * std::sqrt(dInX0) / (beta * p) *
286  (1. + 0.038 * std::log(dInX0 / (beta * beta)));
287 }
288 
Trk::MaterialInteraction::dEdl_ionization
static double dEdl_ionization(double p, const Material &mat, ParticleHypothesis particle, double &sigma, double &kazL)
dE/dl ionization energy loss per path unit
Definition: MaterialInteraction.cxx:117
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
Trk::MaterialInteraction::sigmaMS
static double sigmaMS(double dInX0, double p, double beta)
multiple scattering as function of dInX0
Definition: MaterialInteraction.cxx:278
pdg_comparison.sigma
sigma
Definition: pdg_comparison.py:324
inline_hints.h
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:126
ParticleGun_SamplingFraction.eta2
eta2
Definition: ParticleGun_SamplingFraction.py:96
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
Trk::MaterialInteraction::dE_MPV_ionization
static double dE_MPV_ionization(double p, const Trk::Material &mat, Trk::ParticleHypothesis particle, double &sigma, double &kazL, double path)
Most Propable dE ionization energly loss.
Definition: MaterialInteraction.cxx:205
mat
GeoMaterial * mat
Definition: LArDetectorConstructionTBEC.cxx:53
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
ATH_ALWAYS_INLINE
#define ATH_ALWAYS_INLINE
Definition: inline_hints.h:53
Trk::undefined
@ undefined
Definition: ParticleHypothesis.h:38
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
TrigVtx::gamma
@ gamma
Definition: TrigParticleTable.h:26
Trk::electron
@ electron
Definition: ParticleHypothesis.h:27
pdg_comparison.kazL
kazL
Definition: pdg_comparison.py:325
Trk::muon
@ muon
Definition: ParticleHypothesis.h:28
Trk::MaterialInteraction::dEdl_radiation
static double dEdl_radiation(double p, const Material &mat, ParticleHypothesis particle, double &sigma)
dE/dl radiation energy loss per path unit
Definition: MaterialInteraction.cxx:229
Trk::ParticleMasses::mass
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:53
VP1PartSpect::E
@ E
Definition: VP1PartSpectFlags.h:21
Trk::nonInteracting
@ nonInteracting
Definition: ParticleHypothesis.h:25
MaterialInteraction.h
Trk::MaterialProperties
Definition: MaterialProperties.h:40
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
Trk::MaterialInteraction::dEdXBetheBloch
static double dEdXBetheBloch(const Trk::MaterialProperties &mat, double beta, double gamma, Trk::ParticleHypothesis particle)
dE/dl ionization energy loss per path unit
Definition: MaterialInteraction.cxx:165
Trk::Material
Definition: Material.h:116
I
#define I(x, y, z)
Definition: MD5.cxx:116
Trk::MaterialInteraction::dEdXBetheHeitler
static double dEdXBetheHeitler(const Trk::MaterialProperties &mat, double initialE, Trk::ParticleHypothesis particle)
Definition: MaterialInteraction.cxx:266
MuonParameters::beta
@ beta
Definition: MuonParamDefs.h:144