ATLAS Offline Software
Loading...
Searching...
No Matches
PowhegHooksSetterMethod.cxx
Go to the documentation of this file.
1// PowhegHooks.h is a part of the PYTHIA event generator.
2// Copyright (C) 2025 Richard Corke, Torbjorn Sjostrand.
3// PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4// Please respect the MCnet Guidelines, see GUIDELINES for details.
5
6// Author: Richard Corke, modified by Christian T Preuss.
7// modified by Katharina Voss (only change: setpThard method)
8// modified version from PowhegHooks.h method in Pythia8.314
9// /cvmfs/atlas-nightlies.cern.ch/repo/sw/main_AthGeneration_x86_64-el9-gcc13-opt/sw/lcg/releases/LCG_107a_ATLAS_9/MCGenerators/pythia8/314/x86_64-el9-gcc13-opt/include/Pythia8Plugins/PowhegHooks.h
10// This class is used to perform a vetoed shower, where emissions
11// already covered in a POWHEG NLO generator should be omitted.
12// To first approximation the handover should happen at the SCALE
13// of the LHA, but since the POWHEG-BOX uses a different pT definition
14// than PYTHIA, both for ISR and FSR, a more sophisticated treatment
15// is needed. See the online manual on POWHEG matching for details.
16
17#ifndef Pythia8_PowhegHooksSetterMethod_H
18#define Pythia8_PowhegHooksSetterMethod_H
19
20// Includes
21#include "Pythia8/Pythia.h"
22#include "Pythia8/Plugins.h"
23
24namespace Pythia8 {
25
26//==========================================================================
27
28// Use userhooks to veto PYTHIA emissions above the POWHEG scale.
29
30class PowhegHooksSetterMethod : public UserHooks {
31
32public:
33
34 // Constructors and destructor.
35 // default member variables from PowhegHooks settings initialized as specified in
36 // /cvmfs/atlas-nightlies.cern.ch/repo/sw/main_AthGeneration_x86_64-el9-gcc13-opt/sw/lcg/releases/LCG_107a_ATLAS_9/MCGenerators/pythia8/314/x86_64-el9-gcc13-opt/share/Pythia8/xmldoc/POWHEGMatching.xml
37 // and showerModel as specified in
38 // /cvmfs/atlas-nightlies.cern.ch/repo/sw/main_AthGeneration_x86_64-el9-gcc13-opt/sw/lcg/releases/LCG_107a_ATLAS_9/MCGenerators/pythia8/314/x86_64-el9-gcc13-opt/share/Pythia8/xmldoc/PartonShowers.xml
41 m_nFinal(-1),
42 m_vetoMode(0),
45 m_vetoCount(3),
46 m_pThardMode(0),
47 m_pTemtMode(0),
49 m_pTdefMode(0),
50 m_pThard(0.),
51 m_pTMPI(0.),
52 m_accepted(false),
53 m_isEmt(false),
54 m_nAcceptSeq(0),
55 m_nISRveto(0),
56 m_nFSRveto(0) {}
57 PowhegHooksSetterMethod(Pythia*, Settings*, Logger*):
59 m_nFinal(-1),
60 m_vetoMode(0),
63 m_vetoCount(3),
64 m_pThardMode(0),
65 m_pTemtMode(0),
67 m_pTdefMode(0),
68 m_pThard(0.),
69 m_pTMPI(0.),
70 m_accepted(false),
71 m_isEmt(false),
72 m_nAcceptSeq(0),
73 m_nISRveto(0),
74 m_nFSRveto(0) {}
76
77 //--------------------------------------------------------------------------
78
79 // Initialize settings, detailing merging strategy to use.
81 m_nFinal = settingsPtr->mode("POWHEG:nFinal");
82 m_vetoMode = settingsPtr->mode("POWHEG:veto");
83 m_vetoCount = settingsPtr->mode("POWHEG:vetoCount");
84 m_pThardMode = settingsPtr->mode("POWHEG:pThard");
85 m_pTemtMode = settingsPtr->mode("POWHEG:pTemt");
86 m_emittedMode = settingsPtr->mode("POWHEG:emitted");
87 m_pTdefMode = settingsPtr->mode("POWHEG:pTdef");
88 m_MPIvetoMode = settingsPtr->mode("POWHEG:MPIveto");
89 m_QEDvetoMode = settingsPtr->mode("POWHEG:QEDveto");
90 m_showerModel = settingsPtr->mode("PartonShowers:model");
91 return true;
92 }
93
94 //--------------------------------------------------------------------------
95
96 // Routines to calculate the pT (according to m_pTdefMode) in a branching:
97 // ISR: i (radiator after) -> j (emitted after) k (radiator before)
98 // FSR: i (radiator before) -> j (emitted after) k (radiator after)
99 // For the Pythia pT definitions, a recoiler (after) must be specified.
100
101 // Top-level wrapper for shower pTs.
102 inline double pT(const Event& e, int RadAfterBranch,
103 int EmtAfterBranch, int RecAfterBranch, bool FSR) {
104 // VINCIA pT definition.
105 if (m_showerModel == 2)
106 return pTvincia(e, RadAfterBranch, EmtAfterBranch, RecAfterBranch);
107 // DIRE pT definition.
108 if (m_showerModel == 3)
109 return pTdire(e, RadAfterBranch, EmtAfterBranch, RecAfterBranch);
110 return pTpythia(e, RadAfterBranch, EmtAfterBranch, RecAfterBranch, FSR);
111 }
112
113 //--------------------------------------------------------------------------
114
115 // Compute the Pythia pT separation.
116 // Based on pTLund function in History.cc and identical to pTevol.
117 inline double pTpythia(const Event& e, int RadAfterBranch,
118 int EmtAfterBranch, int RecAfterBranch, bool FSR) {
119
120 // Convenient shorthands for later
121 Vec4 radVec = e[RadAfterBranch].p();
122 Vec4 emtVec = e[EmtAfterBranch].p();
123 Vec4 recVec = e[RecAfterBranch].p();
124 int radID = e[RadAfterBranch].id();
125
126 // Calculate virtuality of splitting
127 double sign = (FSR) ? 1. : -1.;
128 Vec4 Q(radVec + sign * emtVec);
129 double Qsq = sign * Q.m2Calc();
130
131 // Mass term of radiator
132 double m2Rad = (std::abs(radID) >= 4 && std::abs(radID) < 7) ?
133 pow2(particleDataPtr->m0(radID)) : 0.;
134
135 // z values for FSR and ISR
136 double z, pTnow;
137 if (FSR) {
138 // Construct 2 -> 3 variables
139 Vec4 sum = radVec + recVec + emtVec;
140 double m2Dip = sum.m2Calc();
141 double x1 = 2. * (sum * radVec) / m2Dip;
142 double x3 = 2. * (sum * emtVec) / m2Dip;
143 z = x1 / (x1 + x3);
144 pTnow = z * (1. - z);
145
146 } else {
147 // Construct dipoles before/after splitting
148 Vec4 qBR(radVec - emtVec + recVec);
149 Vec4 qAR(radVec + recVec);
150 z = qBR.m2Calc() / qAR.m2Calc();
151 pTnow = (1. - z);
152 }
153
154 // Virtuality with correct sign
155 pTnow *= (Qsq - sign * m2Rad);
156
157 // Can get negative pT for massive splittings.
158 if (pTnow < 0.) {
159 loggerPtr->WARNING_MSG("negative pT");
160 return -1.;
161 }
162
163 // Return pT
164 return sqrt(pTnow);
165 }
166
167 //--------------------------------------------------------------------------
168
169 // Compute the Vincia pT as in Eq. (2.63)-(2.66) in arXiv:2003.00702.
170 // Branching is assumed to be {13} {23} -> 1 3 2.
171 inline double pTvincia(const Event& event, int i1, int i3, int i2) {
172
173 // Shorthands.
174 Vec4 p1 = event[i1].p();
175 Vec4 p3 = event[i3].p();
176 Vec4 p2 = event[i2].p();
177
178 // Fetch mothers of 1 and 2.
179 int iMoth1 = event[i1].mother1();
180 int iMoth2 = event[i2].mother1();
181 if (iMoth1 == 0 || iMoth2 == 0) {
182 loggerPtr->ABORT_MSG("could not find mothers of particles");
183 exit(1);
184 }
185
186 // Invariants defined as in Eq. (5) in arXiv:2008.09468.
187 double mMoth1Sq = event[iMoth1].m2();
188 double mMoth2Sq = event[iMoth2].m2();
189 double sgn1 = event[i1].isFinal() ? 1. : -1.;
190 double sgn2 = event[i2].isFinal() ? 1. : -1.;
191 double qSq13 = sgn1*(m2(sgn1*p1+p3) - mMoth1Sq);
192 double qSq23 = sgn2*(m2(sgn2*p2+p3) - mMoth2Sq);
193
194 // Normalisation as in Eq. (6) in arXiv:2008.09468.
195 double sMax = -1.;
196 if (event[i1].isFinal() && event[i2].isFinal()) {
197 // FF.
198 sMax = m2(p1+p2+p3) - mMoth1Sq - mMoth2Sq;
199 } else if ((event[i1].isResonance() && event[i2].isFinal())
200 || (!event[i1].isFinal() && event[i2].isFinal())) {
201 // RF or IF.
202 sMax = 2.*p1*p3 + 2.*p1*p2;
203 } else if ((event[i1].isFinal() && event[i2].isResonance())
204 || (event[i1].isFinal() && !event[i2].isFinal())) {
205 // FR or FI.
206 sMax = 2.*p2*p3 + 2.*p1*p2;
207 } else if (!event[i1].isFinal() || !event[i2].isFinal()) {
208 // II.
209 sMax = 2.*p1*p2;
210 } else {
211 loggerPtr->ABORT_MSG("could not determine branching type");
212 exit(1);
213 }
214
215 // Calculate pT2 as in Eq. (5) in arXiv:2008.09468.
216 double pT2now = qSq13*qSq23/sMax;
217
218 // Sanity check.
219 if (pT2now < 0.) {
220 loggerPtr->WARNING_MSG("negative pT");
221 return -1.;
222 }
223
224 // Return pT.
225 return sqrt(pT2now);
226 }
227
228 //--------------------------------------------------------------------------
229
230 // Compute the Dire pT as in
231 // DireTimes::pT2_FF, DireTimes::pT2_FI,
232 // DireSpace::pT2_IF, DireSpace::pT2_II.
233 inline double pTdire(const Event& event, int iRad, int iEmt, int iRec) {
234
235 // Shorthands.
236 const Particle& rad = event[iRad];
237 const Particle& emt = event[iEmt];
238 const Particle& rec = event[iRec];
239
240 // Calculate pT2 depending on dipole configuration.
241 double pT2 = -1.;
242 if (rad.isFinal() && rec.isFinal()) {
243 // FF -- copied from DireTimes::pT2_FF.
244 const double sij = 2.*rad.p()*emt.p();
245 const double sik = 2.*rad.p()*rec.p();
246 const double sjk = 2.*rec.p()*emt.p();
247 pT2 = sij*sjk/(sij+sik+sjk);
248 } else if (rad.isFinal() && !rec.isFinal()) {
249 // FI.
250 const double sij = 2.*rad.p()*emt.p();
251 const double sai = -2.*rec.p()*rad.p();
252 const double saj = -2.*rec.p()*emt.p();
253 pT2 = sij*saj/(sai+saj)*(sij+saj+sai)/(sai+saj);
254 if (sij+saj+sai < 1e-5 && std::abs(sij+saj+sai) < 1e-5) pT2 = sij;
255 } else if (!rad.isFinal() && rec.isFinal()) {
256 // IF.
257 const double sai = -2.*rad.p()*emt.p();
258 const double sik = 2.*rec.p()*emt.p();
259 const double sak = -2.*rad.p()*rec.p();
260 pT2 = sai*sik/(sai+sak)*(sai+sik+sak)/(sai+sak);
261 } else if (!rad.isFinal() || !rec.isFinal()) {
262 // II.
263 const double sai = -2.*rad.p()*emt.p();
264 const double sbi = -2.*rec.p()*emt.p();
265 const double sab = 2.*rad.p()*rec.p();
266 pT2 = sai*sbi/sab*(sai+sbi+sab)/sab;
267 } else {
268 loggerPtr->ABORT_MSG("could not determine branching type");
269 exit(1);
270 }
271
272 // Sanity check.
273 if (pT2 < 0.) {
274 loggerPtr->WARNING_MSG("negative pT");
275 return -1.;
276 }
277
278 // Return pT.
279 return sqrt(pT2);
280 }
281
282 //--------------------------------------------------------------------------
283
284 // Compute the POWHEG pT separation between i and j.
285 inline double pTpowheg(const Event &e, int i, int j, bool FSR) {
286
287 // pT value for FSR and ISR
288 double pTnow = 0.;
289 if (FSR) {
290 // POWHEG d_ij (in CM frame). Note that the incoming beams have not
291 // been updated in the parton systems pointer yet (i.e. prior to any
292 // potential recoil).
293 int iInA = partonSystemsPtr->getInA(0);
294 int iInB = partonSystemsPtr->getInB(0);
295 double betaZ = - ( e[iInA].pz() + e[iInB].pz() ) /
296 ( e[iInA].e() + e[iInB].e() );
297 Vec4 iVecBst(e[i].p()), jVecBst(e[j].p());
298 iVecBst.bst(0., 0., betaZ);
299 jVecBst.bst(0., 0., betaZ);
300 pTnow = sqrt( (iVecBst + jVecBst).m2Calc() *
301 iVecBst.e() * jVecBst.e() /
302 pow2(iVecBst.e() + jVecBst.e()) );
303
304 } else {
305 // POWHEG pT_ISR is just kinematic pT
306 pTnow = e[j].pT();
307 }
308
309 // Check result.
310 if (pTnow < 0.) {
311 loggerPtr->WARNING_MSG("negative pT");
312 return -1.;
313 }
314
315 return pTnow;
316 }
317
318 //--------------------------------------------------------------------------
319
320 // Calculate pT for a splitting based on m_pTdefMode.
321 // If j is -1, all final-state partons are tried.
322 // If i, k, r and xSR are -1, then all incoming and outgoing
323 // partons are tried.
324 // xSR set to 0 means ISR, while xSR set to 1 means FSR.
325 inline double pTcalc(const Event &e, int i, int j, int k, int r, int xSRin) {
326
327 // Loop over ISR and FSR if necessary
328 double pTemt = -1., pTnow;
329 int xSR1 = (xSRin == -1) ? 0 : xSRin;
330 int xSR2 = (xSRin == -1) ? 2 : xSRin + 1;
331 for (int xSR = xSR1; xSR < xSR2; xSR++) {
332 // FSR flag
333 bool FSR = (xSR == 0) ? false : true;
334
335 // If all necessary arguments have been given, then directly calculate.
336 // POWHEG ISR and FSR, need i and j.
337 if ((m_pTdefMode == 0 || m_pTdefMode == 1) && i > 0 && j > 0) {
338 pTemt = pTpowheg(e, i, j, (m_pTdefMode == 0) ? false : FSR);
339
340 // Pythia ISR, need i, j and r.
341 } else if (!FSR && m_pTdefMode == 2 && i > 0 && j > 0 && r > 0) {
342 pTemt = pT(e, i, j, r, FSR);
343
344 // Pythia FSR, need k, j and r.
345 } else if (FSR && m_pTdefMode == 2 && j > 0 && k > 0 && r > 0) {
346 pTemt = pT(e, k, j, r, FSR);
347
348 // Otherwise need to try all possible combinations.
349 } else {
350 // Start by finding incoming legs to the hard system after
351 // branching (radiator after branching, i for ISR).
352 // Use partonSystemsPtr to find incoming just prior to the
353 // branching and track mothers.
354 int iInA = partonSystemsPtr->getInA(0);
355 int iInB = partonSystemsPtr->getInB(0);
356 while (e[iInA].mother1() != 1) { iInA = e[iInA].mother1(); }
357 while (e[iInB].mother1() != 2) { iInB = e[iInB].mother1(); }
358
359 // If we do not have j, then try all final-state partons.
360 int jNow = (j > 0) ? j : 0;
361 int jMax = (j > 0) ? j + 1 : e.size();
362 for (; jNow < jMax; jNow++) {
363
364 // Final-state only.
365 if (!e[jNow].isFinal()) continue;
366 // Exclude photons (and W/Z!)
367 if (m_QEDvetoMode==0 && e[jNow].colType() == 0) continue;
368
369 // POWHEG.
370 if (m_pTdefMode == 0 || m_pTdefMode == 1) {
371
372 // ISR - only done once as just kinematical pT.
373 if (!FSR) {
374 pTnow = pTpowheg(e, iInA, jNow, (m_pTdefMode == 0) ? false : FSR);
375 if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
376
377 // FSR - try all outgoing partons from system before branching
378 // as i. Note that for the hard system, there is no
379 // "before branching" information.
380 } else {
381
382 int outSize = partonSystemsPtr->sizeOut(0);
383 for (int iMem = 0; iMem < outSize; iMem++) {
384 int iNow = partonSystemsPtr->getOut(0, iMem);
385
386 // i != jNow and no carbon copies
387 if (iNow == jNow ) continue;
388 // Exclude photons (and W/Z!)
389 if (m_QEDvetoMode==0 && e[iNow].colType() == 0) continue;
390 if (jNow == e[iNow].daughter1()
391 && jNow == e[iNow].daughter2()) continue;
392
393 pTnow = pTpowheg(e, iNow, jNow, (m_pTdefMode == 0)
394 ? false : FSR);
395 if (pTnow > 0.) pTemt = (pTemt < 0)
396 ? pTnow : min(pTemt, pTnow);
397 }
398 // for (iMem)
399 }
400 // if (!FSR)
401 // Pythia.
402 } else if (m_pTdefMode == 2) {
403
404 // ISR - other incoming as recoiler.
405 if (!FSR) {
406 pTnow = pT(e, iInA, jNow, iInB, FSR);
407 if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
408 pTnow = pT(e, iInB, jNow, iInA, FSR);
409 if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
410
411 // FSR - try all final-state coloured partons as radiator
412 // after emission (k).
413 } else {
414 for (int kNow = 0; kNow < e.size(); kNow++) {
415 if (kNow == jNow || !e[kNow].isFinal()) continue;
416 if (m_QEDvetoMode==0 && e[kNow].colType() == 0) continue;
417
418 // For this kNow, need to have a recoiler.
419 // Try two incoming.
420 pTnow = pT(e, kNow, jNow, iInA, FSR);
421 if (pTnow > 0.) pTemt = (pTemt < 0)
422 ? pTnow : min(pTemt, pTnow);
423 pTnow = pT(e, kNow, jNow, iInB, FSR);
424 if (pTnow > 0.) pTemt = (pTemt < 0)
425 ? pTnow : min(pTemt, pTnow);
426
427 // Try all other outgoing.
428 for (int rNow = 0; rNow < e.size(); rNow++) {
429 if (rNow == kNow || rNow == jNow ||
430 !e[rNow].isFinal()) continue;
431 if(m_QEDvetoMode==0 && e[rNow].colType() == 0) continue;
432 pTnow = pT(e, kNow, jNow, rNow, FSR);
433 if (pTnow > 0.) pTemt = (pTemt < 0)
434 ? pTnow : min(pTemt, pTnow);
435 }
436 // for (rNow)
437 }
438 // for (kNow)
439 }
440 // if (!FSR)
441 }
442 // if (m_pTdefMode)
443 }
444 // for (j)
445 }
446 }
447 // for (xSR)
448
449 return pTemt;
450 }
451
452 //--------------------------------------------------------------------------
453
454 // Extraction of m_pThard based on the incoming event.
455 // Assume that all the final-state particles are in a continuous block
456 // at the end of the event and the final entry is the POWHEG emission.
457 // If there is no POWHEG emission, then m_pThard is set to SCALUP.
458
459 inline bool canVetoMPIStep() { return true; }
460 inline int numberVetoMPIStep() { return 1; }
461 inline bool doVetoMPIStep(int nMPI, const Event &e) {
462 // Extra check on nMPI
463 if (nMPI > 1) return false;
464 int iEmt = -1;
465 double pT1(0.), pTsum(0.);
466
467 // When m_nFinal is set, be strict about comparing the number of final-state
468 // particles with expectation from Born and single-real emission states.
469 // (Note: the default from 8.309 onwards is m_nFinal = -1).
470 if (m_nFinal > 0) {
471 // Find if there is a POWHEG emission. Go backwards through the
472 // event record until there is a non-final particle. Also sum pT and
473 // find pT_1 for possible MPI vetoing
474 int count = 0;
475 for (int i = e.size() - 1; i > 0; i--) {
476 if (e[i].isFinal()) {
477 count++;
478 pT1 = e[i].pT();
479 pTsum += e[i].pT();
480 } else break;
481 }
482 // Extra check that we have the correct final state
483 if (count != m_nFinal && count != m_nFinal + 1) {
484 loggerPtr->ABORT_MSG("wrong number of final state particles in event");
485 exit(1);
486 }
487 // Flag if POWHEG radiation present and index
488 m_isEmt = (count == m_nFinal) ? false : true;
489 iEmt = (m_isEmt) ? e.size() - 1 : -1;
490
491 // If m_nFinal == -1, then go through the event and extract only the
492 // information on the emission and its pT, but do not enforce strict
493 // comparisons of final state multiplicity.
494 } else {
495
496 // Flag whether POWHEG radiation is present, and save index of emission.
497 m_isEmt = false;
498 for (int i = e.size() - 1; i > 0; i--) {
499 if (e[i].isFinal()) {
500 if ( e[i].isParton() && iEmt < 0
501 && e[e[i].mother1()].isParton() ) {
502 m_isEmt = true;
503 iEmt = i;
504 }
505 pT1 = e[i].pT();
506 pTsum += e[i].pT();
507 } else break;
508 }
509 }
510
511 // If there is no radiation or if m_pThardMode is 0 then set m_pThard = SCALUP.
512 if (!m_isEmt || m_pThardMode == 0) {
513 m_pThard = infoPtr->scalup();
514
515 // If m_pThardMode is 1 then the pT of the POWHEG emission is checked against
516 // all other incoming and outgoing partons, with the minimal value taken.
517 } else if (m_pThardMode == 1) {
518 if (m_nFinal < 0) {
519 loggerPtr->WARNING_MSG(
520 "pThard == 1 not available for m_nFinal == -1, reset pThard = 0. (But might be reset later by child class)");
521 m_pThardMode = 0;
522 m_pThard = infoPtr->scalup();
523 } else {
524 m_pThard = pTcalc(e, -1, iEmt, -1, -1, -1);
525 }
526
527 // If m_pThardMode is 2, then the pT of all final-state partons is checked
528 // against all other incoming and outgoing partons, with the minimal value
529 // taken.
530 } else if (m_pThardMode == 2) {
531 if (m_nFinal < 0) {
532 loggerPtr->WARNING_MSG(
533 "pThard == 2 not available for m_nFinal == -1, reset pThard = 0. (But might be reset later by child class)");
534 m_pThardMode = 0;
535 m_pThard = infoPtr->scalup();
536 } else {
537 m_pThard = pTcalc(e, -1, -1, -1, -1, -1);
538 }
539 }
540
541 // Find MPI veto pT if necessary.
542 if (m_MPIvetoMode == 1) {
543 m_pTMPI = (m_isEmt) ? pTsum / 2. : pT1;
544 }
545
546 // Initialise other variables.
547 m_accepted = false;
549
550 // Do not veto the event
551 return false;
552 }
553
554 //--------------------------------------------------------------------------
555
556 // ISR veto.
557
558 inline bool canVetoISREmission() { return (m_vetoMode == 0) ? false : true; }
559 inline bool doVetoISREmission(int, const Event &e, int iSys) {
560 // Must be radiation from the hard system
561 if (iSys != 0) return false;
562
563 // If we already have m_accepted 'm_vetoCount' emissions in a row, do nothing
564 if (m_vetoMode == 1 && m_nAcceptSeq >= m_vetoCount) return false;
565
566 // Pythia radiator after, emitted and recoiler after.
567 int iRadAft = -1, iEmt = -1, iRecAft = -1;
568 for (int i = e.size() - 1; i > 0; i--) {
569 if (m_showerModel == 1) {
570 // Pythia.
571 if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
572 else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
573 else if (iRecAft == -1 && e[i].status() == -42) iRecAft = i;
574 } else if (m_showerModel == 2) {
575 // Vincia.
576 if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
577 else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
578 else if (iRecAft == -1
579 && (e[i].status() == -41 || e[i].status() == 44)) iRecAft = i;
580 } else if (m_showerModel == 3) {
581 // Dire.
582 if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
583 else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
584 else if (iRecAft == -1
585 && (e[i].status() == -41
586 || e[i].status() == 44 || e[i].status() == 48)) iRecAft = i;
587 }
588 if (iRadAft != -1 && iEmt != -1 && iRecAft != -1) break;
589 }
590 if (iRadAft == -1 || iEmt == -1 || iRecAft == -1) {
591 loggerPtr->ABORT_MSG("could not find ISR emission");
592 exit(1);
593 }
594
595 // m_pTemtMode == 0: pT of emitted w.r.t. radiator
596 // m_pTemtMode == 1: min(pT of emitted w.r.t. all incoming/outgoing)
597 // m_pTemtMode == 2: min(pT of all outgoing w.r.t. all incoming/outgoing)
598 int xSR = (m_pTemtMode == 0) ? 0 : -1;
599 int i = (m_pTemtMode == 0) ? iRadAft : -1;
600 int j = (m_pTemtMode != 2) ? iEmt : -1;
601 int k = -1;
602 int r = (m_pTemtMode == 0) ? iRecAft : -1;
603 double pTemt = pTcalc(e, i, j, k, r, xSR);
604
605 // If a Born configuration, and a photon, and m_QEDvetoMode=2,
606 // then don't veto photons, W, or Z harder than m_pThard.
607 bool vetoParton = (!m_isEmt && e[iEmt].colType()==0 && m_QEDvetoMode==2)
608 ? false: true;
609
610 // Veto if pTemt > m_pThard.
611 if (pTemt > m_pThard) {
612 if(!vetoParton) {
613 // Don't veto ANY emissions afterwards.
615 } else {
616 m_nAcceptSeq = 0;
617 m_nISRveto++;
618 return true;
619 }
620 }
621
622 // Else mark that an emission has been m_accepted and continue.
623 m_nAcceptSeq++;
624 m_accepted = true;
625 return false;
626 }
627
628 //--------------------------------------------------------------------------
629
630 // FSR veto.
631
632 inline bool canVetoFSREmission() { return (m_vetoMode == 0) ? false : true; }
633 inline bool doVetoFSREmission(int, const Event &e, int iSys, bool) {
634 // Must be radiation from the hard system.
635 if (iSys != 0) return false;
636
637 // If we already have m_accepted 'm_vetoCount' emissions in a row, do nothing.
638 if (m_vetoMode == 1 && m_nAcceptSeq >= m_vetoCount) return false;
639
640 // Pythia radiator (before and after), emitted and recoiler (after).
641 int iRecAft = e.size() - 1;
642 int iEmt = e.size() - 2;
643 int iRadAft = e.size() - 3;
644 int iRadBef = e[iEmt].mother1();
645 bool stop = false;
646 if (m_showerModel == 1 || m_showerModel == 3) {
647 // Pythia or Dire.
648 if ( (e[iRecAft].status() != 52 && e[iRecAft].status() != -53) ||
649 e[iEmt].status() != 51 || e[iRadAft].status() != 51) stop = true;
650 } else if (m_showerModel == 2) {
651 // Vincia.
652 if ( (e[iRecAft].status() != 51 && e[iRecAft].status() != 52) ||
653 e[iEmt].status() != 51 || e[iRadAft].status() != 51) stop = true;
654 }
655 if (stop) {
656 loggerPtr->ABORT_MSG("could not find FSR emission");
657 exit(1);
658 }
659
660 // Behaviour based on m_pTemtMode:
661 // 0 - pT of emitted w.r.t. radiator before
662 // 1 - min(pT of emitted w.r.t. all incoming/outgoing)
663 // 2 - min(pT of all outgoing w.r.t. all incoming/outgoing)
664 int xSR = (m_pTemtMode == 0) ? 1 : -1;
665 int i = (m_pTemtMode == 0) ? iRadBef : -1;
666 int k = (m_pTemtMode == 0) ? iRadAft : -1;
667 int r = (m_pTemtMode == 0) ? iRecAft : -1;
668
669 // When m_pTemtMode is 0 or 1, iEmt has been selected.
670 double pTemt = 0.;
671 if (m_pTemtMode == 0 || m_pTemtMode == 1) {
672 // Which parton is emitted, based on m_emittedMode:
673 // 0 - Pythia definition of emitted
674 // 1 - Pythia definition of radiated after emission
675 // 2 - Random selection of emitted or radiated after emission
676 // 3 - Try both emitted and radiated after emission
677 int j = iRadAft;
678 if (m_emittedMode == 0 || (m_emittedMode == 2 && rndmPtr->flat() < 0.5)) j++;
679
680 for (int jLoop = 0; jLoop < 2; jLoop++) {
681 if (jLoop == 0) pTemt = pTcalc(e, i, j, k, r, xSR);
682 else if (jLoop == 1) pTemt = min(pTemt, pTcalc(e, i, j, k, r, xSR));
683
684 // For m_emittedMode == 3, have tried iRadAft, now try iEmt
685 if (m_emittedMode != 3) break;
686 if (k != -1) swap(j, k); else j = iEmt;
687 }
688
689 // If m_pTemtMode is 2, then try all final-state partons as emitted
690 } else if (m_pTemtMode == 2) {
691 pTemt = pTcalc(e, i, -1, k, r, xSR);
692
693 }
694
695 // If a Born configuration, and a photon, and m_QEDvetoMode=2,
696 // then don't veto photons, W's or Z's harder than m_pThard
697 bool vetoParton = (!m_isEmt && e[iEmt].colType()==0 && m_QEDvetoMode==2)
698 ? false: true;
699
700 // Veto if pTemt > m_pThard
701 if (pTemt > m_pThard) {
702 if(!vetoParton) {
703 // Don't veto ANY emissions afterwards
705 } else {
706 m_nAcceptSeq = 0;
707 m_nFSRveto++;
708 return true;
709 }
710 }
711
712 // Else mark that an emission has been m_accepted and continue
713 m_nAcceptSeq++;
714 m_accepted = true;
715 return false;
716 }
717
718 //--------------------------------------------------------------------------
719
720 // MPI veto.
721
722 inline bool canVetoMPIEmission() {return (m_MPIvetoMode == 0) ? false : true;}
723 inline bool doVetoMPIEmission(int, const Event &e) {
724 if (m_MPIvetoMode == 1) {
725 if (e[e.size() - 1].pT() > m_pTMPI) return true;
726 }
727 return false;
728 }
729
730 //--------------------------------------------------------------------------
731
732 // Functions to return information.
733
734 inline int getNISRveto() { return m_nISRveto; }
735 inline int getNFSRveto() { return m_nFSRveto; }
736
737 //--------------------------------------------------------------------------
738
739 //--------------------------------------------------------------------------
740 // Setter function of m_pThard, if this is calculated outside of base class UserHook
741 inline void setpThard(double newPThard) {m_pThard = newPThard;}
742
743 //--------------------------------------------------------------------------
744
745 private:
750 // The number of m_accepted emissions (in a row)
751 // Flag for PowHeg Born or Radiation
753 // Statistics on vetos
754 unsigned long int m_nISRveto, m_nFSRveto;
755
756};
757
758//==========================================================================
759
760} // end namespace Pythia8
761
762#endif // end Pythia8_PowhegHooksSetterMethod_H
bool isResonance(const T &p)
Definition AtlasPID.h:400
bool isParton(const T &p)
Definition AtlasPID.h:1103
int sign(int a)
static const std::map< unsigned int, unsigned int > pow2
#define z
#define min(a, b)
Definition cfImp.cxx:40
double pT(const Event &e, int RadAfterBranch, int EmtAfterBranch, int RecAfterBranch, bool FSR)
double pTcalc(const Event &e, int i, int j, int k, int r, int xSRin)
double pTdire(const Event &event, int iRad, int iEmt, int iRec)
bool doVetoISREmission(int, const Event &e, int iSys)
double pTpythia(const Event &e, int RadAfterBranch, int EmtAfterBranch, int RecAfterBranch, bool FSR)
PowhegHooksSetterMethod(Pythia *, Settings *, Logger *)
double pTvincia(const Event &event, int i1, int i3, int i2)
double pTpowheg(const Event &e, int i, int j, bool FSR)
bool doVetoFSREmission(int, const Event &e, int iSys, bool)
bool doVetoMPIStep(int nMPI, const Event &e)
int r
Definition globals.cxx:22
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
Author: James Monk (jmonk@cern.ch)
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)