]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PYTHIA8/pythia8170/src/SusyResonanceWidths.cxx
Update to pythi8.170
[u/mrichter/AliRoot.git] / PYTHIA8 / pythia8170 / src / SusyResonanceWidths.cxx
1 // SusyResonanceWidths.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2012 Torbjorn Sjostrand
3 // Authors: N. Desai, P. Skands
4 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
5 // Please respect the MCnet Guidelines, see GUIDELINES for details.
6
7 // Function definitions (not found in the header) for the 
8 // SUSY Resonance widths classes. 
9
10 #include "SusyResonanceWidths.h"
11 #include "SusyCouplings.h"
12 #include "PythiaComplex.h"
13
14 namespace Pythia8 {
15
16 //==========================================================================
17
18 // WidthFunctions Class 
19
20 // Contains functions to be integrated for calculating the 3-body
21 // decay widths
22
23 //--------------------------------------------------------------------------
24
25 void WidthFunction::init( ParticleData* particleDataPtrIn, 
26   CoupSUSY* coupSUSYPtrIn) {
27
28   particleDataPtr = particleDataPtrIn;
29   coupSUSYPtr = coupSUSYPtrIn;
30
31 }
32
33 //--------------------------------------------------------------------------
34
35 void WidthFunction::setInternal2(int idResIn, int id1In, int id2In, 
36   int id3In, int idIntIn) {
37
38   // Res -> 1,2,3
39   idRes = idResIn;
40   id1 = id1In; 
41   id2 = id2In; 
42   id3 = id3In; 
43   idInt = idIntIn; 
44
45   mRes = particleDataPtr->m0(idRes);
46   m1 = particleDataPtr->m0(id1);
47   m2 = particleDataPtr->m0(id2);
48   m3 = particleDataPtr->m0(id3);
49
50   // Internal propagator
51   mInt = particleDataPtr->m0(idInt);
52   gammaInt = particleDataPtr->mWidth(idInt);
53
54   return;
55 }
56
57 //--------------------------------------------------------------------------
58
59 double WidthFunction::function(double) {
60
61   cout<<"Warning using dummy width function"<<endl;
62   return 0.;
63 }
64
65 //--------------------------------------------------------------------------
66
67 double WidthFunction::function(double,double) {
68
69   cout<<"Warning using dummy width function"<<endl;
70   return 0.;
71 }
72
73 //==========================================================================
74
75 // Psi, Upsilon and Phi classes.
76
77 //--------------------------------------------------------------------------
78
79 void Psi::setInternal (int idResIn, int id1In, int id2In, int id3In, 
80   int idIntIn, int) {
81
82   setInternal2(idResIn, id1In, id2In, id3In, idIntIn);
83
84   mInt = particleDataPtr->m0(idInt);
85   gammaInt = particleDataPtr->mWidth(idInt);
86   iX = coupSUSYPtr->typeNeut(idRes);  
87   iQ = (id3+1)/2;
88   iSq = (idInt>1000000)? 3 + (idInt%10+1)/2 :  (idInt%10+1)/2;
89   isSqDown = (idInt % 2 == 1)? true : false;
90   m1 = particleDataPtr->m0(id1);
91   m2 = particleDataPtr->m0(id2);
92   m3 = particleDataPtr->m0(id3);
93   return;
94 }
95
96 //--------------------------------------------------------------------------
97
98 void Upsilon::setInternal (int idResIn, int id1In, int id2In, int id3In, 
99   int idIntIn, int idInt2In) {
100
101   setInternal2(idResIn, id1In, id2In, id3In, idIntIn);
102
103   idInt2 = idInt2In;
104   mInt = particleDataPtr->m0(idInt);
105   gammaInt = particleDataPtr->mWidth(idInt);
106   mInt2 = particleDataPtr->m0(idInt2);
107   gammaInt2 = particleDataPtr->mWidth(idInt2);
108
109   iX = coupSUSYPtr->typeNeut(idRes);  
110   iQ = (id3+1)/2;
111   iSq  = (idInt>1000000)? 3 + (idInt%10+1)/2 :  (idInt%10+1)/2;
112   iSq2 = (idInt2>1000000)? 3 + (idInt2%10+1)/2 :  (idInt2%10+1)/2;
113   isSqDown = (idIntIn % 2 == 1)? true : false;
114   m1 = particleDataPtr->m0(id1);
115   m2 = particleDataPtr->m0(id2);
116   m3 = particleDataPtr->m0(id3);
117   return;
118 }
119
120 //--------------------------------------------------------------------------
121
122 void Phi::setInternal (int idResIn, int id1In, int id2In, int id3In, 
123   int idIntIn, int idInt2In) {
124
125   setInternal2(idResIn, id1In, id2In, id3In, idIntIn);
126
127   idInt2 = idInt2In;
128   mInt = particleDataPtr->m0(idInt);
129   gammaInt = particleDataPtr->mWidth(idInt);
130   mInt2 = particleDataPtr->m0(idInt2);
131   gammaInt2 = particleDataPtr->mWidth(idInt2);
132
133   iX = coupSUSYPtr->typeNeut(idRes);  
134   iQ = (id3+1)/2;
135   iSq  = (idInt>1000000)? 3 + (idInt%10+1)/2 :  (idInt%10+1)/2;
136   iSq2 = (idInt2>1000000)? 3 + (idInt2%10+1)/2 :  (idInt2%10+1)/2;
137   isSqDown = (idIntIn % 2 == 1)? true : false;
138   m1 = particleDataPtr->m0(id1);
139   m2 = particleDataPtr->m0(id2);
140   m3 = particleDataPtr->m0(id3);
141   return;
142 }
143
144 //--------------------------------------------------------------------------
145
146 double Psi::function(double m12sq) {
147
148   double R, factor1, factor2, value;
149
150   // Check that the propagators are offshell
151   if(m12sq > pow2(mInt) || abs(m12sq - pow2(mInt)) < gammaInt) return 0; 
152
153   R = 1.0/(pow2(m12sq-pow2(mInt)) + pow2(gammaInt*mInt));
154   if(isSqDown){
155     factor1 = (norm(coupSUSYPtr->LsddX[iSq][iQ][iX])
156                + norm(coupSUSYPtr->RsddX[iSq][iQ][iX]))*
157       (mRes*mRes + m3*m3 - m12sq);
158     factor2 = 4.0 * real(coupSUSYPtr->LsddX[iSq][iQ][iX] 
159                          * conj(coupSUSYPtr->RsddX[iSq][iQ][iX])) * m3 * mRes;
160
161   } else {
162     factor1 = (norm(coupSUSYPtr->LsuuX[iSq][iQ][iX]) 
163                + norm(coupSUSYPtr->RsuuX[iSq][iQ][iX]))*
164       (mRes*mRes + m3*m3 - m12sq);
165     factor2 = 4.0 * real(coupSUSYPtr->LsuuX[iSq][iQ][iX] 
166                          * conj(coupSUSYPtr->RsuuX[iSq][iQ][iX])) * m3 * mRes;
167   }
168
169   value = R * (m12sq - m1*m1 - m2*m2) * (factor1+factor2);
170
171   return value;
172 }
173
174
175 //--------------------------------------------------------------------------
176
177 double Upsilon::function(double m12sq) {
178
179   double R1,R2, S, factor1, factor2, value;
180
181   // Check that the propagators are offshell
182   if(m12sq > pow2(mInt) || abs(m12sq - pow2(mInt)) < gammaInt) return 0; 
183   if(m12sq > pow2(mInt2) || abs(m12sq - pow2(mInt2)) < gammaInt2) return 0; 
184   
185   R1 = 1.0/(pow2(m12sq-pow2(mInt)) + pow2(gammaInt*mInt));
186   R2 =  1.0/(pow2(m12sq-pow2(mInt2)) + pow2(gammaInt2*mInt2));
187   S = R1 * R2 * ((m12sq - pow2(mInt)) * (m12sq - pow2(mInt2)) 
188                  + gammaInt * mInt * gammaInt2 * mInt2);
189
190   if(isSqDown){
191     factor1 = real(coupSUSYPtr->LsddX[iSq][iQ][iX] 
192                    * conj(coupSUSYPtr->LsddX[iSq2][iQ][iX])) 
193       + real(coupSUSYPtr->RsddX[iSq][iQ][iX] 
194              * conj(coupSUSYPtr->RsddX[iSq2][iQ][iX]));
195     factor2 = real(coupSUSYPtr->LsddX[iSq][iQ][iX] 
196                    * conj(coupSUSYPtr->RsddX[iSq2][iQ][iX])) 
197       + real(coupSUSYPtr->RsddX[iSq][iQ][iX] 
198              * conj(coupSUSYPtr->LsddX[iSq2][iQ][iX]));
199   }else{
200     factor1 = real(coupSUSYPtr->LsuuX[iSq][iQ][iX]
201                    * conj(coupSUSYPtr->LsuuX[iSq2][iQ][iX])) 
202       + real(coupSUSYPtr->RsuuX[iSq][iQ][iX]
203              * conj(coupSUSYPtr->RsuuX[iSq2][iQ][iX]));
204     factor2 = real(coupSUSYPtr->LsuuX[iSq][iQ][iX]
205                    * conj(coupSUSYPtr->RsuuX[iSq2][iQ][iX])) 
206       + real(coupSUSYPtr->RsuuX[iSq][iQ][iX]
207              * conj(coupSUSYPtr->LsuuX[iSq2][iQ][iX]));
208   }
209
210   value = S * (m12sq - pow2(m1) - pow2(m2)) *
211     ( factor1 * (pow2(mRes) + pow2(m3) - m12sq) + 2.0 * factor2 * m3 * mRes);
212
213   //  cout<<"I1: "<<idInt<<" I2:"<<idInt2<<" factor1: "<<factor1
214   //        <<" factor2:"<<factor2<<" value:"<<value<<endl;
215
216   return value;
217
218 }
219
220 //--------------------------------------------------------------------------
221
222 double Phi::function(double m12sqIn) {
223
224   m12sq =  m12sqIn;
225   // Check that the propagators are offshell
226   if(m12sq > pow2(mInt) || abs(m12sq - pow2(mInt)) < gammaInt) return 0; 
227
228   double m23max, m23min, E2, E3;
229
230   E2 = (m12sq - pow2(m1) - pow2(m2))/(2.0 * sqrt(m12sq));
231   E3 = (pow2(mRes) - m12sq - pow2(m3))/(2.0 * sqrt(m12sq));
232   m23max = pow2(E2+E3) - (sqrt(E2*E2 - m2*m2) - sqrt(E3*E3 - m3*m3)) ;
233   m23min = pow2(E2+E3) - (sqrt(E2*E2 - m2*m2) + sqrt(E3*E3 - m3*m3)) ;
234
235   if(E2 < m2 || E3 < m3){
236     cout <<"Error in Phi:function"<<endl;
237     return 0.;
238   }
239
240   double integral2 = integrateGauss(m23min,m23max,1.0e-4);
241   return integral2;
242 }
243
244 //--------------------------------------------------------------------------
245
246 double Phi::function2(double m23sq) {
247
248   // Check that the propagators are offshell
249   if(m23sq > pow2(mInt2) || abs(m23sq - pow2(mInt2)) < gammaInt2) return 0; 
250
251   double R1, R2, S, factor1, factor2, factor3, factor4, value, fac;
252   int iQ2;
253
254   R1 = 1.0/(pow2(m12sq-pow2(mInt)) + pow2(gammaInt*mInt));
255   R2 = 1.0/(pow2(m12sq-pow2(mInt2)) + pow2(gammaInt2*mInt2));
256   S = R1 * R2 * ((m12sq - pow2(mInt)) * (m12sq - pow2(mInt2)) 
257     + gammaInt * mInt * gammaInt2 * mInt2);
258
259   fac = 1.0;
260
261   if(isSqDown){
262     // Only factor is when both d_i and d_j are near.
263     iQ2 = (id1%2 == 1)? (id1+1)/2 : (id2+1)/2;
264
265     if(mRes > mInt2 + particleDataPtr->m0(iQ2)) fac = 0.;
266
267     factor1 = m1 * m3 * real(coupSUSYPtr->LsddX[iSq][iQ][iX] 
268                              * conj(coupSUSYPtr->LsddX[iSq2][iQ2][iX]))
269       * (m12sq + m23sq - pow2(m1) - pow2(m3));
270     factor2 = m1 * mRes * real(coupSUSYPtr->RsddX[iSq][iQ][iX] 
271                                * conj(coupSUSYPtr->LsddX[iSq2][iQ2][iX]))
272       * (m23sq - pow2(m2) - pow2(m3));
273     factor3 = m3 * mRes * real(coupSUSYPtr->LsddX[iSq][iQ][iX] 
274                                * conj(coupSUSYPtr->RsddX[iSq2][iQ2][iX]))
275       * (m12sq - pow2(m1) - pow2(m2));
276     factor4 = m3 * mRes * real(coupSUSYPtr->RsddX[iSq][iQ][iX] 
277                                * conj(coupSUSYPtr->RsddX[iSq2][iQ2][iX]))
278       * (m12sq * m23sq - pow2(m1 * m3) - pow2(m2 * mRes));
279
280   }else{
281     // Factor A: u and d_1
282     iQ2 = (id1+1)/2;
283
284     if(mRes > mInt2 + particleDataPtr->m0(iQ2)) fac = 0.;
285
286     factor1 = m1 * m3 * real(coupSUSYPtr->LsuuX[iSq][iQ][iX] 
287                              * conj(coupSUSYPtr->LsddX[iSq2][iQ2][iX]))
288       * (m12sq + m23sq - pow2(m1) - pow2(m3));
289     factor2 = m1 * mRes * real(coupSUSYPtr->RsuuX[iSq][iQ][iX] 
290                                * conj(coupSUSYPtr->LsddX[iSq2][iQ2][iX]))
291       * (m23sq - pow2(m2) - pow2(m3));
292     factor3 = m3 * mRes * real(coupSUSYPtr->LsuuX[iSq][iQ][iX] 
293                                * conj(coupSUSYPtr->RsddX[iSq2][iQ2][iX]))
294       * (m12sq - pow2(m1) - pow2(m2));
295     factor4 = m3 * mRes * real(coupSUSYPtr->RsuuX[iSq][iQ][iX] 
296                                * conj(coupSUSYPtr->RsddX[iSq2][iQ2][iX]))
297       * (m12sq * m23sq - pow2(m1 * m3) - pow2(m2 * mRes));
298
299
300     // Factor B: u and d_2; change 1 <=> 2
301     iQ2 = (id2+1)/2;
302
303     if(mRes > mInt2 + particleDataPtr->m0(iQ2)) fac = 0.;
304
305     factor1 += m2 * m3 * real(coupSUSYPtr->LsuuX[iSq][iQ][iX] 
306                               * conj(coupSUSYPtr->LsddX[iSq2][iQ2][iX]))
307       * (m12sq + m23sq - pow2(m2) - pow2(m3));
308     factor2 += m2 * mRes * real(coupSUSYPtr->RsuuX[iSq][iQ][iX] 
309                                 * conj(coupSUSYPtr->LsddX[iSq2][iQ2][iX]))
310       * (m23sq - pow2(m1) - pow2(m3));
311     factor3 += m3 * mRes * real(coupSUSYPtr->LsuuX[iSq][iQ][iX] 
312                                 * conj(coupSUSYPtr->RsddX[iSq2][iQ2][iX]))
313       * (m12sq - pow2(m2) - pow2(m1));
314     factor4 += m3 * mRes * real(coupSUSYPtr->RsuuX[iSq][iQ][iX] 
315                                 * conj(coupSUSYPtr->RsddX[iSq2][iQ2][iX]))
316       * (m12sq * m23sq - pow2(m2 * m3) - pow2(m1 * mRes));
317   }
318
319   value = S * (factor1 + factor2 + factor3 + factor4);
320
321   //  cout<<"I1: "<<idInt<<" I2:"<<idInt2<<" factor1: "<<factor1
322   //      <<" factor2:"<<factor2<<" value:"<<value<<endl;
323
324   return (fac * value);
325 }
326
327 //--------------------------------------------------------------------------
328
329 double Phi::integrateGauss(double xlo, double xhi, double tol) {
330
331   //8-point unweighted
332   static double x8[4]={0.96028985649753623,
333                        0.79666647741362674,
334                        0.52553240991632899, 
335                        0.18343464249564980};
336   static double w8[4]={0.10122853629037626,
337                        0.22238103445337447,
338                        0.31370664587788729,
339                        0.36268378337836198};
340   //16-point unweighted
341   static double x16[8]={0.98940093499164993, 
342                        0.94457502307323258, 
343                        0.86563120238783174, 
344                        0.75540440835500303, 
345                        0.61787624440264375, 
346                        0.45801677765722739,
347                        0.28160355077925891, 
348                        0.09501250983763744};
349   static double w16[8]={0.027152459411754095,
350                        0.062253523938647893,
351                        0.095158511682492785,
352                        0.12462897125553387,
353                        0.14959598881657673,
354                        0.16915651939500254,
355                        0.18260341504492359,
356                        0.18945061045506850};
357   //boundary checks
358   if (xlo == xhi) {
359     cerr<<"xlo = xhi"<<endl;
360     return 0.0;
361   }
362   if ( xlo > xhi ) {
363     cerr<<" (integrateGauss:) -> xhi < xlo"<<endl;
364     return 0.0;
365   }
366   //initialize
367   double sum = 0.0;
368   double c = 0.001/abs(xhi-xlo);
369   double zlo = xlo;
370   double zhi = xhi;
371     
372   bool nextbin = true;
373   
374   while ( nextbin ) {
375     
376     double zmi = 0.5*(zhi+zlo); // midpoint
377     double zmr = 0.5*(zhi-zlo); // midpoint, relative to zlo
378     
379     //calculate 8-point and 16-point quadratures
380     double s8=0.0;
381     for (int i=0;i<4;i++) {
382       double dz = zmr * x8[i];
383       s8 += w8[i]*(function2(zmi+dz) + function2(zmi-dz));
384     }
385     s8 *= zmr;
386     double s16=0.0;
387     for (int i=0;i<8;i++) {
388       double dz = zmr * x16[i];
389       s16 += w16[i]*(function2(zmi+dz) + function2(zmi-dz)); 
390     }
391     s16 *= zmr;
392     if (abs(s16-s8) < tol*(1+abs(s16))) { 
393       //precision in this bin OK, add to cumulative and go to next
394       nextbin=true;
395       sum += s16;
396       //next bin: LO = end of current, HI = end of integration region.
397       zlo=zhi;
398       zhi=xhi;
399       if ( zlo == zhi ) nextbin = false;
400     } else {
401       //precision in this bin not OK, subdivide.
402       if (1.0 + c*abs(zmr) == 1.0) {
403         cerr << " (integrateGauss:) too high accuracy required"<<endl;
404         sum = 0.0 ;
405         break;
406       }
407       zhi=zmi;
408       nextbin=true;
409     }
410   }
411   return sum;
412 }
413
414 //==========================================================================
415
416 // The SUSYResonanceWidths Class
417 // Derived class for SUSY resonances
418
419 const bool SUSYResonanceWidths::DEBUG = false;
420
421 //--------------------------------------------------------------------------
422
423 bool SUSYResonanceWidths::init(Info* infoPtrIn, Settings* settingsPtrIn,
424    ParticleData* particleDataPtrIn, Couplings* couplingsPtrIn) {
425
426   // Save pointers.
427   infoPtr         = infoPtrIn;
428   settingsPtr     = settingsPtrIn;
429   particleDataPtr = particleDataPtrIn;
430   coupSUSYPtr     = (couplingsPtrIn->isSUSY ? (CoupSUSY *) couplingsPtrIn: 0 );
431
432   // No width calculation necessary for SM-only
433   bool calcWidthAllow = true;
434   if(!couplingsPtrIn->isSUSY) calcWidthAllow = false;
435
436   // Minimal decaying-resonance width. Minimal phase space for meMode = 103.
437   minWidth     = settingsPtr->parm("ResonanceWidths:minWidth");
438   minThreshold = settingsPtr->parm("ResonanceWidths:minThreshold");
439
440   // Pointer to particle species.
441   particlePtr  = particleDataPtr->particleDataEntryPtr(idRes);
442   if (particlePtr == 0) {
443     infoPtr->errorMsg("Error in ResonanceWidths::init:"
444       " unknown resonance identity code");   
445     return false;
446   }  
447
448   // Generic particles should not have meMode < 100, but allow 
449   // some exceptions: not used Higgses and not used Technicolor.
450   if (idRes == 35 || idRes == 36 || idRes == 37 
451     || idRes/1000000 == 3) isGeneric = false;
452
453   // Resonance properties: antiparticle, mass, width
454   hasAntiRes   = particlePtr->hasAnti();
455   mRes         = particlePtr->m0();
456   GammaRes     = particlePtr->mWidth();
457   m2Res        = mRes*mRes;
458
459   // For very narrow resonances assign fictitious small width.
460   if (GammaRes < minWidth) GammaRes = 0.1 * minWidth;  
461   GamMRat      = GammaRes / mRes;
462
463   // Secondary decay chains by default all on.
464   openPos      = 1.;
465   openNeg      = 1.;
466
467   // Allow option where on-shell width is forced to current value.
468   doForceWidth = particlePtr->doForceWidth();
469   forceFactor  = 1.;
470
471   // Check that resonance OK.
472   if (particlePtr == 0) infoPtr->errorMsg("Error in ResonanceWidths::init:"
473       " unknown resonance identity code");   
474
475   // Check if decay table was read in via SLHA
476   bool hasDecayTable = false;
477   if(calcWidthAllow) {
478     for(unsigned int iDec = 1; iDec < (coupSUSYPtr->slhaPtr)->decays.size(); 
479       iDec++)
480       if(!hasDecayTable) hasDecayTable 
481         = ((coupSUSYPtr->slhaPtr)->decays[iDec].getId() == abs(idRes));
482   }
483
484   if(hasDecayTable && settingsPtr->flag("SLHA:useDecayTable")) {
485     calcWidthAllow = false;
486     if(DEBUG) cout<<"Found decay table for:"<<idRes<<endl;  
487   }
488
489   // Initialize constants used for a resonance.
490   if(calcWidthAllow) {
491     mHat          = mRes;
492     initConstants();
493     calcPreFac(true);
494   }
495
496   // Reset quantities to sum. Declare variables inside loop.
497   double widTot = 0.; 
498   double widPos = 0.;
499   double widNeg = 0.;
500   int    idNow, idAnti;
501   double openSecPos, openSecNeg;
502
503   // Loop over all decay channels. Basic properties of channel.
504   for (int i = 0; i < particlePtr->sizeChannels(); ++i) {
505     iChannel    = i;
506     onMode      = particlePtr->channel(i).onMode();
507     meMode      = particlePtr->channel(i).meMode();
508     mult        = particlePtr->channel(i).multiplicity();
509     widNow      = 0.;
510
511     // Warn if not relevant meMode.
512     if ( meMode < 0 || meMode > 103 || (isGeneric && meMode < 100) ) { 
513       infoPtr->errorMsg("Error in ResonanceWidths::init:"
514         " resonance meMode not acceptable"); 
515     }
516
517     // Calculation of SUSY particle widths
518     if (meMode == 103 && GammaRes > 0. && calcWidthAllow &&
519         (!settingsPtr->flag("SLHA:useDecayTable") || !hasDecayTable)) {
520       // Read out information on channel: primarily use first two. 
521       id1       = particlePtr->channel(i).product(0);
522       id2       = particlePtr->channel(i).product(1);
523       id1Abs    = abs(id1);
524       id2Abs    = abs(id2);
525        
526       // Order first two in descending order of absolute values.
527       if (id2Abs > id1Abs) {swap( id1, id2); swap( id1Abs, id2Abs);}
528
529       // Allow for third product to be treated in derived classes.
530       if (mult > 2) { 
531         id3     = particlePtr->channel(i).product(2);
532         id3Abs  = abs(id3);
533         
534         // Also order third into descending order of absolute values.
535         if (id3Abs > id2Abs) {swap( id2, id3); swap( id2Abs, id3Abs);}
536         if (id2Abs > id1Abs) {swap( id1, id2); swap( id1Abs, id2Abs);}
537       }
538
539       // Read out masses. Calculate two-body phase space.
540       mf1       = particleDataPtr->m0(id1Abs);
541       mf2       = particleDataPtr->m0(id2Abs);
542       mr1       = pow2(mf1 / mHat);
543       mr2       = pow2(mf2 / mHat);
544       ps        = (mHat < mf1 + mf2 + MASSMARGIN) ? 0. 
545         : sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 ) * pow2(mHat);
546       if (mult > 2) {      
547         mf3     = particleDataPtr->m0(id3Abs);
548         mr3     = pow2(mf3 / mHat);
549
550         //Check phase space
551         ps = 1.0;
552         if(mHat < mf1 + mf2 + mf3 + MASSMARGIN) ps = 0.;
553       }
554
555       // Let derived class calculate width for channel provided.
556       calcWidth(true);
557     }
558
559     // Width calculated based on stored values.
560     else widNow = GammaRes * particlePtr->channel(i).bRatio();
561    
562     // Find secondary open fractions of partial width.
563     openSecPos  = 1.;
564     openSecNeg  = 1.;
565     if (widNow > 0.) for (int j = 0; j < mult; ++j) {
566       idNow     = particlePtr->channel(i).product(j);
567       idAnti    = (particleDataPtr->hasAnti(idNow)) ? -idNow : idNow;
568       // Secondary widths not yet initialized for heavier states,
569       // so have to assume unit open fraction there.
570       if (idNow == 23 || abs(idNow) == 24 
571         || particleDataPtr->m0(abs(idNow)) < mRes) {
572         openSecPos *= particleDataPtr->resOpenFrac(idNow); 
573         openSecNeg *= particleDataPtr->resOpenFrac(idAnti);
574       } 
575     }
576
577     // Store partial widths and secondary open fractions.
578     particlePtr->channel(i).onShellWidth(widNow); 
579     particlePtr->channel(i).openSec( idRes, openSecPos);  
580     particlePtr->channel(i).openSec(-idRes, openSecNeg);  
581
582     // Update sum over all channnels and over open channels only.
583     widTot     += widNow;    
584     if (onMode == 1 || onMode == 2) widPos += widNow * openSecPos;
585     if (onMode == 1 || onMode == 3) widNeg += widNow * openSecNeg;
586   }
587
588   // If no decay channels are open then set particle stable and done.
589   if (widTot < minWidth) { 
590     particlePtr->setMayDecay(false, false);
591     particlePtr->setMWidth(0., false);
592     for (int i = 0; i < particlePtr->sizeChannels(); ++i) 
593       particlePtr->channel(i).bRatio( 0., false);
594     return true;
595   }
596
597   // Normalize branching ratios to unity.
598   double bRatio;
599   for (int i = 0; i < particlePtr->sizeChannels(); ++i) {
600     bRatio      = particlePtr->channel(i).onShellWidth() / widTot;
601     particlePtr->channel(i).bRatio( bRatio, false);
602   }
603
604   // Optionally force total width by rescaling of all partial ones.
605   if (doForceWidth) {
606     forceFactor = GammaRes / widTot;
607     for (int i = 0; i < particlePtr->sizeChannels(); ++i)
608       particlePtr->channel(i).onShellWidthFactor( forceFactor);
609   } 
610
611   // Else update newly calculated partial width.
612   else {
613     particlePtr->setMWidth(widTot, false);
614     GammaRes    = widTot;
615   }
616
617   // Updated width-to-mass ratio. Secondary widths for open.
618   GamMRat       = GammaRes / mRes;  
619   openPos       = widPos / widTot;
620   openNeg       = widNeg / widTot;
621
622   // Done.
623   return true;
624
625 }  
626
627 //==========================================================================
628
629 // The ResonanceSquark class
630 // Derived class for Squark resonances
631
632 //--------------------------------------------------------------------------
633
634 // Initialize constants.
635
636 void ResonanceSquark::initConstants() {
637
638   // Locally stored properties and couplings.
639   alpS  = coupSUSYPtr->alphaS(mHat * mHat );
640   alpEM = coupSUSYPtr->alphaEM(mHat * mHat);
641   s2W   = coupSUSYPtr->sin2W;
642 }
643
644 //--------------------------------------------------------------------------
645
646 // Calculate various common prefactors for the current mass.
647
648 void ResonanceSquark::calcPreFac(bool) {
649
650   // Common coupling factors.
651   preFac = 1.0 / (s2W * pow(mHat,3));
652
653 }
654
655 //--------------------------------------------------------------------------
656
657 // Calculate width for currently considered channel.
658
659 void ResonanceSquark::calcWidth(bool) {
660
661   // Squark type -- in u_i/d_i and generation
662   int ksusy = 1000000;
663   bool idown = (abs(idRes)%2 == 0 ? false : true);
664   int isq = (abs(idRes)/ksusy == 2) ? 
665     (abs(idRes)%10+1)/2 + 3: (abs(idRes)%10+1)/2;
666   // int isqgen = (abs(idRes)%10 + 1)/2;
667
668   // Check that mass is above threshold.
669   if(ps == 0.) return;
670   else{
671     // Two-body decays
672     kinFac = (mHat * mHat - mf1 * mf1 - mf2 * mf2);
673     
674     double fac = 0.0 , wid = 0.0;
675   
676     //RPV decays
677     //Case 1a:  UDD-type 
678     if(id1Abs < 7 && id2Abs < 7){
679       
680       // Quark generations
681       int iq1 = (id1Abs + 1)/2;
682       int iq2 = (id2Abs + 1)/2;
683       
684       // Check for RPV UDD couplings
685       if(!coupSUSYPtr->isUDD) {widNow = 0; return;}
686       
687       // ~q -> q_i + q_j
688       
689       fac = 2.0 * kinFac / (16.0 * M_PI * pow(mHat,3)); 
690       wid = 0.0;
691       if(idown) {
692         if ((id1Abs+id2Abs)%2 == 1){
693           if(id1Abs%2==1)
694             for(int isq2 = 1; isq2 < 4; isq2++)
695               wid += norm(coupSUSYPtr->rvUDD[iq2][iq1][isq2] 
696                    * coupSUSYPtr->Rdsq[isq][isq2+3]);
697           else
698             for(int isq2 = 1; isq2 < 4; isq2++)
699               wid += norm(coupSUSYPtr->rvUDD[iq1][iq2][isq2] 
700                    * coupSUSYPtr->Rdsq[isq][isq2+3]);
701         }
702       }
703       else {
704         if ((id1Abs+id2Abs)%2 != 0) widNow = 0.0;
705         else
706           for(int isq2 = 1; isq2 < 4; isq2++)
707             wid += norm(coupSUSYPtr->rvUDD[isq2][iq1][iq2] 
708                  * coupSUSYPtr->Rusq[isq][isq2+3]);
709       }
710   }
711     
712     //Case 1b:  LQD-type 
713     else if(id1Abs < 17 && id2Abs < 7){
714       if(!coupSUSYPtr->isLQD) {widNow = 0; return;}
715       
716       int ilep = (id1Abs - 9)/2;
717       int iq = (id2Abs + 1)/2;
718     
719       fac = kinFac / (16.0 * M_PI * pow(mHat,3)); 
720       wid = 0.0;
721       if(idown){
722         if(iq%2 == 0){
723           // q is up-type; ~q is right-handed down type
724           for(int isq2=1; isq2<3; isq2++)
725             wid += norm(coupSUSYPtr->Rdsq[isq][isq2+3] 
726                  * coupSUSYPtr->rvLQD[ilep][iq][isq2]);
727         }else{
728           //q is down type; ~q left-handed down-type
729           for(int isq2=1; isq2<3; isq2++)
730             wid += norm(coupSUSYPtr->Rdsq[isq][isq2] 
731                  * coupSUSYPtr->rvLQD[ilep][isq2][isq2]);
732         }
733       }
734       else{
735         if(iq%2 == 0) {widNow = 0.0; return;}
736         // q is down type; ~q is left-handed up-type
737         for(int isq2=1; isq2<3; isq2++)
738           wid += norm(coupSUSYPtr->Rusq[isq][isq2] 
739                * coupSUSYPtr->rvLQD[ilep][isq2][iq]);
740       }
741     }
742     
743     //Case 2: quark + gaugino 
744     else if (id1Abs > ksusy && id2Abs < 7) {
745       
746       int iq = (id2Abs + 1)/2;
747       
748       // ~q -> ~g + q
749       if(id1Abs == 1000021 && idRes%10 == id2Abs) {
750         // Removed factor of s2W in denominator: strong process -- no EW
751         fac = 2.0 * alpS / (3.0 * pow3(mHat));
752         if(idown)
753           wid = kinFac * (norm(coupSUSYPtr->LsddG[isq][iq]) 
754               + norm(coupSUSYPtr->RsddG[isq][iq]))
755               - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsddG[isq][iq] 
756               * conj(coupSUSYPtr->RsddG[isq][iq]));
757         else
758           wid = kinFac * (norm(coupSUSYPtr->LsuuG[isq][iq]) 
759               + norm(coupSUSYPtr->RsuuG[isq][iq]))
760               - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsuuG[isq][iq] 
761               * conj(coupSUSYPtr->RsuuG[isq][iq]));
762       } 
763       else 
764         for(int i=1; i<6 ; i++){
765           // ~q -> ~chi0 + q
766           if(coupSUSYPtr->idNeut(i)==id1Abs && idRes%2 == id2Abs%2){
767             fac = alpEM *  preFac / (2.0 * (1 - s2W));
768             if(idown)
769               wid = kinFac * (norm(coupSUSYPtr->LsddX[isq][iq][i]) 
770                   + norm(coupSUSYPtr->RsddX[isq][iq][i]))
771                   - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsddX[isq][iq][i] 
772                   * conj(coupSUSYPtr->RsddX[isq][iq][i]));
773             else
774               wid = kinFac * (norm(coupSUSYPtr->LsuuX[isq][iq][i]) 
775                   + norm(coupSUSYPtr->RsuuX[isq][iq][i]))
776                   - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsuuX[isq][iq][i] 
777                   * conj(coupSUSYPtr->RsuuX[isq][iq][i]));
778           }
779           
780           // ~q -> chi- + q
781           else if (i < 3 && coupSUSYPtr->idChar(i)==id1Abs 
782             && idRes%2 != id2Abs%2){
783             
784             fac = alpEM *  preFac / (4.0 * (1 - s2W));
785             if(idown)
786               wid = kinFac * (norm(coupSUSYPtr->LsduX[isq][iq][i]) 
787                   + norm(coupSUSYPtr->RsduX[isq][iq][i]))
788                   - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsduX[isq][iq][i] 
789                   * conj(coupSUSYPtr->RsduX[isq][iq][i]));
790             else
791               wid = kinFac * (norm(coupSUSYPtr->LsudX[isq][iq][i]) 
792                   + norm(coupSUSYPtr->RsudX[isq][iq][i]))
793                   - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsudX[isq][iq][i] 
794                   * conj(coupSUSYPtr->RsudX[isq][iq][i]));
795           }
796         }
797     }
798     
799     //Case 3: ~q_i -> ~q_j + Z/W
800     else if (id1Abs > ksusy && id1Abs%100 < 7 
801       && (id2Abs == 23 || id2Abs == 24)){
802       
803       // factor of lambda^(3/2) = ps^(3/2) ; 
804       fac = alpEM * preFac/(16.0 * pow2(particleDataPtr->m0(id2Abs)) 
805           * (1.0 - s2W)) * pow2(ps) ;
806       
807       int isq2 = (id1Abs/ksusy == 2) ? (id1Abs%10+1)/2 + 3: (id1Abs%10+1)/2;
808       
809       if(id2Abs == 23 && id1Abs%2 == idRes%2){
810         if(idown)
811           wid = norm(coupSUSYPtr->LsdsdZ[isq][isq2] 
812                      + coupSUSYPtr->RsdsdZ[isq][isq2]);
813         else
814           wid = norm(coupSUSYPtr->LsusuZ[isq][isq2] 
815                      + coupSUSYPtr->RsusuZ[isq][isq2]);
816       }
817       else if (id2Abs == 24 && id1Abs%2 != idRes%2){
818         if(idown)
819           wid = norm(coupSUSYPtr->LsusdW[isq2][isq]);
820         else
821           wid = norm(coupSUSYPtr->LsusdW[isq][isq2]);
822       }
823     }
824     
825     // TODO: Case ~q_i -> ~q_j + h/H
826     widNow = fac * wid * ps;
827     if(DEBUG) cout<<idRes<<":: id1:"<<id1Abs<<" id2:"<<id2Abs
828                   <<" Width: "<<widNow<<endl;
829     return;
830   }
831         
832 }
833
834 //==========================================================================
835
836 // The ResonanceGluino class
837 // Derived class for Gluino resonances
838
839 //--------------------------------------------------------------------------
840
841 // Initialize constants.
842
843 void ResonanceGluino::initConstants() {
844
845   // Locally stored properties and couplings.
846   alpS  = coupSUSYPtr->alphaS(mHat * mHat);
847   return;
848 }
849
850 //--------------------------------------------------------------------------
851
852 // Calculate various common prefactors for the current mass.
853
854 void ResonanceGluino::calcPreFac(bool) {
855   // Common coupling factors.
856   preFac = alpS /( 8.0 * pow(mHat,3));
857   return;
858 }
859
860 //--------------------------------------------------------------------------
861
862 // Calculate width for currently considered channel.
863
864 void ResonanceGluino::calcWidth(bool) {
865
866
867   widNow = 0.0;
868   if(ps == 0.) return;
869   kinFac = (mHat * mHat - mf1 * mf1 + mf2 * mf2);
870
871   if(id1Abs > 1000000 && (id1Abs % 100) < 7 && id2Abs < 7) {
872
873     int isq = (abs(id1Abs)/1000000 == 2) ? (abs(id1Abs)%10+1)/2 + 3
874                                          : (abs(id1Abs)%10+1)/2;
875     bool idown = id2Abs%2;
876     int iq = (id2Abs + 1)/2;
877
878     // ~g -> ~q + q
879     if(idown){
880       widNow = kinFac * (norm(coupSUSYPtr->LsddG[isq][iq]) 
881              + norm(coupSUSYPtr->RsddG[isq][iq]))
882              + 4.0 * mHat * mf2 * real(coupSUSYPtr->LsddG[isq][iq] 
883              * conj(coupSUSYPtr->RsddG[isq][iq]));
884     }
885     else{
886       widNow = kinFac * (norm(coupSUSYPtr->LsuuG[isq][iq]) 
887              + norm(coupSUSYPtr->RsuuG[isq][iq]))
888              + 4.0 * mHat * mf2 * real(coupSUSYPtr->LsuuG[isq][iq] 
889              * conj(coupSUSYPtr->RsuuG[isq][iq]));
890     }
891     widNow = widNow * preFac * ps;
892     if(DEBUG) {
893       cout<<"Gluino:: id1:"<<id1Abs<<" id2:"<<id2Abs<<" Width: ";
894       cout<<scientific<<widNow<<endl;
895     }
896     return;
897   }
898 }
899
900 //==========================================================================
901
902 //  Class ResonanceNeut
903 //  Derived class for Neutralino Resonances
904 //
905 //--------------------------------------------------------------------------
906
907
908 void ResonanceNeut::initConstants(){
909   
910   alpEM = coupSUSYPtr->alphaEM(mHat * mHat);
911   s2W   = coupSUSYPtr->sin2W;
912
913   // Initialize functions for calculating 3-body widths
914   psi.init(particleDataPtr,coupSUSYPtr);
915   phi.init(particleDataPtr,coupSUSYPtr);
916   upsil.init(particleDataPtr,coupSUSYPtr);
917 }
918  
919 //--------------------------------------------------------------------------
920
921 // Calculate various common prefactors for the current mass.
922 void  ResonanceNeut::calcPreFac(bool){
923
924   // Common coupling factors.
925   preFac = alpEM / (8.0 * s2W * pow(mHat,3));
926   return;
927 }
928
929 //--------------------------------------------------------------------------
930
931 // Calculate width for currently considered channel.
932 void  ResonanceNeut::calcWidth(bool){
933
934   widNow = 0.0;
935
936   if(ps ==0.) return;
937   else if(mult ==2){
938     // Two-body decays
939     
940     kinFac = mHat * mHat - mf1 * mf1 + mf2 * mf2;
941     kinFac2 = pow(mHat,4) + pow(mf1,4) - 2.0 * pow(mf2,4) 
942             + pow2(mHat) * pow2(mf2) + pow2(mf1) * pow2(mf2) 
943             - 2.0 * pow2(mHat) * pow2(mf1);
944     
945     // Stable lightest neutralino
946     if(idRes == 1000022) return;
947     
948     double fac = 0.0;
949     int iNeut1 = coupSUSYPtr->typeNeut(idRes);
950     int iNeut2 = coupSUSYPtr->typeNeut(id1Abs);
951     int iChar1 = coupSUSYPtr->typeChar(id1Abs);
952     
953     if(iNeut2>0 && id2Abs == 23){
954       // ~chi0_i -> chi0_j + Z
955       fac = kinFac2 * (norm(coupSUSYPtr->OLpp[iNeut1][iNeut2]) 
956           + norm(coupSUSYPtr->ORpp[iNeut1][iNeut2]));
957       fac -= 12.0 * mHat * mf1 * pow2(mf2) 
958            * real(coupSUSYPtr->OLpp[iNeut1][iNeut2] 
959            * conj(coupSUSYPtr->ORpp[iNeut1][iNeut2]));
960       fac /= pow2(mf2) * (1.0 - s2W);
961     }
962     else if(iChar1>0 && id2Abs==24){
963       // ~chi0_i -> chi+_j + W- (or c.c.)
964       
965       fac = kinFac2 * (norm(coupSUSYPtr->OL[iNeut1][iChar1]) 
966           + norm(coupSUSYPtr->OR[iNeut1][iChar1]));
967       fac -= 12.0 * mHat * mf1 * pow2(mf2) 
968            * real(coupSUSYPtr->OL[iNeut1][iChar1] 
969            * conj(coupSUSYPtr->OR[iNeut1][iChar1]));
970       fac /= pow2(mf2);
971     }
972     else if(id1Abs > 1000000 && id1Abs%100 < 7 && id2Abs < 7){
973       // ~chi0_k -> ~q + q
974       bool idown = (id1Abs%2 == 1);
975       int iq = (id2Abs + 1 )/ 2;
976       int isq = (abs(id1Abs)/1000000 == 2) ? (abs(id1Abs)%10+1)/2 + 3
977                                            : (abs(id1Abs)%10+1)/2;
978       
979       if(idown){
980         fac  = kinFac * (norm(coupSUSYPtr->LsddX[isq][iq][iNeut1]) 
981              + norm(coupSUSYPtr->RsddX[isq][iq][iNeut1]));
982         fac += 4.0 * mHat * mf2 * real(coupSUSYPtr->LsddX[isq][iq][iNeut1] 
983              * conj(coupSUSYPtr->RsddX[isq][iq][iNeut1]));
984       }
985       else{
986         fac = kinFac * (norm(coupSUSYPtr->LsuuX[isq][iq][iNeut1]) 
987             + norm(coupSUSYPtr->RsuuX[isq][iq][iNeut1]));
988         fac += 4.0 * mHat * mf2 * real(coupSUSYPtr->LsuuX[isq][iq][iNeut1] 
989              * conj(coupSUSYPtr->RsuuX[isq][iq][iNeut1]));
990       }
991       // Extra multiplicative factor of 3 over sleptons
992       fac *= 6.0/(1 - s2W);
993     }
994     else if(id1Abs > 1000000 && id1Abs%100 > 10 && id1Abs%100 < 17 
995       && id2Abs < 17){
996       // ~chi0_k -> ~l + l
997       bool idown = id2Abs%2;
998       int il = (id2Abs - 9)/ 2;
999       int isl = (abs(id1Abs)/1000000 == 2) ? (abs(id1Abs)%10+1)/2 + 3
1000                                            : (abs(id1Abs)%10+1)/2;
1001       
1002       if(idown){
1003         fac  = kinFac * (norm(coupSUSYPtr->LsllX[isl][il][iNeut1]) 
1004              + norm(coupSUSYPtr->RsllX[isl][il][iNeut1]));
1005         fac += 4.0 * mHat * mf2 * real(coupSUSYPtr->LsllX[isl][il][iNeut1] 
1006              * conj(coupSUSYPtr->RsllX[isl][il][iNeut1]));
1007       }
1008       else{
1009         fac = kinFac * (norm(coupSUSYPtr->LsvvX[isl][il][iNeut1]));
1010       }
1011       fac *= 2.0/(1 - s2W);
1012     }
1013     // TODO: Decays in higgs
1014     // Final width for 2-body decays
1015     widNow = fac * preFac * ps ;
1016     if(DEBUG) {
1017       cout<<idRes<<":: id1:"<<id1Abs<<" id2:"<<id2Abs<<" Width: ";
1018       cout<<scientific<<widNow<<endl;
1019     }
1020   }
1021   else {
1022     //RPV 3-body decays
1023     //Case: UDD-type
1024
1025     if(!coupSUSYPtr->isUDD) return;
1026
1027     if(id1Abs < 7 && id2Abs < 7 && id3Abs < 7){
1028
1029       // Check that quarks compatible with UDD structure
1030       if((id1Abs+id2Abs+id3Abs)%2 == 1) return; 
1031       double rvfac,m12min,m12max,integral;
1032       int idInt;
1033       
1034       // Loop over mass eigenstate in actual propagator
1035       for(int idIntRes = 1; idIntRes <= 6; idIntRes++){ 
1036         // Right handed field in the UDD coupling
1037         for (int iSq = 1; iSq <= 3; iSq++){ 
1038           double m1, m2, m3, mixfac1(0.), mixfac2(0.), mixfac3(0.);
1039           int itemp1,itemp2,itemp3;
1040           // up/down-type internal lines
1041           for(int itype = 1; itype<=3; itype++){ 
1042             //itype = 1: up
1043             //itype = 2: down1
1044             //itype = 3: down2
1045             if(itype ==1 ) idInt = coupSUSYPtr->idSup(idIntRes);
1046             else idInt = coupSUSYPtr->idSdown(idIntRes);
1047             if(id1Abs%2 == 0){
1048               if(itype == 1){
1049                 itemp3 = id1Abs;
1050                 itemp1 = id2Abs;
1051                 itemp2 = id3Abs;
1052                 rvfac = pow2(
1053                   coupSUSYPtr->rvUDD[iSq][(id2Abs+1)/2][(id3Abs+1)/2]);
1054               }else if (itype ==2){
1055                 itemp3 = id2Abs;
1056                 itemp1 = id1Abs;
1057                 itemp2 = id3Abs;
1058                 rvfac = pow2(
1059                   coupSUSYPtr->rvUDD[(id1Abs+1)/2][iSq][(id3Abs+1)/2]);
1060               } else{
1061                 itemp3 = id3Abs;
1062                 itemp1 = id1Abs;
1063                 itemp2 = id2Abs;
1064                 rvfac = pow2(
1065                   coupSUSYPtr->rvUDD[(id1Abs+1)/2][(id2Abs+1)/2][iSq]);
1066               }
1067             }else if(id2Abs%2 == 0){
1068               if(itype==1){
1069                 itemp3 = id2Abs;
1070                 itemp1 = id1Abs;
1071                 itemp2 = id3Abs;
1072                 rvfac = pow2(
1073                   coupSUSYPtr->rvUDD[iSq][(id1Abs+1)/2][(id3Abs+1)/2]);
1074               }else if (itype ==2){
1075                 itemp3 = id1Abs;
1076                 itemp1 = id2Abs;
1077                 itemp2 = id3Abs;
1078                 rvfac = pow2(
1079                   coupSUSYPtr->rvUDD[(id2Abs+1)/2][iSq][(id3Abs+1)/2]);
1080               } else{
1081                 itemp3 = id3Abs;
1082                 itemp1 = id2Abs;
1083                 itemp2 = id1Abs;
1084                 rvfac = pow2(
1085                   coupSUSYPtr->rvUDD[(id2Abs+1)/2][(id2Abs+1)/2][iSq]);
1086               }
1087             }else{
1088               if(itype==1){
1089                 itemp3 = id3Abs;
1090                 itemp1 = id1Abs;
1091                 itemp2 = id2Abs;
1092                 rvfac = pow2(
1093                   coupSUSYPtr->rvUDD[iSq][(id1Abs+1)/2][(id2Abs+1)/2]);
1094               }else if (itype ==2){
1095                 itemp3 = id2Abs;
1096                 itemp1 = id1Abs;
1097                 itemp2 = id3Abs;
1098                 rvfac = pow2(
1099                   coupSUSYPtr->rvUDD[(id3Abs+1)/2][iSq][(id2Abs+1)/2]);
1100               } else{
1101                 itemp3 = id3Abs;
1102                 itemp1 = id1Abs;
1103                 itemp2 = id2Abs;
1104                 rvfac = pow2(
1105                   coupSUSYPtr->rvUDD[(id3Abs+1)/2][(id1Abs+1)/2][iSq]);
1106               }
1107               
1108             }
1109             
1110             m1 = particleDataPtr->m0(itemp1);
1111             m2 = particleDataPtr->m0(itemp2);
1112             m3 = particleDataPtr->m0(itemp3);
1113
1114             m12min = pow2(m1+m2);
1115             m12max = pow2(mHat-m3);
1116
1117             // Ignore mode when 2-body decay is possible
1118             if(mRes > particleDataPtr->m0(idInt) + particleDataPtr->m0(itemp3))
1119               continue;
1120             
1121             // Single diagram squared terms
1122             psi.setInternal(idRes, itemp1, itemp2, itemp3, idInt, 0);
1123             // Mixing with R-states
1124             if(itype == 1)
1125               mixfac1 = norm(coupSUSYPtr->Rusq[idIntRes][iSq+3]); 
1126             else
1127               mixfac1 = norm(coupSUSYPtr->Rdsq[idIntRes][iSq+3]); 
1128             
1129             if(abs(rvfac * mixfac1) > 1.0e-8) {
1130               integral =  integrateGauss(&psi,m12min,m12max,1.0e-4);
1131               widNow += rvfac * mixfac1 * integral;
1132             //   if(DEBUG || idRes == 1000023)
1133             //  cout << scientific << setw(10) <<"Psi: intRes: "<<idInt
1134             //       <<" integral:"<<integral<<" mixfac:"<<mixfac1
1135             //       <<" widNow:"<<widNow<<endl;
1136             }
1137             
1138             // Mixing of diagrams with different internal squarks 
1139             // of same isospin
1140             for (int idIntRes2 = 1; idIntRes2 <= 6; idIntRes2++){
1141               if(idIntRes2 == idIntRes) continue;
1142               int idInt2;
1143               if(itype == 1 ){
1144                 idInt2 = coupSUSYPtr->idSup(idIntRes2);
1145                 mixfac2 = 2.0 * real(coupSUSYPtr->Rusq[idIntRes][iSq+3] 
1146                         * conj(coupSUSYPtr->Rusq[idIntRes2][iSq+3]));
1147               } else {
1148                 idInt2 = coupSUSYPtr->idSdown(idIntRes2);
1149                 mixfac2 = 2.0 * real(coupSUSYPtr->Rdsq[idIntRes][iSq+3]
1150                         * conj(coupSUSYPtr->Rdsq[idIntRes2][iSq+3]));
1151               }
1152
1153               // Ignore mode when 2-body decay is possible
1154               if(mRes > particleDataPtr->m0(idInt2) 
1155                       + particleDataPtr->m0(itemp3)) continue;
1156
1157               upsil.setInternal(idRes,itemp1, itemp2,itemp3,idInt,idInt2);
1158               if(abs(rvfac * mixfac2) > 0.0) {
1159                 integral =  integrateGauss(&upsil,m12min,m12max,1.0e-4);
1160                 widNow += rvfac * mixfac2 * integral;
1161                 // if(DEBUG || idRes == 1000023)
1162                 //   cout << scientific << setw(10) <<"Upsilon: intRes: "
1163                 //        <<idInt<<" intRes2:"<<idInt2<<" integral:"<<integral
1164                 //        <<" mixfac:"<<mixfac2<<" widNow:"<<widNow<<endl;
1165               }
1166             }
1167             
1168             // Interference between two diagrams with quarks 
1169             // of different isospin
1170
1171             for (int idIntRes2 = 1; idIntRes2 <= 6; idIntRes2++){
1172               if(itype != 1 && idIntRes2 == idIntRes) continue;
1173               int idInt2;
1174
1175               for (int iSq2 = 1; iSq2 <= 3; iSq2++){
1176                 if(itype == 1 ){
1177                   idInt2 = coupSUSYPtr->idSdown(idIntRes2);
1178                   mixfac3 = 2.0 * real(coupSUSYPtr->Rusq[idIntRes][iSq+3]  
1179                           * conj(coupSUSYPtr->Rdsq[idIntRes2][iSq2+3]));
1180                 } else {
1181                   idInt2 = coupSUSYPtr->idSdown(idIntRes2);
1182                   mixfac3 = 2.0 * real(coupSUSYPtr->Rdsq[idIntRes][iSq+3]  
1183                           * conj(coupSUSYPtr->Rdsq[idIntRes2][iSq2+3]));
1184                 }
1185
1186                 if(abs(rvfac * mixfac3) > 0.0) {
1187                   phi.setInternal(idRes,itemp1, itemp2,itemp3,idInt,idInt2);
1188                   //integral = 0;
1189                   //if(idIntRes == 2 && iSq2 ==4)
1190                   integral =  integrateGauss(&phi,m12min,m12max,1.0e-4);
1191                   widNow -= rvfac * mixfac2 * integral;
1192                 }
1193               }
1194             }
1195           }
1196         }
1197       }
1198     }
1199     // Normalisation.  Extra factor of 2 to account for the fact that
1200     // d_i, d_j will always be ordered in ascending order. N_c! = 6
1201     widNow *= 12.0 /(pow3(2.0 * M_PI * mHat) * 32.0); 
1202   }
1203
1204   return;
1205 }
1206
1207 //==========================================================================
1208
1209 //  Class ResonanceChar
1210 //  Derived class for Neutralino Resonances
1211 //  Decays into higgses/sleptons not yet implemented
1212
1213 //--------------------------------------------------------------------------
1214
1215 void ResonanceChar::initConstants(){
1216
1217   alpEM = coupSUSYPtr->alphaEM(mHat * mHat);
1218   s2W   = coupSUSYPtr->sin2W;
1219   return;
1220 }
1221  
1222 //--------------------------------------------------------------------------
1223
1224 // Calculate various common prefactors for the current mass.
1225 void  ResonanceChar::calcPreFac(bool){
1226
1227   preFac = alpEM / (8.0 * s2W * pow(mHat,3));
1228   return;
1229 }
1230
1231 //--------------------------------------------------------------------------
1232
1233 // Calculate width for currently considered channel.
1234 void  ResonanceChar::calcWidth(bool){
1235
1236   widNow = 0.0;
1237   if(ps == 0.) return;
1238
1239   if(mult ==2){
1240     double fac = 0.0;
1241     kinFac = mHat * mHat - mf1 * mf1 + mf2 * mf2;
1242     kinFac2 = pow(mHat,4) + pow(mf1,4) - 2.0 * pow(mf2,4) 
1243       + pow2(mHat) * pow2(mf2) + pow2(mf1) 
1244       * pow2(mf2) - 2.0 * pow2(mHat) * pow2(mf1);
1245     
1246     int idChar1 = coupSUSYPtr->typeChar(idRes);
1247     int idChar2 = coupSUSYPtr->typeChar(id1Abs);
1248     int idNeut1 = coupSUSYPtr->typeNeut(id1Abs);
1249     
1250     if(idChar2>0 && id2Abs == 23){
1251       // ~chi_i -> chi_j + Z
1252       fac = kinFac2 * (norm(coupSUSYPtr->OLp[idChar1][idChar2]) 
1253           + norm(coupSUSYPtr->ORp[idChar1][idChar2]));
1254       fac -= 12.0 * mHat * mf1 * pow2(mf2) 
1255            * real(coupSUSYPtr->OLp[idChar1][idChar2] 
1256            * conj(coupSUSYPtr->ORp[idChar1][idChar2]));
1257       fac /= pow2(mf2) * (1.0 - s2W);
1258     }
1259     else if(idNeut1>0 && id2Abs==24){
1260       // ~chi_i -> chi0_j + W- (or c.c.)
1261       
1262       fac  = kinFac2 * (norm(coupSUSYPtr->OL[idNeut1][idChar1]) 
1263            + norm(coupSUSYPtr->OR[idNeut1][idChar1]));
1264       fac -= 12.0 * mHat * mf1 * pow2(mf2) 
1265            * real(coupSUSYPtr->OL[idNeut1][idChar1] 
1266            * conj(coupSUSYPtr->OR[idNeut1][idChar1]));
1267       fac /= pow2(mf2);
1268     }
1269     else if(id1Abs > 1000000 && id1Abs%100 < 7 && id2Abs < 7){
1270       // ~chi0_k -> ~q + q
1271       bool idown = (id1Abs%2 == 1);
1272       int iq = (id2Abs + 1 )/ 2;
1273       int isq = (abs(id1Abs)/1000000 == 2) ? (abs(id1Abs)%10+1)/2 + 3
1274                                            : (abs(id1Abs)%10+1)/2;
1275       
1276       if(idown){
1277         fac  = kinFac * (norm(coupSUSYPtr->LsduX[isq][iq][idChar1]) 
1278              + norm(coupSUSYPtr->RsduX[isq][iq][idChar1]));
1279         fac += 4.0 * mHat * mf2  
1280              * real(coupSUSYPtr->LsduX[isq][iq][idChar1] 
1281              * conj(coupSUSYPtr->RsduX[isq][iq][idChar1]));
1282       }
1283       else{
1284         fac  = kinFac * (norm(coupSUSYPtr->LsudX[isq][iq][idChar1]) 
1285              + norm(coupSUSYPtr->RsudX[isq][iq][idChar1]));
1286         fac += 4.0 * mHat * mf2  
1287              * real(coupSUSYPtr->LsudX[isq][iq][idChar1] 
1288              * conj(coupSUSYPtr->RsudX[isq][iq][idChar1]));
1289       }
1290       fac *= 6.0/(1 - s2W);
1291     }
1292     else if(id1Abs > 1000000 && id1Abs%100 > 10 && id1Abs%100 < 17 
1293       && id2Abs < 17){
1294       // ~chi+_k -> ~l + l
1295       bool idown = id2Abs%2;
1296       int il = (id2Abs - 9)/ 2;
1297       int isl = (abs(id1Abs)/1000000 == 2) ? (abs(id1Abs)%10+1)/2 + 3
1298                                            : (abs(id1Abs)%10+1)/2;
1299       
1300       if(idown){
1301         fac  = kinFac * (norm(coupSUSYPtr->LslvX[isl][il][idChar1]) 
1302              + norm(coupSUSYPtr->RslvX[isl][il][idChar1]));
1303         fac += 4.0 * mHat * mf2 * real(coupSUSYPtr->LslvX[isl][il][idChar1] 
1304              * conj(coupSUSYPtr->RslvX[isl][il][idChar1]));
1305       }
1306       else{
1307         fac = kinFac * (norm(coupSUSYPtr->LsvlX[isl][il][idChar1]));
1308       }
1309       fac *= 2.0/(1 - s2W);
1310     }
1311
1312     // TODO: Decays in higgs
1313     widNow = fac * preFac * ps ;
1314     if(DEBUG) {
1315       cout<<idRes<<":: id1:"<<id1Abs<<" id2:"<<id2Abs<<" Width: ";
1316       cout<<scientific<<widNow<<endl;
1317     }
1318   }else{
1319     //TODO: Implement Chargino 3-body decays
1320   }
1321   return;
1322 }
1323
1324
1325 //==========================================================================
1326 // The ResonanceSlepton class
1327 // Derived class for Slepton (and sneutrino) resonances
1328
1329 //--------------------------------------------------------------------------
1330
1331 // Initialize constants.
1332
1333 void ResonanceSlepton::initConstants() {
1334
1335   // Locally stored properties and couplings.
1336   alpEM = coupSUSYPtr->alphaEM(mHat * mHat);
1337   s2W   = coupSUSYPtr->sin2W;
1338 }
1339
1340 //--------------------------------------------------------------------------
1341
1342 // Calculate various common prefactors for the current mass.
1343
1344 void ResonanceSlepton::calcPreFac(bool) {
1345
1346   // Common coupling factors.
1347   preFac = 1.0 / (s2W * pow(mHat,3));
1348
1349 }
1350
1351 //--------------------------------------------------------------------------
1352
1353 // Calculate width for currently considered channel.
1354
1355 void ResonanceSlepton::calcWidth(bool) {
1356
1357   // Slepton type -- in u_i/d_i and generation
1358   int ksusy = 1000000;
1359   int isl = (abs(idRes)/ksusy == 2) ? (abs(idRes)%10+1)/2 + 3
1360                                     : (abs(idRes)%10+1)/2;
1361   int il = (id2Abs-9)/2;
1362   bool islep = idRes%2;
1363
1364   // Check that mass is above threshold.
1365   if(ps == 0.) return;
1366   else{
1367     // Two-body decays
1368     kinFac = (mHat * mHat - mf1 * mf1 - mf2 * mf2);
1369     
1370     double fac = 0.0 , wid = 0.0;
1371
1372     //Case 1: RPV: To be implemented
1373     //Case 2: slepton + gaugino 
1374
1375     if (id1Abs > ksusy && id2Abs > 10 && id2Abs < 17) {
1376       for(int i=1; i<6 ; i++){
1377         // ~ell/~nu -> ~chi0 + ell/nu
1378         if(coupSUSYPtr->idNeut(i)==id1Abs && idRes%2 == id2Abs%2){
1379           fac = alpEM *  preFac / (2.0 * (1 - s2W));
1380           if(islep)
1381             wid = kinFac * (norm(coupSUSYPtr->LsllX[isl][il][i]) 
1382                 + norm(coupSUSYPtr->RsllX[isl][il][i]))
1383                 - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsllX[isl][il][i] 
1384                 * conj(coupSUSYPtr->RsllX[isl][il][i]));
1385           else
1386             wid = kinFac * (norm(coupSUSYPtr->LsvvX[isl][il][i]) 
1387                 + norm(coupSUSYPtr->RsvvX[isl][il][i]))
1388                 - 4.0 * mHat * mf2 * real(coupSUSYPtr->LsvvX[isl][il][i] 
1389                 * conj(coupSUSYPtr->RsvvX[isl][il][i]));
1390         }
1391         
1392         // ~ell/~nu -> ~chi- + nu/ell
1393         else if (i < 3 && coupSUSYPtr->idChar(i)==id1Abs 
1394           && idRes%2 != id2Abs%2){
1395           
1396           fac = alpEM *  preFac / (4.0 * (1 - s2W));
1397           if(islep)
1398             wid = kinFac * (norm(coupSUSYPtr->LslvX[isl][il][i]) 
1399                 + norm(coupSUSYPtr->RslvX[isl][il][i]))
1400                 - 4.0 * mHat * mf2 * real(coupSUSYPtr->LslvX[isl][il][i] 
1401                 * conj(coupSUSYPtr->RslvX[isl][il][i]));
1402           else
1403             wid = kinFac * (norm(coupSUSYPtr->LslvX[isl][il][i]) 
1404                 + norm(coupSUSYPtr->RslvX[isl][il][i]))
1405                 - 4.0 * mHat * mf2 * real(coupSUSYPtr->LslvX[isl][il][i] 
1406                 * conj(coupSUSYPtr->RslvX[isl][il][i]));
1407         }
1408       }
1409     }
1410     
1411     //Case 3: ~l_i -> ~l_j + Z/W
1412     else if (id1Abs > ksusy+10 && id1Abs%100 < 17 
1413       && (id2Abs == 23 || id2Abs == 24)){
1414       
1415       // factor of lambda^(3/2) = ps^3; 
1416       fac = alpEM * preFac/(16.0 * pow2(mf2) * (1.0 - s2W)) * pow2(ps) ;
1417       
1418       int isl2 = (id1Abs/ksusy == 2) ? (id1Abs%10+1)/2 + 3: (id1Abs%10+1)/2;
1419       
1420       if(id2Abs == 23 && id1Abs%2 == idRes%2){
1421         if(islep)
1422           wid = norm(coupSUSYPtr->LslslZ[isl][isl2] 
1423               + coupSUSYPtr->RslslZ[isl][isl2]);
1424         else
1425           wid = norm(coupSUSYPtr->LsvsvZ[isl][isl2] 
1426               + coupSUSYPtr->RsvsvZ[isl][isl2]);
1427       }
1428       else if (id2Abs == 24 && id1Abs%2 != idRes%2){
1429         if(islep)
1430           wid = norm(coupSUSYPtr->LslsvW[isl2][isl]);
1431         else
1432           wid = norm(coupSUSYPtr->LslsvW[isl][isl2]);
1433       }
1434     }
1435     
1436     // TODO: Case ~l_i -> ~l_j + h/H
1437     
1438     
1439     widNow = fac * wid * ps;
1440     if(DEBUG) cout<<idRes<<":: id1:"<<id1Abs<<" id2:"<<id2Abs
1441                   <<" Width: "<<widNow<<endl;
1442     return;
1443   }
1444         
1445 }
1446
1447 //==========================================================================
1448
1449 // Gaussian Integrator for 3-body decay widths
1450
1451 double SUSYResonanceWidths::integrateGauss(WidthFunction* widthFn, 
1452   double xlo, double xhi, double tol) {
1453
1454   //8-point unweighted
1455   static double x8[4]={0.96028985649753623,
1456                        0.79666647741362674,
1457                        0.52553240991632899, 
1458                        0.18343464249564980};
1459   static double w8[4]={0.10122853629037626,
1460                        0.22238103445337447,
1461                        0.31370664587788729,
1462                        0.36268378337836198};
1463   //16-point unweighted
1464   static double x16[8]={0.98940093499164993, 
1465                        0.94457502307323258, 
1466                        0.86563120238783174, 
1467                        0.75540440835500303, 
1468                        0.61787624440264375, 
1469                        0.45801677765722739,
1470                        0.28160355077925891, 
1471                        0.09501250983763744};
1472   static double w16[8]={0.027152459411754095,
1473                        0.062253523938647893,
1474                        0.095158511682492785,
1475                        0.12462897125553387,
1476                        0.14959598881657673,
1477                        0.16915651939500254,
1478                        0.18260341504492359,
1479                        0.18945061045506850};
1480   //boundary checks
1481   if (xlo == xhi) {
1482     cerr<<"xlo = xhi"<<endl;
1483     return 0.0;
1484   }
1485   if ( xlo > xhi ) {
1486     cerr<<" (integrateGauss:) -> xhi < xlo"<<endl;
1487     return 0.0;
1488   }
1489   //initialize
1490   double sum = 0.0;
1491   double c = 0.001/abs(xhi-xlo);
1492   double zlo = xlo;
1493   double zhi = xhi;
1494     
1495   bool nextbin = true;
1496   
1497   while ( nextbin ) {
1498     
1499     double zmi = 0.5*(zhi+zlo); // midpoint
1500     double zmr = 0.5*(zhi-zlo); // midpoint, relative to zlo
1501     
1502     //calculate 8-point and 16-point quadratures
1503     double s8=0.0;
1504     for (int i=0;i<4;i++) {
1505       double dz = zmr * x8[i];
1506       s8 += w8[i]*(widthFn->function(zmi+dz) + widthFn->function(zmi-dz));
1507     }
1508     s8 *= zmr;
1509     double s16=0.0;
1510     for (int i=0;i<8;i++) {
1511       double dz = zmr * x16[i];
1512       s16 += w16[i]*(widthFn->function(zmi+dz) + widthFn->function(zmi-dz)); 
1513     }
1514     s16 *= zmr;
1515     if (abs(s16-s8) < tol*(1+abs(s16))) { 
1516       //precision in this bin OK, add to cumulative and go to next
1517       nextbin=true;
1518       sum += s16;
1519       //next bin: LO = end of current, HI = end of integration region.
1520       zlo=zhi;
1521       zhi=xhi;
1522       if ( zlo == zhi ) nextbin = false;
1523     } else {
1524       //precision in this bin not OK, subdivide.
1525       if (1.0 + c*abs(zmr) == 1.0) {
1526         cerr << " (integrateGauss:) too high accuracy required"<<endl;
1527         sum = 0.0 ;
1528         break;
1529       }
1530       zhi=zmi;
1531       nextbin=true;
1532     }
1533   }
1534
1535   return sum;
1536 }
1537
1538 //======================================================================
1539
1540 } //end namespace Pythia8
1541
1542