CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 
32 
33 HelixArbitraryPlaneCrossing::HelixArbitraryPlaneCrossing(const PositionType& point,
34  const DirectionType& direction,
35  const float curvature,
36  const PropagationDirection propDir) :
37  theQuadraticCrossingFromStart(point,direction,curvature,propDir),
38  theX0(point.x()),
39  theY0(point.y()),
40  theZ0(point.z()),
41  theRho(curvature),
42  thePropDir(propDir),
43  theCachedS(0),
44  theCachedDPhi(0.),
45  theCachedSDPhi(0.),
46  theCachedCDPhi(1.)
47 {
48  //
49  // Components of direction vector (with correct normalisation)
50  //
51  double px = direction.x();
52  double py = direction.y();
53  double pz = direction.z();
54  double pt2 = px*px+py*py;
55  double p2 = pt2+pz*pz;
56  double pI = 1./sqrt(p2);
57  double ptI = 1./sqrt(pt2);
58  theCosPhi0 = px*ptI;
59  theSinPhi0 = py*ptI;
60  theCosTheta = pz*pI;
61  theSinTheta = pt2*ptI*pI;
62 }
63 //
64 // Propagation status and path length to intersection
65 //
66 std::pair<bool,double>
67 HelixArbitraryPlaneCrossing::pathLength(const Plane& plane) {
68  //
69  // Constants used for control of convergence
70  //
71  constexpr int maxIterations = 20;
72  //
73  // maximum distance to plane (taking into account numerical precision)
74  //
75  float maxNumDz = theNumericalPrecision*plane.position().mag();
76  float safeMaxDist = (theMaxDistToPlane>maxNumDz?theMaxDistToPlane:maxNumDz);
77  //
78  // Prepare internal value of the propagation direction and position / direction vectors for iteration
79  //
80 
81  float dz = plane.localZ(Surface::GlobalPoint(theX0,theY0,theZ0));
82  if (std::abs(dz)<safeMaxDist) return std::make_pair(true,0.);
83 
84  bool notFail;
85  double dSTotal;
86  // Use existing 2nd order object at first pass
87  std::tie(notFail,dSTotal) = theQuadraticCrossingFromStart.pathLength(plane);
88  if unlikely(!notFail) return std::make_pair(notFail,dSTotal);
89  auto xnew = positionInDouble(dSTotal);
90 
91  auto propDir = thePropDir;
92  auto newDir = dSTotal>=0 ? alongMomentum : oppositeToMomentum;
93  if ( propDir == anyDirection ) {
94  propDir = newDir;
95  } else {
96  if unlikely( newDir!=propDir ) return std::pair<bool,double>(false,0);
97  }
98 
99 
100  //
101  // Prepare iterations: count and total pathlength
102  //
103  auto iteration = maxIterations;
104  while ( notAtSurface(plane,xnew,safeMaxDist) ) {
105  //
106  // return empty solution vector if no convergence after maxIterations iterations
107  //
108  if unlikely( --iteration == 0 ) {
109  LogDebug("HelixArbitraryPlaneCrossing") << "pathLength : no convergence";
110  return std::pair<bool,double>(false,0);
111  }
112 
113  //
114  // create temporary object for subsequent passes.
115  auto pnew = directionInDouble(dSTotal);
116  HelixArbitraryPlaneCrossing2Order quadraticCrossing(xnew.x(),xnew.y(),xnew.z(),
117  pnew.x(),pnew.y(),
118  theCosTheta,theSinTheta,
119  theRho,
120  anyDirection);
121 
122  auto deltaS2 = quadraticCrossing.pathLength(plane);
123 
124 
125  if unlikely( !deltaS2.first ) return deltaS2;
126  //
127  // Calculate and sort total pathlength (max. 2 solutions)
128  //
129  dSTotal += deltaS2.second;
130  auto newDir = dSTotal>=0 ? alongMomentum : oppositeToMomentum;
131  if ( propDir == anyDirection ) {
132  propDir = newDir;
133  }
134  else {
135  if unlikely( newDir!=propDir ) return std::pair<bool,double>(false,0);
136  }
137  //
138  // Step forward by dSTotal.
139  //
140  xnew = positionInDouble(dSTotal);
141  }
142  //
143  // Return result
144  //
145  maxiter(iteration);
146 
147  return std::make_pair(true,dSTotal);
148 }
149 //
150 // Position on helix after a step of path length s.
151 //
153 HelixArbitraryPlaneCrossing::position (double s) const {
154  // use result in double precision
155  PositionTypeDouble pos = positionInDouble(s);
156  return PositionType(pos.x(),pos.y(),pos.z());
157 }
158 //
159 // Position on helix after a step of path length s in double precision.
160 //
161 HelixArbitraryPlaneCrossing::PositionTypeDouble
162 HelixArbitraryPlaneCrossing::positionInDouble (double s) const {
163  //
164  // Calculate delta phi (if not already available)
165  //
166  if unlikely( s!=theCachedS ) {
167  theCachedS = s;
168  theCachedDPhi = theCachedS*theRho*theSinTheta;
169  vdt::fast_sincos(theCachedDPhi,theCachedSDPhi,theCachedCDPhi);
170  }
171  //
172  // Calculate with appropriate formulation of full helix formula or with
173  // 2nd order approximation.
174  //
175 // if ( fabs(theCachedDPhi)>1.e-1 ) {
176  if ( std::abs(theCachedDPhi)>1.e-4 ) {
177  // "standard" helix formula
178  double o = 1./theRho;
179  return PositionTypeDouble(theX0+(-theSinPhi0*(1.-theCachedCDPhi)+theCosPhi0*theCachedSDPhi)*o,
180  theY0+( theCosPhi0*(1.-theCachedCDPhi)+theSinPhi0*theCachedSDPhi)*o,
181  theZ0+theCachedS*theCosTheta);
182  }
183 // else if ( fabs(theCachedDPhi)>theNumericalPrecision ) {
184 // // full helix formula, but avoiding (1-cos(deltaPhi)) for small angles
185 // return PositionTypeDouble(theX0+(-theSinPhi0*theCachedSDPhi*theCachedSDPhi/(1.+theCachedCDPhi)+
186 // theCosPhi0*theCachedSDPhi)/theRho,
187 // theY0+(theCosPhi0*theCachedSDPhi*theCachedSDPhi/(1.+theCachedCDPhi)+
188 // theSinPhi0*theCachedSDPhi)/theRho,
189 // theZ0+theCachedS*theCosTheta);
190 // }
191  else {
192  // Use 2nd order.
193  return theQuadraticCrossingFromStart.positionInDouble(theCachedS);
194  }
195 }
196 //
197 // Direction vector on helix after a step of path length s.
198 //
200 HelixArbitraryPlaneCrossing::direction (double s) const {
201  // use result in double precision
202  DirectionTypeDouble dir = directionInDouble(s);
203  return DirectionType(dir.x(),dir.y(),dir.z());
204 }
205 //
206 // Direction vector on helix after a step of path length s in double precision.
207 //
208 HelixArbitraryPlaneCrossing::DirectionTypeDouble
209 HelixArbitraryPlaneCrossing::directionInDouble (double s) const {
210  //
211  // Calculate delta phi (if not already available)
212  //
213  if unlikely( s!=theCachedS ) { // very very unlikely!
214  theCachedS = s;
215  theCachedDPhi = theCachedS*theRho*theSinTheta;
216  vdt::fast_sincos(theCachedDPhi,theCachedSDPhi,theCachedCDPhi);
217  }
218 
219  if ( std::abs(theCachedDPhi)>1.e-4 ) {
220  // full helix formula
221  return DirectionTypeDouble(theCosPhi0*theCachedCDPhi-theSinPhi0*theCachedSDPhi,
222  theSinPhi0*theCachedCDPhi+theCosPhi0*theCachedSDPhi,
223  theCosTheta/theSinTheta);
224  }
225  else {
226  // 2nd order
227  return theQuadraticCrossingFromStart.directionInDouble(theCachedS);
228  }
229 }
230 // Iteration control: continue if distance to plane > theMaxDistToPlane. Includes
231 // protection for numerical precision (Surfaces work with single precision).
232 bool HelixArbitraryPlaneCrossing::notAtSurface (const Plane& plane,
233  const PositionTypeDouble& point,
234  const float maxDist) const {
235  float dz = plane.localZ(Surface::GlobalPoint(point.x(),point.y(),point.z()));
236  return std::abs(dz)>maxDist;
237 }
238 
239 const float HelixArbitraryPlaneCrossing::theNumericalPrecision = 5.e-7f;
240 const float HelixArbitraryPlaneCrossing::theMaxDistToPlane = 1.e-4f;
#define LogDebug(id)
int i
Definition: DBlmapReader.cc:9
float localZ(const GlobalPoint &gp) const
Definition: Plane.h:49
PropagationDirection
Definition: Plane.h:17
float float float z
static int position[TOTALCHAMBERS][3]
Definition: ReadPGInfo.cc:509
Point3DBase< Scalar, GlobalTag > PositionType
Definition: Definitions.h:30
U second(std::pair< T, U > const &p)
#define unlikely(x)
Definition: Likely.h:21
T mag() const
Definition: PV3DBase.h:67
T curvature(T InversePt, const edm::EventSetup &iSetup)
tuple iteration
Definition: align_cfg.py:5
T sqrt(T t)
Definition: SSEVec.h:48
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
static const MaxIter maxiter
double p2[4]
Definition: TauolaWrapper.h:90
return(e1-e2)*(e1-e2)+dp *dp
if(dp >Float(M_PI)) dp-
void operator()(int) const
tuple cout
Definition: gather_cfg.py:121
dbl *** dir
Definition: mlp_gen.cc:35
volatile std::atomic< bool > shutdown_flag false
Definition: DDAxes.h:10
const PositionType & position() const
#define constexpr
*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