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) 2020 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, 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 "Pythia8/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.01;
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, int iDecNow) {
49 
50  // Loop over all entries to find resonances that should decay.
51  // (Except for iDecNow > 0, where only it will be handled.)
52  int iDec = iDecNow;
53  do {
54  Particle& decayer = process[iDec];
55  if (decayer.isFinal() && decayer.canDecay() && decayer.mayDecay()
56  && decayer.isResonance() ) {
57 
58  // Fill the decaying particle in slot 0 of arrays.
59  id0 = decayer.id();
60  m0 = decayer.m();
61  idProd.resize(0);
62  mProd.resize(0);
63  idProd.push_back( id0 );
64  mProd.push_back( m0 );
65 
66  // Mother flavour - relevant for gamma*/Z0 mixing. (Not always??)
67  int idIn = process[decayer.mother1()].id();
68 
69  // Prepare decay selection.
70  if (!decayer.particleDataEntry().preparePick(id0, m0, idIn)) {
71  ostringstream osWarn;
72  osWarn << "for id = " << id0;
73  infoPtr->errorMsg("Error in ResonanceDecays::next:"
74  " no open decay channel", osWarn.str());
75  return false;
76  }
77 
78  // Pick a decay channel; allow up to ten tries.
79  bool foundChannel = false;
80  for (int iTryChannel = 0; iTryChannel < NTRYCHANNEL; ++iTryChannel) {
81 
82  // Pick decay channel. Find multiplicity.
83  DecayChannel& channel = decayer.particleDataEntry().pickChannel();
84  mult = channel.multiplicity();
85 
86  // Read out flavours.
87  idProd.resize(1);
88  int idNow;
89  for (int i = 1; i <= mult; ++i) {
90  idNow = channel.product(i - 1);
91  if (id0 < 0 && particleDataPtr->hasAnti(idNow)) idNow = -idNow;
92  idProd.push_back( idNow);
93  }
94 
95  // Pick masses. Pick new channel if fail.
96  mProd.resize(1);
97  if (!pickMasses()) continue;
98  foundChannel = true;
99  break;
100  }
101 
102  // Failed to find acceptable decays.
103  if (!foundChannel) {
104  ostringstream osWarn;
105  osWarn << "for id = " << id0;
106  infoPtr->errorMsg("Error in ResonanceDecays::next:"
107  " failed to find workable decay channel", osWarn.str());
108  return false;
109  }
110 
111  // Select colours in decay.
112  if (!pickColours(iDec, process)) return false;
113 
114  // Select four-momenta in decay, boosted to lab frame.
115  pProd.resize(0);
116  pProd.push_back( decayer.p() );
117  if (!pickKinematics()) return false;
118 
119  // Append decay products to the process event record. Set lifetimes.
120  int iFirst = process.size();
121  for (int i = 1; i <= mult; ++i) {
122  process.append( idProd[i], 23, iDec, 0, 0, 0, cols[i], acols[i],
123  pProd[i], mProd[i], m0);
124  }
125  int iLast = process.size() - 1;
126 
127  // Set decay vertex when this is displaced.
128  if (process[iDec].hasVertex() || process[iDec].tau() > 0.) {
129  Vec4 vDec = process[iDec].vDec();
130  for (int i = iFirst; i <= iLast; ++i) process[i].vProd( vDec );
131  }
132 
133  // Set lifetime of daughters.
134  for (int i = iFirst; i <= iLast; ++i)
135  process[i].tau( process[i].tau0() * rndmPtr->exp() );
136 
137  // Modify mother status and daughters.
138  decayer.status(-22);
139  decayer.daughters(iFirst, iLast);
140 
141  // End of loop over all entries.
142  }
143  } while (iDecNow == 0 && ++iDec < process.size());
144 
145  // Done.
146  return true;
147 
148 }
149 
150 //--------------------------------------------------------------------------
151 
152 // Select masses of decay products.
153 
154 bool ResonanceDecays::pickMasses() {
155 
156  // Arrays with properties of particles. Fill with dummy values for mother.
157  vector<bool> useBW;
158  vector<double> m0BW, mMinBW, mMaxBW, widthBW;
159  double mMother = mProd[0];
160  double m2Mother = mMother * mMother;
161  useBW.push_back( false );
162  m0BW.push_back( mMother );
163  mMinBW.push_back( mMother );
164  mMaxBW.push_back( mMother );
165  widthBW.push_back( 0. );
166 
167  // Loop throught products for masses and widths. Set nominal mass.
168  bool useBWNow;
169  double m0Now, mMinNow, mMaxNow, widthNow;
170  for (int i = 1; i <= mult; ++i) {
171  useBWNow = particleDataPtr->useBreitWigner( idProd[i] );
172  m0Now = particleDataPtr->m0( idProd[i] );
173  mMinNow = particleDataPtr->m0Min( idProd[i] );
174  mMaxNow = particleDataPtr->m0Max( idProd[i] );
175  if (useBWNow && mMaxNow < mMinNow) mMaxNow = mMother;
176  widthNow = particleDataPtr->mWidth( idProd[i] );
177  useBW.push_back( useBWNow );
178  m0BW.push_back( m0Now );
179  mMinBW.push_back( mMinNow );
180  mMaxBW.push_back( mMaxNow );
181  widthBW.push_back( widthNow );
182  mProd.push_back( m0Now );
183  }
184 
185  // Find number of Breit-Wigners and summed (minimal) masses.
186  int nBW = 0;
187  double mSum = 0.;
188  double mSumMin = 0.;
189  for (int i = 1; i <= mult; ++i) {
190  if (useBW[i]) ++nBW;
191  mSum += max( m0BW[i], mMinBW[i]);
192  mSumMin += mMinBW[i];
193  }
194 
195  // If sum of minimal masses above mother mass then give up.
196  if (mSumMin + MSAFETY > mMother) return false;
197 
198  // If sum of masses below and no Breit-Wigners then done.
199  if (mSum + 0.5 * MSAFETY < mMother && nBW == 0) return true;
200 
201  // Else if below then retry Breit-Wigners, with simple treshold.
202  if (mSum + MSAFETY < mMother) {
203  double wtMax = 2. * sqrtpos(1. - mSum*mSum / m2Mother);
204  double wt;
205  for (int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
206  if (iTryMasses == NTRYMASSES) return false;
207  mSum = 0.;
208  for (int i = 1; i <= mult; ++i) {
209  if (useBW[i]) mProd[i] = particleDataPtr->mSel( idProd[i] );
210  mSum += mProd[i];
211  }
212  wt = (mSum + 0.5 * MSAFETY < mMother)
213  ? sqrtpos(1. - mSum*mSum / m2Mother) : 0.;
214  if (wt > rndmPtr->flat() * wtMax) break;
215  }
216  return true;
217  }
218 
219  // From now on some particles will have to be forced off shell.
220 
221  // Order Breit-Wigners in decreasing widths. Sum of other masses.
222  vector<int> iBW;
223  double mSum0 = 0.;
224  for (int i = 1; i <= mult; ++i) {
225  if (useBW[i]) iBW.push_back(i);
226  else mSum0 += mProd[i];
227  }
228  for (int i = 1; i < nBW; ++i) {
229  for (int j = i - 1; j >= 0; --j) {
230  if (widthBW[iBW[j+1]] > widthBW[iBW[j]]) swap (iBW[j+1], iBW[j]);
231  else break;
232  }
233  }
234 
235  // Do all but broadest two in increasing-width order. Includes only one.
236  if (nBW != 2) {
237  int iMin = (nBW == 1) ? 0 : 2;
238  for (int i = nBW - 1; i >= iMin; --i) {
239  int iBWi = iBW[i];
240 
241  // Find allowed mass range of current resonance.
242  double mMax = mMother - mSum0 - MSAFETY;
243  if (nBW != 1) for (int j = 0; j < i; ++j) mMax -= mMinBW[iBW[j]];
244  mMax = min( mMaxBW[iBWi], mMax );
245  double mMin = min( mMinBW[iBWi], mMax - MSAFETY);
246  if (mMin < 0.) return false;
247 
248  // Parameters for Breit-Wigner choice, with constrained mass range.
249  double m2Nom = pow2( m0BW[iBWi] );
250  double m2Max = mMax * mMax;
251  double m2Min = mMin * mMin;
252  double mmWid = m0BW[iBWi] * widthBW[iBWi];
253  double atanMin = atan( (m2Min - m2Nom) / mmWid );
254  double atanMax = atan( (m2Max - m2Nom) / mmWid );
255  double atanDif = atanMax - atanMin;
256 
257  // Fail if too narrow mass range; e.g. out in tail of Breit-Wigner.
258  if (atanDif < TINYBWRANGE) return false;
259 
260  // Retry mass according to Breit-Wigner, with simple threshold factor.
261  double mr1 = mSum0*mSum0 / m2Mother;
262  double mr2 = m2Min / m2Mother;
263  double wtMax = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
264  double m2Now, wt;
265  for (int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
266  if (iTryMasses == NTRYMASSES) return false;
267  m2Now = m2Nom + mmWid * tan(atanMin + rndmPtr->flat() * atanDif);
268  mr2 = m2Now / m2Mother;
269  wt = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
270  if (wt > rndmPtr->flat() * wtMax) break;
271  }
272 
273  // Prepare to iterate for more. Done for one Breit-Wigner.
274  mProd[iBWi] = sqrt(m2Now);
275  mSum0 += mProd[iBWi];
276  }
277  if (nBW == 1) return true;
278  }
279 
280  // Left to do two broadest Breit-Wigners correlated, i.e. more realistic.
281  int iBW1 = iBW[0];
282  int iBW2 = iBW[1];
283  int idMother = abs(idProd[0]);
284  int idDau1 = abs(idProd[iBW1]);
285  int idDau2 = abs(idProd[iBW2]);
286 
287  // In some cases known phase-space behaviour; else simple beta factor.
288  int psMode = 1 ;
289  if ( (idMother == 25 || idMother == 35) && idDau1 < 19
290  && idDau2 == idDau1 ) psMode = 3;
291  if ( (idMother == 25 || idMother == 35 )
292  && (idDau1 == 23 || idDau1 == 24) && idDau2 == idDau1 ) psMode = 5;
293  if ( idMother == 36
294  && (idDau1 == 23 || idDau1 == 24) && idDau2 == idDau1 ) psMode = 6;
295 
296  // Find allowed mass ranges. Ensure that they are not closed.
297  double mRem = mMother - mSum0 - MSAFETY;
298  double mMax1 = min( mMaxBW[iBW1], mRem - mMinBW[iBW2] );
299  double mMin1 = min( mMinBW[iBW1], mMax1 - MSAFETY);
300  double mMax2 = min( mMaxBW[iBW2], mRem - mMinBW[iBW1] );
301  double mMin2 = min( mMinBW[iBW2], mMax2 - MSAFETY);
302 
303  // At least one range must extend below half remaining mass.
304  if (mMin1 + mMin2 > mRem) return false;
305  double mMid = 0.5 * mRem;
306  bool hasMid1 = (mMin1 < mMid);
307  bool hasMid2 = (mMin2 < mMid);
308  if (!hasMid1 && !hasMid2) return false;
309 
310  // Parameters for Breit-Wigner choice, with constrained mass range.
311  double m2Nom1 = pow2( m0BW[iBW1] );
312  double m2Max1 = mMax1 * mMax1;
313  double m2Min1 = mMin1 * mMin1;
314  double m2Mid1 = min( mMid * mMid, m2Max1);
315  double mmWid1 = m0BW[iBW1] * widthBW[iBW1];
316  double atanMin1 = atan( (m2Min1 - m2Nom1) / mmWid1 );
317  double atanMax1 = atan( (m2Max1 - m2Nom1) / mmWid1 );
318  double atanMid1 = (hasMid1) ? atan( (m2Mid1 - m2Nom1) / mmWid1 ) : 0.;
319  double m2Nom2 = pow2( m0BW[iBW2] );
320  double m2Max2 = mMax2 * mMax2;
321  double m2Min2 = mMin2 * mMin2;
322  double m2Mid2 = min( mMid * mMid, m2Max2);
323  double mmWid2 = m0BW[iBW2] * widthBW[iBW2];
324  double atanMin2 = atan( (m2Min2 - m2Nom2) / mmWid2 );
325  double atanMax2 = atan( (m2Max2 - m2Nom2) / mmWid2 );
326  double atanMid2 = (hasMid2) ? atan( (m2Mid2 - m2Nom2) / mmWid2 ) : 0.;
327 
328  // Relative weight to pick either below half remaining mass.
329  double probLow1 = (hasMid1) ? 1. : 0.;
330  if (hasMid1 && hasMid2) {
331  double intLow1 = (atanMid1 - atanMin1) * (atanMax2 - atanMin2);
332  double intLow2 = (atanMax1 - atanMin1) * (atanMid2 - atanMin2);
333  probLow1 = intLow1 / (intLow1 + intLow2);
334  }
335 
336  // Maximum matrix element times phase space weight.
337  double m2Rem = mRem * mRem;
338  double mr1 = m2Min1 / m2Rem;
339  double mr2 = m2Min2 / m2Rem;
340  double psMax = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
341  double wtMax = 1.;
342  if (psMode == 1) wtMax = psMax;
343  else if (psMode == 3) wtMax = pow3(psMax);
344  else if (psMode == 5) wtMax = psMax
345  * (pow2(1. - mr1 - mr2) + 8. * mr1 * mr2);
346  else if (psMode == 6) wtMax = pow3(psMax);
347 
348  // Retry mass according to Breit-Wigners, with simple threshold factor.
349  double atanDif1, atanDif2, m2Now1, m2Now2, mNow1, mNow2, ps, wt;
350  for (int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
351  if (iTryMasses == NTRYMASSES) return false;
352 
353  // Pick either below half remaining mass.
354  bool pickLow1 = false;
355  if (rndmPtr->flat() < probLow1) {
356  atanDif1 = atanMid1 - atanMin1;
357  atanDif2 = atanMax2 - atanMin2;
358  pickLow1 = true;
359  } else {
360  atanDif1 = atanMax1 - atanMin1;
361  atanDif2 = atanMid2 - atanMin2;
362  }
363  m2Now1 = m2Nom1 + mmWid1 * tan(atanMin1 + rndmPtr->flat() * atanDif1);
364  m2Now2 = m2Nom2 + mmWid2 * tan(atanMin2 + rndmPtr->flat() * atanDif2);
365  mNow1 = sqrt(m2Now1);
366  mNow2 = sqrt(m2Now2);
367 
368  // Check that intended mass ordering is fulfilled.
369  bool rejectRegion = (pickLow1) ? (mNow1 > mNow2) : (mNow2 > mNow1);
370  if (rejectRegion) continue;
371 
372  // Threshold weight.
373  mr1 = m2Now1 / m2Rem;
374  mr2 = m2Now2 / m2Rem;
375  wt = 0.;
376  if (mNow1 + mNow2 + MSAFETY < mMother) {
377  ps = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
378  wt = 1.;
379  if (psMode == 1) wt = 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 
399 bool 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 antisextet (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[pickA] = 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 
689 bool 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  // Calculate four-momenta and boost to lab frame.
700  pair<Vec4, Vec4> ps = rndmPtr->phaseSpace2(m0, m1, m2);
701  pProd.push_back(ps.first);
702  pProd.push_back(ps.second);
703  pProd[1].bst( pProd[0] );
704  pProd[2].bst( pProd[0] );
705 
706  // Done for two-body decay.
707  return true;
708  }
709 
710  // Description of three-body decays as semi-simple special case.
711  if (mult == 3) {
712 
713  // Masses.
714  m0 = mProd[0];
715  double m1 = mProd[1];
716  double m2 = mProd[2];
717  double m3 = mProd[3];
718  double mDiff = m0 - (m1 + m2 + m3);
719 
720  // Kinematical limits for 2+3 mass. Maximum phase-space weight.
721  double m23Min = m2 + m3;
722  double m23Max = m0 - m1;
723  double p1Max = 0.5 * sqrtpos( (m0 - m1 - m23Min) * (m0 + m1 + m23Min)
724  * (m0 + m1 - m23Min) * (m0 - m1 + m23Min) ) / m0;
725  double p23Max = 0.5 * sqrtpos( (m23Max - m2 - m3) * (m23Max + m2 + m3)
726  * (m23Max + m2 - m3) * (m23Max - m2 + m3) ) / m23Max;
727  double wtPSmax = 0.5 * p1Max * p23Max;
728 
729  // Pick an intermediate mass m23 flat in the allowed range.
730  double wtPS, m23, p1Abs, p23Abs;
731  do {
732  m23 = m23Min + rndmPtr->flat() * mDiff;
733 
734  // Translate into relative momenta and find phase-space weight.
735  p1Abs = 0.5 * sqrtpos( (m0 - m1 - m23) * (m0 + m1 + m23)
736  * (m0 + m1 - m23) * (m0 - m1 + m23) ) / m0;
737  p23Abs = 0.5 * sqrtpos( (m23 - m2 - m3) * (m23 + m2 + m3)
738  * (m23 + m2 - m3) * (m23 - m2 + m3) ) / m23;
739  wtPS = p1Abs * p23Abs;
740 
741  // If rejected, try again with new invariant masses.
742  } while ( wtPS < rndmPtr->flat() * wtPSmax );
743 
744  // Set up m23 -> m2 + m3 isotropic in its rest frame.
745  pair<Vec4, Vec4> ps23 = rndmPtr->phaseSpace2(m23, m2, m3);
746  Vec4 p2(ps23.first);
747  Vec4 p3(ps23.second);
748 
749  // Set up 0 -> 1 + 23 isotropic in its rest frame.
750  pair<Vec4, Vec4> ps123 = rndmPtr->phaseSpace2(m0, m1, m23);
751  pProd.push_back(ps123.first);
752 
753  // Boost 2 + 3 to the 0 rest frame and fill.
754  p2.bst( ps123.second );
755  p3.bst( ps123.second );
756  pProd.push_back( p2 );
757  pProd.push_back( p3 );
758 
759  // Boost from rest frame to lab frame.
760  pProd[1].bst( pProd[0] );
761  pProd[2].bst( pProd[0] );
762  pProd[3].bst( pProd[0] );
763 
764  // Done for three-body decay.
765  return true;
766  }
767 
768  // Do a multibody decay using the M-generator algorithm.
769 
770  // Mother and sum daughter masses.
771  m0 = mProd[0];
772  double mSum = mProd[1];
773  for (int i = 2; i <= mult; ++i) mSum += mProd[i];
774  double mDiff = m0 - mSum;
775 
776  // Begin setup of intermediate invariant masses.
777  vector<double> mInv;
778  for (int i = 0; i <= mult; ++i) mInv.push_back( mProd[i]);
779 
780  // Calculate the maximum weight in the decay.
781  double wtPSmax = 1. / WTCORRECTION[mult];
782  double mMax = mDiff + mProd[mult];
783  double mMin = 0.;
784  for (int i = mult - 1; i > 0; --i) {
785  mMax += mProd[i];
786  mMin += mProd[i+1];
787  double mNow = mProd[i];
788  wtPSmax *= 0.5 * sqrtpos( (mMax - mMin - mNow) * (mMax + mMin + mNow)
789  * (mMax + mMin - mNow) * (mMax - mMin + mNow) ) / mMax;
790  }
791 
792  // Begin loop to find the set of intermediate invariant masses.
793  vector<double> rndmOrd;
794  double wtPS;
795  do {
796  wtPS = 1.;
797 
798  // Find and order random numbers in descending order.
799  rndmOrd.resize(0);
800  rndmOrd.push_back(1.);
801  for (int i = 1; i < mult - 1; ++i) {
802  double rndm = rndmPtr->flat();
803  rndmOrd.push_back(rndm);
804  for (int j = i - 1; j > 0; --j) {
805  if (rndm > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
806  else break;
807  }
808  }
809  rndmOrd.push_back(0.);
810 
811  // Translate into intermediate masses and find weight.
812  for (int i = mult - 1; i > 0; --i) {
813  mInv[i] = mInv[i+1] + mProd[i] + (rndmOrd[i-1] - rndmOrd[i]) * mDiff;
814  wtPS *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
815  * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
816  * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
817  }
818 
819  // If rejected, try again with new invariant masses.
820  } while ( wtPS < rndmPtr->flat() * wtPSmax );
821 
822  // Perform two-particle decays in the respective rest frame.
823  vector<Vec4> pInv;
824  pInv.resize(mult + 1);
825  for (int i = 1; i < mult; ++i) {
826  // Calculate four-momenta
827  pair<Vec4, Vec4> ps = rndmPtr->phaseSpace2(mInv[i], mInv[i+1], mProd[i]);
828  pInv[i+1].p(ps.first);
829  pProd.push_back(ps.second);
830  }
831  pProd.push_back( pInv[mult] );
832 
833  // Boost decay products to the mother rest frame and on to lab frame.
834  pInv[1] = pProd[0];
835  for (int iFrame = mult - 1; iFrame > 0; --iFrame)
836  for (int i = iFrame; i <= mult; ++i) pProd[i].bst(pInv[iFrame]);
837 
838  // Done for multibody decay.
839  return true;
840 
841 }
842 
843 //==========================================================================
844 
845 } // end namespace Pythia8
Definition: AgUStep.h:26