ATLAS Offline Software
Loading...
Searching...
No Matches
MultipleScatteringUpdator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// MultipleScatteringUpdator.cxx, (c) ATLAS Detector software
8
9// Trk include
12// CLHEP
13
16#include "GaudiKernel/ThreadLocalContext.h"
17#include "CLHEP/Random/RandFlat.h"
20
22
23namespace{
24// static doubles
25constexpr double s_main_RutherfordScott = 13.6 * Gaudi::Units::MeV;
26constexpr double s_log_RutherfordScott = 0.038;
27
28constexpr double s_main_RossiGreisen = 17.5 * Gaudi::Units::MeV;
29constexpr double s_log_RossiGreisen = 0.125;
30
31// ============================= Gaussian mixture model =============
32constexpr double s_gausMixSigma1_a0 = 8.471e-1;
33constexpr double s_gausMixSigma1_a1 = 3.347e-2;
34constexpr double s_gausMixSigma1_a2 = -1.843e-3;
35
36constexpr double s_gausMixEpsilon_a0 = 4.841e-2;
37constexpr double s_gausMixEpsilon_a1 = 6.348e-3;
38constexpr double s_gausMixEpsilon_a2 = 6.096e-4;
39
40constexpr double s_gausMixEpsilon_b0 = -1.908e-2;
41constexpr double s_gausMixEpsilon_b1 = 1.106e-1;
42constexpr double s_gausMixEpsilon_b2 = -5.729e-3;
43}
44
45
46// constructor
47Trk::MultipleScatteringUpdator::MultipleScatteringUpdator(const std::string &t, const std::string &n,
48 const IInterface *p) :
49 AthAlgTool(t, n, p) {
50 declareInterface<IMultipleScatteringUpdator>(this);
51}
52
53// destructor
55
56// Athena standard methods
57// initialize
58StatusCode
60 // if Gaussian mixture is required
62 // get the random generator service
63 if (m_rndGenSvc.retrieve().isFailure()) {
64 ATH_MSG_WARNING("Could not retrieve " << m_rndGenSvc << " -> switching Gaussian mixture model off.");
65 m_gaussianMixture = false;
66 } else {
67 ATH_MSG_VERBOSE("Successfully retrieved " << m_rndGenSvc);
68 }
69
70 // Get own engine with own seeds:
71 m_rngWrapper = m_gaussianMixture ? m_rndGenSvc->getEngine(this, m_randomEngineName) : nullptr;
72 if (!m_rngWrapper) {
74 "Could not get random engine '" << m_randomEngineName << "' -> switching Gaussian mixture model off.");
75 m_gaussianMixture = false;
76 }
77 }
79 ATH_MSG_VERBOSE("Gaussian mixture model = ON ... optimised = " << m_optGaussianMixtureG4);
80 } else {
81 ATH_MSG_VERBOSE("Gaussian mixture model = OFF");
82 }
83
84 return StatusCode::SUCCESS;
85}
86
87double
89 double p,
90 double pathcorrection,
91 ParticleHypothesis particle,
92 double) const {
93 if (mat.thicknessInX0() <= 0. || particle == Trk::geantino) {
94 return 0.;
95 }
96
97 // make sure the path correction is positive to avoid a floating point exception
98 pathcorrection *= pathcorrection < 0. ? (-1.) : (1);
99
100 // scale the path length to the radiation length
101 double t = pathcorrection * mat.thicknessInX0();
102
103 // kinematics (relativistic)
104 double m = Trk::ParticleMasses::mass[particle];
105 double E = sqrt(p * p + m * m);
106 double beta = p / E;
107
108 double sigma2(0.);
109
110 double sigma = Trk::MaterialInteraction::sigmaMS(t, p, beta);
111 sigma2 = sigma * sigma;
112
113 if (m_useTrkUtils && particle != Trk::electron) {
114 return sigma2;
115 }
116
117// Code below will not be used if the parameterization of TrkUtils is used
118
119
120 if (particle != Trk::electron) {
121 if (auto denom = beta * p; not close_to_zero(denom)){
122 // the highland formula
123 sigma2 = s_main_RutherfordScott / denom;
124 }
125
126 if (m_log_include) {
127 sigma2 *= (1. + s_log_RutherfordScott * std::log(t));
128 }
129
130 sigma2 *= (sigma2 * t);
131 }else {
132 // Electron multiple scattering effects - see Highland NIM 129 (1975) p497-499
133 // (Highland extension to the Rossi-Greisen formulation)
134 // NOTE: The formula can be extended by replacing the momentum^2 term with pi * pf
135 sigma2 = s_main_RossiGreisen / (beta * p);
136 sigma2 *= (sigma2 * t);
137
138 if (m_log_include) {
139 double factor = 1. + s_log_RossiGreisen * std::log10(10. * t);
140 factor *= factor;
141 sigma2 *= factor;
142 }
143 }
144
145 // use the Gaussian mixture model
146 if (m_gaussianMixture) {
147 // Reseed the RNG if needed.
148 const EventContext& ctx = Gaudi::Hive::currentContext();
149 if (m_rngWrapper->evtSeeded(ctx) != ctx.evt()) {
150 // Ok, the wrappers are unique to this algorithm and a given slot,
151 // so cannot be accessed concurrently.
153 wrapper_nc->setSeed (this->name(), ctx);
154 }
155 CLHEP::HepRandomEngine* engine = m_rngWrapper->getEngine (ctx);
156 // d_0'
157 double dprime{};
158 if (auto denom = beta * beta; not close_to_zero(denom)){
159 dprime = t / denom;
160 } else {
161 ATH_MSG_WARNING("Trk::MultipleScatteringUpdator::sigmaSquare: beta close to zero");
162 return 0.;
163 }
164 double log_dprime = std::log(dprime);
165 // d_0''
166 double log_dprimeprime = std::log(std::pow(mat.averageZ(), 2.0 / 3.0) * dprime);
167 // get epsilon
168 double epsilon = log_dprimeprime < 0.5 ?
169 s_gausMixEpsilon_a0 + s_gausMixEpsilon_a1 * log_dprimeprime + s_gausMixEpsilon_a2 *
170 log_dprimeprime * log_dprimeprime :
171 s_gausMixEpsilon_b0 + s_gausMixEpsilon_b1 * log_dprimeprime + s_gausMixEpsilon_b2 *
172 log_dprimeprime * log_dprimeprime;
173 // the standard sigma
174 double sigma1square = s_gausMixSigma1_a0 + s_gausMixSigma1_a1 * log_dprime + s_gausMixSigma1_a2 * log_dprime *
175 log_dprime;
176 // G4 optimised / native double Gaussian model
178 if (auto denom = p * p;not close_to_zero(denom)){
179 sigma2 = 225. * dprime / (p * p);
180 } else {
181 ATH_MSG_WARNING("Trk::MultipleScatteringUpdator::sigmaSquare: p close to zero");
182 }
183 }
184 // throw the random number core/tail
185 if (CLHEP::RandFlat::shoot(engine) < epsilon) {
186 sigma2 *= (1. - (1. - epsilon) * sigma1square) / epsilon;
187 }
188 }
189
190 return sigma2;
191}
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
bool close_to_zero(T value, T eps=std::numeric_limits< T >::epsilon())
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Material with information about thickness of material.
ATHRNG::RNGWrapper * m_rngWrapper
Random engine.
virtual StatusCode initialize() override
AlgTool initailize method.
MultipleScatteringUpdator(const std::string &, const std::string &, const IInterface *)
AlgTool like constructor.
virtual ~MultipleScatteringUpdator()
Virtual destructor.
ServiceHandle< IAthRNGSvc > m_rndGenSvc
Random Generator service.
virtual double sigmaSquare(const MaterialProperties &mat, double p, double pathcorrection, ParticleHypothesis particle=pion, double deltaE=0.) const override
Calculate the sigma on theta introduced by multiple scattering, according to the RutherFord-Scott For...
test if a value is close enough to zero to be an unreliable denominator.
bool close_to_zero(T value, T eps=std::numeric_limits< T >::epsilon())
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
static double sigmaMS(double dInX0, double p, double beta)
multiple scattering as function of dInX0