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) 2018 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.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, 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 == 2) wtMax = psMax * psMax;
344  else if (psMode == 3) wtMax = pow3(psMax);
345  else if (psMode == 5) wtMax = psMax
346  * (pow2(1. - mr1 - mr2) + 8. * mr1 * mr2);
347  else if (psMode == 6) wtMax = pow3(psMax);
348 
349  // Retry mass according to Breit-Wigners, with simple threshold factor.
350  double atanDif1, atanDif2, m2Now1, m2Now2, mNow1, mNow2, ps, wt;
351  for (int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
352  if (iTryMasses == NTRYMASSES) return false;
353 
354  // Pick either below half remaining mass.
355  bool pickLow1 = false;
356  if (rndmPtr->flat() < probLow1) {
357  atanDif1 = atanMid1 - atanMin1;
358  atanDif2 = atanMax2 - atanMin2;
359  pickLow1 = true;
360  } else {
361  atanDif1 = atanMax1 - atanMin1;
362  atanDif2 = atanMid2 - atanMin2;
363  }
364  m2Now1 = m2Nom1 + mmWid1 * tan(atanMin1 + rndmPtr->flat() * atanDif1);
365  m2Now2 = m2Nom2 + mmWid2 * tan(atanMin2 + rndmPtr->flat() * atanDif2);
366  mNow1 = sqrt(m2Now1);
367  mNow2 = sqrt(m2Now2);
368 
369  // Check that intended mass ordering is fulfilled.
370  bool rejectRegion = (pickLow1) ? (mNow1 > mNow2) : (mNow2 > mNow1);
371  if (rejectRegion) continue;
372 
373  // Threshold weight.
374  mr1 = m2Now1 / m2Rem;
375  mr2 = m2Now2 / m2Rem;
376  wt = 0.;
377  if (mNow1 + mNow2 + MSAFETY < mMother) {
378  ps = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
379  wt = 1.;
380  if (psMode == 1) wt = ps;
381  else if (psMode == 2) wt = ps * ps;
382  else if (psMode == 3) wt = pow3(ps);
383  else if (psMode == 5) wt = ps
384  * (pow2(1. - mr1 - mr2) + 8. * mr1 * mr2);
385  else if (psMode == 6) wt = pow3(ps)*mr1*mr2;
386  }
387  if (wt > rndmPtr->flat() * wtMax) break;
388  }
389  mProd[iBW1] = mNow1;
390  mProd[iBW2] = mNow2;
391 
392  // Done.
393  return true;
394 
395 }
396 
397 //--------------------------------------------------------------------------
398 
399 // Select colours of decay products.
400 
401 bool ResonanceDecays::pickColours(int iDec, Event& process) {
402 
403  // Reset or create arrays with colour info.
404  cols.resize(0);
405  acols.resize(0);
406  vector<int> iTriplet, iAtriplet, iOctet, iDipCol, iDipAcol;
407 
408  // Mother colours already known.
409  int col0 = process[iDec].col();
410  int acol0 = process[iDec].acol();
411  int colType0 = process[iDec].colType();
412  cols.push_back( col0);
413  acols.push_back(acol0);
414 
415  // Loop through all daughters.
416  int colTypeNow;
417  for (int i = 1; i <= mult; ++i) {
418  // Daughter colours initially empty, so that all is set for singlet.
419  cols.push_back(0);
420  acols.push_back(0);
421  // Find character (singlet, triplet, antitriplet, octet) of daughters.
422  colTypeNow = particleDataPtr->colType( idProd[i] );
423  if (colTypeNow == 0);
424  else if (colTypeNow == 1) iTriplet.push_back(i);
425  else if (colTypeNow == -1) iAtriplet.push_back(i);
426  else if (colTypeNow == 2) iOctet.push_back(i);
427  // Add two entries for sextets;
428  else if (colTypeNow == 3) {
429  iTriplet.push_back(i);
430  iTriplet.push_back(i);
431  } else if (colTypeNow == -3) {
432  iAtriplet.push_back(i);
433  iAtriplet.push_back(i);
434  } else {
435  infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
436  " unknown colour type encountered");
437  return false;
438  }
439  }
440 
441  // Check excess of colours and anticolours in final over initial state.
442  int nCol = iTriplet.size();
443  if (colType0 == 1 || colType0 == 2) nCol -= 1;
444  else if (colType0 == 3) nCol -= 2;
445  int nAcol = iAtriplet.size();
446  if (colType0 == -1 || colType0 == 2) nAcol -= 1;
447  else if (colType0 == -3) nAcol -= 2;
448 
449  // If net creation of three colours then find junction kind:
450  // mother is 1 = singlet, triplet, or sextet (no incoming RPV tags)
451  // 3 = antitriplet, octet, or antisextet (acol0 = incoming RPV tag)
452  // 5 = not applicable to decays (needs two incoming RPV tags)
453  if (nCol - nAcol == 3) {
454  int kindJun = (colType0 == 0 || colType0 == 1 || colType0 == 3) ? 1 : 3;
455 
456  // Set colours in three junction legs and store junction.
457  int colJun[3];
458  colJun[0] = (kindJun == 1) ? process.nextColTag() : acol0;
459  colJun[1] = process.nextColTag();
460  colJun[2] = process.nextColTag();
461  process.appendJunction( kindJun, colJun[0], colJun[1], colJun[2]);
462 
463  // Loop over three legs. Remove an incoming anticolour on first leg.
464  for (int leg = 0; leg < 3; ++leg) {
465  if (leg == 0 && kindJun != 1) acol0 = 0;
466 
467  // Pick final-state triplets to carry these new colours.
468  else {
469  int pickT = (iTriplet.size() == 1) ? 0
470  : int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
471  int iPickT = iTriplet[pickT];
472  cols[iPickT] = colJun[leg];
473 
474  // Remove matched triplet and store new colour dipole ends.
475  iTriplet[pickT] = iTriplet.back();
476  iTriplet.pop_back();
477  iDipCol.push_back(iPickT);
478  iDipAcol.push_back(0);
479  }
480  }
481 
482  // Update colour counter. Done with junction.
483  nCol -= 3;
484  }
485 
486  // If net creation of three anticolours then find antijunction kind:
487  // mother is 2 = singlet, antitriplet, or antisextet (no incoming RPV tags)
488  // 4 = triplet, octet, or sextet (col0 = incoming RPV tag)
489  // 6 = not applicable to decays (needs two incoming RPV tags)
490  if (nAcol - nCol == 3) {
491  int kindJun = (colType0 == 0 || colType0 == -1 || colType0 == -3) ? 2 : 4;
492 
493  // Set anticolours in three antijunction legs and store antijunction.
494  int acolJun[3];
495  acolJun[0] = (kindJun == 2) ? process.nextColTag() : col0;
496  acolJun[1] = process.nextColTag();
497  acolJun[2] = process.nextColTag();
498  process.appendJunction( kindJun, acolJun[0], acolJun[1], acolJun[2]);
499 
500  // Loop over three legs. Remove an incoming colour on first leg.
501  for (int leg = 0; leg < 3; ++leg) {
502  if (leg == 0 && kindJun != 2) col0 = 0;
503 
504  // Pick final-state antitriplets to carry these new anticolours.
505  else {
506  int pickA = (iAtriplet.size() == 1) ? 0
507  : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
508  int iPickA = iAtriplet[pickA];
509  acols[iPickA] = acolJun[leg];
510 
511  // Remove matched antitriplet and store new colour dipole ends.
512  iAtriplet[pickA] = iAtriplet.back();
513  iAtriplet.pop_back();
514  iDipCol.push_back(0);
515  iDipAcol.push_back(iPickA);
516  }
517  }
518 
519  // Update anticolour counter. Done with antijunction.
520  nAcol -= 3;
521  }
522 
523  // If colours and anticolours do not match now then unphysical.
524  if (nCol != nAcol) {
525  infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
526  " inconsistent colour tags");
527  return false;
528  }
529 
530  // Pick final-state triplet (if any) to carry initial colour.
531  if (col0 > 0 && iTriplet.size() > 0) {
532  int pickT = (iTriplet.size() == 1) ? 0
533  : int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
534  int iPickT = iTriplet[pickT];
535  cols[iPickT] = col0;
536 
537  // Remove matched triplet and store new colour dipole ends.
538  col0 = 0;
539  iTriplet[pickT] = iTriplet.back();
540  iTriplet.pop_back();
541  iDipCol.push_back(iPickT);
542  iDipAcol.push_back(0);
543  }
544 
545  // Pick final-state antitriplet (if any) to carry initial anticolour.
546  if (acol0 > 0 && iAtriplet.size() > 0) {
547  int pickA = (iAtriplet.size() == 1) ? 0
548  : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
549  int iPickA = iAtriplet[pickA];
550  acols[iPickA] = acol0;
551 
552  // Remove matched antitriplet and store new colour dipole ends.
553  acol0 = 0;
554  iAtriplet[pickA] = iAtriplet.back();
555  iAtriplet.pop_back();
556  iDipCol.push_back(0);
557  iDipAcol.push_back(iPickA);
558  }
559 
560  // Sextets: second final-state triplet (if any)
561  if (acol0 < 0 && iTriplet.size() > 0) {
562  int pickT = (iTriplet.size() == 1) ? 0
563  : int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
564  int iPickT = iTriplet[pickT];
565  cols[iPickT] = -acol0;
566 
567  // Remove matched antitriplet and store new colour dipole ends.
568  acol0 = 0;
569  iTriplet[pickT] = iTriplet.back();
570  iTriplet.pop_back();
571  iDipCol.push_back(iPickT);
572  iDipAcol.push_back(0);
573  }
574 
575  // Sextets: second final-state antitriplet (if any)
576  if (col0 < 0 && iAtriplet.size() > 0) {
577  int pickA = (iAtriplet.size() == 1) ? 0
578  : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
579  int iPickA = iAtriplet[pickA];
580  acols[iPickA] = -col0;
581 
582  // Remove matched triplet and store new colour dipole ends.
583  col0 = 0;
584  iAtriplet[pickA] = iAtriplet.back();
585  iAtriplet.pop_back();
586  iDipCol.push_back(0);
587  iDipAcol.push_back(iPickA);
588  }
589 
590  // Error checks that amount of leftover colours and anticolours match.
591  if ( (iTriplet.size() != iAtriplet.size())
592  || (col0 != 0 && acol0 == 0) || (col0 == 0 && acol0 != 0) ) {
593  infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
594  " inconsistent colour tags");
595  return false;
596  }
597 
598  // Match triplets to antitriplets in the final state.
599  for (int pickT = 0; pickT < int(iTriplet.size()); ++pickT) {
600  int iPickT = iTriplet[pickT];
601  int pickA = (iAtriplet.size() == 1) ? 0
602  : int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
603  int iPickA = iAtriplet[pickA];
604 
605  // Connect pair with new colour tag.
606  cols[iPickT] = process.nextColTag();
607  acols[iPickA] = cols[iPickT];
608 
609  // Remove matched antitriplet and store new colour dipole ends.
610  iAtriplet[pickA] = iAtriplet.back();
611  iAtriplet.pop_back();
612  iDipCol.push_back(iPickT);
613  iDipAcol.push_back(iPickA);
614  }
615 
616  // If no octets are around then matching is done.
617  if (col0 == 0 && acol0 == 0 && iOctet.size() == 0) return true;
618 
619  // If initial-state octet remains then store as (first!) new dipole.
620  if (col0 != 0) {
621  iDipCol.push_back(0);
622  iDipAcol.push_back(0);
623  }
624 
625  // Now attach all final-state octets at random to existing dipoles.
626  for (int i = 0; i < int(iOctet.size()); ++i) {
627  int iOct = iOctet[i];
628 
629  // If no dipole then start new one. (Happens for singlet -> octets.)
630  if (iDipCol.size() == 0) {
631  cols[iOct] = process.nextColTag();
632  acols[iOct] = cols[iOct] ;
633  iDipCol.push_back(iOct);
634  iDipAcol.push_back(iOct);
635  }
636 
637  // Else attach to existing dipole picked at random.
638  else {
639  int pickDip = (iDipCol.size() == 1) ? 0
640  : int( TINY + rndmPtr->flat() * (iDipCol.size() - TINY) );
641 
642  // Case with dipole in initial state: reattach existing colours.
643  if (iDipCol[pickDip] == 0 && iDipAcol[pickDip] == 0) {
644  cols[iOct] = col0;
645  acols[iOct] = acol0;
646  iDipAcol[pickDip] = iOct;
647  iDipCol.push_back(iOct);
648  iDipAcol.push_back(0);
649 
650  // Case with dipole from colour in initial state: also new colour.
651  } else if (iDipAcol[pickDip] == 0) {
652  int iPickCol = iDipCol[pickDip];
653  cols[iOct] = cols[iPickCol];
654  acols[iOct] = process.nextColTag();
655  cols[iPickCol] = acols[iOct];
656  iDipCol[pickDip] = iOct;
657  iDipCol.push_back(iPickCol);
658  iDipAcol.push_back(iOct);
659 
660  // Remaining cases with dipole from anticolour in initial state
661  // or dipole inside final state: also new colour.
662  } else {
663  int iPickAcol = iDipAcol[pickDip];
664  acols[iOct] = acols[iPickAcol];
665  cols[iOct] = process.nextColTag();
666  acols[iPickAcol] = cols[iOct];
667  iDipAcol[pickDip] = iOct;
668  iDipCol.push_back(iOct);
669  iDipAcol.push_back(iPickAcol);
670  }
671  }
672  }
673 
674  // Must now have at least two dipoles (no 1 -> 8 or 8 -> 1).
675  if (iDipCol.size() < 2) {
676  infoPtr->errorMsg("Error in ResonanceDecays::pickColours:"
677  " inconsistent colour tags");
678  return false;
679  }
680 
681  // Done.
682  return true;
683 
684 }
685 
686 //--------------------------------------------------------------------------
687 
688 // Select decay products momenta isotropically in phase space.
689 // Process-dependent angular distributions may be imposed in SigmaProcess.
690 
691 bool ResonanceDecays::pickKinematics() {
692 
693  // Description of two-body decays as simple special case.
694  if (mult == 2) {
695 
696  // Masses.
697  m0 = mProd[0];
698  double m1 = mProd[1];
699  double m2 = mProd[2];
700 
701  // Energies and absolute momentum in the rest frame.
702  double e1 = 0.5 * (m0*m0 + m1*m1 - m2*m2) / m0;
703  double e2 = 0.5 * (m0*m0 + m2*m2 - m1*m1) / m0;
704  double pAbs = 0.5 * sqrtpos( (m0 - m1 - m2) * (m0 + m1 + m2)
705  * (m0 + m1 - m2) * (m0 - m1 + m2) ) / m0;
706 
707  // Pick isotropic angles to give three-momentum.
708  double cosTheta = 2. * rndmPtr->flat() - 1.;
709  double sinTheta = sqrt(1. - cosTheta*cosTheta);
710  double phi = 2. * M_PI * rndmPtr->flat();
711  double pX = pAbs * sinTheta * cos(phi);
712  double pY = pAbs * sinTheta * sin(phi);
713  double pZ = pAbs * cosTheta;
714 
715  // Fill four-momenta in mother rest frame and then boost to lab frame.
716  pProd.push_back( Vec4( pX, pY, pZ, e1) );
717  pProd.push_back( Vec4( -pX, -pY, -pZ, e2) );
718  pProd[1].bst( pProd[0] );
719  pProd[2].bst( pProd[0] );
720 
721  // Done for two-body decay.
722  return true;
723  }
724 
725  // Description of three-body decays as semi-simple special case.
726  if (mult == 3) {
727 
728  // Masses.
729  m0 = mProd[0];
730  double m1 = mProd[1];
731  double m2 = mProd[2];
732  double m3 = mProd[3];
733  double mDiff = m0 - (m1 + m2 + m3);
734 
735  // Kinematical limits for 2+3 mass. Maximum phase-space weight.
736  double m23Min = m2 + m3;
737  double m23Max = m0 - m1;
738  double p1Max = 0.5 * sqrtpos( (m0 - m1 - m23Min) * (m0 + m1 + m23Min)
739  * (m0 + m1 - m23Min) * (m0 - m1 + m23Min) ) / m0;
740  double p23Max = 0.5 * sqrtpos( (m23Max - m2 - m3) * (m23Max + m2 + m3)
741  * (m23Max + m2 - m3) * (m23Max - m2 + m3) ) / m23Max;
742  double wtPSmax = 0.5 * p1Max * p23Max;
743 
744  // Pick an intermediate mass m23 flat in the allowed range.
745  double wtPS, m23, p1Abs, p23Abs;
746  do {
747  m23 = m23Min + rndmPtr->flat() * mDiff;
748 
749  // Translate into relative momenta and find phase-space weight.
750  p1Abs = 0.5 * sqrtpos( (m0 - m1 - m23) * (m0 + m1 + m23)
751  * (m0 + m1 - m23) * (m0 - m1 + m23) ) / m0;
752  p23Abs = 0.5 * sqrtpos( (m23 - m2 - m3) * (m23 + m2 + m3)
753  * (m23 + m2 - m3) * (m23 - m2 + m3) ) / m23;
754  wtPS = p1Abs * p23Abs;
755 
756  // If rejected, try again with new invariant masses.
757  } while ( wtPS < rndmPtr->flat() * wtPSmax );
758 
759  // Set up m23 -> m2 + m3 isotropic in its rest frame.
760  double cosTheta = 2. * rndmPtr->flat() - 1.;
761  double sinTheta = sqrt(1. - cosTheta*cosTheta);
762  double phi = 2. * M_PI * rndmPtr->flat();
763  double pX = p23Abs * sinTheta * cos(phi);
764  double pY = p23Abs * sinTheta * sin(phi);
765  double pZ = p23Abs * cosTheta;
766  double e2 = sqrt( m2*m2 + p23Abs*p23Abs);
767  double e3 = sqrt( m3*m3 + p23Abs*p23Abs);
768  Vec4 p2( pX, pY, pZ, e2);
769  Vec4 p3( -pX, -pY, -pZ, e3);
770 
771  // Set up 0 -> 1 + 23 isotropic in its rest frame.
772  cosTheta = 2. * rndmPtr->flat() - 1.;
773  sinTheta = sqrt(1. - cosTheta*cosTheta);
774  phi = 2. * M_PI * rndmPtr->flat();
775  pX = p1Abs * sinTheta * cos(phi);
776  pY = p1Abs * sinTheta * sin(phi);
777  pZ = p1Abs * cosTheta;
778  double e1 = sqrt( m1*m1 + p1Abs*p1Abs);
779  double e23 = sqrt( m23*m23 + p1Abs*p1Abs);
780  pProd.push_back( Vec4( pX, pY, pZ, e1) );
781 
782  // Boost 2 + 3 to the 0 rest frame and then boost to lab frame.
783  Vec4 p23( -pX, -pY, -pZ, e23);
784  p2.bst( p23 );
785  p3.bst( p23 );
786  pProd.push_back( p2 );
787  pProd.push_back( p3 );
788  pProd[1].bst( pProd[0] );
789  pProd[2].bst( pProd[0] );
790  pProd[3].bst( pProd[0] );
791 
792  // Done for three-body decay.
793  return true;
794  }
795 
796  // Do a multibody decay using the M-generator algorithm.
797 
798  // Mother and sum daughter masses.
799  m0 = mProd[0];
800  double mSum = mProd[1];
801  for (int i = 2; i <= mult; ++i) mSum += mProd[i];
802  double mDiff = m0 - mSum;
803 
804  // Begin setup of intermediate invariant masses.
805  vector<double> mInv;
806  for (int i = 0; i <= mult; ++i) mInv.push_back( mProd[i]);
807 
808  // Calculate the maximum weight in the decay.
809  double wtPSmax = 1. / WTCORRECTION[mult];
810  double mMax = mDiff + mProd[mult];
811  double mMin = 0.;
812  for (int i = mult - 1; i > 0; --i) {
813  mMax += mProd[i];
814  mMin += mProd[i+1];
815  double mNow = mProd[i];
816  wtPSmax *= 0.5 * sqrtpos( (mMax - mMin - mNow) * (mMax + mMin + mNow)
817  * (mMax + mMin - mNow) * (mMax - mMin + mNow) ) / mMax;
818  }
819 
820  // Begin loop to find the set of intermediate invariant masses.
821  vector<double> rndmOrd;
822  double wtPS;
823  do {
824  wtPS = 1.;
825 
826  // Find and order random numbers in descending order.
827  rndmOrd.resize(0);
828  rndmOrd.push_back(1.);
829  for (int i = 1; i < mult - 1; ++i) {
830  double rndm = rndmPtr->flat();
831  rndmOrd.push_back(rndm);
832  for (int j = i - 1; j > 0; --j) {
833  if (rndm > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
834  else break;
835  }
836  }
837  rndmOrd.push_back(0.);
838 
839  // Translate into intermediate masses and find weight.
840  for (int i = mult - 1; i > 0; --i) {
841  mInv[i] = mInv[i+1] + mProd[i] + (rndmOrd[i-1] - rndmOrd[i]) * mDiff;
842  wtPS *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
843  * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
844  * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
845  }
846 
847  // If rejected, try again with new invariant masses.
848  } while ( wtPS < rndmPtr->flat() * wtPSmax );
849 
850  // Perform two-particle decays in the respective rest frame.
851  vector<Vec4> pInv;
852  pInv.resize(mult + 1);
853  for (int i = 1; i < mult; ++i) {
854  double pAbs = 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
855  * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
856  * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
857 
858  // Isotropic angles give three-momentum.
859  double cosTheta = 2. * rndmPtr->flat() - 1.;
860  double sinTheta = sqrt(1. - cosTheta*cosTheta);
861  double phi = 2. * M_PI * rndmPtr->flat();
862  double pX = pAbs * sinTheta * cos(phi);
863  double pY = pAbs * sinTheta * sin(phi);
864  double pZ = pAbs * cosTheta;
865 
866  // Calculate energies, fill four-momenta.
867  double eHad = sqrt( mProd[i]*mProd[i] + pAbs*pAbs);
868  double eInv = sqrt( mInv[i+1]*mInv[i+1] + pAbs*pAbs);
869  pProd.push_back( Vec4( pX, pY, pZ, eHad) );
870  pInv[i+1].p( -pX, -pY, -pZ, eInv);
871  }
872  pProd.push_back( pInv[mult] );
873 
874  // Boost decay products to the mother rest frame and on to lab frame.
875  pInv[1] = pProd[0];
876  for (int iFrame = mult - 1; iFrame > 0; --iFrame)
877  for (int i = iFrame; i <= mult; ++i) pProd[i].bst(pInv[iFrame]);
878 
879  // Done for multibody decay.
880  return true;
881 
882 }
883 
884 //==========================================================================
885 
886 } // end namespace Pythia8
Definition: AgUStep.h:26