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