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