ATLAS Offline Software
Loading...
Searching...
No Matches
TopRecoilHook.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// PowhegHooksBB4L.h
6// Copyright (C) 2017 Tomas Jezo, Markus Seidel, Ben Nachman
7
8// Author: Tomas Jezo, Markus Seidel and Ben Nachman based on
9// PowhegHooks.h by Richard Corke
10
12#include "UserSetting.h"
13
14namespace Pythia8 {
15
16 // Create the user hook
17 class TopRecoilHook;
19
20 // Use userhooks to veto PYTHIA emissions above the POWHEG scale
21 class TopRecoilHook : public UserHooks {//class PowhegHooksBB4L : public PowhegHooks {
22
23 public:
24
25 // Constructor.
26 // m_doTopRecoil : eikonal correction in GW dipole on/off when no MEC applied.
27 // m_useOldDipole : in GW dipole, use partons before or after branching.
28 // m_doList : diagnostic output; set false for production runs.
29 TopRecoilHook(bool doTopRecoilIn=true, bool useOldDipoleIn=false, bool doListIn = false) {
30 m_doTopRecoil = doTopRecoilIn;
31 m_useOldDipole = useOldDipoleIn;
32 m_doList = doListIn;
33 // Constructor also creates some histograms for analysis inside User Hook.
34 m_wtCorr = new Hist("corrective weight", 100, 0., 2.);
35 std::cout << " enabling TopRecoilHook"<< std::endl;
36
37 }
38
39 // Destructor prints histogram.
40 ~TopRecoilHook() override {
41 if (m_doTopRecoil) cout << *m_wtCorr;
42 delete m_wtCorr;
43 }
44
45
46 // Initialise. Only use hook for simple showers with recoilToColoured = off.
47 virtual bool initAfterBeams() override {
48
49 // Switch off if not using simple showers or if recoilToColoured = on.
50 bool recoilToColoured = settingsPtr->flag("TimeShower:recoilToColoured");
51 if (recoilToColoured){
52 m_doTopRecoil=false;
53 std::cout << " TopRecoilHook should not be used with RecoilToColoured=on; disabling"<< std::endl;
54 }
55 // Flag if W mass term is already accounted for (true) or not (false).
56 m_recoilDeadCone = settingsPtr->flag("TimeShower:recoilDeadCone");
57 // All ok.
58 return true;
59 }
60
61 // Allow a veto after an FSR emission
62 virtual bool canVetoFSREmission() override {return m_doTopRecoil;}
63
64 // Access the event after an FSR emission, specifically inside top decay.
65 virtual bool doVetoFSREmission( int sizeOld, const Event& event, int iSys,
66 bool inResonance) override {
67
68 // Check that we are inside a resonance decay.
69 if (!inResonance) return false;
70
71 // Check that it is a top decay.
72 int iTop = partonSystemsPtr->getInRes(iSys);
73 if (iTop == 0 || event[iTop].idAbs() != 6) return false;
74
75 // Skip first emission, where ME corrections are already made.
76 int sizeOut = partonSystemsPtr->sizeOut(iSys);
77 if (sizeOut == 2) return false;
78
79 // Location of trial new particles: radiator, emitted, recoiler.
80 int iRad = sizeOld;
81 int iEmt = sizeOld + 1;
82 int iRec = sizeOld + 2;
83
84 // The above partons are after emission;
85 // alternatively use the ones before.
86 if (m_useOldDipole) {
87 iRad = event[iRad].mother1();
88 iRec = event[iRec].mother1();
89 }
90
91 // Check if newly emitted gluon matches (anti)top colour line.
92 if (event[iEmt].id() != 21) return false;
93 if (event[iTop].id() == 6) {
94 if (event[iEmt].col() != event[iTop].col()) return false;
95 } else {
96 if (event[iEmt].acol() != event[iTop].acol()) return false;
97 }
98
99 // Recoiler should now be a W, else something is wrong.
100 if (event[iRec].idAbs() != 24) {
101 cout << " ERROR: recoiler is " << event[iRec].id() << endl;
102 return false;
103 }
104
105 // Denominator: eikonal weight with W as recoiler.
106 double pRadRec = event[iRad].p() * event[iRec].p();
107 double pRadEmt = event[iRad].p() * event[iEmt].p();
108 double pRecEmt = event[iRec].p() * event[iEmt].p();
109 double wtW = 2. * pRadRec / (pRadEmt * pRecEmt)
110 - pow2(event[iRad].m() / pRadEmt);
111 // If m_recoilDeadCone = on, include W mass term in denominator.
112 if (m_recoilDeadCone) wtW -= pow2(event[iRec].m() / pRecEmt);
113
114 // Numerator: eikonal weight with top as recoiler.
115 double pRadTop = event[iRad].p() * event[iTop].p();
116 double pTopEmt = event[iTop].p() * event[iEmt].p();
117 double wtT = 2. * pRadTop / (pRadEmt * pTopEmt)
118 - pow2(event[iRad].m() / pRadEmt) - pow2(event[iTop].m() / pTopEmt);
119
120 // Histogram weight ratio.
121 m_wtCorr->fill( wtT / wtW );
122
123 // List relevant properties.
124 if (m_doList) {
125 std::ios oldState(nullptr);
126 std::cout << "\n now event with sizeOld = " << sizeOld << ", iSys = "
127 << iSys << ", sizeOut = " << sizeOut << scientific
128 << setprecision(3)
129 << ", weight with W = " << wtW << " and with t = " << wtT << std::endl;
130 partonSystemsPtr->list();
131 event.list();
132 std::cout.copyfmt(oldState);
133 }
134
135 // Accept/reject emission. Smooth suppression or step function.
136 return (wtT < wtW * rndmPtr->flat());
137 }
138
139
140private:
141
142 // Options and Histograms.
144 Hist *m_wtCorr{};
145
146 };
147
148//==========================================================================
149
150} // end namespace Pythia8
static const std::map< unsigned int, unsigned int > pow2
virtual bool canVetoFSREmission() override
TopRecoilHook(bool doTopRecoilIn=true, bool useOldDipoleIn=false, bool doListIn=false)
virtual bool initAfterBeams() override
virtual bool doVetoFSREmission(int sizeOld, const Event &event, int iSys, bool inResonance) override
Author: James Monk (jmonk@cern.ch)
Pythia8_UserHooks::UserHooksFactory::Creator< Pythia8::TopRecoilHook > TopRecoilHookCreator("TopRecoilHook")