2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
5 ///////////////////////////////////////////////////////////////////
6 // StaticNavigationEngine.icc, (c) ATLAS Detector software
7 ///////////////////////////////////////////////////////////////////
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"
17 /** handle the failure - as configured */
18 template <class T> Trk::ExtrapolationCode Trk::StaticNavigationEngine::resolveBoundaryT(Trk::ExtrapolationCell<T>& eCell,
19 Trk::PropDirection pDir) const
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,
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;
34 for (auto& boundaryCandidate : boundaryIntersections){
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
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
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
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
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){
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
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
117 EX_MSG_DEBUG(eCell.navigationStep, "navigation", "", "could not resolve the boundary situation. Exiting.");
119 return Trk::ExtrapolationCode::FailureNavigation;
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,
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;
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
154 eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectBoundary); // ST fixing memory leak
155 return Trk::ExtrapolationCode::SuccessBoundaryReached;
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;
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);
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;
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;
198 // we have bParameters -> break the loop over boundaryIntersections
199 return Trk::ExtrapolationCode::InProgress;
202 // you need to keep on trying
203 return Trk::ExtrapolationCode::Unset;
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
212 EX_MSG_DEBUG(++eCell.navigationStep, "navigation", "", "resolve position '"<< eCell.leadParameters->position()
213 << (int(pDir) > 0 ? "' along momentum." : "' opposite momentum.") );
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(),
223 nextVol, pDir, 0.01) ) { // set tolerance globally
225 //if (noLoop && nextVol==eCell.leadVolume) return Trk::ExtrapolationCode::FailureLoop;
228 eCell.leadVolume = nextVol;
229 return Trk::ExtrapolationCode::InProgress;
230 } else return Trk::ExtrapolationCode::FailureNavigation;
233 return Trk::ExtrapolationCode::InProgress;