source: HiSusy/trunk/Pythia8/pythia8170/src/ResonanceDecays.cc

Last change on this file was 1, checked in by zerwas, 11 years ago

first import of structure, PYTHIA8 and DELPHES

File size: 30.6 KB
Line 
1// ResonanceDecays.cc is a part of the PYTHIA event generator.
2// Copyright (C) 2012 Torbjorn Sjostrand.
3// PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4// Please respect the MCnet Guidelines, see GUIDELINES for details.
5
6// Function definitions (not found in the header) for
7// the ResonanceDecays class.
8
9#include "ResonanceDecays.h"
10
11namespace Pythia8 {
12
13//==========================================================================
14
15// The ResonanceDecays class.
16// Do all resonance decays sequentially.
17
18//--------------------------------------------------------------------------
19
20// Constants: could be changed here if desired, but normally should not.
21// These are of technical nature, as described for each.
22
23// Number of tries to pick a decay channel.
24const int    ResonanceDecays::NTRYCHANNEL = 10;
25
26// Number of tries to pick a set of daughter masses.
27const int    ResonanceDecays::NTRYMASSES  = 10000;
28
29// Mass above threshold for allowed decays.
30const double ResonanceDecays::MSAFETY     = 0.1; 
31
32// When constrainted kinematics cut high-mass tail of Breit-Wigner.
33const double ResonanceDecays::WIDTHCUT    = 5.;
34
35// Small number (relative to 1) to protect against roundoff errors.
36const double ResonanceDecays::TINY        = 1e-10; 
37
38// Forbid small Breit-Wigner mass range, as mapped onto atan range.
39const double ResonanceDecays::TINYBWRANGE = 1e-8; 
40
41// These numbers are hardwired empirical parameters,
42// intended to speed up the M-generator.
43const double ResonanceDecays::WTCORRECTION[11] = { 1., 1., 1., 
44  2., 5., 15., 60., 250., 1250., 7000., 50000. };
45
46//--------------------------------------------------------------------------
47 
48bool ResonanceDecays::next( Event& process) {
49
50  // Loop over all entries to find resonances that should decay.
51  int iDec = 0;
52  do {
53    Particle& decayer = process[iDec];
54    if (decayer.isFinal() && decayer.canDecay() && decayer.mayDecay() 
55    && decayer.isResonance() ) {
56
57      // Fill the decaying particle in slot 0 of arrays. 
58      id0    = decayer.id();
59      m0     = decayer.m();
60      idProd.resize(0);
61      mProd.resize(0);
62      idProd.push_back( id0 );
63      mProd.push_back( m0 );
64
65      // Mother flavour - relevant for gamma*/Z0 mixing. (Not always??)
66      int idIn = process[decayer.mother1()].id();
67
68      // Prepare decay selection.
69      if (!decayer.particleDataEntry().preparePick(id0, m0, idIn)) {
70        ostringstream osWarn;
71        osWarn << "for id = " << id0;
72        infoPtr->errorMsg("Error in ResonanceDecays::next:"
73          " no open decay channel", osWarn.str());         
74        return false;       
75      }
76
77      // Pick a decay channel; allow up to ten tries.
78      bool foundChannel = false;
79      for (int iTryChannel = 0; iTryChannel < NTRYCHANNEL; ++iTryChannel) {
80
81        // Pick decay channel. Find multiplicity.
82        DecayChannel& channel = decayer.particleDataEntry().pickChannel(); 
83        mult = channel.multiplicity();
84
85        // Read out flavours.
86        idProd.resize(1);
87        int idNow;
88        for (int i = 1; i <= mult; ++i) {
89          idNow = channel.product(i - 1);
90          if (id0 < 0 && particleDataPtr->hasAnti(idNow)) idNow = -idNow;
91          idProd.push_back( idNow);
92        }
93
94        // Pick masses. Pick new channel if fail.
95        if (!pickMasses()) continue;
96        foundChannel = true;
97        break;
98      }
99
100      // Failed to find acceptable decays.
101      if (!foundChannel) {
102        ostringstream osWarn;
103        osWarn << "for id = " << id0;
104        infoPtr->errorMsg("Error in ResonanceDecays::next:"
105          " failed to find workable decay channel", osWarn.str());         
106        return false;
107      }
108
109      // Select colours in decay.
110      if (!pickColours(iDec, process)) return false;
111
112      // Select four-momenta in decay, boosted to lab frame.
113      pProd.resize(0);
114      pProd.push_back( decayer.p() );
115      if (!pickKinematics()) return false;
116
117      // Append decay products to the process event record. Set lifetimes.
118      int iFirst = process.size();
119        for (int i = 1; i <= mult; ++i) {
120          process.append( idProd[i], 23, iDec, 0, 0, 0, cols[i], acols[i], 
121            pProd[i], mProd[i], m0);
122        }
123      int iLast = process.size() - 1;
124
125      // Set decay vertex when this is displaced.
126      if (process[iDec].hasVertex() || process[iDec].tau() > 0.) {
127        Vec4 vDec = process[iDec].vDec();
128        for (int i = iFirst; i <= iLast; ++i) process[i].vProd( vDec );
129      }
130
131      // Set lifetime of daughters.
132      for (int i = iFirst; i <= iLast; ++i) 
133        process[i].tau( process[i].tau0() * rndmPtr->exp() );
134
135      // Modify mother status and daughters.
136      decayer.status(-22);
137      decayer.daughters(iFirst, iLast); 
138                 
139    // End of loop over all entries.
140    }
141  } while (++iDec < process.size());
142
143  // Done.
144  return true;
145
146}
147
148//--------------------------------------------------------------------------
149
150// Select masses of decay products.
151 
152bool ResonanceDecays::pickMasses() {
153
154  // Arrays with properties of particles. Fill with dummy values for mother.
155  vector<bool>   useBW;
156  vector<double> m0BW, mMinBW, mMaxBW, widthBW;
157  double mMother  = mProd[0];
158  double m2Mother = mMother * mMother;
159  useBW.push_back( false );
160  m0BW.push_back( mMother );
161  mMinBW.push_back( mMother );
162  mMaxBW.push_back( mMother );
163  widthBW.push_back( 0. ); 
164
165  // Loop throught products for masses and widths. Set nominal mass.
166  bool   useBWNow; 
167  double m0Now, mMinNow, mMaxNow, widthNow;
168  for (int i = 1; i <= mult; ++i) {
169    useBWNow  = particleDataPtr->useBreitWigner( idProd[i] ); 
170    m0Now     = particleDataPtr->m0( idProd[i] );   
171    mMinNow   = particleDataPtr->m0Min( idProd[i] );   
172    mMaxNow   = particleDataPtr->m0Max( idProd[i] );
173    if (useBWNow && mMaxNow < mMinNow) mMaxNow = mMother;   
174    widthNow  = particleDataPtr->mWidth( idProd[i] );
175    useBW.push_back( useBWNow );
176    m0BW.push_back( m0Now );
177    mMinBW.push_back( mMinNow );
178    mMaxBW.push_back( mMaxNow );
179    widthBW.push_back( widthNow );
180    mProd.push_back( m0Now );
181  }
182
183  // Find number of Breit-Wigners and summed (minimal) masses.
184  int    nBW     = 0;
185  double mSum    = 0.;
186  double mSumMin = 0.;
187  for (int i = 1; i <= mult; ++i) {
188    if (useBW[i]) ++nBW;
189    mSum        += max( m0BW[i], mMinBW[i]); 
190    mSumMin     += mMinBW[i]; 
191  }
192 
193  // If sum of minimal masses above mother mass then give up.
194  if (mSumMin + MSAFETY > mMother) return false;
195
196  // If sum of masses below and no Breit-Wigners then done.
197  if (mSum + 0.5 * MSAFETY < mMother && nBW == 0) return true;
198
199  // Else if below then retry Breit-Wigners, with simple treshold.
200  if (mSum + MSAFETY < mMother) {
201    double wtMax = 2. * sqrtpos(1. - mSum*mSum / m2Mother);
202    double wt;
203    for (int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
204      if (iTryMasses == NTRYMASSES) return false;
205      mSum = 0.;
206      for (int i = 1; i <= mult; ++i) {
207        if (useBW[i])  mProd[i] = particleDataPtr->mass( idProd[i] ); 
208        mSum += mProd[i];   
209      }
210      wt = (mSum + 0.5 * MSAFETY < mMother)
211         ? sqrtpos(1. - mSum*mSum / m2Mother) : 0.;
212      if (wt > rndmPtr->flat() * wtMax) break;
213    } 
214    return true;
215  }
216
217  // From now on some particles will have to be forced off shell.
218
219  // Order Breit-Wigners in decreasing widths. Sum of other masses. 
220  vector<int> iBW;
221  double mSum0 = 0.;
222  for (int i = 1; i <= mult; ++i) {
223    if (useBW[i]) iBW.push_back(i);
224    else          mSum0 += mProd[i]; 
225  }
226  for (int i = 1; i < nBW; ++i) {
227    for (int j = i - 1; j >= 0; --j) {
228      if (widthBW[iBW[j+1]] > widthBW[iBW[j]]) swap (iBW[j+1], iBW[j]);
229      else break;
230    }
231  }
232
233  // Do all but broadest two in increasing-width order. Includes only one.
234  if (nBW != 2) {
235    int iMin = (nBW == 1) ? 0 : 2;
236    for (int i = nBW - 1; i >= iMin; --i) {
237      int iBWi = iBW[i];
238
239      // Find allowed mass range of current resonance.
240      double mMax    = mMother - mSum0 - MSAFETY;
241      if (nBW  != 1) for (int j = 0; j < i; ++j) mMax -= mMinBW[iBW[j]];
242      mMax           = min( mMaxBW[iBWi], mMax );
243      double mMin    = min( mMinBW[iBWi], mMax - MSAFETY);
244      if (mMin < 0.) return false;
245   
246      // Parameters for Breit-Wigner choice, with constrained mass range.
247      double m2Nom   = pow2( m0BW[iBWi] );
248      double m2Max   = mMax * mMax;
249      double m2Min   = mMin * mMin;
250      double mmWid   = m0BW[iBWi] * widthBW[iBWi]; 
251      double atanMin = atan( (m2Min - m2Nom) / mmWid );
252      double atanMax = atan( (m2Max - m2Nom) / mmWid );
253      double atanDif = atanMax - atanMin;
254
255      // Fail if too narrow mass range; e.g. out in tail of Breit-Wigner.
256      if (atanDif < TINYBWRANGE) return false;
257
258      // Retry mass according to Breit-Wigner, with simple threshold factor.
259      double mr1     = mSum0*mSum0 / m2Mother;
260      double mr2     = m2Min / m2Mother;
261      double wtMax   = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
262      double m2Now, wt;
263      for (int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
264        if (iTryMasses == NTRYMASSES) return false;
265        m2Now = m2Nom + mmWid * tan(atanMin + rndmPtr->flat() * atanDif);
266        mr2   = m2Now / m2Mother;
267        wt    = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
268        if (wt > rndmPtr->flat() * wtMax) break;
269      } 
270
271      // Prepare to iterate for more. Done for one Breit-Wigner.
272      mProd[iBWi] = sqrt(m2Now); 
273      mSum0        += mProd[iBWi];
274    }
275    if (nBW == 1) return true;
276  } 
277       
278  // Left to do two broadest Breit-Wigners correlated, i.e. more realistic.
279  int iBW1        = iBW[0];
280  int iBW2        = iBW[1];
281  int idMother    = abs(idProd[0]);
282  int idDau1      = abs(idProd[iBW1]);
283  int idDau2      = abs(idProd[iBW2]);
284
285  // In some cases known phase-space behaviour; else simple beta factor.
286  int psMode      = 1 ; 
287  if ( (idMother == 25 || idMother == 35) && idDau1 < 19 
288    && idDau2 == idDau1 ) psMode = 3; 
289  if ( (idMother == 25 || idMother == 35 ) 
290    && (idDau1 == 23 || idDau1 == 24) && idDau2 == idDau1 ) psMode = 5; 
291  if ( idMother == 36 
292    && (idDau1 == 23 || idDau1 == 24) && idDau2 == idDau1 ) psMode = 6; 
293
294  // Find allowed mass ranges. Ensure that they are not closed.
295  double mRem     = mMother - mSum0 - MSAFETY;
296  double mMax1    = min( mMaxBW[iBW1], mRem - mMinBW[iBW2] );
297  double mMin1    = min( mMinBW[iBW1], mMax1 - MSAFETY);
298  double mMax2    = min( mMaxBW[iBW2], mRem - mMinBW[iBW1] );
299  double mMin2    = min( mMinBW[iBW2], mMax2 - MSAFETY);
300   
301  // At least one range must extend below half remaining mass.
302  if (mMin1 + mMin2 > mRem) return false;
303  double mMid     = 0.5 * mRem;
304  bool   hasMid1  = (mMin1 < mMid);
305  bool   hasMid2  = (mMin2 < mMid);
306  if (!hasMid1 && !hasMid2) return false;
307
308  // Parameters for Breit-Wigner choice, with constrained mass range.
309  double m2Nom1   = pow2( m0BW[iBW1] );
310  double m2Max1   = mMax1 * mMax1;
311  double m2Min1   = mMin1 * mMin1;
312  double m2Mid1   = min( mMid * mMid, m2Max1);
313  double mmWid1   = m0BW[iBW1] * widthBW[iBW1]; 
314  double atanMin1 = atan( (m2Min1 - m2Nom1) / mmWid1 );
315  double atanMax1 = atan( (m2Max1 - m2Nom1) / mmWid1 );
316  double atanMid1 = (hasMid1) ? atan( (m2Mid1 - m2Nom1) / mmWid1 ) : 0.; 
317  double m2Nom2   = pow2( m0BW[iBW2] );
318  double m2Max2   = mMax2 * mMax2;
319  double m2Min2   = mMin2 * mMin2;
320  double m2Mid2   = min( mMid * mMid, m2Max2);
321  double mmWid2   = m0BW[iBW2] * widthBW[iBW2]; 
322  double atanMin2 = atan( (m2Min2 - m2Nom2) / mmWid2 );
323  double atanMax2 = atan( (m2Max2 - m2Nom2) / mmWid2 );
324  double atanMid2 = (hasMid2) ? atan( (m2Mid2 - m2Nom2) / mmWid2 ) : 0.; 
325
326  // Relative weight to pick either below half remaining mass.
327  double probLow1 = (hasMid1) ? 1. : 0.;
328  if (hasMid1 && hasMid2) {
329    double intLow1 = (atanMid1 - atanMin1) * (atanMax2 - atanMin2);
330    double intLow2 = (atanMax1 - atanMin1) * (atanMid2 - atanMin2);
331    probLow1 = intLow1 / (intLow1 + intLow2);
332  }
333
334  // Maximum matrix element times phase space weight.
335  double m2Rem    = mRem * mRem;   
336  double mr1      = m2Min1 / m2Rem;
337  double mr2      = m2Min2 / m2Rem;
338  double psMax    = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 ); 
339  double wtMax   = 1.;
340  if      (psMode == 1) wtMax = psMax;
341  else if (psMode == 2) wtMax = psMax * psMax; 
342  else if (psMode == 3) wtMax = pow3(psMax); 
343  else if (psMode == 5) wtMax = psMax
344    * (pow2(1. - mr1 - mr2) + 8. * mr1 * mr2);
345  else if (psMode == 6) wtMax = pow3(psMax);
346 
347  // Retry mass according to Breit-Wigners, with simple threshold factor.
348  double atanDif1, atanDif2, m2Now1, m2Now2, mNow1, mNow2, ps, wt;
349  for (int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
350    if (iTryMasses == NTRYMASSES) return false;
351 
352    // Pick either below half remaining mass.   
353    bool pickLow1 = false;
354    if (rndmPtr->flat() < probLow1) {
355      atanDif1 = atanMid1 - atanMin1;
356      atanDif2 = atanMax2 - atanMin2;
357      pickLow1 = true;
358    } else {
359      atanDif1 = atanMax1 - atanMin1;
360      atanDif2 = atanMid2 - atanMin2;
361    }
362    m2Now1 = m2Nom1 + mmWid1 * tan(atanMin1 + rndmPtr->flat() * atanDif1);
363    m2Now2 = m2Nom2 + mmWid2 * tan(atanMin2 + rndmPtr->flat() * atanDif2);
364    mNow1  = sqrt(m2Now1);
365    mNow2  = sqrt(m2Now2);
366
367    // Check that intended mass ordering is fulfilled.
368    bool rejectRegion = (pickLow1) ? (mNow1 > mNow2) : (mNow2 > mNow1);
369    if (rejectRegion) continue;
370
371    // Threshold weight.
372    mr1    = m2Now1 / m2Rem;
373    mr2    = m2Now2 / m2Rem;
374    wt     = 0.;
375    if (mNow1 + mNow2 + MSAFETY < mMother) {
376      ps   = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 ); 
377      wt   = 1.;
378      if      (psMode == 1) wt = ps;
379      else if (psMode == 2) wt = ps * ps; 
380      else if (psMode == 3) wt = pow3(ps); 
381      else if (psMode == 5) wt = ps
382        * (pow2(1. - mr1 - mr2) + 8. * mr1 * mr2);
383      else if (psMode == 6) wt = pow3(ps)*mr1*mr2;
384    }
385    if (wt > rndmPtr->flat() * wtMax) break;
386  }
387  mProd[iBW1] = mNow1; 
388  mProd[iBW2] = mNow2; 
389 
390  // Done.
391  return true;
392
393}
394
395//--------------------------------------------------------------------------
396
397// Select colours of decay products.
398 
399bool ResonanceDecays::pickColours(int iDec, Event& process) {
400
401  // Reset or create arrays with colour info.
402  cols.resize(0);
403  acols.resize(0);
404  vector<int> iTriplet, iAtriplet, iOctet, iDipCol, iDipAcol;
405
406  // Mother colours already known.
407  int col0     = process[iDec].col();
408  int acol0    = process[iDec].acol();
409  int colType0 = process[iDec].colType();
410  cols.push_back(  col0);
411  acols.push_back(acol0);
412
413  // Loop through all daughters.
414  int colTypeNow;   
415  for (int i = 1; i <= mult; ++i) {
416    // Daughter colours initially empty, so that all is set for singlet.
417    cols.push_back(0);
418    acols.push_back(0);
419    // Find character (singlet, triplet, antitriplet, octet) of daughters.
420    colTypeNow = particleDataPtr->colType( idProd[i] );
421    if      (colTypeNow ==  0);
422    else if (colTypeNow ==  1) iTriplet.push_back(i);
423    else if (colTypeNow == -1) iAtriplet.push_back(i);
424    else if (colTypeNow ==  2) iOctet.push_back(i);
425    // Add two entries for sextets;
426    else if (colTypeNow ==  3) {
427      iTriplet.push_back(i); 
428      iTriplet.push_back(i);
429    } else if (colTypeNow == -3) {
430      iAtriplet.push_back(i); 
431      iAtriplet.push_back(i);
432    } else {
433      infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
434        " unknown colour type encountered");
435      return false;
436    }
437  }
438
439  // Check excess of colours and anticolours in final over initial state.
440  int nCol = iTriplet.size();
441  if (colType0 == 1 || colType0 == 2) nCol -= 1;
442  else if (colType0 == 3) nCol -= 2;
443  int nAcol = iAtriplet.size();
444  if (colType0 == -1 || colType0 == 2) nAcol -= 1;
445  else if (colType0 == -3) nAcol -= 2;
446
447  // If net creation of three colours then find junction kind:
448  // mother is 1 = singlet, triplet, or sextet (no incoming RPV tags)
449  //           3 = antitriplet, octet, or anti-sextet (acol0 = incoming RPV tag)
450  //           5 = not applicable to decays (needs two incoming RPV tags)
451  if (nCol - nAcol == 3) {
452    int kindJun = (colType0 == 0 || colType0 == 1 || colType0 == 3) ? 1 : 3;
453
454    // Set colours in three junction legs and store junction.
455    int colJun[3];
456    colJun[0] = (kindJun == 1) ? process.nextColTag() : acol0; 
457    colJun[1] = process.nextColTag(); 
458    colJun[2] = process.nextColTag(); 
459    process.appendJunction( kindJun, colJun[0], colJun[1], colJun[2]);
460 
461    // Loop over three legs. Remove an incoming anticolour on first leg.
462    for (int leg = 0; leg < 3; ++leg) {
463      if (leg == 0 && kindJun != 1) acol0 = 0;
464
465      // Pick final-state triplets to carry these new colours.
466      else {     
467        int pickT    = (iTriplet.size() == 1) ? 0
468          : int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
469        int iPickT   = iTriplet[pickT];
470        cols[iPickT] = colJun[leg];
471
472        // Remove matched triplet and store new colour dipole ends.
473        iTriplet[pickT] = iTriplet.back();
474        iTriplet.pop_back();
475        iDipCol.push_back(iPickT);
476        iDipAcol.push_back(0);
477      }
478    }
479
480    // Update colour counter. Done with junction.
481    nCol -= 3;
482  }
483
484  // If net creation of three anticolours then find antijunction kind:
485  // mother is 2 = singlet, antitriplet, or antisextet (no incoming RPV tags)
486  //           4 = triplet, octet, or sextet (col0 = incoming RPV tag)
487  //           6 = not applicable to decays (needs two incoming RPV tags)
488  if (nAcol - nCol == 3) {
489    int kindJun = (colType0 == 0 || colType0 == -1 || colType0 == -3) ? 2 : 4;
490
491    // Set anticolours in three antijunction legs and store antijunction.
492    int acolJun[3];
493    acolJun[0] = (kindJun == 2) ? process.nextColTag() : col0; 
494    acolJun[1] = process.nextColTag(); 
495    acolJun[2] = process.nextColTag(); 
496    process.appendJunction( kindJun, acolJun[0], acolJun[1], acolJun[2]);
497 
498    // Loop over three legs. Remove an incoming colour on first leg.
499    for (int leg = 0; leg < 3; ++leg) {
500      if (leg == 0 && kindJun != 2) col0 = 0;
501
502      // Pick final-state antitriplets to carry these new anticolours.
503      else {     
504        int pickA     = (iAtriplet.size() == 1) ? 0
505          : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
506        int iPickA    = iAtriplet[pickA];
507        acols[iPickA] = acolJun[leg];
508
509        // Remove matched antitriplet and store new colour dipole ends.
510        iAtriplet[pickA] = iAtriplet.back();
511        iAtriplet.pop_back();
512        iDipCol.push_back(0);
513        iDipAcol.push_back(iPickA);
514      }
515    }
516
517    // Update anticolour counter. Done with antijunction.
518    nAcol -= 3;
519  }
520
521  // If colours and anticolours do not match now then unphysical.
522  if (nCol != nAcol) {
523    infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
524      " inconsistent colour tags");
525    return false;
526  }
527
528  // Pick final-state triplet (if any) to carry initial colour.
529  if (col0 > 0 && iTriplet.size() > 0) {
530    int pickT    = (iTriplet.size() == 1) ? 0
531      : int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
532    int iPickT = iTriplet[pickT];
533    cols[iPickT] = col0;
534
535    // Remove matched triplet and store new colour dipole ends.
536    col0 = 0;   
537    iTriplet[pickT] = iTriplet.back();
538    iTriplet.pop_back();
539    iDipCol.push_back(iPickT);
540    iDipAcol.push_back(0);
541  }
542
543  // Pick final-state antitriplet (if any) to carry initial anticolour.
544  if (acol0 > 0 && iAtriplet.size() > 0) {
545    int pickA = (iAtriplet.size() == 1) ? 0
546      : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
547    int iPickA = iAtriplet[pickA];
548    acols[iPickA] = acol0;
549
550    // Remove matched antitriplet and store new colour dipole ends.
551    acol0 = 0;   
552    iAtriplet[pickA] = iAtriplet.back();
553    iAtriplet.pop_back();
554    iDipCol.push_back(0);
555    iDipAcol.push_back(iPickA);
556  }
557
558  // Sextets: second final-state triplet (if any)
559  if (acol0 < 0 && iTriplet.size() > 0) {
560    int pickT = (iTriplet.size() == 1) ? 0
561      : int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
562    int iPickT = iTriplet[pickT];
563    cols[iPickT] = -acol0;
564
565    // Remove matched antitriplet and store new colour dipole ends.
566    acol0 = 0;   
567    iTriplet[pickT] = iTriplet.back();
568    iTriplet.pop_back();
569    iDipCol.push_back(iPickT);
570    iDipAcol.push_back(0);
571  }
572
573  // Sextets: second final-state antitriplet (if any)
574  if (col0 < 0 && iAtriplet.size() > 0) {
575    int pickA    = (iAtriplet.size() == 1) ? 0
576      : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
577    int iPickA = iAtriplet[pickA];
578    acols[iPickA] = -col0;
579
580    // Remove matched triplet and store new colour dipole ends.
581    col0 = 0;   
582    iAtriplet[pickA] = iAtriplet.back();
583    iAtriplet.pop_back();
584    iDipCol.push_back(0);
585    iDipAcol.push_back(iPickA);
586  }
587
588  // Error checks that amount of leftover colours and anticolours match.
589  if ( (iTriplet.size() != iAtriplet.size())
590    || (col0 != 0 && acol0 == 0) || (col0 == 0 && acol0 != 0) ) {
591    infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
592      " inconsistent colour tags");
593    return false;
594  }
595
596  // Match triplets to antitriplets in the final state.
597  for (int pickT = 0; pickT < int(iTriplet.size()); ++pickT) {
598    int iPickT = iTriplet[pickT];   
599    int pickA  = (iAtriplet.size() == 1) ? 0
600      : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
601    int iPickA = iAtriplet[pickA];
602
603    // Connect pair with new colour tag.
604    cols[iPickT]  = process.nextColTag(); 
605    acols[iPickA] = cols[iPickT];
606
607    // Remove matched antitriplet and store new colour dipole ends.
608    iAtriplet[pickT] = iAtriplet.back();
609    iAtriplet.pop_back();
610    iDipCol.push_back(iPickT);
611    iDipAcol.push_back(iPickA);
612  }
613
614  // If no octets are around then matching is done.
615  if (col0 == 0 && acol0 == 0 && iOctet.size() == 0) return true;
616
617  // If initial-state octet remains then store as (first!) new dipole.
618  if (col0 != 0) {
619    iDipCol.push_back(0);
620    iDipAcol.push_back(0);
621  }   
622 
623  // Now attach all final-state octets at random to existing dipoles.
624  for (int i = 0; i < int(iOctet.size()); ++i) {
625    int iOct = iOctet[i];
626
627    // If no dipole then start new one. (Happens for singlet -> octets.)
628    if (iDipCol.size() == 0) {     
629      cols[iOct]  = process.nextColTag();
630      acols[iOct] = cols[iOct] ;
631      iDipCol.push_back(iOct);
632      iDipAcol.push_back(iOct);
633    }
634
635    // Else attach to existing dipole picked at random.
636    else { 
637      int pickDip = (iDipCol.size() == 1) ? 0
638        : int( TINY + rndmPtr->flat() * (iDipCol.size() - TINY) );
639
640      // Case with dipole in initial state: reattach existing colours.
641      if (iDipCol[pickDip] == 0 && iDipAcol[pickDip] == 0) {
642        cols[iOct]        = col0;
643        acols[iOct]       = acol0;
644        iDipAcol[pickDip] = iOct;
645        iDipCol.push_back(iOct);
646        iDipAcol.push_back(0);
647
648      // Case with dipole from colour in initial state: also new colour.
649      } else if (iDipAcol[pickDip] == 0) {
650        int iPickCol      = iDipCol[pickDip];
651        cols[iOct]        = cols[iPickCol];
652        acols[iOct]       = process.nextColTag();
653        cols[iPickCol]    = acols[iOct];
654        iDipCol[pickDip]  = iOct;
655        iDipCol.push_back(iPickCol);
656        iDipAcol.push_back(iOct);
657
658      // Remaining cases with dipole from anticolour in initial state
659      // or dipole inside final state: also new colour.
660      } else {
661        int iPickAcol     = iDipAcol[pickDip];
662        acols[iOct]       = acols[iPickAcol];
663        cols[iOct]        = process.nextColTag();
664        acols[iPickAcol]  = cols[iOct];
665        iDipAcol[pickDip] = iOct;
666        iDipCol.push_back(iOct);
667        iDipAcol.push_back(iPickAcol);
668      }
669    }
670  }
671 
672  // Must now have at least two dipoles (no 1 -> 8 or 8 -> 1).
673  if (iDipCol.size() < 2) {
674    infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
675      " inconsistent colour tags");
676    return false;
677  }
678
679  // Done.
680  return true;
681
682}
683
684//--------------------------------------------------------------------------
685
686// Select decay products momenta isotropically in phase space.
687// Process-dependent angular distributions may be imposed in SigmaProcess.
688 
689bool ResonanceDecays::pickKinematics() {
690
691  // Description of two-body decays as simple special case.
692  if (mult == 2) {
693
694    // Masses.
695    m0          = mProd[0];
696    double m1   = mProd[1];   
697    double m2   = mProd[2];   
698
699    // Energies and absolute momentum in the rest frame.
700    double e1   = 0.5 * (m0*m0 + m1*m1 - m2*m2) / m0;
701    double e2   = 0.5 * (m0*m0 + m2*m2 - m1*m1) / m0;
702    double pAbs = 0.5 * sqrtpos( (m0 - m1 - m2) * (m0 + m1 + m2)
703      * (m0 + m1 - m2) * (m0 - m1 + m2) ) / m0; 
704
705    // Pick isotropic angles to give three-momentum.
706    double cosTheta = 2. * rndmPtr->flat() - 1.;
707    double sinTheta = sqrt(1. - cosTheta*cosTheta);
708    double phi      = 2. * M_PI * rndmPtr->flat();
709    double pX       = pAbs * sinTheta * cos(phi); 
710    double pY       = pAbs * sinTheta * sin(phi); 
711    double pZ       = pAbs * cosTheta; 
712
713    // Fill four-momenta in mother rest frame and then boost to lab frame.
714    pProd.push_back( Vec4(  pX,  pY,  pZ, e1) );
715    pProd.push_back( Vec4( -pX, -pY, -pZ, e2) );
716    pProd[1].bst( pProd[0] );
717    pProd[2].bst( pProd[0] );
718
719    // Done for two-body decay.
720    return true;
721  }
722
723  // Description of three-body decays as semi-simple special case.
724  if (mult == 3) {
725
726    // Masses.
727    m0             = mProd[0];
728    double m1      = mProd[1];   
729    double m2      = mProd[2];   
730    double m3      = mProd[3]; 
731    double mDiff   = m0 - (m1 + m2 + m3);
732
733    // Kinematical limits for 2+3 mass. Maximum phase-space weight.
734    double m23Min  = m2 + m3;
735    double m23Max  = m0 - m1;
736    double p1Max   = 0.5 * sqrtpos( (m0 - m1 - m23Min) * (m0 + m1 + m23Min)
737      * (m0 + m1 - m23Min) * (m0 - m1 + m23Min) ) / m0; 
738    double p23Max  = 0.5 * sqrtpos( (m23Max - m2 - m3) * (m23Max + m2 + m3)
739      * (m23Max + m2 - m3) * (m23Max - m2 + m3) ) / m23Max;
740    double wtPSmax = 0.5 * p1Max * p23Max;
741
742    // Pick an intermediate mass m23 flat in the allowed range.
743    double wtPS, m23, p1Abs, p23Abs;
744    do {     
745      m23 = m23Min + rndmPtr->flat() * mDiff;
746
747      // Translate into relative momenta and find phase-space weight.
748      p1Abs  = 0.5 * sqrtpos( (m0 - m1 - m23) * (m0 + m1 + m23)
749        * (m0 + m1 - m23) * (m0 - m1 + m23) ) / m0; 
750      p23Abs = 0.5 * sqrtpos( (m23 - m2 - m3) * (m23 + m2 + m3)
751        * (m23 + m2 - m3) * (m23 - m2 + m3) ) / m23;
752      wtPS   = p1Abs * p23Abs;
753
754    // If rejected, try again with new invariant masses.
755    } while ( wtPS < rndmPtr->flat() * wtPSmax ); 
756
757    // Set up m23 -> m2 + m3 isotropic in its rest frame.
758    double cosTheta = 2. * rndmPtr->flat() - 1.;
759    double sinTheta = sqrt(1. - cosTheta*cosTheta);
760    double phi      = 2. * M_PI * rndmPtr->flat();
761    double pX       = p23Abs * sinTheta * cos(phi); 
762    double pY       = p23Abs * sinTheta * sin(phi); 
763    double pZ       = p23Abs * cosTheta; 
764    double e2       = sqrt( m2*m2 + p23Abs*p23Abs);
765    double e3       = sqrt( m3*m3 + p23Abs*p23Abs);
766    Vec4 p2(  pX,  pY,  pZ, e2);
767    Vec4 p3( -pX, -pY, -pZ, e3);
768
769    // Set up 0 -> 1 + 23 isotropic in its rest frame.
770    cosTheta        = 2. * rndmPtr->flat() - 1.;
771    sinTheta        = sqrt(1. - cosTheta*cosTheta);
772    phi             = 2. * M_PI * rndmPtr->flat();
773    pX              = p1Abs * sinTheta * cos(phi); 
774    pY              = p1Abs * sinTheta * sin(phi); 
775    pZ              = p1Abs * cosTheta; 
776    double e1       = sqrt( m1*m1 + p1Abs*p1Abs);
777    double e23      = sqrt( m23*m23 + p1Abs*p1Abs);
778    pProd.push_back( Vec4( pX, pY, pZ, e1) );
779
780    // Boost 2 + 3 to the 0 rest frame and then boost to lab frame.
781    Vec4 p23( -pX, -pY, -pZ, e23);
782    p2.bst( p23 );
783    p3.bst( p23 );
784    pProd.push_back( p2 );
785    pProd.push_back( p3 );
786    pProd[1].bst( pProd[0] );
787    pProd[2].bst( pProd[0] );
788    pProd[3].bst( pProd[0] );
789
790    // Done for three-body decay.
791    return true;
792  }
793
794  // Do a multibody decay using the M-generator algorithm.
795
796  // Mother and sum daughter masses.
797  m0             = mProd[0];
798  double mSum    = mProd[1];
799  for (int i = 2; i <= mult; ++i) mSum += mProd[i]; 
800  double mDiff   = m0 - mSum;
801   
802  // Begin setup of intermediate invariant masses.
803  vector<double> mInv;
804  for (int i = 0; i <= mult; ++i) mInv.push_back( mProd[i]);
805
806  // Calculate the maximum weight in the decay.
807  double wtPSmax = 1. / WTCORRECTION[mult];
808  double mMax    = mDiff + mProd[mult];
809  double mMin    = 0.; 
810  for (int i = mult - 1; i > 0; --i) {
811    mMax        += mProd[i];
812    mMin        += mProd[i+1];
813    double mNow  = mProd[i];
814    wtPSmax *= 0.5 * sqrtpos( (mMax - mMin - mNow) * (mMax + mMin + mNow)
815    * (mMax + mMin - mNow) * (mMax - mMin + mNow) ) / mMax; 
816  }
817
818  // Begin loop to find the set of intermediate invariant masses.
819  vector<double> rndmOrd;
820  double wtPS;
821  do {
822    wtPS  = 1.;
823
824    // Find and order random numbers in descending order.
825    rndmOrd.resize(0);
826    rndmOrd.push_back(1.);
827    for (int i = 1; i < mult - 1; ++i) { 
828      double rndm = rndmPtr->flat();
829      rndmOrd.push_back(rndm);
830      for (int j = i - 1; j > 0; --j) {
831        if (rndm > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
832        else break;
833      } 
834    }
835    rndmOrd.push_back(0.);
836 
837    // Translate into intermediate masses and find weight.
838    for (int i = mult - 1; i > 0; --i) {
839      mInv[i] = mInv[i+1] + mProd[i] + (rndmOrd[i-1] - rndmOrd[i]) * mDiff; 
840      wtPS   *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i]) 
841        * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i]) 
842        * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i]; 
843    }
844
845  // If rejected, try again with new invariant masses.
846  } while ( wtPS < rndmPtr->flat() * wtPSmax ); 
847
848  // Perform two-particle decays in the respective rest frame.
849  vector<Vec4> pInv;
850  pInv.resize(mult + 1);
851  for (int i = 1; i < mult; ++i) {
852    double pAbs = 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i]) 
853      * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
854      * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i]; 
855
856    // Isotropic angles give three-momentum.
857    double cosTheta = 2. * rndmPtr->flat() - 1.;
858    double sinTheta = sqrt(1. - cosTheta*cosTheta);
859    double phi      = 2. * M_PI * rndmPtr->flat();
860    double pX       = pAbs * sinTheta * cos(phi); 
861    double pY       = pAbs * sinTheta * sin(phi); 
862    double pZ       = pAbs * cosTheta; 
863
864    // Calculate energies, fill four-momenta.
865    double eHad     = sqrt( mProd[i]*mProd[i] + pAbs*pAbs);
866    double eInv     = sqrt( mInv[i+1]*mInv[i+1] + pAbs*pAbs);
867    pProd.push_back( Vec4( pX, pY, pZ, eHad) );
868    pInv[i+1].p( -pX, -pY, -pZ, eInv);
869  }       
870  pProd.push_back( pInv[mult] );
871 
872  // Boost decay products to the mother rest frame and on to lab frame.
873  pInv[1] = pProd[0];
874  for (int iFrame = mult - 1; iFrame > 0; --iFrame) 
875    for (int i = iFrame; i <= mult; ++i) pProd[i].bst(pInv[iFrame]);
876
877  // Done for multibody decay.
878  return true;
879
880}
881
882//==========================================================================
883
884} // end namespace Pythia8
Note: See TracBrowser for help on using the repository browser.