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