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
EvtSherpaPhotons.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_SHERPA
22
24
29
30#include "ATOOLS/Org/MyStrStream.H"
31#include "ATOOLS/Phys/Particle.H"
32#include "SHERPA/Initialization/Initialization_Handler.H"
33#include "SHERPA/SoftPhysics/Soft_Photon_Handler.H"
34
35#include <cstring>
36#include <iostream>
37#include <vector>
38
39using std::endl;
40
41std::unique_ptr<SHERPA::Sherpa> EvtSherpaPhotons::m_sherpaGen;
44
45EvtSherpaPhotons::EvtSherpaPhotons( const bool useEvtGenRandom,
46 const double infraredCutOff, const int mode,
47 const int useME ) :
48 m_useEvtGenRandom{ useEvtGenRandom },
49 m_infraredCutOff{ infraredCutOff },
50 m_mode{ mode },
51 m_useME{ useME }
52{
53}
54
56{
57 // Sherpa initialisation is not thread safe, so we mutex it
58 const std::lock_guard<std::mutex> lock( m_sherpa_mutex );
59
62
63 if ( m_initialised ) {
64 return;
65 }
66
67 EvtGenReport( EVTGEN_INFO, "EvtGen" )
68 << "Setting up Sherpa PHOTONS++ generator for FSR." << endl;
69
70 /* Specify whether we are going to use EvtGen's random number generator
71 * (via EvtSherpaRandom interface) for Sherpa's PHOTONS++ simulation. */
72 if ( m_useEvtGenRandom ) {
73 m_configs.push_back( "SHERPA_LDADD=EvtGenExternal" );
74 m_configs.push_back( "EXTERNAL_RNG=EvtSherpaRandom" );
75 }
76
77 /*
78 * Internal PHOTONS++ settings.
79 * Documentation at
80 * https://sherpa.hepforge.org/doc/Sherpa.html#QED-Corrections
81 */
82
83 /*
84 * YFS_IR_CUTOFF sets the infrared cut-off which serves as a
85 * minimum photon energy in this frame for explicit photon generation.
86 * The default is YFS_IR_CUTOFF = 1E-3 (GeV) but we set it to 1E-7 to equalize
87 * with the cutoff used for PHOTOS.
88 */
89 m_configs.push_back( "YFS_IR_CUTOFF=" + ATOOLS::ToString( m_infraredCutOff ) );
90
91 /*
92 * The keyword YFS_MODE = [0,1,2] determines the mode of operation.
93 * YFS_MODE = 0 switches Photons off.
94 * YFS_MODE = 1 sets the mode to "soft only", meaning soft emissions will be
95 * treated correctly to all orders but no hard emission corrections will be included.
96 * YFS_MODE = 2 these hard emission corrections will also be included up to
97 * first order in alpha_QED. This is the default setting in Sherpa.
98 */
99
100 m_configs.push_back( "YFS_MODE=" + ATOOLS::ToString( m_mode ) );
101
102 /*
103 * The switch YFS_USE_ME = [0,1] tells Photons how to correct hard emissions to
104 * first order in alpha_QED. If YFS_USE_ME = 0, then Photons will use collinearly
105 * approximated real emission matrix elements. Virtual emission matrix elements of
106 * order alpha_QED are ignored. If, however, YFS_USE_ME=1, then exact real and/or
107 * virtual emission matrix elements are used wherever possible.
108 * These are presently available for V->FF, V->SS, S->FF, S->SS, S->Slnu,
109 * S->Vlnu type decays, Z->FF decays and leptonic tau and W decays. For all other
110 * decay types general collinearly approximated matrix elements are used.
111 * In both approaches all hadrons are treated as point-like objects.
112 * The default setting is YFS_USE_ME = 1. This switch is only effective if YFS_MODE = 2.
113 */
114 m_configs.push_back( "YFS_USE_ME=" + ATOOLS::ToString( m_useME ) );
115
116 // TODO: Virtual photon splitting into l+l- will be part of ME corrections from Sherpa 3.0.0 on,
117 // Once released, this should be switched off by default or
118 // taken into account while retrieving the event.
119
120 // Set up run-time arguments for Sherpa.
121 std::vector<char*> argv = this->addParameters();
122
123 // Create instance and initialise Sherpa.
124 m_sherpaGen = std::make_unique<SHERPA::Sherpa>();
125 m_sherpaGen->InitializeTheRun( argv.size(), &argv[0] );
126
127 this->updateParticleLists();
128
129 m_initialised = true;
130}
131
133{
134 std::vector<char*> argv;
135 argv.reserve( m_configs.size() );
136
137 for ( auto& config : m_configs ) {
138 if ( config != "Sherpa" ) {
139 EvtGenReport( EVTGEN_INFO, "EvtGen" )
140 << " EvtSherpaPhotons::initialise: Setting parameter '"
141 << config << "'" << endl;
142 }
143 argv.push_back( config.data() );
144 }
145
146 return argv;
147}
148
150{
151 /* Use the EvtGen decay and pdl tables (decay/user.dec and evt.pdl)
152 * to update Sherpa's KF_Table which contains all defined particles
153 * and their properties.
154 * Loop over all entries in the EvtPDL particle data table.
155 */
156 const int nPDL = EvtPDL::entries();
157
158 for ( int iPDL = 0; iPDL < nPDL; iPDL++ ) {
159 const EvtId particleId = EvtPDL::getEntry( iPDL );
160
161 // Sherpa and EvtGen should use the same PDG codes for particles
162 const int PDGCode = EvtPDL::getStdHep( particleId );
163 const long unsigned int particleCode = std::abs( PDGCode );
164
165 // If particle is found in Sherpa's KF_Table, then continue.
166 // Updating the pole mass is not necessary because we provide the 4-momenta
167 // and the final mass for final-state radiation generation.
168 ATOOLS::KFCode_ParticleInfo_Map::const_iterator kf_it(
169 ATOOLS::s_kftable.find( particleCode ) );
170 if ( kf_it != ATOOLS::s_kftable.end() ) {
171 continue;
172 }
173
174 // If the PDG is negative, use the charge conjugated ID because
175 // the KF_Table is defined only for positive PDG numbers.
176 const EvtId particleIdConj = EvtPDL::chargeConj( particleId );
177
178 // Get mass, width, charge and spin
179 const double mass = EvtPDL::getMeanMass( particleId );
180 const double width = EvtPDL::getWidth( particleId );
181 const int charge = PDGCode < 0 ? EvtPDL::chg3( particleIdConj )
182 : EvtPDL::chg3( particleId );
183 const int spin = EvtSpinType::getSpin2(
184 EvtPDL::getSpinType( particleId ) );
185
186 // Use as reference the name of the particle (not anti-particle).
187 const std::string idName = PDGCode < 0 ? particleIdConj.getName()
188 : particleId.getName();
189
190 // Create new entry in the KF_Table. The 0 and 1 in the constructor below
191 // stand for m_on = 0 and m_stable = 1. These properties are irrelevant
192 // for final-state radiation and set to default values.
193 ATOOLS::s_kftable[particleCode] = new ATOOLS::Particle_Info(
194 particleCode, mass, width, charge, spin, 0, 1, idName, idName );
195 }
196}
197
199{
200 if ( !theParticle ) {
201 return;
202 }
203
204 /* Skip running FSR if the particle has no daughters, since we can't add FSR.
205 * Also skip FSR if the particle has too many daughters (>= 10) as done for PHOTOS.
206 */
207 const int nDaughters( theParticle->getNDaug() );
208 if ( nDaughters == 0 || nDaughters >= 10 ) {
209 return;
210 }
211
212 // Create a blob.
213 std::unique_ptr<ATOOLS::Blob> blob = std::make_unique<ATOOLS::Blob>();
214
215 // Tell Sherpa that the blob needs FSR (that is extra QED)
216 blob->SetStatus( ATOOLS::blob_status::needs_extraQED );
217
218 // Create mother particle and add it to blob
219 ATOOLS::Flavour mother_flav( EvtPDL::getStdHep( theParticle->getId() ) );
220 mother_flav.SetStable( false );
221 const double motherM0 = theParticle->mass();
222 const ATOOLS::Vec4D mother_mom( motherM0, 0., 0., 0. );
223
224 // Add mother to blob with m_number=-1. The m_number will start from 0 for daughters.
225 ATOOLS::Particle* mother_part = new ATOOLS::Particle( -1, mother_flav,
226 mother_mom );
227 mother_part->SetFinalMass( motherM0 );
228 mother_part->SetStatus( ATOOLS::part_status::decayed );
229 // Set m_info="I" (initial) for mother. The m_info will be "F" (final) for daughters.
230 mother_part->SetInfo( 'I' );
231
232 blob->AddToInParticles( mother_part );
233
234 // Add daughters to the blob
235 for ( int iDaug = 0; iDaug < nDaughters; iDaug++ ) {
236 const EvtParticle* theDaughter = theParticle->getDaug( iDaug );
237 ATOOLS::Flavour daughter_flav( EvtPDL::getStdHep( theDaughter->getId() ) );
238 daughter_flav.SetStable( true );
239
240 const double daugE = theDaughter->getP4().get( 0 );
241 const double daugPx = theDaughter->getP4().get( 1 );
242 const double daugPy = theDaughter->getP4().get( 2 );
243 const double daugPz = theDaughter->getP4().get( 3 );
244 const double daugM0 = theDaughter->mass();
245
246 const ATOOLS::Vec4D daughter_mom( daugE, daugPx, daugPy, daugPz );
247
248 ATOOLS::Particle* daughter_part =
249 new ATOOLS::Particle( iDaug, daughter_flav, daughter_mom );
250 daughter_part->SetFinalMass( daugM0 );
251
252 daughter_part->SetStatus( ATOOLS::part_status::active );
253 daughter_part->SetInfo( 'F' );
254
255 blob->AddToOutParticles( daughter_part );
256 }
257
258 {
259 // AddRadiation function is not yet thread_safe, so we mutex it
260 const std::lock_guard<std::mutex> lock( m_sherpa_mutex );
261
262 const SHERPA::Initialization_Handler* inithandler =
263 m_sherpaGen->GetInitHandler();
264 SHERPA::Soft_Photon_Handler* softphotonhandler =
265 inithandler->GetSoftPhotonHandler();
266
267 // Simulate the radiation
268 softphotonhandler->AddRadiation( blob.get() );
269 }
270
271 // Get number of final-state particles
272 const int nFinal( blob->NOutP() );
273
274 // Retrieve the event from Sherpa blob if FSR photons were added
275 if ( nFinal > nDaughters ) {
276 for ( int iLoop = 0; iLoop < nFinal; iLoop++ ) {
277 const ATOOLS::Particle* outParticle = blob->OutParticle( iLoop );
278 const ATOOLS::Vec4D daughter_mom = outParticle->Momentum();
279 const long int pdgId = outParticle->Flav();
280 const EvtVector4R newP4( daughter_mom[0], daughter_mom[1],
281 daughter_mom[2], daughter_mom[3] );
282 const char daugInfo = outParticle->Info();
283
284 if ( iLoop < nDaughters ) {
285 // Update momenta of initial particles
286 EvtParticle* daugParticle = theParticle->getDaug( iLoop );
287 if ( daugParticle ) {
288 daugParticle->setP4WithFSR( newP4 );
289 }
290 } else if ( pdgId == m_gammaPDG && daugInfo == 'S' ) {
291 // Add FSR photons. PHOTONS flags them with info 'S'.
292 // Create a new photon particle and add it to the list of daughters
294 gamma->init( m_gammaId, newP4 );
295 gamma->setFSRP4toZero();
296 gamma->setAttribute( "FSR", 1 );
297 gamma->addDaug( theParticle );
298 }
299 }
300 }
301}
302
303#endif
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=nullptr)
Definition EvtReport.cpp:32
@ EVTGEN_INFO
Definition EvtReport.hh:52
Definition EvtId.hh:27
std::string getName() const
Definition EvtId.cpp:38
static double getWidth(EvtId i)
Definition EvtPDL.cpp:346
static EvtSpinType::spintype getSpinType(EvtId i)
Definition EvtPDL.cpp:371
static int getStdHep(EvtId id)
Definition EvtPDL.cpp:356
static int chg3(EvtId i)
Definition EvtPDL.cpp:366
static EvtId getEntry(int i)
Definition EvtPDL.cpp:386
static size_t entries()
Definition EvtPDL.cpp:381
static double getMeanMass(EvtId i)
Definition EvtPDL.cpp:306
static EvtId chargeConj(EvtId id)
Definition EvtPDL.cpp:201
static EvtId getId(const std::string &name)
Definition EvtPDL.cpp:283
EvtId getId() const
void setAttribute(std::string attName, int attValue)
const EvtVector4R & getP4() const
EvtParticle * getDaug(const int i)
double mass() const
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)
void doRadCorr(EvtParticle *p) override
static std::unique_ptr< SHERPA::Sherpa > m_sherpaGen
static std::mutex m_sherpa_mutex
static bool m_initialised
std::vector< std::string > m_configs
EvtSherpaPhotons(const bool useEvtGenRandom=true, const double infraredCutOff=1.0e-7, const int mode=2, const int useME=0)
std::vector< char * > addParameters()
const std::string m_photonType
void initialise() override
static int getSpin2(spintype stype)
double get(int i) const