EvtGen 2.2.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
Loading...
Searching...
No Matches
EvtPHOTOS.cpp
Go to the documentation of this file.
1
2/***********************************************************************
3* Copyright 1998-2020 CERN for the benefit of the EvtGen authors *
4* *
5* This file is part of EvtGen. *
6* *
7* EvtGen is free software: you can redistribute it and/or modify *
8* it under the terms of the GNU General Public License as published by *
9* the Free Software Foundation, either version 3 of the License, or *
10* (at your option) any later version. *
11* *
12* EvtGen is distributed in the hope that it will be useful, *
13* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15* GNU General Public License for more details. *
16* *
17* You should have received a copy of the GNU General Public License *
18* along with EvtGen. If not, see <https://www.gnu.org/licenses/>. *
19***********************************************************************/
20
21#ifdef EVTGEN_PHOTOS
22
24
25#include "EvtGenBase/EvtPDL.hh"
30
31#include <iostream>
32#include <sstream>
33#include <vector>
34
35using std::endl;
36
37// Mutex PHOTOS as it is not thread safe.
38bool EvtPHOTOS::m_initialised = false;
40
41EvtPHOTOS::EvtPHOTOS( const std::string& photonType, const bool useEvtGenRandom,
42 const double infraredCutOff,
43 const double maxWtInterference ) :
44 m_useEvtGenRandom{ useEvtGenRandom },
45 m_infraredCutOff{ infraredCutOff },
46 m_maxWtInterference{ maxWtInterference },
47 m_photonType{ photonType }
48{
49}
50
52{
53 const std::lock_guard<std::mutex> lock( m_photos_mutex );
54
56 if ( m_gammaId == EvtId( -1, -1 ) ) {
57 EvtGenReport( EVTGEN_INFO, "EvtGen" )
58 << "Error in EvtPHOTOS. Do not recognise the photon type "
59 << m_photonType << ". Setting this to \"gamma\". " << endl;
60 m_gammaId = EvtPDL::getId( "gamma" );
61 }
63
64 if ( m_initialised ) {
65 return;
66 }
67
68 EvtGenReport( EVTGEN_INFO, "EvtGen" ) << "Setting up PHOTOS." << endl;
69
70 if ( m_useEvtGenRandom ) {
71 EvtGenReport( EVTGEN_INFO, "EvtGen" )
72 << "Using EvtGen random number engine also for Photos++" << endl;
73
74 Photospp::Photos::setRandomGenerator( EvtRandom::Flat );
75 }
76
77 Photospp::Photos::initialize();
78
79 Photospp::Photos::setExponentiation( true );
80
81 /* Sets the infrared cutoff (default at 1e-7)
82 * Reset the minimum photon energy, if required, in units of half of the decaying particle mass.
83 * This must be done after exponentiation! Keep the cut at 1e-7, i.e. 0.1 keV at the 1 GeV scale,
84 * which is appropriate for B decays
85 */
86 Photospp::Photos::setInfraredCutOff( m_infraredCutOff );
87
88 Photospp::Photos::setInterference( true );
89
90 /* Increase the maximum possible value of the interference weight
91 * corresponding to 2^n, where n = number of charges (+,-).
92 */
93 Photospp::Photos::maxWtInterference( m_maxWtInterference );
94
95#ifdef EVTGEN_PHOTOS_NEWLIBS
96 // This turns off/on virtual photons splitting into l+l-
97 // It is false by default, but just to keep track of it here.
98 Photospp::Photos::setPairEmission( false );
99#endif
100
101 m_initialised = true;
102}
103
105{
106 if ( !theParticle ) {
107 return;
108 }
109
110 /* Skip running Photos if the particle has no daughters, since we can't add FSR.
111 * Also skip Photos if the particle has too many daughters (>= 10) to avoid a problem
112 * with a hard coded upper limit in the PHOENE subroutine.
113 */
114 const int nDaughters( theParticle->getNDaug() );
115 if ( nDaughters == 0 || nDaughters >= 10 ) {
116 return;
117 }
118
119 /* Create a dummy HepMC GenEvent containing a single vertex, with the mother
120 * assigned as the incoming particle and its daughters as outgoing particles.
121 * We then pass this event to Photos for processing.
122 * It will return a modified version of the event, updating the momentum of
123 * the original particles and will contain any new photon particles.
124 * We add these extra photons to the mother particle daughter list.
125 * First, Create the dummy event.
126 */
127 auto theEvent = std::make_unique<GenEvent>( Units::GEV, Units::MM );
128
129 // Create the decay "vertex".
130 GenVertexPtr theVertex = newGenVertexPtr();
131 theEvent->add_vertex( theVertex );
132
133 // Add the mother particle as the incoming particle to the vertex.
134 const GenParticlePtr hepMCMother = this->createGenParticle( *theParticle,
135 true );
136 theVertex->add_particle_in( hepMCMother );
137
138 /* Find all daughter particles and assign them as outgoing particles to the vertex.
139 * Keep track of the number of photons already in the decay (e.g. we may have B -> K* gamma)
140 */
141 int iDaug( 0 ), nGamma( 0 );
142 for ( iDaug = 0; iDaug < nDaughters; iDaug++ ) {
143 const EvtParticle& theDaughter = *theParticle->getDaug( iDaug );
144 const GenParticlePtr hepMCDaughter =
145 this->createGenParticle( theDaughter, false );
146 theVertex->add_particle_out( hepMCDaughter );
147
148 if ( theDaughter.getPDGId() == m_gammaPDG ) {
149 nGamma++;
150 }
151 }
152
153 {
154 const std::lock_guard<std::mutex> lock( m_photos_mutex );
155 /* Now pass the event to Photos for processing
156 * Create a Photos event object */
157#ifdef EVTGEN_HEPMC3
158 Photospp::PhotosHepMC3Event photosEvent( theEvent.get() );
159#else
160 Photospp::PhotosHepMCEvent photosEvent( theEvent.get() );
161#endif
162
163 // Run the Photos algorithm
164 photosEvent.process();
165 }
166
167 // Find the number of (outgoing) photons in the event
168 const int nPhotons = this->getNumberOfPhotons( theVertex );
169
170 int iLoop( 0 );
171 // See whether Photos has created additional photons. If not, do nothing extra.
172 if ( nPhotons > nGamma ) {
173 // We have extra particles from Photos; these would have been appended
174 // to the outgoing particle list
175
176 // Get the iterator of outgoing particles for this vertex
177#ifdef EVTGEN_HEPMC3
178 for ( const auto& outParticle : theVertex->particles_out() ) {
179#else
180 HepMC::GenVertex::particles_out_const_iterator outIter;
181 for ( outIter = theVertex->particles_out_const_begin();
182 outIter != theVertex->particles_out_const_end(); ++outIter ) {
183 // Get the next HepMC GenParticle
184 const HepMC::GenParticle* outParticle = *outIter;
185#endif
186 // Get the three-momentum Photos result for this particle, and the PDG id
187 if ( outParticle ) {
188 const FourVector HepMCP4 = outParticle->momentum();
189 const double px = HepMCP4.px();
190 const double py = HepMCP4.py();
191 const double pz = HepMCP4.pz();
192 const double energy = HepMCP4.e();
193 const int pdgId = outParticle->pdg_id();
194 const EvtVector4R newP4( energy, px, py, pz );
195
196 if ( iLoop < nDaughters ) {
197 /* Original daughters: keep the original particle mass,
198 * but set the three-momentum according to what Photos
199 * has modified.
200 */
201 EvtParticle* daugParticle = theParticle->getDaug( iLoop );
202 if ( daugParticle ) {
203 daugParticle->setP4WithFSR( newP4 );
204 }
205
206 } else if ( pdgId == m_gammaPDG ) {
207 // Extra photon particle. Setup the four-momentum object
208
209 // Create a new photon particle and add it to the list of daughters
211 gamma->init( m_gammaId, newP4 );
212 // Set the pre-FSR photon momentum to zero
213 gamma->setFSRP4toZero();
214 // Set its particle attribute to specify it is a FSR photon
215 gamma->setAttribute( "FSR", 1 ); // it is a FSR photon
216 // Let the mother know about this new photon
217 gamma->addDaug( theParticle );
218 }
219
220 // Increment the loop counter for detecting additional photon particles
221 iLoop++;
222 }
223 }
224 }
225
226 // Cleanup
227 theEvent->clear();
228
229 return;
230}
231
233 bool incoming ) const
234{
235 /* Method to create an HepMC::GenParticle version of the given EvtParticle.
236 */
237
238 // Get the 4-momentum (E, px, py, pz) for the EvtParticle
239 const EvtVector4R p4 = incoming ? theParticle.getP4Restframe()
240 : theParticle.getP4();
241
242 // Convert this to the HepMC 4-momentum
243 const double E = p4.get( 0 );
244 const double px = p4.get( 1 );
245 const double py = p4.get( 2 );
246 const double pz = p4.get( 3 );
247
248 const FourVector hepMC_p4( px, py, pz, E );
249
250 const int PDGInt = EvtPDL::getStdHep( theParticle.getId() );
251
252 // Set the status flag for the particle. This is required, otherwise Photos++
253 // will crash from out-of-bounds array index problems.
254 const int status = incoming ? Photospp::PhotosParticle::HISTORY
255 : Photospp::PhotosParticle::STABLE;
256
257 const GenParticlePtr genParticle = newGenParticlePtr( hepMC_p4, PDGInt,
258 status );
259
260 return genParticle;
261}
262
263int EvtPHOTOS::getNumberOfPhotons( const GenVertexPtr theVertex ) const
264{
265 /* Find the number of photons from the outgoing particle list
266 */
267
268 if ( !theVertex ) {
269 return 0;
270 }
271
272 int nPhotons( 0 );
273
274 // Get the iterator of outgoing particles for this vertex
275#ifdef EVTGEN_HEPMC3
276 for ( const auto& outParticle : theVertex->particles_out() ) {
277#else
278 HepMC::GenVertex::particles_out_const_iterator outIter;
279 for ( outIter = theVertex->particles_out_const_begin();
280 outIter != theVertex->particles_out_const_end(); ++outIter ) {
281 // Get the next HepMC GenParticle
282 const HepMC::GenParticle* outParticle = *outIter;
283#endif
284
285 // Get the PDG id
286 int pdgId( 0 );
287 if ( outParticle != nullptr ) {
288 pdgId = outParticle->pdg_id();
289 }
290
291 // Keep track of how many photons there are
292 if ( pdgId == m_gammaPDG ) {
293 nPhotons++;
294 }
295 }
296
297 return nPhotons;
298}
299
300#endif
HepMC3::GenVertexPtr GenVertexPtr
GenVertexPtr newGenVertexPtr(const FourVector &pos=FourVector::ZERO_VECTOR())
GenParticlePtr newGenParticlePtr(const FourVector &mom=FourVector::ZERO_VECTOR(), int pid=0, int status=0)
HepMC3::GenParticlePtr GenParticlePtr
HepMC3::FourVector FourVector
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=nullptr)
Definition EvtReport.cpp:32
@ EVTGEN_INFO
Definition EvtReport.hh:52
Definition EvtId.hh:27
static int getStdHep(EvtId id)
Definition EvtPDL.cpp:356
static EvtId getId(const std::string &name)
Definition EvtPDL.cpp:283
bool m_useEvtGenRandom
Definition EvtPHOTOS.hh:71
static std::mutex m_photos_mutex
Definition EvtPHOTOS.hh:85
GenParticlePtr createGenParticle(const EvtParticle &theParticle, bool incoming) const
double m_maxWtInterference
Definition EvtPHOTOS.hh:77
static bool m_initialised
Definition EvtPHOTOS.hh:84
double m_infraredCutOff
Definition EvtPHOTOS.hh:75
int getNumberOfPhotons(const GenVertexPtr theVertex) const
long int m_gammaPDG
Definition EvtPHOTOS.hh:82
void doRadCorr(EvtParticle *theParticle) override
std::string m_photonType
Definition EvtPHOTOS.hh:80
void initialise() override
Definition EvtPHOTOS.cpp:51
EvtPHOTOS(const std::string &photonType="gamma", const bool useEvtGenRandom=true, const double infraredCutOff=1.0e-7, const double maxWtInterference=64.0)
Definition EvtPHOTOS.cpp:41
EvtId m_gammaId
Definition EvtPHOTOS.hh:81
EvtId getId() const
EvtVector4R getP4Restframe() const
void setAttribute(std::string attName, int attValue)
int getPDGId() const
const EvtVector4R & getP4() const
EvtParticle * getDaug(const int i)
void setP4WithFSR(const EvtVector4R &p4)
size_t getNDaug() const
void addDaug(EvtParticle *node)
void setFSRP4toZero()
void init(EvtId part_n, double e, double px, double py, double pz)
static double Flat()
Definition EvtRandom.cpp:95
double get(int i) const