ATLAS Offline Software
StaticNavigationEngine.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 ///////////////////////////////////////////////////////////////////
6 // StaticNavigationEngine.icc, (c) ATLAS Detector software
7 ///////////////////////////////////////////////////////////////////
8 
9 #include "TrkExInterfaces/IPropagationEngine.h"
10 #include "TrkExInterfaces/IMaterialEffectsEngine.h"
11 #include "TrkGeometry/TrackingVolume.h"
12 #include "TrkGeometry/TrackingGeometry.h"
13 #include "TrkVolumes/BoundarySurface.h"
14 #include "GeoPrimitives/GeoPrimitives.h"
15 
16 /** handle the failure - as configured */
17 template <class T> Trk::ExtrapolationCode Trk::StaticNavigationEngine::resolveBoundaryT(Trk::ExtrapolationCell<T>& eCell,
18  Trk::PropDirection pDir) const
19 {
20  EX_MSG_DEBUG(++eCell.navigationStep, "navigation", "", "resolve boundary situation leaving '"<< eCell.leadVolume->volumeName()
21  << (int(pDir) > 0 ? "' along momentum." : "' opposite momentum.") );
22  // initialize the extrapolation code to progress
23  Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
24  // [1] ------------------------ fast boundary access : take straight line estimates as navigation guide --------------
25  auto boundaryIntersections = eCell.leadVolume->boundarySurfacesOrdered(*eCell.leadParameters,
26  pDir,
27  eCell.onLastBoundary() );
28  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "found " << boundaryIntersections.size() << " boundary surfaces to try"
29  << ( eCell.onLastBoundary() ? " - starting from last boundary." : "." ) );
30  // remember them for the slow acces
31  std::map< const Trk::BoundarySurface<Trk::TrackingVolume>*, bool > bSurfacesTried;
32 
33  for (auto& boundaryCandidate : boundaryIntersections){
34  // the surface of the
35  const Trk::BoundarySurface<Trk::TrackingVolume>* bSurfaceTV = boundaryCandidate.object;
36  // skip if it's the last boundary surface
37  if ( eCell.onLastBoundary() && &bSurfaceTV->surfaceRepresentation() == eCell.lastBoundarySurface ) continue;
38  // check this boudnary, possible return codes are:
39  // - SuccessPathLimit : propagation to boundary caused PathLimit to be fail @TODO implement protection againg far of tries
40  // - SuccessMaterialLimit : boundary was reached and material update on boundary reached limit
41  // - InProgress : boundary was reached and ready for continueing the navigation
42  // - UnSet : boundary was not reached, try the next one
43  // - FailureLoop : next Volume was previous Volume
44  eCode = handleBoundaryT<T>(eCell,*bSurfaceTV,pDir);
45  CHECK_ECODE_SUCCESS(eCell, eCode);
46  // Failure or Unset are not triggering a return, try more sophisticated navigation
47  if (!eCode.inProgress()){
48  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "boundary surface not reached with " << eCode.toString() << ", skipping.");
49  // book keeping for the slow access not to try again the same stuff
50  bSurfacesTried[bSurfaceTV] = false;
51  // skip to the next surface if there's one
52  continue;
53  }
54  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "boundary surface handling yielded code " << eCode.toString());
55  // set that this was the last boundary surface
56  eCell.lastBoundarySurface = &bSurfaceTV->surfaceRepresentation();
57  // and return the code yielded by the handleBoundaryT
58  return eCode;
59  }
60  // [2] ------------------------ slow boundary access : take all boundary surfaces and simply try --------------
61  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "fast boundary navigation did not succeeed - trying slow navigation now.");
62  // ignore the ones you have tried already
63  const auto& bSurface = eCell.leadVolume->boundarySurfaces();
64  for (size_t ib=0 ; ib< bSurface.size(); ++ib){
65  // we tried this one already, no point to do it again
66  if ( bSurfacesTried.size() && bSurfacesTried.find(bSurface[ib]) != bSurfacesTried.end() ) continue;
67  // skip if it's the last boundary surface
68  if ( &bSurface[ib]->surfaceRepresentation() == eCell.lastBoundarySurface ) continue;
69  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "trying a boundary surface.");
70  // there is now loop protection in the slow access, needs to be done by hand
71  // check this boudnary, possible return codes are:
72  // - SuccessPathLimit : propagation to boundary caused PathLimit to be fail @TODO implement protection againg far of tries
73  // - SuccessMaterialLimit : boundary was reached and material update on boundary reached limit
74  // - InProgress : boundary was reached and ready for continueing the navigation
75  // - UnSet : boundary was not reached, try the next one
76  eCode = handleBoundaryT<T>(eCell,*bSurface[ib],pDir);
77  CHECK_ECODE_SUCCESS(eCell, eCode);
78  // Failure or Unset are not triggering a return, try more sophisticated navigation
79  if (!eCode.inProgress()){
80  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "boundary surface not reached with " << eCode.toString() << ", skipping.");
81  // skip to the next surface if there's one
82  continue;
83  }
84  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "boundary surface handling yielded code " << eCode.toString());
85  // set that this was the last boundary surface
86  eCell.lastBoundarySurface = &bSurface[ib]->surfaceRepresentation();
87  // and return the code yielded by the handleBoundaryT
88  return eCode;
89  }
90  // [3] ------------------------ slowest boundary access : step-out-of-volume approach -------------------------
91  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "slow boundary navigation did not succeeed - trying step-out-of-volume approach now");
92  for (auto& boundaryCandidate : boundaryIntersections){
93  // the surface of the
94  const Trk::BoundarySurface<Trk::TrackingVolume>* bSurfaceTV = boundaryCandidate.object;
95  // check this boudnary, possible return codes are:
96  // - SuccessPathLimit : propagation to boundary caused PathLimit to be fail @TODO implement protection againg far of tries
97  // - SuccessMaterialLimit : boundary was reached and material update on boundary reached limit
98  // - InProgress : boundary was reached and ready for continueing the navigation
99  // - UnSet : boundary was not reached, try the next one
100  // - FailureLoop : next Volume was previous Volume
101  eCode = handleBoundaryT<T>(eCell,*bSurfaceTV,pDir,true);
102  CHECK_ECODE_SUCCESS(eCell, eCode);
103  // Failure or Unset are not triggering a return, try more sophisticated navigation
104  if (!eCode.inProgress()){
105  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "boundary surface not reached with " << eCode.toString() << ", skipping.");
106  // skip to the next surface if there's one
107  continue;
108  }
109  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "boundary surface handling yielded code " << eCode.toString());
110  // set that this was the last boundary surface
111  eCell.lastBoundarySurface = &bSurfaceTV->surfaceRepresentation();
112  // and return the code yielded by the handleBoundaryT
113  return eCode;
114  }
115  // return it back
116  EX_MSG_DEBUG(eCell.navigationStep, "navigation", "", "could not resolve the boundary situation. Exiting.");
117 
118  return Trk::ExtrapolationCode::FailureNavigation;
119 }
120 
121 /** handle the failure - as configured */
122 template <class T> Trk::ExtrapolationCode Trk::StaticNavigationEngine::handleBoundaryT(Trk::ExtrapolationCell<T>& eCell,
123  const Trk::BoundarySurface<Trk::TrackingVolume>& bSurfaceTV,
124  Trk::PropDirection pDir,
125  bool stepout) const
126 {
127  // get the bondary surface and compare with last one to prevent loops
128  const Trk::Surface& bSurface = bSurfaceTV.surfaceRepresentation();
129  // propagate the parameters to the boundary (force boundaryCheck to true in case it is not a step-out trial), possible return codes :
130  // - SuccessPathLimit : pathLimit reached during propagation
131  // - InProgress : boundary reached
132  // - Recovered : boundary not reached
133  Trk::ExtrapolationCode eCode = m_propagationEngine->propagate(eCell,bSurface,pDir,!stepout,eCell.destinationCurvilinear);
134  CHECK_ECODE_SUCCESS(eCell, eCode);
135  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "handleBoundaryT", "propagation with eCode " << eCode.toString());
136  // check for progress
137  if (eCode.inProgress()){
138  // check if the boundary solution is compatible with the radial direciton of the extrapolation
139  if (!eCell.checkRadialCompatibility()) {
140  // screen output for the radial compatibility check
141  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "handleBoundaryT", "radial compatbility check failed, radial direction is: " << eCell.radialDirection);
142  // it's not jump back to the last valid lead parameters and return Unset as a trigger
143  eCell.leadParameters = eCell.lastLeadParameters;
144  return Trk::ExtrapolationCode::Unset;
145  }
146  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "parameters on boundary surface created, moving to next volume.");
147  // get the nextVolume - modify the position in case you have a step out trial, take attachment otherwise
148  const Trk::TrackingVolume* nextVolume = stepout ?
149  trackingGeometry().lowestTrackingVolume(Amg::Vector3D(eCell.leadParameters->position()+pDir*eCell.leadParameters->momentum().unit())) :
150  bSurfaceTV.attachedVolume(eCell.leadParameters->position(), eCell.leadParameters->momentum(), pDir);
151  // check if we have no nextVolume : boundary rechaed @TODO it's not really a success
152  if (!nextVolume) {
153  eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectBoundary); // ST fixing memory leak
154  return Trk::ExtrapolationCode::SuccessBoundaryReached;
155  }
156  // check if it is a boundary reached case
157  // - geometrySignature change and configuration to stop then triggers a Success
158  bool stopAtThisBoundary = eCell.checkConfigurationMode(Trk::ExtrapolationMode::StopAtBoundary)
159  && (nextVolume->geometrySignature() != eCell.leadVolume->geometrySignature() && nextVolume->geometrySignature()!=Trk::HGTD);
160  // fill the boundary into the cache if successfully hit boundary surface
161  // - only cache if those are not the final parameters caused by a StopAtBoundary
162  if (!stopAtThisBoundary)
163  eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectBoundary);
164  // loop protection - relaxed for the cases where you start from the boundary
165  if (eCell.leadVolume == nextVolume ) {
166  // the start parameters where on the boundary already give a relaxed return code
167  if (&bSurface == eCell.lastBoundarySurface) return Trk::ExtrapolationCode::Unset;
168  // give some screen output as of why this happens
169  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "loop detected while trying to leave TrackingVolume '" << nextVolume->volumeName() << ".");
170  // return a loop failure, parameter deletion will be done by cache
171  return Trk::ExtrapolationCode::FailureLoop;
172  }
173  // update the with the information of the layer material - will change the leadParameters
174  if (bSurface.materialLayer()) {
175  // assign the new lead layer for material inclusion
176  eCell.leadLayer = bSurface.materialLayer();
177  // now handle the material, possible return codes:
178  // - InProgress : material update performed or not (depending on material)
179  // - SuccessMaterialLimit : material limit reached & configured to stop there
180  eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
181  CHECK_ECODE_SUCCESS(eCell, eCode);
182  }
183  // break if configured to break at volume boundary and signature change
184  if (stopAtThisBoundary){
185  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "geometry signature change from " << eCell.leadVolume->geometrySignature() << " to " << nextVolume->geometrySignature());
186  eCell.nextGeometrySignature = nextVolume->geometrySignature();
187  // return the boundary reached : the navigation resolved already
188  eCell.leadVolume = nextVolume;
189  return Trk::ExtrapolationCode::SuccessBoundaryReached;
190  }
191  // remember the last boundary surface for loop protection
192  eCell.lastBoundarySurface = &bSurface;
193  eCell.lastBoundaryParameters = eCell.leadParameters;
194  // set next volume and reset lead layer
195  eCell.leadVolume = nextVolume;
196  eCell.leadLayer = 0;
197  // we have bParameters -> break the loop over boundaryIntersections
198  return Trk::ExtrapolationCode::InProgress;
199  }
200 
201  // you need to keep on trying
202  return Trk::ExtrapolationCode::Unset;
203  }
204 
205 
206 /** handle the failure - as configured */
207 template <class T> Trk::ExtrapolationCode Trk::StaticNavigationEngine::resolvePositionT(Trk::ExtrapolationCell<T>& eCell,
208  Trk::PropDirection pDir,
209  bool /*noLoop*/ ) const
210 {
211  EX_MSG_DEBUG(++eCell.navigationStep, "navigation", "", "resolve position '"<< eCell.leadParameters->position()
212  << (int(pDir) > 0 ? "' along momentum." : "' opposite momentum.") );
213 
214  // noLoop= True is used when we have exit from leadVolume
215  const TrackingGeometry &tracking_geometry = trackingGeometry();
216  if (!eCell.leadVolume) eCell.leadVolume = tracking_geometry.lowestStaticTrackingVolume(eCell.leadParameters->position());
217  if (!eCell.leadVolume) return Trk::ExtrapolationCode::FailureNavigation;
218  const Trk::TrackingVolume* nextVol=0;
219  if ( tracking_geometry.atVolumeBoundary(eCell.leadParameters->position(),
220  eCell.leadParameters->momentum(),
221  eCell.leadVolume,
222  nextVol, pDir, 0.01) ) { // set tolerance globally
223 
224  //if (noLoop && nextVol==eCell.leadVolume) return Trk::ExtrapolationCode::FailureLoop;
225 
226  if (nextVol) {
227  eCell.leadVolume = nextVol;
228  return Trk::ExtrapolationCode::InProgress;
229  } else return Trk::ExtrapolationCode::FailureNavigation;
230  }
231 
232  return Trk::ExtrapolationCode::InProgress;
233 }