9 #include "GaudiKernel/MsgStream.h"
10 #include "GaudiKernel/PhysicalConstants.h"
59 m_stepPropagator(
"Trk::STEP_Propagator/AtlasSTEP_Propagator"),
60 m_navigator(
"Trk::Navigator/AtlasNavigator"),
63 m_elossupdater(
"Trk::EnergyLossUpdator/AtlasEnergyLossUpdator"),
70 m_configurationLevel(10),
71 m_includeMaterialEffects(true),
72 m_stopWithNavigationBreak(false),
73 m_stopWithUpdateZero(false),
74 m_skipInitialLayerUpdate(false),
75 m_referenceMaterial(false),
76 m_extendedLayerSearch(true),
77 m_initialLayerAttempts(3),
78 m_successiveLayerAttempts(1),
80 m_caloMsSecondary(false),
81 m_activeOverlap(false),
82 m_robustSampling(true),
83 m_useDenseVolumeDescription(true),
84 m_useMuonMatApprox(false),
85 m_resolveActive(false),
86 m_resolveMultilayers(true),
87 m_printHelpOutputAtInitialize(false),
88 m_printRzOutput(true),
89 m_navigationStatistics(false),
90 m_navigationBreakDetails(false),
91 m_materialEffectsOnTrackValidation(false),
95 declareInterface<ITimedExtrapolator>(
this);
98 declareProperty(
"StopWithNavigationBreak", m_stopWithNavigationBreak);
99 declareProperty(
"StopWithUpdateKill", m_stopWithUpdateZero);
100 declareProperty(
"SkipInitialPostUpdate", m_skipInitialLayerUpdate);
102 declareProperty(
"Propagators", m_propagators);
103 declareProperty(
"SubPropagators", m_propNames);
104 declareProperty(
"STEP_Propagator", m_stepPropagator);
106 declareProperty(
"ApplyMaterialEffects", m_includeMaterialEffects);
107 declareProperty(
"MaterialEffectsUpdators", m_updators);
108 declareProperty(
"MultipleScatteringUpdators", m_msupdators);
109 declareProperty(
"EnergyLossUpdater", m_elossupdater);
110 declareProperty(
"SubMEUpdators", m_updatNames);
112 declareProperty(
"Navigator", m_navigator);
113 declareProperty(
"UseDenseVolumeDescription", m_useDenseVolumeDescription);
115 declareProperty(
"UseMuonMatApproximation", m_useMuonMatApprox);
116 declareProperty(
"ResolveMuonStation", m_resolveActive);
117 declareProperty(
"ResolveMultilayers", m_resolveMultilayers);
118 declareProperty(
"ConsiderMuonStationOverlaps", m_activeOverlap);
120 declareProperty(
"RobustSampling", m_robustSampling );
122 declareProperty(
"MaterialEffectsOnTrackProviderIndex", m_meotpIndex);
123 declareProperty(
"MaterialEffectsOnTrackValidation", m_materialEffectsOnTrackValidation);
124 declareProperty(
"ReferenceMaterial", m_referenceMaterial);
125 declareProperty(
"ExtendedLayerSearch", m_extendedLayerSearch);
126 declareProperty(
"InitialLayerAttempts", m_initialLayerAttempts);
127 declareProperty(
"SuccessiveLayerAttempts", m_successiveLayerAttempts);
129 declareProperty(
"HelpOutput", m_printHelpOutputAtInitialize);
130 declareProperty(
"positionOutput", m_printRzOutput);
131 declareProperty(
"NavigationStatisticsOutput", m_navigationStatistics);
132 declareProperty(
"DetailedNavigationOutput", m_navigationBreakDetails);
133 declareProperty(
"Tolerance", m_tolerance);
134 declareProperty(
"CaloMsSecondary", m_caloMsSecondary);
136 declareProperty(
"MagneticFieldProperties", m_fastField);
148 if (m_propagators.empty()) {
149 m_propagators.push_back(
"Trk::RungeKuttaPropagator/DefaultPropagator");
151 if (m_updators.empty()) {
152 m_updators.push_back(
"Trk::MaterialEffectsUpdator/DefaultMaterialEffectsUpdator");
154 if (m_msupdators.empty()) {
155 m_msupdators.push_back(
"Trk::MultipleScatteringUpdator/AtlasMultipleScatteringUpdator");
159 if (!m_propagators.empty()) {
160 if (m_propagators.retrieve().isFailure()) {
162 return StatusCode::FAILURE;
170 unsigned int validprop = m_propagators.size();
173 ATH_MSG_WARNING(
"None of the defined propagators could be retrieved!");
174 ATH_MSG_WARNING(
" Extrapolators jumps back in unconfigured mode, only strategy pattern methods can be used.");
176 m_configurationLevel = validprop - 1;
177 ATH_MSG_VERBOSE(
"Configuration level automatically set to " << m_configurationLevel);
181 if (m_navigator.retrieve().isFailure()) {
183 return StatusCode::FAILURE;
188 if (m_includeMaterialEffects && !m_updators.empty()) {
189 if (m_updators.retrieve().isFailure()) {
190 ATH_MSG_FATAL(
"None of the defined material updatros could be retrieved!");
191 ATH_MSG_FATAL(
"No multiple scattering and energy loss material update will be done.");
192 return StatusCode::FAILURE;
199 unsigned int validmeuts = m_updators.size();
204 if (m_propNames.empty() && !m_propagators.empty()) {
205 ATH_MSG_DEBUG(
"Inconsistent setup of Extrapolator, no sub-propagators configured, doing it for you. ");
206 m_propNames.push_back(m_propagators[0]->
name().substr(8, m_propagators[0]->
name().
size() - 8));
209 if (m_updatNames.empty() && !m_updators.empty()) {
210 ATH_MSG_DEBUG(
"Inconsistent setup of Extrapolator, no sub-materialupdators configured, doing it for you. ");
211 m_updatNames.push_back(m_updators[0]->
name().substr(8, m_updators[0]->
name().
size() - 8));
218 m_propNames.push_back(m_propNames[0]);
221 m_updatNames.push_back(m_updatNames[0]);
223 if (validprop && validmeuts) {
226 unsigned int index = 0;
228 for (
unsigned int iProp = 0; iProp < m_propagators.size(); iProp++) {
229 std::string pname = m_propagators[iProp]->name().substr(8, m_propagators[iProp]->
name().size() - 8);
230 if (m_propNames[isign] == pname) {
235 m_subPropagators[isign] = (
index < validprop) ? &(*m_propagators[
index]) : &(*m_propagators[
Trk::Global]);
238 for (
unsigned int iUp = 0; iUp < m_updators.size(); iUp++) {
239 std::string uname = m_updators[iUp]->name().substr(8, m_updators[iUp]->
name().size() - 8);
240 if (m_updatNames[isign] == uname) {
249 <<
" -- At least one IPropagator and IMaterialUpdator instance have to be given.! ");
253 m_maxNavigSurf = 1000;
258 return StatusCode::SUCCESS;
265 return StatusCode::SUCCESS;
268 std::unique_ptr<const Trk::TrackParameters>
274 std::vector<Trk::HitInfo> * &hitInfo,
286 "M-[" << ++cache.
m_methodSequence <<
"] extrapolateWithPathLimit(...): resolve active layers? " << m_resolveActive);
288 if (!m_stepPropagator) {
290 if (m_stepPropagator.retrieve().isFailure()) {
291 ATH_MSG_ERROR(
"Failed to retrieve tool " << m_stepPropagator);
292 ATH_MSG_ERROR(
"Configure STEP Propagator for extrapolation with path limit");
308 if (boundaryVol && !boundaryVol->
inside(parm.
position(), m_tolerance)) {
313 std::unique_ptr<const Trk::TrackParameters> returnParms =
314 extrapolateToVolumeWithPathLimit(
315 cache, parm, timeLim,
dir, particle, nextGeoID, boundaryVol);
323 ATH_MSG_DEBUG(hitInfo->size() <<
" identified intersections found");
324 for (
auto & ih : *hitInfo) {
325 ATH_MSG_DEBUG(
"R,z,ID:" << ih.trackParms->position().perp() <<
","
326 << ih.trackParms->position().z() <<
","
333 for (; garbageIter != garbageEnd; ++garbageIter)
if (garbageIter->first) {
334 if(garbageIter->first == returnParms.get()) {
337 << positionOutput(garbageIter->first->position())
338 <<
" parm=" << garbageIter->first
339 <<
" is the return param. Cloning to" << ret.get());
340 returnParms = std::move(ret);
347 std::unique_ptr<const Trk::TrackParameters>
361 std::unique_ptr<const Trk::TrackParameters> returnParameters =
nullptr;
365 std::vector<unsigned int> solutions;
367 unsigned int iDest = 0;
368 const EventContext& ctx = Gaudi::Hive::currentContext();
369 ATH_MSG_DEBUG(
" [+] start extrapolateToVolumeWithPathLimit - at " << positionOutput(parm.
position())<<
" parm="<<&parm);
371 if (destVol && m_navigator->atVolumeBoundary(currPar, destVol,
dir, nextVol, m_tolerance) && nextVol != destVol) {
379 emptyGarbageBin(cache,&parm);
389 if (!tgVol || tgVol != destVol) {
391 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
395 iDest = bounds.size();
400 bool updateStatic =
false;
404 cache.
m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
430 return returnParameters;
432 throwIntoGarbageBin(cache,aPar);
434 return extrapolateToVolumeWithPathLimit(cache,*aPar, timeLim,
dir, particle, nextGeoID, destVol);
442 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
474 if (!detVols.empty()) {
476 for (; iTer != detVols.end(); ++iTer) {
478 const Trk::Layer *layR = (*iTer)->layerRepresentation();
480 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
484 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
485 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
489 !m_useMuonMatApprox ||
490 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
497 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
498 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
499 && (*iTer)->trackingVolume()->confinedArbitraryLayers().empty()) {
500 cache.
m_denseVols.emplace_back((*iTer)->trackingVolume(), detBounds.size());
501 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
502 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
507 if (!(*iTer)->trackingVolume()->confinedDenseVolumes().empty() || (confLays.size() > detBounds.size())) {
509 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
510 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
513 }
else if (!confLays.empty()) {
514 for (
const Trk::Layer*
const lIt : confLays) {
515 cache.
m_layers.emplace_back(&(lIt->surfaceRepresentation()),
517 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
553 std::vector<std::pair<const Trk::TrackingVolume *, unsigned int> > navigVols;
556 std::vector<const Trk::DetachedTrackingVolume *> detVols =
557 m_navigator->trackingGeometry(ctx)->lowestDetachedTrackingVolumes(gp);
559 for (; dIter != detVols.end(); ++dIter) {
560 const Trk::Layer *layR = (*dIter)->layerRepresentation();
562 if (
active && !m_resolveActive) {
566 m_useMuonMatApprox && (*dIter)->name().substr((*dIter)->name().size() - 4, 4) !=
"PERM") {
571 bool dExit = m_navigator->atVolumeBoundary(currPar, dVol,
dir, nextVol, m_tolerance) && !nextVol;
579 if (!
active && confinedDense.empty() && confinedLays.empty()) {
583 if (!
active && confinedDense.empty() && confinedLays.size() <= bounds.size()) {
586 if (!confinedDense.empty() || !confinedLays.empty()) {
587 navigVols.emplace_back(dVol, bounds.size());
588 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
593 if (!confinedDense.empty()) {
594 auto vIter = confinedDense.begin();
595 for (; vIter != confinedDense.end(); ++vIter) {
596 const auto& bounds = (*vIter)->boundarySurfaces();
597 cache.
m_denseVols.emplace_back(*vIter, bounds.size());
598 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
605 if (!confinedLays.empty()) {
606 for (
const auto *confinedLay : confinedLays) {
607 cache.
m_layers.emplace_back(&(confinedLay->surfaceRepresentation()),
true);
615 for (
const auto *subvol : subvols) {
616 if (subvol->inside(gp, m_tolerance)) {
626 bool vExit = m_navigator->atVolumeBoundary(currPar, detVol,
dir, nextVol, m_tolerance) && nextVol != detVol;
627 if (vExit && nextVol && nextVol->
inside(gp, m_tolerance)) {
633 navigVols.emplace_back(detVol, bounds.size());
634 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
639 cache.
m_denseVols.emplace_back(detVol, bounds.size());
640 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
649 for (
const auto *cLay : cLays) {
650 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
651 cache.
m_layers.emplace_back(&(cLay->surfaceRepresentation()),
true);
667 if (nextLayer && nextLayer != lay) {
675 cache.
m_layers.emplace_back(&(
layer->surfaceRepresentation()),
true);
688 for (
const auto *cLay : cLays) {
689 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
690 cache.
m_layers.emplace_back(&(cLay->surfaceRepresentation()),
707 if (nextLayer && nextLayer != lay) {
714 if (backLayer && backLayer != lay) {
749 if (!m_navigator->atVolumeBoundary(currPar, dVol,
dir, nextVol, m_tolerance) || nextVol == dVol) {
763 overlapSearch(cache,*m_subPropagators[0], *currPar, *currPar, *cache.
m_navigLays[
i].second, timeLim.
time,
dir,
true,
766 ATH_MSG_VERBOSE(
" [o] Collecting intersection with active input layer.");
779 std::vector<unsigned int> solutions;
783 <<
" (current momentum: " << currPar->
momentum().mag() <<
793 || m_navigator->atVolumeBoundary(currPar, cache.
m_currentDense,
dir, assocVol, m_tolerance))) {
812 ATH_MSG_DEBUG(
" [+] Position after propagation - at " << positionOutput(
819 return returnParameters;
822 throwIntoGarbageBin(cache,nextPar);
840 return returnParameters;
843 throwIntoGarbageBin(cache,iPar);
844 return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim,
dir, particle, nextGeoID, destVol);
846 return returnParameters;
850 if (timeLim.
tMax > 0. && timeLim.
time >= timeLim.
tMax) {
859 return returnParameters;
861 throwIntoGarbageBin(cache,iPar);
862 return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim,
dir, particle, nextGeoID, destVol);
864 return returnParameters;
870 || m_navigator->atVolumeBoundary(nextPar, cache.
m_currentDense,
dir, assocVol, m_tolerance))) {
875 ATH_MSG_DEBUG(
" [+] Number of intersection solutions: " << solutions.size());
877 unsigned int iSol = 0;
878 while (iSol < solutions.size()) {
879 if (solutions[iSol] < iDest) {
884 if (
mb && m_includeMaterialEffects) {
885 if (
mb->layerMaterialProperties() &&
mb->layerMaterialProperties()->fullMaterial(nextPar->
position())) {
887 nextPar = currentUpdator ? currentUpdator
899 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
901 return returnParameters;
903 throwIntoGarbageBin(cache,nextPar);
910 unsigned int index = solutions[iSol] - iDest;
920 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
931 m_tolerance) && assocVol != nextVol) {
936 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
952 return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir, particle, nextGeoID, destVol);
966 double pIn = nextPar->
momentum().mag();
967 nextPar = currentUpdator ? currentUpdator->
update(nextPar, *nextLayer, timeLim, cache.
m_path,
969 particle).release() : nextPar;
973 return returnParameters;
976 " Layer energy loss:" << nextPar->
momentum().mag() - pIn <<
"at position:" << nextPar->
position() <<
", current momentum:" <<
978 throwIntoGarbageBin(cache,nextPar);
986 overlapSearch(cache,*m_subPropagators[0], *currPar, *nextPar, *nextLayer, timeLim.
time,
dir,
true, particle);
998 if (newLayer && newLayer != nextLayer) {
1016 return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir, particle, nextGeoID, destVol);
1026 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator dIter = cache.
m_denseVols.begin();
1028 index -= (*dIter).second;
1032 currVol = (*dIter).first;
1036 if (!nextVol || !nextVol->
inside(
tp, m_tolerance)) {
1060 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator nIter = navigVols.begin();
1061 while (nIter != navigVols.end() &&
index >= (*nIter).second) {
1062 index -= (*nIter).second;
1065 if (nIter != navigVols.end()) {
1066 currVol = (*nIter).first;
1067 nextVol = ((*nIter).first->boundarySurfaces())[
index]->attachedVolume(*nextPar,
dir);
1069 ATH_MSG_DEBUG(
" [+] Navigation volume boundary, leaving volume '"
1078 return extrapolateToVolumeWithPathLimit(cache,*currPar, timeLim,
dir, particle, nextGeoID, destVol);
1089 index -= (*dIter).second;
1093 currVol = (*dIter).first->trackingVolume();
1095 ((*dIter).first->trackingVolume()->boundarySurfaces())[
index]->attachedVolume(*nextPar,
dir);
1104 return extrapolateToVolumeWithPathLimit(cache, *currPar, timeLim,
dir, particle, nextGeoID, destVol);
1113 return returnParameters;
1127 bool startingLayer)
const {
1129 const EventContext& ctx = Gaudi::Hive::currentContext();
1131 bool isDestinationLayer =
false;
1141 ATH_MSG_VERBOSE(
" [o] OverlapSearch called " << (startSurface ?
"with " :
"w/o ") <<
"start, "
1142 << (endSurface ?
"with " :
"w/o ") <<
"end surface.");
1150 ATH_MSG_VERBOSE(
" [o] Detector surface found through subSurface() call");
1155 ATH_MSG_VERBOSE(
" [o] Detector surface found through parameter on layer association");
1159 bool isStartLayer = (detSurface && detSurface == startSurface);
1163 std::vector<const Trk::TrackParameters*> detParametersOnLayer;
1164 bool reorderDetParametersOnLayer =
false;
1168 if (isDestinationLayer) {
1169 detParameters = (&parsOnLayer);
1170 }
else if (isStartLayer) {
1171 detParameters = (&parm);
1172 }
else if (detSurface) {
1174 detParameters = prop.
propagate(ctx,parm, *detSurface,
dir,
false, m_fieldProperties, particle).release();
1178 bool surfaceHit =
true;
1179 if (detParameters &&
1181 !isDestinationLayer) {
1182 ATH_MSG_VERBOSE(
" [o] First intersection with Detector surface: " << *detParameters);
1184 surfaceHit = detParameters && detSurface ? detSurface->isOnSurface(detParameters->
position()) : 0;
1190 surfaceHit = (surfaceHit && startSurface) ?
1193 surfaceHit = (surfaceHit && endSurface) ?
1204 detSurface != startSurface) {
1207 detParametersOnLayer.push_back(detParameters);
1208 }
else if (detParameters) {
1210 ATH_MSG_VERBOSE(
" [-] Detector surface hit cancelled through bounds check or start/end surface check.");
1211 throwIntoGarbageBin(cache,detParameters);
1216 if (detParameters) {
1218 std::vector<Trk::SurfaceIntersection> cSurfaces;
1223 ATH_MSG_VERBOSE(
"found " << ncSurfaces <<
" candidate sensitive surfaces to test.");
1226 for (
auto &csf : cSurfaces) {
1235 particle).release();
1237 if (overlapParameters) {
1238 ATH_MSG_VERBOSE(
" [+] Overlap surface was hit, checking start/end surface condition.");
1240 surfaceHit = (startSurface) ?
1243 surfaceHit = (surfaceHit && endSurface) ?
1245 parsOnLayer.
momentum().normalized())
1247 if (surfaceHit && csf.object!=detSurface) {
1250 reorderDetParametersOnLayer =
true;
1252 detParametersOnLayer.push_back(overlapParameters);
1255 ATH_MSG_VERBOSE(
" [-] Detector surface hit cancelled through start/end surface check.");
1256 throwIntoGarbageBin(cache,overlapParameters);
1264 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIter = detParametersOnLayer.begin();
1265 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIterEnd = detParametersOnLayer.end();
1268 if (reorderDetParametersOnLayer) {
1271 sort(detParametersOnLayer.begin(), detParametersOnLayer.end(), parameterSorter);
1275 parsOnLayerIter = detParametersOnLayer.begin();
1276 parsOnLayerIterEnd = detParametersOnLayer.end();
1278 for (; parsOnLayerIter != parsOnLayerIterEnd; ++parsOnLayerIter) {
1281 std::unique_ptr<const Trk::TrackParameters>(*parsOnLayerIter),
1291 std::stringstream outStream;
1293 if (m_printRzOutput) {
1294 outStream <<
"[r,phi,z] = [ " <<
pos.perp() <<
", " <<
pos.phi() <<
", " <<
pos.z() <<
" ]";
1296 outStream <<
"[xyz] = [ " <<
pos.x() <<
", " <<
pos.y() <<
", " <<
pos.z() <<
" ]";
1298 return outStream.str();
1303 std::stringstream outStream;
1305 outStream <<
"[eta,phi] = [ " <<
mom.eta() <<
", " <<
mom.phi() <<
" ]";
1306 return outStream.str();
1316 bool throwCurrent =
false;
1318 for (; garbageIter != garbageEnd; ++garbageIter) {
1319 if (garbageIter->first && garbageIter->first != trPar) {
1320 delete (garbageIter->first);
1322 if (garbageIter->first && garbageIter->first == trPar) {
1323 throwCurrent =
true;
1329 throwIntoGarbageBin(cache,trPar);
1337 for (
const auto *subUpdator : m_subUpdators) {
1338 subUpdator->validationAction();
1343 std::unique_ptr<const Trk::TrackParameters>
1348 std::vector<Trk::HitInfo> * &hitInfo,
1360 "M-[" << ++cache.
m_methodSequence <<
"] transportNeutralsWithPathLimit(...) " << pathLim.
x0Max <<
", from " <<
1377 if (boundaryVol && !boundaryVol->
inside(parm.
position(), m_tolerance)) {
1384 std::unique_ptr<const Trk::TrackParameters> returnParms =
1385 transportToVolumeWithPathLimit(
1386 cache, parm, timeLim,
dir, particle, nextGeoID, boundaryVol);
1398 for (; garbageIter != garbageEnd; ++garbageIter)
if (garbageIter->first) {
1399 if(garbageIter->first == returnParms.get()) {
1402 << positionOutput(garbageIter->first->position())
1403 <<
" parm=" << garbageIter->first
1404 <<
" is the return param. Cloning to" << ret.get());
1405 returnParms=std::move(ret);
1412 std::unique_ptr<const Trk::TrackParameters>
1427 std::unique_ptr<const Trk::TrackParameters> returnParameters =
nullptr;
1433 unsigned int iDest = 0;
1435 const EventContext& ctx = Gaudi::Hive::currentContext();
1437 if (destVol && m_navigator->atVolumeBoundary(currPar, destVol,
dir, nextVol, m_tolerance) && nextVol != destVol) {
1446 emptyGarbageBin(cache,&parm);
1448 if (cache.
m_trSurfs.capacity() > m_maxNavigSurf) {
1449 cache.
m_trSurfs.reserve(m_maxNavigSurf);
1456 if (!tgVol || tgVol != destVol) {
1458 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
1459 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
1488 cache.
m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1513 const Trk::TrackParameters *aPar = transportInAlignableTV(cache,parm, timeLim,
dir, particle, nextGeoID, alignTV).trPar;
1515 return returnParameters;
1517 throwIntoGarbageBin(cache,aPar);
1518 return transportToVolumeWithPathLimit(cache,*aPar, timeLim,
dir, particle, nextGeoID, destVol);
1526 for (
unsigned int ib = 0;
ib < bounds.size(); ++
ib) {
1527 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
1532 distSol.
first() > m_tolerance) {
1533 double dist = distSol.
first();
1540 if (surf.
isOnSurface(gp,
true, m_tolerance, m_tolerance)) {
1545 double dist = distSol.
second();
1548 if (surf.
isOnSurface(gp,
true, m_tolerance, m_tolerance)) {
1549 if (dist > m_tolerance) {
1558 " transportToVolumeWithPathLimit() - at " << currPar->
position() <<
", missing static volume boundary "
1560 ": transport interrupted");
1563 "---> particle R,phi,z, momentum:" << currPar->
position().perp() <<
"," << currPar->
position().phi() <<
"," << currPar->
position().z() <<
"," <<
1575 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
1576 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
1580 "---> decomposed boundary surface position, normal, estimated distance:" <<
ib <<
"," << surf.
center() <<
"," <<
1583 "---> estimated distance to (first solution):boundary check:" << distSol.
numberOfSolutions() <<
"," << distSol.
first() <<
":" <<
1585 m_tolerance, m_tolerance));
1587 ATH_MSG_DEBUG(
"---> estimated distance to (second solution):boundary check:" << distSol.
second() <<
"," <<
1589 m_tolerance, m_tolerance));
1593 return returnParameters;
1599 cache.
m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1602 return transportToVolumeWithPathLimit(cache,parm, timeLim,
dir, particle, nextGeoID, destVol);
1604 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
1620 if (!detVols.empty()) {
1622 for (; iTer != detVols.end(); ++iTer) {
1624 const Trk::Layer *layR = (*iTer)->layerRepresentation();
1628 if (!m_resolveMultilayers || (*iTer)->multilayerRepresentation().empty()) {
1637 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), layR);
1641 const auto&
multi = (*iTer)->multilayerRepresentation();
1642 for (
const auto *
i :
multi) {
1651 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(),
i);
1658 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
"PERM") {
1661 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
1662 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
1663 && ((*iTer)->trackingVolume()->confinedArbitraryLayers().empty())) {
1664 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
1666 for (
unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
1667 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
1680 cache.
m_denseVols.emplace_back((*iTer)->trackingVolume(), newB);
1690 const auto confinedDense =
1691 (*iTer)->trackingVolume()->confinedDenseVolumes();
1692 if (!confinedDense.empty()) {
1693 auto vIter = confinedDense.begin();
1694 for (; vIter != confinedDense.end(); ++vIter) {
1695 const auto& bounds = (*vIter)->boundarySurfaces();
1697 for (
unsigned int ibb = 0; ibb < bounds.size(); ibb++) {
1698 const Trk::Surface &surf = (bounds[ibb])->surfaceRepresentation();
1713 if (!(*vIter)->confinedArbitraryLayers().empty()) {
1715 " transportToVolumeWithPathLimit() - at " << currPar->
position() <<
", unresolved sublayers/subvolumes for "
1716 << (*vIter)->volumeName());
1723 if (!confLays.empty()) {
1724 for (
const Trk::Layer*
const lIt: confLays) {
1725 const Trk::Surface &surf = lIt->surfaceRepresentation();
1733 cache.
m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
1746 cache.
m_trSurfs.emplace_back((*bIter).surface, (*bIter).distance);
1775 for (
const auto *cLay : cLays) {
1776 if (cLay->layerMaterialProperties()) {
1777 const Trk::Surface &surf = cLay->surfaceRepresentation();
1809 if (!m_navigator->atVolumeBoundary(currPar, dVol,
dir, nextVol, m_tolerance) ||
1823 std::vector<unsigned int> sols;
1825 for (
unsigned int i = 0;
i < cache.
m_trSurfs.size(); ++
i) {
1829 if (sols.size() > 1) {
1830 unsigned int itest = 1;
1831 while (itest < sols.size()) {
1833 unsigned int iex = sols[itest - 1];
1834 sols[itest - 1] = sols[itest];
1842 for (
unsigned int is = 1; is < sols.size(); is++) {
1844 std::cout <<
"wrong intersection ordering" << std::endl;
1863 for (
unsigned int sol : sols) {
1864 if (cache.
m_trSurfs[sol].second == 0.) {
1916 double fr = fmin(frT, frM);
1941 if (nextPar &&
process == 121) {
1942 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
1943 return returnParameters;
1947 return returnParameters;
1950 throwIntoGarbageBin(cache,nextPar);
1953 return returnParameters;
1965 throwIntoGarbageBin(cache,nextPar);
1972 if (
mb && m_includeMaterialEffects) {
1973 if (
mb->layerMaterialProperties() &&
mb->layerMaterialProperties()->fullMaterial(nextPos)) {
1984 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
1986 return returnParameters;
1988 throwIntoGarbageBin(cache,nextPar);
2005 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2020 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
2035 return transportToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir, particle, nextGeoID, destVol);
2038 return transportToVolumeWithPathLimit(cache,*nextPar, timeLim,
dir, particle, nextGeoID, destVol);
2048 if (matUp && m_includeMaterialEffects) {
2051 nextPar = currentUpdator ? currentUpdator
2063 ATH_MSG_VERBOSE(
" [+] Update may have killed neutral track - return.");
2065 return returnParameters;
2067 throwIntoGarbageBin(cache,nextPar);
2074 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >
::iterator dIter = cache.
m_denseVols.begin();
2076 index -= (*dIter).second;
2080 currVol = (*dIter).first;
2086 }
else if (currVol->
inside(nextPos + 0.002 *
dir * nextPar->
momentum().normalized())) {
2091 if (m_useMuonMatApprox && cache.
m_denseVols.empty()) {
2108 throwIntoGarbageBin(cache,nextPar);
2130 const std::string
m = aliTV ? aliTV->
volumeName() :
" NULLPTR!";
2131 ATH_MSG_DEBUG(
" [0] starting transport of neutral particle in alignable volume " <<
m);
2140 std::vector<Trk::IdentifiedIntersection> iis;
2142 emptyGarbageBin(cache,&parm);
2144 const EventContext& ctx = Gaudi::Hive::currentContext();
2146 return {
nullptr,
nullptr,
nullptr};
2172 if (binIDMat->second > 0) {
2179 unsigned int cbin = lbu->
bin(
pos);
2187 if (d2n.first == cbin) {
2198 if (d2n.first == cbin && fabs(d2n.second) < 0.002) {
2204 if (d2n.second > 0.001) {
2205 pot =
pos + 0.5 * d2n.second *
dir * umo;
2207 iis.emplace_back(distTot, binIDMat->second, binIDMat->first.get());
2218 for (
unsigned int ib = 0;
ib < bounds.size();
ib++) {
2219 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
2222 double dist = distSol.
first();
2231 if (dist > m_tolerance && surf.
isOnSurface(gp,
true, m_tolerance, m_tolerance)) {
2234 if (attachedVol && !(attachedVol->
inside(gp + 0.01 *
dir * currPar->
momentum().normalized(), m_tolerance))) {
2238 attachedVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2239 gp + 0.01 *
dir * currPar->
momentum().normalized());
2246 nextVol = attachedVol;
2248 }
else if (dist > 0.001) {
2253 "gluing problem at the exit from alignable volume: " << gp.perp() <<
"," << gp.z() <<
":" <<
2262 "next volume resolved to:" << testVol->
volumeName() <<
" at the position(R,Z):" << gp.perp() <<
"," <<
2276 return {
nullptr,
nullptr,
nullptr};
2280 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2285 if (!iis.empty() && cache.
m_trStaticBounds[0].distance - iis.back().distance < 0.01) {
2301 for (
unsigned int is = 0; is < iis.size(); is++) {
2306 double step = iis[is].distance - dist;
2308 nextPos = currPar->
position() +
dir * currPar->
momentum().normalized() * iis[is].distance;
2327 double mDeltaL = currMat->
L0 > 0. ?
step / currMat->
L0 : mDelta / 0.37 / currMat->
averageZ();
2334 double fr = fmin(frT, frM);
2342 if (mDelta > 0 && currMat->
averageZ() > 0) {
2349 if (m_caloMsSecondary) {
2354 throwIntoGarbageBin(cache, nextPar);
2360 if (nextPar &&
process == 121) {
2361 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2362 return {
nullptr,
nullptr,
nullptr};
2366 return {
nullptr,
nullptr,
nullptr};
2371 return {
nullptr,
nullptr,
nullptr};
2376 dist = iis[is].distance;
2377 if (mDelta > 0 && currMat->
averageZ() > 0) {
2382 if (is < iis.size() - 1) {
2385 currMat = iis[is].material;
2386 currLay = iis[is].identifier;
2388 if (cache.
m_hitVector && iis[is].identifier > 0) {
2389 ATH_MSG_VERBOSE(
"active layer entry:" << currLay <<
" at R,z:" << nextPos.perp() <<
"," << nextPos.z());
2390 auto nextPar = std::make_unique<Trk::CurvilinearParameters>(nextPos, currPar->
momentum(), 0.);
2391 cache.
m_hitVector->emplace_back(std::move(nextPar), timeLim.
time, iis[is].identifier, 0.);
2399 ATH_MSG_VERBOSE(
"active layer/volume exit:" << currLay <<
" at R,z:" << nextPos.perp() <<
"," << nextPos.z());
2400 if (binIDMat and(binIDMat->second > 0)) {
2405 throwIntoGarbageBin(cache,nextPar);
2413 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
2434 const std::string
m = vol ? vol->
volumeName():
"NULLPTR";
2449 std::vector<unsigned int> solutions;
2452 const EventContext& ctx = Gaudi::Hive::currentContext();
2457 emptyGarbageBin(cache,&parm);
2461 if (vol && vol->
inside(gp, m_tolerance)) {
2464 currVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2466 if (m_navigator->atVolumeBoundary(currPar, currVol,
dir, nextStatVol, m_tolerance) && nextStatVol != currVol) {
2467 currVol = nextStatVol;
2469 if (currVol && currVol != vol) {
2478 ATH_MSG_DEBUG(
" [!] failing in retrieval of AlignableTV, return 0");
2479 return {
nullptr,
nullptr,
nullptr};
2490 if (binIDMat->second > 0) {
2506 for (
unsigned int ib = 0;
ib < bounds.size(); ++
ib) {
2507 const Trk::Surface &surf = (bounds[
ib])->surfaceRepresentation();
2521 std::vector<unsigned int> solutions;
2524 <<
" (current momentum: " << currPar->
momentum().mag() <<
2551 ATH_MSG_DEBUG(
" [+] Number of intersection solutions: " << solutions.size());
2554 throwIntoGarbageBin(cache,nextPar);
2576 return {
nullptr,
nullptr,
nullptr};
2579 throwIntoGarbageBin(cache,iPar);
2582 ATH_MSG_DEBUG(
" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2583 return {
nullptr,
nullptr,
nullptr};
2588 return {
nullptr,
nullptr,
nullptr};
2593 if (timeLim.
tMax > 0. && timeLim.
time >= timeLim.
tMax) {
2600 return {
nullptr,
nullptr,
nullptr};
2603 throwIntoGarbageBin(cache,iPar);
2605 return {
nullptr,
nullptr,
nullptr};
2607 return {
nullptr,
nullptr,
nullptr};
2612 unsigned int iSol = 0;
2613 while (iSol < solutions.size()) {
2617 unsigned int index = solutions[iSol];
2626 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2639 if (binIDMat && binIDMat->second > 0 && !cache.
m_hitVector->empty() &&
2640 cache.
m_hitVector->back().detID == binIDMat->second) {
2653 ATH_MSG_DEBUG(
" [+] World boundary reached - at " << positionOutput(
2669 return {
nullptr,
nullptr,
nullptr};