9 #include "GaudiKernel/MsgStream.h"
10 #include "GaudiKernel/PhysicalConstants.h"
60 m_stepPropagator(
"Trk::STEP_Propagator/AtlasSTEP_Propagator"),
61 m_navigator(
"Trk::Navigator/AtlasNavigator"),
64 m_elossupdater(
"Trk::EnergyLossUpdator/AtlasEnergyLossUpdator"),
71 m_configurationLevel(10),
72 m_includeMaterialEffects(true),
73 m_requireMaterialDestinationHit(false),
74 m_stopWithNavigationBreak(false),
75 m_stopWithUpdateZero(false),
76 m_skipInitialLayerUpdate(false),
77 m_referenceMaterial(false),
78 m_extendedLayerSearch(true),
79 m_initialLayerAttempts(3),
80 m_successiveLayerAttempts(1),
82 m_caloMsSecondary(false),
83 m_activeOverlap(false),
84 m_robustSampling(true),
85 m_useDenseVolumeDescription(true),
86 m_useMuonMatApprox(false),
87 m_checkForCompundLayers(false),
88 m_resolveActive(false),
89 m_resolveMultilayers(true),
90 m_printHelpOutputAtInitialize(false),
91 m_printRzOutput(true),
92 m_navigationStatistics(false),
93 m_navigationBreakDetails(false),
94 m_materialEffectsOnTrackValidation(false),
99 declareInterface<ITimedExtrapolator>(
this);
102 declareProperty(
"StopWithNavigationBreak", m_stopWithNavigationBreak);
103 declareProperty(
"StopWithUpdateKill", m_stopWithUpdateZero);
104 declareProperty(
"SkipInitialPostUpdate", m_skipInitialLayerUpdate);
106 declareProperty(
"Propagators", m_propagators);
107 declareProperty(
"SubPropagators", m_propNames);
108 declareProperty(
"STEP_Propagator", m_stepPropagator);
110 declareProperty(
"ApplyMaterialEffects", m_includeMaterialEffects);
111 declareProperty(
"RequireMaterialDestinationHit", m_requireMaterialDestinationHit);
112 declareProperty(
"MaterialEffectsUpdators", m_updators);
113 declareProperty(
"MultipleScatteringUpdators", m_msupdators);
114 declareProperty(
"EnergyLossUpdater", m_elossupdater);
115 declareProperty(
"SubMEUpdators", m_updatNames);
118 declareProperty(
"Navigator", m_navigator);
119 declareProperty(
"UseDenseVolumeDescription", m_useDenseVolumeDescription);
121 declareProperty(
"UseMuonMatApproximation", m_useMuonMatApprox);
122 declareProperty(
"CheckForCompoundLayers", m_checkForCompundLayers);
123 declareProperty(
"ResolveMuonStation", m_resolveActive);
124 declareProperty(
"ResolveMultilayers", m_resolveMultilayers);
125 declareProperty(
"ConsiderMuonStationOverlaps", m_activeOverlap);
127 declareProperty(
"RobustSampling", m_robustSampling );
129 declareProperty(
"MaterialEffectsOnTrackProviderIndex", m_meotpIndex);
130 declareProperty(
"MaterialEffectsOnTrackValidation", m_materialEffectsOnTrackValidation);
131 declareProperty(
"ReferenceMaterial", m_referenceMaterial);
132 declareProperty(
"ExtendedLayerSearch", m_extendedLayerSearch);
133 declareProperty(
"InitialLayerAttempts", m_initialLayerAttempts);
134 declareProperty(
"SuccessiveLayerAttempts", m_successiveLayerAttempts);
136 declareProperty(
"HelpOutput", m_printHelpOutputAtInitialize);
137 declareProperty(
"positionOutput", m_printRzOutput);
138 declareProperty(
"NavigationStatisticsOutput", m_navigationStatistics);
139 declareProperty(
"DetailedNavigationOutput", m_navigationBreakDetails);
140 declareProperty(
"Tolerance", m_tolerance);
141 declareProperty(
"CaloMsSecondary", m_caloMsSecondary);
143 declareProperty(
"MagneticFieldProperties", m_fastField);
155 if (m_propagators.empty()) {
156 m_propagators.push_back(
"Trk::RungeKuttaPropagator/DefaultPropagator");
158 if (m_updators.empty()) {
159 m_updators.push_back(
"Trk::MaterialEffectsUpdator/DefaultMaterialEffectsUpdator");
161 if (m_msupdators.empty()) {
162 m_msupdators.push_back(
"Trk::MultipleScatteringUpdator/AtlasMultipleScatteringUpdator");
166 if (!m_propagators.empty()) {
167 if (m_propagators.retrieve().isFailure()) {
169 return StatusCode::FAILURE;
177 unsigned int validprop = m_propagators.size();
180 ATH_MSG_WARNING(
"None of the defined propagators could be retrieved!");
181 ATH_MSG_WARNING(
" Extrapolators jumps back in unconfigured mode, only strategy pattern methods can be used.");
183 m_configurationLevel = validprop - 1;
184 ATH_MSG_VERBOSE(
"Configuration level automatically set to " << m_configurationLevel);
188 if (m_navigator.retrieve().isFailure()) {
190 return StatusCode::FAILURE;
195 if (m_includeMaterialEffects && !m_updators.empty()) {
196 if (m_updators.retrieve().isFailure()) {
197 ATH_MSG_FATAL(
"None of the defined material updatros could be retrieved!");
198 ATH_MSG_FATAL(
"No multiple scattering and energy loss material update will be done.");
199 return StatusCode::FAILURE;
206 unsigned int validmeuts = m_updators.size();
211 if (m_propNames.empty() && !m_propagators.empty()) {
212 ATH_MSG_DEBUG(
"Inconsistent setup of Extrapolator, no sub-propagators configured, doing it for you. ");
213 m_propNames.push_back(m_propagators[0]->
name().substr(8, m_propagators[0]->
name().
size() - 8));
216 if (m_updatNames.empty() && !m_updators.empty()) {
217 ATH_MSG_DEBUG(
"Inconsistent setup of Extrapolator, no sub-materialupdators configured, doing it for you. ");
218 m_updatNames.push_back(m_updators[0]->
name().substr(8, m_updators[0]->
name().
size() - 8));
225 m_propNames.push_back(m_propNames[0]);
228 m_updatNames.push_back(m_updatNames[0]);
230 if (validprop && validmeuts) {
233 unsigned int index = 0;
235 for (
unsigned int iProp = 0; iProp < m_propagators.size(); iProp++) {
236 std::string pname = m_propagators[iProp]->name().substr(8, m_propagators[iProp]->
name().size() - 8);
237 if (m_propNames[isign] == pname) {
242 m_subPropagators[isign] = (
index < validprop) ? &(*m_propagators[
index]) : &(*m_propagators[
Trk::Global]);
245 for (
unsigned int iUp = 0; iUp < m_updators.size(); iUp++) {
246 std::string uname = m_updators[iUp]->name().substr(8, m_updators[iUp]->
name().size() - 8);
247 if (m_updatNames[isign] == uname) {
256 <<
" -- At least one IPropagator and IMaterialUpdator instance have to be given.! ");
260 m_maxNavigSurf = 1000;
265 return StatusCode::SUCCESS;
272 return StatusCode::SUCCESS;
275 std::unique_ptr<const Trk::TrackParameters>
281 std::vector<Trk::HitInfo> * &hitInfo,
293 "M-[" << ++cache.
m_methodSequence <<
"] extrapolateWithPathLimit(...): resolve active layers? " << m_resolveActive);
295 if (!m_stepPropagator) {
297 if (m_stepPropagator.retrieve().isFailure()) {
298 ATH_MSG_ERROR(
"Failed to retrieve tool " << m_stepPropagator);
299 ATH_MSG_ERROR(
"Configure STEP Propagator for extrapolation with path limit");
315 if (boundaryVol && !boundaryVol->
inside(parm.
position(), m_tolerance)) {
320 std::unique_ptr<const Trk::TrackParameters> returnParms =
321 extrapolateToVolumeWithPathLimit(
322 cache, parm, timeLim,
dir,
particle, nextGeoID, boundaryVol);
330 ATH_MSG_DEBUG(hitInfo->size() <<
" identified intersections found");
331 for (
auto & ih : *hitInfo) {
332 ATH_MSG_DEBUG(
"R,z,ID:" << ih.trackParms->position().perp() <<
","
333 << ih.trackParms->position().z() <<
","
340 for (; garbageIter != garbageEnd; ++garbageIter)
if (garbageIter->first) {
341 if(garbageIter->first == returnParms.get()) {
344 << positionOutput(garbageIter->first->position())
345 <<
" parm=" << garbageIter->first
346 <<
" is the return param. Cloning to" << ret.get());
347 returnParms = std::move(ret);
354 std::unique_ptr<const Trk::TrackParameters>
368 std::unique_ptr<const Trk::TrackParameters> returnParameters =
nullptr;
372 std::vector<unsigned int> solutions;
374 unsigned int iDest = 0;
375 const EventContext& ctx = Gaudi::Hive::currentContext();
376 ATH_MSG_DEBUG(
" [+] start extrapolateToVolumeWithPathLimit - at " << positionOutput(parm.
position())<<
" parm="<<&parm);
378 if (destVol && m_navigator->atVolumeBoundary(currPar, destVol,
dir, nextVol, m_tolerance) && nextVol != destVol) {
389 emptyGarbageBin(cache,&parm);
399 if (!tgVol || tgVol != destVol) {
401 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
405 iDest = bounds.size();
410 bool updateStatic =
false;
414 cache.
m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
440 return returnParameters;
442 throwIntoGarbageBin(cache,aPar);
444 return extrapolateToVolumeWithPathLimit(cache,*aPar, timeLim,
dir,
particle, nextGeoID, destVol);
452 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
484 if (!detVols.empty()) {
486 for (; iTer != detVols.end(); ++iTer) {
488 const Trk::Layer *layR = (*iTer)->layerRepresentation();
490 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
494 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
495 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
499 !m_useMuonMatApprox ||
500 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
507 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
508 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
509 && (*iTer)->trackingVolume()->confinedArbitraryLayers().empty()) {
510 cache.
m_denseVols.emplace_back((*iTer)->trackingVolume(), detBounds.size());
511 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
512 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
517 if (!(*iTer)->trackingVolume()->confinedDenseVolumes().empty() || (confLays.size() > detBounds.size())) {
519 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
520 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
523 }
else if (!confLays.empty()) {
524 for (
const Trk::Layer*
const lIt : confLays) {
525 cache.
m_layers.emplace_back(&(lIt->surfaceRepresentation()),
527 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
563 std::vector<std::pair<const Trk::TrackingVolume *, unsigned int> > navigVols;
566 std::vector<const Trk::DetachedTrackingVolume *> detVols =
567 m_navigator->trackingGeometry(ctx)->lowestDetachedTrackingVolumes(gp);
569 for (; dIter != detVols.end(); ++dIter) {
570 const Trk::Layer *layR = (*dIter)->layerRepresentation();
572 if (
active && !m_resolveActive) {
576 m_useMuonMatApprox && (*dIter)->name().substr((*dIter)->name().size() - 4, 4) !=
"PERM") {
581 bool dExit = m_navigator->atVolumeBoundary(currPar, dVol,
dir, nextVol, m_tolerance) && !nextVol;
589 if (!
active && confinedDense.empty() && confinedLays.empty()) {
593 if (!
active && confinedDense.empty() && confinedLays.size() <= bounds.size()) {
596 if (!confinedDense.empty() || !confinedLays.empty()) {
597 navigVols.emplace_back(dVol, bounds.size());
598 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
603 if (!confinedDense.empty()) {
604 auto vIter = confinedDense.begin();
605 for (; vIter != confinedDense.end(); ++vIter) {
606 const auto& bounds = (*vIter)->boundarySurfaces();
607 cache.
m_denseVols.emplace_back(*vIter, bounds.size());
608 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
615 if (!confinedLays.empty()) {
616 for (
const auto *confinedLay : confinedLays) {
617 cache.
m_layers.emplace_back(&(confinedLay->surfaceRepresentation()),
true);
625 for (
const auto *subvol : subvols) {
626 if (subvol->inside(gp, m_tolerance)) {
636 bool vExit = m_navigator->atVolumeBoundary(currPar, detVol,
dir, nextVol, m_tolerance) && nextVol != detVol;
637 if (vExit && nextVol && nextVol->
inside(gp, m_tolerance)) {
643 navigVols.emplace_back(detVol, bounds.size());
644 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
649 cache.
m_denseVols.emplace_back(detVol, bounds.size());
650 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
659 for (
const auto *cLay : cLays) {
660 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
661 cache.
m_layers.emplace_back(&(cLay->surfaceRepresentation()),
true);
677 if (nextLayer && nextLayer != lay) {
685 cache.
m_layers.emplace_back(&(
layer->surfaceRepresentation()),
true);
698 for (
const auto *cLay : cLays) {
699 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
700 cache.
m_layers.emplace_back(&(cLay->surfaceRepresentation()),
717 if (nextLayer && nextLayer != lay) {
724 if (backLayer && backLayer != lay) {
759 if (!m_navigator->atVolumeBoundary(currPar, dVol,
dir, nextVol, m_tolerance) || nextVol == dVol) {
773 overlapSearch(cache,*m_subPropagators[0], *currPar, *currPar, *cache.
m_navigLays[
i].second, timeLim.
time,
dir,
true,
776 ATH_MSG_VERBOSE(
" [o] Collecting intersection with active input layer.");
789 std::vector<unsigned int> solutions;
793 <<
" (current momentum: " << currPar->
momentum().mag() <<
803 || m_navigator->atVolumeBoundary(currPar, cache.
m_currentDense,
dir, assocVol, m_tolerance))) {
822 ATH_MSG_DEBUG(
" [+] Position after propagation - at " << positionOutput(
829 return returnParameters;
832 throwIntoGarbageBin(cache,nextPar);
850 return returnParameters;
853 throwIntoGarbageBin(cache,iPar);
854 return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim,
dir,
particle, nextGeoID, destVol);
856 return returnParameters;
860 if (timeLim.
tMax > 0. && timeLim.
time >= timeLim.
tMax) {
869 return returnParameters;
871 throwIntoGarbageBin(cache,iPar);
872 return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim,
dir,
particle, nextGeoID, destVol);
874 return returnParameters;
880 || m_navigator->atVolumeBoundary(nextPar, cache.
m_currentDense,
dir, assocVol, m_tolerance))) {
885 ATH_MSG_DEBUG(
" [+] Number of intersection solutions: " << solutions.size());
887 unsigned int iSol = 0;
888 while (iSol < solutions.size()) {
889 if (solutions[iSol] < iDest) {
894 if (
mb && m_includeMaterialEffects) {
895 if (
mb->layerMaterialProperties() &&
mb->layerMaterialProperties()->fullMaterial(nextPar->
position())) {
897 nextPar = currentUpdator ? currentUpdator
909 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
911 return returnParameters;
913 throwIntoGarbageBin(cache,nextPar);
920 unsigned int index = solutions[iSol] - iDest;
930 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
941 m_tolerance) && assocVol != nextVol) {
946 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
962 return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir,
particle, nextGeoID, destVol);
982 double pIn = nextPar->
momentum().mag();
983 nextPar = currentUpdator ? currentUpdator->
update(nextPar, *nextLayer, timeLim, cache.
m_path,
989 return returnParameters;
992 " Layer energy loss:" << nextPar->
momentum().mag() - pIn <<
"at position:" << nextPar->
position() <<
", current momentum:" <<
994 throwIntoGarbageBin(cache,nextPar);
1002 overlapSearch(cache,*m_subPropagators[0], *currPar, *nextPar, *nextLayer, timeLim.
time,
dir,
true,
particle);
1014 if (newLayer && newLayer != nextLayer) {
1032 return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir,
particle, nextGeoID, destVol);
1042 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator dIter = cache.
m_denseVols.begin();
1044 index -= (*dIter).second;
1048 currVol = (*dIter).first;
1052 if (!nextVol || !nextVol->
inside(
tp, m_tolerance)) {
1076 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator nIter = navigVols.begin();
1077 while (nIter != navigVols.end() &&
index >= (*nIter).second) {
1078 index -= (*nIter).second;
1081 if (nIter != navigVols.end()) {
1082 currVol = (*nIter).first;
1083 nextVol = ((*nIter).first->boundarySurfaces())[
index]->attachedVolume(*nextPar,
dir);
1085 ATH_MSG_DEBUG(
" [+] Navigation volume boundary, leaving volume '"
1094 return extrapolateToVolumeWithPathLimit(cache,*currPar, timeLim,
dir,
particle, nextGeoID, destVol);
1105 index -= (*dIter).second;
1109 currVol = (*dIter).first->trackingVolume();
1111 ((*dIter).first->trackingVolume()->boundarySurfaces())[
index]->attachedVolume(*nextPar,
dir);
1120 return extrapolateToVolumeWithPathLimit(cache, *currPar, timeLim,
dir,
particle, nextGeoID, destVol);
1129 return returnParameters;
1143 bool startingLayer)
const {
1145 const EventContext& ctx = Gaudi::Hive::currentContext();
1147 bool isDestinationLayer =
false;
1157 ATH_MSG_VERBOSE(
" [o] OverlapSearch called " << (startSurface ?
"with " :
"w/o ") <<
"start, "
1158 << (endSurface ?
"with " :
"w/o ") <<
"end surface.");
1166 ATH_MSG_VERBOSE(
" [o] Detector surface found through subSurface() call");
1171 ATH_MSG_VERBOSE(
" [o] Detector surface found through parameter on layer association");
1175 bool isStartLayer = (detSurface && detSurface == startSurface);
1179 std::vector<const Trk::TrackParameters*> detParametersOnLayer;
1180 bool reorderDetParametersOnLayer =
false;
1184 if (isDestinationLayer) {
1185 detParameters = (&parsOnLayer);
1186 }
else if (isStartLayer) {
1187 detParameters = (&parm);
1188 }
else if (detSurface) {
1190 detParameters = prop.
propagate(ctx,parm, *detSurface,
dir,
false, m_fieldProperties,
particle).release();
1194 bool surfaceHit =
true;
1195 if (detParameters &&
1197 !isDestinationLayer) {
1198 ATH_MSG_VERBOSE(
" [o] First intersection with Detector surface: " << *detParameters);
1200 surfaceHit = detParameters && detSurface ? detSurface->isOnSurface(detParameters->
position()) : 0;
1206 surfaceHit = (surfaceHit && startSurface) ?
1209 surfaceHit = (surfaceHit && endSurface) ?
1220 detSurface != startSurface) {
1223 detParametersOnLayer.push_back(detParameters);
1224 }
else if (detParameters) {
1226 ATH_MSG_VERBOSE(
" [-] Detector surface hit cancelled through bounds check or start/end surface check.");
1227 throwIntoGarbageBin(cache,detParameters);
1232 if (detParameters) {
1234 std::vector<Trk::SurfaceIntersection> cSurfaces;
1239 ATH_MSG_VERBOSE(
"found " << ncSurfaces <<
" candidate sensitive surfaces to test.");
1242 for (
auto &csf : cSurfaces) {
1253 if (overlapParameters) {
1254 ATH_MSG_VERBOSE(
" [+] Overlap surface was hit, checking start/end surface condition.");
1256 surfaceHit = (startSurface) ?
1259 surfaceHit = (surfaceHit && endSurface) ?
1261 parsOnLayer.
momentum().normalized())
1263 if (surfaceHit && csf.object!=detSurface) {
1266 reorderDetParametersOnLayer =
true;
1268 detParametersOnLayer.push_back(overlapParameters);
1271 ATH_MSG_VERBOSE(
" [-] Detector surface hit cancelled through start/end surface check.");
1272 throwIntoGarbageBin(cache,overlapParameters);
1280 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIter = detParametersOnLayer.begin();
1281 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIterEnd = detParametersOnLayer.end();
1284 if (reorderDetParametersOnLayer) {
1287 sort(detParametersOnLayer.begin(), detParametersOnLayer.end(), parameterSorter);
1291 parsOnLayerIter = detParametersOnLayer.begin();
1292 parsOnLayerIterEnd = detParametersOnLayer.end();
1294 for (; parsOnLayerIter != parsOnLayerIterEnd; ++parsOnLayerIter) {
1297 std::unique_ptr<const Trk::TrackParameters>(*parsOnLayerIter),
1307 std::stringstream outStream;
1309 if (m_printRzOutput) {
1310 outStream <<
"[r,phi,z] = [ " <<
pos.perp() <<
", " <<
pos.phi() <<
", " <<
pos.z() <<
" ]";
1312 outStream <<
"[xyz] = [ " <<
pos.x() <<
", " <<
pos.y() <<
", " <<
pos.z() <<
" ]";
1314 return outStream.str();
1319 std::stringstream outStream;
1321 outStream <<
"[eta,phi] = [ " <<
mom.eta() <<
", " <<
mom.phi() <<
" ]";
1322 return outStream.str();
1332 bool throwCurrent =
false;
1334 for (; garbageIter != garbageEnd; ++garbageIter) {
1335 if (garbageIter->first && garbageIter->first != trPar) {
1336 delete (garbageIter->first);
1338 if (garbageIter->first && garbageIter->first == trPar) {
1339 throwCurrent =
true;
1345 throwIntoGarbageBin(cache,trPar);
1353 for (
const auto *subUpdator : m_subUpdators) {
1354 subUpdator->validationAction();
1359 std::unique_ptr<const Trk::TrackParameters>
1364 std::vector<Trk::HitInfo> * &hitInfo,
1376 "M-[" << ++cache.
m_methodSequence <<
"] transportNeutralsWithPathLimit(...) " << pathLim.
x0Max <<
", from " <<
1393 if (boundaryVol && !boundaryVol->
inside(parm.
position(), m_tolerance)) {
1400 std::unique_ptr<const Trk::TrackParameters> returnParms =
1401 transportToVolumeWithPathLimit(
1402 cache, parm, timeLim,
dir,
particle, nextGeoID, boundaryVol);
1414 for (; garbageIter != garbageEnd; ++garbageIter)
if (garbageIter->first) {
1415 if(garbageIter->first == returnParms.get()) {
1418 << positionOutput(garbageIter->first->position())
1419 <<
" parm=" << garbageIter->first
1420 <<
" is the return param. Cloning to" << ret.get());
1421 returnParms=std::move(ret);
1428 std::unique_ptr<const Trk::TrackParameters>
1443 std::unique_ptr<const Trk::TrackParameters> returnParameters =
nullptr;
1449 unsigned int iDest = 0;
1451 const EventContext& ctx = Gaudi::Hive::currentContext();
1453 if (destVol && m_navigator->atVolumeBoundary(currPar, destVol,
dir, nextVol, m_tolerance) && nextVol != destVol) {
1462 emptyGarbageBin(cache,&parm);
1464 if (cache.
m_trSurfs.capacity() > m_maxNavigSurf) {
1465 cache.
m_trSurfs.reserve(m_maxNavigSurf);
1472 if (!tgVol || tgVol != destVol) {
1474 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
1475 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
1504 cache.
m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1531 return returnParameters;
1533 throwIntoGarbageBin(cache,aPar);
1534 return transportToVolumeWithPathLimit(cache,*aPar, timeLim,
dir,
particle, nextGeoID, destVol);
1542 for (
unsigned int ib = 0;
ib < bounds.size(); ++
ib) {
1543 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
1548 distSol.
first() > m_tolerance) {
1549 double dist = distSol.
first();
1556 if (surf.
isOnSurface(gp,
true, m_tolerance, m_tolerance)) {
1561 double dist = distSol.
second();
1564 if (surf.
isOnSurface(gp,
true, m_tolerance, m_tolerance)) {
1565 if (dist > m_tolerance) {
1574 " transportToVolumeWithPathLimit() - at " << currPar->
position() <<
", missing static volume boundary "
1576 ": transport interrupted");
1579 "---> particle R,phi,z, momentum:" << currPar->
position().perp() <<
"," << currPar->
position().phi() <<
"," << currPar->
position().z() <<
"," <<
1591 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
1592 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
1596 "---> decomposed boundary surface position, normal, estimated distance:" <<
ib <<
"," << surf.
center() <<
"," <<
1599 "---> estimated distance to (first solution):boundary check:" << distSol.
numberOfSolutions() <<
"," << distSol.
first() <<
":" <<
1601 m_tolerance, m_tolerance));
1603 ATH_MSG_DEBUG(
"---> estimated distance to (second solution):boundary check:" << distSol.
second() <<
"," <<
1605 m_tolerance, m_tolerance));
1609 return returnParameters;
1615 cache.
m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1618 return transportToVolumeWithPathLimit(cache,parm, timeLim,
dir,
particle, nextGeoID, destVol);
1620 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
1636 if (!detVols.empty()) {
1638 for (; iTer != detVols.end(); ++iTer) {
1640 const Trk::Layer *layR = (*iTer)->layerRepresentation();
1644 if (!m_resolveMultilayers || (*iTer)->multilayerRepresentation().empty()) {
1653 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), layR);
1657 const auto&
multi = (*iTer)->multilayerRepresentation();
1658 for (
const auto *
i :
multi) {
1667 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(),
i);
1674 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
"PERM") {
1677 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
1678 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
1679 && ((*iTer)->trackingVolume()->confinedArbitraryLayers().empty())) {
1680 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
1682 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
1683 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
1696 cache.
m_denseVols.emplace_back((*iTer)->trackingVolume(), newB);
1706 const auto confinedDense =
1707 (*iTer)->trackingVolume()->confinedDenseVolumes();
1708 if (!confinedDense.empty()) {
1709 auto vIter = confinedDense.begin();
1710 for (; vIter != confinedDense.end(); ++vIter) {
1711 const auto& bounds = (*vIter)->boundarySurfaces();
1713 for (
unsigned int ibb = 0; ibb < bounds.size(); ibb++) {
1714 const Trk::Surface &surf = (bounds[ibb])->surfaceRepresentation();
1729 if (!(*vIter)->confinedArbitraryLayers().empty()) {
1731 " transportToVolumeWithPathLimit() - at " << currPar->
position() <<
", unresolved sublayers/subvolumes for "
1732 << (*vIter)->volumeName());
1739 if (!confLays.empty()) {
1740 for (
const Trk::Layer*
const lIt: confLays) {
1741 const Trk::Surface &surf = lIt->surfaceRepresentation();
1749 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
1762 cache.
m_trSurfs.emplace_back((*bIter).surface, (*bIter).distance);
1791 for (
const auto *cLay : cLays) {
1792 if (cLay->layerMaterialProperties()) {
1793 const Trk::Surface &surf = cLay->surfaceRepresentation();
1825 if (!m_navigator->atVolumeBoundary(currPar, dVol,
dir, nextVol, m_tolerance) ||
1839 std::vector<unsigned int> sols;
1840 for (
unsigned int i = 0;
i < cache.
m_trSurfs.size();
i++) {
1844 if (sols.size() > 1) {
1845 unsigned int itest = 1;
1846 while (itest < sols.size()) {
1848 unsigned int iex = sols[itest - 1];
1849 sols[itest - 1] = sols[itest];
1857 for (
unsigned int is = 1; is < sols.size(); is++) {
1859 std::cout <<
"wrong intersection ordering" << std::endl;
1878 for (
unsigned int sol : sols) {
1879 if (cache.
m_trSurfs[sol].second == 0.) {
1931 double fr = fmin(frT, frM);
1956 if (nextPar &&
process == 121) {
1957 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
1958 return returnParameters;
1962 return returnParameters;
1965 throwIntoGarbageBin(cache,nextPar);
1968 return returnParameters;
1980 throwIntoGarbageBin(cache,nextPar);
1987 if (
mb && m_includeMaterialEffects) {
1988 if (
mb->layerMaterialProperties() &&
mb->layerMaterialProperties()->fullMaterial(nextPos)) {
1999 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
2001 return returnParameters;
2003 throwIntoGarbageBin(cache,nextPar);
2020 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2035 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
2050 return transportToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir,
particle, nextGeoID, destVol);
2053 return transportToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir,
particle, nextGeoID, destVol);
2073 if (matUp && m_includeMaterialEffects) {
2076 nextPar = currentUpdator ? currentUpdator
2088 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
2090 return returnParameters;
2092 throwIntoGarbageBin(cache,nextPar);
2099 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator dIter = cache.
m_denseVols.begin();
2101 index -= (*dIter).second;
2105 currVol = (*dIter).first;
2107 if (m_navigator->trackingGeometry(ctx)->atVolumeBoundary(nextPos, nextPar->
momentum(), currVol, assocVol,
dir,
2111 }
else if (currVol->
inside(nextPos + 0.002 *
dir * nextPar->
momentum().normalized())) {
2116 if (m_useMuonMatApprox && cache.
m_denseVols.empty()) {
2133 throwIntoGarbageBin(cache,nextPar);
2163 std::vector<Trk::IdentifiedIntersection> iis;
2165 emptyGarbageBin(cache,&parm);
2167 const EventContext& ctx = Gaudi::Hive::currentContext();
2169 return {
nullptr,
nullptr,
nullptr};
2199 if (binIDMat->second > 0) {
2206 unsigned int cbin = lbu->
bin(
pos);
2214 if (d2n.first == cbin) {
2225 if (d2n.first == cbin && fabs(d2n.second) < 0.002) {
2231 if (d2n.second > 0.001) {
2232 pot =
pos + 0.5 * d2n.second *
dir * umo;
2234 iis.emplace_back(distTot, binIDMat->second, binIDMat->first);
2245 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
2246 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
2249 double dist = distSol.
first();
2258 if (dist > m_tolerance && surf.
isOnSurface(gp,
true, m_tolerance, m_tolerance)) {
2261 if (attachedVol && !(attachedVol->
inside(gp + 0.01 *
dir * currPar->
momentum().normalized(), m_tolerance))) {
2265 attachedVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2266 gp + 0.01 *
dir * currPar->
momentum().normalized());
2273 nextVol = attachedVol;
2275 }
else if (dist > 0.001) {
2280 "gluing problem at the exit from alignable volume: " << gp.perp() <<
"," << gp.z() <<
":" <<
2289 "next volume resolved to:" << testVol->
volumeName() <<
" at the position(R,Z):" << gp.perp() <<
"," <<
2303 return {
nullptr,
nullptr,
nullptr};
2307 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2312 if (!iis.empty() && cache.
m_trStaticBounds[0].distance - iis.back().distance < 0.01) {
2328 for (
unsigned int is = 0; is < iis.size(); is++) {
2333 double step = iis[is].distance - dist;
2335 nextPos = currPar->
position() +
dir * currPar->
momentum().normalized() * iis[is].distance;
2354 double mDeltaL = currMat->
L0 > 0. ?
step / currMat->
L0 : mDelta / 0.37 / currMat->
averageZ();
2361 double fr = fmin(frT, frM);
2369 if (mDelta > 0 && currMat->
averageZ() > 0) {
2376 if (m_caloMsSecondary) {
2381 throwIntoGarbageBin(cache, nextPar);
2387 if (nextPar &&
process == 121) {
2388 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2389 return {
nullptr,
nullptr,
nullptr};
2393 return {
nullptr,
nullptr,
nullptr};
2398 return {
nullptr,
nullptr,
nullptr};
2403 dist = iis[is].distance;
2404 if (mDelta > 0 && currMat->
averageZ() > 0) {
2409 if (is < iis.size() - 1) {
2412 currMat = iis[is].material;
2413 currLay = iis[is].identifier;
2415 if (cache.
m_hitVector && iis[is].identifier > 0) {
2416 ATH_MSG_VERBOSE(
"active layer entry:" << currLay <<
" at R,z:" << nextPos.perp() <<
"," << nextPos.z());
2417 auto nextPar = std::make_unique<Trk::CurvilinearParameters>(nextPos, currPar->
momentum(), 0.);
2418 cache.
m_hitVector->emplace_back(std::move(nextPar), timeLim.
time, iis[is].identifier, 0.);
2426 ATH_MSG_VERBOSE(
"active layer/volume exit:" << currLay <<
" at R,z:" << nextPos.perp() <<
"," << nextPos.z());
2427 if (binIDMat and(binIDMat->second > 0)) {
2432 throwIntoGarbageBin(cache,nextPar);
2452 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
2487 std::vector<unsigned int> solutions;
2490 const EventContext& ctx = Gaudi::Hive::currentContext();
2495 emptyGarbageBin(cache,&parm);
2499 if (vol && vol->
inside(gp, m_tolerance)) {
2502 currVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2504 if (m_navigator->atVolumeBoundary(currPar, currVol,
dir, nextStatVol, m_tolerance) && nextStatVol != currVol) {
2505 currVol = nextStatVol;
2507 if (currVol && currVol != vol) {
2516 ATH_MSG_DEBUG(
" [!] failing in retrieval of AlignableTV, return 0");
2517 return {
nullptr,
nullptr,
nullptr};
2528 if (binIDMat->second > 0) {
2544 for (
unsigned int ib = 0;
ib < bounds.size(); ++
ib) {
2545 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
2559 std::vector<unsigned int> solutions;
2562 <<
" (current momentum: " << currPar->
momentum().mag() <<
2589 ATH_MSG_DEBUG(
" [+] Number of intersection solutions: " << solutions.size());
2592 throwIntoGarbageBin(cache,nextPar);
2614 return {
nullptr,
nullptr,
nullptr};
2617 throwIntoGarbageBin(cache,iPar);
2620 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2621 return {
nullptr,
nullptr,
nullptr};
2626 return {
nullptr,
nullptr,
nullptr};
2631 if (timeLim.
tMax > 0. && timeLim.
time >= timeLim.
tMax) {
2638 return {
nullptr,
nullptr,
nullptr};
2641 throwIntoGarbageBin(cache,iPar);
2643 return {
nullptr,
nullptr,
nullptr};
2645 return {
nullptr,
nullptr,
nullptr};
2650 unsigned int iSol = 0;
2651 while (iSol < solutions.size()) {
2655 unsigned int index = solutions[iSol];
2664 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2677 if (binIDMat && binIDMat->second > 0 && !cache.
m_hitVector->empty() &&
2678 cache.
m_hitVector->back().detID == binIDMat->second) {
2691 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
2707 return {
nullptr,
nullptr,
nullptr};