ATLAS Offline Software
StepEngine.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 // StepEngine.icc, (c) ATLAS Detector software
7 ///////////////////////////////////////////////////////////////////
8 
9 #include "TrkExInterfaces/IMaterialEffectsEngine.h"
10 #include "TrkExInterfaces/INavigationEngine.h"
11 #include "TrkSurfaces/Surface.h"
12 #include "TrkGeometry/TrackingGeometry.h"
13 #include "TrkGeometry/TrackingVolume.h"
14 #include "TrkGeometry/Layer.h"
15 #include <iostream>
16 #include <iomanip>
17 
18 template<class T> Trk::ExtrapolationCode Trk::StepEngine::targetSurfacesT(Trk::ExtrapolationCell<T>& eCell,
19  Trk::TargetSurfaceVector& ts,
20  bool trueOrderedIntersections,
21  const Trk::Surface* sf,
22  const Trk::BoundaryCheck& bcheck ) const
23 {
24  // evaluate the initial distance and save for the propagator/transport step
25  Amg::Vector3D gp = eCell.leadParameters->position();
26  Amg::Vector3D mom = eCell.leadParameters->momentum().normalized();
27  Trk::PropDirection dir = eCell.propDirection;
28 
29  // destination surface
30  if (sf) {
31  Trk::TargetSurface tt(sf,bcheck,Trk::SurfNavigType::Target,0,0,Trk::TVNavigType::Unknown);
32  evaluateDistance(tt,gp,mom*dir,ts,trueOrderedIntersections);
33  // abort if no valid intersection
34  if (!ts.size()) return Trk::ExtrapolationCode::FailureDestination;
35  }
36 
37  // static frame boundaries
38  const auto &bounds = eCell.leadVolume->boundarySurfaces();
39  // count number of non-trivial solutions
40  unsigned int iInt=0;
41  for (unsigned int ib=0; ib< bounds.size(); ib++ ){
42  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
43  Trk::TargetSurface bb(&surf,true,Trk::SurfNavigType::BoundaryFrame,ib,eCell.leadVolume,Trk::TVNavigType::Frame);
44  evaluateDistance(bb,gp,mom*dir,ts,trueOrderedIntersections);
45  if (ts.size() && ts.back().surf==&surf && ts.back().distanceAlongPath>m_tolerance) iInt++;
46  }
47  if (iInt==0 ) { // navigation problem : frame volume not resolved : trigger return && catch inf loop
48  return Trk::ExtrapolationCode::FailureLoop;
49  }
50 
51  // frame resolved
52 
53  // order intersections
54  if ( ts.size()>1 && trueOrderedIntersections ) {
55 
56  std::vector<unsigned int> sols(ts.size());
57  for (unsigned int i=0;i<ts.size(); i++) { sols[i]=i; }
58 
59  unsigned int itest=1;
60  while ( itest<sols.size() ) {
61  if ( ts[sols[itest]].distanceAlongPath < ts[sols[itest-1]].distanceAlongPath ) {
62  unsigned int iex = sols[itest-1];
63  sols[itest-1]=sols[itest];
64  sols[itest]=iex;
65  itest=1;
66  } else itest++;
67  }
68 
69  Trk::TargetSurfaceVector tsOrd ;
70  for (unsigned int i=0;i<ts.size(); i++) tsOrd.push_back(ts[sols[i]]);
71  for (unsigned int i=0;i<ts.size(); i++) ts[i]=tsOrd[i];
72  }
73 
74  return Trk::ExtrapolationCode::InProgress;
75 }
76 
77 template<class T> Trk::ExtrapolationCode Trk::StepEngine::resolveFrameBoundaryT(Trk::ExtrapolationCell<T>& eCell, Amg::Vector3D gp,
78  unsigned int bIndex ) const
79 {
80  const auto &bounds = eCell.leadVolume->boundarySurfaces();
81 
82  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "","current lead volume:"<<eCell.leadVolume->volumeName());
83 
84  const Trk::TrackingVolume* nextVolume = bounds[bIndex]->attachedVolume(gp,
85  eCell.leadParameters->momentum(),
86  eCell.propDirection);
87 
88  if (nextVolume) EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "resolveFrameBoundary:"<< nextVolume->volumeName()
89  <<" at position:"<< eCell.leadParameters->position().perp() <<","<<eCell.leadParameters->position().z()
90  << ","<<eCell.leadParameters->momentum().normalized()<<","<<eCell.propDirection);
91 
92  if (!nextVolume) return Trk::ExtrapolationCode::SuccessBoundaryReached;
93 
94  // - geometrySignature change and configuration to stop then triggers a Success
95  bool stopAtThisBoundary = eCell.checkConfigurationMode(Trk::ExtrapolationMode::StopAtBoundary)
96  && (nextVolume->geometrySignature() != eCell.leadVolume->geometrySignature());
97 
98  if (stopAtThisBoundary) {
99  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "", "geometry signature change from " <<
100  eCell.leadVolume->geometrySignature() << " to " << nextVolume->geometrySignature());
101  eCell.nextGeometrySignature = nextVolume->geometrySignature();
102  // return the boundary reached
103  return Trk::ExtrapolationCode::SuccessBoundaryReached;
104  } else {
105  // fill the boundary into the cache if successfully hit boundary surface
106  eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectBoundary);
107  }
108  // loop protection - relaxed for the cases where you start from the boundary
109  if (eCell.leadVolume == nextVolume ) {
110  // the start parameters where on the boundary already give a relaxed return code
111  // if (&bSurface == eCell.lastBoundarySurface) return Trk::ExtrapolationCode::Unset;
112  // give some screen output as of why this happens
113  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "",
114  "loop detected while trying to leave TrackingVolume '" << nextVolume->volumeName() << ".");
115 
116  // can be a precision problem
117  if ((eCell.leadParameters->position()-eCell.lastBoundaryParameters->position()).mag()>0
118  && nextVolume->inside(gp+0.01*eCell.leadParameters->momentum().normalized()*eCell.propDirection,0.001) )
119  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "",
120  "recovered, continue propagation in " << nextVolume->volumeName() << ".");
121  else return Trk::ExtrapolationCode::FailureLoop;
122  }
123  // remember the last boundary surface for loop protection
124  // ecNeutral.lastBoundarySurface = &bounds[index];
125  eCell.lastBoundaryParameters = eCell.leadParameters;
126  // set next volume
127  eCell.leadVolume = nextVolume;
128 
129  // retrieve frame boundary surfaces, check early exit
130  if ( !m_targetSurfaces.initFrameVolume(eCell.leadParameters->position(),
131  eCell.leadParameters->momentum().normalized()*eCell.propDirection,
132  eCell.leadVolume ) ) {
133  // problem detected in the update of tracking surfaces: probably exit from the frame volume within tolerance range
134  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", "","early exit detected at boundary index:"<< m_targetSurfaces.nextSf());
135  Amg::Vector3D gp = eCell.leadParameters->position()+
136  eCell.leadParameters->momentum().normalized()*eCell.propDirection*m_targetSurfaces.distanceToNext();
137  return resolveFrameBoundaryT(eCell,gp,m_targetSurfaces.nextSf());
138 
139  }
140 
141  EX_MSG_VERBOSE(eCell.navigationStep, "navigation", ""," frame volume resolved :"<< eCell.leadVolume->volumeName());
142 
143  return Trk::ExtrapolationCode::InProgress;
144  }