CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/TrackingTools/GeomPropagators/src/HelixArbitraryPlaneCrossing.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
00002 #include "DataFormats/GeometrySurface/interface/Plane.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 
00005 #include <cmath>
00006 #include <iostream>
00007 
00008 HelixArbitraryPlaneCrossing::HelixArbitraryPlaneCrossing(const PositionType& point,
00009                                                          const DirectionType& direction,
00010                                                          const float curvature,
00011                                                          const PropagationDirection propDir) :
00012   theQuadraticCrossingFromStart(point,direction,curvature,propDir),
00013   theX0(point.x()),
00014   theY0(point.y()),
00015   theZ0(point.z()),
00016   theRho(curvature),
00017   thePropDir(propDir),
00018   theCachedS(0),
00019   theCachedDPhi(0.),
00020   theCachedSDPhi(0.),
00021   theCachedCDPhi(1.)
00022 {
00023   //
00024   // Components of direction vector (with correct normalisation)
00025   //
00026   double px = direction.x();
00027   double py = direction.y();
00028   double pz = direction.z();
00029   double pt2 = px*px+py*py;
00030   double p2 = pt2+pz*pz;
00031   double pI = 1./sqrt(p2);
00032   double ptI = 1./sqrt(pt2);
00033   theCosPhi0 = px*ptI;
00034   theSinPhi0 = py*ptI;
00035   theCosTheta = pz*pI;
00036   theSinTheta = pt2*ptI*pI;
00037 }
00038 //
00039 // Propagation status and path length to intersection
00040 //
00041 std::pair<bool,double>
00042 HelixArbitraryPlaneCrossing::pathLength(const Plane& plane) {
00043   //
00044   // Constants used for control of convergence
00045   //
00046   const int maxIterations(100);
00047   //
00048   // maximum distance to plane (taking into account numerical precision)
00049   //
00050   float maxNumDz = theNumericalPrecision*plane.position().mag();
00051   float safeMaxDist = (theMaxDistToPlane>maxNumDz?theMaxDistToPlane:maxNumDz);
00052   //
00053   // Prepare internal value of the propagation direction and position / direction vectors for iteration 
00054   //
00055   PropagationDirection propDir = thePropDir;
00056   PositionTypeDouble xnew(theX0,theY0,theZ0);
00057   DirectionTypeDouble pnew(theCosPhi0,theSinPhi0,theCosTheta/theSinTheta);
00058   //
00059   // Prepare iterations: count and total pathlength
00060   //
00061   int iteration(maxIterations);
00062   double dSTotal(0.);
00063   //
00064   bool first = true;
00065   while ( notAtSurface(plane,xnew,safeMaxDist) ) {
00066     //
00067     // return empty solution vector if no convergence after maxIterations iterations
00068     //
00069     if ( --iteration<0 ) {
00070       edm::LogInfo("HelixArbitraryPlaneCrossing") << "pathLength : no convergence";
00071       return std::pair<bool,double>(false,0);
00072     }
00073 
00074     //
00075     // Use existing 2nd order object at first pass, create temporary object
00076     // for subsequent passes.
00077     //
00078     std::pair<bool,double> deltaS2;
00079     if ( first ) {
00080       first = false;
00081       deltaS2 = theQuadraticCrossingFromStart.pathLength(plane);
00082     }
00083     else {
00084       HelixArbitraryPlaneCrossing2Order quadraticCrossing(xnew.x(),xnew.y(),xnew.z(),
00085                                                           pnew.x(),pnew.y(),
00086                                                           theCosTheta,theSinTheta,
00087                                                           theRho,
00088                                                           anyDirection);
00089       
00090       deltaS2 = quadraticCrossing.pathLength(plane);
00091     }
00092      
00093     if ( !deltaS2.first )  return deltaS2;
00094     //
00095     // Calculate and sort total pathlength (max. 2 solutions)
00096     //
00097     dSTotal += deltaS2.second;
00098     PropagationDirection newDir = dSTotal>=0 ? alongMomentum : oppositeToMomentum;
00099     if ( propDir == anyDirection ) {
00100       propDir = newDir;
00101     }
00102     else {
00103       if ( newDir!=propDir )  return std::pair<bool,double>(false,0);
00104     }
00105     //
00106     // Step forward by dSTotal.
00107     //
00108     xnew = positionInDouble(dSTotal);
00109     pnew = directionInDouble(dSTotal);
00110   }
00111   //
00112   // Return result
00113   //
00114   return std::pair<bool,double>(true,dSTotal);
00115 }
00116 //
00117 // Position on helix after a step of path length s.
00118 //
00119 HelixPlaneCrossing::PositionType
00120 HelixArbitraryPlaneCrossing::position (double s) const {
00121   // use result in double precision
00122   PositionTypeDouble pos = positionInDouble(s);
00123   return PositionType(pos.x(),pos.y(),pos.z());
00124 }
00125 //
00126 // Position on helix after a step of path length s in double precision.
00127 //
00128 HelixArbitraryPlaneCrossing::PositionTypeDouble
00129 HelixArbitraryPlaneCrossing::positionInDouble (double s) const {
00130   //
00131   // Calculate delta phi (if not already available)
00132   //
00133   if ( s!=theCachedS ) {
00134     theCachedS = s;
00135     theCachedDPhi = theCachedS*theRho*theSinTheta;
00136     theCachedSDPhi = sin(theCachedDPhi);
00137     theCachedCDPhi = cos(theCachedDPhi);
00138   }
00139   //
00140   // Calculate with appropriate formulation of full helix formula or with 
00141   //   2nd order approximation.
00142   //
00143 //    if ( fabs(theCachedDPhi)>1.e-1 ) {
00144   if ( std::abs(theCachedDPhi)>1.e-4 ) {
00145     // "standard" helix formula
00146     double o = 1./theRho;
00147     return PositionTypeDouble(theX0+(-theSinPhi0*(1.-theCachedCDPhi)+theCosPhi0*theCachedSDPhi)*o,
00148                               theY0+( theCosPhi0*(1.-theCachedCDPhi)+theSinPhi0*theCachedSDPhi)*o,
00149                               theZ0+theCachedS*theCosTheta);
00150     }
00151 //    else if ( fabs(theCachedDPhi)>theNumericalPrecision ) {
00152 //      // full helix formula, but avoiding (1-cos(deltaPhi)) for small angles
00153 //      return PositionTypeDouble(theX0+(-theSinPhi0*theCachedSDPhi*theCachedSDPhi/(1.+theCachedCDPhi)+
00154 //                                   theCosPhi0*theCachedSDPhi)/theRho,
00155 //                            theY0+(theCosPhi0*theCachedSDPhi*theCachedSDPhi/(1.+theCachedCDPhi)+
00156 //                                   theSinPhi0*theCachedSDPhi)/theRho,
00157 //                            theZ0+theCachedS*theCosTheta);
00158 //    }
00159   else {
00160     // Use 2nd order.
00161     return theQuadraticCrossingFromStart.positionInDouble(theCachedS);
00162   }
00163 }
00164 //
00165 // Direction vector on helix after a step of path length s.
00166 //
00167 HelixPlaneCrossing::DirectionType
00168 HelixArbitraryPlaneCrossing::direction (double s) const {
00169   // use result in double precision
00170   DirectionTypeDouble dir = directionInDouble(s);
00171   return DirectionType(dir.x(),dir.y(),dir.z());
00172 }
00173 //
00174 // Direction vector on helix after a step of path length s in double precision.
00175 //
00176 HelixArbitraryPlaneCrossing::DirectionTypeDouble
00177 HelixArbitraryPlaneCrossing::directionInDouble (double s) const {
00178   //
00179   // Calculate delta phi (if not already available)
00180   //
00181   if ( s!=theCachedS ) {
00182     theCachedS = s;
00183     theCachedDPhi = theCachedS*theRho*theSinTheta;
00184     theCachedSDPhi = sin(theCachedDPhi);
00185     theCachedCDPhi = cos(theCachedDPhi);
00186   }
00187 
00188   if ( std::abs(theCachedDPhi)>1.e-4 ) {
00189     // full helix formula
00190     return DirectionTypeDouble(theCosPhi0*theCachedCDPhi-theSinPhi0*theCachedSDPhi,
00191                                theSinPhi0*theCachedCDPhi+theCosPhi0*theCachedSDPhi,
00192                                theCosTheta/theSinTheta);
00193   }
00194   else {
00195     // 2nd order
00196     return theQuadraticCrossingFromStart.directionInDouble(theCachedS);
00197   }
00198 }
00199 //   Iteration control: continue if distance to plane > theMaxDistToPlane. Includes 
00200 //   protection for numerical precision (Surfaces work with single precision).
00201 bool HelixArbitraryPlaneCrossing::notAtSurface (const Plane& plane,                                    
00202                                                 const PositionTypeDouble& point,
00203                                                 const float maxDist) const {
00204   float dz = plane.localZ(Surface::GlobalPoint(point.x(),point.y(),point.z()));
00205   return std::abs(dz)>maxDist;
00206 }
00207 
00208 const float HelixArbitraryPlaneCrossing::theNumericalPrecision = 5.e-7f;
00209 const float HelixArbitraryPlaneCrossing::theMaxDistToPlane = 1.e-4f;