ATLAS Offline Software
Loading...
Searching...
No Matches
PTRelVetoedShower.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#include "UserHooksUtils.h"
7#include <stdexcept>
8#include <iostream>
9
10namespace Pythia8{
12}
13
15
16namespace Pythia8{
17
34
35 class PTRelVetoedShower : public UserHooks{
36
37 public:
38
40
41 std::cout<<"*************************************************************************"<<std::endl;
42 std::cout<<"* *"<<std::endl;
43 std::cout<<"* Using PTRel vetoed shower for PoWHEG QCD production! *"<<std::endl;
44 std::cout<<"* *"<<std::endl;
45 std::cout<<"*************************************************************************"<<std::endl;
46
47 m_pxCMS = 0;
48 m_pyCMS = 0;
49 m_pzCMS = 0;
50
51 }
52
54
61 bool doVetoMPIStep(int nMPI, const Event &evt){
62
63 // Only do anything on the first call.
64 if(nMPI > 1) return false;
65
66 m_powhegScale = infoPtr->QRen();
67
68 size_t nPwgOutgoing = 0;
69
70 for(int ii = evt.size()-1; ii > 0; --ii){
71 if(! (evt[ii].isFinal())) break;
72 ++nPwgOutgoing;
73 }
74
75 if(nPwgOutgoing == m_nPoWHEGFinal) return false;
76
77 if(nPwgOutgoing != m_nPoWHEGFinal + 1){
78 throw std::runtime_error("Wrong number of final state PoWHEG legs: " + std::to_string(nPwgOutgoing));
79 }
80
81 // momentum components to boost to CMS frame
82 m_pxCMS = 0.;
83 m_pyCMS = 0.;
84 m_pzCMS = 0.;
85 double eCMS = 0.;
86
87 // The outgoing powheg legs
88 std::vector<Particle> powhegLegs;
89
90 // Find the entries corresponding to outgoing legs from PoWHEG
91 // start the loop at 1, since entry 0 represents the event as a whole
92 for(int ii=1; ii != evt.size(); ++ii){
93
94 // status -21 is the incoming hard partons
95 if(evt[ii].status() == -21){
96 m_pxCMS += evt[ii].px();
97 m_pyCMS += evt[ii].py();
98 m_pzCMS += evt[ii].pz();
99 eCMS += evt[ii].e();
100 }
101
102 // here Event::isFinal refers to whether the particle can still decay/radiate, or whether it is an internal leg
103 if(evt[ii].isFinal()){
104 powhegLegs.push_back(Particle(evt[ii]));
105 }
106 }
107
108 // Start the search for the powheg scale above the collision energy,
109 // which is guaranteed to be above the veto scale.
110
111 m_powhegScale = 1.1*infoPtr->s();
112
113 // compare the pT of each leg to the powheg scale.
114 // Set the scale to the lowest
115 for(std::vector<Particle>::const_iterator leg=powhegLegs.begin();
116 leg != powhegLegs.end(); ++leg){
117 double pTTmp = leg->pT();
118 if(pTTmp < m_powhegScale )m_powhegScale = pTTmp;
119 }
120
121 // normalise the boost vector to the CMS frame...
122 double norm = (eCMS == 0.)? 0 : -1./eCMS;
123 m_pxCMS *= norm;
124 m_pyCMS *= norm;
125 m_pzCMS *= norm;
126
127 // ...and boost all outgoing legs to that frame
128 for(std::vector<Particle>::iterator leg=powhegLegs.begin();
129 leg != powhegLegs.end(); ++leg){
130 leg->bst(m_pxCMS, m_pyCMS, m_pzCMS);
131 }
132
133 for(std::vector<Particle>::const_iterator leg=powhegLegs.begin();
134 leg != powhegLegs.end(); ++leg){
135 // calculate the pT relative to each other leg
136 // if any such pT is lower than the current scale, reset the scale to that value
137 for(std::vector<Particle>::const_iterator otherLeg = powhegLegs.begin();
138 otherLeg != powhegLegs.end(); ++otherLeg){
139 if(otherLeg == leg) continue;
140
141 double pTLeg = Pythia8_UserHooks::pTLeg(*leg, *otherLeg);
142
143 if(pTLeg < m_powhegScale) m_powhegScale = pTLeg;
144 }
145 }
146
147 // barf if the scale was not found properly!
148 if(m_powhegScale > infoPtr->s()){
149 throw std::runtime_error("Veto scale could not be determined!");
150 }
151
152 return false;
153 }
154
161 bool doVetoISREmission(int, const Event &evt, int iSys){
162
163 // only veto emissions from the hard system
164 if(iSys != 0) return false;
165
166 size_t emission = Pythia8_UserHooks::findLastISREmission(evt);
167
168 if(evt[emission].pT() > m_powhegScale) return true;
169
170 return false;
171 }
172
177 bool doVetoFSREmission(int, const Event &evt, int iSys, bool){
178 if(iSys != 0) return false;
179
180 size_t emissionIndex = Pythia8_UserHooks::findLastFSREmission(evt);
181 size_t radiatorIndex = Pythia8_UserHooks::findLastFSRRadiator(evt);
182
183 Particle emission(evt[emissionIndex]);
184 Particle radiator(evt[radiatorIndex]);
185
186 emission.bst(m_pxCMS, m_pyCMS, m_pzCMS);
187 radiator.bst(m_pxCMS, m_pyCMS, m_pzCMS);
188
189 double pTRel = Pythia8_UserHooks::pTLeg(emission, radiator);
190 if(pTRel > m_powhegScale) return true;
191
192 return false;
193 }
194
195
197 bool canVetoMPIStep(){return true;}
199 int numberVetoMPIStep(){return 1;}
201 bool canVetoISREmission(){return true;}
203 bool canVetoFSREmission(){return true;}
204
205 private:
206
207 const size_t m_nPoWHEGFinal;
208
210
211 // defines the boost vector to the CMS frame
212 double m_pxCMS;
213 double m_pyCMS;
214 double m_pzCMS;
215
216 };
217}
218
Pythia8_UserHooks::UserHooksFactory::Creator< Pythia8::PTRelVetoedShower > pTRelVetoedShowerCreator("PTRelVetoedShower")
This user hook is derived from the main31 example distributed with Pythia 8 and is for use with QCD e...
bool doVetoFSREmission(int, const Event &evt, int iSys, bool)
This is similar to the ISR veto.
bool doVetoISREmission(int, const Event &evt, int iSys)
This is called after the generation of each new ISR emission Can use it to test if the last generated...
bool canVetoISREmission()
Switch on veto of ISR.
bool canVetoMPIStep()
Switch on calling of doVetoMPIStep.
int numberVetoMPIStep()
Call doVetoMIStep once.
bool doVetoMPIStep(int nMPI, const Event &evt)
doVetoMPIStep is called immediately after the MPI generation In this case it never actually vetoes th...
bool canVetoFSREmission()
Switch off veto of FSR.
size_t findLastFSRRadiator(const Pythia8::Event &evt)
size_t findLastISREmission(const Pythia8::Event &evt)
size_t findLastFSREmission(const Pythia8::Event &evt)
double pTLeg(const Pythia8::Particle &leg, const Pythia8::Particle &comparison)
Author: James Monk (jmonk@cern.ch)