35#include "CLHEP/Random/RandFlat.h"
36#include "CLHEP/Random/RandGauss.h"
37#include "GaudiKernel/PhysicalConstants.h"
57 if (
cache.m_solenoid) {
58 cache.m_fieldCache.getFieldZR(R,
H);
60 cache.m_fieldCache.getField(R,
H);
67 if (
cache.m_solenoid) {
68 cache.m_fieldCache.getFieldZR(R,
H, dH);
70 cache.m_fieldCache.getField(R,
H, dH);
82getMagneticField(Cache& cache,
87 constexpr double magScale = 10000.;
93 cache.m_includeBgradients) {
95 getFieldGradient(cache, R,
H, dH);
96 BG[0] =
H[0] * magScale;
97 BG[1] =
H[1] * magScale;
98 BG[2] =
H[2] * magScale;
99 BG[3] = dH[0] * magScale;
100 BG[4] = dH[1] * magScale;
101 BG[5] = dH[2] * magScale;
102 BG[6] = dH[3] * magScale;
103 BG[7] = dH[4] * magScale;
104 BG[8] = dH[5] * magScale;
105 BG[9] = dH[6] * magScale;
106 BG[10] = dH[7] * magScale;
107 BG[11] = dH[8] * magScale;
111 getField(cache, R,
H);
112 BG[0] =
H[0] * magScale;
113 BG[1] =
H[1] * magScale;
114 BG[2] =
H[2] * magScale;
116 for (
int i = 3;
i < 12; ++
i) {
126std::unique_ptr<Trk::TrackParameters>
129 AmgVector(5) lp = inputTrackParameters->parameters();
130 lp[
Trk::qOverP] = 1. / 1e10;
132 if (inputTrackParameters->
type() ==
Trk::Curvilinear) {
133 return std::make_unique<Trk::CurvilinearParameters>(
138 (inputTrackParameters->covariance() ? std::optional<
AmgSymMatrix(5)>(*inputTrackParameters->covariance())
147 (inputTrackParameters->covariance() ? std::optional<
AmgSymMatrix(5)>(*inputTrackParameters->covariance())
151std::unique_ptr<Trk::TrackParameters>
153 std::vector<Trk::DestSurf>& targetSurfaces,
155 std::vector<unsigned int>& solutions,
164 std::vector<std::pair<unsigned int, double>> currentDist;
166 std::vector<std::pair<const Trk::Surface*, Trk::BoundaryCheck>>
::iterator sIter = targetSurfaces.begin();
167 std::vector<std::pair<unsigned int, double>>
::iterator oIter = currentDist.begin();
168 std::vector<Trk::DestSurf>::iterator sBeg = targetSurfaces.begin();
173 for (; sIter != targetSurfaces.end(); ++sIter) {
176 unsigned int numSf = sIter - sBeg;
177 if (distSol.
first() > tol) {
178 if (!currentDist.empty()) {
179 oIter = currentDist.end();
180 while (oIter != currentDist.begin() && distSol.
first() < (*(oIter - 1)).second)
182 oIter = currentDist.insert(oIter, std::pair<unsigned int, double>(numSf, distSol.
first()));
184 currentDist.emplace_back(numSf, distSol.
first());
188 if (!currentDist.empty()) {
189 oIter = currentDist.end();
190 while (oIter != currentDist.begin() && distSol.
second() < (*(oIter - 1)).second)
192 oIter = currentDist.insert(oIter, std::pair<unsigned int, double>(numSf, distSol.
second()));
194 currentDist.emplace_back(numSf, distSol.
second());
201 for (oIter = currentDist.begin(); oIter != currentDist.end(); ++oIter) {
203 if (targetSurfaces[(*oIter).first].first->isOnSurface(xsct, (*oIter).second, 0.001, 0.001)) {
204 if (usePathLimit && path > 0. && path < ((*oIter).second)) {
206 return std::make_unique<Trk::CurvilinearParameters>(endpoint, parm.
momentum(), parm.
charge());
208 path = (*oIter).second;
209 solutions.push_back((*oIter).first);
213 return std::make_unique<Trk::CurvilinearParameters>(xsct, parm.
momentum(), parm.
charge());
215 return sf->createUniqueTrackParameters(xsct, parm.
momentum(), parm.
charge(), std::nullopt);
225 cache.m_delIoni = 0.;
227 cache.m_sigmaIoni = 0.;
228 cache.m_sigmaRad = 0.;
235dEds(Cache& cache,
double p)
237 cache.m_delIoni = 0.;
243 if (
cache.m_material->x0() == 0 ||
cache.m_material->averageZ() == 0)
261dgdlambda(Cache& cache,
double l)
265 if (
cache.m_material->x0() == 0 ||
cache.m_material->averageZ() == 0)
267 if (
cache.m_material->zOverAtimesRho() == 0)
270 double p = std::abs(1. / l);
273 double E = std::sqrt(p * p + m * m);
276 double I = 16.e-6 * std::pow(
cache.m_material->averageZ(), 0.9);
277 double kaz = 0.5 * 30.7075 *
cache.m_material->zOverAtimesRho();
280 double lnCore = 4. * me * me / (
m *
m *
m *
m *
I *
I *
l *
l *
l *
l) / (1. + 2. * gamma * me / m + me * me / m * m);
281 double lnCore_deriv =
282 -4. * me * me / (
m *
m *
m *
m *
I *
I) *
283 std::pow(l * l * l * l + 2. * gamma * l * l * l * l * me / m + l * l * l * l * me * me / (m * m), -2) *
285 4. *
l *
l *
l * me * me / (
m *
m));
286 double ln_deriv = 2. *
l *
m *
m * std::log(lnCore) + lnCore_deriv / (lnCore *
beta *
beta);
287 double Bethe_Bloch_deriv = -kaz * ln_deriv;
291 double delta = 2. * std::log(28.816e-6 * std::sqrt(1000. *
cache.m_material->zOverAtimesRho()) /
I) +
292 2. * std::log(beta * gamma) - 1.;
293 double delta_deriv = -2. / (
l *
beta *
beta) + 2. * delta * l * m * m;
294 Bethe_Bloch_deriv += kaz * delta_deriv;
298 double Bethe_Heitler_deriv = me * me / (
m *
m *
cache.m_material->x0() * l * l * l * E);
301 double radiative_deriv = 0.;
304 radiative_deriv = 6.803e-5 / (
cache.m_material->x0() * l * l * l * E) +
305 2. * 2.278e-11 / (
cache.m_material->x0() * l * l * l) -
306 3. * 9.899e-18 *
E / (
cache.m_material->x0() * l * l * l);
308 radiative_deriv = 9.253e-5 / (
cache.m_material->x0() * l * l * l * E);
314 return 0.9 * Bethe_Bloch_deriv + 0.15 * Bethe_Heitler_deriv + 0.15 * radiative_deriv;
316 return Bethe_Bloch_deriv + Bethe_Heitler_deriv + radiative_deriv;
324updateMaterialEffects(Cache& cache,
double mom,
double sinTheta,
double path)
329 if (
cache.m_straggling) {
330 cache.m_covariance(4, 4) +=
cache.m_stragglingVariance;
331 cache.m_stragglingVariance = 0.;
334 if (!
cache.m_multipleScattering)
337 double totalMomentumLoss =
mom -
cache.m_matupd_lastmom;
338 double pathSinceLastUpdate =
path -
cache.m_matupd_lastpath;
340 double pathAbs = std::abs(pathSinceLastUpdate);
342 if (pathAbs < 1.e-03)
345 double matX0 =
cache.m_material->x0();
348 int msLayers = int(pathAbs /
cache.m_layXmax / matX0) + 1;
351 double layerThickness = pathAbs / msLayers;
352 double radiationLengths = layerThickness / matX0;
353 sinTheta = std::max(sinTheta, 1e-20);
354 double remainingPath = pathAbs;
359 double dLambdads = 0.;
360 double thetaVariance = 0.;
362 double average_dEds = totalMomentumLoss / pathAbs;
364 double cumulatedVariance =
cache.m_inputThetaVariance +
cache.m_combinedCovariance(3, 3) +
cache.m_covariance(3, 3);
365 if (cumulatedVariance < 0) {
366 cumulatedVariance = 0;
368 double cumulatedX0 = 0.;
372 double dX0 = std::abs(
cache.m_combinedThickness) - pathAbs / matX0;
375 if (
cache.m_extrapolationCache->x0tot() > 0)
376 cumulatedX0 =
cache.m_extrapolationCache->x0tot() + dX0;
380 for (
int layer = 1;
layer <= msLayers; ++
layer) {
386 E = std::sqrt(mom2 + massSquared);
389 double C0 = 13.6 * 13.6 / mom2 /
beta /
beta;
390 double C1 = 2 * 0.038 * C0;
391 double C2 = 0.038 * 0.038 * C0;
393 double MS2 = radiationLengths;
396 remainingPath -= layerThickness;
403 cumulatedX0 = cumulatedVariance / C0;
404 if (cumulatedX0 > 0.001) {
405 double lX0 =
log(cumulatedX0);
406 cumulatedX0 = cumulatedX0 / (1 + 2 * 0.038 * lX0 + 0.038 * 0.038 * lX0 * lX0);
410 double MS2s = MS2 + cumulatedX0;
411 thetaVariance = C0 * MS2 + C1 * MS2s *
log(MS2s) + C2 * MS2s *
log(MS2s) *
log(MS2s);
413 if (cumulatedX0 > 0.001) {
414 double lX0 =
log(cumulatedX0);
415 thetaVariance += -C1 * cumulatedX0 * lX0 - C2 * cumulatedX0 * lX0 * lX0;
419 double varScale =
cache.m_scatteringScale *
cache.m_scatteringScale;
420 double positionVariance = thetaVariance * (layerThickness * layerThickness / 3. + remainingPath * layerThickness +
421 remainingPath * remainingPath);
422 cache.m_covariance(0, 0) += varScale * positionVariance;
423 cache.m_covariance(1, 1) += varScale * positionVariance;
424 cache.m_covariance.fillSymmetric(
425 2, 0,
cache.m_covariance(2, 0) + varScale * thetaVariance / (sinTheta) * (layerThickness / 2. + remainingPath));
426 cache.m_covariance(2, 2) += varScale * thetaVariance / (sinTheta * sinTheta);
427 cache.m_covariance.fillSymmetric(
428 3, 1,
cache.m_covariance(3, 1) + varScale * thetaVariance * (-layerThickness / 2. - remainingPath));
429 cache.m_covariance(3, 3) += varScale * thetaVariance;
430 cache.m_covariance(4, 4) +=
431 varScale * 3. * thetaVariance * thetaVariance * layerThickness * layerThickness * dLambdads * dLambdads;
432 cumulatedVariance += varScale * thetaVariance;
445covarianceContribution(Cache& cache,
452 double finalMomentum = targetParms->
momentum().mag();
455 updateMaterialEffects(cache, finalMomentum,
sin(trackParameters->
momentum().theta()), path);
462 Trk::
RungeKuttaUtils::newCovarianceMatrix(Jac, cache.m_combinedCovariance + cache.m_covariance);
464 measurementCovariance += localMSCov;
472covarianceContribution(Cache& cache,
473 const Trk::TrackParameters* trackParameters,
475 double finalMomentum,
479 updateMaterialEffects(cache, finalMomentum,
sin(trackParameters->momentum().theta()), path);
482 measurementCovariance +=
cache.m_combinedCovariance +
cache.m_covariance;
499rungeKuttaStep(Cache& cache,
500 bool errorPropagation,
506 double& distanceStepped)
508 constexpr double sol = 0.0299792458;
511 double lambda1 =
P[6];
512 double lambda2 =
P[6];
513 double lambda3 =
P[6];
514 double lambda4 =
P[6];
523 double initialMomentum = std::abs(1. /
P[6]);
533 double BG23[12] = { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. };
535 double BG4[12] = { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. };
544 if (
cache.m_energyLoss &&
cache.m_matPropOK) {
545 g = dEds(cache, momentum);
546 double E = std::sqrt(momentum * momentum + particleMass * particleMass);
548 if (errorPropagation) {
549 if (
cache.m_includeGgradient) {
550 dgdl = dgdlambda(cache, lambda1);
553 -lambda1 * lambda1 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda1 * lambda1 * lambda1 * E * dgdl;
563 getMagneticField(cache,
570 dir.y() * BG1[2] -
dir.z() * BG1[1],
dir.z() * BG1[0] -
dir.x() * BG1[2],
dir.x() * BG1[1] -
dir.y() * BG1[0]);
571 k1 = sol * lambda1 * k1;
574 if (steps++ >
cache.m_maxSteps)
577 if (
cache.m_energyLoss &&
cache.m_matPropOK) {
578 momentum = initialMomentum + (
h / 2.) * dP1;
579 if (momentum <=
cache.m_momentumCutOff)
581 double E = std::sqrt(momentum * momentum + particleMass * particleMass);
584 if (errorPropagation) {
586 -lambda2 * lambda2 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda2 * lambda2 * lambda2 * E * dgdl;
589 pos = initialPos + (
h / 2.) * initialDir + (
h *
h / 8.) * k1;
590 dir = initialDir + (
h / 2.) * k1;
593 getMagneticField(cache, pos, errorPropagation, BG23);
595 dir.z() * BG23[0] -
dir.x() * BG23[2],
596 dir.x() * BG23[1] -
dir.y() * BG23[0]);
597 k2 = sol * lambda2 * k2;
600 if (
cache.m_energyLoss &&
cache.m_matPropOK) {
601 momentum = initialMomentum + (
h / 2.) * dP2;
602 if (momentum <=
cache.m_momentumCutOff)
604 double E = std::sqrt(momentum * momentum + particleMass * particleMass);
607 if (errorPropagation) {
609 -lambda3 * lambda3 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda3 * lambda3 * lambda3 * E * dgdl;
612 dir = initialDir + (
h / 2.) * k2;
615 dir.z() * BG23[0] -
dir.x() * BG23[2],
616 dir.x() * BG23[1] -
dir.y() * BG23[0]);
617 k3 = sol * lambda3 * k3;
620 if (
cache.m_energyLoss &&
cache.m_matPropOK) {
622 if (momentum <=
cache.m_momentumCutOff)
624 double E = std::sqrt(momentum * momentum + particleMass * particleMass);
627 if (errorPropagation) {
629 -lambda4 * lambda4 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda4 * lambda4 * lambda4 * E * dgdl;
632 pos = initialPos +
h * initialDir + (
h *
h / 2.) * k3;
633 dir = initialDir +
h * k3;
637 getMagneticField(cache, pos, errorPropagation, BG4);
639 dir.y() * BG4[2] -
dir.z() * BG4[1],
dir.z() * BG4[0] -
dir.x() * BG4[2],
dir.x() * BG4[1] -
dir.y() * BG4[0]);
640 k4 = sol * lambda4 * k4;
644 double errorEstimate = std::max(errorPos.mag(), 1e-20);
648 h =
h * std::min(std::max(0.25, std::sqrt(std::sqrt(
cache.m_tolerance / errorEstimate))), 4.);
651 if (errorEstimate > 4. *
cache.m_tolerance)
656 pos = initialPos + distanceStepped * initialDir + (distanceStepped * distanceStepped / 6.) * (k1 + k2 + k3);
662 dir = initialDir + (distanceStepped / 6.) * (k1 + 2. * k2 + 2. * k3 + k4);
668 double norm = 1. / std::sqrt(
P[3] *
P[3] +
P[4] *
P[4] +
P[5] *
P[5]);
674 if (
cache.m_energyLoss &&
cache.m_matPropOK) {
675 momentum = initialMomentum + (distanceStepped / 6.) * (dP1 + 2. * dP2 + 2. * dP3 + dP4);
676 if (momentum <=
cache.m_momentumCutOff)
689 if (errorPropagation) {
690 double initialjLambda =
P[41];
691 double jLambda = initialjLambda;
697 for (
int i = 7;
i < 42;
i += 7) {
710 jDir.z() * BG1[0] - jDir.x() * BG1[2],
711 jDir.x() * BG1[1] - jDir.y() * BG1[0]);
714 if (
cache.m_includeBgradients) {
716 (dir1.y() * BG1[9] - dir1.z() * BG1[6]) * jPos.x() + (dir1.y() * BG1[10] - dir1.z() * BG1[7]) * jPos.y() +
717 (dir1.y() * BG1[11] - dir1.z() * BG1[8]) * jPos.z(),
718 (dir1.z() * BG1[3] - dir1.x() * BG1[9]) * jPos.x() + (dir1.z() * BG1[4] - dir1.x() * BG1[10]) * jPos.y() +
719 (dir1.z() * BG1[5] - dir1.x() * BG1[11]) * jPos.z(),
720 (dir1.x() * BG1[6] - dir1.y() * BG1[3]) * jPos.x() + (dir1.x() * BG1[7] - dir1.y() * BG1[4]) * jPos.y() +
721 (dir1.x() * BG1[8] - dir1.y() * BG1[5]) * jPos.z());
724 jk1 = sol * lambda1 * jk1;
728 jdL1 = dL1 * jLambda;
729 jk1 = jk1 + k1 * jLambda / lambda1;
733 jPos = initialjPos + (distanceStepped / 2.) * initialjDir + (distanceStepped * distanceStepped / 8.) * jk1;
734 jDir = initialjDir + (distanceStepped / 2.) * jk1;
737 jDir.z() * BG23[0] - jDir.x() * BG23[2],
738 jDir.x() * BG23[1] - jDir.y() * BG23[0]);
740 if (
cache.m_includeBgradients) {
741 Amg::Vector3D C((dir2.y() * BG23[9] - dir2.z() * BG23[6]) * jPos.x() +
742 (dir2.y() * BG23[10] - dir2.z() * BG23[7]) * jPos.y() +
743 (dir2.y() * BG23[11] - dir2.z() * BG23[8]) * jPos.z(),
744 (dir2.z() * BG23[3] - dir2.x() * BG23[9]) * jPos.x() +
745 (dir2.z() * BG23[4] - dir2.x() * BG23[10]) * jPos.y() +
746 (dir2.z() * BG23[5] - dir2.x() * BG23[11]) * jPos.z(),
747 (dir2.x() * BG23[6] - dir2.y() * BG23[3]) * jPos.x() +
748 (dir2.x() * BG23[7] - dir2.y() * BG23[4]) * jPos.y() +
749 (dir2.x() * BG23[8] - dir2.y() * BG23[5]) * jPos.z());
752 jk2 = sol * lambda2 * jk2;
755 jLambda = initialjLambda + (distanceStepped / 2.) * jdL1;
756 jdL2 = dL2 * jLambda;
757 jk2 = jk2 + k2 * jLambda / lambda2;
761 jDir = initialjDir + (distanceStepped / 2.) * jk2;
764 jDir.z() * BG23[0] - jDir.x() * BG23[2],
765 jDir.x() * BG23[1] - jDir.y() * BG23[0]);
767 if (
cache.m_includeBgradients) {
768 Amg::Vector3D C((dir3.y() * BG23[9] - dir3.z() * BG23[6]) * jPos.x() +
769 (dir3.y() * BG23[10] - dir3.z() * BG23[7]) * jPos.y() +
770 (dir3.y() * BG23[11] - dir3.z() * BG23[8]) * jPos.z(),
771 (dir3.z() * BG23[3] - dir3.x() * BG23[9]) * jPos.x() +
772 (dir3.z() * BG23[4] - dir3.x() * BG23[10]) * jPos.y() +
773 (dir3.z() * BG23[5] - dir3.x() * BG23[11]) * jPos.z(),
774 (dir3.x() * BG23[6] - dir3.y() * BG23[3]) * jPos.x() +
775 (dir3.x() * BG23[7] - dir3.y() * BG23[4]) * jPos.y() +
776 (dir3.x() * BG23[8] - dir3.y() * BG23[5]) * jPos.z());
779 jk3 = sol * lambda3 * jk3;
782 jLambda = initialjLambda + (distanceStepped / 2.) * jdL2;
783 jdL3 = dL3 * jLambda;
784 jk3 = jk3 + k3 * jLambda / lambda3;
788 jPos = initialjPos + distanceStepped * initialjDir + (distanceStepped * distanceStepped / 2.) * jk3;
789 jDir = initialjDir + distanceStepped * jk3;
792 jDir.z() * BG4[0] - jDir.x() * BG4[2],
793 jDir.x() * BG4[1] - jDir.y() * BG4[0]);
795 if (
cache.m_includeBgradients) {
797 (dir4.y() * BG4[9] - dir4.z() * BG4[6]) * jPos.x() + (dir4.y() * BG4[10] - dir4.z() * BG4[7]) * jPos.y() +
798 (dir4.y() * BG4[11] - dir4.z() * BG4[8]) * jPos.z(),
799 (dir4.z() * BG4[3] - dir4.x() * BG4[9]) * jPos.x() + (dir4.z() * BG4[4] - dir4.x() * BG4[10]) * jPos.y() +
800 (dir4.z() * BG4[5] - dir4.x() * BG4[11]) * jPos.z(),
801 (dir4.x() * BG4[6] - dir4.y() * BG4[3]) * jPos.x() + (dir4.x() * BG4[7] - dir4.y() * BG4[4]) * jPos.y() +
802 (dir4.x() * BG4[8] - dir4.y() * BG4[5]) * jPos.z());
805 jk4 = sol * lambda4 * jk4;
808 jLambda = initialjLambda + distanceStepped * jdL3;
809 jdL4 = dL4 * jLambda;
810 jk4 = jk4 + k4 * jLambda / lambda4;
815 initialjPos + distanceStepped * initialjDir + (distanceStepped * distanceStepped / 6.) * (jk1 + jk2 + jk3);
816 jDir = initialjDir + (distanceStepped / 6.) * (jk1 + 2. * jk2 + 2. * jk3 + jk4);
818 jLambda = initialjLambda + (distanceStepped / 6.) * (jdL1 + 2. * jdL2 + 2. * jdL3 + jdL4);
835 for (
int i = 0;
i < 12; ++
i) {
845propagateWithJacobianImpl(Cache& cache,
846 bool errorPropagation,
852 double maxPath =
cache.m_maxPath;
855 double dDir[3] = { 0., 0., 0. };
856 int targetPassed = 0;
857 double previousDistance = 0.;
858 double distanceStepped = 0.;
859 bool distanceEstimationSuccessful =
false;
860 double BG1[12] = { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. };
862 bool firstStep =
true;
863 double absolutePath = 0.;
870 surfaceType, targetSurface,
P, distanceEstimationSuccessful);
871 if (!distanceEstimationSuccessful) {
877 distanceToTarget > 100. ?
h = 100. : distanceToTarget < -100. ?
h = -100. :
h = distanceToTarget;
883 double distanceTolerance = std::min(std::max(std::abs(distanceToTarget) *
cache.m_tolerance, 1e-6), 1e-2);
885 while (std::abs(distanceToTarget) > distanceTolerance) {
887 if (!rungeKuttaStep(cache, errorPropagation,
h,
P, dDir, BG1, firstStep, distanceStepped))
889 path += distanceStepped;
890 absolutePath += std::abs(distanceStepped);
892 if (std::abs(distanceStepped) > 0.001) {
893 cache.m_sigmaIoni =
cache.m_sigmaIoni -
cache.m_kazL *
log(std::abs(distanceStepped));
896 if (errorPropagation &&
cache.m_straggling) {
899 mom = std::abs(1. /
P[6]);
902 cache.m_stragglingVariance += sigTot2 / (bp2 * bp2) * distanceStepped * distanceStepped;
904 if (
cache.m_matstates || errorPropagation)
905 cache.m_combinedEloss.update(
cache.m_delIoni * distanceStepped,
906 cache.m_sigmaIoni * std::abs(distanceStepped),
907 cache.m_delRad * distanceStepped,
908 cache.m_sigmaRad * std::abs(distanceStepped),
911 previousDistance = std::abs(distanceToTarget);
913 surfaceType, targetSurface,
P, distanceEstimationSuccessful);
914 if (!distanceEstimationSuccessful)
918 if (
h * distanceToTarget < 0.) {
923 if (std::abs(
h) > std::abs(distanceToTarget))
924 h = distanceToTarget;
927 if ((targetPassed > 3 && std::abs(distanceToTarget) >= previousDistance) || (absolutePath > maxPath))
930 if (steps++ >
cache.m_maxSteps)
934 if (
cache.m_material &&
cache.m_material->x0() != 0.)
935 cache.m_combinedThickness += std::abs(path) /
cache.m_material->x0();
941 pos[0] =
pos[0] + distanceToTarget * (
dir[0] + 0.5 * distanceToTarget *
dDir[0]);
942 pos[1] =
pos[1] + distanceToTarget * (
dir[1] + 0.5 * distanceToTarget *
dDir[1]);
943 pos[2] =
pos[2] + distanceToTarget * (
dir[2] + 0.5 * distanceToTarget *
dDir[2]);
951 double norm = 1. / std::sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
964std::unique_ptr<Trk::TrackParameters>
965propagateRungeKuttaImpl(Cache& cache,
966 bool errorPropagation,
980 std::unique_ptr<Trk::TrackParameters> trackParameters{};
986 if (
cache.m_tolerance <= 0.)
988 if (
cache.m_momentumCutOff < 0.)
992 if (inputTrackParameters.parameters()[
Trk::qOverP] == 0) {
993 trackParameters = createStraightLine(&inputTrackParameters);
994 if (!trackParameters) {
998 trackParameters.reset(inputTrackParameters.
clone());
1001 if (std::abs(1. / trackParameters->parameters()[
Trk::qOverP]) <=
cache.m_momentumCutOff) {
1006 if (
cache.m_matPropOK && ((
cache.m_material->zOverAtimesRho() == 0.) || (
cache.m_material->x0() == 0.) ||
1007 (
cache.m_material->zOverAtimesRho() !=
cache.m_material->zOverAtimesRho()))) {
1008 cache.m_matPropOK =
false;
1011 cache.m_stragglingVariance = 0.;
1012 if (errorPropagation ||
cache.m_matstates) {
1013 cache.m_combinedCovariance.setZero();
1014 cache.m_covariance.setZero();
1016 cache.m_inputThetaVariance = trackParameters->covariance() ? (*trackParameters->covariance())(3, 3) : 0.;
1017 cache.m_combinedEloss.set(0., 0., 0., 0., 0., 0.);
1018 cache.m_combinedThickness = 0.;
1031 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1044 if (!propagateWithJacobianImpl(cache, errorPropagation, ty, s,
cache.m_P, path)) {
1051 double s[6] = { T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2) };
1052 if (!propagateWithJacobianImpl(cache, errorPropagation, ty, s,
cache.m_P, path)) {
1060 double s[9] = { T(0, 3), T(1, 3), T(2, 3), T(0, 2),
1061 T(1, 2), T(2, 2), cyl->
bounds().
r(), (
double)propagationDirection,
1063 if (!propagateWithJacobianImpl(cache, errorPropagation, ty, s,
cache.m_P, path)) {
1070 double k =
static_cast<const Trk::ConeSurface*
>(&targetSurface)->bounds().tanAlpha();
1072 double s[9] = { T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2),
k, (
double)propagationDirection, 0. };
1073 if (!propagateWithJacobianImpl(cache, errorPropagation, ty, s,
cache.m_P, path)) {
1080 double s[6] = { T(0, 3), T(1, 3), T(2, 3), 0., 0., 1. };
1081 if (!propagateWithJacobianImpl(cache, errorPropagation, ty, s,
cache.m_P, path)) {
1089 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1102 if (!propagateWithJacobianImpl(cache, errorPropagation, ty, s,
cache.m_P, path)) {
1107 if (propagationDirection * path < 0.) {
1118 if (boundaryCheck && !targetSurface.
isOnSurface(gp)) {
1122 if (!errorPropagation || !trackParameters->covariance()) {
1123 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4]);
1131 if (cache.m_matPropOK && (cache.m_multipleScattering || cache.m_straggling) &&
std::abs(path) > 0.)
1132 covarianceContribution(cache, trackParameters.
get(), path,
std::abs(1. / cache.m_P[6]), measurementCovariance);
1134 return
std::make_unique<
Trk::CurvilinearParameters>(
1135 gp, localp[2], localp[3], localp[4],
std::move(measurementCovariance));
1139 Trk::
RungeKuttaUtils::transformGlobalToLocal(&targetSurface, errorPropagation, cache.m_P, localp, Jacobian);
1141 if (boundaryCheck) {
1143 if (!targetSurface.insideBounds(localPosition, 0.)) {
1149 targetSurface.createUniqueTrackParameters(localp[0], localp[1], localp[2], localp[3], localp[4], std::nullopt);
1151 if (!errorPropagation || !trackParameters->covariance()) {
1152 return onTargetSurf;
1160 if (cache.m_matPropOK && (cache.m_multipleScattering || cache.m_straggling) &&
std::abs(path) > 0.)
1161 covarianceContribution(cache, trackParameters.
get(), path, onTargetSurf.
get(), measurementCovariance);
1163 return targetSurface.createUniqueTrackParameters(
1164 localp[0], localp[1], localp[2], localp[3], localp[4],
std::move(measurementCovariance));
1176 declareInterface<Trk::IPropagator>(
this);
1201 ATH_MSG_WARNING(
"Simulation mode requested but material updator not found - no brem photon emission.");
1210 return StatusCode::SUCCESS;
1215 return StatusCode::SUCCESS;
1224 ATH_MSG_WARNING(
"[STEP_Propagator] STEP_Propagator does not handle neutral track parameters."
1225 <<
"Use the StraightLinePropagator instead.");
1240 double Jacobian[25];
1246 clearMaterialEffects(
cache);
1249 cache.m_trackingVolume = tVol;
1250 cache.m_material = tVol;
1251 cache.m_matPropOK = tVol !=
nullptr;
1254 cache.m_matupd_lastpath = 0.;
1255 cache.m_matdump_lastpath = 0.;
1258 cache.m_identifiedParameters =
nullptr;
1259 cache.m_matstates =
nullptr;
1260 cache.m_extrapolationCache =
nullptr;
1261 cache.m_hitVector =
nullptr;
1263 return propagateRungeKuttaImpl(
cache,
true, trackParameters, targetSurface, propagationDirection,
1264 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1275 std::vector<unsigned int>& solutions,
double& path,
bool usePathLimit,
bool returnCurv,
1283 clearMaterialEffects(
cache);
1286 cache.m_trackingVolume = tVol;
1287 cache.m_material = tVol;
1288 cache.m_matPropOK = tVol !=
nullptr;
1291 cache.m_identifiedParameters =
nullptr;
1292 cache.m_matstates =
nullptr;
1293 cache.m_extrapolationCache =
nullptr;
1294 cache.m_hitVector =
nullptr;
1297 cache.m_matupd_lastpath = 0.;
1298 cache.m_matdump_lastpath = 0.;
1302 cache.m_propagateWithPathLimit = usePathLimit ? 1 : 0;
1303 cache.m_pathLimit = path;
1306 cache.m_propagateWithPathLimit = 0;
1307 cache.m_pathLimit = -1.;
1311 return propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions, path,
1312 usePathLimit, returnCurv);
1315 magneticFieldProperties, particle, solutions, path, returnCurv);
1326 std::vector<unsigned int>& solutions,
PathLimit& pathLim,
TimeLimit& timeLim,
bool returnCurv,
1334 clearMaterialEffects(
cache);
1343 cache.m_trackingVolume = tVol;
1344 cache.m_material = tVol;
1345 cache.m_matPropOK = tVol !=
nullptr;
1348 cache.m_identifiedParameters =
nullptr;
1349 cache.m_matstates =
nullptr;
1350 cache.m_extrapolationCache =
nullptr;
1354 cache.m_matupd_lastpath = 0.;
1355 cache.m_matdump_lastpath = 0.;
1360 dMat > 0 &&
cache.m_matPropOK &&
cache.m_material->x0() > 0. ? dMat *
cache.m_material->x0() : -1.;
1362 double dTim = timeLim.
tMax - timeLim.
time;
1365 double mom = trackParameters.
momentum().mag();
1366 beta = mom / std::sqrt(mom * mom +
cache.m_particleMass *
cache.m_particleMass);
1368 double timMax = dTim > 0 ? dTim * beta * Gaudi::Units::c_light : -1.;
1370 if (timMax > 0. && timMax < path)
1372 bool usePathLimit = (path > 0.);
1376 cache.m_propagateWithPathLimit = usePathLimit ? 1 : 0;
1377 cache.m_pathLimit = path;
1380 cache.m_propagateWithPathLimit = 0;
1381 cache.m_pathLimit = -1.;
1385 std::unique_ptr<Trk::TrackParameters> nextPar{};
1388 nextPar = propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions, path,
1389 usePathLimit, returnCurv);
1392 magneticFieldProperties, particle, solutions, path, returnCurv);
1395 if (
cache.m_matPropOK &&
cache.m_material->x0() > 0. && path > 0.) {
1412 std::vector<unsigned int>& solutions, std::vector<const Trk::TrackStateOnSurface*>* matstates,
1413 std::vector<std::pair<std::unique_ptr<Trk::TrackParameters>,
int>>* intersections,
double& path,
1422 clearMaterialEffects(
cache);
1425 cache.m_trackingVolume = tVol;
1426 cache.m_material = tVol;
1427 cache.m_matPropOK = tVol !=
nullptr;
1429 cache.m_matstates = matstates;
1430 cache.m_identifiedParameters = intersections;
1431 cache.m_extrapolationCache = extrapCache;
1432 cache.m_hitVector =
nullptr;
1435 cache.m_matupd_lastpath = 0.;
1436 cache.m_matdump_lastpath = 0.;
1437 cache.m_extrapolationCache = extrapCache;
1440 if (
cache.m_extrapolationCache) {
1441 cache.m_detailedElossFlag =
true;
1445 cache.m_propagateWithPathLimit = usePathLimit ? 1 : 0;
1446 cache.m_pathLimit = path;
1449 cache.m_propagateWithPathLimit = 0;
1450 cache.m_pathLimit = -1.;
1454 return propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions, path,
1455 usePathLimit, returnCurv);
1458 magneticFieldProperties, particle, solutions, path, returnCurv);
1465 const EventContext& ctx,
1471 std::optional<Trk::TransportJacobian>& jacobian,
1477 double Jacobian[25];
1483 clearMaterialEffects(
cache);
1486 cache.m_trackingVolume = tVol;
1487 cache.m_material = tVol;
1488 cache.m_matPropOK = tVol !=
nullptr;
1491 cache.m_identifiedParameters =
nullptr;
1492 cache.m_matstates =
nullptr;
1493 cache.m_extrapolationCache =
nullptr;
1494 cache.m_hitVector =
nullptr;
1497 cache.m_matupd_lastpath = 0.;
1498 cache.m_matdump_lastpath = 0.;
1500 std::unique_ptr<Trk::TrackParameters> parameters =
1501 propagateRungeKuttaImpl(
cache,
true, trackParameters, targetSurface, propagationDirection,
1502 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1505 Jacobian[24] = Jacobian[20];
1510 jacobian = std::make_optional<Trk::TransportJacobian>(Jacobian);
1528 double Jacobian[25];
1534 clearMaterialEffects(
cache);
1537 cache.m_trackingVolume = tVol;
1538 cache.m_material = tVol;
1539 cache.m_matPropOK = tVol !=
nullptr;
1542 cache.m_identifiedParameters =
nullptr;
1543 cache.m_matstates =
nullptr;
1544 cache.m_hitVector =
nullptr;
1546 return propagateRungeKuttaImpl(
cache,
false, trackParameters, targetSurface, propagationDirection,
1547 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1554 const EventContext& ctx,
1560 std::optional<Trk::TransportJacobian>& jacobian,
1565 double Jacobian[25];
1572 clearMaterialEffects(
cache);
1575 cache.m_trackingVolume = tVol;
1576 cache.m_material = tVol;
1577 cache.m_matPropOK = tVol !=
nullptr;
1580 cache.m_identifiedParameters =
nullptr;
1581 cache.m_matstates =
nullptr;
1582 cache.m_extrapolationCache =
nullptr;
1583 cache.m_hitVector =
nullptr;
1585 std::unique_ptr<Trk::TrackParameters> parameters =
1586 propagateRungeKuttaImpl(
cache,
true, trackParameters, targetSurface, propagationDirection,
1587 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1590 Jacobian[24] = Jacobian[20];
1595 jacobian = std::make_optional<Trk::TransportJacobian>(Jacobian);
1607 const EventContext& ctx,
1619 clearMaterialEffects(
cache);
1621 cache.m_particle = particle;
1624 cache.m_trackingVolume = tVol;
1625 cache.m_material = tVol;
1626 cache.m_matPropOK = tVol !=
nullptr;
1629 cache.m_identifiedParameters =
nullptr;
1630 cache.m_matstates =
nullptr;
1631 cache.m_extrapolationCache =
nullptr;
1632 cache.m_hitVector =
nullptr;
1638 if (
cache.m_tolerance <= 0.) {
1639 return std::nullopt;
1641 if (
cache.m_momentumCutOff < 0.) {
1642 return std::nullopt;
1644 if (std::abs(1. / trackParameters.parameters()[
Trk::qOverP]) <=
cache.m_momentumCutOff) {
1645 return std::nullopt;
1649 if (
cache.m_matPropOK && ((
cache.m_material->zOverAtimesRho() == 0.) || (
cache.m_material->x0() == 0.) ||
1650 (
cache.m_material->zOverAtimesRho() !=
cache.m_material->zOverAtimesRho()))) {
1651 cache.m_matPropOK =
false;
1656 return std::nullopt;
1665 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1678 if (!propagateWithJacobianImpl(
cache,
false, ty, s,
cache.m_P, path)){
1679 return std::nullopt;
1685 double s[6] = {T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2)};
1686 if (!propagateWithJacobianImpl(
cache,
false, ty, s,
cache.m_P, path)) {
1687 return std::nullopt;
1695 T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2), cyl->
bounds().
r(),
Trk::alongMomentum, 0.};
1696 if (!propagateWithJacobianImpl(
cache,
false, ty, s,
cache.m_P, path)) {
1697 return std::nullopt;
1703 double k =
static_cast<const Trk::ConeSurface*
>(&targetSurface)->bounds().tanAlpha();
1705 double s[9] = {T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2), k,
Trk::alongMomentum, 0.};
1706 if (!propagateWithJacobianImpl(
cache,
false, ty, s,
cache.m_P, path)) {
1707 return std::nullopt;
1713 double s[6] = {T(0, 3), T(1, 3), T(2, 3), 0., 0., 1.};
1714 if (!propagateWithJacobianImpl(
cache,
false, ty, s,
cache.m_P, path)) {
1715 return std::nullopt;
1722 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1735 if (!propagateWithJacobianImpl(
cache,
false, ty, s,
cache.m_P, path)) {
1736 return std::nullopt;
1742 return std::make_optional<Trk::TrackSurfaceIntersection>(globalPosition,
direction, path);
1745std::optional<Trk::TrackSurfaceIntersection>
1758 auto tmpTrackParameters =
1761 std::optional<Trk::TrackSurfaceIntersection> solution =
1763 ?
intersect(ctx, tmpTrackParameters, surface,
1765 :
intersect(ctx, tmpTrackParameters, surface, mft, particle,
nullptr);
1785 clearMaterialEffects(
cache);
1787 cache.m_particle = particle;
1790 cache.m_trackingVolume = tVol;
1791 cache.m_material = tVol;
1792 cache.m_matPropOK = tVol !=
nullptr;
1795 if (
cache.m_matPropOK && ((
cache.m_material->zOverAtimesRho() == 0.) || (
cache.m_material->x0() == 0.) ||
1796 (
cache.m_material->zOverAtimesRho() !=
cache.m_material->zOverAtimesRho()))) {
1797 cache.m_matPropOK =
false;
1803 if (
cache.m_tolerance <= 0.)
1810 double maxPath =
cache.m_maxPath;
1811 double dDir[3] = {0., 0., 0.};
1812 double distanceStepped = 0.;
1813 double BG1[12] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
1815 bool firstStep =
true;
1817 double radius2Max = cylinderBounds.
r() * cylinderBounds.
r();
1819 double radius2 = PP[0] * PP[0] + PP[1] * PP[1];
1820 double direction = PP[0] * PP[3] + PP[1] * PP[4];
1821 double h = maxStepSize;
1824 if ((std::abs(PP[2]) > zMax) || (radius2 > radius2Max))
1829 positionsList.push_back(initialPosition);
1831 bool perigee =
false;
1836 for (
int i = 0; i != 2; ++i) {
1842 double p[7] = {PP[0], PP[1], PP[2], PP[3], PP[4], PP[5], PP[6]};
1844 while (std::abs(path) < maxPath) {
1846 if (!rungeKuttaStep(
cache,
false,
h, p, dDir, BG1, firstStep, distanceStepped))
1848 path = path + distanceStepped;
1851 if (
h > maxStepSize) {
1853 }
else if (
h < -maxStepSize) {
1860 positionsList.push_back(globalPosition);
1862 positionsList.push_front(globalPosition);
1866 radius2 = p[0] * p[0] + p[1] * p[1];
1867 if ((std::abs(p[2]) > zMax) || (radius2 > radius2Max))
1871 if ((p[0] * p[3] + p[1] * p[4]) *
direction < 0.) {
1888 std::vector<unsigned int>& solutions,
double& totalPath,
bool returnCurv)
const {
1890 cache.m_particle = particle;
1892 cache.m_inputThetaVariance = 0.;
1894 std::unique_ptr<Trk::TrackParameters> trackParameters{};
1900 if (
cache.m_tolerance <= 0.)
1902 if (
cache.m_momentumCutOff < 0.)
1906 if (inputTrackParameters.parameters()[
Trk::qOverP] == 0) {
1907 trackParameters = createStraightLine(&inputTrackParameters);
1908 if (!trackParameters) {
1912 trackParameters.reset(inputTrackParameters.
clone());
1915 if (std::abs(1. / trackParameters->parameters()[
Trk::qOverP]) <=
cache.m_momentumCutOff) {
1920 if (
cache.m_matPropOK && ((
cache.m_material->zOverAtimesRho() == 0.) || (
cache.m_material->x0() == 0.) ||
1921 (
cache.m_material->zOverAtimesRho() !=
cache.m_material->zOverAtimesRho()))) {
1922 cache.m_matPropOK =
false;
1925 if (errorPropagation && !trackParameters->covariance()) {
1926 errorPropagation =
false;
1929 if (
cache.m_matPropOK && errorPropagation &&
cache.m_straggling)
1930 cache.m_stragglingVariance = 0.;
1931 cache.m_combinedCovariance.setZero();
1932 cache.m_covariance.setZero();
1934 if (errorPropagation ||
cache.m_matstates) {
1936 cache.m_inputThetaVariance = trackParameters->covariance() ? (*trackParameters->covariance())(3, 3) : 0.;
1937 cache.m_combinedEloss.set(0., 0., 0., 0., 0., 0.);
1938 cache.m_combinedThickness = 0.;
1952 bool validStep =
true;
1954 cache.m_timeOfFlight = 0.;
1957 double Jacobian[21];
1961 propagationDirection, solutions, path, totalPath);
1965 if (propagationDirection * path <= 0.) {
1970 if (
cache.m_propagateWithPathLimit > 1 ||
cache.m_binMat) {
1973 std::unique_ptr<Trk::CurvilinearParameters> cPar =
nullptr;
1975 if (!errorPropagation) {
1976 cPar = std::make_unique<Trk::CurvilinearParameters>(
1982 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
1984 if (
cache.m_matPropOK && (
cache.m_multipleScattering ||
cache.m_straggling) &&
1985 std::abs(totalPath) > 0.) {
1986 covarianceContribution(
cache, trackParameters.get(), totalPath, std::abs(1. /
cache.m_P[6]),
1987 measurementCovariance);
1989 cPar = std::make_unique<Trk::CurvilinearParameters>(
1991 std::move(measurementCovariance));
1995 if (
cache.m_binMat && (
cache.m_matstates || (errorPropagation &&
cache.m_extrapolationCache)) &&
1996 std::abs(totalPath -
cache.m_matdump_lastpath) > 1.) {
2001 if (
cache.m_propagateWithPathLimit > 0)
2002 cache.m_pathLimit -= path;
2006 bool solution =
false;
2007 std::vector<unsigned int> valid_solutions;
2008 valid_solutions.reserve(solutions.size());
2010 std::vector<unsigned int>::iterator iSol = solutions.begin();
2011 while (iSol != solutions.end()) {
2012 if (targetSurfaces[*iSol].first->isOnSurface(gp, targetSurfaces[*iSol].second, 0.001, 0.001)) {
2019 cache.m_P, localp, Jacobian);
2022 valid_solutions.push_back(*iSol);
2026 solutions = std::move(valid_solutions);
2031 if (solutions.empty()) {
2037 double radDist = totalPath /
cache.m_material->x0();
2038 smear(
cache, localp[2], localp[3], trackParameters.get(), radDist);
2041 std::unique_ptr<Trk::TrackParameters> onTargetSurf =
2044 : targetSurfaces[solutions[0]].first->createUniqueTrackParameters(
2045 localp[0], localp[1], localp[2], localp[3], localp[4], std::nullopt);
2047 if (!errorPropagation) {
2050 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4]);
2052 return onTargetSurf;
2057 for (
double i : Jacobian) {
2064 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
2069 if (
cache.m_matPropOK && (
cache.m_multipleScattering ||
cache.m_straggling) && std::abs(totalPath) > 0.) {
2071 covarianceContribution(
cache, trackParameters.get(), totalPath, std::abs(1. /
cache.m_P[6]),
2072 measurementCovariance);
2074 covarianceContribution(
cache, trackParameters.get(), totalPath, onTargetSurf.get(),
2075 measurementCovariance);
2081 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4],
2082 std::move(measurementCovariance));
2086 return targetSurfaces[solutions[0]].first->createUniqueTrackParameters(
2087 localp[0], localp[1], localp[2], localp[3], localp[4], std::move(measurementCovariance));
2095 std::vector<DestSurf>& sfs,
double*
P,
2097 std::vector<unsigned int>& solutions,
double& path,
2098 double sumPath)
const {
2099 double maxPath =
cache.m_maxPath;
2100 double* pos = &
P[0];
2101 double* dir = &
P[3];
2102 double dDir[3] = {0., 0., 0.};
2104 double previousDistance = 0.;
2105 double distanceStepped = 0.;
2106 double BG1[12] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
2108 bool firstStep =
true;
2111 cache.m_timeStep = 0.;
2116 double helpSoft = 1.;
2119 int restartLimit = 10;
2125 cache.m_binMat =
nullptr;
2126 if (
cache.m_trackingVolume &&
cache.m_trackingVolume->isAlignable()) {
2139 double distanceToTarget = propDir * maxPath;
2140 cache.m_currentDist.resize(sfs.size());
2142 int nextSf = sfs.size();
2143 int nextSfCand = nextSf;
2144 std::vector<DestSurf>::iterator sIter = sfs.begin();
2145 std::vector<DestSurf>::iterator sBeg = sfs.begin();
2146 unsigned int numSf = 0;
2147 unsigned int iCurr = 0;
2149 for (; sIter != sfs.end(); ++sIter) {
2151 double distEst = -propDir * maxPath;
2152 double dist1Est = distEst;
2154 distEst = distSol.
first();
2155 dist1Est = distSol.
first();
2157 (std::abs(distEst) < tol || (propDir * distEst < -tol && propDir * distSol.
second() > tol)))
2158 distEst = distSol.
second();
2163 if (distEst * propDir > -tol) {
2165 cache.m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2166 0, std::pair<double, double>(distEst, distSol.
currentDistance(
true)));
2168 cache.m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2169 1, std::pair<double, double>(distEst, distSol.
currentDistance(
true)));
2171 if (tol < propDir * distEst && propDir * distEst < propDir * distanceToTarget) {
2172 distanceToTarget = distEst;
2178 cache.m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2181 if (std::abs(dist1Est) < tol)
2182 startSf = (int)iCurr;
2186 if (distanceToTarget == maxPath || numSf == 0)
2190 std::vector<std::pair<int, std::pair<double, double>>>
::iterator vsBeg =
cache.m_currentDist.begin();
2191 std::vector<std::pair<int, std::pair<double, double>>>
::iterator vsEnd =
cache.m_currentDist.end();
2192 const int num_vs_dist =
cache.m_currentDist.size();
2196 double absPath = 0.;
2197 distanceToTarget > 100. ?
h = 100. : distanceToTarget < -100. ?
h = -100. :
h = distanceToTarget;
2201 if (
cache.m_binMat) {
2207 if (dist2next.first < lbu->
bins() && std::abs(dist2next.second) > 1. &&
2208 std::abs(dist2next.second) < std::abs(
h)) {
2209 h = dist2next.second * propDir;
2212 cache.m_material = binIDMat->first.get();
2220 double distanceTolerance = std::min(std::max(std::abs(distanceToTarget) *
cache.m_tolerance, 1e-6), 1e-2);
2224 mom = std::abs(1. /
P[6]);
2228 while (numSf > 0 && (std::abs(distanceToTarget) > distanceTolerance ||
2229 std::abs(path + distanceStepped) < tol)) {
2231 if (!rungeKuttaStep(
cache, errorPropagation,
h,
P, dDir, BG1, firstStep, distanceStepped)) {
2241 for (
int i = 0; i < 3; ++i)
2247 path = path + distanceStepped;
2249 mom = std::abs(1. /
P[6]);
2250 beta = mom / std::sqrt(mom * mom +
cache.m_particleMass *
cache.m_particleMass);
2251 cache.m_timeStep += distanceStepped / beta / Gaudi::Units::c_light;
2253 if (std::abs(distanceStepped) > 0.001) {
2254 cache.m_sigmaIoni =
cache.m_sigmaIoni -
cache.m_kazL * log(std::abs(distanceStepped));
2257 if (errorPropagation &&
cache.m_straggling) {
2261 double bp2 = beta * mom * mom;
2262 cache.m_stragglingVariance += sigTot2 / (bp2 * bp2) * distanceStepped * distanceStepped;
2264 if (
cache.m_matstates || errorPropagation) {
2265 cache.m_combinedEloss.update(
2266 cache.m_delIoni * distanceStepped,
cache.m_sigmaIoni * std::abs(distanceStepped),
2267 cache.m_delRad * distanceStepped,
cache.m_sigmaRad * std::abs(distanceStepped),
cache.m_MPV);
2269 if (
cache.m_material &&
cache.m_material->x0() != 0.) {
2270 cache.m_combinedThickness += propDir * distanceStepped /
cache.m_material->x0();
2275 path = path + distanceStepped;
2276 absPath += std::abs(distanceStepped);
2279 mom = std::abs(1. /
P[6]);
2280 beta = mom / std::sqrt(mom * mom +
cache.m_particleMass *
cache.m_particleMass);
2281 cache.m_timeStep += distanceStepped / beta / Gaudi::Units::c_light;
2283 if (std::abs(distanceStepped) > 0.001)
2284 cache.m_sigmaIoni =
cache.m_sigmaIoni -
cache.m_kazL * log(std::abs(distanceStepped));
2286 if (errorPropagation &&
cache.m_straggling) {
2290 double bp2 = beta * mom * mom;
2291 cache.m_stragglingVariance += sigTot2 / (bp2 * bp2) * distanceStepped * distanceStepped;
2293 if (
cache.m_matstates || errorPropagation) {
2294 cache.m_combinedEloss.update(
2295 cache.m_delIoni * distanceStepped,
cache.m_sigmaIoni * std::abs(distanceStepped),
2296 cache.m_delRad * distanceStepped,
cache.m_sigmaRad * std::abs(distanceStepped),
cache.m_MPV);
2298 if (
cache.m_material &&
cache.m_material->x0() != 0.) {
2299 cache.m_combinedThickness += propDir * distanceStepped /
cache.m_material->x0();
2302 if (absPath > maxPath)
2306 if (
cache.m_propagateWithPathLimit > 0 &&
cache.m_pathLimit <= path) {
2307 ++
cache.m_propagateWithPathLimit;
2311 bool restart =
false;
2313 if (propDir * path < -tol || absPath - std::abs(path) > 10.) {
2314 helpSoft = std::abs(path) / absPath > 0.5 ? std::abs(path) / absPath : 0.5;
2321 float distanceToNextBin =
h;
2322 if (
cache.m_binMat) {
2328 distanceToNextBin = dist2next.second;
2329 if (layerBin !=
cache.m_currentLayerBin) {
2332 float stepOver = dist2previous.second;
2335 auto cPar = std::make_unique<Trk::CurvilinearParameters>(
Amg::Vector3D(
P[0],
P[1],
P[2]), localp[2],
2336 localp[3], localp[4]);
2337 if (
cache.m_identifiedParameters) {
2338 if (binIDMat && binIDMat->second > 0 && !iMat) {
2339 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2340 }
else if (binIDMat && binIDMat->second > 0 &&
2341 (iMat->second == 0 || iMat->second == binIDMat->second)) {
2342 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2343 }
else if (iMat && iMat->second > 0) {
2344 cache.m_identifiedParameters->emplace_back(cPar->clone(), iMat->second);
2347 if (
cache.m_hitVector) {
2348 double hitTiming =
cache.m_timeIn +
cache.m_timeOfFlight +
cache.m_timeStep;
2349 if (binIDMat && binIDMat->second > 0 && !iMat) {
2350 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2351 }
else if (binIDMat && binIDMat->second > 0 &&
2352 (iMat->second == 0 || iMat->second == binIDMat->second)) {
2353 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2354 }
else if (iMat && iMat->second > 0) {
2355 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, iMat->second, 0.);
2359 cache.m_currentLayerBin = layerBin;
2367 if (
cache.m_material) {
2368 updateMaterialEffects(
cache, mom, sin(
direction.theta()), sumPath + path - stepOver);
2370 cache.m_material = binIDMat->first.get();
2373 if (distanceToNextBin <
h) {
2376 distanceToNextBin += d2n.second +
h;
2378 }
else if (dist2next.first < lbu->
bins() && std::abs(distanceToNextBin) < 0.01 &&
2382 auto cPar = std::make_unique<Trk::CurvilinearParameters>(
Amg::Vector3D(
P[0],
P[1],
P[2]), localp[2],
2383 localp[3], localp[4]);
2388 nextMat =
cache.m_binMat->material(probe);
2390 if (
cache.m_identifiedParameters) {
2391 if (binIDMat && binIDMat->second > 0 && !nextMat) {
2392 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2393 }
else if (binIDMat && binIDMat->second > 0 &&
2394 (nextMat->second == 0 || nextMat->second == binIDMat->second)) {
2396 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2397 }
else if (nextMat && nextMat->second > 0) {
2398 cache.m_identifiedParameters->emplace_back(cPar->clone(), nextMat->second);
2401 if (
cache.m_hitVector) {
2402 double hitTiming =
cache.m_timeIn +
cache.m_timeOfFlight +
cache.m_timeStep;
2403 if (binIDMat && binIDMat->second > 0 && !nextMat) {
2404 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2405 }
else if (binIDMat && binIDMat->second > 0 &&
2406 (nextMat->second == 0 ||
2407 nextMat->second == binIDMat->second)) {
2408 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2409 }
else if (nextMat && nextMat->second > 0) {
2410 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, nextMat->second, 0.);
2414 cache.m_currentLayerBin = dist2next.first;
2415 if (binIDMat != nextMat) {
2418 assert(
cache.m_material);
2419 updateMaterialEffects(
cache, mom, sin(
direction.theta()), sumPath + path);
2420 cache.m_material = binIDMat->first.get();
2425 distanceToNextBin += d2n.second + 0.01;
2433 bool flipDirection =
false;
2435 nextSfCand = nextSf;
2437 std::vector<DestSurf>::iterator sIter = sBeg;
2438 std::vector<std::pair<int, std::pair<double, double>>>
::iterator vsIter = vsBeg;
2448 cache.m_bremEmitThreshold = 0.;
2450 if (mom <
cache.m_bremSampleThreshold)
2454 for (; vsIter != vsEnd; ++vsIter) {
2457 if (numRestart > restartLimit)
2463 distanceToTarget = propDir * maxPath;
2469 if ((*vsIter).first != -1 &&
2470 (ic == nextSf || (*vsIter).first == 1 || nextSf < 0 || std::abs((*vsIter).second.first) < 500. ||
2471 std::abs(path) > 0.5 * std::abs((*vsIter).second.second))) {
2472 previousDistance = (*vsIter).second.first;
2475 double distanceEst = -propDir * maxPath;
2477 distanceEst = distSol.
first();
2479 std::abs(distSol.
first() * propDir + distanceStepped - previousDistance) >
2480 std::abs(distSol.
second() * propDir + distanceStepped - previousDistance)) {
2481 distanceEst = distSol.
second();
2488 if (ic == startSf && distanceEst < 0 && distSol.
first() > 0)
2489 distanceEst = distSol.
first();
2492 if (ic == nextSf && std::abs(distanceEst) < tol && std::abs(path) < tol) {
2493 (*vsIter).first = -1;
2496 distanceToTarget = maxPath;
2504 if ((*vsIter).second.first * propDir * distanceEst < 0. &&
2505 std::abs(distanceEst) > distanceTolerance) {
2509 std::abs((*vsIter).second.second) < tol ||
2512 ((*vsIter).first)++;
2514 if ((*vsIter).first > 3) {
2515 helpSoft = fmax(0.05, 1. - 0.05 * (*vsIter).first);
2516 if ((*vsIter).first > 20)
2517 helpSoft = 1. / (*vsIter).first;
2520 if ((*vsIter).first > 50 &&
h * propDir > 0) {
2522 (*vsIter).first = -1;
2527 if ((*vsIter).first != -1)
2528 flipDirection =
true;
2529 }
else if (std::abs((*vsIter).second.second) > tol &&
2532 if (ic > nextSf && nextSf != -1) {
2533 if (propDir * distanceEst < (
cache.m_currentDist.at(nextSf)).second.first - tol) {
2534 if ((*vsIter).first != -1) {
2535 ((*vsIter).first)++;
2536 flipDirection =
true;
2540 }
else if (distanceToTarget >
2542 if ((*vsIter).first != -1) {
2543 ((*vsIter).first)++;
2544 flipDirection =
true;
2549 }
else if (ic == nextSf) {
2557 (*vsIter).second.first = propDir * distanceEst;
2563 if ((*vsIter).first != -1 && (distanceEst > 0. || ic == nextSf)) {
2565 if (distanceEst < std::abs(distanceToTarget)) {
2566 distanceToTarget = propDir * distanceEst;
2570 }
else if (std::abs(path) > std::abs((*vsIter).second.second) || dev < 0.985 ||
2574 double distanceEst = -propDir * maxPath;
2576 distanceEst = distSol.
first();
2579 (*vsIter).second.first = propDir * distanceEst;
2582 if (distanceEst > tol && distanceEst < maxPath) {
2583 (*vsIter).first = 0;
2587 if ((*vsIter).first != -1 && distanceEst > 0.) {
2589 if (distanceEst < std::abs(distanceToTarget)) {
2590 distanceToTarget = propDir * distanceEst;
2598 if (std::abs(distanceToTarget) <= distanceTolerance && path * propDir < distanceTolerance) {
2599 (*vsIter).first = -1;
2608 if (nextSf < 0 && nextSfCand < 0)
2611 if (flipDirection) {
2613 if (nextSf < 0 || nextSf >= num_vs_dist)
2615 distanceToTarget = (*(vsBeg + nextSf)).second.first;
2617 }
else if (nextSfCand != nextSf) {
2618 nextSf = nextSfCand;
2620 if (nextSf < 0 || nextSf >= num_vs_dist)
2622 if (
cache.m_currentDist[nextSf].first < 3)
2627 if (std::abs(
h) > std::abs(distanceToTarget))
2628 h = distanceToTarget;
2631 if (
cache.m_binMat && std::abs(
h) > std::abs(distanceToNextBin) + 0.001) {
2632 if (distanceToNextBin > 0) {
2633 h = distanceToNextBin * propDir;
2641 if (
cache.m_propagateWithPathLimit > 0 &&
h >
cache.m_pathLimit)
2642 h =
cache.m_pathLimit + tol;
2645 if (std::abs(path) > maxPath)
2648 if (steps++ >
cache.m_maxSteps)
2656 path = path + distanceToTarget;
2659 mom = std::abs(1. /
P[6]);
2660 beta = mom / std::sqrt(mom * mom +
cache.m_particleMass *
cache.m_particleMass);
2661 cache.m_timeStep += distanceToTarget / beta / Gaudi::Units::c_light;
2664 pos[0] = pos[0] + distanceToTarget * (dir[0] + 0.5 * distanceToTarget * dDir[0]);
2665 pos[1] = pos[1] + distanceToTarget * (dir[1] + 0.5 * distanceToTarget * dDir[1]);
2666 pos[2] = pos[2] + distanceToTarget * (dir[2] + 0.5 * distanceToTarget * dDir[2]);
2669 dir[0] = dir[0] + distanceToTarget * dDir[0];
2670 dir[1] = dir[1] + distanceToTarget * dDir[1];
2671 dir[2] = dir[2] + distanceToTarget * dDir[2];
2674 double norm = 1. / std::sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
2675 dir[0] = norm * dir[0];
2676 dir[1] = norm * dir[1];
2677 dir[2] = norm * dir[2];
2683 std::vector<std::pair<int, std::pair<double, double>>>
::iterator vsIter = vsBeg;
2686 for (; vsIter != vsEnd; ++vsIter) {
2687 if ((*vsIter).first != -1 && propDir * (*vsIter).second.first >= propDir * distanceToTarget - tol &&
2688 propDir * (*vsIter).second.first < 0.01 &&
index != nextSf) {
2689 solutions.push_back(
index);
2691 if (
index == nextSf)
2692 solutions.push_back(
index);
2703 double path)
const {
2706 double mom = parms->
momentum().mag();
2709 updateMaterialEffects(
cache, mom, sin(parms->
momentum().theta()), path);
2711 if (
cache.m_extrapolationCache) {
2712 cache.m_extrapolationCache->updateX0(
cache.m_combinedThickness);
2713 cache.m_extrapolationCache->updateEloss(
2714 cache.m_combinedEloss.meanIoni(),
cache.m_combinedEloss.sigmaIoni(),
cache.m_combinedEloss.meanRad(),
2715 cache.m_combinedEloss.sigmaRad());
2718 if (
cache.m_matstates) {
2720 ? std::make_unique<Trk::EnergyLoss>(
cache.m_combinedEloss.deltaE(),
2721 cache.m_combinedEloss.sigmaDeltaE())
2722 : std::make_unique<Trk::EnergyLoss>(
2723 cache.m_combinedEloss.deltaE(),
cache.m_combinedEloss.sigmaDeltaE(),
2724 cache.m_combinedEloss.sigmaDeltaE(),
cache.m_combinedEloss.sigmaDeltaE(),
2725 cache.m_combinedEloss.meanIoni(),
cache.m_combinedEloss.sigmaIoni(),
2726 cache.m_combinedEloss.meanRad(),
cache.m_combinedEloss.sigmaRad(), path);
2729 std::sqrt(
cache.m_covariance(3, 3)));
2732 auto mefot = std::make_unique<Trk::MaterialEffectsOnTrack>(
cache.m_combinedThickness, sa,
2733 std::move(eloss), cvlTP->associatedSurface());
2738 cache.m_matdump_lastpath = path;
2741 cache.m_combinedCovariance +=
cache.m_covariance;
2742 cache.m_covariance.setZero();
2743 cache.m_combinedThickness = 0.;
2744 cache.m_combinedEloss.set(0., 0., 0., 0., 0., 0.);
2750 double radDist)
const {
2756 if (!
cache.m_randomEngine) {
2763 double momentum = parms->
momentum().mag();
2764 double energy = std::sqrt(momentum * momentum + particleMass * particleMass);
2765 double beta = momentum / energy;
2766 double th = std::sqrt(2.) * 15. * std::sqrt(radDist) / (beta * momentum) *
2767 CLHEP::RandGauss::shoot(
cache.m_randomEngine);
2772 double ph = 2. *
M_PI * CLHEP::RandFlat::shoot(
cache.m_randomEngine);
2780 theta = rotated.theta();
2781 phi = rotated.phi();
2787 if (!
cache.m_randomEngine) {
2790 double rndx = CLHEP::RandFlat::shoot(
cache.m_randomEngine);
2791 double rnde = CLHEP::RandFlat::shoot(
cache.m_randomEngine);
2794 double eps =
cache.m_momentumCutOff / mom;
2795 cache.m_bremMom = pow(eps, pow(rndx, exp(1.))) * mom;
2796 cache.m_bremSampleThreshold = mom -
cache.m_bremMom;
2797 cache.m_bremEmitThreshold = mom - rnde *
cache.m_bremMom;
2803 if (fieldCondObj ==
nullptr) {
2804 ATH_MSG_ERROR(
"extrapolate: Failed to retrieve AtlasFieldCacheCondObj with key "
2811CLHEP::HepRandomEngine*
2821 wrapper_nc->setSeed (this->name(), ctx);
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
double charge(const T &p)
#define AmgSymMatrix(dim)
std::vector< FPGATrackSimHit > hitVector
#define ATLAS_THREAD_SAFE
A wrapper class for event-slot-local random engines.
Header file for AthHistogramAlgorithm.
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
Base Class for a navigation object (active) in the Calo realm.
const BinnedMaterial * binnedMaterial() const
access to binned material
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
size_t bins(size_t ba=0) const
Number of bins.
std::pair< size_t, float > distanceToNext(const Amg::Vector3D &position, const Amg::Vector3D &direction, size_t ba=0) const
Distance estimate to next bin.
The BoundaryCheck class allows to steer the way surface boundaries are used for inside/outside checks...
Class for a conical surface in the ATLAS detector.
Bounds for a cylindrical Surface.
virtual double r() const override final
This method returns the radius.
double halflengthZ() const
This method returns the halflengthZ.
Class for a CylinderSurface in the ATLAS detector.
virtual const CylinderBounds & bounds() const override final
This method returns the CylinderBounds by reference (NoBounds is not possible for cylinder).
Access to distance solutions.
double second() const
Distance to second intersection solution along direction (for a cylinder surface).
double currentDistance(bool signedDist=false) const
Current distance to surface (spatial), signed (along/opposite to surface normal) if input argument tr...
int numberOfSolutions() const
Number of intersection solutions.
bool signedDistance() const
This method indicates availability of signed current distance (false for Perigee and StraighLineSurfa...
double first() const
Distance to first intersection solution along direction.
magnetic field properties to steer the behavior of the extrapolation
MagneticFieldMode magneticFieldMode() const
Returns the MagneticFieldMode as specified.
const Amg::Vector3D & momentum() const
Access method for the momentum.
virtual ParametersBase< DIM, T > * clone() const override=0
clone method for polymorphic deep copy
const Amg::Vector3D & position() const
Access method for the position.
double charge() const
Returns the charge.
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
Class describing the Line to which the Perigee refers to.
void smear(Cache &cache, double &phi, double &theta, const Trk::TrackParameters *parms, double radDist) const
ToolHandle< ITimedMatEffUpdator > m_simMatUpdator
secondary interactions (brem photon emission)
virtual std::unique_ptr< Trk::NeutralParameters > propagate(const Trk::NeutralParameters &, const Trk::Surface &, Trk::PropDirection, const Trk::BoundaryCheck &, bool rC=false) const override final
Main propagation method NeutralParameters.
void dumpMaterialEffects(Cache &cache, const Trk::CurvilinearParameters *trackParameters, double path) const
virtual std::optional< TrackSurfaceIntersection > intersectSurface(const EventContext &ctx, const Surface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP, const MagneticFieldProperties &mft, ParticleHypothesis particle) const override final
Intersection and propagation:
virtual StatusCode finalize() override final
AlgTool finalize method.
BooleanProperty m_detailedEloss
virtual StatusCode initialize() override final
AlgTool initialize method.
STEP_Propagator(const std::string &, const std::string &, const IInterface *)
virtual std::unique_ptr< Trk::TrackParameters > propagateT(const EventContext &ctx, const Trk::TrackParameters &trackParameters, std::vector< Trk::DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, Trk::PathLimit &path, Trk::TimeLimit &time, bool returnCurv, const Trk::TrackingVolume *tVol, std::vector< Trk::HitInfo > *&hitVector) const override final
Propagate parameters and covariance with search of closest surface time included.
BooleanProperty m_materialEffects
BooleanProperty m_simulation
StringProperty m_randomEngineName
virtual std::unique_ptr< Trk::TrackParameters > propagateParameters(const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, Trk::PropDirection propagationDirection, const Trk::BoundaryCheck &boundaryCheck, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr) const override final
Propagate parameters only.
void setCacheFromProperties(Cache &cache) const
initialize cache with the variables we need to take from
virtual ~STEP_Propagator()
std::unique_ptr< Trk::TrackParameters > propagateRungeKutta(Cache &cache, bool errorPropagation, const Trk::TrackParameters &trackParameters, std::vector< DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, double &path, bool returnCurv=false) const
BooleanProperty m_multipleScattering
BooleanProperty m_straggling
CLHEP::HepRandomEngine * getRandomEngine(const EventContext &ctx) const
DoubleProperty m_momentumCutOff
void sampleBrem(Cache &cache, double mom) const
virtual std::optional< TrackSurfaceIntersection > intersect(const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, const Trk::MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, const Trk::TrackingVolume *tVol=nullptr) const override final
Propagate parameters and return path (Similar to propagateParameters.
ServiceHandle< IAthRNGSvc > m_rndGenSvc
Random Generator service.
void getFieldCacheObject(Cache &cache, const EventContext &ctx) const
virtual std::unique_ptr< Trk::TrackParameters > propagateM(const EventContext &ctx, const Trk::TrackParameters &trackParameters, std::vector< Trk::DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, std::vector< const Trk::TrackStateOnSurface * > *matstates, std::vector< std::pair< std::unique_ptr< Trk::TrackParameters >, int > > *intersections, double &path, bool usePathLimit=false, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr, Trk::ExtrapolationCache *=nullptr) const override final
Propagate parameters and covariance with search of closest surface and material collection.
bool propagateWithJacobian(Cache &cache, bool errorPropagation, std::vector< DestSurf > &sfs, double *P, Trk::PropDirection propDir, std::vector< unsigned int > &solutions, double &path, double sumPath) const
ATHRNG::RNGWrapper * m_rngWrapper
Random engine.
BooleanProperty m_energyLoss
virtual void globalPositions(const EventContext &ctx, std::deque< Amg::Vector3D > &positionsList, const TrackParameters &trackParameters, const MagneticFieldProperties &magneticFieldProperties, const CylinderBounds &cylinderBounds, double maxStepSize, ParticleHypothesis particle, const Trk::TrackingVolume *tVol=0) const override final
Return a list of positions along the track.
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
represents a deflection of the track caused through multiple scattering in material.
Abstract Base Class for tracking surfaces.
virtual ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - charged.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
virtual bool isOnSurface(const Amg::Vector3D &glopo, const BoundaryCheck &bchk=true, double tol1=0., double tol2=0.) const
This method returns true if the GlobalPosition is on the Surface for both, within or without check of...
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
represents the track state (measurement, material, fit parameters and quality) at a surface.
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Eigen::AngleAxisd AngleAxis3D
bool saneVector(const AmgVector(N) &vec)
Eigen::Affine3d Transform3D
bool saneCovarianceElement(double ele)
A covariance matrix formally needs to be positive semi definite.
Eigen::Matrix< double, 2, 1 > Vector2D
bool hasPositiveOrZeroDiagElems(const AmgSymMatrix(N) &mat)
Returns true if all diagonal elements of the covariance matrix are finite aka sane in the above defin...
Eigen::Matrix< double, 3, 1 > Vector3D
double R(const INavigable4Momentum *p1, const double v_eta, const double v_phi)
l
Printing final latex table to .tex output file.
Trk::RungeKuttaUtils is set algorithms for track parameters transformation from local to global and g...
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
void transformGlobalToCurvilinear(bool, double *ATH_RESTRICT, double *ATH_RESTRICT, double *ATH_RESTRICT)
bool transformLocalToGlobal(bool, const Trk::TrackParameters &, double *ATH_RESTRICT)
void transformGlobalToLocal(double *ATH_RESTRICT, double *ATH_RESTRICT)
void jacobianTransformCurvilinearToLocal(const Trk::TrackParameters &, double *ATH_RESTRICT)
double stepEstimator(int kind, double *ATH_RESTRICT Su, const double *ATH_RESTRICT P, bool &Q)
Ensure that the ATLAS eigen extensions are properly loaded.
PropDirection
PropDirection, enum for direction of the propagation.
SurfaceType
This enumerator simplifies the persistency & calculations,.
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
const Amg::Vector3D & direction() const
Method to retrieve the direction at the Intersection.
ParametersBase< NeutralParametersDim, Neutral > NeutralParameters
CurvilinearParametersT< TrackParametersDim, Charged, PlaneSurface > CurvilinearParameters
@ FastField
call the fast field access method of the FieldSvc
@ NoField
Field is set to 0., 0., 0.,.
TrackSurfaceIntersection(const Amg::Vector3D &pos, const Amg::Vector3D &dir, double path)
Constructor.
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
std::pair< std::shared_ptr< Material >, int > IdentifiedMaterial
const Amg::Vector3D & position() const
Method to retrieve the position of the Intersection.
ParametersBase< TrackParametersDim, Charged > TrackParameters
const IIntersectionCache * cache() const
Retrieve the associated cache block, if it exists.
path
python interpreter configuration --------------------------------------—
static double dEdl_ionization(double p, const Material &mat, ParticleHypothesis particle, double &sigma, double &kazL)
dE/dl ionization energy loss per path unit
static double dEdl_radiation(double p, const Material &mat, ParticleHypothesis particle, double &sigma)
dE/dl radiation energy loss per path unit
void updateMat(float dX0, float Z, float dL0)
collected material update
stuct to pass information to the heavy lifting calculation internal methods