15#include <Pythia8/Pythia.h>
17#include <SHiP/Units.hpp>
28using PythiaTime = mp_units::quantity<ship::units::mm_per_c, double>;
33inline int pythia_seed(std::uint32_t base,
int extra_streams = 0) {
34 if (extra_streams < 0 || extra_streams >= 900000000)
35 throw std::invalid_argument(
"pythia_seed: extra_streams " +
36 std::to_string(extra_streams) +
37 " must be in [0, 900000000)");
38 auto const range =
static_cast<std::uint32_t
>(900000000 - extra_streams);
39 return static_cast<int>(base % range) + 1;
44template <
typename Pythia>
46 ship::Energy beam_energy) {
47 pythia.readString(
"Beams:idA = " + std::to_string(idA));
48 pythia.readString(
"Beams:idB = " + std::to_string(idB));
49 pythia.readString(
"Beams:frameType = 2");
52 std::to_string(beam_energy.numerical_value_in(ship::units::GeV)));
53 pythia.readString(
"Beams:eB = 0.");
59template <
typename Pythia>
61 double const threshold =
62 tau0_threshold.numerical_value_in(ship::units::mm_per_c);
63 for (
auto it = pythia.particleData.begin(); it != pythia.particleData.end();
65 auto& entry = it->second;
66 if (entry && entry->tau0() > threshold) entry->setMayDecay(
false);
75template <
typename Pythia>
76void next_event(Pythia& pythia, std::string_view source_name,
77 int max_attempts = 10) {
78 for (
int attempt = 0; attempt < max_attempts; ++attempt)
79 if (pythia.next())
return;
80 throw std::runtime_error(std::string(source_name) +
81 ": Pythia8 event generation failed " +
82 std::to_string(max_attempts) +
" times in a row");
94template <
typename MCParticle>
96 Pythia8::Event
const& event, ship::Length z_offset = ship::Length::zero()) {
97 namespace su = ship::units;
98 std::vector<MCParticle> particles;
99 particles.reserve(event.size());
100 double const z_offset_mm = z_offset.numerical_value_in(su::mm);
103 std::vector<int> out_index(
static_cast<std::size_t
>(event.size()), -1);
105 for (
int i = 0; i <
event.size(); ++i) {
106 auto const& p =
event[i];
107 if (!p.isFinal())
continue;
109 out_index[
static_cast<std::size_t
>(i)] =
static_cast<int>(particles.size());
114 mc.vertex = {p.xProd(), p.yProd(), p.zProd() + z_offset_mm};
115 mc.momentum = {p.px(), p.py(), p.pz()};
118 mc.time = (p.tProd() * su::mm_per_c).numerical_value_in(su::ns);
119 mc.motherId = p.mother1();
120 mc.status = p.statusHepMC();
121 particles.push_back(mc);
124 for (
auto& mc : particles) {
126 mc.motherId = (m >= 0 && m < static_cast<int>(out_index.size()))
127 ? out_index[
static_cast<std::size_t
>(m)]
Definition math_utils.hpp:12
void configure_beams(Pythia &pythia, int idA, int idB, ship::Energy beam_energy)
Definition pythia_common.hpp:45
std::vector< MCParticle > extract_particles(Pythia8::Event const &event, ship::Length z_offset=ship::Length::zero())
Definition pythia_common.hpp:95
mp_units::quantity< ship::units::mm_per_c, double > PythiaTime
Definition pythia_common.hpp:28
void next_event(Pythia &pythia, std::string_view source_name, int max_attempts=10)
Definition pythia_common.hpp:76
int pythia_seed(std::uint32_t base, int extra_streams=0)
Definition pythia_common.hpp:33
void stabilise_long_lived(Pythia &pythia, PythiaTime tau0_threshold)
Definition pythia_common.hpp:60