diff --git a/GeneratorInterface/EvtGenInterface/BuildFile.xml b/GeneratorInterface/EvtGenInterface/BuildFile.xml
index 1c760778eb73e..96c60fae69557 100644
--- a/GeneratorInterface/EvtGenInterface/BuildFile.xml
+++ b/GeneratorInterface/EvtGenInterface/BuildFile.xml
@@ -4,6 +4,7 @@
+
diff --git a/GeneratorInterface/EvtGenInterface/interface/myEvtRandomEngine.h b/GeneratorInterface/EvtGenInterface/interface/myEvtRandomEngine.h
index be9ab5345067f..abdf86ff981a1 100644
--- a/GeneratorInterface/EvtGenInterface/interface/myEvtRandomEngine.h
+++ b/GeneratorInterface/EvtGenInterface/interface/myEvtRandomEngine.h
@@ -32,6 +32,10 @@ class myEvtRandomEngine : public EvtRandomEngine {
double random() override;
+ void setSeed(unsigned long int seed) override;
+
+ unsigned long int lastSeed() const override;
+
void setRandomEngine(CLHEP::HepRandomEngine* v) { the_engine = v; }
CLHEP::HepRandomEngine* engine() const { return the_engine; }
@@ -40,5 +44,6 @@ class myEvtRandomEngine : public EvtRandomEngine {
void throwNullPtr() const;
CLHEP::HepRandomEngine* the_engine;
+ unsigned long int m_lastSeed = 0;
};
#endif
diff --git a/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.cc b/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.cc
index c71fe59e637a5..ed8ff91ee0430 100644
--- a/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.cc
+++ b/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.cc
@@ -36,25 +36,38 @@
#include "EvtGenBase/EvtDecayBase.hh"
#include "EvtGenBase/EvtId.hh"
#include "EvtGenBase/EvtDecayTable.hh"
+#include "EvtGenBase/EvtPDL.hh"
+#include "EvtGenBase/EvtRandom.hh"
#include "EvtGenBase/EvtParticle.hh"
#include "EvtGenBase/EvtParticleFactory.hh"
#include "EvtGenBase/EvtHepMCEvent.hh"
#include "HepPID/ParticleIDTranslations.hh"
+#include "ATOOLS/Org/My_MPI.H"
+
#include "TString.h"
#include
#include
#include
+thread_local std::unique_ptr gen::EvtGenInterface::m_EvtGen{};
+
using namespace gen;
using namespace edm;
-CLHEP::HepRandomEngine* EvtGenInterface::fRandomEngine;
+// Sherpa is built with MPI and aborts unless MPI is initialized.
+// We only need a dummy init, and it must happen exactly once per process not per thread.
+void initDummyMPIOnce() {
+ [[maybe_unused]] static const bool init = [] {
+ MPI_Init(0, nullptr);
+ return true;
+ }();
+}
EvtGenInterface::EvtGenInterface(const ParameterSet& pset) {
- fPSet = new ParameterSet(pset);
- the_engine = new myEvtRandomEngine(nullptr);
+ fPSet = std::make_unique(pset);
+ the_engine = std::make_unique(nullptr);
}
void EvtGenInterface::SetDefault_m_PDGs() {
@@ -284,19 +297,28 @@ void EvtGenInterface::SetDefault_m_PDGs() {
}
}
+// Destructor is a no-op: m_EvtGen is a thread_local std::unique_ptr that cleans up at thread exit.
EvtGenInterface::~EvtGenInterface() {}
-void EvtGenInterface::init() {
- // flags for pythia8
- fSpecialSettings.push_back("Pythia8:ParticleDecays:mixB = off");
- //
+void EvtGenInterface::ensureEvtGenOnThread() {
+ // This thread already has its EvtGen
+ if (m_EvtGen)
+ return;
edm::FileInPath decay_table(fPSet->getParameter("decay_table"));
edm::FileInPath pdt(fPSet->getParameter("particle_property_file"));
bool usePythia = fPSet->getUntrackedParameter("use_internal_pythia", true);
bool useTauola = fPSet->getUntrackedParameter("use_internal_tauola", true);
- bool usePhotos = fPSet->getUntrackedParameter("use_internal_photos", true);
+
+ if (fPSet->existsAs("use_internal_fsr", false)) {
+ edm::LogWarning("EvtGenInterface::ensureEvtGenOnThread")
+ << "The 'use_internal_fsr' parameter is deprecated and has no effect. "
+ "Please use 'fsr_model' instead (set to 'none' to disable FSR, or "
+ "'photos', 'sherpa', or 'vincia' to select the FSR model).";
+ }
+
+ std::string fsrModel = fPSet->getParameter("fsr_model");
//Setup evtGen following instructions on http://evtgen.warwick.ac.uk/docs/external/
bool convertPythiaCodes = fPSet->getUntrackedParameter(
@@ -305,8 +327,8 @@ void EvtGenInterface::init() {
std::getenv("PYTHIA8DATA"); // Specify the pythia xml data directory to use the default PYTHIA8DATA location
if (tmp == nullptr) {
- edm::LogError("EvtGenInterface::~EvtGenInterface")
- << "EvtGenInterface::init() PYTHIA8DATA not defined. Terminating program ";
+ edm::LogError("EvtGenInterface::ensureEvtGenOnThread")
+ << "PYTHIA8DATA not defined. Terminating program ";
exit(0);
}
@@ -317,8 +339,20 @@ void EvtGenInterface::init() {
// Set up the default external generator list: Photos, Pythia and/or Tauola
EvtExternalGenList genList(convertPythiaCodes, pythiaDir, photonType, useEvtGenRandom);
EvtAbsRadCorr* radCorrEngine = nullptr;
- if (usePhotos)
- radCorrEngine = genList.getPhotosModel(); // Get interface to radiative correction engine
+ if (fsrModel == "none") {
+ // FSR disabled
+ } else if (fsrModel == "photos") {
+ radCorrEngine = genList.getPhotosModel();
+ } else if (fsrModel == "sherpa") {
+ initDummyMPIOnce(); // Sherpa is built with MPI and complains if not initialized; do this once per process.
+ radCorrEngine = genList.getSherpaPhotonsModel(1e-7, 1, 0);
+ } else if (fsrModel == "vincia") {
+ radCorrEngine = genList.getVinciaQEDModel(1.0e-7);
+ } else {
+ throw cms::Exception("Configuration")
+ << "EvtGenInterface: unknown fsr_model '" << fsrModel
+ << "'. Allowed values are 'none', 'photos', 'sherpa', or 'vincia'.";
+ }
std::list extraModels = genList.getListOfModels(); // get interface to Pythia and Tauola
std::list myExtraModels;
for (unsigned int i = 0; i < extraModels.size(); i++) {
@@ -339,21 +373,12 @@ void EvtGenInterface::init() {
std::list::iterator it = userModels.begin();
std::advance(it, i);
TString name = (*it)->getName();
- edm::LogInfo("EvtGenInterface::~EvtGenInterface") << "Adding user model: " << name;
+ edm::LogInfo("EvtGenInterface::ensureEvtGenOnThread") << "Adding user model: " << name;
myExtraModels.push_back(*it);
}
- // Set up the incoherent (1) or coherent (0) B mixing option
- BmixingOption = fPSet->getUntrackedParameter("B_Mixing", 1);
- if (BmixingOption != 0 && BmixingOption != 1) {
- throw cms::Exception("Configuration") << "EvtGenProducer requires B_Mixing to be 0 (coherent) or 1 (incoherent) \n"
- "Please fix this in your configuration.";
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Create the EvtGen generator object, passing the external generators
- m_EvtGen = new EvtGen(
- decay_table.fullPath().c_str(), pdt.fullPath().c_str(), the_engine, radCorrEngine, &myExtraModels, BmixingOption);
+ m_EvtGen = std::make_unique(
+ decay_table.fullPath().c_str(), pdt.fullPath().c_str(), the_engine.get(), radCorrEngine, &myExtraModels, BmixingOption);
// Add additional user information
if (fPSet->exists("user_decay_file")) {
@@ -370,9 +395,8 @@ void EvtGenInterface::init() {
int tmp_creation = mkstemp(user_decay_tmp);
FILE* tmpf = std::fopen(user_decay_tmp, "w");
if (!tmpf || (tmp_creation == -1)) {
- edm::LogError("EvtGenInterface::~EvtGenInterface")
- << "EvtGenInterface::init() fails when trying to open a temporary file for embedded user.dec. Terminating "
- "program ";
+ edm::LogError("EvtGenInterface::ensureEvtGenOnThread")
+ << "fails when trying to open a temporary file for embedded user.dec. Terminating program ";
exit(0);
}
for (unsigned int i = 0; i < user_decay_lines.size(); i++) {
@@ -382,6 +406,23 @@ void EvtGenInterface::init() {
std::fclose(tmpf);
m_EvtGen->readUDecay(user_decay_tmp);
}
+}
+
+void EvtGenInterface::init() {
+ // flags for pythia8
+ fSpecialSettings.push_back("Pythia8:ParticleDecays:mixB = off");
+
+ // Set up the incoherent (1) or coherent (0) B mixing option. Must be set before
+ // ensureEvtGenOnThread() because the EvtGen ctor consumes it.
+ BmixingOption = fPSet->getUntrackedParameter("B_Mixing", 1);
+ if (BmixingOption != 0 && BmixingOption != 1) {
+ throw cms::Exception("Configuration") << "EvtGenProducer requires B_Mixing to be 0 (coherent) or 1 (incoherent) \n"
+ "Please fix this in your configuration.";
+ }
+
+ // Construct the EvtGen instance for this thread (no-op if already constructed). Streams
+ // running decay() later on a different thread will lazy-construct on that thread instead.
+ ensureEvtGenOnThread();
// setup pdgid which the generator/hadronizer should not decay
if (fPSet->exists("operates_on_particles")) {
@@ -452,6 +493,10 @@ void EvtGenInterface::init() {
}
HepMC::GenEvent* EvtGenInterface::decay(HepMC::GenEvent* evt) {
+ // If the framework scheduled this stream onto a thread that has not yet built an EvtGen,
+ // construct one now. No-op on threads that already initialised in init().
+ ensureEvtGenOnThread();
+
if (the_engine->engine() == nullptr) {
throw edm::Exception(edm::errors::LogicError)
<< "The EvtGen code attempted to use a random number engine while\n"
@@ -496,8 +541,8 @@ HepMC::GenEvent* EvtGenInterface::decay(HepMC::GenEvent* evt) {
}
EvtId idEvt = EvtPDL::evtIdFromStdHep(idHep);
int ipart = idEvt.getId();
- EvtDecayTable* evtDecayTable = EvtDecayTable::getInstance();
- if (!isforced && isDefaultEvtGen && ipart != -1 && evtDecayTable->getNMode(ipart) != 0) {
+ EvtDecayTable& evtDecayTable = EvtDecayTable::getInstance();
+ if (!isforced && isDefaultEvtGen && ipart != -1 && evtDecayTable.getNMode(ipart) != 0) {
addToHepMC(*p, idEvt, evt, true); // generate decay and remove daugther if they are forced
}
}
@@ -616,17 +661,11 @@ void EvtGenInterface::update_particles(HepMC::GenParticle* partHep, HepMC::GenEv
void EvtGenInterface::setRandomEngine(CLHEP::HepRandomEngine* v) {
the_engine->setRandomEngine(v);
- fRandomEngine = v;
+ EvtRandom::setRandomEngine(the_engine.get());
}
double EvtGenInterface::flat() {
- if (!fRandomEngine) {
- throw cms::Exception("LogicError")
- << "EvtGenInterface::flat: Attempt to generate random number when engine pointer is null\n"
- << "This might mean that the code was modified to generate a random number outside the\n"
- << "event and beginLuminosityBlock methods, which is not allowed.\n";
- }
- return fRandomEngine->flat();
+ return the_engine->random();
}
bool EvtGenInterface::findLastinChain(HepMC::GenParticle*& p) {
diff --git a/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.h b/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.h
index 0dad34911846c..bb5f810784254 100644
--- a/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.h
+++ b/GeneratorInterface/EvtGenInterface/plugins/EvtGen/EvtGenInterface.h
@@ -43,7 +43,7 @@ namespace gen {
const std::vector& operatesOnParticles() override { return m_PDGs; }
HepMC::GenEvent* decay(HepMC::GenEvent*) override;
void setRandomEngine(CLHEP::HepRandomEngine* v) override;
- static double flat();
+ double flat();
private:
bool addToHepMC(HepMC::GenParticle* partHep, const EvtId& idEvt, HepMC::GenEvent* theEvent, bool del_daug);
@@ -52,8 +52,10 @@ namespace gen {
bool findLastinChain(HepMC::GenParticle*& p);
bool hasnoDaughter(HepMC::GenParticle* p);
void go_through_daughters(EvtParticle* part);
+ void ensureEvtGenOnThread();
- EvtGen* m_EvtGen; // EvtGen main object
+ // One EvtGen per thread
+ static thread_local std::unique_ptr m_EvtGen;
std::vector forced_id; // EvtGen Id's of particles which are to be forced by EvtGen
std::vector forced_pdgids; // PDG Id's of particles which are to be forced by EvtGen
@@ -65,10 +67,9 @@ namespace gen {
std::vector polarize_pol;
std::map polarizations;
int BmixingOption = 1;
- edm::ParameterSet* fPSet;
+ std::unique_ptr fPSet;
- static CLHEP::HepRandomEngine* fRandomEngine;
- myEvtRandomEngine* the_engine;
+ std::unique_ptr the_engine;
};
} // namespace gen
#endif
diff --git a/GeneratorInterface/EvtGenInterface/plugins/myEvtRandomEngine.cc b/GeneratorInterface/EvtGenInterface/plugins/myEvtRandomEngine.cc
index 43506f9a9b132..5d39dd28369a3 100644
--- a/GeneratorInterface/EvtGenInterface/plugins/myEvtRandomEngine.cc
+++ b/GeneratorInterface/EvtGenInterface/plugins/myEvtRandomEngine.cc
@@ -30,6 +30,10 @@ double myEvtRandomEngine::random() {
return the_engine->flat();
}
+void myEvtRandomEngine::setSeed(unsigned long int seed) { m_lastSeed = seed; }
+
+unsigned long int myEvtRandomEngine::lastSeed() const { return m_lastSeed; }
+
void myEvtRandomEngine::throwNullPtr() const {
throw edm::Exception(edm::errors::LogicError) << "The EvtGen code attempted to a generate random number while\n"
<< "the engine pointer was null. This might mean that the code\n"
diff --git a/GeneratorInterface/EvtGenInterface/plugins/test/Py8_lambadb_evtgen1_Lb2plnuLCSR_cfg.py b/GeneratorInterface/EvtGenInterface/plugins/test/Py8_lambadb_evtgen1_Lb2plnuLCSR_cfg.py
index d9678b66c8d3b..c845c0d3fd33f 100644
--- a/GeneratorInterface/EvtGenInterface/plugins/test/Py8_lambadb_evtgen1_Lb2plnuLCSR_cfg.py
+++ b/GeneratorInterface/EvtGenInterface/plugins/test/Py8_lambadb_evtgen1_Lb2plnuLCSR_cfg.py
@@ -56,6 +56,7 @@
decay_table = cms.string('GeneratorInterface/EvtGenInterface/data/DECAY_NOLONGLIFE.DEC'),
list_forced_decays = cms.vstring('MyLambda_b0','Myanti-Lambda_b0'),
particle_property_file = cms.FileInPath('GeneratorInterface/EvtGenInterface/data/evt.pdl'),
+ fsr_model = cms.string('sherpa'),
operates_on_particles = cms.vint32(5122), #only care about signal particle
user_decay_embedded = cms.vstring(
"""
diff --git a/GeneratorInterface/EvtGenInterface/test/Py8_bplus_evtgen1_cfg.py b/GeneratorInterface/EvtGenInterface/test/Py8_bplus_evtgen1_cfg.py
index 08dc631309246..289c2d96b9e85 100644
--- a/GeneratorInterface/EvtGenInterface/test/Py8_bplus_evtgen1_cfg.py
+++ b/GeneratorInterface/EvtGenInterface/test/Py8_bplus_evtgen1_cfg.py
@@ -97,7 +97,8 @@
'0.0168 Mychi_c1 K+ SVS ;',
'Enddecay',
'CDecay MyB-',
- 'End')
+ 'End'),
+ fsr_model = cms.string('sherpa'),
),
parameterSets = cms.vstring('EvtGen1')
),
diff --git a/GeneratorInterface/EvtGenInterface/test/Py8_tt_evtgen1_cfg.py b/GeneratorInterface/EvtGenInterface/test/Py8_tt_evtgen1_cfg.py
index db0b7f6c948cf..9c2a3e81ae620 100644
--- a/GeneratorInterface/EvtGenInterface/test/Py8_tt_evtgen1_cfg.py
+++ b/GeneratorInterface/EvtGenInterface/test/Py8_tt_evtgen1_cfg.py
@@ -24,7 +24,8 @@
particle_property_file = cms.FileInPath('GeneratorInterface/EvtGenInterface/data/evt.pdl'),
convertPythiaCodes = cms.untracked.bool(False), # this is needed since 1.6
list_forced_decays = cms.vstring(),
- operates_on_particles = cms.vint32(0) #will decay all particles coded in interface, it test the whole system
+ operates_on_particles = cms.vint32(0), #will decay all particles coded in interface, it test the whole system,
+ fsr_model = cms.string('sherpa')
),
parameterSets = cms.vstring('EvtGen1')
),
diff --git a/GeneratorInterface/EvtGenInterface/test/external_Py8_bplus_evtgen1_cfg.py b/GeneratorInterface/EvtGenInterface/test/external_Py8_bplus_evtgen1_cfg.py
index ceb2a1d1440f9..72d8c8457a2fd 100644
--- a/GeneratorInterface/EvtGenInterface/test/external_Py8_bplus_evtgen1_cfg.py
+++ b/GeneratorInterface/EvtGenInterface/test/external_Py8_bplus_evtgen1_cfg.py
@@ -97,7 +97,8 @@
'0.0168 Mychi_c1 K+ SVS ;',
'Enddecay',
'CDecay MyB-',
- 'End')
+ 'End'),
+ fsr_model = cms.string('sherpa')
),
parameterSets = cms.vstring('EvtGen1')
),
diff --git a/GeneratorInterface/ExternalDecays/BuildFile.xml b/GeneratorInterface/ExternalDecays/BuildFile.xml
index 64b095a3fc707..fbe5ec16d2f99 100644
--- a/GeneratorInterface/ExternalDecays/BuildFile.xml
+++ b/GeneratorInterface/ExternalDecays/BuildFile.xml
@@ -1,6 +1,7 @@
+
diff --git a/GeneratorInterface/ExternalDecays/interface/ConcurrentExternalDecayDriver.h b/GeneratorInterface/ExternalDecays/interface/ConcurrentExternalDecayDriver.h
index 80f45590dfa09..244d95cee8199 100644
--- a/GeneratorInterface/ExternalDecays/interface/ConcurrentExternalDecayDriver.h
+++ b/GeneratorInterface/ExternalDecays/interface/ConcurrentExternalDecayDriver.h
@@ -21,6 +21,7 @@ namespace lhef {
namespace gen {
+ class EvtGenThreadOwner;
class EvtGenInterfaceBase;
class TauolaInterfaceBase;
class PhotosInterfaceBase;
@@ -45,8 +46,9 @@ namespace gen {
private:
bool fIsInitialized;
+ std::unique_ptr fThreadOwner;
+ std::unique_ptr fEvtGenInterface;
//std::unique_ptr fTauolaInterface;
- //std::unique_ptr fEvtGenInterface;
//std::unique_ptr fPhotosInterface;
std::vector fPDGs;
std::vector fSpecialSettings;
diff --git a/GeneratorInterface/ExternalDecays/interface/EvtGenThreadOwner.h b/GeneratorInterface/ExternalDecays/interface/EvtGenThreadOwner.h
new file mode 100644
index 0000000000000..d3c2573efbedd
--- /dev/null
+++ b/GeneratorInterface/ExternalDecays/interface/EvtGenThreadOwner.h
@@ -0,0 +1,33 @@
+#ifndef gen_EvtGenThreadOwner_h
+#define gen_EvtGenThreadOwner_h
+
+// Pins one dedicated pthread per stream and marshals every EvtGen call onto it.
+
+#include "FWCore/Utilities/interface/ThreadHandoff.h"
+#include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
+
+namespace gen {
+
+ class EvtGenThreadOwner {
+ public:
+ explicit EvtGenThreadOwner(int stackSize) : m_handoff{stackSize} {}
+
+ EvtGenThreadOwner(const EvtGenThreadOwner&) = delete;
+ EvtGenThreadOwner& operator=(const EvtGenThreadOwner&) = delete;
+
+ template
+ void run(F&& f) {
+ auto token = edm::ServiceRegistry::instance().presentToken();
+ m_handoff.runAndWait([token, &f]() {
+ edm::ServiceRegistry::Operate guard{token};
+ f();
+ });
+ }
+
+ private:
+ edm::ThreadHandoff m_handoff;
+ };
+
+}
+
+#endif
diff --git a/GeneratorInterface/ExternalDecays/src/ConcurrentExternalDecayDriver.cc b/GeneratorInterface/ExternalDecays/src/ConcurrentExternalDecayDriver.cc
index 57ccbe49710af..c86db8ecc2279 100644
--- a/GeneratorInterface/ExternalDecays/src/ConcurrentExternalDecayDriver.cc
+++ b/GeneratorInterface/ExternalDecays/src/ConcurrentExternalDecayDriver.cc
@@ -1,4 +1,5 @@
#include "GeneratorInterface/ExternalDecays/interface/ConcurrentExternalDecayDriver.h"
+#include "GeneratorInterface/ExternalDecays/interface/EvtGenThreadOwner.h"
#include "GeneratorInterface/Core/interface/FortranInstance.h"
#include "GeneratorInterface/EvtGenInterface/interface/EvtGenFactory.h"
@@ -20,100 +21,55 @@
using namespace gen;
using namespace edm;
-ConcurrentExternalDecayDriver::ConcurrentExternalDecayDriver(const ParameterSet& pset) : fIsInitialized(false) {
+// Matches SimG4Core's OscarMTProducer default (`workerThreadStackSize`).
+constexpr int kEvtGenThreadStackSize = 10 * 1024 * 1024;
+
+ConcurrentExternalDecayDriver::ConcurrentExternalDecayDriver(const ParameterSet& pset)
+ : fIsInitialized(false), fThreadOwner(std::make_unique(kEvtGenThreadStackSize)) {
std::vector extGenNames = pset.getParameter >("parameterSets");
for (unsigned int ip = 0; ip < extGenNames.size(); ++ip) {
const std::string& curSet = extGenNames[ip];
- throw cms::Exception("ThreadUnsafeDecayer") << "The decayer " << curSet << " is not thread-friendly.";
- /*
- if (curSet == "EvtGen") {
- fEvtGenInterface = std::unique_ptr(
- EvtGenFactory::get()->create("EvtGen", pset.getUntrackedParameter(curSet)));
- exSharedResources.emplace_back(edm::SharedResourceNames::kEvtGen);
- exSharedResources.emplace_back(edm::SharedResourceNames::kPythia6);
- exSharedResources.emplace_back(gen::FortranInstance::kFortranInstance);
- } else if (curSet == "EvtGen1" || curSet == "EvtGen130") {
- fEvtGenInterface = std::unique_ptr(
- EvtGenFactory::get()->create("EvtGen130", pset.getUntrackedParameter(curSet)));
- exSharedResources.emplace_back(edm::SharedResourceNames::kEvtGen);
- exSharedResources.emplace_back(edm::SharedResourceNames::kPythia8);
- exSharedResources.emplace_back(edm::SharedResourceNames::kTauola);
- exSharedResources.emplace_back(edm::SharedResourceNames::kPhotos);
- exSharedResources.emplace_back(gen::FortranInstance::kFortranInstance);
- } else if (curSet == "Tauola" || curSet == "Tauolapp" || curSet == "Tauolapp114") {
- fTauolaInterface = std::unique_ptr(
- TauolaFactory::get()->create("Tauolapp114", pset.getUntrackedParameter(curSet)));
- fPhotosInterface = std::unique_ptr(
- PhotosFactory::get()->create("Photos2155", pset.getUntrackedParameter(curSet)));
- fPhotosInterface->configureOnlyFor(15);
- fPhotosInterface->avoidTauLeptonicDecays();
- exSharedResources.emplace_back(edm::SharedResourceNames::kTauola);
- exSharedResources.emplace_back(edm::SharedResourceNames::kPhotos);
- } else if (curSet == "Photos" || curSet == "Photos2155") {
- if (!fPhotosInterface) {
- fPhotosInterface = std::unique_ptr(
- PhotosFactory::get()->create("Photos2155", pset.getUntrackedParameter(curSet)));
- exSharedResources.emplace_back(edm::SharedResourceNames::kPhotos);
- }
- } else if (curSet == "Photospp" || curSet == "Photospp356") {
- if (!fPhotosInterface) {
- fPhotosInterface = std::unique_ptr(
- PhotosFactory::get()->create("Photospp356", pset.getUntrackedParameter(curSet)));
- exSharedResources.emplace_back(edm::SharedResourceNames::kPhotos);
- }
+ if (curSet == "EvtGen1" || curSet == "EvtGen130") {
+ fThreadOwner->run([&]() {
+ fEvtGenInterface = std::unique_ptr(
+ EvtGenFactory::get()->create("EvtGen130", pset.getUntrackedParameter(curSet)));
+ });
+ } else {
+ throw cms::Exception("ThreadUnsafeDecayer") << "The decayer " << curSet << " is not thread-friendly.";
}
- */
}
}
-ConcurrentExternalDecayDriver::~ConcurrentExternalDecayDriver() = default;
+ConcurrentExternalDecayDriver::~ConcurrentExternalDecayDriver() {
+ if (fEvtGenInterface) {
+ fThreadOwner->run([&]() { fEvtGenInterface.reset(); });
+ }
+}
HepMC::GenEvent* ConcurrentExternalDecayDriver::decay(HepMC::GenEvent* evt, lhef::LHEEvent* lheEvent) {
- /* if (fTauolaInterface)
- fTauolaInterface->SetLHE(lheEvent); */
return decay(evt);
}
HepMC::GenEvent* ConcurrentExternalDecayDriver::decay(HepMC::GenEvent* evt) {
if (!fIsInitialized)
return evt;
- /*
- if (fEvtGenInterface) {
- evt = fEvtGenInterface->decay(evt);
- if (!evt)
- return nullptr;
- }
- if (fTauolaInterface) {
- evt = fTauolaInterface->decay(evt);
+ if (fEvtGenInterface) {
+ fThreadOwner->run([&]() { evt = fEvtGenInterface->decay(evt); });
if (!evt)
return nullptr;
}
- if (fPhotosInterface) {
- evt = fPhotosInterface->apply(evt);
- if (!evt)
- return nullptr;
- }
- */
return evt;
}
void ConcurrentExternalDecayDriver::init(const edm::EventSetup& es) {
if (fIsInitialized)
return;
- /*
- if (fTauolaInterface) {
- fTauolaInterface->init(es);
- for (std::vector::const_iterator i = fTauolaInterface->operatesOnParticles().begin();
- i != fTauolaInterface->operatesOnParticles().end();
- i++)
- fPDGs.push_back(*i);
- }
if (fEvtGenInterface) {
- fEvtGenInterface->init();
+ fThreadOwner->run([&]() { fEvtGenInterface->init(); });
for (std::vector::const_iterator i = fEvtGenInterface->operatesOnParticles().begin();
i != fEvtGenInterface->operatesOnParticles().end();
i++)
@@ -123,39 +79,15 @@ void ConcurrentExternalDecayDriver::init(const edm::EventSetup& es) {
}
}
- if (fPhotosInterface) {
- fPhotosInterface->init();
- // for tauola++
- if (fPhotosInterface) {
- for (unsigned int iss = 0; iss < fPhotosInterface->specialSettings().size(); iss++) {
- fSpecialSettings.push_back(fPhotosInterface->specialSettings()[iss]);
- }
- }
- }
- */
-
fIsInitialized = true;
return;
}
-void ConcurrentExternalDecayDriver::statistics() const {
- /* if (fTauolaInterface)
- fTauolaInterface->statistics();
- if (fPhotosInterface)
- fPhotosInterface->statistics();
- */
- // similar for EvtGen if needed
- return;
-}
+void ConcurrentExternalDecayDriver::statistics() const { return; }
void ConcurrentExternalDecayDriver::setRandomEngine(CLHEP::HepRandomEngine* v) {
- /*
- if (fTauolaInterface)
- fTauolaInterface->setRandomEngine(v);
- if (fEvtGenInterface)
- fEvtGenInterface->setRandomEngine(v);
- if (fPhotosInterface)
- fPhotosInterface->setRandomEngine(v);
- */
+ if (fEvtGenInterface) {
+ fThreadOwner->run([&]() { fEvtGenInterface->setRandomEngine(v); });
+ }
}