File indexing completed on 2025-01-18 10:06:36
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef Pythia8_EvtGen_H
0010 #define Pythia8_EvtGen_H
0011
0012 #include "Pythia8/Pythia.h"
0013 #include "EvtGen/EvtGen.hh"
0014 #include "EvtGenBase/EvtRandomEngine.hh"
0015 #include "EvtGenBase/EvtParticle.hh"
0016 #include "EvtGenBase/EvtParticleFactory.hh"
0017 #include "EvtGenBase/EvtPDL.hh"
0018 #include "EvtGenBase/EvtDecayTable.hh"
0019 #include "EvtGenBase/EvtParticleDecayList.hh"
0020 #include "EvtGenBase/EvtDecayBase.hh"
0021 #include "EvtGenExternal/EvtExternalGenList.hh"
0022
0023 namespace Pythia8 {
0024
0025
0026
0027
0028
0029 class EvtGenRandom : public EvtRandomEngine {
0030
0031 public:
0032
0033
0034 EvtGenRandom(Rndm *rndmPtrIn) {rndmPtr = rndmPtrIn;}
0035
0036
0037 double random() {if (rndmPtr) return rndmPtr->flat(); else return -1.0;}
0038
0039
0040 Rndm *rndmPtr;
0041
0042 };
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 class EvtGenDecays {
0088
0089 public:
0090
0091
0092 EvtGenDecays(Pythia *pythiaPtrIn, string decayFile, string particleDataFile,
0093 EvtExternalGenList *extPtrIn = 0, EvtAbsRadCorr *fsrPtrIn = 0,
0094 int mixing = 1, bool xml = false, bool limit = true,
0095 bool extUse = true, bool fsrUse = true);
0096
0097
0098 ~EvtGenDecays() {
0099 if (evtgen) delete evtgen;
0100 if (extOwner && extPtr) delete extPtr;
0101 if (fsrOwner && fsrPtr) delete fsrPtr;
0102 }
0103
0104
0105 double decay();
0106
0107
0108 void exclude(int id) {excIds.insert(id);}
0109
0110
0111 void updatePythia();
0112
0113
0114 void updateEvtGen();
0115
0116
0117 void readDecayFile(string decayFile, bool xml = false) {
0118 evtgen->readUDecay(decayFile.c_str(), xml); updateData();}
0119
0120
0121 bool extOwner, fsrOwner;
0122 EvtExternalGenList *extPtr;
0123 EvtAbsRadCorr *fsrPtr;
0124 std::list<EvtDecayBase*> models;
0125
0126
0127 struct Signal {int status; EvtId egId; vector<double> bfs; vector<int> map;
0128 EvtParticleDecayList modes;};
0129 map<int, Signal> signals;
0130
0131
0132 string signalSuffix;
0133
0134 protected:
0135
0136
0137 void updateData(bool final = false);
0138
0139
0140 void updateEvent(Particle *pyPro, EvtParticle *egPro,
0141 vector<int> *pySigs = 0, vector<EvtParticle*> *egSigs = 0,
0142 vector<double> *bfs = 0, double *wgt = 0);
0143
0144
0145 bool checkVertex(Particle *pyPro);
0146
0147
0148 bool checkSignal(Particle *pyPro);
0149
0150
0151 bool checkOsc(EvtParticle *egPro);
0152
0153
0154 static const int NTRYDECAY = 1000;
0155
0156
0157 Pythia *pythiaPtr;
0158
0159
0160 EvtGenRandom rndm;
0161
0162
0163 EvtGen *evtgen;
0164
0165
0166 set<int> incIds, excIds;
0167
0168
0169 bool updated;
0170
0171
0172 map<int, Signal>::iterator signal;
0173
0174
0175 double tau0Max, tauMax, rMax, xyMax, zMax;
0176 bool limitTau0, limitTau, limitRadius, limitCylinder, limitDecay;
0177
0178 };
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 EvtGenDecays::EvtGenDecays(Pythia *pythiaPtrIn, string decayFile,
0223 string particleDataFile, EvtExternalGenList *extPtrIn,
0224 EvtAbsRadCorr *fsrPtrIn, int mixing, bool xml, bool limit,
0225 bool extUse, bool fsrUse) : extPtr(extPtrIn), fsrPtr(fsrPtrIn),
0226 signalSuffix("_SIGNAL"), pythiaPtr(pythiaPtrIn), rndm(&pythiaPtr->rndm),
0227 updated(false) {
0228
0229
0230 if (!extPtr && fsrPtr) {
0231 cout << "Error in EvtGenDecays::"
0232 << "EvtGenDecays: extPtr is null but fsrPtr is provided\n";
0233 return;
0234 }
0235 if (extPtr) extOwner = false;
0236 else {extOwner = true; extPtr = new EvtExternalGenList();}
0237 if (fsrPtr) fsrOwner = false;
0238 else {fsrOwner = true; fsrPtr = extPtr->getPhotosModel();}
0239 models = extPtr->getListOfModels();
0240 evtgen = new EvtGen(decayFile.c_str(), particleDataFile.c_str(),
0241 &rndm, fsrUse ? fsrPtr : 0, extUse ? &models : 0, mixing, xml);
0242
0243
0244 if (!pythiaPtr) return;
0245 limitTau0 = pythiaPtr->settings.flag("ParticleDecays:limitTau0");
0246 tau0Max = pythiaPtr->settings.parm("ParticleDecays:tau0Max");
0247 limitTau = pythiaPtr->settings.flag("ParticleDecays:limitTau");
0248 tauMax = pythiaPtr->settings.parm("ParticleDecays:tauMax");
0249 limitRadius = pythiaPtr->settings.flag("ParticleDecays:limitRadius");
0250 rMax = pythiaPtr->settings.parm("ParticleDecays:rMax");
0251 limitCylinder = pythiaPtr->settings.flag("ParticleDecays:limitCylinder");
0252 xyMax = pythiaPtr->settings.parm("ParticleDecays:xyMax");
0253 zMax = pythiaPtr->settings.parm("ParticleDecays:zMax");
0254 limitDecay = limit && (limitTau0 || limitTau ||
0255 limitRadius || limitCylinder);
0256
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282 double EvtGenDecays::decay() {
0283
0284
0285 if (!pythiaPtr || !evtgen) return -1;
0286 if (!updated) updateData(true);
0287
0288
0289 Event &event = pythiaPtr->event;
0290 vector<int> pySigs; vector<EvtParticle*> egSigs, egPrts;
0291 vector<double> bfs; double wgt(1.);
0292 for (int iPro = 0; iPro < event.size(); ++iPro) {
0293
0294
0295 Particle *pyPro = &event[iPro];
0296 if (!pyPro->isFinal()) continue;
0297 if (incIds.find(pyPro->id()) == incIds.end()) continue;
0298 if (pyPro->status() == 93 || pyPro->status() == 94) continue;
0299
0300
0301 EvtParticle *egPro = EvtParticleFactory::particleFactory
0302 (EvtPDL::evtIdFromStdHep(pyPro->id()),
0303 EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
0304 egPrts.push_back(egPro);
0305 egPro->setDiagonalSpinDensity();
0306 evtgen->generateDecay(egPro);
0307 pyPro->tau(egPro->getLifetime());
0308 if (!checkVertex(pyPro)) continue;
0309
0310
0311 if (checkOsc(egPro))
0312 updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
0313
0314
0315 else if (checkSignal(pyPro)) {
0316 pySigs.push_back(pyPro->index());
0317 egSigs.push_back(egPro);
0318 bfs.push_back(signal->second.bfs[0]);
0319 wgt *= 1 - bfs.back();
0320 egPro->deleteDaughters();
0321 EvtParticle *egDau = EvtParticleFactory::particleFactory
0322 (EvtPDL::evtIdFromStdHep(pyPro->id()),
0323 EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
0324 egDau->addDaug(egPro);
0325 egDau->setDiagonalSpinDensity();
0326
0327
0328 } else updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
0329 }
0330 if (pySigs.size() == 0) {
0331 for (int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
0332 egPrts[iPrt]->deleteTree();
0333 return 0;
0334 }
0335
0336
0337 vector<int> modes; int force(-1), n(0);
0338 for (int iTry = 1; iTry <= NTRYDECAY; ++iTry) {
0339 modes.clear(); force = pythiaPtr->rndm.pick(bfs); n = 0;
0340 for (int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
0341 if (iSig == force) modes.push_back(0);
0342 else modes.push_back(pythiaPtr->rndm.flat() > bfs[iSig]);
0343 if (modes.back() == 0) ++n;
0344 }
0345 if (pythiaPtr->rndm.flat() <= 1.0 / n) break;
0346 if (iTry == NTRYDECAY) {
0347 wgt = 2.;
0348 cout << "Warning in EvtGenDecays::decay: maximum "
0349 << "number of signal decay attempts exceeded";
0350 }
0351 }
0352
0353
0354 for (int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
0355 EvtParticle *egSig = egSigs[iSig];
0356 Particle *pySig = &event[pySigs[iSig]];
0357 signal = signals.find(pySig->id());
0358 if (egSig->getNDaug() > 0) egSig = egSig->getDaug(0);
0359 if (modes[iSig] == 0) egSig->setId(signal->second.egId);
0360 else {
0361 signal->second.modes.getDecayModel(egSig);
0362 egSig->setChannel(signal->second.map[egSig->getChannel()]);
0363 }
0364 if (iSig == force)
0365 pySig->status(pySig->status() == 92 || pySig->status() == 94 ? 96 : 95);
0366 evtgen->generateDecay(egSig);
0367 updateEvent(pySig, egSigs[iSig]);
0368 }
0369
0370
0371 for (int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
0372 egPrts[iPrt]->deleteTree();
0373 return 1. - wgt;
0374
0375 }
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 void EvtGenDecays::updatePythia() {
0386 if (!pythiaPtr || !evtgen) return;
0387 for (int entry = 0; entry < (int)EvtPDL::entries(); ++entry) {
0388 EvtId egId = EvtPDL::getEntry(entry);
0389 int pyId = EvtPDL::getStdHep(egId);
0390 pythiaPtr->particleData.spinType (pyId, EvtPDL::getSpinType(egId));
0391 pythiaPtr->particleData.chargeType(pyId, EvtPDL::chg3(egId));
0392 pythiaPtr->particleData.m0 (pyId, EvtPDL::getMass(egId));
0393 pythiaPtr->particleData.mWidth (pyId, EvtPDL::getWidth(egId));
0394 pythiaPtr->particleData.mMin (pyId, EvtPDL::getMinMass(egId));
0395 pythiaPtr->particleData.mMax (pyId, EvtPDL::getMaxMass(egId));
0396 pythiaPtr->particleData.tau0 (pyId, EvtPDL::getctau(egId));
0397 }
0398 }
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408 void EvtGenDecays::updateEvtGen() {
0409 if (!pythiaPtr || !evtgen) return;
0410 int pyId = pythiaPtr->particleData.nextId(1);
0411 while (pyId != 0) {
0412 EvtId egId = EvtPDL::evtIdFromStdHep(pyId);
0413 EvtPDL::reSetMass (egId, pythiaPtr->particleData.m0(pyId));
0414 EvtPDL::reSetWidth (egId, pythiaPtr->particleData.mWidth(pyId));
0415 EvtPDL::reSetMassMin(egId, pythiaPtr->particleData.mMin(pyId));
0416 EvtPDL::reSetMassMax(egId, pythiaPtr->particleData.mMax(pyId));
0417 pyId = pythiaPtr->particleData.nextId(pyId);
0418 }
0419 }
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433 void EvtGenDecays::updateData(bool final) {
0434
0435
0436 if (!pythiaPtr) return;
0437 EvtDecayTable *egTable = EvtDecayTable::getInstance();
0438 if (!egTable) return;
0439 for (int iEntry = 0; iEntry < (int)EvtPDL::entries(); ++iEntry) {
0440 EvtId egId = EvtPDL::getEntry(iEntry);
0441 int pyId = EvtPDL::getStdHep(egId);
0442 if (egTable->getNModes(egId) == 0) continue;
0443 if (excIds.find(pyId) != excIds.end()) continue;
0444
0445
0446 if (final) {
0447 incIds.insert(pyId);
0448 pythiaPtr->particleData.mayDecay(pyId, false);
0449 }
0450
0451
0452 string egName = EvtPDL::name(egId);
0453 if (egName.size() <= signalSuffix.size() || egName.substr
0454 (egName.size() - signalSuffix.size()) != signalSuffix) continue;
0455 signal = signals.find(pyId);
0456 if (signal == signals.end()) {
0457 signals[pyId].status = -1;
0458 signal = signals.find(pyId);
0459 }
0460 signal->second.egId = egId;
0461 signal->second.bfs = vector<double>(2, 0);
0462 if (!final) continue;
0463
0464
0465 vector<EvtParticleDecayList> egList = egTable->getDecayTable();
0466 int sigIdx = egId.getAlias();
0467 int bkgIdx = EvtPDL::evtIdFromStdHep(pyId).getAlias();
0468 if (sigIdx > (int)egList.size() || bkgIdx > (int)egList.size()) continue;
0469 EvtParticleDecayList sigModes = egList[sigIdx];
0470 EvtParticleDecayList bkgModes = egList[bkgIdx];
0471 EvtParticleDecayList allModes = egList[bkgIdx];
0472 double sum(0);
0473
0474
0475 for (int iMode = 0; iMode < sigModes.getNMode(); ++iMode) {
0476 EvtDecayBase *mode = sigModes.getDecayModel(iMode);
0477 if (!mode) continue;
0478 signal->second.bfs[0] += mode->getBranchingFraction();
0479 sum += mode->getBranchingFraction();
0480 }
0481
0482
0483 for (int iMode = 0; iMode < allModes.getNMode(); ++iMode) {
0484 EvtDecayBase *mode = allModes.getDecayModel(iMode);
0485 if (!mode) continue;
0486 bool match(false);
0487 for (int jMode = 0; jMode < sigModes.getNMode(); ++jMode)
0488 if (mode->matchingDecay(*(sigModes.getDecayModel(jMode)))) {
0489 match = true; break;}
0490 if (match) bkgModes.removeMode(mode);
0491 else {
0492 signal->second.map.push_back(iMode);
0493 signal->second.bfs[1] += mode->getBranchingFraction();
0494 sum += mode->getBranchingFraction();
0495 }
0496 }
0497 signal->second.modes = bkgModes;
0498 for (int iBf = 0; iBf < (int)signal->second.bfs.size(); ++iBf)
0499 signal->second.bfs[iBf] /= sum;
0500 }
0501 if (final) updated = true;
0502
0503 }
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524 void EvtGenDecays::updateEvent(Particle *pyPro, EvtParticle *egPro,
0525 vector<int> *pySigs, vector<EvtParticle*> *egSigs,
0526 vector<double> *bfs, double *wgt) {
0527
0528
0529 if (!pythiaPtr) return;
0530 EvtParticle* egMom = egPro;
0531 if (egPro->getNDaug() == 1 && egPro->getPDGId() ==
0532 egPro->getDaug(0)->getPDGId()) egMom = egPro->getDaug(0);
0533 Event &event = pythiaPtr->event;
0534 vector< pair<EvtParticle*, int> >
0535 moms(1, pair<EvtParticle*, int>(egMom, pyPro->index()));
0536
0537
0538 while (moms.size() != 0) {
0539
0540
0541 egMom = moms.back().first;
0542 int iMom = moms.back().second;
0543 Particle* pyMom = &event[iMom];
0544 moms.pop_back();
0545 if (!checkVertex(pyMom)) continue;
0546 bool osc(checkOsc(egMom));
0547
0548
0549 pyMom->daughters(event.size(), event.size() + egMom->getNDaug() - 1);
0550 pyMom->statusNeg();
0551 Vec4 vProd = pyMom->vDec();
0552 for (int iDtr = 0 ; iDtr < (int)egMom->getNDaug(); ++iDtr) {
0553 EvtParticle *egDtr = egMom->getDaug(iDtr);
0554 int id = egDtr->getPDGId();
0555 EvtVector4R p = egDtr->getP4Lab();
0556 int idx = event.append(id, 93, iMom, 0, 0, 0, 0, 0, p.get(1),
0557 p.get(2), p.get(3), p.get(0), egDtr->mass());
0558 Particle *pyDtr = &event.back();
0559 pyDtr->vProd(vProd);
0560 pyDtr->tau(egDtr->getLifetime());
0561 if (pySigs && egSigs && bfs && wgt && checkSignal(pyDtr)) {
0562 pySigs->push_back(pyDtr->index());
0563 egSigs->push_back(egDtr);
0564 bfs->push_back(signal->second.bfs[0]);
0565 (*wgt) *= 1 - bfs->back();
0566 egDtr->deleteDaughters();
0567 }
0568 if (osc) pyDtr->status(94);
0569 if (egDtr->getNDaug() > 0)
0570 moms.push_back(pair<EvtParticle*, int>(egDtr, idx));
0571 }
0572 }
0573
0574 }
0575
0576
0577
0578
0579
0580
0581
0582 bool EvtGenDecays::checkVertex(Particle *pyPro) {
0583 if (!limitDecay) return true;
0584 if (limitTau0 && pyPro->tau0() > tau0Max) return false;
0585 if (limitTau && pyPro->tau() > tauMax) return false;
0586 if (limitRadius && pow2(pyPro->xDec()) + pow2(pyPro->yDec())
0587 + pow2(pyPro->zDec()) > pow2(rMax)) return false;
0588 if (limitCylinder && (pow2(pyPro->xDec()) + pow2(pyPro->yDec())
0589 > pow2(xyMax) || abs(pyPro->zDec()) > zMax) ) return false;
0590 return true;
0591 }
0592
0593
0594
0595
0596
0597 bool EvtGenDecays::checkSignal(Particle *pyPro) {
0598 signal = signals.find(pyPro->id());
0599 if (signal != signals.end() && (signal->second.status < 0 ||
0600 signal->second.status == pyPro->status())) return true;
0601 else return false;
0602 }
0603
0604
0605
0606
0607
0608
0609
0610
0611 bool EvtGenDecays::checkOsc(EvtParticle *egPro) {
0612 if (egPro && egPro->getNDaug() == 1 &&
0613 egPro->getPDGId() != egPro->getDaug(0)->getPDGId()) return true;
0614 else return false;
0615 }
0616
0617
0618
0619 }
0620
0621 #endif