cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
PhaseSpaceGenerator2to4.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2019-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 <memory>
20
22#include "CepGen/Event/Event.h"
24#include "CepGen/Physics/Cuts.h"
25#include "CepGen/Physics/PDG.h"
31#include "CepGen/Utils/Math.h"
33
34namespace cepgen {
36 template <typename T>
38 public:
40 : PhaseSpaceGenerator(params),
41 part_psgen_(new T(params)),
42 particles_(steer<std::vector<int> >("ids")),
43 randomise_charge_(steer<bool>("randomiseCharge")) {}
44
47 desc.setDescription("2-to-4 phase space mapper (" + T::description().description() + "/" +
48 T::description().description() + ")");
49 desc.add<std::vector<int> >("ids", {}).setDescription("list of particles produced");
50 desc.add<bool>("randomiseCharge", true)
51 .setDescription("randomise the charges of the central system (if charged)?");
52 desc += T::description();
53 return desc;
54 }
55
56 bool ktFactorised() const override {
57 CG_ASSERT(part_psgen_);
58 return part_psgen_->ktFactorised();
59 }
60
61 void setCentralCuts(const cuts::Central& single) override { single_limits_ = single; }
62
63 void initialise(proc::FactorisedProcess* process) override {
64 proc_ = process;
65 CG_ASSERT(part_psgen_);
66 part_psgen_->initialise(process);
67 const auto& kin_cuts = proc_->kinematics().cuts().central;
68 const auto lim_rap = kin_cuts.rapidity_single.truncate(Limits{-6., 6.});
69 (*proc_)
70 .defineVariable(m_y_c1_, proc::Process::Mapping::linear, lim_rap, "y1", "First outgoing particle rapidity")
71 .defineVariable(m_y_c2_, proc::Process::Mapping::linear, lim_rap, "y2", "Second outgoing particle rapidity")
72 .defineVariable(m_pt_diff_,
74 kin_cuts.pt_diff.truncate(Limits{0., 500.}),
75 "pt_diff",
76 "Final state particles transverse momentum difference")
77 .defineVariable(m_phi_pt_diff_,
79 kin_cuts.phi_diff.truncate(Limits{0., 2. * M_PI}),
80 "phi_pt_diff",
81 "Final state particles azimuthal angle difference");
82 }
83
84 bool generate() override {
85 CG_ASSERT(part_psgen_);
86 if (!part_psgen_->generatePartonKinematics())
87 return false;
88 central_weight_ = generateCentralKinematics();
89 return utils::positive(central_weight_);
90 }
91
92 double weight() const override {
93 const auto fluxes_weight = part_psgen_->fluxes();
94 if (!utils::positive(fluxes_weight))
95 return 0.;
96 return fluxes_weight * central_weight_;
97 }
98
99 pdgids_t partons() const override {
100 CG_ASSERT(part_psgen_);
101 return pdgids_t{part_psgen_->positiveFlux().partonPdgId(), part_psgen_->negativeFlux().partonPdgId()};
102 }
103
104 std::vector<int> central() const override { return particles_; }
105
106 void setCentral(const std::vector<int>& cent) override { particles_ = cent; }
107
108 double that() const override {
109 return 0.5 * ((proc_->q1() - proc_->pc(0)).mass2() + (proc_->q2() - proc_->pc(1)).mass2());
110 }
111
112 double uhat() const override {
113 return 0.5 * ((proc_->q1() - proc_->pc(1)).mass2() + (proc_->q2() - proc_->pc(0)).mass2());
114 }
115
116 private:
117 double generateCentralKinematics() {
118 const auto& kin = proc_->kinematics();
119 if (!kin.cuts().central.rapidity_diff.contains(std::fabs(m_y_c1_ - m_y_c2_))) // rapidity distance
120 return 0.;
121 {
122 const auto qt_sum = (proc_->q1() + proc_->q2()).transverse(); // two-parton system
123 const auto pt_diff = Momentum::fromPtEtaPhiE(m_pt_diff_, 0., m_phi_pt_diff_);
124 const auto pt_c1 = 0.5 * (qt_sum + pt_diff), pt_c2 = 0.5 * (qt_sum - pt_diff);
125 const auto p1t = pt_c1.pt(), p2t = pt_c2.pt();
126 // apply user cuts on central system
127 if (!kin.cuts().central.pt_single.contains(p1t) || !single_limits_.pt_single.contains(p1t))
128 return 0.;
129 if (!kin.cuts().central.pt_single.contains(p2t) || !single_limits_.pt_single.contains(p2t))
130 return 0.;
131 if (!kin.cuts().central.pt_diff.contains(std::fabs(p1t - p2t))) // transverse momentum difference
132 return 0.;
133 //--- four-momenta of the outgoing central particles
134 if (particles_.size() != 2)
135 throw CG_FATAL("PhaseSpaceGenerator2to4:generateCentralKinematics")
136 << "Invalid central particles multiplicity. Expecting 2, got " << particles_.size() << ".";
137 proc_->pc(0) = Momentum::fromPtYPhiM(p1t, m_y_c1_, pt_c1.phi(), PDG::get().mass(particles_.at(0)));
138 proc_->pc(1) = Momentum::fromPtYPhiM(p2t, m_y_c2_, pt_c2.phi(), PDG::get().mass(particles_.at(1)));
139 }
140
141 //--- window in central system invariant mass
142 const auto invm = (proc_->pc(0) + proc_->pc(1)).mass();
143 if (!kin.cuts().central.mass_sum.contains(invm))
144 return 0.;
145
146 //--- compute and sanitise the momentum losses
147 const auto amt1 = proc_->pc(0).massT() / proc_->sqrtS(), amt2 = proc_->pc(1).massT() / proc_->sqrtS();
148 static const auto x_lim = Limits{0., 1.};
149 const auto x1 = amt1 * exp(+m_y_c1_) + amt2 * exp(+m_y_c2_);
150 if (!x_lim.contains(x1))
151 return 0.;
152 const auto x2 = amt1 * exp(-m_y_c1_) + amt2 * exp(-m_y_c2_);
153 if (!x_lim.contains(x2))
154 return 0.;
155
156 //--- additional conditions for energy-momentum conservation
157 const auto s = proc_->s(), mx2 = proc_->mX2(), my2 = proc_->mY2();
158 if (!kin.incomingBeams().positive().elastic() && x2 * s - invm - proc_->q2().p2() <= mx2)
159 return 0.;
160 if (!kin.incomingBeams().negative().elastic() && x1 * s - invm - proc_->q1().p2() <= my2)
161 return 0.;
162
163 //--- four-momenta of the outgoing protons (or remnants)
164
165 const auto px_p = (1. - x1) * proc_->pA().p() * M_SQRT2, px_m = (mx2 + proc_->q1().p2()) * 0.5 / px_p;
166 const auto py_m = (1. - x2) * proc_->pB().p() * M_SQRT2, py_p = (my2 + proc_->q2().p2()) * 0.5 / py_m;
167 CG_DEBUG_LOOP("2to4:pxy") << "px+ = " << px_p << " / px- = " << px_m << "\n\t"
168 << "py+ = " << py_p << " / py- = " << py_m << ".";
169
170 const auto px = -Momentum(proc_->q1()).setPz((px_p - px_m) * M_SQRT1_2).setEnergy((px_p + px_m) * M_SQRT1_2),
171 py = -Momentum(proc_->q2()).setPz((py_p - py_m) * M_SQRT1_2).setEnergy((py_p + py_m) * M_SQRT1_2);
172
173 CG_DEBUG_LOOP("2to4:remnants") << "First remnant: " << px << ", mass = " << px.mass() << "\n\t"
174 << "Second remnant: " << py << ", mass = " << py.mass() << ".";
175
176 if (std::fabs(px.mass2() - mx2) > NUM_LIMITS) {
177 CG_WARNING("2to4:px") << "Invalid X system squared mass: " << px.mass2() << "/" << mx2 << ".";
178 return 0.;
179 }
180 if (std::fabs(py.mass2() - my2) > NUM_LIMITS) {
181 CG_WARNING("2to4:py") << "Invalid Y system squared mass: " << py.mass2() << "/" << my2 << ".";
182 return 0.;
183 }
184
185 //--- four-momenta of the intermediate partons
186 const double norm = 1. / proc_->wCM() / proc_->wCM() / s, prefac = 0.5 / std::sqrt(norm);
187 { // positive-z incoming parton collinear kinematics
188 const double tau1 = norm * proc_->q1().p2() / x1;
189 proc_->q1().setPz(+prefac * (x1 - tau1)).setEnergy(+prefac * (x1 + tau1));
190 }
191 { // negative-z incoming parton collinear kinematics
192 const double tau2 = norm * proc_->q2().p2() / x2;
193 proc_->q2().setPz(-prefac * (x2 - tau2)).setEnergy(+prefac * (x2 + tau2));
194 }
195
196 CG_DEBUG_LOOP("2to4:partons") << "Squared c.m. energy = " << s << " GeV^2\n\t"
197 << "First parton: " << proc_->q1() << ", mass2 = " << proc_->q1().mass2()
198 << ", x1 = " << x1 << ", p = " << proc_->q1().p() << "\n\t"
199 << "Second parton: " << proc_->q2() << ", mass2 = " << proc_->q2().mass2()
200 << ", x2 = " << x2 << ", p = " << proc_->q2().p() << ".";
201
202 if (randomise_charge_) { // randomise the charge of outgoing system
203 const auto sign = proc_->randomGenerator().uniformInt(0, 1) == 1;
204 proc_->event()[Particle::CentralSystem][0].get().setAntiparticle(sign);
205 proc_->event()[Particle::CentralSystem][1].get().setAntiparticle(!sign);
206 }
207 proc_->event()[Particle::CentralSystem][0].get().setStatus(Particle::Status::FinalState);
208 proc_->event()[Particle::CentralSystem][1].get().setStatus(Particle::Status::FinalState);
209 proc_->x1() = x1;
210 proc_->x2() = x2;
211 proc_->pX() = px;
212 proc_->pY() = py;
213 return prefactor_ * m_pt_diff_;
214 }
215
216 // factor 1/4 from jacobian of transformations
217 static constexpr double prefactor_ = 0.25 * 0.0625 * M_1_PI * M_1_PI;
218 static constexpr double NUM_LIMITS = 1.e-3;
219
220 const std::unique_ptr<PartonsPhaseSpaceGenerator> part_psgen_;
221 std::vector<int> particles_;
222 const bool randomise_charge_;
223
224 proc::FactorisedProcess* proc_{nullptr}; //NOT owning
225
226 cuts::Central single_limits_;
227 // mapped variables
228 double m_y_c1_{0.};
229 double m_y_c2_{0.};
230 double m_pt_diff_{0.};
231 double m_phi_pt_diff_{0.};
232
233 double central_weight_{0.};
234 };
235} // namespace cepgen
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_ASSERT(assertion)
Definition Exception.h:62
#define CG_WARNING(mod)
Definition Message.h:228
#define CG_DEBUG_LOOP(mod)
Definition Message.h:224
#define REGISTER_PSGEN(name, obj)
Add a central phase space generator to the list of handled modules.
CutsList & cuts()
Phase space cuts.
Definition Kinematics.h:41
Validity interval for a variable.
Definition Limits.h:28
Limits truncate(const Limits &) const
Truncate limits to minimal/maximal values.
Definition Limits.cpp:130
bool contains(double val, bool exclude_boundaries=false) const
Check if value is inside limits' boundaries.
Definition Limits.cpp:77
double p2() const
Squared 3-momentum norm (in GeV )
Definition Momentum.h:132
Momentum & setEnergy(double)
Set the energy (in GeV)
Definition Momentum.cpp:171
double massT() const
Transverse mass (in GeV)
Definition Momentum.cpp:226
Momentum & setPz(double pz)
Set the longitudinal momentum (in GeV)
Definition Momentum.cpp:166
double p() const
3-momentum norm (in GeV)
Definition Momentum.h:130
static Momentum fromPtYPhiM(double pt, double rap, double phi, double m)
Build a 4-momentum from its transverse momentum, azimuthal angle, rapidity and mass.
Definition Momentum.cpp:93
static Momentum fromPtEtaPhiE(double pt, double eta, double phi, double e=-1.)
Build a 3-momentum from its three pseudo-cylindrical coordinates.
Definition Momentum.cpp:69
double mass2() const
Squared mass (in GeV ) as computed from its energy and momentum.
Definition Momentum.cpp:220
double mass(spdgid_t) const
Particle mass (in GeV)
Definition PDG.cpp:90
static PDG & get()
Retrieve a unique instance of this particles info collection.
Definition PDG.cpp:41
A description object for parameters collection.
@ FinalState
Stable, final state particle.
@ CentralSystem
Central particles system.
Definition Particle.h:56
A 2-to-4 (or 2-to-2 central) phase space generator.
void initialise(proc::FactorisedProcess *process) override
Set all process parameters.
double weight() const override
Return the event weight for a kinematics combination.
bool generate() override
Generate a kinematics combination, and return a success flag.
std::vector< int > central() const override
List of outgoing central particles in kinematics.
void setCentralCuts(const cuts::Central &single) override
Set cuts on central particles.
static ParametersDescription description()
pdgids_t partons() const override
List of incoming partons in kinematics.
void setCentral(const std::vector< int > &cent) override
Override the central particles list.
PhaseSpaceGenerator2to4(const ParametersList &params)
Class template to define any phase space helper process.
static ParametersDescription description()
Description of all object parameters.
Definition Steerable.cpp:42
T steer(const std::string &key) const
Retrieve a parameters as previously steered.
Definition Steerable.h:39
Generic parton emission-factorised process.
double wCM() const
Two-parton centre of mass energy.
Definition Process.h:90
const Kinematics & kinematics() const
Constant reference to the process kinematics.
Definition Process.h:50
const Momentum & pA() const
Positive-z incoming beam particle's 4-momentum.
Definition Process.cpp:91
const Momentum & pX() const
Positive-z outgoing beam particle's 4-momentum.
Definition Process.cpp:99
double x2() const
Negative-z incoming parton's fractional momentum.
Definition Process.h:83
const Momentum & q2() const
Negative-z incoming parton's 4-momentum.
Definition Process.cpp:111
utils::RandomGenerator & randomGenerator() const
Accessor for this process' random number generator.
Definition Process.cpp:340
double s() const
Two-beam squared centre of mass energy.
Definition Process.h:107
double x1() const
Positive-z incoming parton's fractional momentum.
Definition Process.h:80
double mY2() const
Negative-z outgoing beam particle's squared mass.
Definition Process.h:77
double sqrtS() const
Two-beam centre of mass energy.
Definition Process.h:108
const Momentum & pB() const
Negative-z incoming beam particle's 4-momentum.
Definition Process.cpp:95
Momentum & pc(size_t)
Central particle's 4-momentum.
Definition Process.cpp:113
const Momentum & pY() const
Negative-z outgoing beam particle's 4-momentum.
Definition Process.cpp:103
double mX2() const
Positive-z outgoing beam particle's squared mass.
Definition Process.h:74
const Event & event() const
Handled particles objects and their relationships.
Definition Process.cpp:267
const Momentum & q1() const
Positive-z incoming parton's 4-momentum.
Definition Process.cpp:107
virtual int uniformInt(int min, int max)=0
std::string s(const std::string &word, float num, bool show_number)
Add a trailing "s" when needed.
Definition String.cpp:228
bool positive(const T &val)
Check if a number is positive and finite.
Definition Math.cpp:26
Common namespace for this Monte Carlo generator.
std::vector< pdgid_t > pdgids_t
cuts::Central central
Cuts on the central system produced.
Definition Cuts.h:95
Centrally produced particles phase space cuts.
Definition Cuts.h:31
Limits rapidity_single
single particle rapidity
Definition Cuts.h:40
Limits pt_single
single particle transverse momentum
Definition Cuts.h:38