ATLAS Offline Software
Loading...
Searching...
No Matches
DecayToSUEP.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "UserHooksUtils.h"
6#include "UserSetting.h"
8#include <math.h>
9#include <stdexcept>
10#include <iostream>
11
12#include "suep_shower.h"
13
14namespace Pythia8{
15 class DecayToSUEP;
16}
17
19
20// Uncomment the following line to enable debug messages to be printed to std::cout
21//#define SUEP_DEBUG 1
22
23namespace Pythia8{
24
25 //******************************
26 //** Main UserHook derived class
27 //******************************
28
37 class DecayToSUEP : public UserHooks{
38
39 public:
40
42 m_pdgId("DecayToSUEP:PDGId", 25),
43 m_mass("DecayToSUEP:Mass", 125.0),
44 m_darkMesonMass("DecayToSUEP:DarkMesonMass", 1.),
45 m_darkTemperature("DecayToSUEP:DarkTemperature", 1.) {
46
47 std::cout<<"**********************************************************"<<std::endl;
48 std::cout<<"* *"<<std::endl;
49 std::cout<<"* Enabled SUEP decay UserHook! *"<<std::endl;
50 std::cout<<"* *"<<std::endl;
51 std::cout<<"**********************************************************"<<std::endl;
52
53 }
54
56
57 // Enable the call to the user-hook
58 virtual bool canVetoProcessLevel() {
59 return true;
60 }
61
62 /* Actually implement the user hook.
63 *
64 * We slightly abuse this function in the sense that no veto is performed but instead
65 * the hook is used to modify the event record in between the process-level and parton-level steps.
66 * This modification is allowed in the Pythia8 manual, with warning of event consistency that
67 * should pose no harm in this context.
68 */
69 virtual bool doVetoProcessLevel(Event& process);
70
71
72 private:
73
76
79
82
85
86 };
87
88
89 //******************************
90 //** Implementation of DecayToSUEP UserHook
91 //******************************
93 {
94#ifdef SUEP_DEBUG
95 std::cout << "[SUEP_DEBUG] " << "Start of user hook for this event." << std::endl;
96#endif
97
98 //First, find the particle to decay
99 bool particleFound=false;
100
101#ifdef SUEP_DEBUG
102 for (int ii=0; ii < process.size(); ++ii) {
103 std::cout << "[SUEP_DEBUG] " << ii << ": id=" << process[ii].id() << ", Final=" << process[ii].isFinal() << ", Status=" << process[ii].status() << ", daughter1=" << process[ii].daughter1() << ", daughter2=" << process[ii].daughter2() << std::endl;
104 }
105#endif
106
107 for (int ii=0; ii < process.size(); ++ii) {
108 if ( (process[ii].id() == m_pdgId(settingsPtr)) and (process[ii].daughter1()!=process[ii].daughter2() && process[ii].daughter1()>0 && process[ii].daughter2()>0) ) {
109
110 Vec4 higgs4mom, mesonmom;
111 vector< Vec4 > suep_shower4momenta;
112 particleFound=true;
113
114 //setup SUEP shower
115 static Suep_shower suep_shower(m_darkMesonMass(settingsPtr), m_darkTemperature(settingsPtr), m_mass(settingsPtr), rndmPtr);
116
117#ifdef SUEP_DEBUG
118 std::cout << "[SUEP_DEBUG] " << "Particle (pdgId=" << m_pdgId(settingsPtr) << ", isFinal=True) found. Decaying to SUEP now." << std::endl;
119#endif
120
121 // First undo decay
122 process[ii].undoDecay();
123
124 int originalEventSize = process.size();
125
126 // Generate the shower, output are 4 vectors in the rest frame of the shower
127 higgs4mom=process[ii].p();
128 int nShowerAttempts=0;
129 do {
130 try {
131 nShowerAttempts++;
132 suep_shower4momenta=suep_shower.generate_shower();
133 if( suep_shower4momenta.size()<3){
134 //Failed to balance energy or less than 3 particles in the shower
135 //Try again until nShowerAttempts >= 3
136 } else {
137 //All ok!
138 nShowerAttempts = -1; //exit condition
139 }
140 } catch (std::exception &e) {
141 //Failed to generate the shower!
142 //Can happen in some rare circumstances,
143 //Try again until nShowerAttempts >= 3
144 }
145 } while ((nShowerAttempts > 0) && (nShowerAttempts < 3));
146 if (nShowerAttempts >= 3) {
147 //Something is seriously wrong then, print warning and skip to next event
148 std::cout << "[SUEP] WARNING: Something went wrong in generating the shower. Skipping the event." << std::endl;
149 return true; //veto the event!
150 }
151
152 // Loop over hidden sector mesons and append to the event
153 for (unsigned j = 0; j < suep_shower4momenta.size(); ++j){
154 //construct pythia 4vector
155 mesonmom = suep_shower4momenta[j];
156
157 // boost to the lab frame
158 mesonmom.bst(higgs4mom.px()/higgs4mom.e(),higgs4mom.py()/higgs4mom.e(), higgs4mom.pz()/higgs4mom.e());
159
160 //append particle to the event. Hidden/dark meson pdg code is 999999.
161 process.append(999999, 91, ii, 0, 0, 0, 0, 0, mesonmom.px(), mesonmom.py(), mesonmom.pz(), mesonmom.e(), m_darkMesonMass(settingsPtr));
162
163#ifdef SUEP_DEBUG
164 std::cout << "[SUEP_DEBUG] " << "Adding dark meson with px=" << mesonmom.px() << ", py=" << mesonmom.py() << ", pz=" << mesonmom.pz() << ", m=" << m_darkMesonMass(settingsPtr) << std::endl;
165#endif
166 }
167
168 // Just to be sure, only modify Higgs status and daughters if a valid decay did happen
169 if ( suep_shower4momenta.size() > 0 ) {
170#ifdef SUEP_DEBUG
171 std::cout << "[SUEP_DEBUG] " << "Setting original particle status-code as non-Final particle. Adding daughters with indices: " << originalEventSize << " - " << process.size()-1 << std::endl;
172#endif
173 // Change the status code of the Higgs to reflect that it has decayed.
174 process[ii].statusNeg();
175
176 //set daughters of the Higgs. Take advantage that we just appended them
177 process[ii].daughters(originalEventSize, process.size()-1);
178 }
179
180 //no need to continue the loop
181 break;
182
183 } // if particle to decay found
184
185 } // loop over particles in the event
186
187 if (not particleFound) {
188 std::cout << "[DecayToSUEP] " << "Particle " << m_pdgId(settingsPtr) << " not found. Nothing to decay to SUEP for this event." << std::endl;
189 } else {
190#ifdef SUEP_DEBUG
191 std::cout << "[SEUP_DEBUG] " << "All Done for this event." << std::endl;
192#endif
193 }
194#ifdef SUEP_DEBUG
195 std::cout << "[SUEP_DEBUG] Printing event after adding SUEP:" << std::endl;
196 for (int ii=0; ii < process.size(); ++ii) {
197 std::cout << "[SUEP_DEBUG] " << ii << ": id=" << process[ii].id() << ", Final=" << process[ii].isFinal() << ", mayDecay=" << process[ii].mayDecay() << ", Status=" << process[ii].status() << ", daughter1=" << process[ii].daughter1() << ", daughter2=" << process[ii].daughter2() << std::endl;
198 }
199#endif
200
201 //return false: let the event continue
202 return false;
203 }
204
205
206} // namespace Pythia8
Pythia8_UserHooks::UserHooksFactory::Creator< Pythia8::DecayToSUEP > DecayToSUEPCreator("DecayToSUEP")
Pythia8 UserHook to decay a given scalar particle to SUEP.
Pythia8_UserHooks::UserSetting< double > m_darkTemperature
Temperature parameter [GeV].
Pythia8_UserHooks::UserSetting< int > m_pdgId
PDG Id of particle to be decayed to SUEP.
Pythia8_UserHooks::UserSetting< double > m_mass
Mass of system decaying [GeV].
virtual bool canVetoProcessLevel()
Pythia8_UserHooks::UserSetting< double > m_darkMesonMass
Dark-meson mass parameter [GeV].
virtual bool doVetoProcessLevel(Event &process)
Auxiliary class for SUEP generation.
Definition suep_shower.h:31
std::vector< Pythia8::Vec4 > generate_shower()
Generate a shower event, in the rest frame of the showe.
const std::string process
Author: James Monk (jmonk@cern.ch).