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) 2012 Philip Ilten, 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 the TauDecays class.
7 
8 #include "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 .initPointers(particleDataPtr, couplingsPtr);
52  hmeTwoFermions2Z2TwoFermions .initPointers(particleDataPtr, couplingsPtr);
53  hmeTwoFermions2Gamma2TwoFermions .initPointers(particleDataPtr,
54  couplingsPtr);
55  hmeTwoFermions2GammaZ2TwoFermions.initPointers(particleDataPtr,
56  couplingsPtr);
57  hmeHiggsEven2TwoFermions .initPointers(particleDataPtr, couplingsPtr);
58  hmeHiggsOdd2TwoFermions .initPointers(particleDataPtr, couplingsPtr);
59  hmeHiggsCharged2TwoFermions .initPointers(particleDataPtr, couplingsPtr);
60  hmeUnpolarized .initPointers(particleDataPtr, couplingsPtr);
61 
62  // Initialize the tau decay matrix elements.
63  hmeTau2Meson .initPointers(particleDataPtr, couplingsPtr);
64  hmeTau2TwoLeptons .initPointers(particleDataPtr, couplingsPtr);
65  hmeTau2TwoMesonsViaVector .initPointers(particleDataPtr, couplingsPtr);
66  hmeTau2TwoMesonsViaVectorScalar.initPointers(particleDataPtr, couplingsPtr);
67  hmeTau2ThreePions .initPointers(particleDataPtr, couplingsPtr);
68  hmeTau2FourPions .initPointers(particleDataPtr, couplingsPtr);
69  hmeTau2PhaseSpace .initPointers(particleDataPtr, couplingsPtr);
70 
71  // User selected tau decay mode.
72  tauMode = settingsPtr->mode("ParticleDecays:sophisticatedTau");
73 
74  // User selected tau decay mother.
75  tauMother = settingsPtr->mode("ParticleDecays:tauMother");
76 
77  // User selected tau polarization.
78  polarization = settingsPtr->parm("ParticleDecays:tauPolarization");
79  }
80 
81 //--------------------------------------------------------------------------
82 
83 // Main method of the TauDecays class. Pass the index of the tau requested
84 // to be decayed along with the event record in which the tau exists. The
85 // tau is then decayed with proper spin correlations as well any partner.
86 // The children of the decays are written to the event record, and if the
87 // decays were succesful, a return value of true is supplied.
88 
89 bool TauDecays::decay(int idxOut1, Event& event) {
90 
91  // Set the first outgoing particle of the hard process.
92  out1 = HelicityParticle(event[idxOut1]);
93  out1.idx = idxOut1;
94 
95  // Find the mediator of the hard process.
96  int idxMediator = out1.mother1();
97  int idxFirstOut1 = idxOut1;
98  while(idxMediator > 0 && event[idxMediator].id() == out1.id()) {
99  idxFirstOut1 = idxMediator;
100  idxMediator = event[idxMediator].mother1();
101  }
102  mediator = HelicityParticle(event[idxMediator]);
103  mediator.idx = idxMediator;
104  mediator.direction = -1;
105 
106  // Find the incoming particles of the hard process.
107  int idxIn1 = mediator.mother1();
108  int idxIn2 = mediator.mother2();
109  while(idxIn1 > 0 && event[idxIn1].id() == mediator.id()) {
110  idxIn1 = event[idxIn1].mother1();
111  idxIn2 = event[idxIn2].mother2();
112  }
113  in1 = HelicityParticle(event[idxIn1]);
114  in1.idx = idxIn1;
115  in1.direction = -1;
116  in2 = HelicityParticle(event[idxIn2]);
117  in2.idx = idxIn2;
118  in2.direction = -1;
119 
120  // Find the second outgoing particle of the hard process.
121  int idxOut2 = (mediator.daughter1() == idxFirstOut1)
122  ? mediator.daughter2() : mediator.daughter1();
123  while (idxOut2 > 0 && event[idxOut2].daughter1() != 0) {
124  idxOut2 = event[idxOut2].daughter1();
125  }
126  out2 = HelicityParticle(event[idxOut2]);
127  out2.idx = idxOut2;
128 
129  // Set the particles vector.
130  particles.clear();
131  particles.push_back(in1);
132  particles.push_back(in2);
133  particles.push_back(out1);
134  particles.push_back(out2);
135 
136  // Set the hard matrix element.
137  // Produced from a W.
138  if (abs(mediator.id()) == 24 &&
139  (abs(in1.id()) <= 18 || abs(in2.id()) <= 18)) {
140  // S-channel production.
141  if (abs(in1.id()) <= 18 && abs(in2.id()) <= 18)
142  hardME = hmeTwoFermions2W2TwoFermions.initChannel(particles);
143  // T-channel production.
144  else {
145  bool fermion = (abs(in1.id()) <= 18) ? 0 : 1;
146  particles[!fermion]
147  = (event[particles[fermion].daughter1()].id() == mediator.id())
148  ? HelicityParticle(event[particles[fermion].daughter2()])
149  : HelicityParticle(event[particles[fermion].daughter1()]);
150  particles[!fermion].direction = 1;
151  if (abs(particles[!fermion].id()) <= 18)
152  hardME = hmeTwoFermions2W2TwoFermions.initChannel(particles);
153  else {
154  infoPtr->errorMsg("Warning in TauDecays::decay: unknown "
155  "tau production, assuming unpolarized and uncorrelated");
156  hardME = hmeUnpolarized.initChannel(particles);
157  }
158  }
159  correlated = false;
160 
161  // Produced from a photon.
162  } else if (abs(mediator.id()) == 22 && abs(in1.id()) <= 18) {
163  particles.push_back(mediator);
164  hardME = hmeTwoFermions2Gamma2TwoFermions.initChannel(particles);
165  correlated = true;
166 
167  // Produced from a photon/Z.
168  } else if (abs(mediator.id()) == 23 && abs(in1.id()) <= 18) {
169  particles.push_back(mediator);
170  if (settingsPtr->mode("WeakZ0:gmZmode") == 0)
171  hardME = hmeTwoFermions2GammaZ2TwoFermions.initChannel(particles);
172  else if (settingsPtr->mode("WeakZ0:gmZmode") == 1)
173  hardME = hmeTwoFermions2Gamma2TwoFermions.initChannel(particles);
174  else if (settingsPtr->mode("WeakZ0:gmZmode") == 2)
175  hardME = hmeTwoFermions2Z2TwoFermions.initChannel(particles);
176  correlated = true;
177 
178  // Produced from a CP even Higgs.
179  } else if (abs(mediator.id()) == 25 || abs(mediator.id()) == 35) {
180  hardME = hmeHiggsEven2TwoFermions.initChannel(particles);
181  correlated = true;
182 
183  // Produced from a CP odd Higgs.
184  } else if (abs(mediator.id()) == 36) {
185  hardME = hmeHiggsOdd2TwoFermions.initChannel(particles);
186  correlated = true;
187 
188  // Produced from a charged Higgs.
189  } else if (abs(mediator.id()) == 37) {
190  hardME = hmeHiggsCharged2TwoFermions.initChannel(particles);
191  correlated = false;
192 
193  // Produced from a D or B meson decay with a single tau.
194  // More particles??
195  } else if ((abs(mediator.id()) == 411 || abs(mediator.id()) == 431
196  || abs(mediator.id()) == 511 || abs(mediator.id()) == 521
197  || abs(mediator.id()) == 531 || abs(mediator.id()) == 541)
198  && abs(out2.id()) == 16) {
199  particles[0] = HelicityParticle( (mediator.id() > 0) ? -5 : 5,
200  0, 0, 0, 0, 0, 0, 0, 0., 0., 0., 0., 0., 0., particleDataPtr);
201  particles[1] = HelicityParticle( (mediator.id() > 0) ? 5 : -5,
202  0, 0, 0, 0, 0, 0, 0, 0., 0., 0., 0., 0., 0., particleDataPtr);
203  particles[0].idx = 0;
204  particles[1].idx = 1;
205 
206  // D or B meson decays into neutrino + tau + meson.
207  if (mediator.daughter1() + 2 == mediator.daughter2()) {
208  particles[0].p(mediator.p());
209  particles[1].direction = 1;
210  particles[1].id(-particles[1].id());
211  particles[1].p(particles[0].p() - particles[2].p() - particles[3].p());
212  }
213 
214  // D or B meson decays into neutrino + tau.
215  else {
216  particles[0].p(mediator.p()/2);
217  particles[1].p(mediator.p()/2);
218  }
219  hardME = hmeTwoFermions2W2TwoFermions.initChannel(particles);
220  correlated = false;
221 
222  // Produced from a virtual photon with correlated taus.
223  } else if (abs(out1.id()) == 15 && abs(out2.id()) == 15) {
224  particles.push_back(mediator);
225  particles[0] = HelicityParticle(-1, 0, 0, 0, 0, 0, 0, 0,
226  mediator.p()/2, 0., 0., particleDataPtr);
227  particles[1] = HelicityParticle(1, 0, 0, 0, 0, 0, 0, 0,
228  mediator.p()/2, 0., 0., particleDataPtr);
229  particles[0].direction = -1;
230  particles[1].direction = -1;
231  particles[0].idx = 0;
232  particles[1].idx = 0;
233  hardME = hmeTwoFermions2Gamma2TwoFermions.initChannel(particles);
234  correlated = true;
235 
236  // Produced from an unknown process, assume unpolarized and uncorrelated.
237  } else {
238  if (tauMode <= 1)
239  infoPtr->errorMsg("Warning in TauDecays::decay: unknown "
240  "tau production, assuming unpolarized and uncorrelated");
241  hardME = hmeUnpolarized.initChannel(particles);
242  correlated = false;
243  }
244 
245  // Pick the first tau to decay.
246  HelicityParticle* tau;
247  int idx;
248  if (correlated) idx = (rndmPtr->flat() < 0.5) ? 2 : 3;
249  else idx = (abs(particles[2].id()) == 15) ? 2 : 3;
250  tau = &particles[idx];
251 
252  // Calculate the density matrix and decay the tau.
253  if ( (tauMode == 2 && abs(mediator.id()) == tauMother) || tauMode == 3) {
254  tau->rho[0][0] = (tau->id() > 0)
255  ? (1 - polarization) / 2 : (1 + polarization) / 2;
256  tau->rho[1][1] = (tau->id() > 0)
257  ? (1 + polarization) / 2 : (1 - polarization) / 2;
258  correlated = false;
259  } else
260  hardME->calculateRho(idx, particles);
261  vector<HelicityParticle> children = createChildren(*tau);
262  if (children.size() == 0) return false;
263 
264  // Decay the first tau.
265  bool accepted = false;
266  int tries = 0;
267  while (!accepted) {
268  isotropicDecay(children);
269  double decayWeight = decayME->decayWeight(children);
270  double decayWeightMax = decayME->decayWeightMax(children);
271  accepted = (rndmPtr->flat() < decayWeight / decayWeightMax);
272  if (decayWeight > decayWeightMax)
273  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
274  "decay weight exceeded in tau decay");
275  if (tries > NTRYDECAY) {
276  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
277  "number of decay attempts exceeded");
278  break;
279  }
280  ++tries;
281  }
282  writeDecay(event,children);
283 
284  // If a correlated second tau exists, decay that tau as well.
285  if (correlated) {
286  idx = (idx == 2) ? 3 : 2;
287  // Calculate the first tau decay matrix.
288  decayME->calculateD(children);
289  // Update the decay matrix for the tau.
290  (*tau).D = children[0].D;
291  // Switch the taus.
292  tau = &particles[idx];
293  // Calculate second tau's density matrix.
294  hardME->calculateRho(idx, particles);
295 
296  // Decay the second tau.
297  children.clear();
298  children = createChildren(*tau);
299  if (children.size() == 0) return false;
300  accepted = false;
301  tries = 0;
302  while (!accepted) {
303  isotropicDecay(children);
304  double decayWeight = decayME->decayWeight(children);
305  double decayWeightMax = decayME->decayWeightMax(children);
306  accepted = (rndmPtr->flat() < decayWeight / decayWeightMax);
307  if (decayWeight > decayWeightMax)
308  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
309  "decay weight exceeded in correlated tau decay");
310  if (tries > NTRYDECAY) {
311  infoPtr->errorMsg("Warning in TauDecays::decay: maximum "
312  "number of decay attempts exceeded");
313  break;
314  }
315  ++tries;
316  }
317  writeDecay(event,children);
318  }
319 
320  // Done.
321  return true;
322 
323 }
324 
325 //--------------------------------------------------------------------------
326 
327 // Given a HelicityParticle parent, select the decay channel and return
328 // a vector of HelicityParticles containing the children, with the parent
329 // particle duplicated in the first entry of the vector.
330 
331 vector<HelicityParticle> TauDecays::createChildren(HelicityParticle parent) {
332 
333  // Initial values.
334  int meMode = 0;
335  vector<HelicityParticle> children;
336 
337  // Set the parent as incoming.
338  parent.direction = -1;
339 
340  // Setup decay data for the decaying particle.
341  ParticleDataEntry decayData = parent.particleDataEntry();
342 
343  // Initialize the decay data.
344  if (!decayData.preparePick(parent.id())) return children;
345 
346  // Try to pick a decay channel.
347  bool decayed = false;
348  int decayTries = 0;
349  while (!decayed && decayTries < NTRYCHANNEL) {
350 
351  // Pick a decay channel.
352  DecayChannel decayChannel = decayData.pickChannel();
353  meMode = decayChannel.meMode();
354  int decayMult = decayChannel.multiplicity();
355 
356  // Select children masses.
357  bool allowed = false;
358  int channelTries = 0;
359  while (!allowed && channelTries < NTRYCHANNEL) {
360  children.resize(0);
361  children.push_back(parent);
362  for (int i = 0; i < decayMult; ++i) {
363  // Grab child ID.
364  int childId = decayChannel.product(i);
365  // Flip sign for anti-particle decay.
366  if (parent.id() < 0 && particleDataPtr->hasAnti(childId))
367  childId = -childId;
368  // Grab child mass.
369  double childMass = particleDataPtr->mass(childId);
370  // Push back the child into the children vector.
371  children.push_back( HelicityParticle(childId, 91, parent.idx, 0, 0,
372  0, 0, 0, 0., 0., 0., 0.,childMass, 0., particleDataPtr) );
373  }
374 
375  // Check there is enough phase space for decay.
376  if (decayMult > 1) {
377  double massDiff = parent.m();
378  for (int i = 0; i < decayMult; ++i) massDiff -= children[i].m();
379  // For now we just check kinematically available.
380  if (massDiff > 0) {
381  allowed = true;
382  decayed = true;
383  }
384  }
385 
386  // End pick a channel.
387  ++channelTries;
388  }
389  ++decayTries;
390  }
391 
392  // Set the decay matrix element.
393  // Two body decays.
394  if (children.size() == 3) {
395  if (meMode == 1521)
396  decayME = hmeTau2Meson.initChannel(children);
397  else decayME = hmeTau2PhaseSpace.initChannel(children);
398  }
399 
400  // Three body decays.
401  else if (children.size() == 4) {
402  // Leptonic decay.
403  if (meMode == 1531)
404  decayME = hmeTau2TwoLeptons.initChannel(children);
405  // Two meson decay via vector meson.
406  else if (meMode == 1532)
407  decayME = hmeTau2TwoMesonsViaVector.initChannel(children);
408  // Two meson decay via vector or scalar meson.
409  else if (meMode == 1533)
410  decayME = hmeTau2TwoMesonsViaVectorScalar.initChannel(children);
411  // Flat phase space.
412  else decayME = hmeTau2PhaseSpace.initChannel(children);
413  }
414 
415  // Four body decays.
416  else if (children.size() == 5) {
417  // Three pion CLEO decay.
418  if (meMode == 1541)
419  decayME = hmeTau2ThreePions.initChannel(children);
420  // Flat phase space.
421  else decayME = hmeTau2PhaseSpace.initChannel(children);
422  }
423 
424  // Five body decays.
425  else if (children.size() == 6) {
426  // Four pion Novosibirsk current.
427  if (meMode == 1551)
428  decayME = hmeTau2FourPions.initChannel(children);
429  // Flat phase space.
430  else decayME = hmeTau2PhaseSpace.initChannel(children);
431  }
432 
433  // Flat phase space.
434  else decayME = hmeTau2PhaseSpace.initChannel(children);
435 
436  // Done.
437  return children;
438 }
439 
440 //--------------------------------------------------------------------------
441 
442 // N-body decay using the M-generator algorithm described in
443 // "Monte Carlo Phase Space" by F. James in CERN 68-15, May 1968. Taken
444 // from ParticleDecays::mGenerator but modified to handle spin particles.
445 // Given a vector of HelicityParticles where the first particle is
446 // the mother, the remaining particles are decayed isotropically.
447 
448 void TauDecays::isotropicDecay(vector<HelicityParticle>& children) {
449 
450  // Mother and sum daughter masses.
451  int decayMult = children.size() - 1;
452  double m0 = children[0].m();
453  double mSum = children[1].m();
454  for (int i = 2; i <= decayMult; ++i) mSum += children[i].m();
455  double mDiff = m0 - mSum;
456 
457  // Begin setup of intermediate invariant masses.
458  vector<double> mInv;
459  for (int i = 0; i <= decayMult; ++i) mInv.push_back( children[i].m());
460 
461  // Calculate the maximum weight in the decay.
462  double wtPS;
463  double wtPSmax = 1. / WTCORRECTION[decayMult];
464  double mMax = mDiff + children[decayMult].m();
465  double mMin = 0.;
466  for (int i = decayMult - 1; i > 0; --i) {
467  mMax += children[i].m();
468  mMin += children[i+1].m();
469  double mNow = children[i].m();
470  wtPSmax *= 0.5 * sqrtpos( (mMax - mMin - mNow) * (mMax + mMin + mNow)
471  * (mMax + mMin - mNow) * (mMax - mMin + mNow) ) / mMax;
472  }
473 
474  // Begin loop to find the set of intermediate invariant masses.
475  vector<double> rndmOrd;
476  do {
477  wtPS = 1.;
478 
479  // Find and order random numbers in descending order.
480  rndmOrd.clear();
481  rndmOrd.push_back(1.);
482  for (int i = 1; i < decayMult - 1; ++i) {
483  double random = rndmPtr->flat();
484  rndmOrd.push_back(random);
485  for (int j = i - 1; j > 0; --j) {
486  if (random > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
487  else break;
488  }
489  }
490  rndmOrd.push_back(0.);
491 
492  // Translate into intermediate masses and find weight.
493  for (int i = decayMult - 1; i > 0; --i) {
494  mInv[i] = mInv[i+1] + children[i].m()
495  + (rndmOrd[i-1] - rndmOrd[i]) * mDiff;
496  wtPS *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - children[i].m())
497  * (mInv[i] + mInv[i+1] + children[i].m())
498  * (mInv[i] + mInv[i+1] - children[i].m())
499  * (mInv[i] - mInv[i+1] + children[i].m()) ) / mInv[i];
500  }
501 
502  // If rejected, try again with new invariant masses.
503  } while ( wtPS < rndmPtr->flat() * wtPSmax );
504 
505  // Perform two-particle decays in the respective rest frame.
506  vector<Vec4> pInv(decayMult + 1);
507  for (int i = 1; i < decayMult; ++i) {
508  double pAbs = 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - children[i].m())
509  * (mInv[i] + mInv[i+1] + children[i].m())
510  * (mInv[i] + mInv[i+1] - children[i].m())
511  * (mInv[i] - mInv[i+1] + children[i].m()) ) / mInv[i];
512 
513  // Isotropic angles give three-momentum.
514  double cosTheta = 2. * rndmPtr->flat() - 1.;
515  double sinTheta = sqrt(1. - cosTheta*cosTheta);
516  double phi = 2. * M_PI * rndmPtr->flat();
517  double pX = pAbs * sinTheta * cos(phi);
518  double pY = pAbs * sinTheta * sin(phi);
519  double pZ = pAbs * cosTheta;
520 
521  // Calculate energies, fill four-momenta.
522  double eHad = sqrt( children[i].m()*children[i].m() + pAbs*pAbs);
523  double eInv = sqrt( mInv[i+1]*mInv[i+1] + pAbs*pAbs);
524  children[i].p( pX, pY, pZ, eHad);
525  pInv[i+1].p( -pX, -pY, -pZ, eInv);
526  }
527 
528  // Boost decay products to the mother rest frame.
529  children[decayMult].p( pInv[decayMult] );
530  for (int iFrame = decayMult - 1; iFrame > 1; --iFrame)
531  for (int i = iFrame; i <= decayMult; ++i)
532  children[i].bst( pInv[iFrame], mInv[iFrame]);
533 
534  // Boost decay products to the current frame.
535  pInv[1].p( children[0].p() );
536  for (int i = 1; i <= decayMult; ++i) children[i].bst( pInv[1], mInv[1] );
537 
538  // Done.
539  return;
540 }
541 
542 //--------------------------------------------------------------------------
543 
544 // Write the vector of HelicityParticles to the event record, excluding the
545 // first particle. Set the lifetime and production vertex of the particles
546 // and mark the first particle of the vector as decayed.
547 
548 void TauDecays::writeDecay(Event& event, vector<HelicityParticle>& children) {
549 
550  // Set additional information and append children to event.
551  int decayMult = children.size() - 1;
552  Vec4 decayVertex = children[0].vDec();
553  for (int i = 1; i <= decayMult; i++) {
554  // Set child lifetime.
555  children[i].tau(children[i].tau0() * rndmPtr->exp());
556  // Set child production vertex.
557  children[i].vProd(decayVertex);
558  // Append child to record.
559  children[i].idx = event.append(children[i]);
560  }
561 
562  // Mark the parent as decayed and set children.
563  event[children[0].idx].statusNeg();
564  event[children[0].idx].daughters(children[1].idx, children[decayMult].idx);
565 
566 }
567 
568 //==========================================================================
569 
570 } // end namespace Pythia8
Definition: AgUStep.h:26