16 #include "GaudiKernel/ThreadLocalContext.h"
17 #include "CLHEP/Random/RandFlat.h"
23 constexpr
double s_log_RutherfordScott = 0.038;
26 constexpr
double s_log_RossiGreisen = 0.125;
29 constexpr
double s_gausMixSigma1_a0 = 8.471e-1;
30 constexpr
double s_gausMixSigma1_a1 = 3.347e-2;
31 constexpr
double s_gausMixSigma1_a2 = -1.843e-3;
33 constexpr
double s_gausMixEpsilon_a0 = 4.841e-2;
34 constexpr
double s_gausMixEpsilon_a1 = 6.348e-3;
35 constexpr
double s_gausMixEpsilon_a2 = 6.096e-4;
37 constexpr
double s_gausMixEpsilon_b0 = -1.908e-2;
38 constexpr
double s_gausMixEpsilon_b1 = 1.106e-1;
39 constexpr
double s_gausMixEpsilon_b2 = -5.729e-3;
45 const IInterface *
p) :
49 m_gaussianMixture(false),
50 m_optGaussianMixtureG4(true),
51 m_rndGenSvc(
"AthRNGSvc",
n),
52 m_rngWrapper(nullptr),
53 m_randomEngineName(
"TrkExRnd") {
54 declareInterface<IMultipleScatteringUpdator>(
this);
73 if (m_gaussianMixture) {
75 if (m_rndGenSvc.retrieve().isFailure()) {
76 ATH_MSG_WARNING(
"Could not retrieve " << m_rndGenSvc <<
" -> switching Gaussian mixture model off.");
77 m_gaussianMixture =
false;
83 m_rngWrapper = m_gaussianMixture ? m_rndGenSvc->getEngine(
this, m_randomEngineName) :
nullptr;
86 "Could not get random engine '" << m_randomEngineName <<
"' -> switching Gaussian mixture model off.");
87 m_gaussianMixture =
false;
90 if (m_gaussianMixture) {
91 ATH_MSG_VERBOSE(
"Gaussian mixture model = ON ... optimised = " << m_optGaussianMixtureG4);
96 return StatusCode::SUCCESS;
102 double pathcorrection,
110 pathcorrection *= pathcorrection < 0. ? (-1.) : (1);
113 double t = pathcorrection *
mat.thicknessInX0();
117 double E = sqrt(
p *
p +
m *
m);
134 sigma2 = s_main_RutherfordScott / (
beta *
p);
137 sigma2 *= (1. + s_log_RutherfordScott *
log(
t));
140 sigma2 *= (sigma2 *
t);
145 sigma2 = s_main_RossiGreisen / (
beta *
p);
146 sigma2 *= (sigma2 *
t);
149 double factor = 1. + s_log_RossiGreisen * log10(10. *
t);
156 if (m_gaussianMixture) {
158 const EventContext& ctx = Gaudi::Hive::currentContext();
159 if (m_rngWrapper->evtSeeded(ctx) != ctx.evt()) {
163 wrapper_nc->setSeed (this->
name(), ctx);
165 CLHEP::HepRandomEngine* engine = m_rngWrapper->getEngine (ctx);
168 double log_dprime =
log(dprime);
170 double log_dprimeprime =
log(
std::pow(
mat.averageZ(), 2.0 / 3.0) * dprime);
172 double epsilon = log_dprimeprime < 0.5 ?
173 s_gausMixEpsilon_a0 + s_gausMixEpsilon_a1 * log_dprimeprime + s_gausMixEpsilon_a2 *
174 log_dprimeprime * log_dprimeprime :
175 s_gausMixEpsilon_b0 + s_gausMixEpsilon_b1 * log_dprimeprime + s_gausMixEpsilon_b2 *
176 log_dprimeprime * log_dprimeprime;
178 double sigma1square = s_gausMixSigma1_a0 + s_gausMixSigma1_a1 * log_dprime + s_gausMixSigma1_a2 * log_dprime *
181 if (!m_optGaussianMixtureG4) {
182 sigma2 = 225. * dprime / (
p *
p);
185 if (CLHEP::RandFlat::shoot(engine) < epsilon) {
186 sigma2 *= (1. - (1. - epsilon) * sigma1square) / epsilon;