14#include "ThePEG/Repository/EventGenerator.h"
15#include "ThePEG/Repository/Repository.h"
16#include "ThePEG/Persistency/PersistentIStream.h"
17#include "ThePEG/Utilities/DynamicLoader.h"
18#include "ThePEG/Utilities/Debug.h"
19#include "ThePEG/EventRecord/Event.h"
20#include "ThePEG/EventRecord/SubProcess.h"
21#include "ThePEG/Handlers/XComb.h"
22#include "ThePEG/Handlers/EventHandler.h"
23#include "ThePEG/PDF/PartonExtractor.h"
24#include "ThePEG/PDF/PDF.h"
26#include "Herwig/API/HerwigAPI.h"
27#include "Herwig/Utilities/HerwigStrategy.h"
78 const long* seeds = engine->getSeeds();
83 int32_t combined_seed = std::abs(seeds[0] * seeds[1]);
85 std::ostringstream ss_seed;
86 ss_seed << combined_seed;
92 ATH_MSG_INFO(
"Using the random number seed " + ss_seed.str() +
" provided by athena");
93 m_api.seed(combined_seed);
98 ThePEG::Repository::exitOnError() = 1;
101 const char* datapath = getenv(
"DATAPATH" );
102 std::vector<std::string> datapaths;
104 std::string datapath_str(datapath);
105 for (
auto part : std::views::split(datapath_str,
':')) {
106 datapaths.emplace_back(part.begin(), part.end());
109 for(
const std::string& p : datapaths ) {
110 ThePEG::Repository::appendReadDir( p );
112 const char* ldpath = getenv(
"LD_LIBRARY_PATH" );
113 std::vector<std::string> ldpaths;
115 std::string ldpath_str(ldpath);
116 for (
auto part : ldpath_str | std::views::split(
':')) {
117 ldpaths.emplace_back(std::string(part.begin(), part.end()));
120 for(
const std::string& p : ldpaths ) {
121 ThePEG::DynamicLoader::appendPath( p );
124 ATH_MSG_DEBUG(
"Num of library search paths = " << ThePEG::DynamicLoader::allPaths().
size());
128 ATH_MSG_DEBUG(
"Loading Herwig default repo from " << repopath);
129 ThePEG::Repository::load(repopath);
130 ATH_MSG_DEBUG(
"Successfully loaded Herwig default repository");
132 const std::string share_path = std::filesystem::path(std::move(repopath)).parent_path().string();
143 m_runinfo = std::make_shared<HepMC3::GenRunInfo>();
145 struct HepMC3::GenRunInfo::ToolInfo generator={std::string(
"Herwig7"), Herwig::HerwigStrategy::version, std::string(
"Used generator")};
146 m_runinfo->tools().push_back(std::move(generator));
151 return StatusCode::SUCCESS;
157 return StatusCode::SUCCESS;
161 const std::string runfile_suffix =
".run";
162 const auto suffix_pos = inputfile_name.rfind(runfile_suffix);
163 if (suffix_pos != std::string::npos) {
164 inputfile_name.replace(suffix_pos, runfile_suffix.size(),
".in");
166 std::filesystem::path inputfile_path(
m_runfile);
167 inputfile_path.replace_extension(
".in");
168 inputfile_name = inputfile_path.string();
171 ATH_MSG_INFO(
"Writing CA infile text to '"+inputfile_name+
"'");
172 std::ofstream infile_stream(inputfile_name);
174 if (!infile_stream) {
175 ATH_MSG_ERROR(
"Failed to write CA infile text to '"+inputfile_name+
"'");
176 return StatusCode::FAILURE;
179 if (share_path.empty()) {
180 ATH_MSG_ERROR(
"Could not determine the Herwig share path for CA infile materialisation");
181 return StatusCode::FAILURE;
184 ATH_MSG_INFO(
"Preparing Herwig runfile from CA infile '"+inputfile_name+
"'");
185 m_api.prependReadDirectory(share_path);
186 m_api.inputfile(inputfile_name);
187 Herwig::API::read(
m_api);
189 return StatusCode::SUCCESS;
201 return StatusCode::SUCCESS;
214 ATH_MSG_DEBUG(
"Converting ThePEG::Event to HepMC::GenEvent");
215 if (!evt->run_info()) evt->set_run_info(
m_runinfo);
216 evt->set_units(HepMC3::Units::MEV, HepMC3::Units::MM);
222 evt->set_event_number(evtInfo->eventNumber());
225 const EventContext& ctx = Gaudi::Hive::currentContext();
227 std::vector<long> seeds(s, s+2);
228 ATH_MSG_DEBUG(
"Random seeds: " << seeds[0] <<
", " << seeds[1]);
232 if (evt->weights().empty()) {
233 evt->weights().push_back(
m_event->weight());
239 ThePEG::tSubProPtr sub =
m_event->primarySubProcess();
240 int id1 = sub->incoming().first ->id();
241 int id2 = sub->incoming().second->id();
243 ThePEG::tcEHPtr eh = ThePEG::dynamic_ptr_cast<ThePEG::tcEHPtr>(
m_event->handler());
245 double x1 = eh->lastX1();
246 double x2 = eh->lastX2();
248 std::pair<ThePEG::PDF,ThePEG::PDF> pdfs;
249 pdfs.first = eh->pdf<ThePEG::PDF>(sub->incoming().first);
250 pdfs.second = eh->pdf<ThePEG::PDF>(sub->incoming().second);
252 ThePEG::Energy2 scale = eh->lastScale();
253 double Q = std::sqrt(scale/ThePEG::GeV2);
255 double pdf1 = pdfs.first.xfx(sub->incoming().first ->dataPtr(), scale, x1);
256 double pdf2 = pdfs.first.xfx(sub->incoming().second->dataPtr(), scale, x2);
258 HepMC3::GenPdfInfoPtr pdfi = std::make_shared<HepMC3::GenPdfInfo>();
259 pdfi->set(id1, id2, x1, x2, Q, pdf1, pdf2);
260 evt->set_pdf_info(std::move(pdfi));
267 return StatusCode::SUCCESS;
278 ATH_MSG_INFO(
"MetaData: generator = Herwig7 " << HWVERSION );
279 ATH_MSG_INFO( std::scientific << std::setprecision(5) <<
"MetaData: cross-section (nb) = " <<
m_gen->eventHandler()->integratedXSec()*
m_xsscale/ThePEG::nanobarn);
283 ThePEG::Repository::cleanup();
286 if (
m_cleanup_herwig_scratch && (std::filesystem::is_directory(
"Herwig-scratch") || std::filesystem::is_directory(
"Herwig-cache"))){
288 ATH_MSG_INFO(
"removing Herwig-scratch/Herwig-cache folder from "+std::filesystem::current_path().
string());
291 std::this_thread::sleep_for(std::chrono::seconds(5));
295 (std::filesystem::remove_all(
"Herwig-scratch") || std::filesystem::remove_all(
"Herwig-cache"));
297 catch (
const std::exception& e) {
298 ATH_MSG_WARNING(
"Failed to delete the folder 'Herwig-scratch': "+std::string(e.what()));
303 return StatusCode::SUCCESS;
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
void convert_to_HepMC(const ThePEG::Event &m_event, HepMC::GenEvent &evt, bool nocopies, ThePEG::Energy eunit, ThePEG::Length lunit)
Athena interface for the Herwig7 generator.
size_t size() const
Number of registered mappings.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
GenModule(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
CLHEP::HepRandomEngine * getRandomEngineDuringInitialize(const std::string &streamName, unsigned long int randomSeedOffset, unsigned int conditionsRun=1, unsigned int lbn=1) const
IntegerProperty m_randomSeed
Seed for random number engine.
std::shared_ptr< HepMC3::GenRunInfo > m_runinfo
The run info for HepMC3.
std::string m_pdfname_mpi
PS PDF name, stored for AMI capture at finalize.
StatusCode callGenerator()
Run the generator for one event.
SG::ReadHandleKey< xAOD::EventInfo > m_evtInfoKey
StatusCode genFinalize()
Close down the generator.
ThePEG::EventPtr m_event
ThePEG event object.
int m_seed_from_generatetf
Random number seed from Generate_tf.py.
StatusCode writeRunFileFromText(const std::string &share_path)
Write the CA input text into a real Herwig runfile.
std::string m_pdfname_me
ME PDF name, stored for AMI capture at finalize.
bool m_cleanup_herwig_scratch
Possibly remove Herwig-scratch folder after finishing the event generation.
Herwig7(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
double m_xsscale
Scale integrated cross section by a factor for MetaData output.
std::string m_runSettings
In-memory run settings provided by CA fragments.
StatusCode fillEvt(HepMC::GenEvent *evt)
Convert the generated event into the HepMC format.
int m_dsid
Gen_tf.py run args needed in interface.
ThePEG::EGPtr m_gen
ThePEG generator object.
std::string m_runfile
Name of run file.
StatusCode genInitialize()
Initialize the generator.
Herwig7API m_api
Herwig7 API object.
std::string m_setupfile
Name of setup file.
bool m_use_seed_from_generatetf
Ignore random number seed provided by athena and use the one from Generate_tf.py instead.
static std::string find_file_from_list(const std::string &logical_file_name, const std::string &search_list)
void set_random_states(GenEvent *e, std::vector< long int > &a)
HepMC3::GenEvent GenEvent