9 #ifndef Pythia8_EvtGen_H
10 #define Pythia8_EvtGen_H
12 #include "Pythia8/Pythia.h"
13 #include "EvtGen/EvtGen.hh"
14 #include "EvtGenBase/EvtRandomEngine.hh"
15 #include "EvtGenBase/EvtParticle.hh"
16 #include "EvtGenBase/EvtParticleFactory.hh"
17 #include "EvtGenBase/EvtPDL.hh"
18 #include "EvtGenBase/EvtDecayTable.hh"
19 #include "EvtGenBase/EvtParticleDecayList.hh"
20 #include "EvtGenBase/EvtDecayBase.hh"
21 #include "EvtGenExternal/EvtExternalGenList.hh"
23 using namespace Pythia8;
37 double random() {
if (rndmPtr)
return rndmPtr->flat();
else return -1.0;}
94 int mixing = 1,
bool xml =
false,
bool limit =
true,
95 bool extUse =
true,
bool fsrUse =
true);
99 if (evtgen)
delete evtgen;
100 if (extOwner && extPtr)
delete extPtr;
101 if (fsrOwner && fsrPtr)
delete fsrPtr;
108 void exclude(
int id) {excIds.insert(
id);}
117 void readDecayFile(
string decayFile,
bool xml =
false) {
118 evtgen->readUDecay(decayFile.c_str(), xml); updateData();}
121 bool extOwner, fsrOwner;
124 std::list<EvtDecayBase*> models;
127 struct Signal {
int status;
EvtId egId; vector<double> bfs; vector<int> map;
129 map<int, Signal> signals;
137 void updateData(
bool final =
false);
141 vector<int> *pySigs = 0, vector<EvtParticle*> *egSigs = 0,
142 vector<double> *bfs = 0,
double *wgt = 0);
154 static const int NTRYDECAY = 1000;
166 set<int> incIds, excIds;
172 map<int, Signal>::iterator signal;
175 double tau0Max, tauMax, rMax, xyMax, zMax;
176 bool limitTau0, limitTau, limitRadius, limitCylinder, limitDecay;
222 EvtGenDecays::EvtGenDecays(
Pythia *pythiaPtrIn,
string decayFile,
225 bool extUse,
bool fsrUse) : extPtr(extPtrIn), fsrPtr(fsrPtrIn),
226 signalSuffix(
"_SIGNAL"), pythiaPtr(pythiaPtrIn), rndm(&pythiaPtr->rndm),
230 if (!extPtr && fsrPtr) {
231 if (pythiaPtr) pythiaPtr->info.errorMsg(
"Error in EvtGenDecays::"
232 "EvtGenDecays: extPtr is null but fsrPtr is provided");
235 if (extPtr) extOwner =
false;
237 if (fsrPtr) fsrOwner =
false;
238 else {fsrOwner =
true; fsrPtr = extPtr->getPhotosModel();}
239 models = extPtr->getListOfModels();
240 evtgen =
new EvtGen(decayFile.c_str(), particleDataFile.c_str(),
241 &rndm, fsrUse ? fsrPtr : 0, extUse ? &models : 0, mixing, xml);
244 if (!pythiaPtr)
return;
245 limitTau0 = pythiaPtr->settings.flag(
"ParticleDecays:limitTau0");
246 tau0Max = pythiaPtr->settings.parm(
"ParticleDecays:tau0Max");
247 limitTau = pythiaPtr->settings.flag(
"ParticleDecays:limitTau");
248 tauMax = pythiaPtr->settings.parm(
"ParticleDecays:tauMax");
249 limitRadius = pythiaPtr->settings.flag(
"ParticleDecays:limitRadius");
250 rMax = pythiaPtr->settings.parm(
"ParticleDecays:rMax");
251 limitCylinder = pythiaPtr->settings.flag(
"ParticleDecays:limitCylinder");
252 xyMax = pythiaPtr->settings.parm(
"ParticleDecays:xyMax");
253 zMax = pythiaPtr->settings.parm(
"ParticleDecays:zMax");
254 limitDecay = limit && (limitTau0 || limitTau ||
255 limitRadius || limitCylinder);
282 double EvtGenDecays::decay() {
285 if (!pythiaPtr || !evtgen)
return -1;
286 if (!updated) updateData(
true);
289 Event &
event = pythiaPtr->event;
290 vector<int> pySigs; vector<EvtParticle*> egSigs, egPrts;
291 vector<double> bfs;
double wgt(1.);
292 for (
int iPro = 0; iPro <
event.size(); ++iPro) {
296 if (!pyPro->isFinal())
continue;
297 if (incIds.find(pyPro->id()) == incIds.end())
continue;
298 if (pyPro->status() == 93 || pyPro->status() == 94)
continue;
301 EvtParticle *egPro = EvtParticleFactory::particleFactory
302 (EvtPDL::evtIdFromStdHep(pyPro->id()),
303 EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
304 egPrts.push_back(egPro);
306 evtgen->generateDecay(egPro);
308 if (!checkVertex(pyPro))
continue;
312 updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
315 else if (checkSignal(pyPro)) {
316 pySigs.push_back(pyPro->index());
317 egSigs.push_back(egPro);
318 bfs.push_back(signal->second.bfs[0]);
319 wgt *= 1 - bfs.back();
320 egPro->deleteDaughters();
321 EvtParticle *egDau = EvtParticleFactory::particleFactory
322 (EvtPDL::evtIdFromStdHep(pyPro->id()),
323 EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
328 }
else updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
330 if (pySigs.size() == 0) {
331 for (
int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
332 egPrts[iPrt]->deleteTree();
337 vector<int> modes;
int force(-1), n(0);
338 for (
int iTry = 1; iTry <= NTRYDECAY; ++iTry) {
339 modes.clear(); force = pythiaPtr->rndm.pick(bfs); n = 0;
340 for (
int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
341 if (iSig == force) modes.push_back(0);
342 else modes.push_back(pythiaPtr->rndm.flat() > bfs[iSig]);
343 if (modes.back() == 0) ++n;
345 if (pythiaPtr->rndm.flat() <= 1.0 / n)
break;
346 if (iTry == NTRYDECAY) {
348 pythiaPtr->info.errorMsg(
"Warning in EvtGenDecays::decay: maximum "
349 "number of signal decay attempts exceeded");
354 for (
int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
356 Particle *pySig = &
event[pySigs[iSig]];
357 signal = signals.find(pySig->id());
359 if (modes[iSig] == 0) egSig->setId(signal->second.egId);
361 signal->second.modes.getDecayModel(egSig);
365 pySig->status(pySig->status() == 92 || pySig->status() == 94 ? 96 : 95);
366 evtgen->generateDecay(egSig);
367 updateEvent(pySig, egSigs[iSig]);
371 for (
int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
372 egPrts[iPrt]->deleteTree();
385 void EvtGenDecays::updatePythia() {
386 if (!pythiaPtr || !evtgen)
return;
387 for (
int entry = 0; entry < (int)EvtPDL::entries(); ++entry) {
388 EvtId egId = EvtPDL::getEntry(entry);
389 int pyId = EvtPDL::getStdHep(egId);
390 pythiaPtr->particleData.spinType (pyId, EvtPDL::getSpinType(egId));
391 pythiaPtr->particleData.chargeType(pyId, EvtPDL::chg3(egId));
392 pythiaPtr->particleData.m0 (pyId, EvtPDL::getMass(egId));
393 pythiaPtr->particleData.mWidth (pyId, EvtPDL::getWidth(egId));
394 pythiaPtr->particleData.mMin (pyId, EvtPDL::getMinMass(egId));
395 pythiaPtr->particleData.mMax (pyId, EvtPDL::getMaxMass(egId));
396 pythiaPtr->particleData.tau0 (pyId, EvtPDL::getctau(egId));
408 void EvtGenDecays::updateEvtGen() {
409 if (!pythiaPtr || !evtgen)
return;
410 int pyId = pythiaPtr->particleData.nextId(1);
412 EvtId egId = EvtPDL::evtIdFromStdHep(pyId);
413 EvtPDL::reSetMass (egId, pythiaPtr->particleData.m0(pyId));
414 EvtPDL::reSetWidth (egId, pythiaPtr->particleData.mWidth(pyId));
415 EvtPDL::reSetMassMin(egId, pythiaPtr->particleData.mMin(pyId));
416 EvtPDL::reSetMassMax(egId, pythiaPtr->particleData.mMax(pyId));
417 pyId = pythiaPtr->particleData.nextId(pyId);
433 void EvtGenDecays::updateData(
bool final) {
436 if (!pythiaPtr)
return;
438 if (!egTable)
return;
439 for (
int iEntry = 0; iEntry < (int)EvtPDL::entries(); ++iEntry) {
440 EvtId egId = EvtPDL::getEntry(iEntry);
441 int pyId = EvtPDL::getStdHep(egId);
442 if (egTable->getNModes(egId) == 0)
continue;
443 if (excIds.find(pyId) != excIds.end())
continue;
448 pythiaPtr->particleData.mayDecay(pyId,
false);
452 string egName = EvtPDL::name(egId);
453 if (egName.size() <= signalSuffix.size() || egName.substr
454 (egName.size() - signalSuffix.size()) != signalSuffix)
continue;
455 signal = signals.find(pyId);
456 if (signal == signals.end()) {
457 signals[pyId].status = -1;
458 signal = signals.find(pyId);
460 signal->second.egId = egId;
461 signal->second.bfs = vector<double>(2, 0);
462 if (!
final)
continue;
465 vector<EvtParticleDecayList> egList = egTable->getDecayTable();
466 int sigIdx = egId.getAlias();
467 int bkgIdx = EvtPDL::evtIdFromStdHep(pyId).getAlias();
468 if (sigIdx > (
int)egList.size() || bkgIdx > (int)egList.size())
continue;
475 for (
int iMode = 0; iMode < sigModes.getNMode(); ++iMode) {
478 signal->second.bfs[0] += mode->getBranchingFraction();
479 sum += mode->getBranchingFraction();
483 for (
int iMode = 0; iMode < allModes.getNMode(); ++iMode) {
487 for (
int jMode = 0; jMode < sigModes.getNMode(); ++jMode)
488 if (mode->matchingDecay(*(sigModes.getDecayModel(jMode)))) {
489 match =
true;
break;}
490 if (match) bkgModes.removeMode(mode);
492 signal->second.map.push_back(iMode);
493 signal->second.bfs[1] += mode->getBranchingFraction();
494 sum += mode->getBranchingFraction();
497 signal->second.modes = bkgModes;
498 for (
int iBf = 0; iBf < (int)signal->second.bfs.size(); ++iBf)
499 signal->second.bfs[iBf] /= sum;
501 if (
final) updated =
true;
525 vector<int> *pySigs, vector<EvtParticle*> *egSigs,
526 vector<double> *bfs,
double *wgt) {
529 if (!pythiaPtr)
return;
533 Event &
event = pythiaPtr->event;
534 vector< pair<EvtParticle*, int> >
535 moms(1, pair<EvtParticle*, int>(egMom, pyPro->index()));
538 while (moms.size() != 0) {
541 egMom = moms.back().first;
542 int iMom = moms.back().second;
545 if (!checkVertex(pyMom))
continue;
546 bool osc(checkOsc(egMom));
549 pyMom->daughters(event.size(),
event.size() + egMom->
getNDaug() - 1);
551 Vec4 vProd = pyMom->vDec();
552 for (
int iDtr = 0 ; iDtr < (int)egMom->
getNDaug(); ++iDtr) {
556 int idx =
event.append(
id, 93, iMom, 0, 0, 0, 0, 0, p.get(1),
557 p.get(2), p.get(3), p.get(0), egDtr->
mass());
561 if (pySigs && egSigs && bfs && wgt && checkSignal(pyDtr)) {
562 pySigs->push_back(pyDtr->index());
563 egSigs->push_back(egDtr);
564 bfs->push_back(signal->second.bfs[0]);
565 (*wgt) *= 1 - bfs->back();
566 egDtr->deleteDaughters();
568 if (osc) pyDtr->status(94);
570 moms.push_back(pair<EvtParticle*, int>(egDtr, idx));
582 bool EvtGenDecays::checkVertex(
Particle *pyPro) {
583 if (!limitDecay)
return true;
584 if (limitTau0 && pyPro->tau0() > tau0Max)
return false;
585 if (limitTau && pyPro->tau() > tauMax)
return false;
586 if (limitRadius && pow2(pyPro->xDec()) + pow2(pyPro->yDec())
587 + pow2(pyPro->zDec()) > pow2(rMax))
return false;
588 if (limitCylinder && (pow2(pyPro->xDec()) + pow2(pyPro->yDec())
589 > pow2(xyMax) || abs(pyPro->zDec()) > zMax) )
return false;
597 bool EvtGenDecays::checkSignal(
Particle *pyPro) {
598 signal = signals.find(pyPro->id());
599 if (signal != signals.end() && (signal->second.status < 0 ||
600 signal->second.status == pyPro->status()))
return true;
612 if (egPro && egPro->
getNDaug() == 1 &&
619 #endif // end Pythia8_EvtGen_H
EvtParticle * getDaug(int i)
EvtVector4R getP4Lab() const
void addDaug(EvtParticle *node)
void setDiagonalSpinDensity()