ATLAS Offline Software
StaticEngine.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 ///////////////////////////////////////////////////////////////////
6 // StaticEngine.icc, (c) ATLAS Detector software
7 ///////////////////////////////////////////////////////////////////
8 
9 #include "TrkExInterfaces/INavigationEngine.h"
10 #include "TrkExInterfaces/IPropagationEngine.h"
11 #include "TrkExInterfaces/IMaterialEffectsEngine.h"
12 #include "TrkSurfaces/Surface.h"
13 #include "TrkGeometry/TrackingGeometry.h"
14 #include "TrkGeometry/TrackingVolume.h"
15 #include "TrkGeometry/Layer.h"
16 #include "TrkGeometry/MaterialLayer.h"
17 #include <iostream>
18 #include <iomanip>
19 
20 template <class T> Trk::ExtrapolationCode Trk::StaticEngine::extrapolateT(Trk::ExtrapolationCell<T>& eCell,
21  const Trk::Surface* sf,
22  Trk::PropDirection pDir,
23  const Trk::BoundaryCheck& bcheck) const
24 {
25  Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
26  // ---- [0] check the direct propagation exit
27  //
28  // obviously need a surface to exercise the fallback & need to be configured to do so
29  if (sf && eCell.checkConfigurationMode(Trk::ExtrapolationMode::Direct)){
30  EX_MSG_DEBUG(++eCell.navigationStep, "extrapolate", "", "direct extapolation in volume : " << eCell.leadVolume->volumeName());
31  // propagate to the surface, possible return codes are : SuccessPathLimit, SucessDestination, FailureDestination
32  eCode = m_propagationEngine->propagate(eCell,*sf,pDir,bcheck,eCell.destinationCurvilinear);
33  // eCode can be directly returned
34  return eCode;
35  }
36  EX_MSG_DEBUG(++eCell.navigationStep, "extrapolate", "", "extrapolation in static environment in volume : " << eCell.leadVolume->volumeName());
37  // evoke or finish the navigation initialization, possible return codes are:
38  // - InProgress : everything is fine, extrapolation in static volume is in progress
39  // - FailureNavigation : navigation setup could not be resolved, but reovery was not configured
40  // - Recovered : navigation setup could not be resolved, recovery by fallback to directly kicked in (and worked)
41  eCode = initNavigationT<T>(eCell,sf,pDir,bcheck);
42  CHECK_ECODE_CONTINUE(eCell, eCode);
43  // ----- [1] handle the ( leadLayer == endLayer )case :
44  //
45  // - this case does not need a layer to layer loop
46  if (sf && eCell.leadLayer == eCell.endLayer && eCell.initialVolume()){
47  // screen output for startLayer == endLayer
48  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "start and destination layer are identical -> jumping to final propagation.");
49  // set the leadLayerSurface to the parameters surface
50  eCell.leadLayerSurface = &(eCell.leadParameters->associatedSurface());
51  // resolve the layer, it is the final extrapolation
52  // - InProgress : layer resolving went without problem
53  // - SuccessPathLimit : path limit reached & configured to stop (rather unlikely within a layer)
54  // - SuccessMaterialLimit : material limit reached & configured to stop there
55  // if the lead layer is also the startLayer found by initialization -> no material handling
56  eCode = resolveLayerT<T>(eCell,
57  sf,
58  pDir,
59  bcheck,
60  eCell.leadLayer->hasSubStructure(eCell.checkConfigurationMode(Trk::ExtrapolationMode::CollectSensitive)),
61  (eCell.leadLayer == eCell.startLayer && eCell.leadVolume == eCell.startVolume),
62  true);
63  // Success triggers a return
64  CHECK_ECODE_SUCCESS_NODEST(eCell, eCode);
65  // extrapolation to destination was not successful
66  // - handle the return as configured (e.g. fallback)
67  return handleReturnT<T>(eCode, eCell, sf, pDir, bcheck);
68  }
69  // ----- [2] now do the layer-to-layer loop
70  //
71  // the volume returns the layers ordered by distance :
72  // - give potential start and end layer (latter only for the final volume)
73  // - start and end layer will be part of the loop
74  // - surface on approach is not yet resolved
75  const Trk::Layer* fLayer = eCell.finalVolumeReached() ? eCell.endLayer : 0;
76  auto layerIntersections = eCell.leadVolume->materialLayersOrdered(eCell.leadLayer, fLayer,
77  *eCell.leadParameters,
78  pDir,
79  true);
80 
81  EX_MSG_VERBOSE(eCell.navigationStep, "layer", "loop", "found " << layerIntersections.size() << " layers for the layer-to-layer loop.");
82  // layer-to-layer loop starts here
83  for (auto& layerCandidate : layerIntersections ) {
84  // assign the leadLayer
85  eCell.leadLayer = layerCandidate.object;
86  // screen output for layer-to-layer loop
87  EX_MSG_VERBOSE(eCell.navigationStep, "layer", "loop", "processing layer with index : " << eCell.leadLayer->layerIndex().value());
88  // resolve the approach surface situation
89  // - it is the approaching surface for all layers but the very first one (where it's the parameter surface)
90  eCell.leadLayerSurface = (eCell.leadLayer == eCell.startLayer) ? &(eCell.leadParameters->associatedSurface()) :
91  &(eCell.leadLayer->surfaceOnApproach(eCell.leadParameters->position(),
92  eCell.leadParameters->momentum(),
93  pDir,
94  true,
95  true));
96  // handle the layer, possible returns are :
97  // - InProgress : fine, whatever happened on the lead layer, may also be missed
98  // - SuccessWithPathLimit : propagation towards layer exceeded path limit
99  // - SuccessWithMaterialLimit : material interaction killed track
100  // - FailureDestination : destination was not hit appropriately
101  eCode = handleLayerT<T>(eCell, sf, pDir, bcheck);
102  EX_MSG_VERBOSE(eCell.navigationStep, "layer", layerCandidate.object->layerIndex().value(), "handleLayerT returned extrapolation code : " << eCode.toString());
103  // Possibilities are:
104  // - SuccessX -> return (via handleReturnT)
105  // - FailureX -> return (via handleReturnT that might evoke a fallback)
106  // - InProgess -> continue layer-to-layer loop
107  if (!eCode.inProgress()) return handleReturnT<T>(eCode, eCell, sf, pDir, bcheck);
108  }
109  // the layer 2 layer loop is done, the lead parameters are at the last valid option
110  // ----- [3] now resolve the boundary situation, call includes information wheather one is alreay at a boundary
111  //
112  // the navigaiton engine ca trigger different return codes
113  // - InProgress : fine, boundary surface has been found
114  // - SuccessWithPathLimit : propagation towards boundary surface exceeded path limit
115  // - FailureLoop/Navigation : problem in boundary resolving
116  eCode = m_navigationEngine->resolveBoundary(eCell, pDir);
117  // SuccessX and FailureX trigger a return
118  CHECK_ECODE_SUCCESS_NODEST(eCell, eCode);
119  // handle the return of the boudnary resolving
120  return handleReturnT<T>(eCode, eCell, sf, pDir, bcheck);
121 }
122 
123 template <class T> Trk::ExtrapolationCode Trk::StaticEngine::initNavigationT(Trk::ExtrapolationCell<T>& eCell,
124  const Trk::Surface* sf,
125  Trk::PropDirection pDir,
126  Trk::BoundaryCheck bcheck) const
127 {
128  // initialize the Navigation stream ----------------------------------------------------------------------------------------
129  //
130  // this is the global initialization, it only associated direct objects
131  // detailed navigation search needs to be done by the sub engines (since they know best)
132  EX_MSG_DEBUG(++eCell.navigationStep, "navigation", "", "complete for static environment.");
133  // [A] the initial volume
134  if (eCell.startVolume == eCell.leadVolume && eCell.startLayer) {
135  // - found the initial start layer through association
136  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "this is the initial volume, everything set up already.");
137  // assigning it to the leadLayer
138  eCell.leadLayer = eCell.startLayer;
139  // return progress
140  return Trk::ExtrapolationCode::InProgress;
141  }
142  // [B] any volume if we don't have a leadLayer
143  if (!eCell.leadLayer){
144  // - finding it through global search, never a boundary layer ... convention says that you update by exit
145  eCell.leadLayer = eCell.leadVolume->associatedLayer(eCell.leadParameters->position());
146  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "no start layer found yet, looking for it ..." << OH_CHECKFOUND(eCell.leadLayer) );
147  }
148  // [C] the final volume - everything's fine
149  if (eCell.leadVolume == eCell.endVolume && sf) {
150  if (eCell.endLayer) {
151  // the end layer had been found already by association
152  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "this is the final volume, everything set up already.");
153  return Trk::ExtrapolationCode::InProgress;
154  } else {
155  // make a straight line intersection
156  Trk::Intersection sfI = sf->straightLineIntersection(eCell.leadParameters->position(), pDir*eCell.leadParameters->momentum(), true);
157  // use this to find endVolume and endLayer
158  eCell.endLayer = eCell.leadVolume->associatedLayer(sfI.position);
159  // if you have a surface you need to require an end layer for the validation, otherwise you need to do a fallbac
160  return eCell.endLayer ? Trk::ExtrapolationCode::InProgress : handleReturnT<T>(Trk::ExtrapolationCode::FailureNavigation, eCell, sf, pDir, bcheck);
161  }
162  }
163  // return that you're in progress
164  return Trk::ExtrapolationCode::InProgress;
165 }
166 
167 /** handle the layer */
168 template <class T> Trk::ExtrapolationCode Trk::StaticEngine::handleLayerT(Trk::ExtrapolationCell<T>& eCell,
169  const Trk::Surface* sf,
170  Trk::PropDirection pDir,
171  Trk::BoundaryCheck bcheck) const
172 {
173  Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
174  EX_MSG_DEBUG(++eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "handle this layer" );
175  // layer has sub structure - this can be (and the layer will tell you):
176  // - sensitive surface which should be tried to hit
177  // - material sub structure to be resolved (independent of sensitive surface)
178  bool hasSubStructure = eCell.leadLayer->hasSubStructure(eCell.checkConfigurationMode(Trk::ExtrapolationMode::CollectSensitive));
179  // [A] layer is a pure navigation layer and has no sub structure -> skip it, but only if it is not the final layer
180  if (!hasSubStructure && !eCell.leadLayer->layerIndex().value() && eCell.leadLayer != eCell.endLayer){
181  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "layer is a navigation layer -> skipping it ...");
182  return Trk::ExtrapolationCode::InProgress;
183  }
184  // [B] layer resolving is necessary -> resolve it
185  // - (a) layer has sub structure - this can be (and the layer will tell you):
186  // - sensitive surface which should be tried to hit
187  // - material sub structure to be resolved (independent of sensitive surface)
188  // - (b) layer is start layer (can not be if there was a volume switch)
189  bool isStartLayer = eCell.initialVolume() && eCell.leadLayer->onLayer(*eCell.leadParameters);
190  // - (c) layer is destination layer
191  // - final propagation to the layer and update if necessary
192  bool isDestinationLayer = (sf && eCell.leadLayer == eCell.endLayer);
193  // sub structure, start and destination need resolving of the layer setp
194  if (hasSubStructure || isStartLayer || isDestinationLayer ){
195  // screen output for sub strucutred layer
196  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "has sub structure, is start layer, or destination layer -> resolving it ..." );
197  // resolve the layer, it handles all possible return types and gives them directly to extrapolateT<T>
198  // - InProgress : layer resolving went without problem
199  // - SuccessPathLimit : path limit reached & configured to stop
200  // - SuccessMaterialLimit : material limit reached & configured to stop there
201  // - SuccessDestination : destination reached & everything is fine
202  return resolveLayerT<T>(eCell,sf,pDir,bcheck,hasSubStructure,isStartLayer,isDestinationLayer);
203  }
204  // [C] layer is a material layer without sub structure but material -> pass through
205  // no resolving ob sub structure to be done, an intermediate layer to be crossed
206  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "intermediate layer without sub structure -> passing through ...");
207  // propagate to it, possible return codes ( with the default of finalPropagation = false):
208  // - SuccessPathLimit : propagation to layer exceeded path limit
209  // - InProgress : layer was hit successfuly, try to handle the material and sub structure, these are new parameters
210  // - Recovered : layer was not hit, so can be ignored in the layer to layer loop
211  eCode = m_propagationEngine->propagate(eCell,*eCell.leadLayerSurface,pDir,true,eCell.navigationCurvilinear);
212  CHECK_ECODE_SUCCESS_NODEST(eCell, eCode);
213  // record the passive parameters
214  if (eCode!=Trk::ExtrapolationCode::Recovered) eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectPassive);
215  // check if the layer was actually hit
216  if (eCode.inProgress()){
217  // successful layer hit
218  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "has been succesful hit, handling material update.");
219  // layer has no sub-structure : it is an intermediate layer that just needs pass-throgh
220  // return possbilities:
221  // - InProgress : material update performed or not (depending on material)
222  // - SuccessMaterialLimit : material limit reached & configured to stop there
223  eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
224  CHECK_ECODE_CONTINUE(eCell, eCode);
225  // return the progress eCode back to the extrapolateT
226  return eCode;
227  }
228  // hit or not hit : it's always in progress since we are in the layer to layer loop
229  return Trk::ExtrapolationCode::InProgress;
230 }
231 
232 
233 /** main sub structure layer handling */
234 template <class T> Trk::ExtrapolationCode Trk::StaticEngine::resolveLayerT(Trk::ExtrapolationCell<T>& eCell,
235  const Trk::Surface* sf,
236  Trk::PropDirection pDir,
237  Trk::BoundaryCheck bcheck,
238  bool hasSubStructure,
239  bool isStartLayer,
240  bool isDestinationLayer) const
241 {
242  Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
243  EX_MSG_DEBUG(++eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "resolve it with" << (hasSubStructure ? " " : "out ") << "sub structure"
244  << (isDestinationLayer ? " -> destination layer." : (isStartLayer ? " -> start layer." : "") ) );
245 
246  // cache the leadLayer - this is needed for the layer-to-layer loop not to be broken
247  const Trk::Layer* initialLayer = eCell.leadLayer;
248  // ----- [0] the start situation on the layer needs to be resolved:
249  // - either for sensitive parameters
250  // - or for material substructure
251  // [A] the layer is not the start layer and not the destination layer
252  // - the surfaceOnApproach() call should have sorted out that this is actually an approaching representation
253  // - the destination layer is excluded from the propagation because it can lead to punch-through to the other side of layers
254  if (!isStartLayer && !isDestinationLayer){
255  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "not the start layer (with sub structue), propagate to it.");
256  // propagate to the representing surface of this layer
257  // - InProgress : propagation to approaching surface worked - check material update
258  // - SuccessPathLimit : propagation to approaching surface reached the path limit
259  // - Recovered : layer was not hit, so can be ignored in the layer to layer loop
260  eCode = m_propagationEngine->propagate(eCell,*eCell.leadLayerSurface,pDir,true,eCell.sensitiveCurvilinear);
261  CHECK_ECODE_SUCCESS_NODEST(eCell,eCode);
262  // the extrapolation to the initial layer did not succeed - skip this layer in the layer-to-layer loop
263  if (eCode == Trk::ExtrapolationCode::Recovered) {
264  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "has not been hit, skipping it.");
265  return Trk::ExtrapolationCode::InProgress;
266  }
267  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "successfuly hit.");
268  // fill the corresponding parameters, the material effects updator can attach material to them
269  eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectPassive);
270  // the correct material layer needs to be assigned - in case of the approach surface not being hit, his can be the layer surface
271  if (eCell.leadLayerSurface->materialLayer() ||
272  (eCell.leadLayerSurface == &(eCell.leadLayer->surfaceRepresentation()) && eCell.leadLayer->layerMaterialProperties()) ){
273  // screen output for debugging
274  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "needs material update.");
275  // assign the right lead layer for the material update
276  if (eCell.leadLayerSurface->materialLayer())
277  eCell.leadLayer = eCell.leadLayerSurface->materialLayer();
278  // now handle the material (full update when passing approach surface), return codes are:
279  // - SuccessMaterialLimit : material limit reached, return back
280  // - InProgress : material update done or not (depending on the material description)
281  eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
282  CHECK_ECODE_CONTINUE(eCell, eCode);
283  }
284  } else if (isStartLayer) {
285  // [B] the layer is the start layer
286  // - let's check if a post update on the start surface has to be done
287  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "start layer (with sub structure), no propagation to be done.");
288  // the start surface could have a material layer attached
289  if (eCell.leadParameters->associatedSurface().materialLayer()){
290  eCell.leadLayer = eCell.leadParameters->associatedSurface().materialLayer();
291  // now handle the material (post update on start layer), return codes are:
292  // - SuccessMaterialLimit : material limit reached, return back
293  // - InProgress : material update done or not (depending on the material description)
294  eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::postUpdate);
295  CHECK_ECODE_CONTINUE(eCell, eCode);
296  // let's reset the lead layer
297  eCell.leadLayer = initialLayer;
298  }
299  }
300  // ----- [1] the sub structure of the layer needs to be resolved:
301  // resolve the substructure
302  std::vector<Trk::SurfaceIntersection> cSurfaces;
303  // this will give you the compatible surfaces of the layer : provided start and destination surface are excluded
304  // - surfaces without material are only provided if they are active and CollectSensitive is configured
305  // - surfaces with material are provided in order to make the necessary material update
306  size_t ncSurfaces = eCell.leadLayer->compatibleSurfaces(cSurfaces,
307  *eCell.leadParameters,
308  pDir,
309  bcheck,
310  !eCell.checkConfigurationMode(Trk::ExtrapolationMode::CollectSensitive),
311  (isStartLayer ? &(eCell.leadParameters->associatedSurface()) : eCell.leadLayerSurface),
312  (isDestinationLayer ? sf : 0) );
313  // some screen output for the sub structure
314  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "found " << ncSurfaces << " sub structrue surfaces to test.");
315  // check if you have to do something
316  if (ncSurfaces){
317  // now loop over the surfaces:
318  // the surfaces will be sorted
319  for (auto& csf : cSurfaces ) {
320  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "trying candidate surfaces with straight line path length " << csf.intersection.pathLength);
321  // propagate to the compatible surface, return types are
322  // - InProgress : propagation to compatible surface worked
323  // - Recovered : propagation to compatible surface did not work, leadParameters stay the same
324  // - SuccessPathLimit : propagation to compatible surface reached the path limit
325  eCode = m_propagationEngine->propagate(eCell,*(csf.object),pDir,true,eCell.sensitiveCurvilinear);
326  CHECK_ECODE_SUCCESS_NODEST(eCell,eCode);
327  // check if the propagation was successful
328  if (eCode.inProgress()){
329  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "successfully hit sub structure surface.");
330  // record the parameters as sensitive or passive depending on the surface
331  Trk::ExtrapolationMode::eMode emode = csf.object->isActive() ? Trk::ExtrapolationMode::CollectSensitive : Trk::ExtrapolationMode::CollectPassive;
332  // fill the corresponding parameters, the material effects updator can attach material to them
333  eCell.stepParameters(eCell.leadParameters, emode);
334  // check if the surface holds a material layer
335  // - yes : it is a sub surface that has a material layer attached
336  // - yes : it is any other layer for the material integration
337  if (csf.object->materialLayer() || ( csf.object->associatedLayer() && csf.object == &(csf.object->associatedLayer()->surfaceRepresentation()) ) ) {
338  // the resolved surface has material, set the leadLayer to
339  // - the materialLayer ( has higher priority than the associatedLayer() )
340  // - the associatedLayer ( it is the representing layer )
341  eCell.leadLayer = csf.object->materialLayer() ? csf.object->materialLayer() : csf.object->associatedLayer();
342  // now handle the material, return codes are:
343  // - SuccessMaterialLimit : material limit reached,return back
344  // - InProgress : material update done or not (depending on the material description)
345  eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
346  CHECK_ECODE_CONTINUE(eCell, eCode);
347  }
348  } else if (eCode== Trk::ExtrapolationCode::SuccessPathLimit) {
349  eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectPassive);
350  }
351  } // loop over test surfaces done
352  } // there are compatible surfaces
353 
354  // ----- [3] the destination situation on the layer needs to be resolved:
355  // the layer is a destination layer
356  // - the final propagation call is indepenent of whether sub structure was resolved or not
357  // - the eCell.leadParameters are at the last possible parameters
358  if (sf && isDestinationLayer) {
359  // [B] the layer is start and destination layer but has no sub-structure
360  // -> propagation to destination surface
361  // (a) the starting layer is the same layer :
362  // - neither preUpdate nore postUpdate to be done, this is old-style within-layer extrapolation
363  // - material will be taken into account either when the layer was reached from another layer
364  // or when the layer is left to another destination
365  // (b) the starting layer is not the same layer :
366  // - apply the preUpdate on the parameters whein they reached the surface
367  // Possible return types:
368  // - SuccessDestination : great, desintation surface hit - but post-update needs to be done
369  // - SuccessPathLimit : pathlimit was reached on the way to the destination surface
370  eCode = m_propagationEngine->propagate(eCell,*sf,pDir,false,eCell.destinationCurvilinear);
371  // check for success return path limit
372  CHECK_ECODE_SUCCESS_NODEST(eCell,eCode);
373  EX_MSG_VERBOSE(eCell.navigationStep, "layer", eCell.leadLayer->layerIndex().value(), "attempt to hit destination surface resulted in " << eCode.toString() );
374  // check for a potential preUpdate
375  // - in case teh destination surface has material and the surface was hit
376  if ( sf->materialLayer() && eCode.isSuccess() ){
377  // the resolved surface has material, set the leadLayer to
378  eCell.leadLayer = sf->materialLayer();
379  // finally do the material update
380  // - this is the final call - still check for SuccessMaterialLimit
381  // the material effects updator usually returns inProgress, this needs to be ingored
382  m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::preUpdate);
383  // check if success was triggered through path limit reached on the way to the layer
384  CHECK_ECODE_SUCCESS(eCell,eCode);
385  }
386  // return what you have handleLayerT or extrapolateT will resolve that
387  return eCode;
388  }
389  // reset the lead layer to ensure the layer-to-layer loop
390  eCell.leadLayer = initialLayer;
391  // return the code:
392  // - if it came until here, return InProgress to not break the layer-to-layer loop
393  return Trk::ExtrapolationCode::InProgress;
394 }
395 
396 /** handle the failure - as configured */
397 template <class T> Trk::ExtrapolationCode Trk::StaticEngine::handleReturnT(Trk::ExtrapolationCode eCode,
398  Trk::ExtrapolationCell<T>& eCell,
399  const Trk::Surface* sf,
400  Trk::PropDirection pDir,
401  Trk::BoundaryCheck bcheck) const
402 {
403  EX_MSG_DEBUG(++eCell.navigationStep, "return", "", "handleReturnT with code " << eCode.toString() << " called." );
404  if (eCode.isSuccessOrRecovered() || eCode.inProgress() ){
405  EX_MSG_VERBOSE(eCell.navigationStep, "return", "", "leaving static extrapolator successfully with code " << eCode.toString());
406  return eCode;
407  }
408  EX_MSG_VERBOSE(eCell.navigationStep, "return", "", "failure detected as " << eCode.toString() << " - checking fallback configuration.");
409  // obviously we need a surface to exercise the fallback
410  if (sf && !eCell.checkConfigurationMode(Trk::ExtrapolationMode::AvoidFallback)){
411  EX_MSG_VERBOSE(eCell.navigationStep, "return", "", "fallback configured. Trying to hit destination surface from last valid parameters.");
412  // check if you hit the surface, could still be stopped by PathLimit, but would also count as recovered
413  eCode = m_propagationEngine->propagate(eCell,*sf,pDir,bcheck,eCell.destinationCurvilinear);
414  }
415 
416  return eCode;
417 }
418 
419