11#include <Pythia8/Pythia.h>
13#include <TClonesArray.h>
14#include <TDatabasePDG.h>
16#include <TLorentzVector.h>
17#include <TObjString.h>
22#include <TVirtualMC.h>
24using namespace Pythia8;
27 double flat() {
return gRandom->Rndm(); }
47 fPythia8->Pythia8()->readString(
"SoftQCD:elastic = on");
50 fPythia8->Pythia8()->readString(
"ParticleDecays:limitRadius = on");
51 fPythia8->Pythia8()->readString(
"ParticleDecays:rMax = 0.");
53 fPythia8->Pythia8()->particleData.readString(
"59:m0 = 100.1396");
55 fPythia8->Pythia8()->particleData.list(223);
61#if PYTHIA_VERSION_INTEGER < 8310
64 auto rndm = make_shared<MyRandomClass>();
66 fPythia8->Pythia8()->setRndmEnginePtr(rndm);
68 fPythia8->Pythia8()->init();
79 static Bool_t init = kFALSE;
83 fParticles =
new TClonesArray(
"TParticle");
86 fPythia8->Pythia8()->particleData.list(3122);
88 fLambda = fPythia8->Pythia8()->particleData.particleDataEntryPtr(3122);
89 DecayChannel &channel = fLambda->channel(0);
90 fBranch = channel.bRatio();
93 fRandom =
new TRandom(0);
97 fPythia8->Pythia8()->particleData.list(113);
108 fParticles->Delete();
110 fMother.SetXYZT(0, 0, 0, 0);
114 TRandom *saveRandom = gRandom;
117 TParticle *part = gMC->GetStack()->GetCurrentTrack();
119 if (fMothersPdg.find(pdg) == fMothersPdg.end()) {
121 new ((*fParticles)[0]) TParticle(*part);
127 part->GetPolarisation(polar);
128 Bool_t polarFlag = kFALSE;
130 if (TMath::Abs(polar.X()) > 0.0001 || TMath::Abs(polar.Z()) > 0.0001) {
133 if (gRandom->Rndm() < fBranch) {
136 new ((*fParticles)[0]) TParticle(*part);
138 gRandom = saveRandom;
143 DecayChannel &channel = fLambda->channel(0);
150 Int_t idPart = fPythia8->Pythia8()->event[0].id();
151 fPythia8->Pythia8()->particleData.mayDecay(idPart, kTRUE);
152 fPythia8->Pythia8()->moreDecays();
153 if (fDebug > 0) fPythia8->EventListing();
155 DecayChannel &channel = fLambda->channel(0);
156 channel.bRatio(fBranch);
159 gRandom = saveRandom;
171 fParticles->Delete();
172 npart = fPythia8->ImportParticles(fParticles,
"All");
173 TLorentzVector lvDaugh;
175 for (Int_t j = 0; j < npart; ++j) {
176 TParticle *part = (TParticle *)fParticles->UncheckedAt(j);
177 part->ProductionVertex(lvDaugh);
179 part->SetProductionVertex(lvDaugh);
180 new ((*particles)[j]) TParticle(*part);
183 npart = fParticles->GetEntriesFast();
184 for (Int_t j = 0; j < npart; ++j)
new ((*particles)[j]) TParticle(*((TParticle *)fParticles->UncheckedAt(j)));
196 printf(
"SetForceDecay not yet implemented !\n");
216 return (fPythia8->Pythia8()->particleData.tau0(pdg) * 3.3333e-12);
229 fPythia8->Pythia8()->event.append(pdg, 11, 0, 0, p->Px(), p->Py(), p->Pz(), p->E(), p->M());
237 fPythia8->Pythia8()->event.clear();
243void MpdDecayerPyt8::Gdecay(Int_t idpart, TLorentzVector *p)
246 Double_t pcm[2][4] = {{0}, {0}};
247 Double_t xm0 = p->M(), xm1 = TDatabasePDG::Instance()->GetParticle(2212)->Mass();
248 Double_t xm2 = TDatabasePDG::Instance()->GetParticle(-211)->Mass();
250 Gdeca2(xm0, xm1, xm2, pcm);
254 TLorentzVector daughter1, daughter2;
255 daughter1.SetPxPyPzE(pcm[0][0], pcm[0][1], pcm[0][2], pcm[0][3]);
256 daughter2.SetPxPyPzE(pcm[1][0], pcm[1][1], pcm[1][2], pcm[1][3]);
260 TVector3 boost(0, 0, p->P() / p->E());
261 daughter1.Boost(boost);
262 daughter2.Boost(boost);
263 daughter1.Transform(fRotation);
264 daughter2.Transform(fRotation);
267 gMC->TrackPosition(pos);
270 Int_t npart = fParticles->GetEntriesFast();
271 new ((*fParticles)[npart++]) TParticle(2212, 1, 1, -1, 0, 0, daughter1, pos);
272 new ((*fParticles)[npart]) TParticle(-211, 1, 1, -1, 0, 0, daughter2, pos);
277 TParticle *mother = (TParticle *)fParticles->UncheckedAt(0);
278 mother->SetFirstMother(1);
279 mother->SetLastMother(-1);
280 mother->SetFirstDaughter(2);
281 mother->SetLastDaughter(3);
282 mother->SetStatusCode(11);
288void MpdDecayerPyt8::Gdeca2(Double_t xm0, Double_t xm1, Double_t xm2, Double_t pcm[2][4])
291 Double_t random[2], pvert[3], costh = 0.0, sinth = 0.0, phi = 0.0;
293 Double_t e1 = (xm0 * xm0 + xm1 * xm1 - xm2 * xm2) / (2. * xm0);
294 Double_t p1 = TMath::Sqrt(TMath::Abs((e1 - xm1) * (e1 + xm1)));
296 static TRandom *myRandom = NULL;
298 myRandom =
new TRandom();
299 myRandom->SetSeed(0);
301 TRandom *oldRandom = gRandom;
304 gRandom->RndmArray(2, random);
307 TParticle *part = gMC->GetStack()->GetCurrentTrack();
308 if (part->GetPdgCode() != 3122) {
309 cout <<
" ??? Not Lambda - exit " << part->GetPdgCode() << endl;
314 part->Momentum(lorV);
315 lorV.Vect().GetXYZ(pvert);
318 part->GetPolarisation(polar);
319 if (fGlobalPolar) polar.SetMag(part->GetWeight());
321 if (TMath::Abs(polar.X()) < 0.0001 && TMath::Abs(polar.Z()) < 0.0001 && TMath::Abs(polar.Y()) < 0.0001) {
322 costh = 2. * random[0] - 1.0;
323 phi = TMath::TwoPi() * random[1];
327 Anisotropy(pvert, random, polar, phi, costh);
330 if (TMath::Abs(costh) >= 1.0)
331 costh = TMath::Sign(1.0, costh);
333 sinth = TMath::Sqrt((1. - costh) * (1. + costh));
337 pcm[0][0] = p1 * sinth * TMath::Cos(phi);
338 pcm[0][1] = p1 * sinth * TMath::Sin(phi);
339 pcm[0][2] = p1 * costh;
344 pcm[1][0] = -pcm[0][0];
345 pcm[1][1] = -pcm[0][1];
346 pcm[1][2] = -pcm[0][2];
347 pcm[1][3] = TMath::Sqrt(pcm[1][0] * pcm[1][0] + pcm[1][1] * pcm[1][1] + pcm[1][2] * pcm[1][2] + xm2 * xm2);
356void MpdDecayerPyt8::Anisotropy(Double_t *pvert, Double_t *rndm, TVector3 &polar3, Double_t &phi, Double_t &costh)
364 Double_t polar = 0.0;
366 polar = polar3.Mag();
372 static TF1
f(
"f",
"1+0.732*[0]*x", -1, 1);
373 f.SetParameter(0, polar);
376 Double_t costhe =
f.GetRandom();
378 Double_t sinth = 0.0;
379 if (TMath::Abs(costhe) >= 1.0)
380 costhe = TMath::Sign(1.0, costhe);
382 sinth = TMath::Sqrt(1.0 - costhe * costhe);
383 phi = TMath::TwoPi() * rndm[1];
388 TVector3 beam(0.0, 0.0, 1.0);
389 TVector3 lambda(pvert[0], pvert[1], pvert[2]);
392 norm = polar3.Unit();
394 norm = beam.Cross(lambda).Unit();
397 TVector3 unit(sinth * TMath::Cos(phi), sinth * TMath::Sin(phi), costhe);
401 TVector3 lambU = lambda.Unit(), lambZ(0, 0, 1), lambX(1, 0, 0), lambY(0, 1, 0);
402 lambZ.RotateUz(lambU);
403 lambX.RotateUz(lambU);
404 lambY.RotateUz(lambU);
406 rotL.RotateAxes(lambX, lambY, lambZ);
410 unit.Transform(rotL);
421 costh = TMath::Cos(unit.Theta());
434 if (fMothersPdg.find(pdg) != fMothersPdg.end())
return;
435 fMothersPdg.insert(pdg);
436 gMC->SetUserDecay(pdg);
448 fParticles->Delete();
462 TRandom *saveRandom = gRandom;
465 part->ProductionVertex(fMother);
467 Int_t pdg = part->GetPdgCode();
471 if (part->GetFirstMother() < 0) {
473 Double_t mass = fPythia8->Pythia8()->particleData.mSel(pdg);
475 p.SetE(TMath::Sqrt(p.P() * p.P() + mass * mass));
481 Int_t idPart = fPythia8->Pythia8()->event[0].id();
482 fPythia8->Pythia8()->particleData.mayDecay(idPart, kTRUE);
483 fPythia8->Pythia8()->moreDecays();
484 if (fDebug > 0) fPythia8->EventListing();
486 gRandom = saveRandom;
491void MpdDecayerPyt8::ChangeBranchings()
496 TString path = gSystem->ExpandPathName(
"$VMCWORKDIR");
497 path +=
"/gconfig/MpdDecayConfig.txt";
498 ifstream fin(path.Data());
501 TObjArray *tokens = NULL;
504 chline.ReadLine(fin);
505 if (fin.eof())
break;
506 cout << chline << endl;
507 if (chline.Contains(
"#"))
continue;
510 tokens = chline.Tokenize(
" ");
512 Bool_t exclusive = kTRUE;
513 if (chline.Contains(
"*")) exclusive = kFALSE;
514 ChangeParticleBr(tokens, exclusive);
525void MpdDecayerPyt8::ChangeParticleBr(TObjArray *channels, Bool_t exclusive)
529 Int_t nchan = channels->GetEntriesFast();
530 TString last = ((TObjString *)channels->Last())->String();
531 if (!last.Contains(
":")) --nchan;
533 Int_t pdg = ((TObjString *)channels->UncheckedAt(0))->String().Atoi();
536 Int_t ndecays = part->sizeChannels();
538 TObjArray *tokens = NULL;
539 Double_t changedBrs = 0.0, unchangedBrs = 1.0;
540 vector<Int_t> decayInds;
541 vector<Double_t> bRatios;
544 for (Int_t ich = 0; ich < nchan; ++ich) {
545 TString chline = ((TObjString *)channels->UncheckedAt(ich))->String();
546 cout << chline << endl;
547 if (chline.Contains(
"*"))
continue;
549 tokens = chline.Tokenize(
":");
552 Int_t nprongs = tokens->GetEntriesFast() - 2;
554 for (Int_t
id = 0;
id < nprongs; ++
id) {
555 pdgs.push_back(((TObjString *)tokens->UncheckedAt(1 +
id))->String().Atoi());
557 TString scale = ((TObjString *)tokens->Last())->String();
559 Double_t scaleBr = scale.Atof();
562 for (Int_t idecay = 0; idecay < ndecays; ++idecay) {
563 DecayChannel &channel = part->channel(idecay);
564 if (channel.multiplicity() != nprongs)
continue;
567 for (Int_t
id = 0;
id < nprongs; ++
id) {
568 if (channel.product(
id) != pdgs[
id])
break;
571 if (ok != nprongs)
continue;
572 changedBrs += channel.bRatio() * scaleBr;
573 unchangedBrs -= channel.bRatio();
574 decayInds.push_back(idecay);
575 bRatios.push_back(channel.bRatio() * scaleBr);
576 activeChan.insert(idecay);
588 part->rescaleBR((1.0 - changedBrs) / unchangedBrs);
589 if (!exclusive) --nchan;
591 for (Int_t ich = 0; ich < nchan; ++ich) {
592 DecayChannel &channel = part->channel(decayInds[ich]);
593 channel.bRatio(bRatios[ich]);
599 for (Int_t idecay = 0; idecay < ndecays; ++idecay) {
600 if (activeChan.find(idecay) == activeChan.end()) {
601 DecayChannel &channel = part->channel(idecay);
608 Double_t totalBr = 0;
609 for (Int_t idecay = 0; idecay < ndecays; ++idecay) {
610 DecayChannel &channel = part->channel(idecay);
611 totalBr += channel.bRatio();
613 cout <<
" Total branching after rescaling: " << totalBr << endl;
void ClearEvent()
Clear the event stack.
void AppendParticle(Int_t pdg, TLorentzVector *p)
Append a particle to the stack.
static MpdDecayerPyt8 * Instance()
Get the singleton object.
virtual void SetForceDecay(Int_t type)
Set forced decay mode.
virtual Float_t GetPartialBranchingRatio(Int_t ipart)
virtual void Init()
Initialize the decayer.
MpdDecayerPyt8()
constructor
virtual void ReadDecayTable()
to read a decay table (not yet implemented)
virtual Float_t GetLifetime(Int_t kf)
return lifetime in seconds of teh particle with PDG number pdg
virtual void ForceDecay()
ForceDecay not yet implemented.
virtual Int_t ImportParticles(TClonesArray *particles)
import the decay products into particles array
virtual void Decay(Int_t pdg, TLorentzVector *p)
Decay a single particle.
void AddMotherPdg(Int_t pdg)
Add PDG of particle to be decayed by this package.
Pythia8::ParticleDataEntry * ParticleDataEntryPtr