285 std::unique_ptr<const Trk::TrackParameters> returnParameters =
nullptr;
289 std::vector<unsigned int> solutions;
291 unsigned int iDest = 0;
292 const EventContext& ctx = Gaudi::Hive::currentContext();
295 if (destVol &&
m_navigator->atVolumeBoundary(currPar, destVol, dir, nextVol,
m_tolerance) && nextVol != destVol) {
313 if (!tgVol || tgVol != destVol) {
315 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
316 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
319 iDest = bounds.size();
324 bool updateStatic =
false;
354 return returnParameters;
366 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
367 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
398 if (!detVols.empty()) {
399 Trk::ArraySpan<const Trk::DetachedTrackingVolume* const>::iterator iTer = detVols.begin();
400 for (; iTer != detVols.end(); ++iTer) {
402 const Trk::Layer *layR = (*iTer)->layerRepresentation();
404 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
408 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
409 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
414 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
421 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
422 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
423 && (*iTer)->trackingVolume()->confinedArbitraryLayers().empty()) {
424 cache.
m_denseVols.emplace_back((*iTer)->trackingVolume(), detBounds.size());
425 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
426 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
431 if (!(*iTer)->trackingVolume()->confinedDenseVolumes().empty() || (confLays.size() > detBounds.size())) {
433 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
434 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
437 }
else if (!confLays.empty()) {
438 for (
const Trk::Layer*
const lIt : confLays) {
439 cache.
m_layers.emplace_back(&(lIt->surfaceRepresentation()),
441 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
477 std::vector<std::pair<const Trk::TrackingVolume *, unsigned int> > navigVols;
480 std::vector<const Trk::DetachedTrackingVolume *> detVols =
481 m_navigator->trackingGeometry(ctx)->lowestDetachedTrackingVolumes(gp);
482 std::vector<const Trk::DetachedTrackingVolume *>::iterator dIter = detVols.begin();
483 for (; dIter != detVols.end(); ++dIter) {
484 const Trk::Layer *layR = (*dIter)->layerRepresentation();
490 m_useMuonMatApprox && (*dIter)->name().substr((*dIter)->name().size() - 4, 4) !=
"PERM") {
503 if (!
active && confinedDense.empty() && confinedLays.empty()) {
507 if (!
active && confinedDense.empty() && confinedLays.size() <= bounds.size()) {
510 if (!confinedDense.empty() || !confinedLays.empty()) {
511 navigVols.emplace_back(dVol, bounds.size());
512 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
513 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
517 if (!confinedDense.empty()) {
518 auto vIter = confinedDense.begin();
519 for (; vIter != confinedDense.end(); ++vIter) {
520 const auto& bounds = (*vIter)->boundarySurfaces();
521 cache.
m_denseVols.emplace_back(*vIter, bounds.size());
522 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
523 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
529 if (!confinedLays.empty()) {
530 for (
const auto *confinedLay : confinedLays) {
531 cache.
m_layers.emplace_back(&(confinedLay->surfaceRepresentation()),
true);
539 for (
const auto *subvol : subvols) {
550 bool vExit =
m_navigator->atVolumeBoundary(currPar, detVol, dir, nextVol,
m_tolerance) && nextVol != detVol;
557 navigVols.emplace_back(detVol, bounds.size());
558 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
559 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
563 cache.
m_denseVols.emplace_back(detVol, bounds.size());
564 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
565 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
573 for (
const auto *cLay : cLays) {
574 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
575 cache.
m_layers.emplace_back(&(cLay->surfaceRepresentation()),
true);
590 dir * currPar->
momentum().normalized(),
true);
591 if (nextLayer && nextLayer != lay) {
598 for (
const auto *layer : layers) {
599 cache.
m_layers.emplace_back(&(layer->surfaceRepresentation()),
true);
612 for (
const auto *cLay : cLays) {
613 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
614 cache.
m_layers.emplace_back(&(cLay->surfaceRepresentation()),
631 if (nextLayer && nextLayer != lay) {
638 if (backLayer && backLayer != lay) {
670 for (
unsigned int i = 0; i < cache.
m_denseVols.size(); i++) {
682 for (
unsigned int i = 0; i < cache.
m_navigLays.size(); i++) {
690 ATH_MSG_VERBOSE(
" [o] Collecting intersection with active input layer.");
703 std::vector<unsigned int> solutions;
707 <<
" (current momentum: " << currPar->
momentum().mag() <<
743 return returnParameters;
764 return returnParameters;
770 return returnParameters;
774 if (timeLim.
tMax > 0. && timeLim.
time >= timeLim.
tMax) {
783 return returnParameters;
788 return returnParameters;
799 ATH_MSG_DEBUG(
" [+] Number of intersection solutions: " << solutions.size());
801 unsigned int iSol = 0;
802 while (iSol < solutions.size()) {
803 if (solutions[iSol] < iDest) {
809 if (mb->layerMaterialProperties() && mb->layerMaterialProperties()->fullMaterial(nextPar->
position())) {
811 nextPar = currentUpdator ? currentUpdator
823 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
825 return returnParameters;
829 ATH_MSG_VERBOSE(
" boundary layer without material:" << mb->layerIndex());
834 unsigned int index = solutions[iSol] - iDest;
840 if (nextVol && !(nextVol->
inside(nextPar->
position() + 0.01 * dir * nextPar->
momentum().normalized(), 0.))) {
844 nextVol =
m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
890 double pIn = nextPar->
momentum().mag();
891 nextPar = currentUpdator ? currentUpdator->
update(nextPar, *nextLayer, timeLim, cache.
m_path,
893 particle).release() : nextPar;
897 return returnParameters;
900 " Layer energy loss:" << nextPar->
momentum().mag() - pIn <<
"at position:" << nextPar->
position() <<
", current momentum:" <<
921 dir * nextPar->
momentum().normalized());
922 if (newLayer && newLayer != nextLayer) {
925 for (
unsigned int i = 0; i < cache.
m_navigLays.size(); i++) {
950 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator dIter = cache.
m_denseVols.begin();
952 index -= (*dIter).second;
956 currVol = (*dIter).first;
965 for (
unsigned int i = 0; i < cache.
m_denseVols.size(); i++) {
984 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator nIter = navigVols.begin();
985 while (nIter != navigVols.end() &&
index >= (*nIter).second) {
986 index -= (*nIter).second;
989 if (nIter != navigVols.end()) {
990 currVol = (*nIter).first;
991 nextVol = ((*nIter).first->boundarySurfaces())[
index]->attachedVolume(*nextPar, dir);
993 ATH_MSG_DEBUG(
" [+] Navigation volume boundary, leaving volume '"
1013 index -= (*dIter).second;
1017 currVol = (*dIter).first->trackingVolume();
1019 ((*dIter).first->trackingVolume()->boundarySurfaces())[
index]->attachedVolume(*nextPar, dir);
1037 return returnParameters;
1051 bool startingLayer)
const {
1053 const EventContext& ctx = Gaudi::Hive::currentContext();
1055 bool isDestinationLayer =
false;
1065 ATH_MSG_VERBOSE(
" [o] OverlapSearch called " << (startSurface ?
"with " :
"w/o ") <<
"start, "
1066 << (endSurface ?
"with " :
"w/o ") <<
"end surface.");
1074 ATH_MSG_VERBOSE(
" [o] Detector surface found through subSurface() call");
1079 ATH_MSG_VERBOSE(
" [o] Detector surface found through parameter on layer association");
1083 bool isStartLayer = (detSurface && detSurface == startSurface);
1087 std::vector<const Trk::TrackParameters*> detParametersOnLayer;
1088 bool reorderDetParametersOnLayer =
false;
1092 if (isDestinationLayer) {
1093 detParameters = (&parsOnLayer);
1094 }
else if (isStartLayer) {
1095 detParameters = (&parm);
1096 }
else if (detSurface) {
1102 bool surfaceHit =
true;
1103 if (detParameters &&
1105 !isDestinationLayer) {
1106 ATH_MSG_VERBOSE(
" [o] First intersection with Detector surface: " << *detParameters);
1108 surfaceHit = detParameters && detSurface ? detSurface->
isOnSurface(detParameters->
position()) : 0;
1114 surfaceHit = (surfaceHit && startSurface) ?
1117 surfaceHit = (surfaceHit && endSurface) ?
1128 detSurface != startSurface) {
1131 detParametersOnLayer.push_back(detParameters);
1132 }
else if (detParameters) {
1134 ATH_MSG_VERBOSE(
" [-] Detector surface hit cancelled through bounds check or start/end surface check.");
1140 if (detParameters) {
1142 std::vector<Trk::SurfaceIntersection> cSurfaces;
1147 ATH_MSG_VERBOSE(
"found " << ncSurfaces <<
" candidate sensitive surfaces to test.");
1150 for (
auto &csf : cSurfaces) {
1159 particle).release();
1161 if (overlapParameters) {
1162 ATH_MSG_VERBOSE(
" [+] Overlap surface was hit, checking start/end surface condition.");
1164 surfaceHit = (startSurface) ?
1167 surfaceHit = (surfaceHit && endSurface) ?
1169 parsOnLayer.
momentum().normalized())
1171 if (surfaceHit && csf.object!=detSurface) {
1174 reorderDetParametersOnLayer =
true;
1176 detParametersOnLayer.push_back(overlapParameters);
1179 ATH_MSG_VERBOSE(
" [-] Detector surface hit cancelled through start/end surface check.");
1188 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIter = detParametersOnLayer.begin();
1189 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIterEnd = detParametersOnLayer.end();
1192 if (reorderDetParametersOnLayer) {
1195 sort(detParametersOnLayer.begin(), detParametersOnLayer.end(), parameterSorter);
1199 parsOnLayerIter = detParametersOnLayer.begin();
1200 parsOnLayerIterEnd = detParametersOnLayer.end();
1202 for (; parsOnLayerIter != parsOnLayerIterEnd; ++parsOnLayerIter) {
1205 std::unique_ptr<const Trk::TrackParameters>(*parsOnLayerIter),
1351 std::unique_ptr<const Trk::TrackParameters> returnParameters =
nullptr;
1357 unsigned int iDest = 0;
1359 const EventContext& ctx = Gaudi::Hive::currentContext();
1361 if (destVol &&
m_navigator->atVolumeBoundary(currPar, destVol, dir, nextVol,
m_tolerance) && nextVol != destVol) {
1380 if (!tgVol || tgVol != destVol) {
1382 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
1383 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1385 dir * currPar->
momentum().normalized());
1439 return returnParameters;
1450 for (
unsigned int ib = 0; ib < bounds.size(); ++ib) {
1451 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1453 dir * currPar->
momentum().normalized());
1457 double dist = distSol.
first();
1469 double dist = distSol.
second();
1482 " transportToVolumeWithPathLimit() - at " << currPar->
position() <<
", missing static volume boundary "
1484 ": transport interrupted");
1487 "---> particle R,phi,z, momentum:" << currPar->
position().perp() <<
"," << currPar->
position().phi() <<
"," << currPar->
position().z() <<
"," <<
1499 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
1500 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1504 "---> decomposed boundary surface position, normal, estimated distance:" << ib <<
"," << surf.
center() <<
"," <<
1507 "---> estimated distance to (first solution):boundary check:" << distSol.
numberOfSolutions() <<
"," << distSol.
first() <<
":" <<
1511 ATH_MSG_DEBUG(
"---> estimated distance to (second solution):boundary check:" << distSol.
second() <<
"," <<
1517 return returnParameters;
1544 if (!detVols.empty()) {
1545 Trk::ArraySpan<const Trk::DetachedTrackingVolume* const>::iterator iTer = detVols.begin();
1546 for (; iTer != detVols.end(); ++iTer) {
1548 const Trk::Layer *layR = (*iTer)->layerRepresentation();
1555 dir * currPar->
momentum().normalized());
1561 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), layR);
1565 const auto& multi = (*iTer)->multilayerRepresentation();
1566 for (
const auto *i : multi) {
1569 dir * currPar->
momentum().normalized());
1575 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), i);
1582 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
"PERM") {
1585 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
1586 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
1587 && ((*iTer)->trackingVolume()->confinedArbitraryLayers().empty())) {
1588 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
1590 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
1591 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
1593 dir * currPar->
momentum().normalized());
1604 cache.
m_denseVols.emplace_back((*iTer)->trackingVolume(), newB);
1614 const auto confinedDense =
1615 (*iTer)->trackingVolume()->confinedDenseVolumes();
1616 if (!confinedDense.empty()) {
1617 auto vIter = confinedDense.begin();
1618 for (; vIter != confinedDense.end(); ++vIter) {
1619 const auto& bounds = (*vIter)->boundarySurfaces();
1621 for (
unsigned int ibb = 0; ibb < bounds.size(); ibb++) {
1622 const Trk::Surface &surf = (bounds[ibb])->surfaceRepresentation();
1624 dir * currPar->
momentum().normalized());
1637 if (!(*vIter)->confinedArbitraryLayers().empty()) {
1639 " transportToVolumeWithPathLimit() - at " << currPar->
position() <<
", unresolved sublayers/subvolumes for "
1640 << (*vIter)->volumeName());
1647 if (!confLays.empty()) {
1648 for (
const Trk::Layer*
const lIt: confLays) {
1649 const Trk::Surface &surf = lIt->surfaceRepresentation();
1651 dir * currPar->
momentum().normalized());
1657 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
1668 std::vector< Trk::DestBound >::iterator bIter = cache.
m_trStaticBounds.begin();
1670 cache.
m_trSurfs.emplace_back((*bIter).surface, (*bIter).distance);
1699 for (
const auto *cLay : cLays) {
1700 if (cLay->layerMaterialProperties()) {
1701 const Trk::Surface &surf = cLay->surfaceRepresentation();
1703 dir * currPar->
momentum().normalized());
1730 for (
unsigned int i = 0; i < cache.
m_denseVols.size(); i++) {
1747 std::vector<unsigned int> sols;
1749 for (
unsigned int i = 0; i < cache.
m_trSurfs.size(); ++i) {
1753 if (sols.size() > 1) {
1754 unsigned int itest = 1;
1755 while (itest < sols.size()) {
1757 unsigned int iex = sols[itest - 1];
1758 sols[itest - 1] = sols[itest];
1766 for (
unsigned int is = 1; is < sols.size(); is++) {
1768 std::cout <<
"wrong intersection ordering" << std::endl;
1782 double mom = currPar->
momentum().mag();
1787 for (
unsigned int sol : sols) {
1788 if (cache.
m_trSurfs[sol].second == 0.) {
1792 double step = cache.
m_trSurfs[sol].second - dist;
1802 for (
unsigned int i = 0; i < cache.
m_denseVols.size(); i++) {
1815 double tDelta = step / beta;
1823 frT = (timeLim.
tMax - cache.
m_time) * beta / step;
1840 double fr = fmin(frT, frM);
1847 cache.
m_time += fr * step / beta;
1852 nextPos = currPar->
position() + dir * currPar->
momentum().normalized() * (dist + fr * step);
1865 if (nextPar &&
process == 121) {
1866 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
1867 return returnParameters;
1871 return returnParameters;
1877 return returnParameters;
1897 if (mb->layerMaterialProperties() && mb->layerMaterialProperties()->fullMaterial(nextPos)) {
1908 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
1910 return returnParameters;
1915 ATH_MSG_VERBOSE(
" boundary layer without material:" << mb->layerIndex());
1925 if (nextVol && !(nextVol->
inside(nextPar->
position() + 0.01 * dir * nextPar->
momentum().normalized(), 0.))) {
1929 nextVol =
m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
1975 nextPar = currentUpdator ? currentUpdator
1987 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
1989 return returnParameters;
1998 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator dIter = cache.
m_denseVols.begin();
2000 index -= (*dIter).second;
2004 currVol = (*dIter).first;
2010 }
else if (currVol->
inside(nextPos + 0.002 * dir * nextPar->
momentum().normalized())) {
2018 for (
unsigned int i = 0; i < cache.
m_denseVols.size(); i++) {
2020 if (dVol->
inside(nextPos + 0.002 * dir * nextPar->
momentum().normalized(),
2054 const std::string m = aliTV ? aliTV->
volumeName() :
" NULLPTR!";
2055 ATH_MSG_DEBUG(
" [0] starting transport of neutral particle in alignable volume " << m);
2064 std::vector<Trk::IdentifiedIntersection> iis;
2068 const EventContext& ctx = Gaudi::Hive::currentContext();
2070 return {
nullptr,
nullptr,
nullptr};
2096 if (binIDMat->second > 0) {
2103 unsigned int cbin = lbu->
bin(pos);
2105 std::pair<size_t, float> d2n = lbu->
distanceToNext(pos, dir * umo);
2111 if (d2n.first == cbin) {
2116 pos = pos + d2n.second * dir * umo;
2117 if (!aliTV->
inside(pos)) {
2122 if (d2n.first == cbin && fabs(d2n.second) < 0.002) {
2123 pos = pos + 0.002 * dir * umo;
2128 if (d2n.second > 0.001) {
2129 pot = pos + 0.5 * d2n.second * dir * umo;
2131 iis.emplace_back(distTot, binIDMat->second, binIDMat->first.get());
2142 for (
unsigned int ib = 0; ib < bounds.size(); ib++) {
2143 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
2145 dir * currPar->
momentum().normalized());
2146 double dist = distSol.
first();
2162 attachedVol =
m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2163 gp + 0.01 * dir * currPar->
momentum().normalized());
2170 nextVol = attachedVol;
2172 }
else if (dist > 0.001) {
2177 "gluing problem at the exit from alignable volume: " << gp.perp() <<
"," << gp.z() <<
":" <<
2183 testVol->
inside(gp + 0.01 * dir * currPar->
momentum().normalized(),
2186 "next volume resolved to:" << testVol->
volumeName() <<
" at the position(R,Z):" << gp.perp() <<
"," <<
2200 return {
nullptr,
nullptr,
nullptr};
2204 nextVol =
m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2209 if (!iis.empty() && cache.
m_trStaticBounds[0].distance - iis.back().distance < 0.01) {
2219 double mom = currPar->
momentum().mag();
2225 for (
unsigned int is = 0; is < iis.size(); is++) {
2226 if (iis[is].distance == 0.) {
2230 double step = iis[is].distance - dist;
2232 nextPos = currPar->
position() + dir * currPar->
momentum().normalized() * iis[is].distance;
2234 double tDelta = step / beta;
2236 double mDelta = (currMat->
zOverAtimesRho() != 0.) ? step / currMat->
x0() : 0.;
2242 frT = (timeLim.
tMax - cache.
m_time) * beta / step;
2251 double mDeltaL = currMat->
L0 > 0. ? step / currMat->
L0 : mDelta / 0.37 / currMat->
averageZ();
2258 double fr = fmin(frT, frM);
2265 cache.
m_time += fr * step / beta;
2266 if (mDelta > 0 && currMat->
averageZ() > 0) {
2270 nextPos = currPar->
position() + dir * currPar->
momentum().normalized() * (dist + fr * step);
2284 if (nextPar &&
process == 121) {
2285 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2286 return {
nullptr,
nullptr,
nullptr};
2290 return {
nullptr,
nullptr,
nullptr};
2295 return {
nullptr,
nullptr,
nullptr};
2300 dist = iis[is].distance;
2301 if (mDelta > 0 && currMat->
averageZ() > 0) {
2306 if (is < iis.size() - 1) {
2309 currMat = iis[is].material;
2310 currLay = iis[is].identifier;
2312 if (cache.
m_hitVector && iis[is].identifier > 0) {
2313 ATH_MSG_VERBOSE(
"active layer entry:" << currLay <<
" at R,z:" << nextPos.perp() <<
"," << nextPos.z());
2314 auto nextPar = std::make_unique<Trk::CurvilinearParameters>(nextPos, currPar->
momentum(), 0.);
2315 cache.
m_hitVector->emplace_back(std::move(nextPar), timeLim.
time, iis[is].identifier, 0.);
2323 ATH_MSG_VERBOSE(
"active layer/volume exit:" << currLay <<
" at R,z:" << nextPos.perp() <<
"," << nextPos.z());
2324 if (binIDMat and(binIDMat->second > 0)) {