lester_mt2_bisect.h
Go to the documentation of this file.
60 double desiredPrecisionOnMt2 = 0; // Must be >=0. If 0 alg aims for machine precision. if >0, MT2 computed to supplied absolute precision. 92 A new approach to characterizing the relative position of two ellipses depending on one parameter 95 Received 15 September 2004; received in revised form 2 November 2005; accepted 10 January 2006 Available online 28 February 2006 104 * Though the paper above talks only about ellipses, from playing with some test cases, I (CGL) have conjectured that the algorithm actually works well even if the conics are parabolas provided that the axx>0&&ayy>0 test is reduced to axx>=0&&ayy>=0&&axx*ayy!=0 ... which is true is good news for the similicity of the MT2 calculator ... as the MT2 calculator will not need to distinguish these two possibilities. In a private communication between me (CGL) and the authors of Computer Aided Geometric Design 23 (2006) 324–350, the authors have indicated that it is not unreasonable to believe that the code does indeed work on the parabolica cases too. This algorithm relies on that generalisation, which may be the subject of a paper (to appear) from Etayo and Gonzalez-Vega. 107 * Definition: an ellipse is defined with respect to cartesian co-ordinates (x,y) by an equation of the form; 111 * where xVec is a columnar three vec containing (x,y,1) and where A is a symmetric matrix having elements: 121 * Note that this parametrisation has one parameter too many ... the "A"-matrix can be multiplied by a non-zero constant, and the ellipse is not changed. 123 * The implementation herein doesn't quite enforce that. The implementation herein allows axx or ayy to be non-negative .... and it is left to the user to ensure that axx and ayy are not exactly zero. 124 * Note also that (1) is general enough to contain all conic sections, so it is left to the user to ensure that only values of A consistent 125 * with (non-singluar) ellipses are fed into the program below. For our purposes, an ellipse is "singular" iff coeffLamPow3 (see below) is zero. 176 const double ans = e1.c_xx*e1.c_yy*e2.c + 2.0*e1.c_xy*e1.c_y*e2.c_x - 2.0*e1.c_x*e1.c_yy*e2.c_x + e1.c*e1.c_yy*e2.c_xx - 2.0*e1.c*e1.c_xy*e2.c_xy + 2.0*e1.c_x*e1.c_y*e2.c_xy + 2.0*e1.c_x*e1.c_xy*e2.c_y - 2.0*e1.c_xx*e1.c_y*e2.c_y + e1.c*e1.c_xx*e2.c_yy - e2.c_yy*(e1.c_x*e1.c_x) - e2.c*(e1.c_xy*e1.c_xy) - e2.c_xx*(e1.c_y*e1.c_y); 203 bool __private_ellipsesAreDisjoint(const double coeffLamPow3, const double coeffLamPow2, const double coeffLamPow1, const double coeffLamPow0); 206 /* We want to construct the polynomial "Det(lamdba A + B)" where A and B are the 3x3 matrices associated with e1 and e2, and we want to get that 210 Note that by default we will not have unity as the coefficient of the lambda^3 term, however the redundancy in the parametrisation of A and B allows us to scale the whole ply until the first term does have a unit coefficient. 218 const double coeffLamPow3 = e1.det; // Note that this is the determinant of the symmetric matrix associated with e1. 221 const double coeffLamPow0 = e2.det; // Note that this is the determinant of the symmetric matrix associated with e2. 223 // Since question is "symmetric" and since we need to dovide by coeffLamPow3 ... do this the way round that involves dividing by the largest number: 226 return __private_ellipsesAreDisjoint(coeffLamPow3, coeffLamPow2, coeffLamPow1, coeffLamPow0); // normal order 228 return __private_ellipsesAreDisjoint(coeffLamPow0, coeffLamPow1, coeffLamPow2, coeffLamPow3); // reversed order 231 bool __private_ellipsesAreDisjoint(const double coeffLamPow3, const double coeffLamPow2, const double coeffLamPow1, const double coeffLamPow0) { 252 << (thing1>0) << " && " << (thing2>0) << " && [[ " << (a>=0) << " " << (3.0*a*c + b*a*a - 4.0*b*b<0) << " ] or " 253 << "[ " << (a< 0) << " ] =("<< ((a >= 0 /*&& thing1 > 0*/ && 3.0*a*c + b*a*a - 4.0*b*b< 0 /*&& thing2 > 0*/) || 269 const bool ans = ( (a >= 0 /*&& thing1 > 0*/ && 3.0*a*c + b*a*a - 4.0*b*b< 0 /*&& thing2 > 0*/) || 300 static double get_mT2( // returns asymmetric mT2 (which is >=0), or returns a negative number (such as MT2_ERROR) in the case of an error. 305 const double desiredPrecisionOnMT2=0, // This must be non-negative. If set to zero (default) MT2 will be calculated to the highest precision available on the machine (or as close to that as the algorithm permits). If set to a positive value, MT2 (note that is MT2, not its square) will be calculated to within +- desiredPrecisionOnMT2. Note that by requesting precision of +- 0.01 GeV on an MT2 value of 100 GeV can result in speedups of a factor of ... 306 const bool useDeciSectionsInitially=true // If true, interval is cut at the 10% point until first acceptance, which gives factor 3 increase in speed calculating kinematic min, but 3% slowdown for events in the bulk. Is on (true) by default, but can be turned off by setting to false. 350 static double get_mT2_Sq( // returns square of asymmetric mT2 (which is >=0), or returns a negative number (such as MT2_ERROR) in the case of an error. 355 const double desiredPrecisionOnMT2=0, // This must be non-negative. If set to zero (default) MT2 will be calculated to the highest precision available on the machine (or as close to that as the algorithm permits). If set to a positive value, MT2 (note that is MT2, not its square) will be calculated to within +- desiredPrecisionOnMT2. Note that by requesting precision of +- 0.01 GeV on an MT2 value of 100 GeV can resJult in speedups of a factor of .. 356 const bool useDeciSectionsInitially=true // If true, interval is cut at the 10% point until first acceptance, which gives factor 3 increase in speed calculating kinematic min, but 3% slowdown for events in the bulk. Is on (true) by default, but can be turned off by setting to false. 360 disableCopyrightMessage(true); // By supplying an argument to disable, we actually ask for the message to be printed, if printing is not already disabled. This counterintuitive function naming is to avoid the need to introduce static variable initialisations .... 362 const double m1Min = mVis1+mInvis1; // when parent has this mass, ellipse 1 has smallest physical size 363 const double m2Min = mVis2+mInvis2; // when parent has this mass, ellipse 2 has smallest physical size 379 const double mMin = m2Min; // when parent has this mass, both ellipses are physical, and at least one has zero size. Note that the name "min" expresses that it is the minimum potential parent mass we should consider, not that it is the min of m1Min and m2Min. It is in fact the MAX of them! 381 // TODO: What about rounding? What about idiots who give us mVis values that have been computed from E^2-p^2 terms that are perilously close to zero, or perilously degenerate? 404 // Check for an easy MT2 zero, not because we think it will speed up many cases, but because it will allow us to, ever after, assume that scaleSq>0. 412 double mUpper = mMin + scale; // since scaleSq is guaranteed to be >0 at this stage, the adition of scaleSq quarantees that mUpperSq is also >0, so it can be exponentially grown (later) by doubling. 419 const Lester::EllipseParams & side1=helper(mUpperSq, msSq, -sx, -sy, mpSq, 0, 0 ); // see side1Coeffs in mathematica notebook 420 const Lester::EllipseParams & side2=helper(mUpperSq, mtSq, +tx, +ty, mqSq, pxMiss, pyMiss); // see side2Coeffs in mathematica notebook 459 std::cout << " MACHINE_PREC " << std::setprecision(10) << mLower << " " << trialM << " " << mUpper << " " << mUpper-mLower << " " << desiredPrecisionOnMT2 << std::endl; 464 const Lester::EllipseParams & side1 = helper(trialMSq, msSq, -sx, -sy, mpSq, 0, 0 ); // see side1Coeffs in mathematica notebook 465 const Lester::EllipseParams & side2 = helper(trialMSq, mtSq, +tx, +ty, mqSq, pxMiss, pyMiss); // see side2Coeffs in mathematica notebook 482 // The test for ellipses being disjoint failed ... this means the ellipses became degenerate, which can only happen right at the bottom of the MT2 search range (subject to numerical precision). So: 501 static const Lester::EllipseParams helper(const double mSq, // The test parent-mass value (squared) 502 const double mtSq, const double tx, const double ty, // The visible particle transverse momentum 521 const double c_y = -4.0* mtSq*pymiss - 4.0* pymiss*txSq - 2.0* mqSq*ty + 2.0* mSq*ty - 2.0* mtSq*ty + 549 std::pair <double,double> ben_findsols(double MT2, double px, double py, double visM, double Ma, double pxb, double pyb, double metx, double mety, double visMb, double Mb){ 574 double TermSqy0 = E4*E2-2.*E4*M2-2.*E4*Ma2-2.*E4*px2-2.*E4*py2+E2*M4-2.*E2*M2*Ma2+2.*E2*M2*px2+2.*E2*M2*py2+E2*Ma4+2.*E2*Ma2*px2-2.*E2*Ma2*py2+E2*px4+2.*E2*px2*py2+E2*py4; 596 double metpx = -(TermB*metpy+TermA-sqrt(TermSqy0+TermSqy1*metpy+TermSqy2*metpy*metpy))*0.5/(E2-px2); 597 double metpx2 = -(TermB*metpy+TermA+sqrt(TermSqy0+TermSqy1*metpy+TermSqy2*metpy*metpy))*0.5/(E2-px2); EllipseParams(const double c_xx2, const double c_yy2, const double c_xy2, const double c_x2, const double c_y2, const double c2) Definition: lester_mt2_bisect.h:138 bool operator==(const EllipseParams &other) const Definition: lester_mt2_bisect.h:179 static double get_mT2(const double mVis1, const double pxVis1, const double pyVis1, const double mVis2, const double pxVis2, const double pyVis2, const double pxMiss, const double pyMiss, const double mInvis1, const double mInvis2, const double desiredPrecisionOnMT2=0, const bool useDeciSectionsInitially=true) Definition: lester_mt2_bisect.h:300 Definition: lester_mt2_bisect.h:295 Definition: lester_mt2_bisect.h:130 bool __private_ellipsesAreDisjoint(const double coeffLamPow3, const double coeffLamPow2, const double coeffLamPow1, const double coeffLamPow0) Definition: lester_mt2_bisect.h:231 double MT(double px1, double px2, double py1, double py2, double m1, double m2) Definition: lester_mt2_bisect.h:541 Definition: lester_mt2_bisect.h:128 static double lestermax(const double x, const double y) Definition: lester_mt2_bisect.h:498 static const Lester::EllipseParams helper(const double mSq, const double mtSq, const double tx, const double ty, const double mqSq, const double pxmiss, const double pymiss) Definition: lester_mt2_bisect.h:501 EllipseParams(const double x0, const double y0) Definition: lester_mt2_bisect.h:163 static double get_mT2_Sq(const double mVis1, const double pxVis1, const double pyVis1, const double mVis2, const double pxVis2, const double pyVis2, const double pxMiss, const double pyMiss, const double mInvis1, const double mInvis2, const double desiredPrecisionOnMT2=0, const bool useDeciSectionsInitially=true) Definition: lester_mt2_bisect.h:350 bool ellipsesAreDisjoint(const EllipseParams &e1, const EllipseParams &e2) Definition: lester_mt2_bisect.h:205 std::pair< double, double > ben_findsols(double MT2, double px, double py, double visM, double Ma, double pxb, double pyb, double metx, double mety, double visMb, double Mb) Definition: lester_mt2_bisect.h:549 double E(const double x, const double y) Definition: flav_loop_functions.hpp:280 static void disableCopyrightMessage(const bool printIfFirst=false) Definition: lester_mt2_bisect.h:322 double lesterFactor(const EllipseParams &e2) const Definition: lester_mt2_bisect.h:174 |