StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TauDecays.cc
1 // TauDecays.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Philip Ilten, 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 the TauDecays class.
7 
8 #include "Pythia8/TauDecays.h"
9 
10 namespace Pythia8 {
11 
12 //==========================================================================
13 
14 // The TauDecays class.
15 
16 //--------------------------------------------------------------------------
17 
18 // Constants: could be changed here if desired, but normally should not.
19 // These are of technical nature, as described for each.
20 
21 // Number of times to try a decay channel.
22 const int TauDecays::NTRYCHANNEL = 10;
23 
24 // Number of times to try a decay sampling.
25 const int TauDecays::NTRYDECAY = 10000;
26 
27 // These numbers are hardwired empirical parameters,
28 // intended to speed up the M-generator.
29 const double TauDecays::WTCORRECTION[11] = { 1., 1., 1.,
30  2., 5., 15., 60., 250., 1250., 7000., 50000. };
31 
32 //--------------------------------------------------------------------------
33 
34 // Initialize the TauDecays class with the necessary pointers to info,
35 // particle data, random numbers, and Standard Model couplings.
36 // Additionally, the necessary matrix elements are initialized with the
37 // Standard Model couplings, and particle data pointers.
38 
39 void TauDecays::init() {
40 
41  // Initialize the hard matrix elements.
42  hmeTwoFermions2W2TwoFermions
43  .initPointers(particleDataPtr, coupSMPtr, settingsPtr);
44  hmeTwoFermions2GammaZ2TwoFermions
45  .initPointers(particleDataPtr, coupSMPtr, settingsPtr);
46  hmeW2TwoFermions
47  .initPointers(particleDataPtr, coupSMPtr, settingsPtr);
48  hmeZ2TwoFermions
49  .initPointers(particleDataPtr, coupSMPtr, settingsPtr);
50  hmeGamma2TwoFermions
51  .initPointers(particleDataPtr, coupSMPtr);
52  hmeHiggs2TwoFermions
53  .initPointers(particleDataPtr, coupSMPtr, settingsPtr);
54 
55  // Initialize the tau decay matrix elements.
56  hmeTau2Meson .initPointers(particleDataPtr, coupSMPtr);
57  hmeTau2TwoLeptons .initPointers(particleDataPtr, coupSMPtr);
58  hmeTau2TwoMesonsViaVector .initPointers(particleDataPtr, coupSMPtr);
59  hmeTau2TwoMesonsViaVectorScalar.initPointers(particleDataPtr, coupSMPtr);
60  hmeTau2ThreePions .initPointers(particleDataPtr, coupSMPtr);
61  hmeTau2ThreeMesonsWithKaons .initPointers(particleDataPtr, coupSMPtr);
62  hmeTau2ThreeMesonsGeneric .initPointers(particleDataPtr, coupSMPtr);
63  hmeTau2TwoPionsGamma .initPointers(particleDataPtr, coupSMPtr);
64  hmeTau2FourPions .initPointers(particleDataPtr, coupSMPtr);
65  hmeTau2FivePions .initPointers(particleDataPtr, coupSMPtr);
66  hmeTau2PhaseSpace .initPointers(particleDataPtr, coupSMPtr);
67 
68  // User selected tau settings.
69  tauExt = mode("TauDecays:externalMode");
70  tauMode = mode("TauDecays:mode");
71  tauMother = mode("TauDecays:tauMother");
72  tauPol = parm("TauDecays:tauPolarization");
73 
74  // Parameters to determine if correlated partner should decay.
75  limitTau0 = flag("ParticleDecays:limitTau0");
76  tau0Max = parm("ParticleDecays:tau0Max");
77  limitTau = flag("ParticleDecays:limitTau");
78  tauMax = parm("ParticleDecays:tauMax");
79  limitRadius = flag("ParticleDecays:limitRadius");
80  rMax = parm("ParticleDecays:rMax");
81  limitCylinder = flag("ParticleDecays:limitCylinder");
82  xyMax = parm("ParticleDecays:xyMax");
83  zMax = parm("ParticleDecays:zMax");
84  limitDecay = limitTau0 || limitTau || limitRadius || limitCylinder;
85 }
86 
87 //--------------------------------------------------------------------------
88 
89 // Main method of the TauDecays class. Pass the index of the tau requested
90 // to be decayed along with the event record in which the tau exists. The
91 // tau is then decayed with proper spin correlations as well any partner.
92 // The children of the decays are written to the event record, and if the
93 // decays were succesful, a return value of true is supplied.
94 
95 bool TauDecays::decay(int idxOut1, Event& event) {
96 
97  // Set the outgoing particles of the hard process.
98  out1 = HelicityParticle(event[idxOut1]);
99  int idxOut1Top = out1.iTopCopyId();
100  vector<int> sistersOut1 = event[idxOut1Top].sisterList();
101  int idxOut2Top = idxOut1Top;
102  if (sistersOut1.size() == 1) idxOut2Top = sistersOut1[0];
103  else {
104  // If more then one sister, select by preference tau, nu_tau, lep, nu_lep.
105  int tau(-1), tnu(-1), lep(-1), lnu(-1);
106  for (int i = 0; i < int(sistersOut1.size()); ++i) {
107  int sn = out1.id() == 15 ? -1 : 1;
108  int id = event[sistersOut1[i]].id();
109  if (id == sn * 15 && tau == -1) tau = sistersOut1[i];
110  else if (id == sn * 16 && tnu == -1) tnu = sistersOut1[i];
111  else if ((id == sn * 11 || (id == sn * 13)) && lep == -1)
112  lep = sistersOut1[i];
113  else if ((id == sn * 12 || (id == sn * 14)) && lnu == -1)
114  lnu = sistersOut1[i];
115  }
116  if (tau > 0) idxOut2Top = tau;
117  else if (tnu > 0) idxOut2Top = tnu;
118  else if (lep > 0) idxOut2Top = lep;
119  else if (lnu > 0) idxOut2Top = lnu;
120  }
121  int idxOut2 = event[idxOut2Top].iBotCopyId();
122  out2 = HelicityParticle(event[idxOut2]);
123 
124  // Set the mediator of the hard process.
125  int idxMediator = event[idxOut1Top].mother1();
126  mediator = HelicityParticle(event[idxMediator]);
127  mediator.direction = -1;
128  if (mediator.m() < out1.m() + out2.m()) {
129  Vec4 p = out1.p() + out2.p();
130  mediator.p(p);
131  mediator.m(p.mCalc());
132  }
133 
134  // Set the incoming particles of the hard process.
135  int idxMediatorTop = mediator.iTopCopyId();
136  int idxIn1 = event[idxMediatorTop].mother1();
137  int idxIn2 = event[idxMediatorTop].mother2();
138  in1 = HelicityParticle(event[idxIn1]);
139  in1.direction = -1;
140  in2 = HelicityParticle(event[idxIn2]);
141  in2.direction = -1;
142 
143  // Set the particles vector.
144  particles.clear();
145  particles.push_back(in1);
146  particles.push_back(in2);
147  particles.push_back(out1);
148  particles.push_back(out2);
149 
150  // Determine if correlated (allow lepton flavor violating partner).
151  correlated = false;
152  if (idxOut1 != idxOut2 &&
153  (abs(out2.id()) == 11 || abs(out2.id()) == 13 || abs(out2.id()) == 15)) {
154  correlated = true;
155  // Check partner vertex is within limits.
156  if (limitTau0 && out2.tau0() > tau0Max) correlated = false;
157  else if (limitTau && out2.tau() > tauMax) correlated = false;
158  else if (limitRadius && pow2(out2.xDec()) + pow2(out2.yDec())
159  + pow2(out2.zDec()) > pow2(rMax)) correlated = false;
160  else if (limitCylinder && (pow2(out2.xDec()) + pow2(out2.yDec())
161  > pow2(xyMax) || abs(out2.zDec()) > zMax))
162  correlated = false;
163  // Check partner can decay.
164  else if (!out2.canDecay()) correlated = false;
165  else if (!out2.mayDecay()) correlated = false;
166  }
167 
168  // Set the production mechanism.
169  bool known = false;
170  hardME = 0;
171  if (tauMode == 4) known = internalMechanism(event);
172  else if (tauMode == 5) known = externalMechanism(event);
173  else {
174  if ((tauMode == 2 && abs(mediator.id()) == tauMother) || tauMode == 3) {
175  known = true;
176  correlated = false;
177  double sign = out1.id() == -15 ? -1 : 1;
178  particles[2].rho[0][0] = (1 - sign * tauPol) / 2;
179  particles[2].rho[1][1] = (1 + sign * tauPol) / 2;
180  } else {
181  if (!externalMechanism(event)) known = internalMechanism(event);
182  else known = true;
183  }
184  }
185 
186  // Catch unknown production mechanims.
187  if (!known) {
188  particles[1] = mediator;
189  if (abs(mediator.id()) == 22)
190  hardME = hmeGamma2TwoFermions.initChannel(particles);
191  else if (abs(mediator.id()) == 23 || abs(mediator.id()) == 32)
192  hardME = hmeZ2TwoFermions.initChannel(particles);
193  else if (abs(mediator.id()) == 24 || abs(mediator.id()) == 34)
194  hardME = hmeW2TwoFermions.initChannel(particles);
195  else if (correlated) {
196  Vec4 p = out1.p() + out2.p();
197  particles[1] = HelicityParticle(22, -22, idxIn1, idxIn2, idxOut1,
198  idxOut2, 0, 0, p, p.mCalc(), 0, particleDataPtr);
199  hardME = hmeGamma2TwoFermions.initChannel(particles);
200  infoPtr->errorMsg("Warning in TauDecays::decay: unknown correlated "
201  "tau production, assuming from unpolarized photon");
202  } else {
203  infoPtr->errorMsg("Warning in TauDecays::decay: unknown uncorrelated "
204  "tau production, assuming unpolarized");
205  }
206  }
207 
208  // Undecay correlated partner if already decayed.
209  if (correlated && !out2.isFinal()) event[out2.index()].undoDecay();
210 
211  // Pick the first tau to decay.
212  HelicityParticle* tau;
213  int idx = 2;
214  if (correlated) idx = (rndmPtr->flat() < 0.5) ? 2 : 3;
215  tau = &particles[idx];
216 
217  // Calculate the density matrix (if needed) and select channel.
218  if (hardME) hardME->calculateRho(idx, particles);
219  vector<HelicityParticle> children = createChildren(*tau);
220  if (children.size() == 0) return false;
221 
222  // Decay the first tau.
223  bool accepted = false;
224  int tries = 0;
225  while (!accepted) {
226  isotropicDecay(children);
227  double decayWeight = decayME->decayWeight(children);
228  double decayWeightMax = decayME->decayWeightMax(children);
229  accepted = (rndmPtr->flat() < decayWeight / decayWeightMax);
230  if (decayWeight > decayWeightMax)
231  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
232  "decay weight exceeded in tau decay");
233  if (tries > NTRYDECAY) {
234  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
235  "number of decay attempts exceeded");
236  break;
237  }
238  ++tries;
239  }
240  writeDecay(event,children);
241 
242  // If a correlated second tau exists, decay that tau as well.
243  if (correlated) {
244  idx = (idx == 2) ? 3 : 2;
245  // Calculate the first tau decay matrix.
246  decayME->calculateD(children);
247  // Update the decay matrix for the tau.
248  tau->D = children[0].D;
249  // Switch the taus.
250  tau = &particles[idx];
251  // Calculate second tau's density matrix.
252  hardME->calculateRho(idx, particles);
253 
254  // Decay the second tau.
255  children.clear();
256  children = createChildren(*tau);
257  if (children.size() == 0) return false;
258  accepted = false;
259  tries = 0;
260  while (!accepted) {
261  isotropicDecay(children);
262  double decayWeight = decayME->decayWeight(children);
263  double decayWeightMax = decayME->decayWeightMax(children);
264  accepted = (rndmPtr->flat() < decayWeight / decayWeightMax);
265  if (decayWeight > decayWeightMax)
266  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
267  "decay weight exceeded in correlated tau decay");
268  if (tries > NTRYDECAY) {
269  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
270  "number of decay attempts exceeded");
271  break;
272  }
273  ++tries;
274  }
275  writeDecay(event,children);
276  }
277 
278  // Done.
279  return true;
280 
281 }
282 
283 //--------------------------------------------------------------------------
284 
285 // Determine the tau polarization and tau decay correlation using the internal
286 // helicity matrix elements.
287 
288 bool TauDecays::internalMechanism(Event&) {
289 
290  // Flag if process is known.
291  bool known = true;
292 
293  // Produced from a photon, Z, or Z'.
294  if (abs(mediator.id()) == 22 || abs(mediator.id()) == 23 ||
295  abs(mediator.id()) == 32) {
296  // Produced from fermions: s-channel.
297  if (abs(in1.id()) <= 18 && abs(in2.id()) <= 18 && in1.daughter2() == 0 &&
298  in2.daughter2() == 0 && in1.daughter1() == in2.daughter1()) {
299  particles.push_back(mediator);
300  hardME = hmeTwoFermions2GammaZ2TwoFermions.initChannel(particles);
301  // Unknown photon production.
302  } else known = false;
303 
304  // Produced from a W or W'.
305  } else if (abs(mediator.id()) == 24 || abs(mediator.id()) == 34) {
306  // Produced from fermions: s-channel.
307  if (abs(in1.id()) <= 18 && abs(in2.id()) <= 18 && in1.daughter2() == 0 &&
308  in2.daughter2() == 0 && in1.daughter1() == in2.daughter1()) {
309  particles.push_back(mediator);
310  hardME = hmeTwoFermions2W2TwoFermions.initChannel(particles);
311  // Unknown W production.
312  } else known = false;
313 
314  // Produced from a Higgs.
315  } else if (abs(mediator.id()) == 25 || abs(mediator.id()) == 35 ||
316  abs(mediator.id()) == 36 || abs(mediator.id()) == 37) {
317  particles[1] = mediator;
318  hardME = hmeHiggs2TwoFermions.initChannel(particles);
319 
320  // Produced from a D or B hadron decay with a single tau.
321  } else if ((abs(mediator.id()) == 411 || abs(mediator.id()) == 431
322  || abs(mediator.id()) == 511 || abs(mediator.id()) == 521
323  || abs(mediator.id()) == 531 || abs(mediator.id()) == 541
324  || (abs(mediator.id()) > 5100 && abs(mediator.id()) < 5600) )
325  && abs(out2.id()) == 16) {
326  int idBmother = (mediator.id() > 0) ? -5 : 5;
327  if (abs(mediator.id()) > 5100) idBmother = -idBmother;
328  particles[0] = HelicityParticle( idBmother, 0, 0, 0, 0, 0, 0, 0,
329  0., 0., 0., 0., 0., 0., particleDataPtr);
330  particles[1] = HelicityParticle( -idBmother, 0, 0, 0, 0, 0, 0, 0,
331  0., 0., 0., 0., 0., 0., particleDataPtr);
332  particles[0].index(-1);
333  particles[1].index(-1);
334 
335  // D or B meson decays into neutrino + tau + meson.
336  if (mediator.daughter1() + 2 == mediator.daughter2()) {
337  particles[0].p(mediator.p());
338  particles[1].direction = 1;
339  particles[1].id(-particles[1].id());
340  particles[1].p(particles[0].p() - particles[2].p() - particles[3].p());
341  }
342 
343  // D or B meson decays into neutrino + tau.
344  else {
345  particles[0].p(mediator.p()/2);
346  particles[1].p(mediator.p()/2);
347  }
348  hardME = hmeTwoFermions2W2TwoFermions.initChannel(particles);
349 
350  // Unknown production.
351  } else known = false;
352  return known;
353 
354 }
355 
356 //--------------------------------------------------------------------------
357 
358 // Determine the tau polarization and tau decay correlation using the provided
359 // SPINUP digits.
360 
361 bool TauDecays::externalMechanism(Event &event) {
362 
363  // Flag if process is known.
364  bool known = true;
365 
366  // Uncorrelated, take directly from SPINUP if valid.
367  if (tauExt == 0) correlated = false;
368  if (!correlated) {
369  double spinup = particles[2].pol();
370  if (abs(spinup) > 1.001) spinup = event[particles[2].iTopCopyId()].pol();
371  if (abs(spinup) > 1.001) known = false;
372  else {
373  particles[2].rho[0][0] = (1 - spinup) / 2;
374  particles[2].rho[1][1] = (1 + spinup) / 2;
375  }
376 
377  // Correlated, try mother.
378  } else if (tauExt == 1) {
379  double spinup = mediator.pol();
380  if (abs(spinup) > 1.001) spinup = event[mediator.iTopCopyId()].pol();
381  if (abs(spinup) > 1.001) spinup = 0;
382  if (mediator.rho.size() > 1) {
383  mediator.rho[0][0] = (1 - spinup) / mediator.spinStates();
384  mediator.rho[1][1] = (1 + spinup) / mediator.spinStates();
385  }
386  particles[1] = mediator;
387  if (abs(mediator.id()) == 22)
388  hardME = hmeGamma2TwoFermions.initChannel(particles);
389  else if (abs(mediator.id()) == 23 || abs(mediator.id()) == 32)
390  hardME = hmeZ2TwoFermions.initChannel(particles);
391  else if (abs(mediator.id()) == 24 || abs(mediator.id()) == 34)
392  hardME = hmeZ2TwoFermions.initChannel(particles);
393  else if (abs(mediator.id()) == 25 || abs(mediator.id()) == 35 ||
394  abs(mediator.id()) == 36 || abs(mediator.id()) == 37)
395  hardME = hmeHiggs2TwoFermions.initChannel(particles);
396  else known = false;
397 
398  // Unknown mechanism.
399  } else known = false;
400  return known;
401 
402 }
403 
404 //--------------------------------------------------------------------------
405 
406 // Given a HelicityParticle parent, select the decay channel and return
407 // a vector of HelicityParticles containing the children, with the parent
408 // particle duplicated in the first entry of the vector.
409 
410 vector<HelicityParticle> TauDecays::createChildren(HelicityParticle parent) {
411 
412  // Initial values.
413  int meMode = 0;
414  vector<HelicityParticle> children;
415 
416  // Set the parent as incoming.
417  parent.direction = -1;
418 
419  // Setup decay data for the decaying particle.
420  ParticleDataEntry decayData = parent.particleDataEntry();
421 
422  // Initialize the decay data.
423  if (!decayData.preparePick(parent.id())) return children;
424 
425  // Try to pick a decay channel.
426  bool decayed = false;
427  int decayTries = 0;
428  while (!decayed && decayTries < NTRYCHANNEL) {
429 
430  // Pick a decay channel.
431  DecayChannel decayChannel = decayData.pickChannel();
432  meMode = decayChannel.meMode();
433  int decayMult = decayChannel.multiplicity();
434 
435  // Select children masses.
436  bool allowed = false;
437  int channelTries = 0;
438  while (!allowed && channelTries < NTRYCHANNEL) {
439  children.resize(0);
440  children.push_back(parent);
441  for (int i = 0; i < decayMult; ++i) {
442  // Grab child ID.
443  int childId = decayChannel.product(i);
444  // Flip sign for anti-particle decay.
445  if (parent.id() < 0 && particleDataPtr->hasAnti(childId))
446  childId = -childId;
447  // Grab child mass.
448  double childMass = particleDataPtr->mSel(childId);
449  // Push back the child into the children vector.
450  children.push_back( HelicityParticle(childId, 91, parent.index(), 0, 0,
451  0, 0, 0, 0., 0., 0., 0.,childMass, 0., particleDataPtr) );
452  }
453 
454  // Check there is enough phase space for decay.
455  if (decayMult > 1) {
456  double massDiff = parent.m();
457  for (int i = 0; i < decayMult; ++i) massDiff -= children[i].m();
458  // For now we just check kinematically available.
459  if (massDiff > 0) {
460  allowed = true;
461  decayed = true;
462  }
463  }
464 
465  // End pick a channel.
466  ++channelTries;
467  }
468  ++decayTries;
469  }
470 
471  // Swap the children ordering for muons.
472  if (parent.idAbs() == 13 && children.size() == 4 && meMode == 22)
473  swap(children[1], children[3]);
474 
475  // Set the decay matrix element.
476  // Two body decays.
477  if (children.size() == 3) {
478  if (meMode == 1521)
479  decayME = hmeTau2Meson.initChannel(children);
480  else decayME = hmeTau2PhaseSpace.initChannel(children);
481  }
482 
483  // Three body decays.
484  else if (children.size() == 4) {
485  // Leptonic decay.
486  if (meMode == 1531 || (parent.idAbs() == 13 && meMode == 22))
487  decayME = hmeTau2TwoLeptons.initChannel(children);
488  // Two meson decay via vector meson.
489  else if (meMode == 1532)
490  decayME = hmeTau2TwoMesonsViaVector.initChannel(children);
491  // Two meson decay via vector or scalar meson.
492  else if (meMode == 1533)
493  decayME = hmeTau2TwoMesonsViaVectorScalar.initChannel(children);
494  // Flat phase space.
495  else decayME = hmeTau2PhaseSpace.initChannel(children);
496  }
497 
498  // Four body decays.
499  else if (children.size() == 5) {
500  // Three pion CLEO decay.
501  if (meMode == 1541)
502  decayME = hmeTau2ThreePions.initChannel(children);
503  // Three meson decay with one or more kaons decay.
504  else if (meMode == 1542)
505  decayME = hmeTau2ThreeMesonsWithKaons.initChannel(children);
506  // Generic three meson decay.
507  else if (meMode == 1543)
508  decayME = hmeTau2ThreeMesonsGeneric.initChannel(children);
509  // Two pions and photon decay.
510  else if (meMode == 1544)
511  decayME = hmeTau2TwoPionsGamma.initChannel(children);
512  // Flat phase space.
513  else decayME = hmeTau2PhaseSpace.initChannel(children);
514  }
515 
516  // Five body decays.
517  else if (children.size() == 6) {
518  // Four pion Novosibirsk current.
519  if (meMode == 1551)
520  decayME = hmeTau2FourPions.initChannel(children);
521  // Flat phase space.
522  else decayME = hmeTau2PhaseSpace.initChannel(children);
523  }
524 
525  // Six body decays.
526  else if (children.size() == 7) {
527  // Four pion Novosibirsk current.
528  if (meMode == 1561)
529  decayME = hmeTau2FivePions.initChannel(children);
530  // Flat phase space.
531  else decayME = hmeTau2PhaseSpace.initChannel(children);
532  }
533 
534  // Flat phase space.
535  else decayME = hmeTau2PhaseSpace.initChannel(children);
536 
537  // Done.
538  return children;
539 }
540 
541 //--------------------------------------------------------------------------
542 
543 // N-body decay using the M-generator algorithm described in
544 // "Monte Carlo Phase Space" by F. James in CERN 68-15, May 1968. Taken
545 // from ParticleDecays::mGenerator but modified to handle spin particles.
546 // Given a vector of HelicityParticles where the first particle is
547 // the mother, the remaining particles are decayed isotropically.
548 
549 void TauDecays::isotropicDecay(vector<HelicityParticle>& children) {
550 
551  // Mother and sum daughter masses.
552  int decayMult = children.size() - 1;
553  double m0 = children[0].m();
554  double mSum = children[1].m();
555  for (int i = 2; i <= decayMult; ++i) mSum += children[i].m();
556  double mDiff = m0 - mSum;
557 
558  // Begin setup of intermediate invariant masses.
559  vector<double> mInv;
560  for (int i = 0; i <= decayMult; ++i) mInv.push_back( children[i].m());
561 
562  // Calculate the maximum weight in the decay.
563  double wtPS;
564  double wtPSmax = 1. / WTCORRECTION[decayMult];
565  double mMax = mDiff + children[decayMult].m();
566  double mMin = 0.;
567  for (int i = decayMult - 1; i > 0; --i) {
568  mMax += children[i].m();
569  mMin += children[i+1].m();
570  double mNow = children[i].m();
571  wtPSmax *= 0.5 * sqrtpos( (mMax - mMin - mNow) * (mMax + mMin + mNow)
572  * (mMax + mMin - mNow) * (mMax - mMin + mNow) ) / mMax;
573  }
574 
575  // Begin loop to find the set of intermediate invariant masses.
576  vector<double> rndmOrd;
577  do {
578  wtPS = 1.;
579 
580  // Find and order random numbers in descending order.
581  rndmOrd.clear();
582  rndmOrd.push_back(1.);
583  for (int i = 1; i < decayMult - 1; ++i) {
584  double random = rndmPtr->flat();
585  rndmOrd.push_back(random);
586  for (int j = i - 1; j > 0; --j) {
587  if (random > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
588  else break;
589  }
590  }
591  rndmOrd.push_back(0.);
592 
593  // Translate into intermediate masses and find weight.
594  for (int i = decayMult - 1; i > 0; --i) {
595  mInv[i] = mInv[i+1] + children[i].m()
596  + (rndmOrd[i-1] - rndmOrd[i]) * mDiff;
597  wtPS *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - children[i].m())
598  * (mInv[i] + mInv[i+1] + children[i].m())
599  * (mInv[i] + mInv[i+1] - children[i].m())
600  * (mInv[i] - mInv[i+1] + children[i].m()) ) / mInv[i];
601  }
602 
603  // If rejected, try again with new invariant masses.
604  } while ( wtPS < rndmPtr->flat() * wtPSmax );
605 
606  // Perform two-particle decays in the respective rest frame.
607  vector<Vec4> pInv(decayMult + 1);
608  for (int i = 1; i < decayMult; ++i) {
609  // Fill four-momenta
610  pair<Vec4, Vec4> ps =
611  rndmPtr->phaseSpace2(mInv[i], mInv[i+1], children[i].m());
612  pInv[i+1].p(ps.first);
613  children[i].p(ps.second);
614  }
615 
616  // Boost decay products to the mother rest frame.
617  children[decayMult].p( pInv[decayMult] );
618  for (int iFrame = decayMult - 1; iFrame > 1; --iFrame)
619  for (int i = iFrame; i <= decayMult; ++i)
620  children[i].bst( pInv[iFrame], mInv[iFrame]);
621 
622  // Boost decay products to the current frame.
623  pInv[1].p( children[0].p() );
624  for (int i = 1; i <= decayMult; ++i) children[i].bst( pInv[1], mInv[1] );
625 
626  // Done.
627  return;
628 }
629 
630 //--------------------------------------------------------------------------
631 
632 // Write the vector of HelicityParticles to the event record, excluding the
633 // first particle. Set the lifetime and production vertex of the particles
634 // and mark the first particle of the vector as decayed.
635 
636 void TauDecays::writeDecay(Event& event, vector<HelicityParticle>& children) {
637 
638  // Set additional information and append children to event.
639  int decayMult = children.size() - 1;
640  Vec4 decayVertex = children[0].vDec();
641  for (int i = 1; i <= decayMult; i++) {
642  // Set child lifetime.
643  children[i].tau(children[i].tau0() * rndmPtr->exp());
644  // Set child production vertex.
645  children[i].vProd(decayVertex);
646  // Append child to record.
647  children[i].index(event.append(children[i]));
648  }
649 
650  // Mark the parent as decayed and set children.
651  event[children[0].index()].statusNeg();
652  event[children[0].index()].daughters(children[1].index(),
653  children[decayMult].index());
654 
655 }
656 
657 //==========================================================================
658 
659 } // end namespace Pythia8
Definition: AgUStep.h:26