cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
EventInterface.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2013-2024 Laurent Forthomme
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <algorithm>
20
22#include "CepGen/Event/Event.h"
24#include "CepGen/Physics/PDG.h"
27#include "CepGen/Utils/String.h"
30
31namespace cepgen {
32 namespace pythia6 {
34 : evt_(event), rnd_(rnd) {
36 roles_.emplace_back(Particle::Role::OutgoingBeam1);
38 roles_.emplace_back(Particle::Role::OutgoingBeam2);
39 }
40
42 CG_DEBUG_LOOP("EventInterface:prepareHadronisation") << "Hadronisation preparation called.";
43
44 for (auto role : roles_) {
45 if (!evt_.hasRole(role))
46 continue;
47 const auto& part = evt_.oneWithRole(role);
48
49 const auto partons = pickPartonsContent();
50 checkPDGid(partons.first);
51 checkPDGid(partons.second);
52 const double mq = pymass(partons.first), mq2 = mq * mq;
53 const double mdq = pymass(partons.second), mdq2 = mdq * mdq;
54
55 // choose random direction in MX frame
56 const double phi = rnd_->uniform(0., 2. * M_PI), theta = acos(rnd_->uniform(-1., 1.));
57
58 // compute momentum of decay particles from MX
59 const double px2 = std::pow(utils::energyFromW(part.momentum().mass(), mdq2, mq2), 2) - mq2;
60 if (px2 < 0.) {
61 CG_WARNING("EventInterface:prepareHadronisation") << "Invalid remnants kinematics for " << role << ".";
62 continue;
63 }
64 const double px = std::sqrt(px2);
65
66 //--- build 4-vectors and boost decay particles
67 auto pdq = Momentum::fromPThetaPhiE(px, theta, phi, std::hypot(px, mdq));
68 auto pq = -pdq;
69 pq.setEnergy(std::hypot(px, mq));
70
71 const auto part_id = part.id();
72
73 // singlet
74 auto& quark = evt_.addParticle(role).get();
75 quark.addMother(evt_[part_id]);
76 quark.setPdgId(partons.first, +1);
77 quark.setStatus(Particle::Status::Unfragmented);
78 quark.setMomentum(pq.lorentzBoost(evt_[part_id].momentum()));
79
80 // quark doublet
81 auto& diquark = evt_.addParticle(role).get();
82 diquark.addMother(evt_[part_id]);
83 diquark.setPdgId(partons.second, +1);
84 diquark.setStatus(Particle::Status::Unfragmented);
85 diquark.setMomentum(pdq.lorentzBoost(evt_[part_id].momentum()));
86
87 evt_[part_id].setStatus(Particle::Status::Fragmented);
88 }
89 }
90
91 void EventInterface::fillEventBlock() {
92 pyjets_.n = 0; // reinitialise the event content
93 evt_strings_.clear(); // reinitialise the string fragmentation variables
94
95 for (const auto& role : evt_.roles()) { // loop on roles
96 string_t evt_string;
97 for (const auto& part : evt_(role)) {
98 const unsigned short i = part.id();
99 pyjets_.p[0][i] = part.momentum().px();
100 pyjets_.p[1][i] = part.momentum().py();
101 pyjets_.p[2][i] = part.momentum().pz();
102 pyjets_.p[3][i] = part.momentum().energy();
103 pyjets_.p[4][i] = part.momentum().mass();
104 try {
105 pyjets_.k[0][i] = pythia6Status((int)part.status());
106 } catch (const std::out_of_range&) {
107 evt_.dump();
108 throw CG_FATAL("EventInterface") << "Failed to retrieve a Pythia 6 particle status translation for "
109 << "CepGen status " << (int)part.status() << "!";
110 }
111 pyjets_.k[1][i] = part.integerPdgId();
112 const auto& moth = part.mothers();
113 pyjets_.k[2][i] = moth.empty() ? 0 // no mother
114 : *moth.begin() + 1; // mother
115 const auto& daug = part.daughters();
116 if (daug.empty()) // no daughters
117 pyjets_.k[3][i] = pyjets_.k[4][i] = 0;
118 else {
119 pyjets_.k[3][i] = *daug.begin() + 1; // daughter 1
120 pyjets_.k[4][i] = *daug.rbegin() + 1; // daughter 2
121 }
122 for (int j = 0; j < 5; ++j)
123 pyjets_.v[j][i] = 0.; // vertex position
124
125 if (part.status() == Particle::Status::Unfragmented) {
126 pyjets_.k[0][i] = 1; // PYTHIA/JETSET workaround
127 evt_string.emplace_back(part.id() + 1);
128 } else if (part.status() == Particle::Status::Undecayed)
129 pyjets_.k[0][i] = 2; // intermediate resonance
130 pyjets_.n++;
131 }
132 //--- at most one string per role
133 if (!evt_string.empty())
134 evt_strings_.emplace_back(evt_string);
135 }
136
137 //--- loop over the strings to bind everything together
138 for (const auto& evt_string : evt_strings_) {
139 if (evt_string.size() < 2)
140 continue;
141
142 CG_DEBUG_LOOP("EventInterface").log([&](auto& dbg) {
143 dbg << "Joining " << utils::s("particle", evt_string.size()) << " with " << evt_[evt_string[0]].role()
144 << " role"
145 << " in a same string";
146 for (const auto& part_id : evt_string) {
147 if (part_id != -1)
148 dbg << utils::format("\n\t * %2d (pdgId=%4d)", part_id, pyjets_.k[1][part_id - 1]);
149 }
150 });
151 pyjoin(evt_string);
152 }
153 }
154
156 fillEventBlock();
157 const auto old_npart = pyjets_.n;
158 pyexec();
159 //--- update the event
160 for (int p = old_npart; p < pyjets_.n; ++p) {
161 // filter the first particles already present in the event
162 const auto pdg_id = std::abs(pyjets_.k[1][p]);
163 checkPDGid(pdg_id);
164
165 const auto moth_id = pyjets_.k[2][p] - 1;
166 const auto role = pyjets_.k[2][p] != 0 ? evt_[moth_id].role() // child particle inherits its mother's role
168
169 auto& pa = evt_.addParticle(role).get();
170 pa.setId(p);
171 pa.setStatus(cepgenStatus(pyjets_.k[0][p]));
172 pa.setPdgId((long)pyjets_.k[1][p]);
173 pa.setMomentum(
174 Momentum(pyjets_.p[0][p], pyjets_.p[1][p], pyjets_.p[2][p], pyjets_.p[3][p]).setMass(pyjets_.p[4][p]));
175 // define particle parentage
176 auto& moth = evt_[moth_id];
177 if (role != Particle::Role::UnknownRole)
180 pa.addMother(moth);
181 }
182 }
183
184 std::pair<short, short> EventInterface::pickPartonsContent() {
185 const auto ranudq = rnd_->uniformInt(0, 9);
186 if (ranudq < 1)
187 return {PDG::down, 2203}; // (d,uu1)
188 if (ranudq < 5)
189 return {PDG::up, 2101}; // (u,ud0)
190 return {PDG::up, 2103}; // (u,ud1)
191 }
192 } // namespace pythia6
193} // namespace cepgen
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_WARNING(mod)
Definition Message.h:228
#define CG_DEBUG_LOOP(mod)
Definition Message.h:224
struct @7 pyjets_
Particles content of the event.
Container for the information on the in- and outgoing particles' kinematics.
Definition Event.h:28
Particle & oneWithRole(Particle::Role role)
First Particle object with a given role in the event.
Definition Event.cpp:190
ParticleRef addParticle(Particle &part, bool replace=false)
Set the information on one particle in the process.
Definition Event.cpp:323
bool hasRole(Particle::Role role) const
Check whether a particle role is represented in this event.
Definition Event.h:82
void dump() const
Dump all the known information on every Particle object contained in this Event container in the outp...
Definition Event.cpp:423
Container for a particle's 4-momentum, along with useful methods to ease the development of any matri...
Definition Momentum.h:33
Momentum & setMass(double)
Compute the energy from the mass.
Definition Momentum.cpp:176
static Momentum fromPThetaPhiE(double p, double theta, double phi, double e=-1.)
Build a 4-momentum from its scalar momentum, and its polar and azimuthal angles.
Definition Momentum.cpp:77
@ down
Definition PDG.h:35
@ Undecayed
Particle to be decayed externally.
@ Fragmented
Already fragmented outgoing beam.
@ Resonance
Already decayed intermediate resonance.
@ Unfragmented
Particle to be hadronised externally.
@ OutgoingBeam1
outgoing beam state/particle
Definition Particle.h:54
@ UnknownRole
Undefined role.
Definition Particle.h:51
@ OutgoingBeam2
outgoing beam state/particle
Definition Particle.h:55
@ CentralSystem
Central particles system.
Definition Particle.h:56
EventInterface(Event &, mode::Kinematics, utils::RandomGenerator *)
A random number generator.
virtual double uniform(double min=0., double max=1.)=0
virtual int uniformInt(int min, int max)=0
Kinematics
Type of scattering.
Definition Modes.h:28
@ InelasticElastic
proton-proton single-dissociative (or elastic-inelastic) case
@ InelasticInelastic
proton-proton double-dissociative case
@ ElasticInelastic
proton-proton single-dissociative (or inelastic-elastic) case
int cepgenStatus(int py_status)
double pymass(int pdgid)
void pyjoin(std::vector< int > join)
Connect entries with colour flow information.
void checkPDGid(int pdg_id)
int pythia6Status(int cg_status)
std::string format(const std::string &fmt, Args... args)
Format a string using a printf style format descriptor.
Definition String.h:61
std::string s(const std::string &word, float num, bool show_number)
Add a trailing "s" when needed.
Definition String.cpp:228
double energyFromW(double w, double mp2, double m2)
Compute energy from mass and emitted mass.
Definition Utils.cpp:47
Common namespace for this Monte Carlo generator.