File indexing completed on 2025-01-18 10:06:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef Pythia8_PowhegHooks_H
0015 #define Pythia8_PowhegHooks_H
0016
0017
0018 #include "Pythia8/Pythia.h"
0019 #include "Pythia8/Plugins.h"
0020
0021 namespace Pythia8 {
0022
0023
0024
0025
0026
0027 class PowhegHooks : public UserHooks {
0028
0029 public:
0030
0031
0032 PowhegHooks() {}
0033 PowhegHooks(Pythia*, Settings*, Logger*) {}
0034 ~PowhegHooks() {}
0035
0036
0037
0038
0039 bool initAfterBeams() {
0040 nFinal = settingsPtr->mode("POWHEG:nFinal");
0041 vetoMode = settingsPtr->mode("POWHEG:veto");
0042 vetoCount = settingsPtr->mode("POWHEG:vetoCount");
0043 pThardMode = settingsPtr->mode("POWHEG:pThard");
0044 pTemtMode = settingsPtr->mode("POWHEG:pTemt");
0045 emittedMode = settingsPtr->mode("POWHEG:emitted");
0046 pTdefMode = settingsPtr->mode("POWHEG:pTdef");
0047 MPIvetoMode = settingsPtr->mode("POWHEG:MPIveto");
0048 QEDvetoMode = settingsPtr->mode("POWHEG:QEDveto");
0049 showerModel = settingsPtr->mode("PartonShowers:model");
0050 return true;
0051 }
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 inline double pT(const Event& e, int RadAfterBranch,
0062 int EmtAfterBranch, int RecAfterBranch, bool FSR) {
0063
0064 if (showerModel == 2)
0065 return pTvincia(e, RadAfterBranch, EmtAfterBranch, RecAfterBranch);
0066
0067 if (showerModel == 3)
0068 return pTdire(e, RadAfterBranch, EmtAfterBranch, RecAfterBranch);
0069 return pTpythia(e, RadAfterBranch, EmtAfterBranch, RecAfterBranch, FSR);
0070 }
0071
0072
0073
0074
0075
0076 inline double pTpythia(const Event& e, int RadAfterBranch,
0077 int EmtAfterBranch, int RecAfterBranch, bool FSR) {
0078
0079
0080 Vec4 radVec = e[RadAfterBranch].p();
0081 Vec4 emtVec = e[EmtAfterBranch].p();
0082 Vec4 recVec = e[RecAfterBranch].p();
0083 int radID = e[RadAfterBranch].id();
0084
0085
0086 double sign = (FSR) ? 1. : -1.;
0087 Vec4 Q(radVec + sign * emtVec);
0088 double Qsq = sign * Q.m2Calc();
0089
0090
0091 double m2Rad = (abs(radID) >= 4 && abs(radID) < 7) ?
0092 pow2(particleDataPtr->m0(radID)) : 0.;
0093
0094
0095 double z, pTnow;
0096 if (FSR) {
0097
0098 Vec4 sum = radVec + recVec + emtVec;
0099 double m2Dip = sum.m2Calc();
0100 double x1 = 2. * (sum * radVec) / m2Dip;
0101 double x3 = 2. * (sum * emtVec) / m2Dip;
0102 z = x1 / (x1 + x3);
0103 pTnow = z * (1. - z);
0104
0105 } else {
0106
0107 Vec4 qBR(radVec - emtVec + recVec);
0108 Vec4 qAR(radVec + recVec);
0109 z = qBR.m2Calc() / qAR.m2Calc();
0110 pTnow = (1. - z);
0111 }
0112
0113
0114 pTnow *= (Qsq - sign * m2Rad);
0115
0116
0117 if (pTnow < 0.) {
0118 loggerPtr->WARNING_MSG("negative pT");
0119 return -1.;
0120 }
0121
0122
0123 return sqrt(pTnow);
0124 }
0125
0126
0127
0128
0129
0130 inline double pTvincia(const Event& event, int i1, int i3, int i2) {
0131
0132
0133 Vec4 p1 = event[i1].p();
0134 Vec4 p3 = event[i3].p();
0135 Vec4 p2 = event[i2].p();
0136
0137
0138 int iMoth1 = event[i1].mother1();
0139 int iMoth2 = event[i2].mother1();
0140 if (iMoth1 == 0 || iMoth2 == 0) {
0141 loggerPtr->ABORT_MSG("could not find mothers of particles");
0142 exit(1);
0143 }
0144
0145
0146 double mMoth1Sq = event[iMoth1].m2();
0147 double mMoth2Sq = event[iMoth2].m2();
0148 double sgn1 = event[i1].isFinal() ? 1. : -1.;
0149 double sgn2 = event[i2].isFinal() ? 1. : -1.;
0150 double qSq13 = sgn1*(m2(sgn1*p1+p3) - mMoth1Sq);
0151 double qSq23 = sgn2*(m2(sgn2*p2+p3) - mMoth2Sq);
0152
0153
0154 double sMax = -1.;
0155 if (event[i1].isFinal() && event[i2].isFinal()) {
0156
0157 sMax = m2(p1+p2+p3) - mMoth1Sq - mMoth2Sq;
0158 } else if ((event[i1].isResonance() && event[i2].isFinal())
0159 || (!event[i1].isFinal() && event[i2].isFinal())) {
0160
0161 sMax = 2.*p1*p3 + 2.*p1*p2;
0162 } else if ((event[i1].isFinal() && event[i2].isResonance())
0163 || (event[i1].isFinal() && !event[i2].isFinal())) {
0164
0165 sMax = 2.*p2*p3 + 2.*p1*p2;
0166 } else if (!event[i1].isFinal() || !event[i2].isFinal()) {
0167
0168 sMax = 2.*p1*p2;
0169 } else {
0170 loggerPtr->ABORT_MSG("could not determine branching type");
0171 exit(1);
0172 }
0173
0174
0175 double pT2now = qSq13*qSq23/sMax;
0176
0177
0178 if (pT2now < 0.) {
0179 loggerPtr->WARNING_MSG("negative pT");
0180 return -1.;
0181 }
0182
0183
0184 return sqrt(pT2now);
0185 }
0186
0187
0188
0189
0190
0191
0192 inline double pTdire(const Event& event, int iRad, int iEmt, int iRec) {
0193
0194
0195 const Particle& rad = event[iRad];
0196 const Particle& emt = event[iEmt];
0197 const Particle& rec = event[iRec];
0198
0199
0200 double pT2 = -1.;
0201 if (rad.isFinal() && rec.isFinal()) {
0202
0203 const double sij = 2.*rad.p()*emt.p();
0204 const double sik = 2.*rad.p()*rec.p();
0205 const double sjk = 2.*rec.p()*emt.p();
0206 pT2 = sij*sjk/(sij+sik+sjk);
0207 } else if (rad.isFinal() && !rec.isFinal()) {
0208
0209 const double sij = 2.*rad.p()*emt.p();
0210 const double sai = -2.*rec.p()*rad.p();
0211 const double saj = -2.*rec.p()*emt.p();
0212 pT2 = sij*saj/(sai+saj)*(sij+saj+sai)/(sai+saj);
0213 if (sij+saj+sai < 1e-5 && abs(sij+saj+sai) < 1e-5) pT2 = sij;
0214 } else if (!rad.isFinal() && rec.isFinal()) {
0215
0216 const double sai = -2.*rad.p()*emt.p();
0217 const double sik = 2.*rec.p()*emt.p();
0218 const double sak = -2.*rad.p()*rec.p();
0219 pT2 = sai*sik/(sai+sak)*(sai+sik+sak)/(sai+sak);
0220 } else if (!rad.isFinal() || !rec.isFinal()) {
0221
0222 const double sai = -2.*rad.p()*emt.p();
0223 const double sbi = -2.*rec.p()*emt.p();
0224 const double sab = 2.*rad.p()*rec.p();
0225 pT2 = sai*sbi/sab*(sai+sbi+sab)/sab;
0226 } else {
0227 loggerPtr->ABORT_MSG("could not determine branching type");
0228 exit(1);
0229 }
0230
0231
0232 if (pT2 < 0.) {
0233 loggerPtr->WARNING_MSG("negative pT");
0234 return -1.;
0235 }
0236
0237
0238 return sqrt(pT2);
0239 }
0240
0241
0242
0243
0244 inline double pTpowheg(const Event &e, int i, int j, bool FSR) {
0245
0246
0247 double pTnow = 0.;
0248 if (FSR) {
0249
0250
0251
0252 int iInA = partonSystemsPtr->getInA(0);
0253 int iInB = partonSystemsPtr->getInB(0);
0254 double betaZ = - ( e[iInA].pz() + e[iInB].pz() ) /
0255 ( e[iInA].e() + e[iInB].e() );
0256 Vec4 iVecBst(e[i].p()), jVecBst(e[j].p());
0257 iVecBst.bst(0., 0., betaZ);
0258 jVecBst.bst(0., 0., betaZ);
0259 pTnow = sqrt( (iVecBst + jVecBst).m2Calc() *
0260 iVecBst.e() * jVecBst.e() /
0261 pow2(iVecBst.e() + jVecBst.e()) );
0262
0263 } else {
0264
0265 pTnow = e[j].pT();
0266 }
0267
0268
0269 if (pTnow < 0.) {
0270 loggerPtr->WARNING_MSG("negative pT");
0271 return -1.;
0272 }
0273
0274 return pTnow;
0275 }
0276
0277
0278
0279
0280
0281
0282
0283
0284 inline double pTcalc(const Event &e, int i, int j, int k, int r, int xSRin) {
0285
0286
0287 double pTemt = -1., pTnow;
0288 int xSR1 = (xSRin == -1) ? 0 : xSRin;
0289 int xSR2 = (xSRin == -1) ? 2 : xSRin + 1;
0290 for (int xSR = xSR1; xSR < xSR2; xSR++) {
0291
0292 bool FSR = (xSR == 0) ? false : true;
0293
0294
0295
0296 if ((pTdefMode == 0 || pTdefMode == 1) && i > 0 && j > 0) {
0297 pTemt = pTpowheg(e, i, j, (pTdefMode == 0) ? false : FSR);
0298
0299
0300 } else if (!FSR && pTdefMode == 2 && i > 0 && j > 0 && r > 0) {
0301 pTemt = pT(e, i, j, r, FSR);
0302
0303
0304 } else if (FSR && pTdefMode == 2 && j > 0 && k > 0 && r > 0) {
0305 pTemt = pT(e, k, j, r, FSR);
0306
0307
0308 } else {
0309
0310
0311
0312
0313 int iInA = partonSystemsPtr->getInA(0);
0314 int iInB = partonSystemsPtr->getInB(0);
0315 while (e[iInA].mother1() != 1) { iInA = e[iInA].mother1(); }
0316 while (e[iInB].mother1() != 2) { iInB = e[iInB].mother1(); }
0317
0318
0319 int jNow = (j > 0) ? j : 0;
0320 int jMax = (j > 0) ? j + 1 : e.size();
0321 for (; jNow < jMax; jNow++) {
0322
0323
0324 if (!e[jNow].isFinal()) continue;
0325
0326 if (QEDvetoMode==0 && e[jNow].colType() == 0) continue;
0327
0328
0329 if (pTdefMode == 0 || pTdefMode == 1) {
0330
0331
0332 if (!FSR) {
0333 pTnow = pTpowheg(e, iInA, jNow, (pTdefMode == 0) ? false : FSR);
0334 if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
0335
0336
0337
0338
0339 } else {
0340
0341 int outSize = partonSystemsPtr->sizeOut(0);
0342 for (int iMem = 0; iMem < outSize; iMem++) {
0343 int iNow = partonSystemsPtr->getOut(0, iMem);
0344
0345
0346 if (iNow == jNow ) continue;
0347
0348 if (QEDvetoMode==0 && e[iNow].colType() == 0) continue;
0349 if (jNow == e[iNow].daughter1()
0350 && jNow == e[iNow].daughter2()) continue;
0351
0352 pTnow = pTpowheg(e, iNow, jNow, (pTdefMode == 0)
0353 ? false : FSR);
0354 if (pTnow > 0.) pTemt = (pTemt < 0)
0355 ? pTnow : min(pTemt, pTnow);
0356 }
0357
0358 }
0359
0360
0361 } else if (pTdefMode == 2) {
0362
0363
0364 if (!FSR) {
0365 pTnow = pT(e, iInA, jNow, iInB, FSR);
0366 if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
0367 pTnow = pT(e, iInB, jNow, iInA, FSR);
0368 if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
0369
0370
0371
0372 } else {
0373 for (int kNow = 0; kNow < e.size(); kNow++) {
0374 if (kNow == jNow || !e[kNow].isFinal()) continue;
0375 if (QEDvetoMode==0 && e[kNow].colType() == 0) continue;
0376
0377
0378
0379 pTnow = pT(e, kNow, jNow, iInA, FSR);
0380 if (pTnow > 0.) pTemt = (pTemt < 0)
0381 ? pTnow : min(pTemt, pTnow);
0382 pTnow = pT(e, kNow, jNow, iInB, FSR);
0383 if (pTnow > 0.) pTemt = (pTemt < 0)
0384 ? pTnow : min(pTemt, pTnow);
0385
0386
0387 for (int rNow = 0; rNow < e.size(); rNow++) {
0388 if (rNow == kNow || rNow == jNow ||
0389 !e[rNow].isFinal()) continue;
0390 if(QEDvetoMode==0 && e[rNow].colType() == 0) continue;
0391 pTnow = pT(e, kNow, jNow, rNow, FSR);
0392 if (pTnow > 0.) pTemt = (pTemt < 0)
0393 ? pTnow : min(pTemt, pTnow);
0394 }
0395
0396 }
0397
0398 }
0399
0400 }
0401
0402 }
0403
0404 }
0405 }
0406
0407
0408 return pTemt;
0409 }
0410
0411
0412
0413
0414
0415
0416
0417
0418 inline bool canVetoMPIStep() { return true; }
0419 inline int numberVetoMPIStep() { return 1; }
0420 inline bool doVetoMPIStep(int nMPI, const Event &e) {
0421
0422 if (nMPI > 1) return false;
0423 int iEmt = -1;
0424 double pT1(0.), pTsum(0.);
0425
0426
0427
0428
0429 if (nFinal > 0) {
0430
0431
0432
0433 int count = 0;
0434 for (int i = e.size() - 1; i > 0; i--) {
0435 if (e[i].isFinal()) {
0436 count++;
0437 pT1 = e[i].pT();
0438 pTsum += e[i].pT();
0439 } else break;
0440 }
0441
0442 if (count != nFinal && count != nFinal + 1) {
0443 loggerPtr->ABORT_MSG("wrong number of final state particles in event");
0444 exit(1);
0445 }
0446
0447 isEmt = (count == nFinal) ? false : true;
0448 iEmt = (isEmt) ? e.size() - 1 : -1;
0449
0450
0451
0452
0453 } else {
0454
0455
0456 isEmt = false;
0457 for (int i = e.size() - 1; i > 0; i--) {
0458 if (e[i].isFinal()) {
0459 if ( e[i].isParton() && iEmt < 0
0460 && e[e[i].mother1()].isParton() ) {
0461 isEmt = true;
0462 iEmt = i;
0463 }
0464 pT1 = e[i].pT();
0465 pTsum += e[i].pT();
0466 } else break;
0467 }
0468 }
0469
0470
0471 if (!isEmt || pThardMode == 0) {
0472 pThard = infoPtr->scalup();
0473
0474
0475
0476 } else if (pThardMode == 1) {
0477 if (nFinal < 0) {
0478 loggerPtr->WARNING_MSG(
0479 "pThard == 1 not available for nFinal == -1, reset pThard = 0.");
0480 pThardMode = 0;
0481 pThard = infoPtr->scalup();
0482 } else {
0483 pThard = pTcalc(e, -1, iEmt, -1, -1, -1);
0484 }
0485
0486
0487
0488
0489 } else if (pThardMode == 2) {
0490 if (nFinal < 0) {
0491 loggerPtr->WARNING_MSG(
0492 "pThard == 2 not available for nFinal == -1, reset pThard = 0.");
0493 pThardMode = 0;
0494 pThard = infoPtr->scalup();
0495 } else {
0496 pThard = pTcalc(e, -1, -1, -1, -1, -1);
0497 }
0498 }
0499
0500
0501 if (MPIvetoMode == 1) {
0502 pTMPI = (isEmt) ? pTsum / 2. : pT1;
0503 }
0504
0505
0506 accepted = false;
0507 nAcceptSeq = nISRveto = nFSRveto = 0;
0508
0509
0510 return false;
0511 }
0512
0513
0514
0515
0516
0517 inline bool canVetoISREmission() { return (vetoMode == 0) ? false : true; }
0518 inline bool doVetoISREmission(int, const Event &e, int iSys) {
0519
0520 if (iSys != 0) return false;
0521
0522
0523 if (vetoMode == 1 && nAcceptSeq >= vetoCount) return false;
0524
0525
0526 int iRadAft = -1, iEmt = -1, iRecAft = -1;
0527 for (int i = e.size() - 1; i > 0; i--) {
0528 if (showerModel == 1) {
0529
0530 if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
0531 else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
0532 else if (iRecAft == -1 && e[i].status() == -42) iRecAft = i;
0533 } else if (showerModel == 2) {
0534
0535 if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
0536 else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
0537 else if (iRecAft == -1
0538 && (e[i].status() == -41 || e[i].status() == 44)) iRecAft = i;
0539 } else if (showerModel == 3) {
0540
0541 if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
0542 else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
0543 else if (iRecAft == -1
0544 && (e[i].status() == -41
0545 || e[i].status() == 44 || e[i].status() == 48)) iRecAft = i;
0546 }
0547 if (iRadAft != -1 && iEmt != -1 && iRecAft != -1) break;
0548 }
0549 if (iRadAft == -1 || iEmt == -1 || iRecAft == -1) {
0550 loggerPtr->ABORT_MSG("could not find ISR emission");
0551 exit(1);
0552 }
0553
0554
0555
0556
0557 int xSR = (pTemtMode == 0) ? 0 : -1;
0558 int i = (pTemtMode == 0) ? iRadAft : -1;
0559 int j = (pTemtMode != 2) ? iEmt : -1;
0560 int k = -1;
0561 int r = (pTemtMode == 0) ? iRecAft : -1;
0562 double pTemt = pTcalc(e, i, j, k, r, xSR);
0563
0564
0565
0566 bool vetoParton = (!isEmt && e[iEmt].colType()==0 && QEDvetoMode==2)
0567 ? false: true;
0568
0569
0570 if (pTemt > pThard) {
0571 if(!vetoParton) {
0572
0573 nAcceptSeq = vetoCount-1;
0574 } else {
0575 nAcceptSeq = 0;
0576 nISRveto++;
0577 return true;
0578 }
0579 }
0580
0581
0582 nAcceptSeq++;
0583 accepted = true;
0584 return false;
0585 }
0586
0587
0588
0589
0590
0591 inline bool canVetoFSREmission() { return (vetoMode == 0) ? false : true; }
0592 inline bool doVetoFSREmission(int, const Event &e, int iSys, bool) {
0593
0594 if (iSys != 0) return false;
0595
0596
0597 if (vetoMode == 1 && nAcceptSeq >= vetoCount) return false;
0598
0599
0600 int iRecAft = e.size() - 1;
0601 int iEmt = e.size() - 2;
0602 int iRadAft = e.size() - 3;
0603 int iRadBef = e[iEmt].mother1();
0604 bool stop = false;
0605 if (showerModel == 1 || showerModel == 3) {
0606
0607 if ( (e[iRecAft].status() != 52 && e[iRecAft].status() != -53) ||
0608 e[iEmt].status() != 51 || e[iRadAft].status() != 51) stop = true;
0609 } else if (showerModel == 2) {
0610
0611 if ( (e[iRecAft].status() != 51 && e[iRecAft].status() != 52) ||
0612 e[iEmt].status() != 51 || e[iRadAft].status() != 51) stop = true;
0613 }
0614 if (stop) {
0615 loggerPtr->ABORT_MSG("could not find FSR emission");
0616 exit(1);
0617 }
0618
0619
0620
0621
0622
0623 int xSR = (pTemtMode == 0) ? 1 : -1;
0624 int i = (pTemtMode == 0) ? iRadBef : -1;
0625 int k = (pTemtMode == 0) ? iRadAft : -1;
0626 int r = (pTemtMode == 0) ? iRecAft : -1;
0627
0628
0629 double pTemt = 0.;
0630 if (pTemtMode == 0 || pTemtMode == 1) {
0631
0632
0633
0634
0635
0636 int j = iRadAft;
0637 if (emittedMode == 0 || (emittedMode == 2 && rndmPtr->flat() < 0.5)) j++;
0638
0639 for (int jLoop = 0; jLoop < 2; jLoop++) {
0640 if (jLoop == 0) pTemt = pTcalc(e, i, j, k, r, xSR);
0641 else if (jLoop == 1) pTemt = min(pTemt, pTcalc(e, i, j, k, r, xSR));
0642
0643
0644 if (emittedMode != 3) break;
0645 if (k != -1) swap(j, k); else j = iEmt;
0646 }
0647
0648
0649 } else if (pTemtMode == 2) {
0650 pTemt = pTcalc(e, i, -1, k, r, xSR);
0651
0652 }
0653
0654
0655
0656 bool vetoParton = (!isEmt && e[iEmt].colType()==0 && QEDvetoMode==2)
0657 ? false: true;
0658
0659
0660 if (pTemt > pThard) {
0661 if(!vetoParton) {
0662
0663 nAcceptSeq = vetoCount-1;
0664 } else {
0665 nAcceptSeq = 0;
0666 nFSRveto++;
0667 return true;
0668 }
0669 }
0670
0671
0672 nAcceptSeq++;
0673 accepted = true;
0674 return false;
0675 }
0676
0677
0678
0679
0680
0681 inline bool canVetoMPIEmission() {return (MPIvetoMode == 0) ? false : true;}
0682 inline bool doVetoMPIEmission(int, const Event &e) {
0683 if (MPIvetoMode == 1) {
0684 if (e[e.size() - 1].pT() > pTMPI) return true;
0685 }
0686 return false;
0687 }
0688
0689
0690
0691
0692
0693 inline int getNISRveto() { return nISRveto; }
0694 inline int getNFSRveto() { return nFSRveto; }
0695
0696
0697
0698 private:
0699 int showerModel, nFinal, vetoMode, MPIvetoMode, QEDvetoMode, vetoCount;
0700 int pThardMode, pTemtMode, emittedMode, pTdefMode;
0701 double pThard, pTMPI;
0702 bool accepted, isEmt;
0703
0704
0705 int nAcceptSeq;
0706
0707 unsigned long int nISRveto, nFSRveto;
0708
0709 };
0710
0711
0712
0713
0714
0715 PYTHIA8_PLUGIN_CLASS(UserHooks, PowhegHooks, false, false, false)
0716 PYTHIA8_PLUGIN_VERSIONS(PYTHIA_VERSION_INTEGER)
0717
0718
0719
0720 }
0721
0722 #endif