cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
PPtoFF.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2018-2024 Laurent Forthomme
4 * 2017-2019 Wolfgang Schaefer
5 * 2019 Marta Luszczak
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
22#include "CepGen/Event/Event.h"
24#include "CepGen/Physics/PDG.h"
27#include "CepGen/Utils/Math.h"
28
29using namespace cepgen;
30
31auto make_pdgids_pair = [](pdgid_t pair) { return spdgids_t{(spdgid_t)pair, -(spdgid_t)pair}; };
32
35public:
36 explicit PPtoFF(const ParametersList& params)
37 : cepgen::proc::FactorisedProcess(params, make_pdgids_pair(params.get<ParticleProperties>("pair").pdgid)),
38 method_(steerAs<int, Mode>("method")),
39 osp_(steer<ParametersList>("offShellParameters")) {
40 if (method_ == Mode::offShell && !psgen_->ktFactorised())
41 throw CG_FATAL("PPtoFF:prepare")
42 << "Off-shell matrix element only defined for factorised process with partons kt.";
43 }
44
45 proc::ProcessPtr clone() const override { return proc::ProcessPtr(new PPtoFF(*this)); }
46
48 auto desc = FactorisedProcess::description();
49 desc.setDescription("γγ → f⁺f¯");
50 desc.addAs<int, pdgid_t>("pair", PDG::muon).setDescription("type of central particles emitted");
51 desc.addAs<int, Mode>("method", Mode::offShell)
52 .setDescription("Matrix element computation method")
53 .allow(0, "on-shell")
54 .allow(1, "off-shell");
55 desc.add("offShellParameters", OffShellParameters::description());
56 return desc;
57 }
58
59private:
60 void prepareFactorisedPhaseSpace() override {
61 const auto cs_prop = PDG::get()(psgen_->central().at(0));
62 // define central particle properties and couplings with partons
63 if (!cs_prop.fermion || cs_prop.charges.empty())
64 throw CG_FATAL("PPtoFF:prepare") << "Invalid fermion pair selected: " << cs_prop << ".";
65 mf2_ = cs_prop.mass * cs_prop.mass;
66 qf2_ = std::pow(cs_prop.integerCharge() * (1. / 3), 2);
67 const auto generate_coupling = [this, &cs_prop](const pdgid_t& parton_id) -> std::function<double(double)> {
68 switch (parton_id) {
69 case PDG::gluon: {
70 if (cs_prop.colours == 0)
71 throw CG_FATAL("PPtoFF:prepare") << "Invalid fermion type for gluon coupling. Should be a quark.";
72 return [this](double q) { return kFourPi * 0.5 * alphaS(q); };
73 }
74 case PDG::photon:
75 return [this](double q) { return kFourPi * qf2_ * alphaEM(q); };
76 default:
77 throw CG_FATAL("PPtoFF:prepare") << "Unsupported parton id: '" << parton_id << "'.";
78 }
79 };
80 g_part1_ = generate_coupling(event().oneWithRole(Particle::Parton1).pdgId());
81 g_part2_ = generate_coupling(event().oneWithRole(Particle::Parton2).pdgId());
82
83 CG_DEBUG("PPtoFF:prepare") << "Incoming beams: mA = " << mA() << " GeV/mB = " << mB() << " GeV.\n\t"
84 << "Produced particles: " << psgen_->central() << ".\n\t"
85 << "ME computation method: " << (int)method_ << ".";
86
87 // constrain central particles cuts
89 kinematics().cuts().central.pt_diff = {0., 50.};
90 }
91 double computeFactorisedMatrixElement() override {
92 switch (method_) {
93 case Mode::onShell:
94 return onShellME();
95 case Mode::offShell:
96 return offShellME();
97 default:
98 throw CG_FATAL("PPtoFF") << "Invalid ME calculation method (" << (int)method_ << ")!";
99 }
100 }
101 double onShellME() const;
102 double offShellME() const;
103
104 const enum class Mode { onShell = 0, offShell = 1 } method_;
105
107 struct OffShellParameters : SteeredObject<OffShellParameters> {
108 explicit OffShellParameters(const ParametersList& params) : SteeredObject(params) {
109 (*this)
110 .add("mat1", mat1)
111 .add("mat2", mat2)
112 .add("termLL", term_ll)
113 .add("termLT", term_lt)
114 .add("termTT", term_tt1)
115 .add("termtt", term_tt2);
116 }
117
118 static ParametersDescription description() {
119 auto desc = ParametersDescription();
120 desc.add("mat1", 1).setDescription("symmetry factor for the first incoming photon");
121 desc.add("mat2", 1).setDescription("symmetry factor for the second incoming photon");
122 desc.add("termLL", 1).setDescription("fully longitudinal relative weight");
123 desc.add("termLT", 1).setDescription("cross-polarisation relative weight");
124 desc.add("termTT", 1).setDescription("fully transverse relative weight");
125 desc.add("termtt", 1).setDescription("fully transverse relative weight");
126 return desc;
127 }
128
129 int mat1{0}, mat2{0};
130 int term_ll{0}, term_lt{0}, term_tt1{0}, term_tt2{0};
131 } osp_;
132
133 static constexpr double kFourPi = 4. * M_PI;
134 double mf2_{0.}, qf2_{0.};
135 std::function<double(double)> g_part1_{nullptr}, g_part2_{nullptr};
136};
137
138double PPtoFF::onShellME() const {
139 const double s_hat = shat(), t_hat = that(), u_hat = uhat(); // buffer Mandelstam variables
140 CG_DEBUG_LOOP("PPtoFF:onShell") << "that: " << t_hat << ", uhat: " << u_hat << ".";
141
142 if (t_hat == mf2_ || u_hat == mf2_)
143 return 0.;
144 const auto q = std::sqrt(t_hat);
145 const auto prefac = g_part1_(q) * g_part2_(q);
146 if (!utils::positive(prefac))
147 return 0.;
148
149 const auto mf4 = mf2_ * mf2_, mf8 = mf4 * mf4;
150 const auto out = 6. * mf8 + (-3. * mf4 * t_hat * t_hat) + (-14. * mf4 * t_hat * u_hat) + (-3. * mf4 * u_hat * u_hat) +
151 (1. * mf2_ * t_hat * t_hat * t_hat) + (7. * mf2_ * t_hat * t_hat * u_hat) +
152 (7. * mf2_ * t_hat * u_hat * u_hat) + (1. * mf2_ * u_hat * u_hat * u_hat) +
153 (-1. * t_hat * t_hat * t_hat * u_hat) + (-1. * t_hat * u_hat * u_hat * u_hat);
154 return -2. * prefac * out * std::pow((mf2_ - t_hat) * (mf2_ - u_hat) * s_hat, -2);
155}
156
157double PPtoFF::offShellME() const {
158 if (q1().pt2() == 0. || q2().pt2() == 0) // only works for kt-factorised case
159 return 0.;
160 const auto mt1 = pc(0).massT(), mt2 = pc(1).massT(); // transverse masses
161 const auto compute_zs = [this, &mt1, &mt2](short pol, double x) -> std::pair<double, double> {
162 const auto norm_pol = pol / std::abs(pol);
163 const auto fact = inverseSqrtS() / x;
164 return std::make_pair(fact * mt1 * std::exp(norm_pol * pc(0).rapidity()),
165 fact * mt2 * std::exp(norm_pol * pc(1).rapidity()));
166 };
167 const auto compute_mat_element =
168 [this](double zp, double zm, double q2, const Momentum& vec_pho, const Momentum& vec_qt) -> double {
169 const auto vec_kt = Momentum(zm * pc(0) - zp * pc(1)).transverse();
170 const auto phi_p = vec_kt + zp * vec_qt, phi_m = vec_kt - zm * vec_qt;
171 const auto zpm = zp * zm, eps2 = mf2_ + zpm * q2;
172
173 const auto kp = 1. / (phi_p.pt2() + eps2), km = 1. / (phi_m.pt2() + eps2);
174 const auto phi = Momentum(kp * phi_p - km * phi_m).setEnergy(kp - km);
175 const auto dot = phi.threeProduct(vec_pho), cross = phi.crossProduct(vec_pho);
176
177 const auto phi_0 = phi.energy(), phi2_0 = phi_0 * phi_0, phi_t = phi.p(), phi2_t = phi_t * phi_t;
178
179 return 2. * zpm / vec_qt.pt2() *
180 ((osp_.term_ll * 4. * zpm * zpm * q2 * phi2_0) +
181 (osp_.term_tt1 * (zp * zp + zm * zm) * phi2_t + mf2_ * phi2_0) +
182 (osp_.term_tt2 * (cross * cross - dot * dot) / vec_pho.pt2()) -
183 (osp_.term_lt * 4. * zpm * (zp - zm) * phi_0 * dot));
184 };
185 //--- t-channel
186 const auto q2_1 = utils::kt::q2(x1(), q1().pt2(), mA2(), mX2());
187 const auto [zp_1, zm_1] = compute_zs(+1, x1());
188 const auto amat2_1 = compute_mat_element(zp_1, zm_1, q2_1, q1(), q2().transverse());
189
190 //--- u-channel
191 const auto q2_2 = utils::kt::q2(x2(), q2().pt2(), mB2(), mY2());
192 const auto [zp_2, zm_2] = compute_zs(-1, x2());
193 const auto amat2_2 = compute_mat_element(zp_2, zm_2, q2_2, q2(), q1().transverse());
194
195 //--- symmetrisation
196 const auto amat2 = 0.5 * (osp_.mat1 * amat2_1 + osp_.mat2 * amat2_2);
197 if (!utils::positive(amat2))
198 return 0.;
199
200 const auto t_limits = Limits{0., std::pow(std::max(mt1, mt2), 2)};
201 const auto prefac = g_part1_(std::sqrt(t_limits.trim(q2_1))) * g_part2_(std::sqrt(t_limits.trim(q2_2)));
202 if (!utils::positive(prefac))
203 return 0.;
204 return prefac * amat2;
205}
206// register process
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_DEBUG_LOOP(mod)
Definition Message.h:224
#define CG_DEBUG(mod)
Definition Message.h:220
auto make_pdgids_pair
Definition PPtoFF.cpp:31
#define REGISTER_PROCESS(name, obj)
Add a generic process definition to the list of handled processes.
Compute the 2-to-4 matrix element for a CE process.
Definition PPtoFF.cpp:34
proc::ProcessPtr clone() const override
Copy all process attributes into a new object.
Definition PPtoFF.cpp:45
static ParametersDescription description()
Definition PPtoFF.cpp:47
PPtoFF(const ParametersList &params)
Definition PPtoFF.cpp:36
CutsList & cuts()
Phase space cuts.
Definition Kinematics.h:41
Validity interval for a variable.
Definition Limits.h:28
bool valid() const
Is there a lower and upper limit?
Definition Limits.cpp:85
Container for a particle's 4-momentum, along with useful methods to ease the development of any matri...
Definition Momentum.h:33
double threeProduct(const Momentum &) const
Scalar product of the 3-momentum with another 3-momentum.
Definition Momentum.cpp:138
Momentum & setEnergy(double)
Set the energy (in GeV)
Definition Momentum.cpp:171
double massT() const
Transverse mass (in GeV)
Definition Momentum.cpp:226
Momentum transverse() const
Transverse coordinates of a momentum.
Definition Momentum.cpp:236
A description object for parameters collection.
@ Parton2
beam incoming parton
Definition Particle.h:59
@ Parton1
beam incoming parton
Definition Particle.h:58
U steerAs(const std::string &key) const
Retrieve a recasted parameters as previously steered.
Definition Steerable.h:44
T steer(const std::string &key) const
Retrieve a parameters as previously steered.
Definition Steerable.h:39
Base user-steerable object.
Generic parton emission-factorised process.
FactorisedProcess(const ParametersList &params, const spdgids_t &output)
Class constructor.
const std::unique_ptr< PhaseSpaceGenerator > psgen_
Kinematic variables generator for the phase space coverage.
double mB2() const
Negative-z incoming beam particle's squared mass.
Definition Process.h:71
const Kinematics & kinematics() const
Constant reference to the process kinematics.
Definition Process.h:50
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
double inverseSqrtS() const
Inverse two-beam centre of mass energy.
Definition Process.h:109
double x1() const
Positive-z incoming parton's fractional momentum.
Definition Process.h:80
double shat() const
Definition Process.cpp:127
double mA() const
Positive-z incoming beam particle's mass.
Definition Process.h:69
double mA2() const
Positive-z incoming beam particle's squared mass.
Definition Process.h:68
double mY2() const
Negative-z outgoing beam particle's squared mass.
Definition Process.h:77
double alphaEM(double q) const
Compute the electromagnetic running coupling algorithm at a given scale.
Definition Process.cpp:346
double mB() const
Negative-z incoming beam particle's mass.
Definition Process.h:72
Momentum & pc(size_t)
Central particle's 4-momentum.
Definition Process.cpp:113
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
double alphaS(double q) const
Compute the strong coupling algorithm at a given scale.
Definition Process.cpp:353
const Momentum & q1() const
Positive-z incoming parton's 4-momentum.
Definition Process.cpp:107
std::unique_ptr< Process > ProcessPtr
Helper typedef for a Process unique pointer.
Definition Process.h:199
double q2(double x, double kt2, double mi2, double mx2)
Compute the virtuality from longitudinal loss/transverse virtuality/diffractive mass.
Definition Utils.cpp:60
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< spdgid_t > spdgids_t
unsigned long long pdgid_t
Alias for the integer-like particle PDG id.
long long spdgid_t
cuts::Central central
Cuts on the central system produced.
Definition Cuts.h:95
A collection of physics constants associated to a single particle.
Limits pt_diff
transverse momentum balance between the central particles
Definition Cuts.h:47