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