gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
mt2w_bisect.cpp
Go to the documentation of this file.
1 /***********************************************************************/
2 /* */
3 /* Finding MT2W */
4 /* Reference: arXiv:1203.4813 [hep-ph] */
5 /* Authors: Yang Bai, Hsin-Chia Cheng, */
6 /* Jason Gallicchio, Jiayin Gu */
7 /* Based on MT2 by: Hsin-Chia Cheng, Zhenyu Han */
8 /* May 8, 2012, v1.00a */
9 /* */
10 /***********************************************************************/
11 
12 /*******************************************************************************
13  Usage:
14 
15  1. Define an object of type "mt2w":
16 
17  mt2w_bisect::mt2w mt2w_event;
18 
19  2. Set momenta:
20 
21  mt2w_event.set_momenta(pl,pb1,pb2,pmiss);
22 
23  where array pl[0..3], pb1[0..3], pb2[0..3] contains (E,px,py,pz), pmiss[0..2] contains (0,px,py)
24  for the visible particles and the missing momentum. pmiss[0] is not used.
25  All quantities are given in double.
26 
27  (Or use non-pointer method to do the same.)
28 
29  3. Use mt2w::get_mt2w() to obtain the value of mt2w:
30 
31  double mt2w_value = mt2w_event.get_mt2w();
32 
33 *******************************************************************************/
34 
35 #include <iostream>
36 #include <math.h>
38 
39 using namespace std;
40 
41 namespace mt2w_bisect
42 {
43 
44 mt2w::mt2w(double upper_bound, double error_value, double scan_step)
45 {
46  solved = false;
47  momenta_set = false;
48  mt2w_b = 0.; // The result field. Start it off at zero.
49  this->upper_bound = upper_bound; // the upper bound of search for MT2W, default value is 500 GeV
50  this->error_value = error_value; // if we couldn't find any compatible region below the upper_bound, output mt2w = error_value;
51  this->scan_step = scan_step; // if we need to scan to find the compatible region, this is the step of the scan
52 }
53 
54 double mt2w::get_mt2w()
55 {
56  if (!momenta_set)
57  {
58  cout <<" Please set momenta first!" << endl;
59  return error_value;
60  }
61 
62  if (!solved) mt2w_bisect();
63  return mt2w_b;
64 }
65 
66 
67 void mt2w::set_momenta(double *pl, double *pb1, double *pb2, double* pmiss)
68 {
69  // Pass in pointers to 4-vectors {E, px, py, px} of doubles.
70  // and pmiss must have [1] and [2] components for x and y. The [0] component is ignored.
71  set_momenta(pl[0], pl[1], pl[2], pl[3],
72  pb1[0], pb1[1], pb1[2], pb1[3],
73  pb2[0], pb2[1], pb2[2], pb2[3],
74  pmiss[1], pmiss[2]);
75 }
76 
77 
78 
79 void mt2w::set_momenta(double El, double plx, double ply, double plz,
80  double Eb1, double pb1x, double pb1y, double pb1z,
81  double Eb2, double pb2x, double pb2y, double pb2z,
82  double pmissx, double pmissy)
83 {
84  solved = false; //reset solved tag when momenta are changed.
85  momenta_set = true;
86 
87  double msqtemp; //used for saving the mass squared temporarily
88 
89 //l is the visible lepton
90 
91  this->El = El;
92  this->plx = plx;
93  this->ply = ply;
94  this->plz = plz;
95 
96  Elsq = El*El;
97 
98  msqtemp = El*El-plx*plx-ply*ply-plz*plz;
99  if (msqtemp > 0.0) {mlsq = msqtemp;}
100  else {mlsq = 0.0;} //mass squared can not be negative
101  ml = sqrt(mlsq); // all the input masses are calculated from sqrt(p^2)
102 
103 //b1 is the bottom on the same side as the visible lepton
104 
105  this->Eb1 = Eb1;
106  this->pb1x = pb1x;
107  this->pb1y = pb1y;
108  this->pb1z = pb1z;
109 
110  Eb1sq = Eb1*Eb1;
111 
112  msqtemp = Eb1*Eb1-pb1x*pb1x-pb1y*pb1y-pb1z*pb1z;
113  if (msqtemp > 0.0) {mb1sq = msqtemp;}
114  else {mb1sq = 0.0;} //mass squared can not be negative
115  mb1 = sqrt(mb1sq); // all the input masses are calculated from sqrt(p^2)
116 
117 //b2 is the other bottom (paired with the invisible W)
118 
119  this->Eb2 = Eb2;
120  this->pb2x = pb2x;
121  this->pb2y = pb2y;
122  this->pb2z = pb2z;
123 
124  Eb2sq = Eb2*Eb2;
125 
126  msqtemp = Eb2*Eb2-pb2x*pb2x-pb2y*pb2y-pb2z*pb2z;
127  if (msqtemp > 0.0) {mb2sq = msqtemp;}
128  else {mb2sq = 0.0;} //mass squared can not be negative
129  mb2 = sqrt(mb2sq); // all the input masses are calculated from sqrt(p^2)
130 
131 
132 //missing pt
133 
134 
135  this->pmissx = pmissx;
136  this->pmissy = pmissy;
137 
138 //set the values of masses
139 
140  mv = 0.0; //mass of neutrino
141  mw = 80.4; //mass of W-boson
142 
143 
144 //precision?
145 
147  else precision = 100.*RELATIVE_PRECISION;
148 }
149 
150 
151 void mt2w::mt2w_bisect()
152 {
153 
154 
155  solved = true;
156  cout.precision(11);
157 
158  // In normal running, mtop_high WILL be compatible, and mtop_low will NOT.
159  double mtop_high = upper_bound; //set the upper bound of the search region
160  double mtop_low; //the lower bound of the search region is best chosen as m_W + m_b
161 
162  if (mb1 >= mb2) {mtop_low = mw + mb1;}
163  else {mtop_low = mw + mb2;}
164 
165  // The following if and while deal with the case where there might be a compatable region
166  // between mtop_low and 500 GeV, but it doesn't extend all the way up to 500.
167  //
168 
169  // If our starting high guess is not compatible, start the high guess from the low guess...
170  if (teco(mtop_high)==0) {mtop_high = mtop_low;}
171 
172  // .. and scan up until a compatible high bound is found.
173  //We can also raise the lower bound since we scaned over a region that is not compatible
174  while (teco(mtop_high)==0 && mtop_high < upper_bound + 2.*scan_step) {
175 
176  mtop_low=mtop_high;
177  mtop_high = mtop_high + scan_step;
178  }
179 
180  // if we can not find a compatible region under the upper bound, output the error value
181  if (mtop_high > upper_bound) {
182  mt2w_b = error_value;
183  return;
184  }
185 
186  // Once we have an compatible mtop_high, we can find mt2w using bisection method
187  while(mtop_high - mtop_low > precision)
188  {
189  double mtop_mid,teco_mid;
190  //bisect
191  mtop_mid = (mtop_high+mtop_low)/2.;
192  teco_mid = teco(mtop_mid);
193 
194  if(teco_mid == 0) {mtop_low = mtop_mid;}
195  else {mtop_high = mtop_mid;}
196 
197  }
198  mt2w_b = mtop_high; //output the value of mt2w
199  return;
200 }
201 
202 
203 // for a given event, teco ( mtop ) gives 1 if trial top mass mtop is compatible, 0 if mtop is not.
204 
205 int mt2w::teco( double mtop)
206 {
207 
208 //first test if mtop is larger than mb+mw
209 
210  if (mtop < mb1+mw || mtop < mb2+mw) {return 0;}
211 
212 //define delta for convenience, note the definition is different from the one in mathematica code by 2*E^2_{b2}
213 
214  double ETb2sq = Eb2sq - pb2z*pb2z; //transverse energy of b2
215  double delta = (mtop*mtop-mw*mw-mb2sq)/(2.*ETb2sq);
216 
217 
218 //del1 and del2 are \Delta'_1 and \Delta'_2 in the notes eq. 10,11
219 
220  double del1 = mw*mw - mv*mv - mlsq;
221  double del2 = mtop*mtop - mw*mw - mb1sq - 2*(El*Eb1-plx*pb1x-ply*pb1y-plz*pb1z);
222 
223 // aa bb cc are A B C in the notes eq.15
224 
225  double aa = (El*pb1x-Eb1*plx)/(Eb1*plz-El*pb1z);
226  double bb = (El*pb1y-Eb1*ply)/(Eb1*plz-El*pb1z);
227  double cc = (El*del2-Eb1*del1)/(2.*Eb1*plz-2.*El*pb1z);
228 
229 
230 //calculate coefficients for the two quadratic equations (ellipses), which are
231 //
232 // a1 x^2 + 2 b1 x y + c1 y^2 + 2 d1 x + 2 e1 y + f1 = 0 , from the 2 steps decay chain (with visible lepton)
233 //
234 // a2 x^2 + 2 b2 x y + c2 y^2 + 2 d2 x + 2 e2 y + f2 <= 0 , from the 1 stop decay chain (with W missing)
235 //
236 // where x and y are px and py of the neutrino on the visible lepton chain
237 
238  a1 = Eb1sq*(1.+aa*aa)-(pb1x+pb1z*aa)*(pb1x+pb1z*aa);
239  b1 = Eb1sq*aa*bb - (pb1x+pb1z*aa)*(pb1y+pb1z*bb);
240  c1 = Eb1sq*(1.+bb*bb)-(pb1y+pb1z*bb)*(pb1y+pb1z*bb);
241  d1 = Eb1sq*aa*cc - (pb1x+pb1z*aa)*(pb1z*cc+del2/2.0);
242  e1 = Eb1sq*bb*cc - (pb1y+pb1z*bb)*(pb1z*cc+del2/2.0);
243  f1 = Eb1sq*(mv*mv+cc*cc) - (pb1z*cc+del2/2.0)*(pb1z*cc+del2/2.0);
244 
245 // First check if ellipse 1 is real (don't need to do this for ellipse 2, ellipse 2 is always real for mtop > mw+mb)
246 
247  double det1 = (a1*(c1*f1 - e1*e1) - b1*(b1*f1 - d1*e1) + d1*(b1*e1-c1*d1))/(a1+c1);
248 
249  if (det1 > 0.0) {return 0;}
250 
251 //coefficients of the ellptical region
252 
253  a2 = 1-pb2x*pb2x/(ETb2sq);
254  b2 = -pb2x*pb2y/(ETb2sq);
255  c2 = 1-pb2y*pb2y/(ETb2sq);
256 
257  // d2o e2o f2o are coefficients in the p2x p2y plane (p2 is the momentum of the missing W-boson)
258  // it is convenient to calculate them first and transfer the ellipse to the p1x p1y plane
259  d2o = -delta*pb2x;
260  e2o = -delta*pb2y;
261  f2o = mw*mw - delta*delta*ETb2sq;
262 
263  d2 = -d2o -a2*pmissx -b2*pmissy;
264  e2 = -e2o -c2*pmissy -b2*pmissx;
265  f2 = a2*pmissx*pmissx + 2*b2*pmissx*pmissy + c2*pmissy*pmissy + 2*d2o*pmissx + 2*e2o*pmissy + f2o;
266 
267 //find a point in ellipse 1 and see if it's within the ellipse 2, define h0 for convenience
268  double x0, h0, y0, r0;
269  x0 = (c1*d1-b1*e1)/(b1*b1-a1*c1);
270  h0 = (b1*x0 + e1)*(b1*x0 + e1) - c1*(a1*x0*x0 + 2*d1*x0 + f1);
271  if (h0 < 0.0) {return 0;} // if h0 < 0, y0 is not real and ellipse 1 is not real, this is a redundant check.
272  y0 = (-b1*x0 -e1 + sqrt(h0))/c1;
273  r0 = a2*x0*x0 + 2*b2*x0*y0 + c2*y0*y0 + 2*d2*x0 + 2*e2*y0 + f2;
274  if (r0 < 0.0) {return 1;} // if the point is within the 2nd ellipse, mtop is compatible
275 
276 
277 //obtain the coefficients for the 4th order equation
278 //devided by Eb1^n to make the variable dimensionless
279  long double A4, A3, A2, A1, A0;
280 
281  A4 =
282  -4*a2*b1*b2*c1 + 4*a1*b2*b2*c1 +a2*a2*c1*c1 +
283  4*a2*b1*b1*c2 - 4*a1*b1*b2*c2 - 2*a1*a2*c1*c2 +
284  a1*a1*c2*c2;
285 
286  A3 =
287  (-4*a2*b2*c1*d1 + 8*a2*b1*c2*d1 - 4*a1*b2*c2*d1 - 4*a2*b1*c1*d2 +
288  8*a1*b2*c1*d2 - 4*a1*b1*c2*d2 - 8*a2*b1*b2*e1 + 8*a1*b2*b2*e1 +
289  4*a2*a2*c1*e1 - 4*a1*a2*c2*e1 + 8*a2*b1*b1*e2 - 8*a1*b1*b2*e2 -
290  4*a1*a2*c1*e2 + 4*a1*a1*c2*e2)/Eb1;
291 
292 
293  A2 =
294  (4*a2*c2*d1*d1 - 4*a2*c1*d1*d2 - 4*a1*c2*d1*d2 + 4*a1*c1*d2*d2 -
295  8*a2*b2*d1*e1 - 8*a2*b1*d2*e1 + 16*a1*b2*d2*e1 +
296  4*a2*a2*e1*e1 + 16*a2*b1*d1*e2 - 8*a1*b2*d1*e2 -
297  8*a1*b1*d2*e2 - 8*a1*a2*e1*e2 + 4*a1*a1*e2*e2 - 4*a2*b1*b2*f1 +
298  4*a1*b2*b2*f1 + 2*a2*a2*c1*f1 - 2*a1*a2*c2*f1 +
299  4*a2*b1*b1*f2 - 4*a1*b1*b2*f2 - 2*a1*a2*c1*f2 + 2*a1*a1*c2*f2)/Eb1sq;
300 
301  A1 =
302  (-8*a2*d1*d2*e1 + 8*a1*d2*d2*e1 + 8*a2*d1*d1*e2 - 8*a1*d1*d2*e2 -
303  4*a2*b2*d1*f1 - 4*a2*b1*d2*f1 + 8*a1*b2*d2*f1 + 4*a2*a2*e1*f1 -
304  4*a1*a2*e2*f1 + 8*a2*b1*d1*f2 - 4*a1*b2*d1*f2 - 4*a1*b1*d2*f2 -
305  4*a1*a2*e1*f2 + 4*a1*a1*e2*f2)/(Eb1sq*Eb1);
306 
307  A0 =
308  (-4*a2*d1*d2*f1 + 4*a1*d2*d2*f1 + a2*a2*f1*f1 +
309  4*a2*d1*d1*f2 - 4*a1*d1*d2*f2 - 2*a1*a2*f1*f2 +
310  a1*a1*f2*f2)/(Eb1sq*Eb1sq);
311 
312  long double B3, B2, B1, B0;
313  B3 = 4*A4;
314  B2 = 3*A3;
315  B1 = 2*A2;
316  B0 = A1;
317 
318  long double C2, C1, C0;
319  C2 = -(A2/2 - 3*A3*A3/(16*A4));
320  C1 = -(3*A1/4. -A2*A3/(8*A4));
321  C0 = -A0 + A1*A3/(16*A4);
322 
323  long double D1, D0;
324  D1 = -B1 - (B3*C1*C1/C2 - B3*C0 -B2*C1)/C2;
325  D0 = -B0 - B3 *C0 *C1/(C2*C2)+ B2*C0/C2;
326 
327  long double E0;
328  E0 = -C0 - C2*D0*D0/(D1*D1) + C1*D0/D1;
329 
330  long double t1,t2,t3,t4,t5;
331 //find the coefficients for the leading term in the Sturm sequence
332  t1 = A4;
333  t2 = A4;
334  t3 = C2;
335  t4 = D1;
336  t5 = E0;
337 
338 
339 //The number of solutions depends on diffence of number of sign changes for x->Inf and x->-Inf
340  int nsol;
341  nsol = signchange_n(t1,t2,t3,t4,t5) - signchange_p(t1,t2,t3,t4,t5);
342 
343 //Cannot have negative number of solutions, must be roundoff effect
344  if (nsol < 0) nsol = 0;
345 
346  int out;
347  if (nsol == 0) {out = 0;} //output 0 if there is no solution, 1 if there is solution
348  else {out = 1;}
349 
350  return out;
351 
352 }
353 
354 inline int mt2w::signchange_n( long double t1, long double t2, long double t3, long double t4, long double t5)
355 {
356  int nsc;
357  nsc=0;
358  if(t1*t2>0) nsc++;
359  if(t2*t3>0) nsc++;
360  if(t3*t4>0) nsc++;
361  if(t4*t5>0) nsc++;
362  return nsc;
363 }
364 inline int mt2w::signchange_p( long double t1, long double t2, long double t3, long double t4, long double t5)
365 {
366  int nsc;
367  nsc=0;
368  if(t1*t2<0) nsc++;
369  if(t2*t3<0) nsc++;
370  if(t3*t4<0) nsc++;
371  if(t4*t5<0) nsc++;
372  return nsc;
373 }
374 
375 }//end namespace mt2w_bisect
Spectrum Spectrum Spectrum mw
Funk delta(std::string arg, double pos, double width)
Definition: daFunk.hpp:902
STL namespace.
double D0(const double a, const double b, const double c, const double d)
double C0(const double a, const double b, const double c)
#define RELATIVE_PRECISION
Definition: mt2_bisect.h:7
double B0(const double a, const double b, const double Q)
#define ABSOLUTE_PRECISION
Definition: mt2_bisect.h:8
double B1(const double a, const double b, const double Q)