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