CMS 3D CMS Logo

HelixExtrapolatorToLine2Order.cc
Go to the documentation of this file.
4 
5 #include <cfloat>
6 
8  const DirectionType& direction,
9  const float curvature,
10  const PropagationDirection propDir)
11  : thePosition(point), theRho(curvature), thePropDir(propDir) {
12  //
13  // Components of direction vector (with correct normalisation)
14  //
15  double px = direction.x();
16  double py = direction.y();
17  double pz = direction.z();
18  double pt = px * px + py * py;
19  double p = sqrt(pt + pz * pz);
20  pt = sqrt(pt);
22  theSinTheta = pt / p;
23 }
24 
25 //
26 // Propagation status and path length to closest approach with point
27 //
28 std::pair<bool, double> HelixExtrapolatorToLine2Order::pathLength(const GlobalPoint& point) const {
29  //
31  DirectionTypeDouble helix2(-0.5 * theRho * theDirection.y(), 0.5 * theRho * theDirection.x(), 0.);
33  //
34  // coefficients of 3rd order equation
35  //
36  double ceq[4];
37  ceq[3] = 2 * helix2.mag2();
38  // ceq[2] = 3*theDirection.dot(helix2) = 0 since they are orthogonal
39  ceq[2] = 0.;
40  ceq[1] = theDirection.mag2() + 2 * deltaPos.dot(helix2);
41  ceq[0] = deltaPos.dot(theDirection);
42  //
43  return pathLengthFromCoefficients(ceq);
44 }
45 
46 //
47 // Propagation status and path length to closest approach with line
48 //
49 std::pair<bool, double> HelixExtrapolatorToLine2Order::pathLength(const Line& line) const {
50  //
51  // Auxiliary vectors. Assumes that line.direction().mag()=1 !
52  //
53  PositionTypeDouble linePosition(line.position());
54  DirectionTypeDouble lineDirection(line.direction());
55  DirectionTypeDouble helix2(-0.5 * theRho * theDirection.y(), 0.5 * theRho * theDirection.x(), 0.);
56  DirectionTypeDouble deltaPos(thePosition - linePosition);
57  DirectionTypeDouble helix1p(theDirection - lineDirection * theDirection.dot(lineDirection));
58  DirectionTypeDouble helix2p(helix2 - lineDirection * helix2.dot(lineDirection));
59  //
60  // coefficients of 3rd order equation
61  //
62  double ceq[4];
63  ceq[3] = 2 * helix2.dot(helix2p);
64  // ceq[2] = 3*helix1.dot(helix1p);
65  // since theDirection.dot(helix2)==0 equivalent to
66  ceq[2] = 3 * theDirection.dot(lineDirection) * helix2.dot(lineDirection);
67  ceq[1] = theDirection.dot(helix1p) + 2 * deltaPos.dot(helix2p);
68  ceq[0] = deltaPos.dot(helix1p);
69  //
70  return pathLengthFromCoefficients(ceq);
71 }
72 
73 //
74 // Propagation status and path length to intersection
75 //
76 std::pair<bool, double> HelixExtrapolatorToLine2Order::pathLengthFromCoefficients(const double ceq[4]) const {
77  //
78  // Solution of 3rd order equation
79  //
80  double solutions[3];
81  unsigned int nRaw = solve3rdOrder(ceq, solutions);
82  //
83  // check compatibility with propagation direction
84  //
85  unsigned int nDir(0);
86  for (unsigned int i = 0; i < nRaw; i++) {
87  if (thePropDir == anyDirection || (solutions[i] >= 0 && thePropDir == alongMomentum) ||
89  solutions[nDir++] = solutions[i];
90  }
91  if (nDir == 0)
92  return std::make_pair(false, 0.);
93  //
94  // check 2nd derivative
95  //
96  unsigned int nMin(0);
97  for (unsigned int i = 0; i < nDir; i++) {
98  double st = solutions[i];
99  double deri2 = (3 * ceq[3] * st + 2 * ceq[2]) * st + ceq[1];
100  if (deri2 > 0.)
101  solutions[nMin++] = st;
102  }
103  if (nMin == 0)
104  return std::make_pair(false, 0.);
105  //
106  // choose smallest path length
107  //
108  double dSt = solutions[0];
109  for (unsigned int i = 1; i < nMin; i++) {
110  if (fabs(solutions[i]) < fabs(dSt))
111  dSt = solutions[i];
112  }
113 
114  return std::make_pair(true, dSt / theSinTheta);
115 }
116 
117 int HelixExtrapolatorToLine2Order::solve3rdOrder(const double ceq[], double solutions[]) const {
118  //
119  // Real 3rd order equation? Follow numerical recipes ..
120  //
121  if (fabs(ceq[3]) > FLT_MIN) {
122  int result(0);
123  double q = (ceq[2] * ceq[2] - 3 * ceq[3] * ceq[1]) / (ceq[3] * ceq[3]) / 9.;
124  double r = (2 * ceq[2] * ceq[2] * ceq[2] - 9 * ceq[3] * ceq[2] * ceq[1] + 27 * ceq[3] * ceq[3] * ceq[0]) /
125  (ceq[3] * ceq[3] * ceq[3]) / 54.;
126  double q3 = q * q * q;
127  if (r * r < q3) {
128  double phi = acos(r / sqrt(q3)) / 3.;
129  double rootq = sqrt(q);
130  for (int i = 0; i < 3; i++) {
131  solutions[i] = -2 * rootq * cos(phi) - ceq[2] / ceq[3] / 3.;
132  phi += 2. / 3. * M_PI;
133  }
134  result = 3;
135  } else {
136  double a = pow(fabs(r) + sqrt(r * r - q3), 1. / 3.);
137  if (r > 0.)
138  a *= -1;
139  double b = fabs(a) > FLT_MIN ? q / a : 0.;
140  solutions[0] = a + b - ceq[2] / ceq[3] / 3.;
141  result = 1;
142  }
143  return result;
144  }
145  //
146  // Second order equation
147  //
148  else if (fabs(ceq[2]) > FLT_MIN) {
149  return solve2ndOrder(ceq, solutions);
150  } else {
151  //
152  // Special case: linear equation
153  //
154  solutions[0] = -ceq[0] / ceq[1];
155  return 1;
156  }
157 }
158 
159 int HelixExtrapolatorToLine2Order::solve2ndOrder(const double coeff[], double solutions[]) const {
160  //
161  double deq1 = coeff[1] * coeff[1];
162  double deq2 = coeff[2] * coeff[0];
163  if (fabs(deq1) < FLT_MIN || fabs(deq2 / deq1) > 1.e-6) {
164  //
165  // Standard solution for quadratic equations
166  //
167  double deq = deq1 + 2 * deq2;
168  if (deq < 0.)
169  return 0;
170  double ceq = -0.5 * (coeff[1] + (coeff[1] > 0 ? 1 : -1) * sqrt(deq));
171  solutions[0] = -2 * ceq / coeff[2];
172  solutions[1] = coeff[0] / ceq;
173  return 2;
174  } else {
175  //
176  // Solution by expansion of sqrt(1+deq)
177  //
178  double ceq = coeff[1] / coeff[2];
179  double deq = deq2 / deq1;
180  deq *= (1 - deq / 2);
181  solutions[0] = -ceq * deq;
182  solutions[1] = ceq * (2 + deq);
183  return 2;
184  }
185 }
186 //
187 // Position after a step of path length s (2nd order)
188 //
190  // use double precision result
191  // PositionTypeDouble pos = positionInDouble(s);
192  // return PositionType(pos.x(),pos.y(),pos.z());
194 }
195 //
196 // Position after a step of path length s (2nd order) (in double precision)
197 //
199  // based on path length in the transverse plane
200  double st = s * theSinTheta;
201  return PositionTypeDouble(thePosition.x() + (theDirection.x() - st * 0.5 * theRho * theDirection.y()) * st,
202  thePosition.y() + (theDirection.y() + st * 0.5 * theRho * theDirection.x()) * st,
203  thePosition.z() + st * theDirection.z());
204 }
205 //
206 // Direction after a step of path length 2 (2nd order) (in double precision)
207 //
209  // use double precision result
210  // DirectionTypeDouble dir = directionInDouble(s);
211  // return DirectionType(dir.x(),dir.y(),dir.z());
213 }
214 //
215 // Direction after a step of path length 2 (2nd order)
216 //
218  // based on delta phi
219  double dph = s * theRho * theSinTheta;
220  return DirectionTypeDouble(theDirection.x() - (theDirection.y() + 0.5 * theDirection.x() * dph) * dph,
221  theDirection.y() + (theDirection.x() - 0.5 * theDirection.y() * dph) * dph,
222  theDirection.z());
223 }
HelixExtrapolatorToLine2Order(const PositionType &point, const DirectionType &direction, const float curvature, const PropagationDirection propDir=alongMomentum)
Constructor using point, direction and (transverse!) curvature.
T x() const
Cartesian x coordinate.
Definition: Line.h:10
Basic3DVector< double > PositionTypeDouble
virtual std::pair< bool, double > pathLengthFromCoefficients(const double ceq[4]) const
common part for propagation to point and line
PositionType position(double s) const override
Position at pathlength s from the starting point.
DirectionTypeDouble directionInDouble(double s) const
Direction at pathlength s from the starting point in double precision.
constexpr int pow(int x)
Definition: conifer.h:24
PropagationDirection
Basic3DVector< double > DirectionTypeDouble
T y() const
Cartesian y coordinate.
int solve2ndOrder(const double ceq[], double sol[]) const
Solutions of 2nd order equation.
T curvature(T InversePt, const MagneticField &field)
Basic3DVector< float > DirectionType
Basic3DVector< float > PositionType
T sqrt(T t)
Definition: SSEVec.h:19
int solve3rdOrder(const double ceq[], double sol[]) const
Solutions of 3rd order equation.
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
#define M_PI
T z() const
Cartesian z coordinate.
double b
Definition: hdecay.h:120
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
double a
Definition: hdecay.h:121
DirectionType direction(double s) const override
Direction at pathlength s from the starting point.
std::pair< bool, double > pathLength(const GlobalPoint &point) const override
T dot(const Basic3DVector &rh) const
Scalar product, or "dot" product, with a vector of same type.
PositionTypeDouble positionInDouble(double s) const
Position at pathlength s from the starting point in double precision.
*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