Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
TimedExtrapolator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // TimedExtrapolator.cxx, (c) ATLAS Detector software
8 
9 #include "GaudiKernel/MsgStream.h"
10 #include "GaudiKernel/PhysicalConstants.h"
11 // Trk include
17 #include "TrkSurfaces/DiscBounds.h"
21 #include "TrkTrack/Track.h"
24 #include "TrkGeometry/Layer.h"
33 #include "TrkVolumes/Volume.h"
43 
44 // for the comparison with a pointer
45 #include <cstdint>
46 
47 // Amg
50 
51 // Trk
53 
54 
55 // constructor
56 Trk::TimedExtrapolator::TimedExtrapolator(const std::string &t, const std::string &n, const IInterface *p) :
57  AthAlgTool(t, n, p),
58  m_propagators(),
59  m_stepPropagator("Trk::STEP_Propagator/AtlasSTEP_Propagator"),
60  m_navigator("Trk::Navigator/AtlasNavigator"),
61  m_updators(),
62  m_msupdators(),
63  m_elossupdater("Trk::EnergyLossUpdator/AtlasEnergyLossUpdator"),
64  // m_dynamicLayerCreator(),
65  m_subPropagators(Trk::NumberOfSignatures),
66  m_subUpdators(Trk::NumberOfSignatures),
67  m_propNames(),
68  m_updatNames(),
69  m_meotpIndex(0),
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),
79  m_tolerance(0.002),
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),
92  m_maxNavigSurf{},
93  m_maxNavigVol{},
94  m_fastField(false) {
95  declareInterface<ITimedExtrapolator>(this);
96 
97  // extrapolation steering
98  declareProperty("StopWithNavigationBreak", m_stopWithNavigationBreak);
99  declareProperty("StopWithUpdateKill", m_stopWithUpdateZero);
100  declareProperty("SkipInitialPostUpdate", m_skipInitialLayerUpdate);
101  // propagation steering
102  declareProperty("Propagators", m_propagators);
103  declareProperty("SubPropagators", m_propNames);
104  declareProperty("STEP_Propagator", m_stepPropagator);
105  // material effects handling
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);
111  // general behavior navigation
112  declareProperty("Navigator", m_navigator);
113  declareProperty("UseDenseVolumeDescription", m_useDenseVolumeDescription);
114  // muon system specifics
115  declareProperty("UseMuonMatApproximation", m_useMuonMatApprox);
116  declareProperty("ResolveMuonStation", m_resolveActive);
117  declareProperty("ResolveMultilayers", m_resolveMultilayers);
118  declareProperty("ConsiderMuonStationOverlaps", m_activeOverlap);
119  // declareProperty("DynamicLayerCreator", m_dynamicLayerCreator);
120  declareProperty("RobustSampling", m_robustSampling );
121  // material & navigation related steering
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);
128  // debug and validation
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);
135  // Magnetic field properties
136  declareProperty("MagneticFieldProperties", m_fastField);
137 }
138 
139 // destructor
141 
142 // Athena standard methods
143 // initialize
146  m_fieldProperties = m_fastField ? Trk::MagneticFieldProperties(Trk::FastField) : Trk::MagneticFieldProperties(
148  if (m_propagators.empty()) {
149  m_propagators.push_back("Trk::RungeKuttaPropagator/DefaultPropagator");
150  }
151  if (m_updators.empty()) {
152  m_updators.push_back("Trk::MaterialEffectsUpdator/DefaultMaterialEffectsUpdator");
153  }
154  if (m_msupdators.empty()) {
155  m_msupdators.push_back("Trk::MultipleScatteringUpdator/AtlasMultipleScatteringUpdator");
156  }
157 
158 
159  if (!m_propagators.empty()) {
160  if (m_propagators.retrieve().isFailure()) {
161  ATH_MSG_FATAL("Failed to retrieve tool " << m_propagators);
162  return StatusCode::FAILURE;
163  }
164  ATH_MSG_INFO("Retrieved tools " << m_propagators);
165 
166  }
167 
168 
169  // from the number of retrieved propagators set the configurationLevel
170  unsigned int validprop = m_propagators.size();
171 
172  if (!validprop) {
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.");
175  } else {
176  m_configurationLevel = validprop - 1;
177  ATH_MSG_VERBOSE("Configuration level automatically set to " << m_configurationLevel);
178  }
179 
180  // Get the Navigation AlgTools
181  if (m_navigator.retrieve().isFailure()) {
182  ATH_MSG_FATAL("Failed to retrieve tool " << m_navigator);
183  return StatusCode::FAILURE;
184  }
185  ATH_MSG_INFO("Retrieved tool " << m_navigator);
186 
187  // Get the Material Updator
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;
193  }
194  ATH_MSG_INFO("Retrieved tools: " << m_updators);
195 
196  }
197 
198  // from the number of retrieved propagators set the configurationLevel
199  unsigned int validmeuts = m_updators.size();
200 
201  // -----------------------------------------------------------
202  // Sanity check 1
203 
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));
207  }
208 
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));
212  }
213 
214  // -----------------------------------------------------------
215  // Sanity check 2
216  // fill the number of propagator names and updator names up with first one
217  while (int(m_propNames.size()) < int(Trk::NumberOfSignatures)) {
218  m_propNames.push_back(m_propNames[0]);
219  }
220  while (int(m_updatNames.size()) < int(Trk::NumberOfSignatures)) {
221  m_updatNames.push_back(m_updatNames[0]);
222  }
223  if (validprop && validmeuts) {
224  // Per definition: if configured not found, take the lowest one
225  for (unsigned int isign = 0; int(isign) < int(Trk::NumberOfSignatures); ++isign) {
226  unsigned int index = 0;
227 
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) {
231  index = iProp;
232  }
233  }
234  ATH_MSG_DEBUG(" subPropagator:" << isign << " pointing to propagator: " << m_propagators[index]->name());
235  m_subPropagators[isign] = (index < validprop) ? &(*m_propagators[index]) : &(*m_propagators[Trk::Global]);
236 
237  index = 0;
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) {
241  index = iUp;
242  }
243  }
244  ATH_MSG_DEBUG(" subMEUpdator:" << isign << " pointing to updator: " << m_updators[index]->name());
245  m_subUpdators[isign] = (index < validmeuts) ? &(*m_updators[index]) : &(*m_updators[Trk::Global]);
246  }
247  } else {
248  ATH_MSG_FATAL("Configuration Problem of Extrapolator: "
249  << " -- At least one IPropagator and IMaterialUpdator instance have to be given.! ");
250  }
251 
252 
253  m_maxNavigSurf = 1000;
254  m_maxNavigVol = 50;
255 
256 
257  ATH_MSG_INFO("initialize() successful");
258  return StatusCode::SUCCESS;
259 }
260 
261 // finalize
264  ATH_MSG_INFO("finalize() successful");
265  return StatusCode::SUCCESS;
266 }
267 
268 std::unique_ptr<const Trk::TrackParameters>
270  const Trk::TrackParameters &parm,
271  Trk::PathLimit &pathLim, Trk::TimeLimit &timeLim,
273  Trk::ParticleHypothesis particle,
274  std::vector<Trk::HitInfo> * &hitInfo,
275  Trk::GeometrySignature &nextGeoID,
276  const Trk::TrackingVolume *boundaryVol) const {
277 // extrapolation method intended for simulation of particle decay; collects intersections with active layers
278 // possible outcomes:1/ returns curvilinear parameters after reaching the maximal path
279 // 2/ returns parameters at destination volume boundary
280 // 3/ returns 0 ( particle stopped ) but keeps vector of hits
281 
282  Trk::TimedExtrapolator::Cache cache(m_maxNavigSurf);
284  "M-[" << ++cache.m_methodSequence << "] extrapolateWithPathLimit(...) " << pathLim.x0Max << ", from " << parm.position());
286  "M-[" << ++cache.m_methodSequence << "] extrapolateWithPathLimit(...): resolve active layers? " << m_resolveActive);
287 
288  if (!m_stepPropagator) {
289  // Get the STEP_Propagator AlgTool
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");
293  return nullptr;
294  }
295  ATH_MSG_INFO("Retrieved tool " << m_stepPropagator);
296 
297  }
298 
299  // reset the path ( in x0 !!)
300  cache.m_path = PathLimit(pathLim.x0Max - pathLim.x0Collected, pathLim.process); // collect material locally
301 
302  // initialize hit vector
303  cache.m_hitVector = hitInfo;
304 
305  // if no input volume, define as highest volume
306  // const Trk::TrackingVolume* destVolume = boundaryVol ? boundaryVol : m_navigator->highestVolume();
307  cache.m_currentStatic = nullptr;
308  if (boundaryVol && !boundaryVol->inside(parm.position(), m_tolerance)) {
309  return nullptr;
310  }
311 
312  // extrapolate to destination volume boundary with path limit
313  std::unique_ptr<const Trk::TrackParameters> returnParms =
314  extrapolateToVolumeWithPathLimit(
315  cache, parm, timeLim, dir, particle, nextGeoID, boundaryVol);
316 
317  // save actual path on output
318  if (cache.m_path.x0Collected > 0.) {
319  pathLim.updateMat(cache.m_path.x0Collected, cache.m_path.weightedZ / cache.m_path.x0Collected, cache.m_path.l0Collected);
320  }
321 
322  if (hitInfo) {
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() << ","
327  << ih.detID);
328  }
329  }
330 
333  for (; garbageIter != garbageEnd; ++garbageIter) if (garbageIter->first) {
334  if(garbageIter->first == returnParms.get()) {
335  auto ret=returnParms->uniqueClone();
336  ATH_MSG_DEBUG(" [+] garbage - at "
337  << positionOutput(garbageIter->first->position())
338  << " parm=" << garbageIter->first
339  << " is the return param. Cloning to" << ret.get());
340  returnParms = std::move(ret);
341  }
342  }
343 
344  return returnParms;
345 }
346 
347 std::unique_ptr<const Trk::TrackParameters>
350  const Trk::TrackParameters &parm,
351  Trk::TimeLimit &timeLim,
353  Trk::ParticleHypothesis particle,
354  Trk::GeometrySignature &nextGeoID,
355  const Trk::TrackingVolume *destVol) const {
356  // returns:
357  // A) curvilinear track parameters if path limit reached
358  // B) boundary parameters (at destination volume boundary)
359 
360  // initialize the return parameters vector
361  std::unique_ptr<const Trk::TrackParameters> returnParameters = nullptr;
362  const Trk::TrackParameters *currPar = &parm;
363  const Trk::TrackingVolume *currVol = nullptr;
364  const Trk::TrackingVolume *nextVol = nullptr;
365  std::vector<unsigned int> solutions;
366  const Trk::TrackingVolume *assocVol = nullptr;
367  unsigned int iDest = 0;
368  const EventContext& ctx = Gaudi::Hive::currentContext();
369  ATH_MSG_DEBUG(" [+] start extrapolateToVolumeWithPathLimit - at " << positionOutput(parm.position())<<" parm="<<&parm);
370  // destination volume boundary ?
371  if (destVol && m_navigator->atVolumeBoundary(currPar, destVol, dir, nextVol, m_tolerance) && nextVol != destVol) {
372  return parm.uniqueClone();
373  }
374 
375  if (!cache.m_highestVolume) {
376  cache.m_highestVolume = m_navigator->highestVolume(ctx);
377  }
378 
379  emptyGarbageBin(cache,&parm);
380  // navigation surfaces
381  if (cache.m_navigSurfs.capacity() > m_maxNavigSurf) {
382  cache.m_navigSurfs.reserve(m_maxNavigSurf);
383  }
384  cache.m_navigSurfs.clear();
385 
386  // target volume may not be part of tracking geometry
387  if (destVol) {
388  const Trk::TrackingVolume *tgVol = m_navigator->trackingGeometry(ctx)->trackingVolume(destVol->volumeName());
389  if (!tgVol || tgVol != destVol) {
390  const auto & bounds = destVol->boundarySurfaces();
391  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
392  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
393  cache.m_navigSurfs.emplace_back(&surf, true);
394  }
395  iDest = bounds.size();
396  }
397  }
398 
399  // resolve current position
400  bool updateStatic = false;
401  Amg::Vector3D gp = parm.position();
402 
403  if (!cache.m_currentStatic || !cache.m_currentStatic->inside(gp, m_tolerance)) {
404  cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
405  updateStatic = true;
406  }
407  if (m_navigator->atVolumeBoundary(currPar, cache.m_currentStatic, dir, nextVol,
408  m_tolerance) && nextVol != cache.m_currentStatic) {
409  // no next volume found --- end of the world
410  if (!nextVol) {
411  ATH_MSG_DEBUG(" [+] Word boundary reached - at " << positionOutput(currPar->position()));
413  return currPar->uniqueClone();
414  }
415  cache.m_currentStatic = nextVol;
416  updateStatic = true;
417  }
418 
419  // current frame volume known-retrieve geoID
420  nextGeoID = cache.m_currentStatic->geometrySignature();
421 
422  // resolve active Calo volumes if hit info required
423  if (cache.m_hitVector && nextGeoID == Trk::Calo) {
424  const Trk::AlignableTrackingVolume *alignTV = dynamic_cast<const Trk::AlignableTrackingVolume *> (cache.m_currentStatic);
425  if (alignTV) {
426  Trk::BoundaryTrackParameters boundPar = extrapolateInAlignableTV(cache,*currPar, timeLim, dir, particle, nextGeoID,
427  alignTV);
428  const Trk::TrackParameters *aPar = boundPar.trPar;
429  if (!aPar) {
430  return returnParameters;
431  }
432  throwIntoGarbageBin(cache,aPar);
433  // cache.m_currentStatic = boundPar.exitVol;
434  return extrapolateToVolumeWithPathLimit(cache,*aPar, timeLim, dir, particle, nextGeoID, destVol);
435  }
436  }
437 
438  // update if new static volume
439  if (updateStatic) { // retrieve boundaries
440  cache.m_staticBoundaries.clear();
441  const auto& bounds = cache.m_currentStatic->boundarySurfaces();
442  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
443  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
444  cache.m_staticBoundaries.emplace_back(&surf, true);
445  }
446 
447  cache.m_detachedVols.clear();
448  cache.m_detachedBoundaries.clear();
449  cache.m_denseVols.clear();
450  cache.m_denseBoundaries.clear();
451  cache.m_layers.clear();
452  cache.m_navigLays.clear();
453 
454  // new: ID volumes may have special material layers ( entry layers ) - add them here
455  // if (cache.m_currentStatic->entryLayerProvider()) {
456  // const std::vector<const Trk::Layer*>& entryLays = cache.m_currentStatic->entryLayerProvider()->layers();
457  // for (unsigned int i=0; i < entryLays.size(); i++) {
458  // if (entryLays[i]->layerType()>0 || entryLays[i]->layerMaterialProperties()) {
459  // cache.m_layers.push_back(std::pair<const
460  // Trk::Surface*,Trk::BoundaryCheck>(&(entryLays[i]->surfaceRepresentation()),true));
461  // cache.m_navigLays.push_back(std::pair<const Trk::TrackingVolume*,const Trk::Layer*> (cache.m_currentStatic,entryLays[i])
462  // );
463  // Trk::DistanceSolution distSol = cache.m_layers.back().first->straightLineDistanceEstimate(currPar->position(),
464  //
465  //
466  //
467  // currPar->momentum().normalized());
468  // }
469  // }
470  // }
471 
472  // detached volume boundaries
474  if (!detVols.empty()) {
476  for (; iTer != detVols.end(); ++iTer) {
477  // active station ?
478  const Trk::Layer *layR = (*iTer)->layerRepresentation();
479  bool active = layR && layR->layerType();
480  const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
481  if (active) {
482  cache.m_detachedVols.emplace_back(*iTer,
483  detBounds.size());
484  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
485  const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
486  cache.m_detachedBoundaries.emplace_back(&surf, true);
487  }
488  } else if (cache.m_currentStatic->geometrySignature() != Trk::MS ||
489  !m_useMuonMatApprox ||
490  (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
491  "PERM") { // retrieve
492  // inert
493  // detached
494  // objects
495  // only if
496  // needed
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();
503  cache.m_denseBoundaries.emplace_back(&surf, true);
504  }
505  }
506  Trk::ArraySpan<const Trk::Layer* const> confLays = (*iTer)->trackingVolume()->confinedArbitraryLayers();
507  if (!(*iTer)->trackingVolume()->confinedDenseVolumes().empty() || (confLays.size() > detBounds.size())) {
508  cache.m_detachedVols.emplace_back(*iTer, detBounds.size());
509  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
510  const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
511  cache.m_detachedBoundaries.emplace_back(&surf, true);
512  }
513  } else if (!confLays.empty()) {
514  for (const Trk::Layer* const lIt : confLays) {
515  cache.m_layers.emplace_back(&(lIt->surfaceRepresentation()),
516  true);
517  cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
518  }
519  }
520  }
521  }
522  }
523  cache.m_denseResolved = std::pair<unsigned int, unsigned int> (cache.m_denseVols.size(), cache.m_denseBoundaries.size());
524  cache.m_layerResolved = cache.m_layers.size();
525  }
526 
527  cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_staticBoundaries.begin(), cache.m_staticBoundaries.end());
528 
529  // resolve the use of dense volumes
530  cache.m_dense = (cache.m_currentStatic->geometrySignature() == Trk::MS && m_useMuonMatApprox) ||
531  (cache.m_currentStatic->geometrySignature() != Trk::MS && m_useDenseVolumeDescription);
532 
533  // reset remaining counters
534  cache.m_currentDense = cache.m_dense ? cache.m_currentStatic : cache.m_highestVolume;
535  cache.m_navigBoundaries.clear();
536  if (cache.m_denseVols.size() > cache.m_denseResolved.first) {
537  cache.m_denseVols.resize(cache.m_denseResolved.first);
538  }
539  while (cache.m_denseBoundaries.size() > cache.m_denseResolved.second) {
540  cache.m_denseBoundaries.pop_back();
541  }
542  if (cache.m_layers.size() > cache.m_layerResolved) {
543  cache.m_navigLays.resize(cache.m_layerResolved);
544  }
545  while (cache.m_layers.size() > cache.m_layerResolved) {
546  cache.m_layers.pop_back();
547  }
548 
549  // current detached volumes
550  // collect : subvolume boundaries, ordered/unordered layers, confined dense volumes
552  // const Trk::DetachedTrackingVolume* currentActive = 0;
553  std::vector<std::pair<const Trk::TrackingVolume *, unsigned int> > navigVols;
554 
555  gp = currPar->position();
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();
561  bool active = layR && layR->layerType();
562  if (active && !m_resolveActive) {
563  continue;
564  }
565  if (!active && cache.m_currentStatic->geometrySignature() == Trk::MS &&
566  m_useMuonMatApprox && (*dIter)->name().substr((*dIter)->name().size() - 4, 4) != "PERM") {
567  continue;
568  }
569  const Trk::TrackingVolume *dVol = (*dIter)->trackingVolume();
570  // detached volume exit ?
571  bool dExit = m_navigator->atVolumeBoundary(currPar, dVol, dir, nextVol, m_tolerance) && !nextVol;
572  if (dExit) {
573  continue;
574  }
575  // inert material
576  const auto& confinedDense = dVol->confinedDenseVolumes();
577  const auto& confinedLays = dVol->confinedArbitraryLayers();
578 
579  if (!active && confinedDense.empty() && confinedLays.empty()) {
580  continue;
581  }
582  const auto &bounds = dVol->boundarySurfaces();
583  if (!active && confinedDense.empty() && confinedLays.size() <= bounds.size()) {
584  continue;
585  }
586  if (!confinedDense.empty() || !confinedLays.empty()) {
587  navigVols.emplace_back(dVol, bounds.size());
588  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
589  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
590  cache.m_navigBoundaries.emplace_back(&surf, true);
591  }
592  // collect dense volume boundary
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++) {
599  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
600  cache.m_denseBoundaries.emplace_back(&surf, true);
601  }
602  }
603  }
604  // collect unordered layers
605  if (!confinedLays.empty()) {
606  for (const auto *confinedLay : confinedLays) {
607  cache.m_layers.emplace_back(&(confinedLay->surfaceRepresentation()), true);
608  cache.m_navigLays.emplace_back(dVol, confinedLay);
609  }
610  }
611  } else { // active material
612  const Trk::TrackingVolume *detVol = dVol->associatedSubVolume(gp);
613  if (!detVol && dVol->confinedVolumes()) {
614  std::span<Trk::TrackingVolume const * const> subvols = dVol->confinedVolumes()->arrayObjects();
615  for (const auto *subvol : subvols) {
616  if (subvol->inside(gp, m_tolerance)) {
617  detVol = subvol;
618  break;
619  }
620  }
621  }
622 
623  if (!detVol) {
624  detVol = dVol;
625  }
626  bool vExit = m_navigator->atVolumeBoundary(currPar, detVol, dir, nextVol, m_tolerance) && nextVol != detVol;
627  if (vExit && nextVol && nextVol->inside(gp, m_tolerance)) {
628  detVol = nextVol;
629  vExit = false;
630  }
631  if (!vExit) {
632  const auto &bounds = detVol->boundarySurfaces();
633  navigVols.emplace_back(detVol, bounds.size());
634  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
635  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
636  cache.m_navigBoundaries.emplace_back(&surf, true);
637  }
638  if (detVol->zOverAtimesRho() != 0.) {
639  cache.m_denseVols.emplace_back(detVol, bounds.size());
640  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
641  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
642  cache.m_denseBoundaries.emplace_back(&surf, true);
643  }
644  }
645  // layers ?
646  if (detVol->confinedLayers()) {
647  if (m_robustSampling || cache.m_currentStatic->geometrySignature() == Trk::MS) {
648  std::span<Trk::Layer const * const> cLays = detVol->confinedLayers()->arrayObjects();
649  for (const auto *cLay : cLays) {
650  if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
651  cache.m_layers.emplace_back(&(cLay->surfaceRepresentation()), true);
652  cache.m_navigLays.emplace_back(cache.m_currentStatic,
653  cLay);
654  }
655  }
656  } else {
657  const Trk::Layer *lay = detVol->associatedLayer(gp);
658  // if (lay && ( (*dIter)->layerRepresentation()
659  // &&(*dIter)->layerRepresentation()->layerType()>0 ) ) currentActive=(*dIter);
660  if (lay) {
661  cache.m_layers.emplace_back(&(lay->surfaceRepresentation()),
662  true);
663  cache.m_navigLays.emplace_back(detVol, lay);
664  }
665  const Trk::Layer *nextLayer = detVol->nextLayer(currPar->position(),
666  dir * currPar->momentum().normalized(), true);
667  if (nextLayer && nextLayer != lay) {
668  cache.m_layers.emplace_back(&(nextLayer->surfaceRepresentation()), true);
669  cache.m_navigLays.emplace_back(detVol, nextLayer);
670  }
671  }
672  } else if (!detVol->confinedArbitraryLayers().empty()) {
674  for (const auto *layer : layers) {
675  cache.m_layers.emplace_back(&(layer->surfaceRepresentation()), true);
676  cache.m_navigLays.emplace_back(detVol, layer);
677  }
678  }
679  }
680  }
681  }
682 
683  // confined layers
684  if (cache.m_currentStatic->confinedLayers() && updateStatic) {
685  // if ( cache.m_currentStatic->confinedLayers() ) {
686  if (m_robustSampling || cache.m_currentStatic->geometrySignature() == Trk::MS) {
687  std::span<Trk::Layer const * const> cLays = cache.m_currentStatic->confinedLayers()->arrayObjects();
688  for (const auto *cLay : cLays) {
689  if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
690  cache.m_layers.emplace_back(&(cLay->surfaceRepresentation()),
691  true);
692  cache.m_navigLays.emplace_back(cache.m_currentStatic, cLay);
693  }
694  }
695  } else {
696  // * this does not work - debug !
697  const Trk::Layer *lay = cache.m_currentStatic->associatedLayer(gp);
698  // if (!lay) {
699  // lay = cache.m_currentStatic->associatedLayer(gp+m_tolerance*parm.momentum().normalized());
700  // std::cout<<" find input associated layer, second attempt:"<< lay<< std::endl;
701  // }
702  if (lay) {
703  cache.m_layers.emplace_back(&(lay->surfaceRepresentation()),
704  Trk::BoundaryCheck(false));
705  cache.m_navigLays.emplace_back(cache.m_currentStatic, lay);
706  const Trk::Layer *nextLayer = lay->nextLayer(currPar->position(), dir * currPar->momentum().normalized());
707  if (nextLayer && nextLayer != lay) {
708  cache.m_layers.emplace_back(&(nextLayer->surfaceRepresentation()),
709  Trk::BoundaryCheck(false));
710  cache.m_navigLays.emplace_back(cache.m_currentStatic,
711  nextLayer);
712  }
713  const Trk::Layer *backLayer = lay->nextLayer(currPar->position(), -dir * currPar->momentum().normalized());
714  if (backLayer && backLayer != lay) {
715  cache.m_layers.emplace_back(&(backLayer->surfaceRepresentation()),
716  Trk::BoundaryCheck(false));
717  cache.m_navigLays.emplace_back(cache.m_currentStatic,
718  backLayer);
719  }
720  }
721  }
722  }
723 
724  // cache.m_navigSurfs contains destination surface (if it exists), static volume boundaries
725  // complete with TG cache.m_layers/dynamic layers, cache.m_denseBoundaries, cache.m_navigBoundaries, m_detachedBoundaries
726 
727  if (!cache.m_layers.empty()) {
728  cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_layers.begin(), cache.m_layers.end());
729  }
730  if (!cache.m_denseBoundaries.empty()) {
731  cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_denseBoundaries.begin(), cache.m_denseBoundaries.end());
732  }
733  if (!cache.m_navigBoundaries.empty()) {
734  cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_navigBoundaries.begin(), cache.m_navigBoundaries.end());
735  }
736  if (!cache.m_detachedBoundaries.empty()) {
737  cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_detachedBoundaries.begin(), cache.m_detachedBoundaries.end());
738  }
739 
740 
741  // current dense
742  cache.m_currentDense = cache.m_highestVolume;
743  if (cache.m_dense && cache.m_denseVols.empty()) {
744  cache.m_currentDense = cache.m_currentStatic;
745  } else {
746  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
747  const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
748  if (dVol->inside(currPar->position(), m_tolerance) && dVol->zOverAtimesRho() != 0.) {
749  if (!m_navigator->atVolumeBoundary(currPar, dVol, dir, nextVol, m_tolerance) || nextVol == dVol) {
750  cache.m_currentDense = dVol;
751  }
752  }
753  }
754  }
755 
756  // before propagation, loop over layers and collect hits
757  if (cache.m_hitVector) {
758  for (unsigned int i = 0; i < cache.m_navigLays.size(); i++) {
759  if (cache.m_navigLays[i].second->layerType() > 0 && cache.m_navigLays[i].second->isOnLayer(currPar->position())) {
760  if (cache.m_navigLays[i].second->surfaceArray()) {
761  // perform the overlap Search on this layer
762  ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on input layer.");
763  overlapSearch(cache,*m_subPropagators[0], *currPar, *currPar, *cache.m_navigLays[i].second, timeLim.time, dir, true,
764  particle);
765  } else {
766  ATH_MSG_VERBOSE(" [o] Collecting intersection with active input layer.");
767  cache.m_hitVector->emplace_back(currPar->uniqueClone(), timeLim.time, cache.m_navigLays[i].second->layerType(), 0.);
768  }
769  } // ------------------------------------------------- Fatras mode off -----------------------------------
770  }
771  }
772 
773  // ready to propagate
774  // till: A/ static volume boundary(bcheck=true) , B/ material layer(bcheck=true), C/ destination surface(bcheck=false)
775  // update of cache.m_navigSurfs required if I/ entry into new navig volume, II/ exit from currentActive without overlaps
776 
777  nextVol = nullptr;
778  while (currPar) {
779  std::vector<unsigned int> solutions;
780  // double time_backup = timeLim.time;
781  // double path_backup = cache.m_path.x0Collected;
782  ATH_MSG_DEBUG(" [+] Starting propagation at position " << positionOutput(currPar->position())
783  << " (current momentum: " << currPar->momentum().mag() <<
784  ")");
785  ATH_MSG_DEBUG(" [+] " << cache.m_navigSurfs.size() << " target surfaces in '" << cache.m_currentDense->volumeName() << "'."); //
786  // verify
787  // that
788  // material
789  // input
790  // makes
791  // sense
792  if (!(cache.m_currentDense->inside(currPar->position(), m_tolerance)
793  || m_navigator->atVolumeBoundary(currPar, cache.m_currentDense, dir, assocVol, m_tolerance))) {
794  cache.m_currentDense = cache.m_highestVolume;
795  }
796  const Trk::TrackParameters* nextPar = m_stepPropagator
797  ->propagateT(ctx,
798  *currPar,
799  cache.m_navigSurfs,
800  dir,
801  m_fieldProperties,
802  particle,
803  solutions,
804  cache.m_path,
805  timeLim,
806  true,
807  cache.m_currentDense,
808  cache.m_hitVector)
809  .release();
810  ATH_MSG_VERBOSE(" [+] Propagation done. ");
811  if (nextPar) {
812  ATH_MSG_DEBUG(" [+] Position after propagation - at " << positionOutput(
813  nextPar->position()) << ", timed at " << timeLim.time);
814  }
815 
816  if (!nextPar) {
817  ATH_MSG_DEBUG(" [!] Propagation failed, return 0");
818  cache.m_parametersAtBoundary.boundaryInformation(cache.m_currentStatic, nextPar, nextPar);
819  return returnParameters;
820  }
821 
822  throwIntoGarbageBin(cache,nextPar);
823 
824  // material update has been done already by the propagator
825  if (cache.m_path.x0Max > 0. &&
826  ((cache.m_path.process < 100 && cache.m_path.x0Collected >= cache.m_path.x0Max) ||
827  (cache.m_path.process > 100 && cache.m_path.l0Collected >= cache.m_path.x0Max))) {
828  // trigger presampled interaction, provide material properties if needed
829  // process interaction only if creation of secondaries allowed
830  if (cache.m_currentStatic->geometrySignature() == Trk::ID || m_caloMsSecondary) {
831  const Trk::Material *extMprop = cache.m_path.process > 100 ? cache.m_currentDense : nullptr;
832 
833  const Trk::TrackParameters* iPar =
834  m_updators[0]
835  ->interact(
836  timeLim.time, nextPar->position(), nextPar->momentum(), particle, cache.m_path.process, extMprop)
837  .release();
838 
839  if (!iPar) {
840  return returnParameters;
841  }
842 
843  throwIntoGarbageBin(cache,iPar);
844  return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim, dir, particle, nextGeoID, destVol);
845  } // kill the particle without trace ( some validation info can be included here eventually )
846  return returnParameters;
847 
848  }
849  // decay ?
850  if (timeLim.tMax > 0. && timeLim.time >= timeLim.tMax) {
851  // process interaction only if creation of secondaries allowed
852  if (cache.m_currentStatic->geometrySignature() == Trk::ID || m_caloMsSecondary) {
853  // trigger presampled interaction
854  const Trk::TrackParameters* iPar =
855  m_updators[0]
856  ->interact(timeLim.time, nextPar->position(), nextPar->momentum(), particle, timeLim.process)
857  .release();
858  if (!iPar) {
859  return returnParameters;
860  }
861  throwIntoGarbageBin(cache,iPar);
862  return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim, dir, particle, nextGeoID, destVol);
863  } // kill the particle without trace ( some validation info can be included here eventually )
864  return returnParameters;
865 
866  }
867 
868  // check missing volume boundary
869  if (nextPar && !(cache.m_currentDense->inside(nextPar->position(), m_tolerance)
870  || m_navigator->atVolumeBoundary(nextPar, cache.m_currentDense, dir, assocVol, m_tolerance))) {
871  ATH_MSG_DEBUG(" [!] ERROR: missing volume boundary for volume" << cache.m_currentDense->volumeName());
872  }
873 
874 
875  ATH_MSG_DEBUG(" [+] Number of intersection solutions: " << solutions.size());
876 
877  unsigned int iSol = 0;
878  while (iSol < solutions.size()) {
879  if (solutions[iSol] < iDest) {
880  return nextPar->uniqueClone();
881  } if (solutions[iSol] < iDest + cache.m_staticBoundaries.size()) {
882  // material attached ?
883  const Trk::Layer *mb = cache.m_navigSurfs[solutions[iSol]].first->materialLayer();
884  if (mb && m_includeMaterialEffects) {
885  if (mb->layerMaterialProperties() && mb->layerMaterialProperties()->fullMaterial(nextPar->position())) {
886  const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
887  nextPar = currentUpdator ? currentUpdator
888  ->update(nextPar,
889  *mb,
890  timeLim,
891  cache.m_path,
893  dir,
894  particle)
895  .release()
896  : nextPar;
897 
898  if (!nextPar) {
899  ATH_MSG_VERBOSE(" [+] Update may have killed neutral track - return.");
901  return returnParameters;
902  }
903  throwIntoGarbageBin(cache,nextPar);
904  } else { // material layer without material ?
905  ATH_MSG_VERBOSE(" boundary layer without material:" << mb->layerIndex());
906  }
907  }
908 
909  // static volume boundary; return to the main loop
910  unsigned int index = solutions[iSol] - iDest;
911 
912  // use global coordinates to retrieve attached volume (just for static!)
913  nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
914  nextPar->position(), nextPar->momentum(), dir);
915  // double check the next volume
916  if (nextVol && !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(), 0.))) {
918  " [!] WARNING: wrongly assigned static volume ?" << cache.m_currentStatic->volumeName() << "->" <<
919  nextVol->volumeName());
920  nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
921  nextPar->position() + 0.01 * dir * nextPar->momentum().normalized());
922  if (nextVol) {
923  ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
924  }
925  }
926  // end double check - to be removed after validation of the geometry gluing
927  if (nextVol != cache.m_currentStatic) {
928  cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
929  ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
930  if (m_navigator->atVolumeBoundary(nextPar, cache.m_currentStatic, dir, assocVol,
931  m_tolerance) && assocVol != nextVol) {
932  cache.m_currentDense = cache.m_dense ? nextVol : cache.m_highestVolume;
933  }
934  // no next volume found --- end of the world
935  if (!nextVol) {
936  ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
937  nextPar->position()) << ", timed at " << timeLim.time);
939  if (!destVol) {
940  return nextPar->uniqueClone();
941  }
942  }
943  // next volume found and parameters are at boundary
944  if (nextVol /*&& nextPar nextPar is dereferenced anyway */) {
945  ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
946  ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
947  if (!destVol && cache.m_currentStatic->geometrySignature() != nextVol->geometrySignature()) {
948  nextGeoID = nextVol->geometrySignature();
949  return nextPar->uniqueClone();
950  }
951  }
952  return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
953  }
954  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size()) {
955  // next layer; don't return passive material layers unless required
956  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size();
957  const Trk::Layer *nextLayer = cache.m_navigLays[index].second;
958  // material update ?
959  // bool matUp = nextLayer->layerMaterialProperties() && m_includeMaterialEffects &&
960  // nextLayer->isOnLayer(nextPar->position());
961  bool matUp = nextLayer->fullUpdateMaterialProperties(*nextPar) && m_includeMaterialEffects &&
962  nextLayer->isOnLayer(nextPar->position());
963  // material update
964  const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
965  if (matUp) {
966  double pIn = nextPar->momentum().mag();
967  nextPar = currentUpdator ? currentUpdator->update(nextPar, *nextLayer, timeLim, cache.m_path,
969  particle).release() : nextPar;
970  if (!nextPar) {
971  ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
973  return returnParameters;
974  }
976  " Layer energy loss:" << nextPar->momentum().mag() - pIn << "at position:" << nextPar->position() << ", current momentum:" <<
977  nextPar->momentum());
978  throwIntoGarbageBin(cache,nextPar);
979 
980  }
981  // active surface intersections ( Fatras hits ...)
982  if (cache.m_hitVector && particle != Trk::neutron) {
983  if (nextLayer->surfaceArray()) {
984  // perform the overlap Search on this layer
985  ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on layer.");
986  overlapSearch(cache,*m_subPropagators[0], *currPar, *nextPar, *nextLayer, timeLim.time, dir, true, particle);
987  } else if (nextLayer->layerType() > 0 && nextLayer->isOnLayer(nextPar->position())) {
988  ATH_MSG_VERBOSE(" [o] Collecting intersection with active layer.");
989  cache.m_hitVector->emplace_back(nextPar->uniqueClone(), timeLim.time, nextLayer->layerType(), 0.);
990  }
991  } // ------------------------------------------------- Fatras mode off -----------------------------------
992 
993  // TODO : debug the retrieval of next layer
994  if (!m_robustSampling && cache.m_currentStatic->geometrySignature() != Trk::MS) {
995  if (cache.m_navigLays[index].first && cache.m_navigLays[index].first->confinedLayers()) {
996  const Trk::Layer *newLayer = nextLayer->nextLayer(nextPar->position(),
997  dir * nextPar->momentum().normalized());
998  if (newLayer && newLayer != nextLayer) {
999  bool found = false;
1000  int replace = -1;
1001  for (unsigned int i = 0; i < cache.m_navigLays.size(); i++) {
1002  if (cache.m_navigLays[i].second == newLayer) {
1003  found = true;
1004  break;
1005  }
1006  if (cache.m_navigLays[i].second != nextLayer) {
1007  replace = i;
1008  }
1009  }
1010  if (!found) {
1011  if (replace > -1) {
1012  cache.m_navigLays[replace].second = newLayer;
1013  cache.m_navigSurfs[solutions[iSol] + replace - index].first = &(newLayer->surfaceRepresentation());
1014  } else {
1015  // can't insert a surface in middle
1016  return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
1017  }
1018  }
1019  }
1020  }
1021  }
1022  currPar = nextPar;
1023  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() + cache.m_denseBoundaries.size()) {
1024  // dense volume boundary
1025  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size();
1026  std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >::iterator dIter = cache.m_denseVols.begin();
1027  while (dIter != cache.m_denseVols.end() && index >= (*dIter).second) {
1028  index -= (*dIter).second;
1029  ++dIter;
1030  }
1031  if (dIter != cache.m_denseVols.end()) {
1032  currVol = (*dIter).first;
1033  nextVol = (currVol->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
1034  // the boundary orientation is not reliable
1035  Amg::Vector3D tp = nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
1036  if (!nextVol || !nextVol->inside(tp, m_tolerance)) { // search for dense volumes
1037  cache.m_currentDense = cache.m_highestVolume;
1038  if (cache.m_dense && cache.m_denseVols.empty()) {
1039  cache.m_currentDense = cache.m_currentStatic;
1040  } else {
1041  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
1042  const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
1043  if (dVol->inside(tp, m_tolerance) && dVol->zOverAtimesRho() != 0.) {
1044  cache.m_currentDense = dVol;
1045  ATH_MSG_DEBUG(" [+] Next dense volume found: '" << cache.m_currentDense->volumeName() << "'.");
1046  break;
1047  }
1048  } // loop over dense volumes
1049  }
1050  } else {
1051  cache.m_currentDense = nextVol;
1052  ATH_MSG_DEBUG(" [+] Next dense volume: '" << cache.m_currentDense->volumeName() << "'.");
1053  }
1054  }
1055  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() + cache.m_denseBoundaries.size()
1056  + cache.m_navigBoundaries.size()) {
1057  // navig volume boundary
1058  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size() -
1059  cache.m_denseBoundaries.size();
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;
1063  ++nIter;
1064  }
1065  if (nIter != navigVols.end()) {
1066  currVol = (*nIter).first;
1067  nextVol = ((*nIter).first->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
1068  if (!nextVol) {
1069  ATH_MSG_DEBUG(" [+] Navigation volume boundary, leaving volume '"
1070  << currVol->volumeName() << "'.");
1071  } else {
1072  ATH_MSG_DEBUG(" [+] Navigation volume boundary, entering volume '" << nextVol->volumeName() << "'.");
1073  }
1074  currPar = nextPar;
1075  // return only if detached volume boundaries not collected
1076  // if ( nextVol || !detachedBoundariesIncluded )
1077  if (nextVol) {
1078  return extrapolateToVolumeWithPathLimit(cache,*currPar, timeLim, dir, particle, nextGeoID, destVol);
1079  }
1080  }
1081  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() + cache.m_denseBoundaries.size()
1082  + cache.m_navigBoundaries.size() + cache.m_detachedBoundaries.size()) {
1083  // detached volume boundary
1084  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size()
1085  - cache.m_denseBoundaries.size() - cache.m_navigBoundaries.size();
1086  std::vector< std::pair<const Trk::DetachedTrackingVolume *,
1087  unsigned int> >::iterator dIter = cache.m_detachedVols.begin();
1088  while (dIter != cache.m_detachedVols.end() && index >= (*dIter).second) {
1089  index -= (*dIter).second;
1090  ++dIter;
1091  }
1092  if (dIter != cache.m_detachedVols.end()) {
1093  currVol = (*dIter).first->trackingVolume();
1094  nextVol =
1095  ((*dIter).first->trackingVolume()->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
1096  if (!nextVol) {
1097  ATH_MSG_DEBUG(" [+] Detached volume boundary, leaving volume '" << currVol->volumeName() << "'.");
1098  } else {
1099  ATH_MSG_DEBUG(" [+] Detached volume boundary, entering volume '" << nextVol->volumeName() << "'.");
1100  }
1101  currPar = nextPar;
1102  // if ( nextVol || !detachedBoundariesIncluded)
1103  if (nextVol) {
1104  return extrapolateToVolumeWithPathLimit(cache, *currPar, timeLim, dir, particle, nextGeoID, destVol);
1105  }
1106  }
1107  }
1108  iSol++;
1109  }
1110  currPar = nextPar;
1111  }
1112 
1113  return returnParameters;
1114 }
1115 
1116 void
1118  const IPropagator &prop,
1119  const TrackParameters &parm,
1120  const TrackParameters &parsOnLayer,
1121  const Layer &lay,
1122  // const TrackingVolume& tvol,
1123  float time,
1125  const BoundaryCheck& bcheck, // bcheck
1126  ParticleHypothesis particle,
1127  bool startingLayer) const {
1128 
1129  const EventContext& ctx = Gaudi::Hive::currentContext();
1130  // indicate destination layer
1131  bool isDestinationLayer = false;
1132  // start and end surface for on-layer navigation
1133  // -> take the start surface if ther parameter surface is owned by detector element
1134  const Trk::Surface *startSurface = ((parm.associatedSurface()).associatedDetectorElement() && startingLayer) ?
1135  &parm.associatedSurface() : nullptr;
1136  const Trk::Surface *endSurface = nullptr;
1137  // - the best detSurface to start from is the one associated to the detector element
1138  const Trk::Surface *detSurface = (parsOnLayer.associatedSurface()).associatedDetectorElement() ?
1139  &parsOnLayer.associatedSurface() : nullptr;
1140 
1141  ATH_MSG_VERBOSE(" [o] OverlapSearch called " << (startSurface ? "with " : "w/o ") << "start, "
1142  << (endSurface ? "with " : "w/o ") << "end surface.");
1143 
1144  if (!detSurface) {
1145  // of parsOnLayer are different from parm, then local position is safe, because the extrapolation
1146  // to the detector surface has been done !
1147  detSurface = isDestinationLayer ? lay.subSurface(parsOnLayer.localPosition()) : lay.subSurface(
1148  parsOnLayer.position());
1149  if (detSurface) {
1150  ATH_MSG_VERBOSE(" [o] Detector surface found through subSurface() call");
1151  } else {
1152  ATH_MSG_VERBOSE(" [o] No Detector surface found on this layer.");
1153  }
1154  } else {
1155  ATH_MSG_VERBOSE(" [o] Detector surface found through parameter on layer association");
1156  }
1157 
1158  // indicate the start layer
1159  bool isStartLayer = (detSurface && detSurface == startSurface);
1160 
1161  const Trk::TrackParameters *detParameters = nullptr;
1162  // the temporary vector (might have to be ordered)
1163  std::vector<const Trk::TrackParameters*> detParametersOnLayer;
1164  bool reorderDetParametersOnLayer = false;
1165  // the first test for the detector surface to be hit (false test)
1166  // - only do this if the parameters aren't on the surface
1167  // (i.e. search on the start layer or end layer)
1168  if (isDestinationLayer) {
1169  detParameters = (&parsOnLayer);
1170  } else if (isStartLayer) {
1171  detParameters = (&parm);
1172  } else if (detSurface) {
1173  // detParameters = prop.propagate(parm, *detSurface, dir, false, tvol, particle);
1174  detParameters = prop.propagate(ctx,parm, *detSurface, dir, false, m_fieldProperties, particle).release();
1175  }
1176 
1177  // set the surface hit to true, it is anyway overruled
1178  bool surfaceHit = true;
1179  if (detParameters &&
1180  !isStartLayer &&
1181  !isDestinationLayer) {
1182  ATH_MSG_VERBOSE(" [o] First intersection with Detector surface: " << *detParameters);
1183  // for the later use in the overlapSearch
1184  surfaceHit = detParameters && detSurface ? detSurface->isOnSurface(detParameters->position()) : 0; // ,bcheck) -
1185  // creates
1186  // problems on
1187  // start layer;
1188  // check also for start/endSurface on this level
1189 
1190  surfaceHit = (surfaceHit && startSurface) ?
1191  ((detParameters->position() - parm.position()).dot(dir * parm.momentum().normalized()) >
1192  0) : surfaceHit;
1193  surfaceHit = (surfaceHit && endSurface) ?
1194  ((detParameters->position() - parsOnLayer.position()).dot(dir * parsOnLayer.momentum().normalized()) <
1195  0) : surfaceHit;
1196 
1197  // surface is hit within bounds (or at least with given boundary check directive) -> it counts
1198  // surface hit also survived start/endsurface search
1199  //
1200  // Convention for Fatras: always apply the full update on the last parameters
1201  // of the gathered vector (no pre/post schema)
1202  // don't record a hit on the destination surface
1203  if (surfaceHit &&
1204  detSurface != startSurface) {
1205  ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded ! ");
1206  // push into the temporary vector
1207  detParametersOnLayer.push_back(detParameters);
1208  } else if (detParameters) {
1209  // no hit -> fill into the garbage bin
1210  ATH_MSG_VERBOSE(" [-] Detector surface hit cancelled through bounds check or start/end surface check.");
1211  throwIntoGarbageBin(cache,detParameters);
1212  }
1213  }
1214 
1215  // search for the overlap ------------------------------------------------------------------------
1216  if (detParameters) {
1217  // retrive compatible subsurfaces
1218  std::vector<Trk::SurfaceIntersection> cSurfaces;
1219  size_t ncSurfaces = lay.compatibleSurfaces(cSurfaces, *detParameters, Trk::anyDirection, bcheck, false);
1220 
1221  // import from StaticEngine.icc
1222  if (ncSurfaces) {
1223  ATH_MSG_VERBOSE("found " << ncSurfaces << " candidate sensitive surfaces to test.");
1224  // now loop over the surfaces:
1225  // the surfaces will be sorted @TODO integrate pathLength propagation into this
1226  for (auto &csf : cSurfaces) {
1227  // propagate to the compatible surface, return types are (pathLimit failure is excluded by Trk::anyDirection for
1228  // the moment):
1229  const Trk::TrackParameters *overlapParameters = prop.propagate(ctx,
1230  parm,
1231  *(csf.object),
1233  true,
1234  m_fieldProperties,
1235  particle).release();
1236 
1237  if (overlapParameters) {
1238  ATH_MSG_VERBOSE(" [+] Overlap surface was hit, checking start/end surface condition.");
1239  // check on start / end surface for on-layer navigaiton action
1240  surfaceHit = (startSurface) ?
1241  ((overlapParameters->position() - parm.position()).dot(dir * parm.momentum().normalized()) >
1242  0) : true;
1243  surfaceHit = (surfaceHit && endSurface) ?
1244  ((overlapParameters->position() - parsOnLayer.position()).dot(dir *
1245  parsOnLayer.momentum().normalized())
1246  < 0) : surfaceHit;
1247  if (surfaceHit && csf.object!=detSurface) { //skipping the initial surface on which a hit has already been created
1248  ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded !");
1249  // distinguish whether sorting is needed or not
1250  reorderDetParametersOnLayer = true;
1251  // push back into the temporary vector
1252  detParametersOnLayer.push_back(overlapParameters);
1253  } else { // the parameters have been cancelled by start/end surface
1254  // no hit -> fill into the garbage bin
1255  ATH_MSG_VERBOSE(" [-] Detector surface hit cancelled through start/end surface check.");
1256  throwIntoGarbageBin(cache,overlapParameters);
1257  }
1258  }
1259  } // loop over test surfaces done
1260  } // there are compatible surfaces
1261  } // ---------------------------------------------------------------------------------------------
1262 
1263  // push them into the parameters vector
1264  std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIter = detParametersOnLayer.begin();
1265  std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIterEnd = detParametersOnLayer.end();
1266 
1267  // reorder the track parameters if neccessary, the overlap descriptor did not provide the ordered surfaces
1268  if (reorderDetParametersOnLayer) {
1269  // sort to reference of incoming parameters
1270  Trk::TrkParametersComparisonFunction parameterSorter(parm.position());
1271  sort(detParametersOnLayer.begin(), detParametersOnLayer.end(), parameterSorter);
1272  }
1273 
1274  // after sorting : reset the iterators
1275  parsOnLayerIter = detParametersOnLayer.begin();
1276  parsOnLayerIterEnd = detParametersOnLayer.end();
1277  // now fill them into the parameter vector -------> hit creation done <----------------------
1278  for (; parsOnLayerIter != parsOnLayerIterEnd; ++parsOnLayerIter) {
1279  if (cache.m_hitVector) {
1280  cache.m_hitVector->emplace_back(
1281  std::unique_ptr<const Trk::TrackParameters>(*parsOnLayerIter),
1282  time,
1283  0,
1284  0.);
1285  }
1286  }
1287 }
1288 
1289 std::string
1291  std::stringstream outStream;
1292 
1293  if (m_printRzOutput) {
1294  outStream << "[r,phi,z] = [ " << pos.perp() << ", " << pos.phi() << ", " << pos.z() << " ]";
1295  } else {
1296  outStream << "[xyz] = [ " << pos.x() << ", " << pos.y() << ", " << pos.z() << " ]";
1297  }
1298  return outStream.str();
1299 }
1300 
1301 std::string
1303  std::stringstream outStream;
1304 
1305  outStream << "[eta,phi] = [ " << mom.eta() << ", " << mom.phi() << " ]";
1306  return outStream.str();
1307 }
1308 
1309 void
1311  const Trk::TrackParameters *trPar) const {
1312  // empty the garbage
1315 
1316  bool throwCurrent = false;
1317 
1318  for (; garbageIter != garbageEnd; ++garbageIter) {
1319  if (garbageIter->first && garbageIter->first != trPar) {
1320  delete (garbageIter->first);
1321  }
1322  if (garbageIter->first && garbageIter->first == trPar) {
1323  throwCurrent = true;
1324  }
1325  }
1326 
1327  cache.m_garbageBin.clear();
1328  if (throwCurrent) {
1329  throwIntoGarbageBin(cache,trPar);
1330  }
1331 }
1332 
1333 // the validation action -> propagated to the SubTools
1334 void
1336  // record the updator validation information
1337  for (const auto *subUpdator : m_subUpdators) {
1338  subUpdator->validationAction();
1339  }
1340  // record the navigator validation information
1341 }
1342 
1343 std::unique_ptr<const Trk::TrackParameters>
1345  Trk::PathLimit &pathLim, Trk::TimeLimit &timeLim,
1347  Trk::ParticleHypothesis particle,
1348  std::vector<Trk::HitInfo> * &hitInfo,
1349  Trk::GeometrySignature &nextGeoID,
1350  const Trk::TrackingVolume *boundaryVol) const {
1351  Trk::TimedExtrapolator::Cache cache(m_maxNavigSurf);
1352 // extrapolation method intended for simulation of particle decay; collects the material up to pre-defined limit and
1353 // triggers
1354 // material interaction
1355 // possible outcomes:1/ returns curvilinear parameters after reaching the maximal path (if to be destroyed)
1356 // 2/ returns parameters at destination volume boundary
1357 // 3/ returns 0 ( particle stopped ) but keeps material and timing info
1358 
1359  ATH_MSG_DEBUG(
1360  "M-[" << ++cache.m_methodSequence << "] transportNeutralsWithPathLimit(...) " << pathLim.x0Max << ", from " <<
1361  parm.position());
1362 
1363  // reset the path ( in x0 !!)
1364  cache.m_path = PathLimit(pathLim.x0Max - pathLim.x0Collected, pathLim.process); // collect material locally
1365 
1366  // initialize time info
1367  cache.m_time = timeLim.time;
1368 
1369  // initialize hit vector
1370  cache.m_hitVector = hitInfo;
1371 
1373 
1374  // if no input volume, define as highest volume
1375  // const Trk::TrackingVolume* destVolume = boundaryVol ? boundaryVol : m_navigator->highestVolume();
1376  cache.m_currentStatic = nullptr;
1377  if (boundaryVol && !boundaryVol->inside(parm.position(), m_tolerance)) {
1378  return nullptr;
1379  }
1380 
1381  cache.m_particleMass = Trk::ParticleMasses::mass[particle];
1382 
1383  // extrapolate to destination volume boundary with path limit
1384  std::unique_ptr<const Trk::TrackParameters> returnParms =
1385  transportToVolumeWithPathLimit(
1386  cache, parm, timeLim, dir, particle, nextGeoID, boundaryVol);
1387 
1388  // save actual path on output
1389  if (cache.m_path.x0Collected > 0.) {
1390  pathLim.updateMat(cache.m_path.x0Collected, cache.m_path.weightedZ / cache.m_path.x0Collected, cache.m_path.l0Collected);
1391  }
1392 
1393  // return timing
1394  timeLim.time = cache.m_time;
1395 
1398  for (; garbageIter != garbageEnd; ++garbageIter) if (garbageIter->first) {
1399  if(garbageIter->first == returnParms.get()) {
1400  auto ret=returnParms->uniqueClone();
1401  ATH_MSG_DEBUG(" [+] garbage - at "
1402  << positionOutput(garbageIter->first->position())
1403  << " parm=" << garbageIter->first
1404  << " is the return param. Cloning to" << ret.get());
1405  returnParms=std::move(ret);
1406  }
1407  }
1408 
1409  return returnParms;
1410 }
1411 
1412 std::unique_ptr<const Trk::TrackParameters>
1415  const Trk::TrackParameters& parm,
1416  Trk::TimeLimit& timeLim,
1418  Trk::ParticleHypothesis particle,
1419  Trk::GeometrySignature& nextGeoID,
1420  const Trk::TrackingVolume* destVol) const
1421 {
1422  // returns:
1423  // A) curvilinear track parameters if path or time limit reached
1424  // B) boundary parameters (at destination volume boundary)
1425 
1426  // initialize the return parameters vector
1427  std::unique_ptr<const Trk::TrackParameters> returnParameters = nullptr;
1428  const Trk::TrackParameters *currPar = &parm;
1429  const Trk::TrackingVolume *currVol = nullptr;
1430  const Trk::TrackingVolume *nextVol = nullptr;
1431  const Trk::TrackingVolume *assocVol = nullptr;
1432  // int nEntryLays = 0;
1433  unsigned int iDest = 0;
1434 
1435  const EventContext& ctx = Gaudi::Hive::currentContext();
1436  // destination volume boundary ?
1437  if (destVol && m_navigator->atVolumeBoundary(currPar, destVol, dir, nextVol, m_tolerance) && nextVol != destVol) {
1438  return parm.uniqueClone();
1439  }
1440 
1441  // bool resolveActive = m_resolveActive;
1442  if (!cache.m_highestVolume) {
1443  cache.m_highestVolume = m_navigator->highestVolume(ctx);
1444  }
1445 
1446  emptyGarbageBin(cache,&parm);
1447  // transport surfaces: collect only those with valid intersection (easy to calculate for neutrals)
1448  if (cache.m_trSurfs.capacity() > m_maxNavigSurf) {
1449  cache.m_trSurfs.reserve(m_maxNavigSurf);
1450  }
1451  cache.m_trSurfs.clear();
1452 
1453  // target volume may not be part of tracking geometry
1454  if (destVol) {
1455  const Trk::TrackingVolume *tgVol = m_navigator->trackingGeometry(ctx)->trackingVolume(destVol->volumeName());
1456  if (!tgVol || tgVol != destVol) {
1457  const auto& bounds = destVol->boundarySurfaces();
1458  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
1459  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1461  dir * currPar->momentum().normalized());
1462  if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1463  // boundary check
1464  Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1465  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1466  iDest++;
1467  cache.m_trSurfs.emplace_back(&surf, distSol.first());
1468  } // valid intersection
1469  } // along path
1470  if (distSol.numberOfSolutions() > 1 && distSol.second() > 0.) {
1471  // boundary check
1472  Amg::Vector3D gp = currPar->position() + distSol.second() * dir * currPar->momentum().normalized();
1473  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1474  iDest++;
1475  cache.m_trSurfs.emplace_back(&surf, distSol.second());
1476  } // valid intersection
1477  }
1478  } // end loop over boundaries
1479  } // end process external volume
1480  }
1481 
1482  // resolve current position
1483  if (cache.m_parametersAtBoundary.nextParameters == currPar) {
1485  } else {
1486  const Amg::Vector3D& gp = parm.position();
1487  if (!cache.m_currentStatic || !cache.m_currentStatic->inside(gp, m_tolerance)) {
1488  cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1489 
1490  if (!cache.m_currentStatic ||
1491  !cache.m_currentStatic->inside(currPar->position() + 0.01 * dir * currPar->momentum().normalized(), 0.)) {
1492  cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(currPar->position()
1493  + 0.01 * dir *
1494  currPar->momentum().normalized());
1495  }
1496  }
1497 
1498  if (!cache.m_currentStatic) {
1499  // no next volume found --- end of the world
1500  ATH_MSG_DEBUG(" [+] Word boundary reached - at " << positionOutput(currPar->position()));
1502  return currPar->uniqueClone();
1503  }
1504  }
1505 
1506  // current frame volume known-retrieve geoID
1507  nextGeoID = cache.m_currentStatic->geometrySignature();
1508 
1509  // resolve active Calo volumes if hit info required
1510  if (cache.m_hitVector && nextGeoID == Trk::Calo) {
1511  const Trk::AlignableTrackingVolume *alignTV = dynamic_cast<const Trk::AlignableTrackingVolume *> (cache.m_currentStatic);
1512  if (alignTV) {
1513  const Trk::TrackParameters *aPar = transportInAlignableTV(cache,parm, timeLim, dir, particle, nextGeoID, alignTV).trPar;
1514  if (!aPar) {
1515  return returnParameters;
1516  }
1517  throwIntoGarbageBin(cache,aPar);
1518  return transportToVolumeWithPathLimit(cache,*aPar, timeLim, dir, particle, nextGeoID, destVol);
1519  }
1520  }
1521 
1522  // distance to static volume boundaries recalculated
1523  // retrieve boundaries along path
1524  cache.m_trStaticBounds.clear();
1525  const auto& bounds = cache.m_currentStatic->boundarySurfaces();
1526  for (unsigned int ib = 0; ib < bounds.size(); ++ib) {
1527  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1529  dir * currPar->momentum().normalized());
1530  if (distSol.numberOfSolutions() > 0 &&
1531  (distSol.currentDistance(false) > m_tolerance || distSol.numberOfSolutions() > 1) &&
1532  distSol.first() > m_tolerance) {
1533  double dist = distSol.first();
1534  // resolve multiple intersection solutions
1535  if (distSol.numberOfSolutions() > 1 && dist < m_tolerance && distSol.second() > dist) {
1536  dist = distSol.second();
1537  }
1538  // boundary check
1539  Amg::Vector3D gp = currPar->position() + dist * dir * currPar->momentum().normalized();
1540  if (surf.isOnSurface(gp, true, m_tolerance, m_tolerance)) {
1541  cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
1542  }
1543  } // along path
1544  if (distSol.numberOfSolutions() > 1 && distSol.second() > m_tolerance) {
1545  double dist = distSol.second();
1546  // boundary check
1547  Amg::Vector3D gp = currPar->position() + dist * dir * currPar->momentum().unit();
1548  if (surf.isOnSurface(gp, true, m_tolerance, m_tolerance)) {
1549  if (dist > m_tolerance) { // valid intersection
1550  cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
1551  }
1552  }
1553  } // along path
1554  } // end loop over boundaries
1555 
1556  if (cache.m_trStaticBounds.empty()) {
1558  " transportToVolumeWithPathLimit() - at " << currPar->position() << ", missing static volume boundary "
1559  << cache.m_currentStatic->volumeName() <<
1560  ": transport interrupted");
1561 
1562  ATH_MSG_DEBUG(
1563  "---> particle R,phi,z, momentum:" << currPar->position().perp() << "," << currPar->position().phi() << "," << currPar->position().z() << "," <<
1564  currPar->momentum());
1565  ATH_MSG_DEBUG("---> static volume position:" << cache.m_currentStatic->center());
1566  const Trk::CylinderVolumeBounds *cyl =
1567  dynamic_cast<const Trk::CylinderVolumeBounds *> (&(cache.m_currentStatic->volumeBounds()));
1568  if (cyl) {
1569  ATH_MSG_DEBUG(
1570  "---> cylinder volume dimensions:" << cyl->innerRadius() << "," << cyl->outerRadius() << "," <<
1571  cyl->halflengthZ());
1572  }
1573 
1574 
1575  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
1576  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1578  dir * currPar->momentum().unit());
1579  ATH_MSG_DEBUG(
1580  "---> decomposed boundary surface position, normal, estimated distance:" << ib << "," << surf.center() << "," <<
1581  surf.normal());
1582  ATH_MSG_DEBUG(
1583  "---> estimated distance to (first solution):boundary check:" << distSol.numberOfSolutions() << "," << distSol.first() << ":" <<
1584  surf.isOnSurface(currPar->position() + distSol.first() * dir * currPar->momentum().unit(), true,
1585  m_tolerance, m_tolerance));
1586  if (distSol.numberOfSolutions() > 1) {
1587  ATH_MSG_DEBUG("---> estimated distance to (second solution):boundary check:" << distSol.second() << "," <<
1588  surf.isOnSurface(currPar->position() + distSol.second() * dir * currPar->momentum().unit(), true,
1589  m_tolerance, m_tolerance));
1590  }
1591  }
1592 
1593  return returnParameters;
1594  } if (cache.m_trStaticBounds[0].distance < m_tolerance) {
1595  // TODO find out why this case (=exit from volume) haven't been handled by Navigator
1596  // ATH_MSG_WARNING( " recovering from glitch at the static volume boundary:"<<cache.m_trStaticBounds[0].distance );
1597 
1598  Amg::Vector3D gp = currPar->position() + m_tolerance * dir * currPar->momentum().unit();
1599  cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1600 
1601  if (cache.m_currentStatic) {
1602  return transportToVolumeWithPathLimit(cache,parm, timeLim, dir, particle, nextGeoID, destVol);
1603  }
1604  ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
1605  currPar->position()) << ", timed at " << cache.m_time);
1607  // if (!destVol) { return currPar;}
1608  return currPar->uniqueClone();
1609 
1610  }
1611 
1612  cache.m_detachedVols.clear();
1613  cache.m_denseVols.clear();
1614  cache.m_trDenseBounds.clear();
1615  cache.m_trLays.clear();
1616  cache.m_navigLays.clear();
1617 
1618  // detached volume boundaries
1620  if (!detVols.empty()) {
1622  for (; iTer != detVols.end(); ++iTer) {
1623  // active station ?
1624  const Trk::Layer *layR = (*iTer)->layerRepresentation();
1625  bool active = layR && layR->layerType();
1626 
1627  if (active) {
1628  if (!m_resolveMultilayers || (*iTer)->multilayerRepresentation().empty()) {
1629  const Trk::Surface &surf = layR->surfaceRepresentation();
1631  dir * currPar->momentum().normalized());
1632  if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1633  // boundary check
1634  Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1635  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1636  cache.m_trLays.emplace_back(&surf, distSol.first());
1637  cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), layR);
1638  }
1639  }
1640  } else {
1641  const auto& multi = (*iTer)->multilayerRepresentation();
1642  for (const auto *i : multi) {
1643  const Trk::Surface &surf = i->surfaceRepresentation();
1645  dir * currPar->momentum().normalized());
1646  if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1647  // boundary check
1648  Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1649  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1650  cache.m_trLays.emplace_back(&surf, distSol.first());
1651  cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), i);
1652  }
1653  }
1654  } // end loop over multilayers
1655  } // end unresolved active
1656  } // active done
1657  else if (cache.m_currentStatic->geometrySignature() != Trk::MS || !m_useMuonMatApprox ||
1658  (*iTer)->name().substr((*iTer)->name().size() - 4, 4) == "PERM") { // retrieve inert detached objects
1659  // only if needed
1660  // dense volume boundaries
1661  if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
1662  ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
1663  && ((*iTer)->trackingVolume()->confinedArbitraryLayers().empty())) {
1664  const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
1665  int newB = 0;
1666  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
1667  const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
1669  dir * currPar->momentum().normalized());
1670  if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1671  // boundary check
1672  Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1673  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1674  cache.m_trDenseBounds.emplace_back(&surf, distSol.first());
1675  newB++;
1676  } // valid intersection
1677  } // along path
1678  } // end loop over boundaries
1679  if (newB > 0) {
1680  cache.m_denseVols.emplace_back((*iTer)->trackingVolume(), newB);
1681  }
1682  }
1683  // subvolumes ?
1684  // if ((*iTer)->trackingVolume()->confinedDenseVolumes() &&
1685  // (*iTer)->trackingVolume()->confinedDenseVolumes()->size())
1686  // ATH_MSG_WARNING( " transportToVolumeWithPathLimit() - at " << currPar->position() <<", unresolved
1687  // subvolumes for "
1688  // << (*iTer)->trackingVolume()->volumeName() );
1689 
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();
1696  int newB = 0;
1697  for (unsigned int ibb = 0; ibb < bounds.size(); ibb++) {
1698  const Trk::Surface &surf = (bounds[ibb])->surfaceRepresentation();
1700  dir * currPar->momentum().normalized());
1701  if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1702  // boundary check
1703  Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1704  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1705  cache.m_trDenseBounds.emplace_back(&surf, distSol.first());
1706  newB++;
1707  } // valid intersection
1708  } // along path
1709  } // end loop over boundaries
1710  if (newB > 0) {
1711  cache.m_denseVols.emplace_back((*vIter), newB);
1712  }
1713  if (!(*vIter)->confinedArbitraryLayers().empty()) {
1714  ATH_MSG_DEBUG(
1715  " transportToVolumeWithPathLimit() - at " << currPar->position() << ", unresolved sublayers/subvolumes for "
1716  << (*vIter)->volumeName());
1717  }
1718  }
1719  }
1720 
1721  // confined layers
1722  Trk::ArraySpan<const Trk::Layer* const>confLays = (*iTer)->trackingVolume()->confinedArbitraryLayers();
1723  if (!confLays.empty()) {
1724  for (const Trk::Layer* const lIt: confLays) {
1725  const Trk::Surface &surf = lIt->surfaceRepresentation();
1727  dir * currPar->momentum().normalized());
1728  if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1729  // boundary check
1730  Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1731  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1732  cache.m_trLays.emplace_back(&surf, distSol.first());
1733  cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
1734  } // valid intersection
1735  } // along path
1736  }
1737  } // end confined layers
1738  } // end inert material
1739  }
1740  } // end detached volumes
1741  cache.m_denseResolved = std::pair<unsigned int, unsigned int> (cache.m_denseVols.size(), cache.m_trDenseBounds.size());
1742  cache.m_layerResolved = cache.m_trLays.size();
1743 
1745  while (bIter != cache.m_trStaticBounds.end()) {
1746  cache.m_trSurfs.emplace_back((*bIter).surface, (*bIter).distance);
1747  ++bIter;
1748  }
1749 
1750  // std::cout <<"navigation in current static:"<< cache.m_trSurfs.size()<<","<<cache.m_trStaticBounds.size()<< std::endl;
1751  // for (unsigned int ib=0; ib<cache.m_trSurfs.size(); ib++) std::cout <<"distance to static:"<<
1752  // ib<<","<<cache.m_trSurfs[ib].second<<std::endl;
1753 
1754  // resolve the use of dense volumes
1755  cache.m_dense = (cache.m_currentStatic->geometrySignature() == Trk::MS && m_useMuonMatApprox) ||
1756  (cache.m_currentStatic->geometrySignature() != Trk::MS && m_useDenseVolumeDescription);
1757 
1758  // reset remaining counters
1759  cache.m_currentDense = cache.m_dense ? cache.m_currentStatic : cache.m_highestVolume;
1760  cache.m_navigBoundaries.clear();
1761  if (cache.m_denseVols.size() > cache.m_denseResolved.first) {
1762  cache.m_denseVols.resize(cache.m_denseResolved.first);
1763  cache.m_trDenseBounds.resize(cache.m_denseResolved.second);
1764  }
1765  if (cache.m_layers.size() > cache.m_layerResolved) {
1766  cache.m_trLays.resize(cache.m_layerResolved);
1767  cache.m_navigLays.resize(cache.m_layerResolved);
1768  }
1769 
1770  // if (cache.m_currentStatic->entryLayerProvider()) nEntryLays = cache.m_currentStatic->entryLayerProvider()->layers().size();
1771 
1772  // confined layers
1773  if (cache.m_currentStatic->confinedLayers()) {
1774  std::span <Trk::Layer const * const> cLays = cache.m_currentStatic->confinedLayers()->arrayObjects();
1775  for (const auto *cLay : cLays) {
1776  if (cLay->layerMaterialProperties()) {
1777  const Trk::Surface &surf = cLay->surfaceRepresentation();
1779  dir * currPar->momentum().normalized());
1780  if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1781  // boundary check
1782  Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1783  if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1784  cache.m_trLays.emplace_back(&surf, distSol.first());
1785  cache.m_navigLays.emplace_back(cache.m_currentStatic,
1786  cLay);
1787  } // valid intersection
1788  } // along path
1789  }
1790  }
1791  }
1792 
1793  // cache.m_trSurfs contains destination surface (if it exists), static volume boundaries
1794  // complete with TG cache.m_layers/dynamic layers, cache.m_denseBoundaries, cache.m_navigBoundaries, m_detachedBoundaries
1795 
1796  if (!cache.m_trLays.empty()) {
1797  cache.m_trSurfs.insert(cache.m_trSurfs.end(), cache.m_trLays.begin(), cache.m_trLays.end());
1798  }
1799  if (!cache.m_trDenseBounds.empty()) {
1800  cache.m_trSurfs.insert(cache.m_trSurfs.end(), cache.m_trDenseBounds.begin(), cache.m_trDenseBounds.end());
1801  }
1802 
1803  // current dense
1804  cache.m_currentDense = cache.m_highestVolume;
1805 
1806  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
1807  const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
1808  if (dVol->inside(currPar->position(), m_tolerance) && dVol->zOverAtimesRho() != 0.) {
1809  if (!m_navigator->atVolumeBoundary(currPar, dVol, dir, nextVol, m_tolerance) ||
1810  dVol->inside(currPar->position() + 2 * m_tolerance * currPar->momentum().unit(), m_tolerance)) {
1811  cache.m_currentDense = dVol;
1812  }
1813  }
1814  }
1815 
1816  if (cache.m_dense && cache.m_currentDense == cache.m_highestVolume) {
1817  cache.m_currentDense = cache.m_currentStatic;
1818  }
1819 
1820  // ready to process
1821  // 1/ order valid intersections ( already in trSurfs )
1822 
1823  std::vector<unsigned int> sols;
1824  sols.reserve(cache.m_trSurfs.size());
1825  for (unsigned int i = 0; i < cache.m_trSurfs.size(); ++i) {
1826  sols.push_back(i);
1827  }
1828 
1829  if (sols.size() > 1) {
1830  unsigned int itest = 1;
1831  while (itest < sols.size()) {
1832  if (cache.m_trSurfs[sols[itest]].second < cache.m_trSurfs[sols[itest - 1]].second) {
1833  unsigned int iex = sols[itest - 1];
1834  sols[itest - 1] = sols[itest];
1835  sols[itest] = iex;
1836  itest = 1;
1837  } else {
1838  itest++;
1839  }
1840  }
1841  // check ordering
1842  for (unsigned int is = 1; is < sols.size(); is++) {
1843  if (cache.m_trSurfs[sols[is]].second < cache.m_trSurfs[sols[is - 1]].second) {
1844  std::cout << "wrong intersection ordering" << std::endl;
1845  }
1846  }
1847  }
1848 
1849 
1850  // 2/ check time/material/boundary limit
1851 
1852  // update of cache.m_navigSurfs required if I/ entry into new navig volume, II/ exit from currentActive without overlaps
1853 
1854  nextVol = nullptr;
1855  const Trk::TrackParameters *nextPar = nullptr;
1856 
1857  double dist = 0.;
1858  double mom = currPar->momentum().mag();
1859  double beta = mom / sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass) * Gaudi::Units::c_light;
1860 
1861  ATH_MSG_DEBUG(" [0] starting transport of neutral particle in (dense) volume " << cache.m_currentDense->volumeName());
1862 
1863  for (unsigned int sol : sols) {
1864  if (cache.m_trSurfs[sol].second == 0.) {
1865  continue;
1866  }
1867 
1868  double step = cache.m_trSurfs[sol].second - dist;
1869 
1870  Amg::Vector3D nextPos = currPar->position() + dir * currPar->momentum().normalized() * cache.m_trSurfs[sol].second;
1871  // Amg::Vector3D halfStep = nextPos - 0.5*step*dir*currPar->momentum().normalized();
1872 
1873  // check missing volume boundary
1874  if (!(cache.m_currentDense->inside(nextPos, m_tolerance))) {
1875  ATH_MSG_DEBUG(" [!] WARNING: missing volume boundary for volume" << cache.m_currentDense->volumeName());
1876  // new search
1877  cache.m_currentDense = cache.m_highestVolume;
1878  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
1879  const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
1880  if (dVol->inside(nextPos, m_tolerance) && dVol->zOverAtimesRho() != 0.) {
1881  cache.m_currentDense = dVol;
1882  }
1883  }
1884  if (cache.m_dense && cache.m_currentDense == cache.m_highestVolume) {
1885  cache.m_currentDense = cache.m_currentStatic;
1886  }
1887 
1888  ATH_MSG_DEBUG(" [!] new search for dense volume : " << cache.m_currentDense->volumeName());
1889  }
1890 
1891  double tDelta = step / beta;
1892 
1893  double mDelta = (cache.m_currentDense->zOverAtimesRho() != 0.) ? step / cache.m_currentDense->x0() : 0.;
1894 
1895  // in case of hadronic interaction retrieve nuclear interaction properties, too
1896 
1897  double frT = 1.;
1898  if (step > 0 && timeLim.tMax > cache.m_time && cache.m_time + tDelta >= timeLim.tMax) {
1899  frT = (timeLim.tMax - cache.m_time) * beta / step;
1900  }
1901 
1902  // TODO : compare x0 or l0 according to the process type
1903  double frM = 1.;
1904  if (mDelta > 0 && cache.m_path.x0Max > 0.) {
1905  if (cache.m_path.process < 100 && cache.m_path.x0Collected + mDelta > cache.m_path.x0Max) {
1906  frM = (cache.m_path.x0Max - cache.m_path.x0Collected) / mDelta;
1907  } else { // waiting for hadronic interaction, retrieve nuclear interaction properties
1908  double mDeltaL = cache.m_currentDense->L0 >
1909  0. ? step / cache.m_currentDense->L0 : mDelta / 0.37 / cache.m_currentDense->averageZ();
1910  if (cache.m_path.l0Collected + mDeltaL > cache.m_path.x0Max) {
1911  frM = (cache.m_path.x0Max - cache.m_path.l0Collected) / mDeltaL;
1912  }
1913  }
1914  }
1915 
1916  double fr = fmin(frT, frM);
1917 
1918  // std::cout << "looping over intersections:"<<is<<","<< cache.m_trSurfs[sols[is]].second<<","<<step << ","<<
1919  // tDelta<<","<<mDelta << std::endl;
1920 
1921  if (fr < 1.) { // decay or material interaction during the step
1922  int process = frT < frM ? timeLim.process : cache.m_path.process;
1923  cache.m_time += fr * step / beta;
1924  if (mDelta > 0 && cache.m_currentDense->averageZ() > 0) {
1925  cache.m_path.updateMat(fr * mDelta, cache.m_currentDense->averageZ(), 0.);
1926  }
1927 
1928  nextPos = currPar->position() + dir * currPar->momentum().normalized() * (dist + fr * step);
1929 
1930  // process interaction only if creation of secondaries allowed
1931  if (cache.m_currentStatic->geometrySignature() == Trk::ID || m_caloMsSecondary) {
1932  const Trk::TrackParameters* nextPar =
1933  m_updators[0]
1934  ->interact(cache.m_time, nextPos, currPar->momentum(), particle, process, cache.m_currentDense)
1935  .release();
1936 
1937  if (nextPar) {
1938  ATH_MSG_DEBUG(" [!] WARNING: particle survives the interaction " << process);
1939  }
1940 
1941  if (nextPar && process == 121) {
1942  ATH_MSG_DEBUG(" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
1943  return returnParameters;
1944  }
1945 
1946  if (!nextPar) {
1947  return returnParameters;
1948  }
1949 
1950  throwIntoGarbageBin(cache,nextPar);
1951  // return transportToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
1952  } else { // kill particle without trace
1953  return returnParameters;
1954  }
1955  } // end decay or material interaction durign the step
1956 
1957  // update
1958  dist = cache.m_trSurfs[sol].second;
1959  if (mDelta > 0 && cache.m_currentDense->averageZ() > 0) {
1960  cache.m_path.updateMat(mDelta, cache.m_currentDense->averageZ(), 0.);
1961  }
1962  cache.m_time += tDelta;
1963 
1964  nextPar = new Trk::CurvilinearParameters(nextPos, currPar->momentum(), 1.); // fake charge
1965  throwIntoGarbageBin(cache,nextPar);
1966 
1967  if (sol < iDest) { // destination volume (most often, subdetector boundary)
1968  return nextPar->uniqueClone();
1969  } if (sol < iDest + cache.m_trStaticBounds.size()) { // tracking geometry frame
1970  // material attached ?
1971  const Trk::Layer *mb = cache.m_trStaticBounds[sol - iDest].surface->materialLayer();
1972  if (mb && m_includeMaterialEffects) {
1973  if (mb->layerMaterialProperties() && mb->layerMaterialProperties()->fullMaterial(nextPos)) {
1974  const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
1975  nextPar =
1976  currentUpdator
1977  ? currentUpdator
1978  ->update(
1979  nextPar, *mb, timeLim, cache.m_path, cache.m_currentStatic->geometrySignature(), dir, particle)
1980  .release()
1981  : nextPar;
1982 
1983  if (!nextPar) {
1984  ATH_MSG_VERBOSE(" [+] Update may have killed neutral track - return.");
1986  return returnParameters;
1987  }
1988  throwIntoGarbageBin(cache,nextPar);
1989 
1990  } else { // material layer without material ?
1991  ATH_MSG_VERBOSE(" boundary layer without material:" << mb->layerIndex());
1992  }
1993  }
1994 
1995  // static volume boundary; return to the main loop
1996  unsigned int index = cache.m_trStaticBounds[sol - iDest].bIndex;
1997  // use global coordinates to retrieve attached volume (just for static!)
1998  nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
1999  nextPar->position(), nextPar->momentum(), dir);
2000  // double check the next volume
2001  if (nextVol && !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(), 0.))) {
2002  ATH_MSG_DEBUG(
2003  " [!] WARNING: wrongly assigned static volume ?" << cache.m_currentStatic->volumeName() << "->" <<
2004  nextVol->volumeName());
2005  nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2006  nextPar->position() + 0.01 * dir * nextPar->momentum().normalized());
2007  if (nextVol) {
2008  ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
2009  }
2010  }
2011  // end double check - to be removed after validation of the geometry gluing
2012  if (nextVol != cache.m_currentStatic) {
2013  ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
2014  if (m_navigator->atVolumeBoundary(nextPar, cache.m_currentStatic, dir, assocVol,
2015  m_tolerance) && assocVol != cache.m_currentStatic) {
2016  cache.m_currentDense = cache.m_dense ? nextVol : cache.m_highestVolume;
2017  }
2018  // no next volume found --- end of the world
2019  if (!nextVol) {
2020  ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
2021  nextPar->position()) << ", timed at " << cache.m_time);
2023  return nextPar->uniqueClone();
2024  }
2025  // next volume found and parameters are at boundary
2026  if (nextVol /*&& nextPar nextPar is dereferenced anyway*/) {
2027  ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
2028  ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
2029  if (!destVol && cache.m_currentStatic->geometrySignature() != nextVol->geometrySignature()) {
2030  nextGeoID = nextVol->geometrySignature();
2031  return nextPar->uniqueClone();
2032  }
2033  }
2034  cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
2035  return transportToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
2036  }
2037  if (dist > 0.) {
2038  return transportToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
2039  }
2040  } else if (sol < iDest + cache.m_trStaticBounds.size() + cache.m_trLays.size()) { // layer
2041  // material thickness - simple approach
2042  unsigned int index = sol - iDest - cache.m_trStaticBounds.size();
2043  const Trk::Layer *nextLayer = cache.m_navigLays[index].second;
2044 
2045  bool matUp = nextLayer->layerMaterialProperties()->fullMaterial(nextPos) && m_includeMaterialEffects;
2046 
2047  // material update
2048  if (matUp && m_includeMaterialEffects) {
2049  const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
2050 
2051  nextPar = currentUpdator ? currentUpdator
2052  ->update(nextPar,
2053  *nextLayer,
2054  timeLim,
2055  cache.m_path,
2057  dir,
2058  particle)
2059  .release()
2060  : nextPar;
2061 
2062  if (!nextPar) {
2063  ATH_MSG_VERBOSE(" [+] Update may have killed neutral track - return.");
2065  return returnParameters;
2066  }
2067  throwIntoGarbageBin(cache,nextPar);
2068 
2069  }
2070  } else if (sol < iDest + cache.m_trStaticBounds.size() + cache.m_trLays.size() + cache.m_trDenseBounds.size()) {
2071  // dense volume boundary : no material update here, navigation only ( set cache.m_currentDense for next step )
2072 
2073  unsigned int index = sol - iDest - cache.m_trStaticBounds.size() - cache.m_trLays.size();
2074  std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >::iterator dIter = cache.m_denseVols.begin();
2075  while (dIter != cache.m_denseVols.end() && index >= (*dIter).second) {
2076  index -= (*dIter).second;
2077  ++dIter;
2078  }
2079  if (dIter != cache.m_denseVols.end()) {
2080  currVol = (*dIter).first;
2081 
2082  if (Trk::TrackingGeometry::atVolumeBoundary(nextPos, nextPar->momentum(), currVol, assocVol, dir,
2083  m_tolerance)) {
2084  if (assocVol && assocVol->zOverAtimesRho() != 0.) {
2085  cache.m_currentDense = assocVol;
2086  } else if (currVol->inside(nextPos + 0.002 * dir * nextPar->momentum().normalized())) {
2087  cache.m_currentDense = currVol;
2088  } else {
2089  // new search
2090  cache.m_currentDense = cache.m_highestVolume;
2091  if (m_useMuonMatApprox && cache.m_denseVols.empty()) {
2092  cache.m_currentDense = cache.m_currentStatic;
2093  } else {
2094  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
2095  const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
2096  if (dVol->inside(nextPos + 0.002 * dir * nextPar->momentum().normalized(),
2097  m_tolerance) && dVol->zOverAtimesRho() != 0.) {
2098  cache.m_currentDense = dVol;
2099  }
2100  }
2101  }
2102  }
2103  }
2104  }
2105  } else { // detached volume bounds - not relevant ?
2106  }
2107 
2108  throwIntoGarbageBin(cache,nextPar);
2109  }
2110 
2111 
2112 
2113  if (nextPar) {
2114  ATH_MSG_DEBUG(
2115  " transportToVolumeWithPathLimit() - return from volume " << cache.m_currentStatic->volumeName() << " at position:" <<
2116  nextPar->position());
2117  return nextPar->uniqueClone();
2118  }
2119  return nullptr;
2120 }
2121 
2124  const Trk::TrackParameters &parm,
2125  Trk::TimeLimit &timeLim,
2127  Trk::ParticleHypothesis particle,
2128  Trk::GeometrySignature &nextGeoID,
2129  const Trk::AlignableTrackingVolume *aliTV) const {
2130  const std::string m = aliTV ? aliTV->volumeName() : " NULLPTR!";
2131  ATH_MSG_DEBUG(" [0] starting transport of neutral particle in alignable volume " << m);
2132 
2133  // material loop in sensitive Calo volumes
2134  // returns: boundary parameters (static volume boundary)
2135  // material collection / intersection with active layers ( binned material used )
2136 
2137  // initialize the return parameters vector
2138  const Trk::TrackParameters *currPar = &parm;
2139  const Trk::TrackingVolume *nextVol = nullptr;
2140  std::vector<Trk::IdentifiedIntersection> iis;
2141 
2142  emptyGarbageBin(cache,&parm);
2143 
2144  const EventContext& ctx = Gaudi::Hive::currentContext();
2145  if (!aliTV) {
2146  return {nullptr, nullptr, nullptr};
2147  }
2148 
2149  // TODO if volume entry go to entry of misaligned volume
2150 
2151  // save volume entry if collection present
2152 
2153  const Trk::BinnedMaterial *binMat = aliTV->binnedMaterial();
2154 
2155  const Trk::IdentifiedMaterial *binIDMat = nullptr;
2156 
2157  const Trk::Material *currMat = aliTV; // material to be used
2158 
2159 
2160  // loop through binned material : save identifier, material, distance
2161 
2162  // binned material
2163  if (binMat) {
2164  Amg::Vector3D pos = currPar->position();
2165  Amg::Vector3D pot = currPar->position();
2166  Amg::Vector3D umo = currPar->momentum().normalized();
2167 
2168  binIDMat = binMat->material(pos);
2169 
2170  if (cache.m_hitVector && binIDMat) {
2171  // std::cout <<"id info at the alignable volume entry:"<<binIDMat->second<<std::endl;
2172  if (binIDMat->second > 0) {
2173  cache.m_hitVector->emplace_back(currPar->uniqueClone(), timeLim.time, binIDMat->second, 0.);
2174  }
2175  }
2176 
2177  const Trk::BinUtility *lbu = binMat->layerBinUtility(pos);
2178  if (lbu) {
2179  unsigned int cbin = lbu->bin(pos);
2180  // std::cout <<"layerBinUtility retrieved:"<<lbu->bins()<< std::endl;
2181  std::pair<size_t, float> d2n = lbu->distanceToNext(pos, dir * umo);
2182  // std::cout<<"estimated distance to the next bin:"<<d2n.first<<","<<d2n.second<< std::endl;
2183  float dTot = 0.;
2184  float distTot = 0.;
2185  // std::cout <<"input bin:"<<cbin<<", next: "<<d2n.first<<", at distance:"<<d2n.second<< std::endl;
2186  while (true) {
2187  if (d2n.first == cbin) {
2188  break;
2189  }
2190  dTot += d2n.second;
2191  distTot = dTot;
2192  pos = pos + d2n.second * dir * umo;
2193  if (!aliTV->inside(pos)) {
2194  break; // step outside volume
2195  }
2196  cbin = d2n.first;
2197  d2n = lbu->distanceToNext(pos, dir * umo);
2198  if (d2n.first == cbin && fabs(d2n.second) < 0.002) { // move ahead
2199  pos = pos + 0.002 * dir * umo;
2200  dTot += 0.002;
2201  d2n = lbu->distanceToNext(pos, dir * umo);
2202  }
2203  // std::cout <<"finding next bin?:"<<d2n.first<<","<<dTot<<"+"<<d2n.second<< std::endl;
2204  if (d2n.second > 0.001) { // retrieve material and save bin entry
2205  pot = pos + 0.5 * d2n.second * dir * umo;
2206  binIDMat = binMat->material(pot);
2207  iis.emplace_back(distTot, binIDMat->second, binIDMat->first.get());
2208  // std::cout <<"saving next bin entry:"<< distTot<<","<<binIDMat->second<<std::endl;
2209  }
2210  }
2211  }
2212  }
2213 
2214  // resolve exit from the volume
2215 
2216  cache.m_trStaticBounds.clear();
2217  const auto &bounds = aliTV->boundarySurfaces();
2218  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
2219  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
2221  dir * currPar->momentum().normalized());
2222  double dist = distSol.first();
2223  // resolve multiple intersection solutions
2224  if (distSol.numberOfSolutions() > 1 && dist < m_tolerance && distSol.second() > dist) {
2225  dist = distSol.second();
2226  }
2227  // boundary check
2228  Amg::Vector3D gp = currPar->position() + dist * dir * currPar->momentum().normalized();
2229  // std::cout<<"alignable volume boundary:"<< ib<<","<<dist<<","<<
2230  // surf.isOnSurface(gp,true,m_tolerance,m_tolerance)<<std::endl;
2231  if (dist > m_tolerance && surf.isOnSurface(gp, true, m_tolerance, m_tolerance)) {
2232  const Trk::TrackingVolume *attachedVol = (bounds[ib])->attachedVolume(gp, currPar->momentum(), dir);
2233 
2234  if (attachedVol && !(attachedVol->inside(gp + 0.01 * dir * currPar->momentum().normalized(), m_tolerance))) {
2235  ATH_MSG_DEBUG(
2236  " [!] WARNING: wrongly assigned exit volume ?" << cache.m_currentStatic->volumeName() << "->" <<
2237  attachedVol->volumeName());
2238  attachedVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2239  gp + 0.01 * dir * currPar->momentum().normalized());
2240  if (attachedVol) {
2241  ATH_MSG_DEBUG(" new search yields: " << attachedVol->volumeName());
2242  }
2243  }
2244 
2245  if (attachedVol != cache.m_currentStatic) { // exit
2246  nextVol = attachedVol;
2247  cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
2248  } else if (dist > 0.001) {
2249  const Trk::TrackingVolume *testVol = (bounds[ib])->attachedVolume(gp,
2250  currPar->momentum(),
2253  "gluing problem at the exit from alignable volume: " << gp.perp() << "," << gp.z() << ":" <<
2254  cache.m_currentStatic->volumeName());
2255  if (testVol) {
2256  ATH_MSG_DEBUG("inverted direction:" << testVol->volumeName());
2257  }
2258  if (testVol &&
2259  testVol->inside(gp + 0.01 * dir * currPar->momentum().normalized(),
2260  m_tolerance) && testVol != cache.m_currentStatic) {
2261  ATH_MSG_DEBUG(
2262  "next volume resolved to:" << testVol->volumeName() << " at the position(R,Z):" << gp.perp() << "," <<
2263  gp.z());
2264  nextVol = testVol;
2265  cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
2266  }
2267  }
2268  }
2269  } // end loop over boundaries
2270 
2271  // if (nextVol) std::cout <<"nextVol, number of exit solutions:"<<
2272  // nextVol->volumeName()<<","<<cache.m_trStaticBounds.size()<< std::endl;
2273 
2274  if (cache.m_trStaticBounds.empty()) {
2275  ATH_MSG_WARNING("exit from alignable volume " << aliTV->volumeName() << " not resolved, aborting");
2276  return {nullptr, nullptr, nullptr};
2277  } if (cache.m_trStaticBounds.size() > 1) { // hit edge ?
2278  Amg::Vector3D gp = currPar->position() + (cache.m_trStaticBounds[0].distance + 1.) * dir *
2279  currPar->momentum().normalized();
2280  nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2281  ATH_MSG_DEBUG("exit volume reassigned:" << nextVol->volumeName());
2282  }
2283 
2284  // exit from the volume may coincide with the last bin boundary - leave 10 microns marge
2285  if (!iis.empty() && cache.m_trStaticBounds[0].distance - iis.back().distance < 0.01) {
2286  iis.pop_back();
2287  }
2288 
2289  // add volume exit
2290  iis.emplace_back(cache.m_trStaticBounds[0].distance, 0, nullptr);
2291 
2292  // loop over intersection taking into account the material effects
2293 
2294  double dist = 0.;
2295  double mom = currPar->momentum().mag();
2296  double beta = mom / sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass) * Gaudi::Units::c_light;
2297  Amg::Vector3D nextPos = currPar->position();
2298 
2299  int currLay = 0;
2300 
2301  for (unsigned int is = 0; is < iis.size(); is++) {
2302  if (iis[is].distance == 0.) {
2303  continue;
2304  }
2305 
2306  double step = iis[is].distance - dist;
2307 
2308  nextPos = currPar->position() + dir * currPar->momentum().normalized() * iis[is].distance;
2309 
2310  double tDelta = step / beta;
2311 
2312  double mDelta = (currMat->zOverAtimesRho() != 0.) ? step / currMat->x0() : 0.;
2313 
2314  // in case of hadronic interaction retrieve nuclear interaction properties, too
2315 
2316  double frT = 1.;
2317  if (step > 0 && timeLim.tMax > cache.m_time && cache.m_time + tDelta >= timeLim.tMax) {
2318  frT = (timeLim.tMax - cache.m_time) * beta / step;
2319  }
2320 
2321  // TODO : compare x0 or l0 according to the process type
2322  double frM = 1.;
2323  if (mDelta > 0 && cache.m_path.x0Max > 0.) {
2324  if (cache.m_path.process < 100 && cache.m_path.x0Collected + mDelta > cache.m_path.x0Max) {
2325  frM = (cache.m_path.x0Max - cache.m_path.x0Collected) / mDelta;
2326  } else { // waiting for hadronic interaction, retrieve nuclear interaction properties
2327  double mDeltaL = currMat->L0 > 0. ? step / currMat->L0 : mDelta / 0.37 / currMat->averageZ();
2328  if (cache.m_path.l0Collected + mDeltaL > cache.m_path.x0Max) {
2329  frM = (cache.m_path.x0Max - cache.m_path.l0Collected) / mDeltaL;
2330  }
2331  }
2332  }
2333 
2334  double fr = fmin(frT, frM);
2335 
2336  // std::cout << "looping over intersections:"<<is<<","<< cache.m_trSurfs[sols[is]].second<<","<<step << ","<<
2337  // tDelta<<","<<mDelta << std::endl;
2338 
2339  if (fr < 1.) { // decay or material interaction during the step
2340  int process = frT < frM ? timeLim.process : cache.m_path.process;
2341  cache.m_time += fr * step / beta;
2342  if (mDelta > 0 && currMat->averageZ() > 0) {
2343  cache.m_path.updateMat(fr * mDelta, currMat->averageZ(), 0.);
2344  }
2345 
2346  nextPos = currPar->position() + dir * currPar->momentum().normalized() * (dist + fr * step);
2347 
2348  // process interaction only if creation of secondaries allowed
2349  if (m_caloMsSecondary) {
2350  const Trk::TrackParameters* nextPar =
2351  m_updators[0]
2352  ->interact(cache.m_time, nextPos, currPar->momentum(), particle, process, currMat)
2353  .release();
2354  throwIntoGarbageBin(cache, nextPar);
2355 
2356  if (nextPar) {
2357  ATH_MSG_DEBUG(" [!] WARNING: particle survives the interaction " << process);
2358  }
2359 
2360  if (nextPar && process == 121) {
2361  ATH_MSG_DEBUG(" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2362  return {nullptr, nullptr, nullptr};
2363  }
2364 
2365  if (!nextPar) {
2366  return {nullptr, nullptr, nullptr};
2367  }
2368 
2369  // return transportToVolumeWithPathLimit(*nextPar, timeLim, dir, particle, nextGeoID, destVol);
2370  } else { // kill particle without trace ?
2371  return {nullptr, nullptr, nullptr};
2372  }
2373  } // end decay or material interaction during the step
2374 
2375  // update
2376  dist = iis[is].distance;
2377  if (mDelta > 0 && currMat->averageZ() > 0) {
2378  cache.m_path.updateMat(mDelta, currMat->averageZ(), 0.);
2379  }
2380  cache.m_time += tDelta;
2381 
2382  if (is < iis.size() - 1) { // update bin material info
2383  // binIDMat = binMat->material(nextPos);
2384  // currMat = binIDMat->first;
2385  currMat = iis[is].material;
2386  currLay = iis[is].identifier;
2387 
2388  if (cache.m_hitVector && iis[is].identifier > 0) { // save entry to the next layer
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.);
2392  }
2393  }
2394  } // end loop over intersections
2395 
2396  Trk::CurvilinearParameters *nextPar = new Trk::CurvilinearParameters(nextPos, currPar->momentum(), 0.);
2397 
2398  if (cache.m_hitVector) { // save volume exit /active layer only ?
2399  ATH_MSG_VERBOSE("active layer/volume exit:" << currLay << " at R,z:" << nextPos.perp() << "," << nextPos.z());
2400  if (binIDMat and(binIDMat->second > 0)) {
2401  cache.m_hitVector->emplace_back(nextPar->uniqueClone(), timeLim.time, currLay, 0.);
2402  }
2403  }
2404 
2405  throwIntoGarbageBin(cache,nextPar);
2406 
2407 
2408 
2409  ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
2410 
2411  // no next volume found --- end of the world
2412  if (!nextVol) {
2413  ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
2414  nextPar->position()) << ", timed at " << cache.m_time);
2416  } else {
2417  ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
2418  ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
2419  }
2420 
2421  cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
2422 
2423  return {nextPar, nextVol, cache.m_currentStatic};
2424 }
2425 
2428  const Trk::TrackParameters &parm,
2429  Trk::TimeLimit &timeLim,
2431  Trk::ParticleHypothesis particle,
2432  Trk::GeometrySignature &nextGeoID,
2433  const Trk::AlignableTrackingVolume *vol) const {
2434  const std::string m = vol ? vol->volumeName():"NULLPTR";
2435  ATH_MSG_DEBUG("M-[" << ++cache.m_methodSequence << "] extrapolateInAlignableTV(...) " << m);
2436 
2437  // material loop in sensitive Calo volumes
2438  // extrapolation without target surface returns:
2439  // A) boundary parameters (static volume boundary)
2440  // if target surface:
2441  // B) trPar at target surface
2442  // material collection done by the propagator ( binned material used )
2443 
2444  // initialize the return parameters vector
2445  const Trk::TrackParameters *currPar = &parm;
2446  const Trk::AlignableTrackingVolume *staticVol = nullptr;
2447  const Trk::TrackingVolume *currVol = nullptr;
2448  const Trk::TrackingVolume *nextVol = nullptr;
2449  std::vector<unsigned int> solutions;
2450  // double tol = 0.001;
2451  // double path = 0.;
2452  const EventContext& ctx = Gaudi::Hive::currentContext();
2453  if (!cache.m_highestVolume) {
2454  cache.m_highestVolume = m_navigator->highestVolume(ctx);
2455  }
2456 
2457  emptyGarbageBin(cache,&parm);
2458 
2459  // verify current position
2460  const Amg::Vector3D& gp = parm.position();
2461  if (vol && vol->inside(gp, m_tolerance)) {
2462  staticVol = vol;
2463  } else {
2464  currVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2465  const Trk::TrackingVolume *nextStatVol = nullptr;
2466  if (m_navigator->atVolumeBoundary(currPar, currVol, dir, nextStatVol, m_tolerance) && nextStatVol != currVol) {
2467  currVol = nextStatVol;
2468  }
2469  if (currVol && currVol != vol) {
2470  const Trk::AlignableTrackingVolume *aliTG = dynamic_cast<const Trk::AlignableTrackingVolume *> (currVol);
2471  if (aliTG) {
2472  staticVol = aliTG;
2473  }
2474  }
2475  }
2476 
2477  if (!staticVol) {
2478  ATH_MSG_DEBUG(" [!] failing in retrieval of AlignableTV, return 0");
2479  return {nullptr, nullptr, nullptr};
2480  }
2481 
2482  // TODO if volume entry go to entry of misaligned volume
2483 
2484  // save volume entry if collection present
2485 
2486  if (cache.m_hitVector) {
2487  const Trk::BinnedMaterial *binMat = staticVol->binnedMaterial();
2488  if (binMat) {
2489  const Trk::IdentifiedMaterial *binIDMat = binMat->material(currPar->position());
2490  if (binIDMat->second > 0) {
2491  cache.m_hitVector->emplace_back(currPar->uniqueClone(), timeLim.time, binIDMat->second, 0.);
2492  }
2493  }
2494  }
2495 
2496  // navigation surfaces
2497  if (cache.m_navigSurfs.capacity() > m_maxNavigSurf) {
2498  cache.m_navigSurfs.reserve(m_maxNavigSurf);
2499  }
2500  cache.m_navigSurfs.clear();
2501 
2502  // assume new static volume, retrieve boundaries
2503  cache.m_currentStatic = staticVol;
2504  cache.m_staticBoundaries.clear();
2505  const auto &bounds = staticVol->boundarySurfaces();
2506  for (unsigned int ib = 0; ib < bounds.size(); ++ib) {
2507  const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
2508  cache.m_staticBoundaries.emplace_back(&surf, true);
2509  }
2510 
2511  cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_staticBoundaries.begin(), cache.m_staticBoundaries.end());
2512 
2513  // current dense
2514  cache.m_currentDense = staticVol;
2515 
2516  // ready to propagate
2517  // till: A/ static volume boundary(bcheck=true) , B/ destination surface(bcheck=false)
2518 
2519  nextVol = nullptr;
2520  while (currPar) {
2521  std::vector<unsigned int> solutions;
2522  // propagate now
2523  ATH_MSG_DEBUG(" [+] Starting propagation at position " << positionOutput(currPar->position())
2524  << " (current momentum: " << currPar->momentum().mag() <<
2525  ")");
2526  ATH_MSG_DEBUG(" [+] " << cache.m_navigSurfs.size() << " target surfaces in '" << cache.m_currentDense->volumeName() << "'.");
2527  // arguments : inputParameters, vector of navigation surfaces, propagation direction, b field service, particle
2528  // type, result,
2529  // material collection, intersection collection, path limit, switch for use of path limit, switch for
2530  // curvilinear on return, current TG volume
2531  const Trk::TrackParameters* nextPar = m_stepPropagator
2532  ->propagateT(ctx,
2533  *currPar,
2534  cache.m_navigSurfs,
2535  dir,
2536  m_fieldProperties,
2537  particle,
2538  solutions,
2539  cache.m_path,
2540  timeLim,
2541  true,
2542  cache.m_currentDense,
2543  cache.m_hitVector)
2544  .release();
2545  ATH_MSG_VERBOSE(" [+] Propagation done. ");
2546  if (nextPar) {
2547  ATH_MSG_DEBUG(" [+] Position after propagation - at " << positionOutput(nextPar->position()));
2548  }
2549 
2550  if (nextPar) {
2551  ATH_MSG_DEBUG(" [+] Number of intersection solutions: " << solutions.size());
2552  }
2553  if (nextPar) {
2554  throwIntoGarbageBin(cache,nextPar);
2555  }
2556 
2557  // material update has been done already by the propagator
2558  if (cache.m_path.x0Max > 0. &&
2559  ((cache.m_path.process < 100 && cache.m_path.x0Collected >= cache.m_path.x0Max) ||
2560  (cache.m_path.process > 100 && cache.m_path.l0Collected >= cache.m_path.x0Max))) {
2561  // trigger presampled interaction, provide material properties if needed
2562  // process interaction only if creation of secondaries allowed
2563  if (cache.m_currentStatic->geometrySignature() == Trk::ID || m_caloMsSecondary) {
2564  const Trk::Material *extMprop = cache.m_path.process > 100 ? cache.m_currentDense : nullptr;
2565 
2566  const Trk::TrackParameters *iPar = nullptr;
2567  if (nextPar) {
2568  iPar =
2569  m_updators[0]
2570  ->interact(
2571  timeLim.time, nextPar->position(), nextPar->momentum(), particle, cache.m_path.process, extMprop)
2572  .release();
2573  }
2574 
2575  if (!iPar) {
2576  return {nullptr, nullptr, nullptr};
2577  }
2578 
2579  throwIntoGarbageBin(cache,iPar);
2580 
2581  if (iPar && cache.m_path.process == 121) {
2582  ATH_MSG_DEBUG(" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2583  return {nullptr, nullptr, nullptr};
2584  }
2585 
2586  // return transportToVolumeWithPathLimit(*nextPar, timeLim, dir, particle, nextGeoID, destVol);
2587  } else { // kill particle without trace ?
2588  return {nullptr, nullptr, nullptr};
2589  }
2590  }
2591 
2592  // decay ?
2593  if (timeLim.tMax > 0. && timeLim.time >= timeLim.tMax) {
2594  // process interaction only if creation of secondaries allowed
2595  if (cache.m_currentStatic->geometrySignature() == Trk::ID || m_caloMsSecondary) {
2596  // trigger presampled interaction
2597  const Trk::TrackParameters* iPar = m_updators[0]->interact(
2598  timeLim.time, nextPar->position(), nextPar->momentum(), particle, timeLim.process).release();
2599  if (!iPar) {
2600  return {nullptr, nullptr, nullptr};
2601  }
2602 
2603  throwIntoGarbageBin(cache,iPar);
2604  ATH_MSG_WARNING("particle decay survival?" << particle << "," << timeLim.process);
2605  return {nullptr, nullptr, nullptr};
2606  } // kill the particle without trace ( some validation info can be included here eventually )
2607  return {nullptr, nullptr, nullptr};
2608 
2609  }
2610 
2611  if (nextPar) {
2612  unsigned int iSol = 0;
2613  while (iSol < solutions.size()) {
2614  if (solutions[iSol] < cache.m_staticBoundaries.size()) {
2615  // TODO if massive boundary coded, add the material effects here
2616  // static volume boundary; return to the main loop : TODO move from misaligned to static
2617  unsigned int index = solutions[iSol];
2618  // use global coordinates to retrieve attached volume (just for static!)
2619  nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
2620  nextPar->position(), nextPar->momentum(), dir);
2621  // double check the next volume
2622  if (nextVol && !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(), 0.))) {
2623  ATH_MSG_DEBUG(
2624  " [!] WARNING: wrongly assigned static volume ?" << cache.m_currentStatic->volumeName() << "->" <<
2625  nextVol->volumeName());
2626  nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2627  nextPar->position() + 0.01 * dir * nextPar->momentum().normalized());
2628  if (nextVol) {
2629  ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
2630  }
2631  }
2632  // end double check - to be removed after validation of the geometry gluing
2633  // lateral exit from calo sample can be handled here
2634  if (cache.m_hitVector) {
2635  const Trk::BinnedMaterial *binMat = staticVol->binnedMaterial();
2636  if (binMat) {
2637  const Trk::IdentifiedMaterial *binIDMat = binMat->material(nextPar->position());
2638  // save only if entry to the sample present, the exit missing and non-zero step in the sample
2639  if (binIDMat && binIDMat->second > 0 && !cache.m_hitVector->empty() &&
2640  cache.m_hitVector->back().detID == binIDMat->second) {
2641  // double s = (nextPar->position()-m_identifiedParameters->back().first->position()).mag();
2642  // if (s>0.001) m_identifiedParameters->push_back(std::pair<const Trk::TrackParameters*,int>
2643  // (nextPar->clone(), -binIDMat->second));
2644  cache.m_hitVector->emplace_back(nextPar->uniqueClone(), timeLim.time, -binIDMat->second, 0.);
2645  }
2646  }
2647  }
2648  // end lateral exit handling
2649 
2650  ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
2651  // no next volume found --- end of the world
2652  if (!nextVol) {
2653  ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
2654  nextPar->position()) << ", timed at " << cache.m_time);
2656  } else {
2657  ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
2658  ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
2659  }
2660 
2661  return {nextPar, nextVol, cache.m_currentStatic};
2662  }
2663  }
2664  }
2665 
2666  currPar = nextPar;
2667  }
2668 
2669  return {nullptr, nullptr, nullptr};
2670 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Trk::Material::averageZ
float averageZ() const
Definition: Material.h:228
Trk::DistanceSolution::currentDistance
double currentDistance(bool signedDist=false) const
Current distance to surface (spatial), signed (along/opposite to surface normal) if input argument tr...
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
Trk::ParamsNextVolume::nextParameters
const TrackParameters * nextParameters
Definition: TimedExtrapolator.h:114
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
Trk::Layer::isOnLayer
virtual bool isOnLayer(const Amg::Vector3D &gp, const BoundaryCheck &bcheck=BoundaryCheck(true)) const
isOnLayer() method, using isOnSurface() with Layer specific tolerance
Definition: Layer.cxx:135
Trk::TimedExtrapolator::Cache::m_denseResolved
std::pair< unsigned int, unsigned int > m_denseResolved
Definition: TimedExtrapolator.h:389
EnergyLoss.h
ScatteringAngles.h
Trk::TimedExtrapolator::Cache::m_trSurfs
std::vector< std::pair< const Trk::Surface *, double > > m_trSurfs
Definition: TimedExtrapolator.h:412
Trk::TrackingGeometry::atVolumeBoundary
static bool atVolumeBoundary(const Amg::Vector3D &gp, const TrackingVolume *vol, double tol)
check position at volume boundary
Definition: TrackingGeometry.cxx:246
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Trk::Layer::fullUpdateMaterialProperties
const MaterialProperties * fullUpdateMaterialProperties(const TrackParameters &par) const
getting the MaterialProperties back - for full update
Definition: Layer.cxx:169
Trk::TrackingVolume::nextLayer
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &mom, bool asres=true, bool skipNavLayer=false) const
Return the next Layer if existing, NULL if no next layer corresponds.
Definition: TrackingVolume.cxx:418
Trk::TimedExtrapolator::initialize
virtual StatusCode initialize() override
AlgTool initailize method.
Definition: TimedExtrapolator.cxx:145
StraightLineSurface.h
TrackParameters.h
DiscBounds.h
Trk::PathLimit::process
int process
Definition: HelperStructs.h:39
GeometrySignature.h
Trk::TimedExtrapolator::Cache::m_denseVols
std::vector< std::pair< const Trk::TrackingVolume *, unsigned int > > m_denseVols
Definition: TimedExtrapolator.h:392
Trk::Material::L0
float L0
Definition: Material.h:121
Trk::TimedExtrapolator::Cache::m_hitVector
std::vector< Trk::HitInfo > * m_hitVector
return helper for hit info
Definition: TimedExtrapolator.h:381
Trk::MagneticFieldProperties
Definition: MagneticFieldProperties.h:31
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
PerigeeSurface.h
Trk::ParamsNextVolume::boundaryInformation
void boundaryInformation(const TrackingVolume *tvol, const TrackParameters *nextPars, const TrackParameters *navPars, BoundarySurfaceFace face=undefinedFace)
reset the boundary information by invalidating it
Definition: TimedExtrapolator.h:127
Trk::LayerMaterialProperties::fullMaterial
virtual const MaterialProperties * fullMaterial(const Amg::Vector3D &gp) const =0
Return method for full material description of the Layer.
Trk::TimedExtrapolator::validationAction
virtual void validationAction() const override
Validation Action: Can be implemented optionally, outside access to internal validation steps.
Definition: TimedExtrapolator.cxx:1335
Trk::TimedExtrapolator::Cache::m_detachedBoundaries
std::vector< DestSurf > m_detachedBoundaries
Definition: TimedExtrapolator.h:395
Trk::DistanceSolution
Definition: DistanceSolution.h:25
Trk::ID
@ ID
Definition: GeometrySignature.h:26
MaterialProperties.h
Trk::Volume::inside
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Definition: Volume.cxx:72
Trk::TimedExtrapolator::~TimedExtrapolator
virtual ~TimedExtrapolator()
Destructor.
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Trk::oppositeMomentum
@ oppositeMomentum
Definition: PropDirection.h:21
Trk::TrackingVolume::geometrySignature
GeometrySignature geometrySignature() const
return the Signature
Trk::DistanceSolution::numberOfSolutions
int numberOfSolutions() const
Number of intersection solutions.
Trk::PathLimit::updateMat
void updateMat(float dX0, float Z, float dL0)
collected material update
Definition: HelperStructs.h:51
index
Definition: index.py:1
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
Trk::Surface::straightLineDistanceEstimate
virtual DistanceSolution straightLineDistanceEstimate(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const =0
fast straight line distance evaluation to Surface
Trk::ParametersBase::uniqueClone
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
Definition: ParametersBase.h:97
IEnergyLossUpdator.h
Trk::TimedExtrapolator::Cache::m_denseBoundaries
std::vector< DestSurf > m_denseBoundaries
Definition: TimedExtrapolator.h:396
Trk::CurvilinearParameters
CurvilinearParametersT< TrackParametersDim, Charged, PlaneSurface > CurvilinearParameters
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:29
TrackParticleBase.h
Trk::TimedExtrapolator::Cache::m_particleMass
double m_particleMass
Definition: TimedExtrapolator.h:417
Trk::ParamsNextVolume::nextVolume
const TrackingVolume * nextVolume
< the members
Definition: TimedExtrapolator.h:113
Trk::BinnedMaterial
Definition: BinnedMaterial.h:31
Trk::TimedExtrapolator::Cache::m_trStaticBounds
std::vector< Trk::DestBound > m_trStaticBounds
Definition: TimedExtrapolator.h:413
Trk::TimedExtrapolator::Cache::m_path
PathLimit m_path
Definition: TimedExtrapolator.h:399
Trk::TrackingVolume::associatedSubVolume
const TrackingVolume * associatedSubVolume(const Amg::Vector3D &gp) const
Return the associated sub Volume, returns THIS if no subVolume exists.
Definition: TrackingVolume.cxx:530
Trk::ParamsNextVolume::resetBoundaryInformation
void resetBoundaryInformation()
Definition: TimedExtrapolator.h:139
module_driven_slicing.layers
layers
Definition: module_driven_slicing.py:114
Trk::BinUtility::distanceToNext
std::pair< size_t, float > distanceToNext(const Amg::Vector3D &position, const Amg::Vector3D &direction, size_t ba=0) const
Distance estimate to next bin
Definition: BinUtility.h:154
Trk::TimeLimit::process
int process
Definition: HelperStructs.h:61
Trk::Material::zOverAtimesRho
float zOverAtimesRho() const
access to members
Definition: Material.h:226
TimedExtrapolator.h
PlotCalibFromCool.ib
ib
Definition: PlotCalibFromCool.py:419
Trk::TimedExtrapolator::Cache::m_detachedVols
std::vector< std::pair< const Trk::DetachedTrackingVolume *, unsigned int > > m_detachedVols
Definition: TimedExtrapolator.h:391
ParticleTest.tp
tp
Definition: ParticleTest.py:25
Trk::TrackingVolume::confinedDetachedVolumes
ArraySpan< DetachedTrackingVolume const *const > confinedDetachedVolumes() const
Return detached subVolumes - not the ownership.
Layer.h
IPropagator.h
Trk::TimedExtrapolator::emptyGarbageBin
void emptyGarbageBin(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters *) const
Private method for emptying the GarbageBin.
Definition: TimedExtrapolator.cxx:1310
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
Trk::DistanceSolution::first
double first() const
Distance to first intersection solution along direction.
PlotCalibFromCool.multi
multi
Definition: PlotCalibFromCool.py:99
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::Surface::center
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Trk::Calo
@ Calo
Definition: GeometrySignature.h:28
Trk::TimedExtrapolator::extrapolateInAlignableTV
BoundaryTrackParameters extrapolateInAlignableTV(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::AlignableTrackingVolume *aliTV) const
Definition: TimedExtrapolator.cxx:2427
Trk::Layer::compatibleSurfaces
size_t compatibleSurfaces(std::vector< SurfaceIntersection > &cSurfaces, const TrackParameters &pars, PropDirection pdir, const BoundaryCheck &bcheck, bool materialSurfacesOnly=true, const Surface *startSurface=nullptr, const Surface *endSurface=nullptr, const ICompatibilityEstimator *ice=nullptr) const
get compatible surfaces starting from charged parameters
Trk::AlignableTrackingVolume::binnedMaterial
const BinnedMaterial * binnedMaterial() const
access to binned material
Definition: AlignableTrackingVolume.h:68
Trk::NumberOfSignatures
@ NumberOfSignatures
Definition: GeometrySignature.h:32
SUSY_SimplifiedModel_PostInclude.process
string process
Definition: SUSY_SimplifiedModel_PostInclude.py:42
Trk::Layer::layerType
int layerType() const
get the Layer coding
Trk::BoundaryTrackParameters::trPar
const TrackParameters * trPar
Definition: TimedExtrapolator.h:75
Trk::TimedExtrapolator::Cache::m_methodSequence
int m_methodSequence
Definition: TimedExtrapolator.h:404
Track.h
Trk::MS
@ MS
Definition: GeometrySignature.h:29
Trk::TrackingVolume::confinedLayers
const LayerArray * confinedLayers() const
Return the subLayer array.
MagneticFieldProperties.h
Trk::Layer::surfaceArray
const SurfaceArray * surfaceArray() const
Return the entire SurfaceArray, returns nullptr if no SurfaceArray.
RunExEngineTest.PathLimit
PathLimit
Definition: RunExEngineTest.py:61
Trk::FastField
@ FastField
call the fast field access method of the FieldSvc
Definition: MagneticFieldMode.h:20
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
Trk::TimedExtrapolator::transportInAlignableTV
BoundaryTrackParameters transportInAlignableTV(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::AlignableTrackingVolume *aliTV) const
Definition: TimedExtrapolator.cxx:2123
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
GeoPrimitives.h
SurfaceBounds.h
Trk::TimedExtrapolator::Cache::m_parametersAtBoundary
ParamsNextVolume m_parametersAtBoundary
return helper for parameters and boundary
Definition: TimedExtrapolator.h:380
CylinderVolumeBounds.h
Trk::Layer::subSurface
const Surface * subSurface(const Amg::Vector3D &gp) const
If no subSurface array is defined or no subSurface can be found to the given Amg::Vector3D,...
Definition: Layer.cxx:107
Trk::TimedExtrapolator::Cache::m_trLays
std::vector< std::pair< const Trk::Surface *, double > > m_trLays
Definition: TimedExtrapolator.h:415
Volume.h
Trk::PropDirection
PropDirection
Definition: PropDirection.h:19
Trk::TimedExtrapolator::extrapolateWithPathLimit
virtual std::unique_ptr< const Trk::TrackParameters > extrapolateWithPathLimit(const Trk::TrackParameters &parm, Trk::PathLimit &pathLim, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, std::vector< Trk::HitInfo > *&hitVector, Trk::GeometrySignature &nextGeoID, const Trk::TrackingVolume *boundaryVol=nullptr) const override
Extrapolation method for charged, possibly unstable particles.
Definition: TimedExtrapolator.cxx:269
Trk::TimeLimit::tMax
float tMax
Definition: HelperStructs.h:59
Trk::GeometrySignature
GeometrySignature
Definition: GeometrySignature.h:24
Trk::Surface::isOnSurface
virtual bool isOnSurface(const Amg::Vector3D &glopo, const BoundaryCheck &bchk=true, double tol1=0., double tol2=0.) const
This method returns true if the GlobalPosition is on the Surface for both, within or without check of...
Definition: Surface.cxx:123
Trk::Material::x0
float x0() const
Definition: Material.h:227
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
Trk::PathLimit::weightedZ
float weightedZ
Definition: HelperStructs.h:38
Trk::PathLimit::x0Collected
float x0Collected
Definition: HelperStructs.h:36
Trk::ITimedMatEffUpdator::update
virtual std::unique_ptr< TrackParameters > update(const TrackParameters *parm, const Layer &sf, TimeLimit &time, PathLimit &path, Trk::GeometrySignature geoID, PropDirection dir=alongMomentum, ParticleHypothesis particle=pion) const =0
Updator interface (full update for a layer): The parmeters are given as a const pointer.
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Trk::Layer::surfaceRepresentation
virtual const Surface & surfaceRepresentation() const =0
Transforms the layer into a Surface representation for extrapolation.
Trk::active
@ active
Definition: Layer.h:47
Trk::TimedExtrapolator::TimedExtrapolator
TimedExtrapolator(const std::string &, const std::string &, const IInterface *)
Constructor.
Definition: TimedExtrapolator.cxx:56
lumiFormat.i
int i
Definition: lumiFormat.py:85
Trk::ArraySpan
std::span< T > ArraySpan
Definition: TrackingVolume.h:59
beamspotman.n
n
Definition: beamspotman.py:731
Trk::TrackingVolume::confinedArbitraryLayers
ArraySpan< Layer const *const > confinedArbitraryLayers() const
Return the confined subLayer array.
Trk::IPropagator
Definition: IPropagator.h:55
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Trk::DestBound
Definition: TimedExtrapolator.h:60
Trk::TimedExtrapolator::positionOutput
std::string positionOutput(const Amg::Vector3D &pos) const
Private method for conversion of the synchronized geometry signature to the natural subdetector order...
Definition: TimedExtrapolator.cxx:1290
Trk::TrackingVolume::confinedDenseVolumes
ArraySpan< TrackingVolume const *const > confinedDenseVolumes() const
Return unordered subVolumes - not the ownership.
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Trk::DistanceSolution::second
double second() const
Distance to second intersection solution along direction (for a cylinder surface)
Trk::TimedExtrapolator::Cache::m_trDenseBounds
std::vector< std::pair< const Trk::Surface *, double > > m_trDenseBounds
Definition: TimedExtrapolator.h:414
CylinderSurface.h
Trk::CylinderVolumeBounds::halflengthZ
double halflengthZ() const
This method returns the halflengthZ.
Definition: CylinderVolumeBounds.h:207
Trk::TimedExtrapolator::Cache::m_currentDense
const Trk::TrackingVolume * m_currentDense
Definition: TimedExtrapolator.h:387
Trk::Surface::normal
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
Trk::Layer::nextLayer
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &udir) const
getting the next/previous Layer if registered - unit for direction vector required
Definition: Layer.cxx:161
CylinderLayer.h
Trk::Volume::center
const Amg::Vector3D & center() const
returns the center of the volume
Definition: Volume.h:90
Trk::TimedExtrapolator::Cache::m_dense
bool m_dense
internal switch for resolved configuration
Definition: TimedExtrapolator.h:377
Trk::ParametersBase
Definition: ParametersBase.h:55
Trk::TrackingVolume::boundarySurfaces
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
Definition: TrackingVolume.cxx:809
Trk::CurvilinearParametersT
Definition: CurvilinearParametersT.h:48
Trk::TimedExtrapolator::Cache::m_navigBoundaries
std::vector< DestSurf > m_navigBoundaries
Definition: TimedExtrapolator.h:397
Trk::TimeLimit
Definition: HelperStructs.h:58
Trk::neutron
@ neutron
Definition: ParticleHypothesis.h:33
ParticleHypothesis.h
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
Trk::Unsigned
@ Unsigned
Definition: GeometrySignature.h:33
Trk::BinnedArray::arrayObjects
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
Trk::FullField
@ FullField
Field is set to be realistic, but within a given Volume.
Definition: MagneticFieldMode.h:21
Trk::TimedExtrapolator::momentumOutput
static std::string momentumOutput(const Amg::Vector3D &mom)
For the output - global momentum.
Definition: TimedExtrapolator.cxx:1302
DetachedTrackingVolume.h
beamspotman.dir
string dir
Definition: beamspotman.py:623
Trk::BinUtility
Definition: BinUtility.h:39
Trk::Global
@ Global
Definition: GeometrySignature.h:25
Trk::ParametersCommon::localPosition
Amg::Vector2D localPosition() const
Access method for the local coordinates, local parameter definitions differ for each surface type.
Trk::ParticleMasses::mass
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:53
EventPrimitives.h
Trk::CylinderVolumeBounds
Definition: CylinderVolumeBounds.h:70
Trk::TimedExtrapolator::Cache::m_navigSurfs
std::vector< std::pair< const Trk::Surface *, Trk::BoundaryCheck > > m_navigSurfs
Definition: TimedExtrapolator.h:411
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
Trk::TrackingVolume::volumeName
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
IMultipleScatteringUpdator.h
python.EventInfoMgtInit.release
release
Definition: EventInfoMgtInit.py:24
Trk::BoundaryTrackParameters
Definition: TimedExtrapolator.h:74
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
Trk::CylinderVolumeBounds::outerRadius
double outerRadius() const
This method returns the outer radius.
Definition: CylinderVolumeBounds.h:191
Trk::TimedExtrapolator::extrapolateToVolumeWithPathLimit
std::unique_ptr< const Trk::TrackParameters > extrapolateToVolumeWithPathLimit(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoID, const Trk::TrackingVolume *destVol) const
Definition: TimedExtrapolator.cxx:348
Trk::TimedExtrapolator::transportToVolumeWithPathLimit
std::unique_ptr< const Trk::TrackParameters > transportToVolumeWithPathLimit(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::TrackingVolume *boundaryVol) const
Definition: TimedExtrapolator.cxx:1413
BoundarySurfaceFace.h
Trk::IdentifiedMaterial
std::pair< std::shared_ptr< Material >, int > IdentifiedMaterial
Definition: BinnedMaterial.h:23
MaterialLayer.h
checkTriggerxAOD.found
found
Definition: checkTriggerxAOD.py:328
Trk::PathLimit
Definition: HelperStructs.h:34
python.PhysicalConstants.c_light
float c_light
Definition: PhysicalConstants.py:72
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::PathLimit::l0Collected
float l0Collected
Definition: HelperStructs.h:37
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
BoundarySurface.h
Trk::ITimedMatEffUpdator
Definition: ITimedMatEffUpdator.h:43
Trk::TimedExtrapolator::Cache::m_navigLays
std::vector< std::pair< const Trk::TrackingVolume *, const Trk::Layer * > > m_navigLays
Definition: TimedExtrapolator.h:393
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Trk::BinnedMaterial::layerBinUtility
const Trk::BinUtility * layerBinUtility(const Amg::Vector3D &position) const
access to layer bin utility
Definition: BinnedMaterial.h:80
DeMoScan.index
string index
Definition: DeMoScan.py:364
IDynamicLayerCreator.h
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
Trk::IPropagator::propagate
virtual std::unique_ptr< NeutralParameters > propagate(const NeutralParameters &parameters, const Surface &sf, PropDirection dir, const BoundaryCheck &bcheck, bool returnCurv=false) const =0
Main propagation method for NeutralParameters.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::CylinderVolumeBounds::innerRadius
double innerRadius() const
This method returns the inner radius.
Definition: CylinderVolumeBounds.h:187
TRT_PAI_physicsConstants::mb
const double mb
1mb to cm2
Definition: TRT_PAI_physicsConstants.h:15
Trk::BoundaryCheck
Definition: BoundaryCheck.h:51
Trk::BinnedMaterial::material
const IdentifiedMaterial * material(const Amg::Vector3D &position) const
access to material/id per bin
Definition: BinnedMaterial.cxx:58
Trk::TimedExtrapolator::Cache
Definition: TimedExtrapolator.h:363
PlaneSurface.h
Trk::TrackingVolume::confinedVolumes
const TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
Trk::Volume::volumeBounds
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition: Volume.h:96
Trk::Layer::layerMaterialProperties
const LayerMaterialProperties * layerMaterialProperties() const
getting the LayerMaterialProperties including full/pre/post update
Trk::TimeLimit::time
float time
Definition: HelperStructs.h:60
Trk::TimedExtrapolator::Cache::m_garbageBin
std::map< const Trk::TrackParameters *, bool > m_garbageBin
garbage collection during extrapolation
Definition: TimedExtrapolator.h:384
LArCellBinning.step
step
Definition: LArCellBinning.py:158
Trk::TimedExtrapolator::finalize
virtual StatusCode finalize() override
AlgTool finalize method.
Definition: TimedExtrapolator.cxx:263
TrackingGeometry.h
Trk::TimedExtrapolator::Cache::m_layerResolved
unsigned int m_layerResolved
Definition: TimedExtrapolator.h:390
SubtractedCylinderLayer.h
Trk::PathLimit::x0Max
float x0Max
Definition: HelperStructs.h:35
Trk::Material
Definition: Material.h:117
Trk::BinUtility::bin
size_t bin(const Amg::Vector3D &position, size_t ba=0) const
Bin from a 3D vector (already in binning frame)
Definition: BinUtility.h:126
Trk::ComparisonFunction< TrackParameters >
AthAlgTool
Definition: AthAlgTool.h:26
Trk::TimedExtrapolator::Cache::m_layers
std::vector< DestSurf > m_layers
Definition: TimedExtrapolator.h:398
MuonParameters::beta
@ beta
Definition: MuonParamDefs.h:144
Trk::TimedExtrapolator::Cache::m_staticBoundaries
std::vector< DestSurf > m_staticBoundaries
Definition: TimedExtrapolator.h:394
Trk::DetachedTrackingVolume
Definition: DetachedTrackingVolume.h:37
Trk::Surface
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:79
grepfile.fr
fr
Definition: grepfile.py:32
Trk::TimedExtrapolator::overlapSearch
void overlapSearch(Trk::TimedExtrapolator::Cache &cache, const IPropagator &prop, const TrackParameters &parm, const TrackParameters &parsOnLayer, const Layer &lay, float time, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, bool startingLayer=false) const
Private to search for overlap surfaces.
Definition: TimedExtrapolator.cxx:1117
Trk::TrackingVolume
Definition: TrackingVolume.h:119
Trk::TrackingVolume::associatedLayer
const Layer * associatedLayer(const Amg::Vector3D &gp) const
Return the associated Layer.
Definition: TrackingVolume.cxx:382
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
AlignableTrackingVolume.h
Trk::TimedExtrapolator::transportNeutralsWithPathLimit
virtual std::unique_ptr< const Trk::TrackParameters > transportNeutralsWithPathLimit(const Trk::TrackParameters &parm, Trk::PathLimit &pathLim, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, std::vector< Trk::HitInfo > *&hitVector, Trk::GeometrySignature &nextGeoId, const Trk::TrackingVolume *boundaryVol=nullptr) const override
Transport method for neutral, possibly unstable particles.
Definition: TimedExtrapolator.cxx:1344
Trk::TimedExtrapolator::Cache::m_time
double m_time
Definition: TimedExtrapolator.h:400
Trk::TimedExtrapolator::Cache::m_highestVolume
const Trk::TrackingVolume * m_highestVolume
Definition: TimedExtrapolator.h:388
Trk::TimedExtrapolator::Cache::m_currentStatic
const Trk::TrackingVolume * m_currentStatic
Definition: TimedExtrapolator.h:386
python.SystemOfUnits.m
float m
Definition: SystemOfUnits.py:105
Trk::Layer
Definition: Layer.h:72
Trk::AlignableTrackingVolume
Definition: AlignableTrackingVolume.h:36
TrkParametersComparisonFunction.h