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 "TrkVolumes/BoundarySurface.h"
14 #include "GeoPrimitives/GeoPrimitives.h"
16 /** handle the failure - as configured */
17 template <class T> Trk::ExtrapolationCode Trk::StaticNavigationEngine::resolveBoundaryT(Trk::ExtrapolationCell<T>& eCell,
18 Trk::PropDirection pDir) const
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,
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;
33 for (auto& boundaryCandidate : boundaryIntersections){
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
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
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
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
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){
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
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
116 EX_MSG_DEBUG(eCell.navigationStep, "navigation", "", "could not resolve the boundary situation. Exiting.");
118 return Trk::ExtrapolationCode::FailureNavigation;
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,
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;
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
153 eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectBoundary); // ST fixing memory leak
154 return Trk::ExtrapolationCode::SuccessBoundaryReached;
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;
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);
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;
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;
197 // we have bParameters -> break the loop over boundaryIntersections
198 return Trk::ExtrapolationCode::InProgress;
201 // you need to keep on trying
202 return Trk::ExtrapolationCode::Unset;
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
211 EX_MSG_DEBUG(++eCell.navigationStep, "navigation", "", "resolve position '"<< eCell.leadParameters->position()
212 << (int(pDir) > 0 ? "' along momentum." : "' opposite momentum.") );
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(),
222 nextVol, pDir, 0.01) ) { // set tolerance globally
224 //if (noLoop && nextVol==eCell.leadVolume) return Trk::ExtrapolationCode::FailureLoop;
227 eCell.leadVolume = nextVol;
228 return Trk::ExtrapolationCode::InProgress;
229 } else return Trk::ExtrapolationCode::FailureNavigation;
232 return Trk::ExtrapolationCode::InProgress;