diff --git a/.clang-format b/.clang-format --- a/.clang-format +++ b/.clang-format @@ -80,7 +80,7 @@ Priority: 4 - Regex: '^"(HepMC|HepMC3)/' Priority: 5 - - Regex: '^"(Pythia8|Photos|Tauola|SHERPA|ATOOLS)/' + - Regex: '^"(Pythia8|Photos|Tauola|SHERPA|ATOOLS|PHOTONS\+\+)/' Priority: 6 - Regex: '^"T[[:alnum:]]+\.h"' Priority: 7 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,8 +4,8 @@ - test variables: - LCG_VERSION: "LCG_105" - GCC_VERSION: "gcc13" + LCG_VERSION: "LCG_106a" + GCC_VERSION: "gcc14" CLANG_VERSION: "clang16" BUILD_TYPE: "Release" BUILD_TESTS: "OFF" @@ -15,6 +15,7 @@ USE_PHOTOS: "ON" USE_TAUOLA: "ON" USE_SHERPA: "ON" + USE_SHERPA3: "ON" .production_os_image: variables: @@ -29,6 +30,7 @@ LCG_VERSION: "LCG_103" GCC_VERSION: "gcc12" CLANG_VERSION: "clang12" + USE_SHERPA3: "OFF" image: gitlab-registry.cern.ch/lhcb-docker/os-base/centos7-devel:latest tags: - k8s-cvmfs @@ -52,7 +54,7 @@ script: - mkdir install - mkdir build && cd build - - cmake -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DCMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/install -DEVTGEN_HEPMC3:BOOL=$USE_HEPMC3 -DEVTGEN_PYTHIA:BOOL=$USE_PYTHIA -DEVTGEN_PHOTOS:BOOL=$USE_PHOTOS -DEVTGEN_TAUOLA:BOOL=$USE_TAUOLA -DEVTGEN_SHERPA:BOOL=$USE_SHERPA -DEVTGEN_BUILD_TESTS:BOOL=$BUILD_TESTS -DEVTGEN_BUILD_VALIDATIONS:BOOL=$BUILD_TESTS -DEVTGEN_BUILD_DOXYGEN:BOOL=$BUILD_DOXYGEN $CI_PROJECT_DIR + - cmake -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DCMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/install -DEVTGEN_HEPMC3:BOOL=$USE_HEPMC3 -DEVTGEN_PYTHIA:BOOL=$USE_PYTHIA -DEVTGEN_PHOTOS:BOOL=$USE_PHOTOS -DEVTGEN_TAUOLA:BOOL=$USE_TAUOLA -DEVTGEN_SHERPA:BOOL=$USE_SHERPA -DEVTGEN_SHERPA3:BOOL=$USE_SHERPA3 -DEVTGEN_BUILD_TESTS:BOOL=$BUILD_TESTS -DEVTGEN_BUILD_VALIDATIONS:BOOL=$BUILD_TESTS -DEVTGEN_BUILD_DOXYGEN:BOOL=$BUILD_DOXYGEN $CI_PROJECT_DIR - cmake --build . - cmake --build . --target install diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ option(EVTGEN_PHOTOS "Enable/disable linking with Photos++" OFF) option(EVTGEN_TAUOLA "Enable/disable linking with Tauola++" OFF) option(EVTGEN_SHERPA "Enable/disable linking with Sherpa" OFF) +option(EVTGEN_SHERPA3 "Prefer Sherpa 3 to Sherpa 2" ON) option(EVTGEN_SUPPRESS_EXTERNAL_WARNINGS "Enable/disable suppression of warnings from external dependencies" OFF) if (EVTGEN_HEPMC3) message(STATUS "EvtGen: Linking with HepMC3") @@ -75,7 +76,11 @@ message(STATUS "EvtGen: Optional linking with Pythia8 EVTGEN_PYTHIA ${EVTGEN_PYTHIA}") message(STATUS "EvtGen: Optional linking with Photos++ EVTGEN_PHOTOS ${EVTGEN_PHOTOS}") message(STATUS "EvtGen: Optional linking with Tauola++ EVTGEN_TAUOLA ${EVTGEN_TAUOLA}") -message(STATUS "EvtGen: Optional linking with Sherpa EVTGEN_SHERPA ${EVTGEN_SHERPA}") +if (EVTGEN_SHERPA3) + message(STATUS "EvtGen: Optional linking with Sherpa3 EVTGEN_SHERPA ${EVTGEN_SHERPA}") +else() + message(STATUS "EvtGen: Optional linking with Sherpa2 EVTGEN_SHERPA ${EVTGEN_SHERPA}") +endif() include(EvtGenExternalDependencies) # Setup clang-tidy checks diff --git a/EvtGenExternal/EvtSherpaPhotons.hh b/EvtGenExternal/EvtSherpaPhotons.hh --- a/EvtGenExternal/EvtSherpaPhotons.hh +++ b/EvtGenExternal/EvtSherpaPhotons.hh @@ -28,6 +28,7 @@ #include "EvtGenBase/EvtPDL.hh" #include "EvtGenBase/EvtParticle.hh" +#include "PHOTONS++/Main/Photons.H" #include "SHERPA/Main/Sherpa.H" #include <string> @@ -48,6 +49,9 @@ void doRadCorr( EvtParticle* p ) override; + // This function is needed to control the deletion of the static instances of Sherpa and PHOTONS++ + static void finalise(); + private: // Provides vector of pointers to the configuration strings for Sherpa std::vector<char*> addParameters(); @@ -56,8 +60,7 @@ void updateParticleLists(); // Vector containing the configuration strings for Sherpa - // INIT_ONLY=6 intialises the Sherpa objects without launching simulation. - std::vector<std::string> m_configs{ "Sherpa", "INIT_ONLY=6" }; + std::vector<std::string> m_configs{ "Sherpa" }; // Use EvtGen's random number generator bool m_useEvtGenRandom = true; @@ -76,10 +79,17 @@ EvtId m_gammaId = EvtId( -1, -1 ); long int m_gammaPDG = 22; - // The Sherpa instance. + // Mutex to serialise all access to the shared Sherpa objects + static std::mutex m_sherpa_mutex; + + // The Sherpa instance static std::unique_ptr<SHERPA::Sherpa> m_sherpaGen; + + // The PHOTONS++ instance + static std::unique_ptr<PHOTONS::Photons> m_photonsGen; + + // Flag whether initialisation has been performed static bool m_initialised; - static std::mutex m_sherpa_mutex; }; #endif diff --git a/History.md b/History.md --- a/History.md +++ b/History.md @@ -11,6 +11,13 @@ === ## R03-00-00-betaX +3 Dec 2024 Fernando Abudinen +* D134: Add support for Sherpa 3 + - Modified EvtSherpaPhotons interface to support both Sherpa 2 and 3 releases + - Introduced finalise function inside EvtSherpaPhotons class to control the order of static destruction + - Updated CI to pick Sherpa 3, use Sherpa 2 for legacy builds + - Updated setupEvtGen for Sherpa 3 + 2 Dec 2024 Thomas Latham * Remove or convert C headers to C++ equivalents diff --git a/cmake/Modules/EvtGenExternalDependencies.cmake b/cmake/Modules/EvtGenExternalDependencies.cmake --- a/cmake/Modules/EvtGenExternalDependencies.cmake +++ b/cmake/Modules/EvtGenExternalDependencies.cmake @@ -33,9 +33,6 @@ # of HepMC we're working with if(EVTGEN_HEPMC3) find_package(HepMC3 REQUIRED PATHS ${HEPMC3_ROOT_DIR}) - if(EVTGEN_PYTHIA) - find_package(Pythia8 REQUIRED) - endif() if(EVTGEN_PHOTOS) # From version 3.64 Photos has HepMC3 support find_package(Photos++ REQUIRED COMPONENTS pp ppHepMC3) @@ -44,14 +41,8 @@ # From version 1.1.8 Tauola has HepMC3 support find_package(Tauola++ REQUIRED COMPONENTS Fortran CxxInterface HepMC3) endif() - if(EVTGEN_SHERPA) - find_package(Sherpa 2.0.0 REQUIRED) - endif() else() find_package(HepMC2 REQUIRED) - if(EVTGEN_PYTHIA) - find_package(Pythia8 REQUIRED) - endif() if(EVTGEN_PHOTOS) # Photos has different library structures for versions before and after 3.58 # so we need to search for either option: pp+ppHepMC or CxxInterface+Fortran @@ -61,7 +52,15 @@ # Older versions of Tauola don't have the HepMC component, the HepMC2 interface is in CxxInterface find_package(Tauola++ REQUIRED COMPONENTS Fortran CxxInterface OPTIONAL_COMPONENTS HepMC) endif() - if(EVTGEN_SHERPA) - find_package(Sherpa 2.0.0 REQUIRED) +endif() + +if(EVTGEN_PYTHIA) + find_package(Pythia8 REQUIRED) +endif() +if(EVTGEN_SHERPA) + if(EVTGEN_SHERPA3) + find_package(SHERPA-MC 3.0.0 CONFIG REQUIRED) + else() + find_package(Sherpa 2.0.0 MODULE REQUIRED) endif() endif() diff --git a/setupEvtGen.sh b/setupEvtGen.sh --- a/setupEvtGen.sh +++ b/setupEvtGen.sh @@ -68,9 +68,13 @@ HEPMCBASEURL="https://hepmc.web.cern.ch/hepmc/releases" if [ "$HEPMCMAJORVERSION" -lt "3" ] then + USEHEPMC3="OFF" HEPMCURL=$HEPMCBASEURL/$HEPMC2TAR + HEPMCTAR=$HEPMC2TAR else + USEHEPMC3="ON" HEPMCURL=$HEPMCBASEURL/$HEPMC3TAR + HEPMCTAR=$HEPMC3TAR fi # Pythia version number with no decimal points, e.g. 8310 corresponds to version 8.310 @@ -102,7 +106,15 @@ # Sherpa version number USESHERPA="ON" -SHERPAVER="2.2.16" +SHERPAMAJORVERSION="3" +if [ "$SHERPAMAJORVERSION" -lt "3" ] +then + USESHERPA3="OFF" + SHERPAVER="2.2.16" +else + USESHERPA3="ON" + SHERPAVER="3.0.0" +fi SHERPAPKG="sherpa-v$SHERPAVER" SHERPATAR="$SHERPAPKG.tar.gz" SHERPABASEURL="https://gitlab.com/sherpa-team/sherpa/-/archive" @@ -190,12 +202,7 @@ cd $BUILD_BASE/sources echo Extracting external dependencies -if [ "$HEPMCMAJORVERSION" -lt "3" ] -then - tar -xzf $BUILD_BASE/tarfiles/$HEPMC2TAR -else - tar -xzf $BUILD_BASE/tarfiles/$HEPMC3TAR -fi +tar -xzf $BUILD_BASE/tarfiles/$HEPMCTAR if [ $USEPYTHIA == "ON" ] then tar -xzf $BUILD_BASE/tarfiles/$PYTHIATAR @@ -314,35 +321,34 @@ if [ $USESHERPA == "ON" ] then - echo Installing Sherpa from $BUILD_BASE/sources/$SHERPAPKG - cd $BUILD_BASE/sources/$SHERPAPKG - autoreconf -i - ./configure --with-sqlite3=install --prefix=$INSTALL_PREFIX - make $BUILDARGS - make install + echo Installing Sherpa $SHERPAMAJORVERSION from $BUILD_BASE/sources/$SHERPAPKG + if [ "$SHERPAMAJORVERSION" -lt "3" ] + then + cd $BUILD_BASE/sources/$SHERPAPKG + autoreconf -i + ./configure --with-sqlite3=install --prefix=$INSTALL_PREFIX + make $BUILDARGS + make install + else + mkdir -p $BUILD_BASE/builds/Sherpa + cd $BUILD_BASE/builds/Sherpa + $CMAKE -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_PREFIX $BUILD_BASE/sources/$SHERPAPKG + $CMAKE --build . + $CMAKE --install . + fi fi echo Installing EvtGen from $BUILD_BASE/sources/evtgen mkdir -p $BUILD_BASE/builds/evtgen cd $BUILD_BASE/builds/evtgen -if [ "$HEPMCMAJORVERSION" -lt "3" ] -then - $CMAKE -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_PREFIX \ - -DEVTGEN_HEPMC3:BOOL=OFF -DHEPMC2_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_PYTHIA:BOOL=$USEPYTHIA -DPYTHIA8_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_PHOTOS:BOOL=$USEPHOTOS -DPHOTOSPP_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_TAUOLA:BOOL=$USETAUOLA -DTAUOLAPP_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_SHERPA:BOOL=$USESHERPA -DSHERPA_ROOT_DIR:PATH=$INSTALL_PREFIX \ - $BUILD_BASE/sources/evtgen -else - $CMAKE -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_PREFIX \ - -DEVTGEN_HEPMC3:BOOL=ON -DHEPMC3_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_PYTHIA:BOOL=$USEPYTHIA -DPYTHIA8_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_PHOTOS:BOOL=$USEPHOTOS -DPHOTOSPP_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_TAUOLA:BOOL=$USETAUOLA -DTAUOLAPP_ROOT_DIR:PATH=$INSTALL_PREFIX \ - -DEVTGEN_SHERPA:BOOL=$USESHERPA -DSHERPA_ROOT_DIR:PATH=$INSTALL_PREFIX \ - $BUILD_BASE/sources/evtgen -fi +$CMAKE -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_PREFIX \ + -DEVTGEN_HEPMC3:BOOL=$USEHEPMC3 -DHEPMC${HEPMCMAJORVERSION}_ROOT_DIR:PATH=$INSTALL_PREFIX \ + -DEVTGEN_PYTHIA:BOOL=$USEPYTHIA -DPYTHIA8_ROOT_DIR:PATH=$INSTALL_PREFIX \ + -DEVTGEN_PHOTOS:BOOL=$USEPHOTOS -DPHOTOSPP_ROOT_DIR:PATH=$INSTALL_PREFIX \ + -DEVTGEN_TAUOLA:BOOL=$USETAUOLA -DTAUOLAPP_ROOT_DIR:PATH=$INSTALL_PREFIX \ + -DEVTGEN_SHERPA:BOOL=$USESHERPA -DSHERPA_ROOT_DIR:PATH=$INSTALL_PREFIX \ + -DEVTGEN_SHERPA3:BOOL=$USESHERPA3 \ + $BUILD_BASE/sources/evtgen make $BUILDARGS make install diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,8 +132,13 @@ endif() if(EVTGEN_SHERPA) target_compile_definitions(objlib_ext PRIVATE EVTGEN_SHERPA) - if( ${SHERPA_VERSION} VERSION_GREATER 2.2.15 ) - target_compile_definitions(objlib_ext PRIVATE EVTGEN_SHERPA_USEMACRO) + if(EVTGEN_SHERPA3) + target_compile_definitions(objlib_ext PRIVATE EVTGEN_SHERPA_USEMACRO EVTGEN_SHERPA3) + get_target_property(SHERPA_INCLUDE_DIRS SHERPA::SherpaMain INTERFACE_INCLUDE_DIRECTORIES) + else() + if( ${SHERPA_VERSION} VERSION_GREATER 2.2.15 ) + target_compile_definitions(objlib_ext PRIVATE EVTGEN_SHERPA_USEMACRO) + endif() endif() if (EVTGEN_SUPPRESS_EXTERNAL_WARNINGS) target_include_directories(objlib_ext SYSTEM PRIVATE ${SHERPA_INCLUDE_DIRS}) @@ -155,11 +160,16 @@ endif() if(EVTGEN_SHERPA) target_compile_definitions(EvtGenExternal PUBLIC EVTGEN_SHERPA) - if( ${SHERPA_VERSION} VERSION_GREATER 2.2.15 ) - target_compile_definitions(EvtGenExternal PRIVATE EVTGEN_SHERPA_USEMACRO) + if(EVTGEN_SHERPA3) + target_compile_definitions(EvtGenExternal PUBLIC EVTGEN_SHERPA_USEMACRO EVTGEN_SHERPA3) + target_link_libraries(EvtGenExternal PUBLIC SHERPA::All) + else() + if( ${SHERPA_VERSION} VERSION_GREATER 2.2.15 ) + target_compile_definitions(EvtGenExternal PUBLIC EVTGEN_SHERPA_USEMACRO) + endif() + target_include_directories(EvtGenExternal PUBLIC ${SHERPA_INCLUDE_DIRS}) + target_link_libraries(EvtGenExternal PUBLIC ${SHERPA_LIBRARIES}) endif() - target_include_directories(EvtGenExternal PUBLIC ${SHERPA_INCLUDE_DIRS}) - target_link_libraries(EvtGenExternal PUBLIC ${SHERPA_LIBRARIES}) endif() if(EVTGEN_HEPMC3) target_compile_definitions(EvtGenExternal PUBLIC EVTGEN_HEPMC3) @@ -220,11 +230,16 @@ endif() if(EVTGEN_SHERPA) target_compile_definitions(EvtGenExternalStatic PUBLIC EVTGEN_SHERPA) - if( ${SHERPA_VERSION} VERSION_GREATER 2.2.15 ) - target_compile_definitions(EvtGenExternalStatic PRIVATE EVTGEN_SHERPA_USEMACRO) + if(EVTGEN_SHERPA3) + target_compile_definitions(EvtGenExternalStatic PUBLIC EVTGEN_SHERPA_USEMACRO EVTGEN_SHERPA3) + target_link_libraries(EvtGenExternalStatic PUBLIC SHERPA::All) + else() + if( ${SHERPA_VERSION} VERSION_GREATER 2.2.15 ) + target_compile_definitions(EvtGenExternalStatic PUBLIC EVTGEN_SHERPA_USEMACRO) + endif() + target_include_directories(EvtGenExternalStatic PUBLIC ${SHERPA_INCLUDE_DIRS}) + target_link_libraries(EvtGenExternalStatic PUBLIC ${SHERPA_LIBRARIES}) endif() - target_include_directories(EvtGenExternalStatic PUBLIC ${SHERPA_INCLUDE_DIRS}) - target_link_libraries(EvtGenExternalStatic PUBLIC ${SHERPA_LIBRARIES}) endif() if(EVTGEN_HEPMC3) target_compile_definitions(EvtGenExternalStatic PUBLIC EVTGEN_HEPMC3) diff --git a/src/EvtGenExternal/EvtSherpaPhotons.cpp b/src/EvtGenExternal/EvtSherpaPhotons.cpp --- a/src/EvtGenExternal/EvtSherpaPhotons.cpp +++ b/src/EvtGenExternal/EvtSherpaPhotons.cpp @@ -28,9 +28,14 @@ #include "EvtGenBase/EvtVector4R.hh" #include "ATOOLS/Org/MyStrStream.H" -#include "ATOOLS/Phys/Particle.H" +#include "ATOOLS/Phys/Flavour.H" +#ifdef EVTGEN_SHERPA3 +#include "ATOOLS/Phys/KF_Table.H" +#else +#include "ATOOLS/Org/Data_Reader.H" #include "SHERPA/Initialization/Initialization_Handler.H" -#include "SHERPA/SoftPhysics/Soft_Photon_Handler.H" +#endif +#include "ATOOLS/Phys/Particle.H" #include <cstring> #include <iostream> @@ -38,9 +43,10 @@ using std::endl; +std::mutex EvtSherpaPhotons::m_sherpa_mutex; std::unique_ptr<SHERPA::Sherpa> EvtSherpaPhotons::m_sherpaGen; +std::unique_ptr<PHOTONS::Photons> EvtSherpaPhotons::m_photonsGen; bool EvtSherpaPhotons::m_initialised = false; -std::mutex EvtSherpaPhotons::m_sherpa_mutex; EvtSherpaPhotons::EvtSherpaPhotons( const bool useEvtGenRandom, const double infraredCutOff, const int mode, @@ -64,65 +70,105 @@ return; } +#ifdef EVTGEN_SHERPA3 + const std::string equal_string = ":"; + const std::string yfs_prefix = "YFS:\n"; + const std::string mode_string = m_mode == 2 + ? "Full" + : ( m_mode == 1 ? "Soft" : "None" ); + + // Beam parameters are necessary in Sherpa 3 for initialisation + // Otherwise m_s (CMS energy) is nan in YFS_Base and creates SegFault + // This has no impact on PHOTONS++. USING LHC values below. + m_configs.push_back( "BEAMS:2212" ); + m_configs.push_back( "BEAM_ENERGIES:7000" ); + +#else + const std::string equal_string = "="; + const std::string yfs_prefix = "YFS_"; + const std::string mode_string = ATOOLS::ToString( m_mode ); +#endif + + // INIT_ONLY=6 intialises the Sherpa objects without launching simulation. + m_configs.push_back( "INIT_ONLY" + equal_string + "6" ); + EvtGenReport( EVTGEN_INFO, "EvtGen" ) << "Setting up Sherpa PHOTONS++ generator for FSR." << endl; - /* Specify whether we are going to use EvtGen's random number generator + /* Specify whether we are going to use EvtGen's random number generator * (via EvtSherpaRandom interface) for Sherpa's PHOTONS++ simulation. */ if ( m_useEvtGenRandom ) { - m_configs.push_back( "SHERPA_LDADD=EvtGenExternal" ); - m_configs.push_back( "EXTERNAL_RNG=EvtSherpaRandom" ); + m_configs.push_back( "SHERPA_LDADD" + equal_string + "EvtGenExternal" ); + m_configs.push_back( "EXTERNAL_RNG" + equal_string + "EvtSherpaRandom" ); } /* * Internal PHOTONS++ settings. - * Documentation at + * Documentation at * https://sherpa.hepforge.org/doc/Sherpa.html#QED-Corrections */ /* - * YFS_IR_CUTOFF sets the infrared cut-off which serves as a + * YFS_IR_CUTOFF sets the infrared cut-off which serves as a * minimum photon energy in this frame for explicit photon generation. * The default is YFS_IR_CUTOFF = 1E-3 (GeV) but we set it to 1E-7 to equalize * with the cutoff used for PHOTOS. */ - m_configs.push_back( "YFS_IR_CUTOFF=" + ATOOLS::ToString( m_infraredCutOff ) ); + m_configs.push_back( yfs_prefix + "IR_CUTOFF" + equal_string + + ATOOLS::ToString( m_infraredCutOff ) ); /* - * The keyword YFS_MODE = [0,1,2] determines the mode of operation. - * YFS_MODE = 0 switches Photons off. - * YFS_MODE = 1 sets the mode to "soft only", meaning soft emissions will be - * treated correctly to all orders but no hard emission corrections will be included. - * YFS_MODE = 2 these hard emission corrections will also be included up to - * first order in alpha_QED. This is the default setting in Sherpa. + * The keyword YFS_MODE = [0,1,2] determines the mode of operation. + * YFS_MODE = 0 switches Photons off. + * YFS_MODE = 1 sets the mode to "soft only", meaning soft emissions will be + * treated correctly to all orders but no hard emission corrections will be included. + * YFS_MODE = 2 these hard emission corrections will also be included up to + * first order in alpha_QED. This is the default setting in Sherpa. */ - - m_configs.push_back( "YFS_MODE=" + ATOOLS::ToString( m_mode ) ); + m_configs.push_back( yfs_prefix + "MODE" + equal_string + mode_string ); /* - * The switch YFS_USE_ME = [0,1] tells Photons how to correct hard emissions to - * first order in alpha_QED. If YFS_USE_ME = 0, then Photons will use collinearly - * approximated real emission matrix elements. Virtual emission matrix elements of - * order alpha_QED are ignored. If, however, YFS_USE_ME=1, then exact real and/or - * virtual emission matrix elements are used wherever possible. - * These are presently available for V->FF, V->SS, S->FF, S->SS, S->Slnu, - * S->Vlnu type decays, Z->FF decays and leptonic tau and W decays. For all other - * decay types general collinearly approximated matrix elements are used. - * In both approaches all hadrons are treated as point-like objects. + * The switch YFS_USE_ME = [0,1] tells Photons how to correct hard emissions to + * first order in alpha_QED. If YFS_USE_ME = 0, then Photons will use collinearly + * approximated real emission matrix elements. Virtual emission matrix elements of + * order alpha_QED are ignored. If, however, YFS_USE_ME=1, then exact real and/or + * virtual emission matrix elements are used wherever possible. + * These are presently available for V->FF, V->SS, S->FF, S->SS, S->Slnu, + * S->Vlnu type decays, Z->FF decays and leptonic tau and W decays. For all other + * decay types general collinearly approximated matrix elements are used. + * In both approaches all hadrons are treated as point-like objects. * The default setting is YFS_USE_ME = 1. This switch is only effective if YFS_MODE = 2. */ - m_configs.push_back( "YFS_USE_ME=" + ATOOLS::ToString( m_useME ) ); - - // TODO: Virtual photon splitting into l+l- will be part of ME corrections from Sherpa 3.0.0 on, - // Once released, this should be switched off by default or - // taken into account while retrieving the event. + m_configs.push_back( yfs_prefix + "USE_ME" + equal_string + + ATOOLS::ToString( m_useME ) ); + +#ifdef EVTGEN_SHERPA3 + // Virtual photon splitting is part of ME corrections from Sherpa 3.0.0 on, + // We switch this off below. + // Support for photon splitting should be implemented for all FSR plug-ins, + // taking into account produced pairs while retrieving the event. + m_configs.push_back( yfs_prefix + "PHOTON_SPLITTER_MODE" + equal_string + + ATOOLS::ToString( 0 ) ); +#endif // Set up run-time arguments for Sherpa. std::vector<char*> argv = this->addParameters(); // Create instance and initialise Sherpa. +#ifdef EVTGEN_SHERPA3 + m_sherpaGen = std::make_unique<SHERPA::Sherpa>( argv.size(), &argv[0] ); + m_sherpaGen->InitializeTheRun(); + // Create the PHOTONS++ instance + m_photonsGen = std::make_unique<PHOTONS::Photons>(); +#else m_sherpaGen = std::make_unique<SHERPA::Sherpa>(); m_sherpaGen->InitializeTheRun( argv.size(), &argv[0] ); + // Create the PHOTONS++ instance + // Needs to create and pass a Data_reader object as in the Soft_Photon_Handler + std::unique_ptr<ATOOLS::Data_Reader> dataread = + std::make_unique<ATOOLS::Data_Reader>( " ", ";", "!", "=" ); + m_photonsGen = std::make_unique<PHOTONS::Photons>( dataread.get() ); +#endif this->updateParticleLists(); @@ -148,9 +194,9 @@ void EvtSherpaPhotons::updateParticleLists() { - /* Use the EvtGen decay and pdl tables (decay/user.dec and evt.pdl) - * to update Sherpa's KF_Table which contains all defined particles - * and their properties. + /* Use the EvtGen decay and pdl tables (decay/user.dec and evt.pdl) + * to update Sherpa's KF_Table which contains all defined particles + * and their properties. * Loop over all entries in the EvtPDL particle data table. */ const int nPDL = EvtPDL::entries(); @@ -190,8 +236,15 @@ // Create new entry in the KF_Table. The 0 and 1 in the constructor below // stand for m_on = 0 and m_stable = 1. These properties are irrelevant // for final-state radiation and set to default values. +#ifdef EVTGEN_SHERPA3 + const double radius{ 0.0 }; + ATOOLS::s_kftable[particleCode] = + new ATOOLS::Particle_Info( particleCode, mass, radius, width, + charge, spin, 0, 1, idName, idName ); +#else ATOOLS::s_kftable[particleCode] = new ATOOLS::Particle_Info( particleCode, mass, width, charge, spin, 0, 1, idName, idName ); +#endif } } @@ -212,9 +265,6 @@ // Create a blob. std::unique_ptr<ATOOLS::Blob> blob = std::make_unique<ATOOLS::Blob>(); - // Tell Sherpa that the blob needs FSR (that is extra QED) - blob->SetStatus( ATOOLS::blob_status::needs_extraQED ); - // Create mother particle and add it to blob ATOOLS::Flavour mother_flav( EvtPDL::getStdHep( theParticle->getId() ) ); mother_flav.SetStable( false ); @@ -259,13 +309,8 @@ // AddRadiation function is not yet thread_safe, so we mutex it const std::lock_guard<std::mutex> lock( m_sherpa_mutex ); - const SHERPA::Initialization_Handler* inithandler = - m_sherpaGen->GetInitHandler(); - SHERPA::Soft_Photon_Handler* softphotonhandler = - inithandler->GetSoftPhotonHandler(); - // Simulate the radiation - softphotonhandler->AddRadiation( blob.get() ); + m_photonsGen->AddRadiation( blob.get() ); } // Get number of final-state particles @@ -300,4 +345,20 @@ } } +void EvtSherpaPhotons::finalise() +{ + // Mutex this since Sherpa instances are static + const std::lock_guard<std::mutex> lock( m_sherpa_mutex ); + + if ( !m_initialised ) { + return; + } + + // We explicitly destroy the static instances to make sure that this occurs in the right order. + // This is needed due to the static destruction order fiasco. + m_photonsGen.reset(); + m_sherpaGen.reset(); + m_initialised = false; +} + #endif diff --git a/test/testDecayModel.cc b/test/testDecayModel.cc --- a/test/testDecayModel.cc +++ b/test/testDecayModel.cc @@ -36,6 +36,7 @@ #ifdef EVTGEN_EXTERNAL #include "EvtGenExternal/EvtExternalGenList.hh" +#include "EvtGenExternal/EvtSherpaPhotons.hh" #endif #include "TROOT.h" @@ -413,6 +414,17 @@ theHistos = runDecayBody( 0, m_config.nEvents ); } +#ifdef EVTGEN_SHERPA + // The Sherpa and PHOTONS++ instances are static global instances inside EvtGen + // as they are not thread safe (they are mutexed). From Sherpa 3.0.0 on, + // the internal Sherpa settings are also a static global instance. + // Because of the static destruction order fiasco, + // we need to control the order in which the static instances are destroyed. + // This is done by hand inside the function below. If the function below is not called, + // a SegFault occurs at the end of the program execution when using Sherpa for FSR. + EvtSherpaPhotons::finalise(); +#endif + const auto end{ std::chrono::steady_clock::now() }; const std::chrono::duration<double, std::milli> elapsed_ms{ ( end - start ) }; const std::chrono::duration<double, std::milli> elapsed_ms_per_event{