35 #include "CLHEP/Random/RandFlat.h"
36 #include "CLHEP/Random/RandGauss.h"
37 #include "GaudiKernel/PhysicalConstants.h"
63 if (cache.m_solenoid) {
66 cache.m_fieldCache.getField(
R,
H);
73 if (cache.m_solenoid) {
74 cache.m_fieldCache.getFieldZR(
R,
H, dH);
76 cache.m_fieldCache.getField(
R,
H, dH);
88 getMagneticField(Cache& cache,
93 constexpr
double magScale = 10000.;
94 const double*
R = position.data();
99 cache.m_includeBgradients) {
101 getFieldGradient(cache,
R,
H, dH);
102 BG[0] =
H[0] * magScale;
103 BG[1] =
H[1] * magScale;
104 BG[2] =
H[2] * magScale;
105 BG[3] = dH[0] * magScale;
106 BG[4] = dH[1] * magScale;
107 BG[5] = dH[2] * magScale;
108 BG[6] = dH[3] * magScale;
109 BG[7] = dH[4] * magScale;
110 BG[8] = dH[5] * magScale;
111 BG[9] = dH[6] * magScale;
112 BG[10] = dH[7] * magScale;
113 BG[11] = dH[8] * magScale;
117 getField(cache,
R,
H);
118 BG[0] =
H[0] * magScale;
119 BG[1] =
H[1] * magScale;
120 BG[2] =
H[2] * magScale;
122 for (
int i = 3;
i < 12; ++
i) {
132 std::unique_ptr<Trk::TrackParameters>
135 AmgVector(5) lp = inputTrackParameters->parameters();
139 return std::make_unique<Trk::CurvilinearParameters>(
144 (inputTrackParameters->covariance() ? std::optional<
AmgSymMatrix(5)>(*inputTrackParameters->covariance())
153 (inputTrackParameters->covariance() ? std::optional<
AmgSymMatrix(5)>(*inputTrackParameters->covariance())
157 std::unique_ptr<Trk::TrackParameters>
159 std::vector<Trk::DestSurf>& targetSurfaces,
161 std::vector<unsigned int>& solutions,
170 std::vector<std::pair<unsigned int, double>> currentDist;
172 std::vector<std::pair<const Trk::Surface*, Trk::BoundaryCheck>>
::iterator sIter = targetSurfaces.begin();
173 std::vector<std::pair<unsigned int, double>>
::iterator oIter = currentDist.begin();
179 for (; sIter != targetSurfaces.end(); ++sIter) {
182 unsigned int numSf = sIter - sBeg;
183 if (distSol.
first() > tol) {
184 if (!currentDist.empty()) {
185 oIter = currentDist.end();
186 while (oIter != currentDist.begin() && distSol.
first() < (*(oIter - 1)).second)
188 oIter = currentDist.insert(oIter, std::pair<unsigned int, double>(numSf, distSol.
first()));
190 currentDist.emplace_back(numSf, distSol.
first());
194 if (!currentDist.empty()) {
195 oIter = currentDist.end();
196 while (oIter != currentDist.begin() && distSol.
second() < (*(oIter - 1)).second)
198 oIter = currentDist.insert(oIter, std::pair<unsigned int, double>(numSf, distSol.
second()));
200 currentDist.emplace_back(numSf, distSol.
second());
207 for (oIter = currentDist.begin(); oIter != currentDist.end(); ++oIter) {
208 Amg::Vector3D xsct = position + propDir * direction * ((*oIter).second);
209 if (targetSurfaces[(*oIter).first].first->isOnSurface(xsct, (*oIter).second, 0.001, 0.001)) {
210 if (usePathLimit &&
path > 0. &&
path < ((*oIter).second)) {
212 return std::make_unique<Trk::CurvilinearParameters>(endpoint, parm.
momentum(), parm.
charge());
214 path = (*oIter).second;
215 solutions.push_back((*oIter).first);
219 return std::make_unique<Trk::CurvilinearParameters>(xsct, parm.
momentum(), parm.
charge());
221 return sf->createUniqueTrackParameters(xsct, parm.
momentum(), parm.
charge(), std::nullopt);
241 dEds(Cache& cache,
double p)
243 cache.m_delIoni = 0.;
249 if (cache.m_material->x0() == 0 || cache.m_material->averageZ() == 0)
257 double eLoss = cache.m_MPV ? 0.9 * cache.m_delIoni + 0.15 * cache.m_delRad : cache.m_delIoni + cache.m_delRad;
267 dgdlambda(Cache& cache,
double l)
271 if (cache.m_material->x0() == 0 || cache.m_material->averageZ() == 0)
273 if (cache.m_material->zOverAtimesRho() == 0)
276 double p = std::abs(1. /
l);
279 double E = std::sqrt(
p *
p +
m *
m);
282 double I = 16.e-6 *
std::pow(cache.m_material->averageZ(), 0.9);
283 double kaz = 0.5 * 30.7075 * cache.m_material->zOverAtimesRho();
286 double lnCore = 4. * me * me / (
m *
m *
m *
m *
I *
I *
l *
l *
l *
l) / (1. + 2. *
gamma * me /
m + me * me /
m *
m);
287 double lnCore_deriv =
288 -4. * me * me / (
m *
m *
m *
m *
I *
I) *
291 4. *
l *
l *
l * me * me / (
m *
m));
292 double ln_deriv = 2. *
l *
m *
m *
std::log(lnCore) + lnCore_deriv / (lnCore *
beta *
beta);
293 double Bethe_Bloch_deriv = -kaz * ln_deriv;
297 double delta = 2. *
std::log(28.816
e-6 * std::sqrt(1000. * cache.m_material->zOverAtimesRho()) /
I) +
299 double delta_deriv = -2. / (
l *
beta *
beta) + 2. * delta *
l *
m *
m;
300 Bethe_Bloch_deriv += kaz * delta_deriv;
304 double Bethe_Heitler_deriv = me * me / (
m *
m * cache.m_material->x0() *
l *
l *
l *
E);
307 double radiative_deriv = 0.;
308 if ((cache.m_particle ==
Trk::muon) && (
E > 8000.)) {
310 radiative_deriv = 6.803e-5 / (cache.m_material->x0() *
l *
l *
l *
E) +
311 2. * 2.278
e-11 / (cache.m_material->x0() *
l *
l *
l) -
312 3. * 9.899
e-18 *
E / (cache.m_material->x0() *
l *
l *
l);
314 radiative_deriv = 9.253e-5 / (cache.m_material->x0() *
l *
l *
l *
E);
320 return 0.9 * Bethe_Bloch_deriv + 0.15 * Bethe_Heitler_deriv + 0.15 * radiative_deriv;
322 return Bethe_Bloch_deriv + Bethe_Heitler_deriv + radiative_deriv;
330 updateMaterialEffects(Cache& cache,
double mom,
double sinTheta,
double path)
335 if (cache.m_straggling) {
336 cache.m_covariance(4, 4) += cache.m_stragglingVariance;
337 cache.m_stragglingVariance = 0.;
340 if (!cache.m_multipleScattering)
343 double totalMomentumLoss =
mom - cache.m_matupd_lastmom;
344 double pathSinceLastUpdate =
path - cache.m_matupd_lastpath;
346 double pathAbs = std::abs(pathSinceLastUpdate);
348 if (pathAbs < 1.
e-03)
351 double matX0 = cache.m_material->x0();
354 int msLayers =
int(pathAbs / cache.m_layXmax / matX0) + 1;
357 double layerThickness = pathAbs / msLayers;
358 double radiationLengths = layerThickness / matX0;
360 double remainingPath = pathAbs;
365 double dLambdads = 0.;
366 double thetaVariance = 0.;
368 double average_dEds = totalMomentumLoss / pathAbs;
370 double cumulatedVariance = cache.m_inputThetaVariance + cache.m_combinedCovariance(3, 3) + cache.m_covariance(3, 3);
371 if (cumulatedVariance < 0) {
372 cumulatedVariance = 0;
374 double cumulatedX0 = 0.;
376 bool useCache = cache.m_extrapolationCache !=
nullptr;
378 double dX0 = std::abs(cache.m_combinedThickness) - pathAbs / matX0;
381 if (cache.m_extrapolationCache->x0tot() > 0)
382 cumulatedX0 = cache.m_extrapolationCache->x0tot() + dX0;
389 momentum = cache.m_matupd_lastmom + totalMomentumLoss * (
layer - 0.5) / msLayers;
392 E = std::sqrt(mom2 + massSquared);
395 double C0 = 13.6 * 13.6 / mom2 /
beta /
beta;
396 double C1 = 2 * 0.038 * C0;
397 double C2 = 0.038 * 0.038 * C0;
399 double MS2 = radiationLengths;
402 remainingPath -= layerThickness;
409 cumulatedX0 = cumulatedVariance / C0;
410 if (cumulatedX0 > 0.001) {
411 double lX0 =
log(cumulatedX0);
412 cumulatedX0 = cumulatedX0 / (1 + 2 * 0.038 * lX0 + 0.038 * 0.038 * lX0 * lX0);
416 double MS2s = MS2 + cumulatedX0;
417 thetaVariance = C0 * MS2 + C1 * MS2s *
log(MS2s) + C2 * MS2s *
log(MS2s) *
log(MS2s);
419 if (cumulatedX0 > 0.001) {
420 double lX0 =
log(cumulatedX0);
421 thetaVariance += -C1 * cumulatedX0 * lX0 - C2 * cumulatedX0 * lX0 * lX0;
425 double varScale = cache.m_scatteringScale * cache.m_scatteringScale;
426 double positionVariance = thetaVariance * (layerThickness * layerThickness / 3. + remainingPath * layerThickness +
427 remainingPath * remainingPath);
428 cache.m_covariance(0, 0) += varScale * positionVariance;
429 cache.m_covariance(1, 1) += varScale * positionVariance;
430 cache.m_covariance.fillSymmetric(
431 2, 0, cache.m_covariance(2, 0) + varScale * thetaVariance / (sinTheta) * (layerThickness / 2. + remainingPath));
432 cache.m_covariance(2, 2) += varScale * thetaVariance / (sinTheta * sinTheta);
433 cache.m_covariance.fillSymmetric(
434 3, 1, cache.m_covariance(3, 1) + varScale * thetaVariance * (-layerThickness / 2. - remainingPath));
435 cache.m_covariance(3, 3) += varScale * thetaVariance;
436 cache.m_covariance(4, 4) +=
437 varScale * 3. * thetaVariance * thetaVariance * layerThickness * layerThickness * dLambdads * dLambdads;
438 cumulatedVariance += varScale * thetaVariance;
442 cache.m_matupd_lastmom =
mom;
443 cache.m_matupd_lastpath =
path;
451 covarianceContribution(Cache& cache,
458 double finalMomentum = targetParms->
momentum().mag();
461 updateMaterialEffects(cache, finalMomentum,
sin(trackParameters->
momentum().theta()),
path);
468 Trk::RungeKuttaUtils::newCovarianceMatrix(Jac, cache.m_combinedCovariance + cache.m_covariance);
470 measurementCovariance += localMSCov;
478 covarianceContribution(Cache& cache,
481 double finalMomentum,
485 updateMaterialEffects(cache, finalMomentum,
sin(trackParameters->
momentum().theta()),
path);
488 measurementCovariance += cache.m_combinedCovariance + cache.m_covariance;
505 rungeKuttaStep(Cache& cache,
506 bool errorPropagation,
512 double& distanceStepped)
514 constexpr
double sol = 0.0299792458;
517 double lambda1 =
P[6];
518 double lambda2 =
P[6];
519 double lambda3 =
P[6];
520 double lambda4 =
P[6];
529 double initialMomentum = std::abs(1. /
P[6]);
539 double BG23[12] = { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. };
541 double BG4[12] = { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. };
550 if (cache.m_energyLoss && cache.m_matPropOK) {
554 if (errorPropagation) {
555 if (cache.m_includeGgradient) {
556 dgdl = dgdlambda(cache, lambda1);
559 -lambda1 * lambda1 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda1 * lambda1 * lambda1 *
E * dgdl;
569 getMagneticField(cache,
576 dir.y() * BG1[2] -
dir.z() * BG1[1],
dir.z() * BG1[0] -
dir.x() * BG1[2],
dir.x() * BG1[1] -
dir.y() * BG1[0]);
577 k1 = sol * lambda1 * k1;
580 if (
steps++ > cache.m_maxSteps)
583 if (cache.m_energyLoss && cache.m_matPropOK) {
584 momentum = initialMomentum + (
h / 2.) * dP1;
585 if (
momentum <= cache.m_momentumCutOff)
590 if (errorPropagation) {
592 -lambda2 * lambda2 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda2 * lambda2 * lambda2 *
E * dgdl;
595 pos = initialPos + (
h / 2.) * initialDir + (
h *
h / 8.) * k1;
596 dir = initialDir + (
h / 2.) * k1;
599 getMagneticField(cache,
pos, errorPropagation, BG23);
601 dir.z() * BG23[0] -
dir.x() * BG23[2],
602 dir.x() * BG23[1] -
dir.y() * BG23[0]);
603 k2 = sol * lambda2 * k2;
606 if (cache.m_energyLoss && cache.m_matPropOK) {
607 momentum = initialMomentum + (
h / 2.) * dP2;
608 if (
momentum <= cache.m_momentumCutOff)
613 if (errorPropagation) {
615 -lambda3 * lambda3 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda3 * lambda3 * lambda3 *
E * dgdl;
618 dir = initialDir + (
h / 2.) * k2;
621 dir.z() * BG23[0] -
dir.x() * BG23[2],
622 dir.x() * BG23[1] -
dir.y() * BG23[0]);
623 k3 = sol * lambda3 * k3;
626 if (cache.m_energyLoss && cache.m_matPropOK) {
628 if (
momentum <= cache.m_momentumCutOff)
633 if (errorPropagation) {
635 -lambda4 * lambda4 *
g *
E * (3. - (
momentum *
momentum) / (
E *
E)) - lambda4 * lambda4 * lambda4 *
E * dgdl;
638 pos = initialPos +
h * initialDir + (
h *
h / 2.) * k3;
639 dir = initialDir +
h * k3;
643 getMagneticField(cache,
pos, errorPropagation, BG4);
645 dir.y() * BG4[2] -
dir.z() * BG4[1],
dir.z() * BG4[0] -
dir.x() * BG4[2],
dir.x() * BG4[1] -
dir.y() * BG4[0]);
646 k4 = sol * lambda4 * k4;
650 double errorEstimate =
std::max(errorPos.mag(), 1
e-20);
654 h =
h *
std::min(
std::max(0.25, std::sqrt(std::sqrt(cache.m_tolerance / errorEstimate))), 4.);
657 if (errorEstimate > 4. * cache.m_tolerance)
662 pos = initialPos + distanceStepped * initialDir + (distanceStepped * distanceStepped / 6.) * (k1 + k2 + k3);
668 dir = initialDir + (distanceStepped / 6.) * (k1 + 2. * k2 + 2. * k3 + k4);
674 double norm = 1. / std::sqrt(
P[3] *
P[3] +
P[4] *
P[4] +
P[5] *
P[5]);
680 if (cache.m_energyLoss && cache.m_matPropOK) {
681 momentum = initialMomentum + (distanceStepped / 6.) * (dP1 + 2. * dP2 + 2. * dP3 + dP4);
682 if (
momentum <= cache.m_momentumCutOff)
695 if (errorPropagation) {
696 double initialjLambda =
P[41];
697 double jLambda = initialjLambda;
703 for (
int i = 7;
i < 42;
i += 7) {
716 jDir.z() * BG1[0] - jDir.x() * BG1[2],
717 jDir.x() * BG1[1] - jDir.y() * BG1[0]);
720 if (cache.m_includeBgradients) {
722 (dir1.y() * BG1[9] - dir1.z() * BG1[6]) * jPos.x() + (dir1.y() * BG1[10] - dir1.z() * BG1[7]) * jPos.y() +
723 (dir1.y() * BG1[11] - dir1.z() * BG1[8]) * jPos.z(),
724 (dir1.z() * BG1[3] - dir1.x() * BG1[9]) * jPos.x() + (dir1.z() * BG1[4] - dir1.x() * BG1[10]) * jPos.y() +
725 (dir1.z() * BG1[5] - dir1.x() * BG1[11]) * jPos.z(),
726 (dir1.x() * BG1[6] - dir1.y() * BG1[3]) * jPos.x() + (dir1.x() * BG1[7] - dir1.y() * BG1[4]) * jPos.y() +
727 (dir1.x() * BG1[8] - dir1.y() * BG1[5]) * jPos.z());
730 jk1 = sol * lambda1 * jk1;
734 jdL1 = dL1 * jLambda;
735 jk1 = jk1 + k1 * jLambda / lambda1;
739 jPos = initialjPos + (distanceStepped / 2.) * initialjDir + (distanceStepped * distanceStepped / 8.) * jk1;
740 jDir = initialjDir + (distanceStepped / 2.) * jk1;
743 jDir.z() * BG23[0] - jDir.x() * BG23[2],
744 jDir.x() * BG23[1] - jDir.y() * BG23[0]);
746 if (cache.m_includeBgradients) {
747 Amg::Vector3D C((dir2.y() * BG23[9] - dir2.z() * BG23[6]) * jPos.x() +
748 (dir2.y() * BG23[10] - dir2.z() * BG23[7]) * jPos.y() +
749 (dir2.y() * BG23[11] - dir2.z() * BG23[8]) * jPos.z(),
750 (dir2.z() * BG23[3] - dir2.x() * BG23[9]) * jPos.x() +
751 (dir2.z() * BG23[4] - dir2.x() * BG23[10]) * jPos.y() +
752 (dir2.z() * BG23[5] - dir2.x() * BG23[11]) * jPos.z(),
753 (dir2.x() * BG23[6] - dir2.y() * BG23[3]) * jPos.x() +
754 (dir2.x() * BG23[7] - dir2.y() * BG23[4]) * jPos.y() +
755 (dir2.x() * BG23[8] - dir2.y() * BG23[5]) * jPos.z());
758 jk2 = sol * lambda2 * jk2;
761 jLambda = initialjLambda + (distanceStepped / 2.) * jdL1;
762 jdL2 = dL2 * jLambda;
763 jk2 = jk2 + k2 * jLambda / lambda2;
767 jDir = initialjDir + (distanceStepped / 2.) * jk2;
770 jDir.z() * BG23[0] - jDir.x() * BG23[2],
771 jDir.x() * BG23[1] - jDir.y() * BG23[0]);
773 if (cache.m_includeBgradients) {
774 Amg::Vector3D C((dir3.y() * BG23[9] - dir3.z() * BG23[6]) * jPos.x() +
775 (dir3.y() * BG23[10] - dir3.z() * BG23[7]) * jPos.y() +
776 (dir3.y() * BG23[11] - dir3.z() * BG23[8]) * jPos.z(),
777 (dir3.z() * BG23[3] - dir3.x() * BG23[9]) * jPos.x() +
778 (dir3.z() * BG23[4] - dir3.x() * BG23[10]) * jPos.y() +
779 (dir3.z() * BG23[5] - dir3.x() * BG23[11]) * jPos.z(),
780 (dir3.x() * BG23[6] - dir3.y() * BG23[3]) * jPos.x() +
781 (dir3.x() * BG23[7] - dir3.y() * BG23[4]) * jPos.y() +
782 (dir3.x() * BG23[8] - dir3.y() * BG23[5]) * jPos.z());
785 jk3 = sol * lambda3 * jk3;
788 jLambda = initialjLambda + (distanceStepped / 2.) * jdL2;
789 jdL3 = dL3 * jLambda;
790 jk3 = jk3 + k3 * jLambda / lambda3;
794 jPos = initialjPos + distanceStepped * initialjDir + (distanceStepped * distanceStepped / 2.) * jk3;
795 jDir = initialjDir + distanceStepped * jk3;
798 jDir.z() * BG4[0] - jDir.x() * BG4[2],
799 jDir.x() * BG4[1] - jDir.y() * BG4[0]);
801 if (cache.m_includeBgradients) {
803 (dir4.y() * BG4[9] - dir4.z() * BG4[6]) * jPos.x() + (dir4.y() * BG4[10] - dir4.z() * BG4[7]) * jPos.y() +
804 (dir4.y() * BG4[11] - dir4.z() * BG4[8]) * jPos.z(),
805 (dir4.z() * BG4[3] - dir4.x() * BG4[9]) * jPos.x() + (dir4.z() * BG4[4] - dir4.x() * BG4[10]) * jPos.y() +
806 (dir4.z() * BG4[5] - dir4.x() * BG4[11]) * jPos.z(),
807 (dir4.x() * BG4[6] - dir4.y() * BG4[3]) * jPos.x() + (dir4.x() * BG4[7] - dir4.y() * BG4[4]) * jPos.y() +
808 (dir4.x() * BG4[8] - dir4.y() * BG4[5]) * jPos.z());
811 jk4 = sol * lambda4 * jk4;
814 jLambda = initialjLambda + distanceStepped * jdL3;
815 jdL4 = dL4 * jLambda;
816 jk4 = jk4 + k4 * jLambda / lambda4;
821 initialjPos + distanceStepped * initialjDir + (distanceStepped * distanceStepped / 6.) * (jk1 + jk2 + jk3);
822 jDir = initialjDir + (distanceStepped / 6.) * (jk1 + 2. * jk2 + 2. * jk3 + jk4);
824 jLambda = initialjLambda + (distanceStepped / 6.) * (jdL1 + 2. * jdL2 + 2. * jdL3 + jdL4);
841 for (
int i = 0;
i < 12; ++
i) {
851 propagateWithJacobianImpl(Cache& cache,
852 bool errorPropagation,
858 double maxPath = cache.m_maxPath;
861 double dDir[3] = { 0., 0., 0. };
862 int targetPassed = 0;
863 double previousDistance = 0.;
864 double distanceStepped = 0.;
865 bool distanceEstimationSuccessful =
false;
866 double BG1[12] = { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. };
868 bool firstStep =
true;
869 double absolutePath = 0.;
876 surfaceType, targetSurface,
P, distanceEstimationSuccessful);
877 if (!distanceEstimationSuccessful) {
883 distanceToTarget > 100. ?
h = 100. : distanceToTarget < -100. ?
h = -100. :
h = distanceToTarget;
889 double distanceTolerance =
std::min(
std::max(std::abs(distanceToTarget) * cache.m_tolerance, 1
e-6), 1
e-2);
891 while (std::abs(distanceToTarget) > distanceTolerance) {
893 if (!rungeKuttaStep(cache, errorPropagation,
h,
P,
dDir, BG1, firstStep, distanceStepped))
895 path += distanceStepped;
896 absolutePath += std::abs(distanceStepped);
898 if (std::abs(distanceStepped) > 0.001) {
899 cache.m_sigmaIoni = cache.m_sigmaIoni - cache.m_kazL *
log(std::abs(distanceStepped));
902 if (errorPropagation && cache.m_straggling) {
903 double sigTot2 = cache.m_sigmaIoni * cache.m_sigmaIoni + cache.m_sigmaRad * cache.m_sigmaRad;
905 mom = std::abs(1. /
P[6]);
906 beta =
mom / std::sqrt(
mom *
mom + cache.m_particleMass * cache.m_particleMass);
908 cache.m_stragglingVariance += sigTot2 / (bp2 * bp2) * distanceStepped * distanceStepped;
910 if (cache.m_matstates || errorPropagation)
911 cache.m_combinedEloss.update(cache.m_delIoni * distanceStepped,
912 cache.m_sigmaIoni * std::abs(distanceStepped),
913 cache.m_delRad * distanceStepped,
914 cache.m_sigmaRad * std::abs(distanceStepped),
917 previousDistance = std::abs(distanceToTarget);
919 surfaceType, targetSurface,
P, distanceEstimationSuccessful);
920 if (!distanceEstimationSuccessful)
924 if (
h * distanceToTarget < 0.) {
929 if (std::abs(
h) > std::abs(distanceToTarget))
930 h = distanceToTarget;
933 if ((targetPassed > 3 && std::abs(distanceToTarget) >= previousDistance) || (absolutePath > maxPath))
936 if (
steps++ > cache.m_maxSteps)
940 if (cache.m_material && cache.m_material->x0() != 0.)
941 cache.m_combinedThickness += std::abs(
path) / cache.m_material->x0();
947 pos[0] =
pos[0] + distanceToTarget * (
dir[0] + 0.5 * distanceToTarget *
dDir[0]);
948 pos[1] =
pos[1] + distanceToTarget * (
dir[1] + 0.5 * distanceToTarget *
dDir[1]);
949 pos[2] =
pos[2] + distanceToTarget * (
dir[2] + 0.5 * distanceToTarget *
dDir[2]);
970 std::unique_ptr<Trk::TrackParameters>
971 propagateRungeKuttaImpl(Cache& cache,
972 bool errorPropagation,
984 cache.m_charge = inputTrackParameters.
charge();
986 std::unique_ptr<Trk::TrackParameters> trackParameters{};
992 if (cache.m_tolerance <= 0.)
994 if (cache.m_momentumCutOff < 0.)
998 if (inputTrackParameters.parameters()[
Trk::qOverP] == 0) {
999 trackParameters = createStraightLine(&inputTrackParameters);
1000 if (!trackParameters) {
1004 trackParameters.reset(inputTrackParameters.
clone());
1007 if (std::abs(1. / trackParameters->parameters()[
Trk::qOverP]) <= cache.m_momentumCutOff) {
1012 if (cache.m_matPropOK && ((cache.m_material->zOverAtimesRho() == 0.) || (cache.m_material->x0() == 0.) ||
1013 (cache.m_material->zOverAtimesRho() != cache.m_material->zOverAtimesRho()))) {
1014 cache.m_matPropOK =
false;
1016 if (cache.m_matPropOK && cache.m_straggling)
1017 cache.m_stragglingVariance = 0.;
1018 if (errorPropagation || cache.m_matstates) {
1019 cache.m_combinedCovariance.setZero();
1022 cache.m_inputThetaVariance = trackParameters->covariance() ? (*trackParameters->covariance())(3, 3) : 0.;
1023 cache.m_combinedEloss.set(0., 0., 0., 0., 0., 0.);
1024 cache.m_combinedThickness = 0.;
1037 double d =
T(0, 3) *
T(0, 2) +
T(1, 3) *
T(1, 2) +
T(2, 3) *
T(2, 2);
1050 if (!propagateWithJacobianImpl(cache, errorPropagation, ty,
s, cache.m_P,
path)) {
1057 double s[6] = {
T(0, 3),
T(1, 3),
T(2, 3),
T(0, 2),
T(1, 2),
T(2, 2) };
1058 if (!propagateWithJacobianImpl(cache, errorPropagation, ty,
s, cache.m_P,
path)) {
1066 double s[9] = {
T(0, 3),
T(1, 3),
T(2, 3),
T(0, 2),
1069 if (!propagateWithJacobianImpl(cache, errorPropagation, ty,
s, cache.m_P,
path)) {
1076 double k =
static_cast<const Trk::ConeSurface*
>(&targetSurface)->bounds().tanAlpha();
1078 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. };
1079 if (!propagateWithJacobianImpl(cache, errorPropagation, ty,
s, cache.m_P,
path)) {
1086 double s[6] = {
T(0, 3),
T(1, 3),
T(2, 3), 0., 0., 1. };
1087 if (!propagateWithJacobianImpl(cache, errorPropagation, ty,
s, cache.m_P,
path)) {
1095 double d =
T(0, 3) *
T(0, 2) +
T(1, 3) *
T(1, 2) +
T(2, 3) *
T(2, 2);
1108 if (!propagateWithJacobianImpl(cache, errorPropagation, ty,
s, cache.m_P,
path)) {
1113 if (propagationDirection *
path < 0.) {
1124 if (boundaryCheck && !targetSurface.
isOnSurface(gp)) {
1128 if (!errorPropagation || !trackParameters->covariance()) {
1129 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4]);
1135 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
1137 if (cache.m_matPropOK && (cache.m_multipleScattering || cache.m_straggling) && std::abs(
path) > 0.)
1138 covarianceContribution(cache, trackParameters.get(),
path, std::abs(1. / cache.m_P[6]), measurementCovariance);
1140 return std::make_unique<Trk::CurvilinearParameters>(
1141 gp, localp[2], localp[3], localp[4], std::move(measurementCovariance));
1147 if (boundaryCheck) {
1157 if (!errorPropagation || !trackParameters->covariance()) {
1158 return onTargetSurf;
1163 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
1166 if (cache.m_matPropOK && (cache.m_multipleScattering || cache.m_straggling) && std::abs(
path) > 0.)
1167 covarianceContribution(cache, trackParameters.get(),
path, onTargetSurf.get(), measurementCovariance);
1170 localp[0], localp[1], localp[2], localp[3], localp[4], std::move(measurementCovariance));
1182 ,m_materialEffects(true)
1183 ,m_includeBgradients(true)
1184 ,m_includeGgradient(false)
1185 ,m_momentumCutOff(50.)
1186 ,m_multipleScattering(true)
1188 ,m_detailedEloss(true)
1191 ,m_stragglingScale(1.)
1192 ,m_scatteringScale(1.)
1196 ,m_simulation(false)
1197 ,m_rndGenSvc(
"AthRNGSvc",
n)
1198 ,m_randomEngineName(
"FatrasRnd") {
1199 declareInterface<Trk::IPropagator>(
this);
1232 ATH_CHECK(m_fieldCacheCondObjInputKey.initialize());
1234 if (!m_materialEffects) {
1235 m_multipleScattering =
false;
1236 m_energyLoss =
false;
1237 m_straggling =
false;
1238 }
else if (!m_energyLoss) {
1239 m_straggling =
false;
1242 if (m_simulation && m_simMatUpdator.retrieve().isFailure()) {
1243 ATH_MSG_WARNING(
"Simulation mode requested but material updator not found - no brem photon emission.");
1249 m_rngWrapper = m_rndGenSvc->getEngine(
this, m_randomEngineName);
1252 return StatusCode::SUCCESS;
1257 return StatusCode::SUCCESS;
1266 ATH_MSG_WARNING(
"[STEP_Propagator] STEP_Propagator does not handle neutral track parameters."
1267 <<
"Use the StraightLinePropagator instead.");
1282 double Jacobian[25];
1286 getFieldCacheObject(cache, ctx);
1287 setCacheFromProperties(cache);
1288 clearMaterialEffects(cache);
1305 return propagateRungeKuttaImpl(cache,
true, trackParameters, targetSurface, propagationDirection,
1306 magneticFieldProperties,
particle, boundaryCheck, Jacobian, returnCurv);
1317 std::vector<unsigned int>& solutions,
double&
path,
bool usePathLimit,
bool returnCurv,
1323 getFieldCacheObject(cache, ctx);
1324 setCacheFromProperties(cache);
1325 clearMaterialEffects(cache);
1353 return propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions,
path,
1354 usePathLimit, returnCurv);
1356 return propagateRungeKutta(cache,
true, trackParameters, targetSurfaces, propagationDirection,
1357 magneticFieldProperties,
particle, solutions,
path, returnCurv);
1368 std::vector<unsigned int>& solutions,
PathLimit& pathLim,
TimeLimit& timeLim,
bool returnCurv,
1374 getFieldCacheObject(cache, ctx);
1375 setCacheFromProperties(cache);
1376 clearMaterialEffects(cache);
1404 double dTim = timeLim.
tMax - timeLim.
time;
1412 if (timMax > 0. && timMax <
path)
1414 bool usePathLimit = (
path > 0.);
1427 std::unique_ptr<Trk::TrackParameters> nextPar{};
1430 nextPar = propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions,
path,
1431 usePathLimit, returnCurv);
1433 nextPar = propagateRungeKutta(cache,
true, trackParameters, targetSurfaces, propagationDirection,
1434 magneticFieldProperties,
particle, solutions,
path, returnCurv);
1454 std::vector<unsigned int>& solutions, std::vector<const Trk::TrackStateOnSurface*>*& matstates,
1455 std::vector<std::pair<std::unique_ptr<Trk::TrackParameters>,
int>>* intersections,
double&
path,
1462 getFieldCacheObject(cache, ctx);
1463 setCacheFromProperties(cache);
1464 clearMaterialEffects(cache);
1496 return propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions,
path,
1497 usePathLimit, returnCurv);
1499 return propagateRungeKutta(cache,
true, trackParameters, targetSurfaces, propagationDirection,
1500 magneticFieldProperties,
particle, solutions,
path, returnCurv);
1507 const EventContext& ctx,
1513 std::optional<Trk::TransportJacobian>& jacobian,
1519 double Jacobian[25];
1523 getFieldCacheObject(cache, ctx);
1524 setCacheFromProperties(cache);
1525 clearMaterialEffects(cache);
1542 std::unique_ptr<Trk::TrackParameters>
parameters =
1543 propagateRungeKuttaImpl(cache,
true, trackParameters, targetSurface, propagationDirection,
1544 magneticFieldProperties,
particle, boundaryCheck, Jacobian, returnCurv);
1547 Jacobian[24] = Jacobian[20];
1552 jacobian = std::make_optional<Trk::TransportJacobian>(Jacobian);
1570 double Jacobian[25];
1574 getFieldCacheObject(cache, ctx);
1575 setCacheFromProperties(cache);
1576 clearMaterialEffects(cache);
1588 return propagateRungeKuttaImpl(cache,
false, trackParameters, targetSurface, propagationDirection,
1589 magneticFieldProperties,
particle, boundaryCheck, Jacobian, returnCurv);
1596 const EventContext& ctx,
1602 std::optional<Trk::TransportJacobian>& jacobian,
1607 double Jacobian[25];
1612 getFieldCacheObject(cache, ctx);
1613 setCacheFromProperties(cache);
1614 clearMaterialEffects(cache);
1627 std::unique_ptr<Trk::TrackParameters>
parameters =
1628 propagateRungeKuttaImpl(cache,
true, trackParameters, targetSurface, propagationDirection,
1629 magneticFieldProperties,
particle, boundaryCheck, Jacobian, returnCurv);
1632 Jacobian[24] = Jacobian[20];
1637 jacobian = std::make_optional<Trk::TransportJacobian>(Jacobian);
1649 const EventContext& ctx,
1659 getFieldCacheObject(cache, ctx);
1660 setCacheFromProperties(cache);
1661 clearMaterialEffects(cache);
1681 return std::nullopt;
1684 return std::nullopt;
1687 return std::nullopt;
1698 return std::nullopt;
1707 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1720 if (!propagateWithJacobianImpl(cache,
false, ty,
s, cache.
m_P,
path)){
1721 return std::nullopt;
1727 double s[6] = {T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2)};
1728 if (!propagateWithJacobianImpl(cache,
false, ty,
s, cache.
m_P,
path)) {
1729 return std::nullopt;
1737 T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2), cyl->
bounds().
r(),
Trk::alongMomentum, 0.};
1738 if (!propagateWithJacobianImpl(cache,
false, ty,
s, cache.
m_P,
path)) {
1739 return std::nullopt;
1745 double k =
static_cast<const Trk::ConeSurface*
>(&targetSurface)->bounds().tanAlpha();
1747 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.};
1748 if (!propagateWithJacobianImpl(cache,
false, ty,
s, cache.
m_P,
path)) {
1749 return std::nullopt;
1755 double s[6] = {T(0, 3), T(1, 3), T(2, 3), 0., 0., 1.};
1756 if (!propagateWithJacobianImpl(cache,
false, ty,
s, cache.
m_P,
path)) {
1757 return std::nullopt;
1764 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1777 if (!propagateWithJacobianImpl(cache,
false, ty,
s, cache.
m_P,
path)) {
1778 return std::nullopt;
1784 return std::make_optional<Trk::TrackSurfaceIntersection>(globalPosition, direction,
path);
1787 std::optional<Trk::TrackSurfaceIntersection>
1800 auto tmpTrackParameters =
1801 Trk::Perigee(0., 0., direction.phi(), direction.theta(),
qOverP, perigeeSurface, std::nullopt);
1803 std::optional<Trk::TrackSurfaceIntersection> solution =
1805 ?
intersect(ctx, tmpTrackParameters, surface,
1825 getFieldCacheObject(cache, ctx);
1826 setCacheFromProperties(cache);
1827 clearMaterialEffects(cache);
1853 double dDir[3] = {0., 0., 0.};
1854 double distanceStepped = 0.;
1855 double BG1[12] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
1857 bool firstStep =
true;
1859 double radius2Max = cylinderBounds.
r() * cylinderBounds.
r();
1861 double radius2 = PP[0] * PP[0] + PP[1] * PP[1];
1862 double direction = PP[0] * PP[3] + PP[1] * PP[4];
1863 double h = maxStepSize;
1866 if ((std::abs(PP[2]) > zMax) || (radius2 > radius2Max))
1871 positionsList.push_back(initialPosition);
1873 bool perigee =
false;
1874 if (std::abs(direction) < 0.00001) {
1878 for (
int i = 0;
i != 2; ++
i) {
1884 double p[7] = {PP[0], PP[1], PP[2], PP[3], PP[4], PP[5], PP[6]};
1886 while (std::abs(
path) < maxPath) {
1888 if (!rungeKuttaStep(cache,
false,
h,
p,
dDir, BG1, firstStep, distanceStepped))
1893 if (
h > maxStepSize) {
1895 }
else if (
h < -maxStepSize) {
1902 positionsList.push_back(globalPosition);
1904 positionsList.push_front(globalPosition);
1908 radius2 =
p[0] *
p[0] +
p[1] *
p[1];
1909 if ((std::abs(
p[2]) > zMax) || (radius2 > radius2Max))
1913 if ((
p[0] *
p[3] +
p[1] *
p[4]) * direction < 0.) {
1930 std::vector<unsigned int>& solutions,
double& totalPath,
bool returnCurv)
const {
1936 std::unique_ptr<Trk::TrackParameters> trackParameters{};
1948 if (inputTrackParameters.parameters()[
Trk::qOverP] == 0) {
1949 trackParameters = createStraightLine(&inputTrackParameters);
1950 if (!trackParameters) {
1954 trackParameters.reset(inputTrackParameters.
clone());
1967 if (errorPropagation && !trackParameters->covariance()) {
1968 errorPropagation =
false;
1973 cache.m_combinedCovariance.setZero();
1974 cache.m_covariance.setZero();
1978 cache.
m_inputThetaVariance = trackParameters->covariance() ? (*trackParameters->covariance())(3, 3) : 0.;
1994 bool validStep =
true;
1999 double Jacobian[21];
2002 validStep = propagateWithJacobian(cache, errorPropagation, targetSurfaces, cache.
m_P,
2003 propagationDirection, solutions,
path, totalPath);
2007 if (propagationDirection *
path <= 0.) {
2015 std::unique_ptr<Trk::CurvilinearParameters> cPar =
nullptr;
2017 if (!errorPropagation) {
2018 cPar = std::make_unique<Trk::CurvilinearParameters>(
2024 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
2027 std::abs(totalPath) > 0.) {
2028 covarianceContribution(cache, trackParameters.get(), totalPath, std::abs(1. / cache.
m_P[6]),
2029 measurementCovariance);
2031 cPar = std::make_unique<Trk::CurvilinearParameters>(
2033 std::move(measurementCovariance));
2039 dumpMaterialEffects(cache, cPar.get(), totalPath);
2048 bool solution =
false;
2049 std::vector<unsigned int> valid_solutions;
2050 valid_solutions.reserve(solutions.size());
2053 while (iSol != solutions.end()) {
2054 if (targetSurfaces[*iSol].
first->isOnSurface(gp, targetSurfaces[*iSol].second, 0.001, 0.001)) {
2061 cache.
m_P, localp, Jacobian);
2064 valid_solutions.push_back(*iSol);
2068 solutions = std::move(valid_solutions);
2073 if (solutions.empty()) {
2080 smear(cache, localp[2], localp[3], trackParameters.get(), radDist);
2083 std::unique_ptr<Trk::TrackParameters> onTargetSurf =
2086 : targetSurfaces[solutions[0]].
first->createUniqueTrackParameters(
2087 localp[0], localp[1], localp[2], localp[3], localp[4], std::nullopt);
2089 if (!errorPropagation) {
2092 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4]);
2094 return onTargetSurf;
2099 for (
double i : Jacobian) {
2106 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
2113 covarianceContribution(cache, trackParameters.get(), totalPath, std::abs(1. / cache.
m_P[6]),
2114 measurementCovariance);
2116 covarianceContribution(cache, trackParameters.get(), totalPath, onTargetSurf.get(),
2117 measurementCovariance);
2123 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4],
2124 std::move(measurementCovariance));
2128 return targetSurfaces[solutions[0]].first->createUniqueTrackParameters(
2129 localp[0], localp[1], localp[2], localp[3], localp[4], std::move(measurementCovariance));
2137 std::vector<DestSurf>& sfs,
double*
P,
2139 std::vector<unsigned int>& solutions,
double&
path,
2140 double sumPath)
const {
2142 double*
pos = &
P[0];
2143 double*
dir = &
P[3];
2144 double dDir[3] = {0., 0., 0.};
2146 double previousDistance = 0.;
2147 double distanceStepped = 0.;
2148 double BG1[12] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
2150 bool firstStep =
true;
2158 double helpSoft = 1.;
2161 int restartLimit = 10;
2181 double distanceToTarget = propDir * maxPath;
2184 int nextSf = sfs.size();
2185 int nextSfCand = nextSf;
2188 unsigned int numSf = 0;
2189 unsigned int iCurr = 0;
2191 for (; sIter != sfs.end(); ++sIter) {
2193 double distEst = -propDir * maxPath;
2194 double dist1Est = distEst;
2196 distEst = distSol.
first();
2197 dist1Est = distSol.
first();
2199 (std::abs(distEst) < tol || (propDir * distEst < -tol && propDir * distSol.
second() > tol)))
2200 distEst = distSol.
second();
2205 if (distEst * propDir > -tol) {
2207 cache.
m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2208 0, std::pair<double, double>(distEst, distSol.
currentDistance(
true)));
2210 cache.
m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2211 1, std::pair<double, double>(distEst, distSol.
currentDistance(
true)));
2213 if (tol < propDir * distEst && propDir * distEst < propDir * distanceToTarget) {
2214 distanceToTarget = distEst;
2220 cache.
m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2223 if (std::abs(dist1Est) < tol)
2224 startSf = (
int)iCurr;
2228 if (distanceToTarget == maxPath || numSf == 0)
2238 double absPath = 0.;
2239 distanceToTarget > 100. ?
h = 100. : distanceToTarget < -100. ?
h = -100. :
h = distanceToTarget;
2248 std::pair<size_t, float> dist2next = lbu->
distanceToNext(position, propDir * direction0);
2249 if (dist2next.first < lbu->
bins() && std::abs(dist2next.second) > 1. &&
2250 std::abs(dist2next.second) < std::abs(
h)) {
2251 h = dist2next.second * propDir;
2266 mom = std::abs(1. /
P[6]);
2267 sampleBrem(cache,
mom);
2270 while (numSf > 0 && (std::abs(distanceToTarget) > distanceTolerance ||
2271 std::abs(
path + distanceStepped) < tol)) {
2273 if (!rungeKuttaStep(cache, errorPropagation,
h,
P,
dDir, BG1, firstStep, distanceStepped)) {
2280 m_momentumCutOff, cache.
m_bremMom, position, direction,
2283 for (
int i = 0;
i < 3; ++
i)
2284 P[3 +
i] = direction[
i];
2291 mom = std::abs(1. /
P[6]);
2295 if (std::abs(distanceStepped) > 0.001) {
2318 absPath += std::abs(distanceStepped);
2321 mom = std::abs(1. /
P[6]);
2325 if (std::abs(distanceStepped) > 0.001)
2344 if (absPath > maxPath)
2353 bool restart =
false;
2355 if (propDir *
path < -tol || absPath - std::abs(
path) > 10.) {
2356 helpSoft = std::abs(
path) / absPath > 0.5 ? std::abs(
path) / absPath : 0.5;
2363 float distanceToNextBin =
h;
2369 std::pair<size_t, float> dist2next = lbu->
distanceToNext(position, propDir * direction);
2370 distanceToNextBin = dist2next.second;
2373 std::pair<size_t, float> dist2previous = lbu->
distanceToNext(position, -propDir * direction);
2374 float stepOver = dist2previous.second;
2377 auto cPar = std::make_unique<Trk::CurvilinearParameters>(
Amg::Vector3D(
P[0],
P[1],
P[2]), localp[2],
2378 localp[3], localp[4]);
2380 if (binIDMat && binIDMat->second > 0 && !iMat) {
2382 }
else if (binIDMat && binIDMat->second > 0 &&
2383 (iMat->second == 0 || iMat->second == binIDMat->second)) {
2385 }
else if (iMat && iMat->second > 0) {
2391 if (binIDMat && binIDMat->second > 0 && !iMat) {
2392 cache.
m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2393 }
else if (binIDMat && binIDMat->second > 0 &&
2394 (iMat->second == 0 || iMat->second == binIDMat->second)) {
2395 cache.
m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2396 }
else if (iMat && iMat->second > 0) {
2397 cache.
m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, iMat->second, 0.);
2410 updateMaterialEffects(cache,
mom,
sin(direction.theta()), sumPath +
path - stepOver);
2415 if (distanceToNextBin <
h) {
2416 Amg::Vector3D probe = position + (distanceToNextBin +
h) * propDir * direction;
2417 std::pair<size_t, float> d2n = lbu->
distanceToNext(probe, propDir * direction);
2418 distanceToNextBin += d2n.second +
h;
2420 }
else if (dist2next.first < lbu->
bins() && std::abs(distanceToNextBin) < 0.01 &&
2424 auto cPar = std::make_unique<Trk::CurvilinearParameters>(
Amg::Vector3D(
P[0],
P[1],
P[2]), localp[2],
2425 localp[3], localp[4]);
2429 Amg::Vector3D probe = position + (distanceToNextBin + 0.01) * propDir * direction.normalized();
2433 if (binIDMat && binIDMat->second > 0 && !nextMat) {
2435 }
else if (binIDMat && binIDMat->second > 0 &&
2436 (nextMat->second == 0 || nextMat->second == binIDMat->second)) {
2439 }
else if (nextMat && nextMat->second > 0) {
2445 if (binIDMat && binIDMat->second > 0 && !nextMat) {
2446 cache.
m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2447 }
else if (binIDMat && binIDMat->second > 0 &&
2448 (nextMat->second == 0 ||
2449 nextMat->second == binIDMat->second)) {
2450 cache.
m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2451 }
else if (nextMat && nextMat->second > 0) {
2452 cache.
m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, nextMat->second, 0.);
2457 if (binIDMat != nextMat) {
2461 updateMaterialEffects(cache,
mom,
sin(direction.theta()), sumPath +
path);
2466 std::pair<size_t, float> d2n = lbu->
distanceToNext(probe, propDir * direction.normalized());
2467 distanceToNextBin += d2n.second + 0.01;
2475 bool flipDirection =
false;
2477 nextSfCand = nextSf;
2478 double dev = direction0.dot(direction);
2480 std::vector<std::pair<int, std::pair<double, double>>>
::iterator vsIter = vsBeg;
2496 for (; vsIter != vsEnd; ++vsIter) {
2499 if (numRestart > restartLimit)
2505 distanceToTarget = propDir * maxPath;
2511 if ((*vsIter).first != -1 &&
2512 (
ic == nextSf || (*vsIter).first == 1 || nextSf < 0 || std::abs((*vsIter).second.first) < 500. ||
2513 std::abs(
path) > 0.5 * std::abs((*vsIter).second.second))) {
2514 previousDistance = (*vsIter).second.first;
2516 (*sIter).
first->straightLineDistanceEstimate(position, propDir * direction);
2517 double distanceEst = -propDir * maxPath;
2519 distanceEst = distSol.
first();
2521 std::abs(distSol.
first() * propDir + distanceStepped - previousDistance) >
2522 std::abs(distSol.
second() * propDir + distanceStepped - previousDistance)) {
2523 distanceEst = distSol.
second();
2530 if (
ic == startSf && distanceEst < 0 && distSol.
first() > 0)
2531 distanceEst = distSol.
first();
2534 if (
ic == nextSf && std::abs(distanceEst) < tol && std::abs(
path) < tol) {
2535 (*vsIter).first = -1;
2538 distanceToTarget = maxPath;
2546 if ((*vsIter).second.first * propDir * distanceEst < 0. &&
2547 std::abs(distanceEst) > distanceTolerance) {
2551 std::abs((*vsIter).second.second) < tol ||
2554 ((*vsIter).first)++;
2556 if ((*vsIter).first > 3) {
2557 helpSoft = fmax(0.05, 1. - 0.05 * (*vsIter).first);
2558 if ((*vsIter).first > 20)
2559 helpSoft = 1. / (*vsIter).first;
2562 if ((*vsIter).first > 50 &&
h * propDir > 0) {
2564 (*vsIter).first = -1;
2569 if ((*vsIter).first != -1)
2570 flipDirection =
true;
2571 }
else if (std::abs((*vsIter).second.second) > tol &&
2574 if (
ic > nextSf && nextSf != -1) {
2575 if (propDir * distanceEst < (cache.
m_currentDist.at(nextSf)).second.first - tol) {
2576 if ((*vsIter).first != -1) {
2577 ((*vsIter).first)++;
2578 flipDirection =
true;
2582 }
else if (distanceToTarget >
2584 if ((*vsIter).first != -1) {
2585 ((*vsIter).first)++;
2586 flipDirection =
true;
2591 }
else if (
ic == nextSf) {
2599 (*vsIter).second.first = propDir * distanceEst;
2605 if ((*vsIter).first != -1 && (distanceEst > 0. ||
ic == nextSf)) {
2607 if (distanceEst < std::abs(distanceToTarget)) {
2608 distanceToTarget = propDir * distanceEst;
2612 }
else if (std::abs(
path) > std::abs((*vsIter).second.second) || dev < 0.985 ||
2615 (*sIter).
first->straightLineDistanceEstimate(position, propDir * direction);
2616 double distanceEst = -propDir * maxPath;
2618 distanceEst = distSol.
first();
2621 (*vsIter).second.first = propDir * distanceEst;
2624 if (distanceEst > tol && distanceEst < maxPath) {
2625 (*vsIter).first = 0;
2629 if ((*vsIter).first != -1 && distanceEst > 0.) {
2631 if (distanceEst < std::abs(distanceToTarget)) {
2632 distanceToTarget = propDir * distanceEst;
2640 if (std::abs(distanceToTarget) <= distanceTolerance &&
path * propDir < distanceTolerance) {
2641 (*vsIter).first = -1;
2650 if (nextSf < 0 && nextSfCand < 0)
2653 if (flipDirection) {
2655 if (nextSf < 0 || nextSf >= num_vs_dist)
2657 distanceToTarget = (*(vsBeg + nextSf)).second.first;
2659 }
else if (nextSfCand != nextSf) {
2660 nextSf = nextSfCand;
2662 if (nextSf < 0 || nextSf >= num_vs_dist)
2669 if (std::abs(
h) > std::abs(distanceToTarget))
2670 h = distanceToTarget;
2673 if (cache.
m_binMat && std::abs(
h) > std::abs(distanceToNextBin) + 0.001) {
2674 if (distanceToNextBin > 0) {
2675 h = distanceToNextBin * propDir;
2687 if (std::abs(
path) > maxPath)
2701 mom = std::abs(1. /
P[6]);
2706 pos[0] =
pos[0] + distanceToTarget * (
dir[0] + 0.5 * distanceToTarget *
dDir[0]);
2707 pos[1] =
pos[1] + distanceToTarget * (
dir[1] + 0.5 * distanceToTarget *
dDir[1]);
2708 pos[2] =
pos[2] + distanceToTarget * (
dir[2] + 0.5 * distanceToTarget *
dDir[2]);
2711 dir[0] =
dir[0] + distanceToTarget *
dDir[0];
2712 dir[1] =
dir[1] + distanceToTarget *
dDir[1];
2713 dir[2] =
dir[2] + distanceToTarget *
dDir[2];
2725 std::vector<std::pair<int, std::pair<double, double>>>
::iterator vsIter = vsBeg;
2728 for (; vsIter != vsEnd; ++vsIter) {
2729 if ((*vsIter).first != -1 && propDir * (*vsIter).second.first >= propDir * distanceToTarget - tol &&
2730 propDir * (*vsIter).second.first < 0.01 &&
index != nextSf) {
2731 solutions.push_back(
index);
2733 if (
index == nextSf)
2734 solutions.push_back(
index);
2745 double path)
const {
2761 auto eloss = !m_detailedEloss
2764 : std::make_unique<Trk::EnergyLoss>(
2771 std::sqrt(cache.m_covariance(3, 3)));
2775 std::move(eloss), cvlTP->associatedSurface());
2783 cache.m_combinedCovariance += cache.m_covariance;
2784 cache.m_covariance.setZero();
2792 double radDist)
const {
2808 double th = std::sqrt(2.) * 15. * std::sqrt(radDist) / (
beta *
momentum) *
2822 theta = rotated.theta();
2823 phi = rotated.phi();
2845 if (fieldCondObj ==
nullptr) {
2846 ATH_MSG_ERROR(
"extrapolate: Failed to retrieve AtlasFieldCacheCondObj with key "
2847 << m_fieldCacheCondObjInputKey.key());
2853 CLHEP::HepRandomEngine*
2856 if (!m_simulation || !m_rngWrapper) {
2859 if (m_rngWrapper->evtSeeded(ctx) != ctx.evt()) {
2863 wrapper_nc->setSeed (this->
name(), ctx);
2865 return m_rngWrapper->getEngine (ctx);