ATLAS Offline Software
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 
24 namespace Pythia8 {
25 
26 //==========================================================================
27 
28 // Use userhooks to veto PYTHIA emissions above the POWHEG scale.
29 
30 class PowhegHooksSetterMethod : public UserHooks {
31 
32 public:
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
40  m_showerModel(1),
41  m_nFinal(-1),
42  m_vetoMode(0),
43  m_MPIvetoMode(0),
44  m_QEDvetoMode(0),
45  m_vetoCount(3),
46  m_pThardMode(0),
47  m_pTemtMode(0),
48  m_emittedMode(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*):
58  m_showerModel(1),
59  m_nFinal(-1),
60  m_vetoMode(0),
61  m_MPIvetoMode(0),
62  m_QEDvetoMode(0),
63  m_vetoCount(3),
64  m_pThardMode(0),
65  m_pTemtMode(0),
66  m_emittedMode(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.
80  bool initAfterBeams() {
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:
748  double m_pThard, m_pTMPI;
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
Pythia8::PowhegHooksSetterMethod::m_nFinal
int m_nFinal
Definition: PowhegHooksSetterMethod.cxx:746
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
beamspotman.r
def r
Definition: beamspotman.py:674
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:215
Pythia8::PowhegHooksSetterMethod::m_QEDvetoMode
int m_QEDvetoMode
Definition: PowhegHooksSetterMethod.cxx:746
Pythia8::PowhegHooksSetterMethod::PowhegHooksSetterMethod
PowhegHooksSetterMethod(Pythia *, Settings *, Logger *)
Definition: PowhegHooksSetterMethod.cxx:57
Pythia8::PowhegHooksSetterMethod::PowhegHooksSetterMethod
PowhegHooksSetterMethod()
Definition: PowhegHooksSetterMethod.cxx:39
Pythia8::PowhegHooksSetterMethod::m_MPIvetoMode
int m_MPIvetoMode
Definition: PowhegHooksSetterMethod.cxx:746
FSR
Definition: FsrPhotonTool.h:25
Pythia8::PowhegHooksSetterMethod::canVetoMPIEmission
bool canVetoMPIEmission()
Definition: PowhegHooksSetterMethod.cxx:722
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
Event
Definition: trigbs_orderedMerge.cxx:42
bTosllAli.Pythia
Pythia
Definition: bTosllAli.py:46
TRTCalib_cfilter.p1
p1
Definition: TRTCalib_cfilter.py:130
Pythia8::PowhegHooksSetterMethod::m_nFSRveto
unsigned long int m_nFSRveto
Definition: PowhegHooksSetterMethod.cxx:754
Pythia8::PowhegHooksSetterMethod::m_pThard
double m_pThard
Definition: PowhegHooksSetterMethod.cxx:748
Pythia8::PowhegHooksSetterMethod::canVetoFSREmission
bool canVetoFSREmission()
Definition: PowhegHooksSetterMethod.cxx:632
isResonance
bool isResonance(const T &p)
Definition: AtlasPID.h:397
isParton
bool isParton(const T &p)
Definition: AtlasPID.h:1072
PixelModuleFeMask_create_db.stop
int stop
Definition: PixelModuleFeMask_create_db.py:76
Pythia8::PowhegHooksSetterMethod::m_nAcceptSeq
int m_nAcceptSeq
Definition: PowhegHooksSetterMethod.cxx:752
xAOD::Particle
Particle_v1 Particle
Define the latest version of the particle class.
Definition: Event/xAOD/xAODParticleEvent/xAODParticleEvent/Particle.h:17
XMLtoHeader.count
count
Definition: XMLtoHeader.py:84
Pythia8::PowhegHooksSetterMethod::initAfterBeams
bool initAfterBeams()
Definition: PowhegHooksSetterMethod.cxx:80
Pythia8
Author: James Monk (jmonk@cern.ch)
Definition: IPythia8Custom.h:10
Pythia8::PowhegHooksSetterMethod
Definition: PowhegHooksSetterMethod.cxx:30
TRTCalib_cfilter.p2
p2
Definition: TRTCalib_cfilter.py:131
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
Pythia8::PowhegHooksSetterMethod::~PowhegHooksSetterMethod
~PowhegHooksSetterMethod()
Definition: PowhegHooksSetterMethod.cxx:75
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
Pythia8::PowhegHooksSetterMethod::doVetoMPIEmission
bool doVetoMPIEmission(int, const Event &e)
Definition: PowhegHooksSetterMethod.cxx:723
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
Pythia8::PowhegHooksSetterMethod::pTdire
double pTdire(const Event &event, int iRad, int iEmt, int iRec)
Definition: PowhegHooksSetterMethod.cxx:233
Pythia8::PowhegHooksSetterMethod::m_pTdefMode
int m_pTdefMode
Definition: PowhegHooksSetterMethod.cxx:747
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
Pythia8::PowhegHooksSetterMethod::doVetoMPIStep
bool doVetoMPIStep(int nMPI, const Event &e)
Definition: PowhegHooksSetterMethod.cxx:461
Pythia8::PowhegHooksSetterMethod::m_pTemtMode
int m_pTemtMode
Definition: PowhegHooksSetterMethod.cxx:747
Pythia8::PowhegHooksSetterMethod::getNISRveto
int getNISRveto()
Definition: PowhegHooksSetterMethod.cxx:734
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:107
Pythia8::PowhegHooksSetterMethod::m_nISRveto
unsigned long int m_nISRveto
Definition: PowhegHooksSetterMethod.cxx:754
Pythia8::PowhegHooksSetterMethod::m_vetoMode
int m_vetoMode
Definition: PowhegHooksSetterMethod.cxx:746
python.SystemOfUnits.rad
float rad
Definition: SystemOfUnits.py:126
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
Pythia8::PowhegHooksSetterMethod::m_showerModel
int m_showerModel
Definition: PowhegHooksSetterMethod.cxx:746
calibdata.exit
exit
Definition: calibdata.py:235
Pythia8::PowhegHooksSetterMethod::canVetoMPIStep
bool canVetoMPIStep()
Definition: PowhegHooksSetterMethod.cxx:459
Pythia8::PowhegHooksSetterMethod::numberVetoMPIStep
int numberVetoMPIStep()
Definition: PowhegHooksSetterMethod.cxx:460
Pythia8::PowhegHooksSetterMethod::pTcalc
double pTcalc(const Event &e, int i, int j, int k, int r, int xSRin)
Definition: PowhegHooksSetterMethod.cxx:325
Pythia8::PowhegHooksSetterMethod::canVetoISREmission
bool canVetoISREmission()
Definition: PowhegHooksSetterMethod.cxx:558
Pythia8::PowhegHooksSetterMethod::m_pTMPI
double m_pTMPI
Definition: PowhegHooksSetterMethod.cxx:748
Pythia8::PowhegHooksSetterMethod::pTvincia
double pTvincia(const Event &event, int i1, int i3, int i2)
Definition: PowhegHooksSetterMethod.cxx:171
Pythia8::PowhegHooksSetterMethod::m_accepted
bool m_accepted
Definition: PowhegHooksSetterMethod.cxx:749
Pythia8::PowhegHooksSetterMethod::setpThard
void setpThard(double newPThard)
Definition: PowhegHooksSetterMethod.cxx:741
Pythia8::PowhegHooksSetterMethod::m_emittedMode
int m_emittedMode
Definition: PowhegHooksSetterMethod.cxx:747
Pythia8::PowhegHooksSetterMethod::getNFSRveto
int getNFSRveto()
Definition: PowhegHooksSetterMethod.cxx:735
Pythia8::PowhegHooksSetterMethod::m_pThardMode
int m_pThardMode
Definition: PowhegHooksSetterMethod.cxx:747
Pythia8::PowhegHooksSetterMethod::m_isEmt
bool m_isEmt
Definition: PowhegHooksSetterMethod.cxx:749
Pythia8::PowhegHooksSetterMethod::pTpowheg
double pTpowheg(const Event &e, int i, int j, bool FSR)
Definition: PowhegHooksSetterMethod.cxx:285
merge.status
status
Definition: merge.py:16
Pythia8::PowhegHooksSetterMethod::m_vetoCount
int m_vetoCount
Definition: PowhegHooksSetterMethod.cxx:746
Pythia8::PowhegHooksSetterMethod::pT
double pT(const Event &e, int RadAfterBranch, int EmtAfterBranch, int RecAfterBranch, bool FSR)
Definition: PowhegHooksSetterMethod.cxx:102
TRTCalib_cfilter.p3
p3
Definition: TRTCalib_cfilter.py:132
Pythia8::PowhegHooksSetterMethod::doVetoFSREmission
bool doVetoFSREmission(int, const Event &e, int iSys, bool)
Definition: PowhegHooksSetterMethod.cxx:633
python.SystemOfUnits.m2
float m2
Definition: SystemOfUnits.py:107
fitman.k
k
Definition: fitman.py:528
Pythia8::PowhegHooksSetterMethod::pTpythia
double pTpythia(const Event &e, int RadAfterBranch, int EmtAfterBranch, int RecAfterBranch, bool FSR)
Definition: PowhegHooksSetterMethod.cxx:117
Pythia8::PowhegHooksSetterMethod::doVetoISREmission
bool doVetoISREmission(int, const Event &e, int iSys)
Definition: PowhegHooksSetterMethod.cxx:559