CMS 3D CMS Logo

HelixArbitraryPlaneCrossing.cc
Go to the documentation of this file.
4 
5 #include <cmath>
6 #include <vdt/vdtMath.h>
7 #include <iostream>
9 
10 #ifdef VI_DEBUG
11 #include <atomic>
12 struct MaxIter {
13  MaxIter() {}
14  ~MaxIter() { std::cout << "maxiter " << v << std::endl; }
15  void operator()(int i) const {
16  int old = v;
17  int t = std::min(old, i);
18  while (not v.compare_exchange_weak(old, t)) {
19  t = std::min(old, i);
20  }
21  }
22  mutable std::atomic<int> v{100};
23 };
24 #else
25 struct MaxIter {
26  MaxIter() {}
27  void operator()(int) const {}
28 };
29 #endif
30 static const MaxIter maxiter;
31 
33  const DirectionType& direction,
34  const float curvature,
35  const PropagationDirection propDir)
36  : theQuadraticCrossingFromStart(point, direction, curvature, propDir),
37  theX0(point.x()),
38  theY0(point.y()),
39  theZ0(point.z()),
40  theRho(curvature),
41  thePropDir(propDir),
42  theCachedS(0),
43  theCachedDPhi(0.),
44  theCachedSDPhi(0.),
45  theCachedCDPhi(1.) {
46  //
47  // Components of direction vector (with correct normalisation)
48  //
49  double px = direction.x();
50  double py = direction.y();
51  double pz = direction.z();
52  double pt2 = px * px + py * py;
53  double p2 = pt2 + pz * pz;
54  double pI = 1. / sqrt(p2);
55  double ptI = 1. / sqrt(pt2);
56  theCosPhi0 = px * ptI;
57  theSinPhi0 = py * ptI;
58  theCosTheta = pz * pI;
59  theSinTheta = pt2 * ptI * pI;
60 }
61 //
62 // Propagation status and path length to intersection
63 //
64 std::pair<bool, double> HelixArbitraryPlaneCrossing::pathLength(const Plane& plane) {
65  //
66  // Constants used for control of convergence
67  //
68  constexpr int maxIterations = 20;
69  //
70  // maximum distance to plane (taking into account numerical precision)
71  //
72  float maxNumDz = theNumericalPrecision * plane.position().mag();
73  float safeMaxDist = (theMaxDistToPlane > maxNumDz ? theMaxDistToPlane : maxNumDz);
74  //
75  // Prepare internal value of the propagation direction and position / direction vectors for iteration
76  //
77 
78  float dz = plane.localZ(Surface::GlobalPoint(theX0, theY0, theZ0));
79  if (std::abs(dz) < safeMaxDist)
80  return std::make_pair(true, 0.);
81 
82  bool notFail;
83  double dSTotal;
84  // Use existing 2nd order object at first pass
85  std::tie(notFail, dSTotal) = theQuadraticCrossingFromStart.pathLength(plane);
86  if UNLIKELY (!notFail)
87  return std::make_pair(notFail, dSTotal);
88  auto xnew = positionInDouble(dSTotal);
89 
90  auto propDir = thePropDir;
91  auto newDir = dSTotal >= 0 ? alongMomentum : oppositeToMomentum;
92  if (propDir == anyDirection) {
93  propDir = newDir;
94  } else {
95  if UNLIKELY (newDir != propDir)
96  return std::pair<bool, double>(false, 0);
97  }
98 
99  //
100  // Prepare iterations: count and total pathlength
101  //
102  auto iteration = maxIterations;
103  while (notAtSurface(plane, xnew, safeMaxDist)) {
104  //
105  // return empty solution vector if no convergence after maxIterations iterations
106  //
107  if UNLIKELY (--iteration == 0) {
108  LogDebug("HelixArbitraryPlaneCrossing") << "pathLength : no convergence";
109  return std::pair<bool, double>(false, 0);
110  }
111 
112  //
113  // create temporary object for subsequent passes.
114  auto pnew = directionInDouble(dSTotal);
115  HelixArbitraryPlaneCrossing2Order quadraticCrossing(
116  xnew.x(), xnew.y(), xnew.z(), pnew.x(), pnew.y(), theCosTheta, theSinTheta, theRho, anyDirection);
117 
118  auto deltaS2 = quadraticCrossing.pathLength(plane);
119 
120  if UNLIKELY (!deltaS2.first)
121  return deltaS2;
122  //
123  // Calculate and sort total pathlength (max. 2 solutions)
124  //
125  dSTotal += deltaS2.second;
126  auto newDir = dSTotal >= 0 ? alongMomentum : oppositeToMomentum;
127  if (propDir == anyDirection) {
128  propDir = newDir;
129  } else {
130  if UNLIKELY (newDir != propDir)
131  return std::pair<bool, double>(false, 0);
132  }
133  //
134  // Step forward by dSTotal.
135  //
136  xnew = positionInDouble(dSTotal);
137  }
138  //
139  // Return result
140  //
142 
143  return std::make_pair(true, dSTotal);
144 }
145 //
146 // Position on helix after a step of path length s.
147 //
149  // use result in double precision
151  return PositionType(pos.x(), pos.y(), pos.z());
152 }
153 //
154 // Position on helix after a step of path length s in double precision.
155 //
157  //
158  // Calculate delta phi (if not already available)
159  //
160  if UNLIKELY (s != theCachedS) {
161  theCachedS = s;
164  }
165  //
166  // Calculate with appropriate formulation of full helix formula or with
167  // 2nd order approximation.
168  //
169  // if ( fabs(theCachedDPhi)>1.e-1 ) {
170  if (std::abs(theCachedDPhi) > 1.e-4) {
171  // "standard" helix formula
172  double o = 1. / theRho;
176  }
177  // else if ( fabs(theCachedDPhi)>theNumericalPrecision ) {
178  // // full helix formula, but avoiding (1-cos(deltaPhi)) for small angles
179  // return PositionTypeDouble(theX0+(-theSinPhi0*theCachedSDPhi*theCachedSDPhi/(1.+theCachedCDPhi)+
180  // theCosPhi0*theCachedSDPhi)/theRho,
181  // theY0+(theCosPhi0*theCachedSDPhi*theCachedSDPhi/(1.+theCachedCDPhi)+
182  // theSinPhi0*theCachedSDPhi)/theRho,
183  // theZ0+theCachedS*theCosTheta);
184  // }
185  else {
186  // Use 2nd order.
188  }
189 }
190 //
191 // Direction vector on helix after a step of path length s.
192 //
194  // use result in double precision
196  return DirectionType(dir.x(), dir.y(), dir.z());
197 }
198 //
199 // Direction vector on helix after a step of path length s in double precision.
200 //
202  //
203  // Calculate delta phi (if not already available)
204  //
205  if UNLIKELY (s != theCachedS) { // very very unlikely!
206  theCachedS = s;
209  }
210 
211  if (std::abs(theCachedDPhi) > 1.e-4) {
212  // full helix formula
216  } else {
217  // 2nd order
219  }
220 }
221 // Iteration control: continue if distance to plane > theMaxDistToPlane. Includes
222 // protection for numerical precision (Surfaces work with single precision).
224  const PositionTypeDouble& point,
225  const float maxDist) const {
226  float dz = plane.localZ(Surface::GlobalPoint(point.x(), point.y(), point.z()));
227  return std::abs(dz) > maxDist;
228 }
229 
std::pair< bool, double > pathLength(const Plane &plane) override
HelixArbitraryPlaneCrossing2Order theQuadraticCrossingFromStart
T x() const
Cartesian x coordinate.
PositionTypeDouble positionInDouble(double s) const
DirectionTypeDouble directionInDouble(double s) const
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
Basic3DVector< double > PositionTypeDouble
const PropagationDirection thePropDir
PropagationDirection
PositionTypeDouble positionInDouble(double s) const
bool notAtSurface(const Plane &, const PositionTypeDouble &, const float) const
T y() const
Cartesian y coordinate.
Definition: Plane.h:16
float float float z
T curvature(T InversePt, const MagneticField &field)
PositionType position(double s) const override
T sqrt(T t)
Definition: SSEVec.h:23
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
static const MaxIter maxiter
Basic3DVector< float > PositionType
the helix is passed to the constructor and does not appear in the interface
Basic3DVector< float > DirectionType
float localZ(const GlobalPoint &gp) const
Definition: Plane.h:45
const PositionType & position() const
T z() const
Cartesian z coordinate.
std::pair< bool, double > pathLength(const Plane &) override
Basic3DVector< double > DirectionTypeDouble
DirectionTypeDouble directionInDouble(double s) const
float x
void operator()(int) const
#define UNLIKELY(x)
Definition: Likely.h:21
HelixArbitraryPlaneCrossing(const PositionType &point, const DirectionType &direction, const float curvature, const PropagationDirection propDir=alongMomentum)
void fast_sincos(const MPF &a, MPF &s, MPF &c)
DirectionType direction(double s) const override
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
#define LogDebug(id)