Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8309521
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
29 KB
Subscribers
None
View Options
diff --git a/input_jets b/input_jets
index a3bdfda..1ca770d 100644
--- a/input_jets
+++ b/input_jets
@@ -1,58 +1,58 @@
# number of attempted resummation phase space points for each input event
trials: 10
min extparton pt: 30 # minimum transverse momentum of extremal partons
resummation jets: # resummation jet properties
min pt: 35 # minimum jet transverse momentum
algorithm: antikt # jet algorithm
R: 0.4 # jet R parameter
fixed order jets: # properties of input jets
min pt: 30
# by default, algorithm and R are like for resummation jets
# treatment of he various event classes
# the supported settings are: reweight, keep, discard
# non-FKL events cannot be reweighted
FKL: reweight
unordered: keep
non-FKL: keep
# scale settings similar to original HEJ
#
# Use combinations of max jet pperp, input scales, ht/2,
# and the jet invariant mass and vary all scales by factors
# of 1, sqrt(2), and 2. Discard combinations where mur and muf
# differ by a factor of more than two.
#
# The weight entries in the final events are ordered as follows:
# 0-18: max jet pperp
# 19-37: input scales
# 38-56: ht/2
# 57-75: jet invariant mass
# In each of these groups, the first entry corresponds to the basic
# scale choice. In the following entries, mur and muf are varied with
# the above factors. The entries are ordered lexicographically so that
# mur1 < mur2 or (mur1 == mur2 and muf1 < muf2).
#
# Note that in contrast to HEJ, the central choice for the event is always
# max jet pperp and cannot be configured (yet).
#
# scales: [max jet pperp, input, Ht/2, jet invariant mass]
# scale factors: [0.5, 0.7071, 1, 1.41421, 2]
# max scale ratio: 2.0001
scales: input
log correction: false # whether or not to include higher order logs
unweight: false # TODO: whether or not to unweight events
Les Houches output: RHEJ.lhe
#ROOT output: RHEJ.root
histograms: all # TODO: histograms in ROOT output
#histograms: [ydif, njets] # only save selected histograms
#wtwt cut # optional cut on (event weight)^2
-#RanLux init: ... # TODO: file for initialisation of random number engine
+#RanLux init: ranlux.0 # file for initialisation of random number engine
diff --git a/main.cc b/main.cc
index f636f66..2056104 100644
--- a/main.cc
+++ b/main.cc
@@ -1,151 +1,155 @@
/**
* Name: main.cc
* Authors: Tuomas Hapola, Andreas Maier <andreas.maier@durham.ac.uk>
*
*/
#include <fstream>
#include <algorithm>
#include <memory>
#include <chrono>
#include <iostream>
#include "yaml-cpp/yaml.h"
#include "LHEF.h"
#include "src/LesHouchesWriter.hh"
#include "src/Histograms.hpp"
#include "Common.h"
#include "src/EventReweighter.hh"
#include "src/config.hh"
#include "src/stream.hh"
#include "src/ROOTWriter.hh"
int event_number(std::string const & record){
size_t start = record.rfind("Number of Events");
start = record.find_first_of("123456789", start);
if(start == std::string::npos) {
throw std::invalid_argument("no event number record found");
}
const size_t end = record.find_first_not_of("0123456789", start);
return std::stoi(record.substr(start, end - start));
}
RHEJ::Config load_config(char const * filename){
try{
return RHEJ::load_config(filename);
}
catch(std::exception const & exc){
std::cerr << "Error: " << exc.what() << '\n';
std::exit(EXIT_FAILURE);
}
}
int main(int argn, char** argv) {
using clock = std::chrono::system_clock;
if (argn < 3) {
std::cerr << "\n# Usage:\n./HEJ config_file input_file\n\n";
return EXIT_FAILURE;
}
const auto start_time = clock::now();
// read configuration
const RHEJ::Config config = load_config(argv[1]);
RHEJ::istream in{argv[2]};
RHEJ::Histograms hist{
config.resummation_jets.def, config.resummation_jets.min_pt
};
LHEF::Reader reader{in};
//Les Houches output
std::unique_ptr<RHEJ::LesHouchesWriter> writer;
if(config.Les_Houches_output){
writer = RHEJ::make_unique<RHEJ::LesHouchesWriter>(
*config.Les_Houches_output, reader.heprup
);
}
//ROOT output
std::unique_ptr<RHEJ::ROOTWriter> root_writer;
if(config.ROOT_output){
constexpr double infinity = std::numeric_limits<double>::infinity();
root_writer = RHEJ::make_unique<RHEJ::ROOTWriter>(
*config.ROOT_output,
config.resummation_jets.def, config.resummation_jets.min_pt,
config.wtwt_cut?(*config.wtwt_cut):infinity
);
}
double global_reweight = 1.;
int max_events = std::numeric_limits<int>::max();
if(argn > 3){
max_events = std::stoi(argv[3]);
const int input_events = event_number(reader.headerBlock);
global_reweight = input_events/static_cast<double>(max_events);
std::cout << "processing " << max_events
<< " out of " << input_events << " events\n";
}
RHEJ::EventReweighter rhej{
reader.heprup,
config.resummation_jets.def, config.resummation_jets.min_pt,
config.fixed_order_jets.def, config.fixed_order_jets.min_pt,
config.treat,
config.min_extparton_pt,
config.log_correction
};
+ if(config.RanLux_init){
+ RHEJ::PhaseSpacePoint::reset_ranlux(*config.RanLux_init);
+ }
+
int nevent = 0;
std::array<int, RHEJ::event_class::last_class + 1>
nevent_class{0}, nfailed_class{0};
// Loop over the events in the inputfile
while(reader.readEvent()){
// reweight events so that the total cross section is conserved
reader.hepeup.setWeight(0, global_reweight * reader.hepeup.weight());
if(nevent == max_events) break;
nevent++;
if (nevent % 10000 == 0)
std::cout << "event number " << nevent << std::endl;
// calculate rHEJ weight
RHEJ::Event FO_event{reader.hepeup};
std::vector<RHEJ::Event> resummed_events;
resummed_events = rhej.reweight(FO_event, config.trials, config.scale_gen);
const auto ev_class = rhej.last_event_class();
++nevent_class[ev_class];
if(resummed_events.empty()) ++nfailed_class[ev_class];
for(auto const & ev: resummed_events){
assert(ev.outgoing.size() >= 2);
const double wt = ev.central.weight;
if(config.wtwt_cut && wt*wt > *config.wtwt_cut){
if(root_writer) root_writer->write(ev);
continue;
}
if(config.ROOT_output) hist.fill(ev);
if(config.Les_Houches_output) writer->write(ev);
}
} // main event loop
if(root_writer) root_writer->write(hist);
using namespace RHEJ::event_class;
std::cout<< "Events processed: " << nevent << '\n';
for(size_t ev_class = first_class; ev_class <= last_class; ++ev_class){
std::cout << '\t' << names[ev_class] << ": " << nevent_class[ev_class]
<< ", failed to reconstruct " << nfailed_class[ev_class]
<< '\n';
}
std::chrono::duration<double> run_time = (clock::now() - start_time);
std::cout << "\nTask Runtime: " << run_time.count() << " seconds.\n";
}
diff --git a/src/PhaseSpacePoint.cc b/src/PhaseSpacePoint.cc
index 21a783b..c9ffc2b 100644
--- a/src/PhaseSpacePoint.cc
+++ b/src/PhaseSpacePoint.cc
@@ -1,551 +1,560 @@
#include "PhaseSpacePoint.hpp"
#include <random>
#include "src/FindObservedJetMomenta.h"
#include "src/Jacobian.hpp"
#include "src/RNGWrapper.hpp"
#include "src/uno.hh"
#include "src/debug.hpp"
#include "src/kinematics.hh"
namespace RHEJ{
namespace{
//generate Ranlux64Engine with fixed, predefined state
/*
* some (all?) of the Ranlux64Engine constructors leave fields
* uninitialised, invoking undefined behaviour. This can be
* circumvented by restoring the state from a file
*/
CLHEP::Ranlux64Engine gen_Ranlux64Engine(){
static const std::string state =
"9876\n"
"0.91280703978419097666\n"
"0.41606065829518357191\n"
"0.99156342622341142601\n"
"0.030922955274050423213\n"
"0.16206278421638486975\n"
"0.76151768001958330956\n"
"0.43765760066092695979\n"
"0.42904698253748563275\n"
"0.11476317525663759511\n"
"0.026620053590963976831\n"
"0.65953715764414511114\n"
"0.30136722624439826745\n"
"3.5527136788005009294e-15 4\n"
"1 202\n";
const std::string file = std::tmpnam(nullptr);
{
std::ofstream out{file};
out << state;
}
CLHEP::Ranlux64Engine result;
result.restoreStatus(file.c_str());
return result;
}
}
CLHEP::Ranlux64Engine PhaseSpacePoint::ran_{gen_Ranlux64Engine()};
+
+ void PhaseSpacePoint::reset_ranlux(std::string const & init_file){
+ reset_ranlux(init_file.c_str());
+ }
+
+ void PhaseSpacePoint::reset_ranlux(char const * init_file){
+ ran_.restoreStatus(init_file);
+ }
+
namespace {
constexpr int max_jet_user_idx = PhaseSpacePoint::ng_max;
bool is_nonjet_parton(fastjet::PseudoJet const & parton){
assert(parton.user_index() != -1);
return parton.user_index() > max_jet_user_idx;
}
bool is_jet_parton(fastjet::PseudoJet const & parton){
assert(parton.user_index() != -1);
return parton.user_index() <= max_jet_user_idx;
}
// user indices for partons with extremal rapidity
constexpr int y_min_user_idx = -3;
constexpr int y_max_user_idx = -2;
}
namespace{
double estimate_ng_mean(std::vector<fastjet::PseudoJet> const & Born_jets){
const double delta_y =
Born_jets.back().rapidity() - Born_jets.front().rapidity();
assert(delta_y > 0);
// Formula derived from fit to 2 jet data
// for 3 jets: -0.0131111 + (1.39385 + 0.050085*delta_y)*delta_y
return -0.0213569 + (1.39765 + 0.0498387*delta_y)*delta_y;
}
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::cluster_jets(
std::vector<fastjet::PseudoJet> const & partons
) const{
fastjet::ClusterSequence cs(partons, jet_def_);
return cs.inclusive_jets(jetptmin_);
}
bool PhaseSpacePoint::pass_resummation_cuts(
std::vector<fastjet::PseudoJet> const & jets
) const{
return cluster_jets(jets).size() == jets.size();
}
int PhaseSpacePoint::sample_ng(std::vector<fastjet::PseudoJet> const & Born_jets){
const double ng_mean = estimate_ng_mean(Born_jets);
std::poisson_distribution<int> dist(ng_mean);
RNGWrapper<CLHEP::Ranlux64Engine> rng{ran_};
const int ng = dist(rng);
assert(ng >= 0);
assert(ng < ng_max);
weight_ *= std::tgamma(ng + 1)*std::exp(ng_mean)*std::pow(ng_mean, -ng);
return ng;
}
namespace {
void copy_AWZH_boson(
std::vector<Sparticle> const & from,
std::vector<Sparticle> & to
){
const auto AWZH_boson = std::find_if(
begin(from), end(from),
[](Sparticle const & p){ return is_AWZH_boson(p); }
);
if(AWZH_boson == end(from)) return;
auto insertion_point = std::lower_bound(
begin(to), end(to), *AWZH_boson, rapidity_less{}
);
to.insert(insertion_point, *AWZH_boson);
assert(std::is_sorted(begin(to), end(to), rapidity_less{}));
}
}
PhaseSpacePoint::PhaseSpacePoint(
Event const & ev,
fastjet::JetDefinition jet_def, double jetptmin,
fastjet::JetDefinition Born_jet_def, double Born_jetptmin,
double extpartonptmin
):
unob_{has_unob_gluon(ev.incoming, ev.outgoing)},
unof_{!unob_ && has_unof_gluon(ev.incoming, ev.outgoing)},
extpartonptmin_{extpartonptmin},
jetptmin_{jetptmin},
Born_jetptmin_{Born_jetptmin},
jet_def_{jet_def},
Born_jet_def_{Born_jet_def},
splitter_{jet_def.R(), jet_def, jetptmin, ran_}
{
weight_ = 1;
fastjet::ClusterSequence cs(
to_PseudoJet(filter_partons(ev.outgoing)),
Born_jet_def_
);
const auto Born_jets = sorted_by_rapidity(
cs.inclusive_jets(Born_jetptmin_)
);
const int ng = sample_ng(Born_jets);
weight_ /= std::tgamma(ng + 1);
const int ng_jets = sample_ng_jets(ng, Born_jets);
std::vector<fastjet::PseudoJet> out_partons = gen_non_jet(
ng - ng_jets, ccut, jetptmin_
);
{
const auto qperp = std::accumulate(
begin(out_partons), end(out_partons),
fastjet::PseudoJet{}
);
const auto jets = reshuffle(Born_jets, qperp);
if(weight_ == 0.) return;
if(! pass_resummation_cuts(jets)){
weight_ = 0.;
return;
}
std::vector<fastjet::PseudoJet> jet_partons = split(jets, ng_jets);
if(weight_ == 0.) return;
rescale_rapidities(
out_partons,
most_backward_FKL(jet_partons).rapidity(),
most_forward_FKL(jet_partons).rapidity()
);
if(! cluster_jets(out_partons).empty()){
weight_ = 0.;
return;
}
std::sort(begin(out_partons), end(out_partons), rapidity_less{});
assert(
std::is_sorted(begin(jet_partons), end(jet_partons), rapidity_less{})
);
const auto first_jet_parton = out_partons.insert(
end(out_partons), begin(jet_partons), end(jet_partons)
);
std::inplace_merge(
begin(out_partons), first_jet_parton, end(out_partons), rapidity_less{}
);
assert(extremal_FKL_ok(out_partons));
}
if(! jets_ok(Born_jets, out_partons)){
weight_ = 0.;
return;
}
weight_ *= phase_space_normalisation(Born_jets.size(), out_partons.size());
outgoing_.reserve(out_partons.size() + 1); // one slot for possible A, W, Z, H
for(auto & p: out_partons){
outgoing_.emplace_back(Sparticle{pid::gluon, std::move(p)});
}
most_backward_FKL(outgoing_).type = ev.incoming.front().type;
most_forward_FKL(outgoing_).type = ev.incoming.back().type;
copy_AWZH_boson(ev.outgoing, outgoing_);
assert(!outgoing_.empty());
reconstruct_incoming(ev.incoming);
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::gen_non_jet(
int count, double ptmin, double ptmax
){
// heuristic parameters for pt sampling
const double ptpar = 1.3 + count/5.;
const double temp1 = atan((ptmax - ptmin)/ptpar);
std::vector<fastjet::PseudoJet> partons(count);
for(size_t i = 0; i < (size_t) count; ++i){
const double r1 = ran_.flat();
const double pt = ptmin + ptpar*tan(r1*temp1);
const double temp2 = cos(r1*temp1);
const double phi = 2*M_PI*ran_.flat();
weight_ *= 2.0*M_PI*pt*ptpar*temp1/(temp2*temp2);
// we don't know the allowed rapidity span yet,
// set a random value to be rescaled later on
const double y = ran_.flat();
partons[i].reset_PtYPhiM(pt, y, phi);
// Set user index higher than any jet-parton index
// in order to assert that these are not inside jets
partons[i].set_user_index(i + 1 + RHEJ::PhaseSpacePoint::ng_max);
assert(ptmin-1e-5 <= partons[i].pt() && partons[i].pt() <= ptmax+1e-5);
}
assert(std::all_of(partons.cbegin(), partons.cend(), is_nonjet_parton));
return partons;
}
void PhaseSpacePoint::rescale_rapidities(
std::vector<fastjet::PseudoJet> & partons,
double ymin, double ymax
){
constexpr double ep = 1e-7;
for(auto & parton: partons){
assert(0 <= parton.rapidity() && parton.rapidity() <= 1);
const double dy = ymax - ymin - 2*ep;
const double y = ymin + ep + dy*parton.rapidity();
parton.reset_momentum_PtYPhiM(parton.pt(), y, parton.phi());
weight_ *= dy;
assert(ymin <= parton.rapidity() && parton.rapidity() <= ymax);
}
}
double PhaseSpacePoint::probability_in_jet(
std::vector<fastjet::PseudoJet> const & Born_jets
) const{
assert(std::is_sorted(begin(Born_jets), end(Born_jets), rapidity_less{}));
assert(Born_jets.size() >= 2);
const double dy =
Born_jets.back().rapidity() - Born_jets.front().rapidity();
const double R_eff = splitter_.R_factor*jet_def_.R();
const int njets = Born_jets.size();
const double p_J = (dy > 2.*R_eff*(njets-1))?
(njets-1)*R_eff*R_eff/(2.*dy):
njets*R_eff*R_eff/(2.*(dy + 2.*R_eff));
return std::min(p_J, 1.);
}
int PhaseSpacePoint::sample_ng_jets(
int ng, std::vector<fastjet::PseudoJet> const & Born_jets
){
RNGWrapper<CLHEP::Ranlux64Engine> rng{ran_};
const double p_J = probability_in_jet(Born_jets);
std::binomial_distribution<> bin_dist(ng, p_J);
const int ng_J = bin_dist(rng);
weight_ *= std::pow(p_J, -ng_J)*std::pow(1 - p_J, ng_J - ng);
return ng_J;
}
std::vector<fastjet::PseudoJet>
PhaseSpacePoint::reshuffle(
std::vector<fastjet::PseudoJet> const & Born_jets,
fastjet::PseudoJet const & q
){
if(q == fastjet::PseudoJet{0, 0, 0, 0}) return Born_jets;
std::vector<fastjet::PseudoJet> jets = FindJetMomenta(Born_jets, q);
if(jets.empty()){
weight_ = 0;
return {};
}
// transform delta functions to integration over resummation momenta
weight_ /= Jacobian(jets, q);
return jets;
}
std::vector<int> PhaseSpacePoint::distribute_jet_partons(
int ng_jets, std::vector<fastjet::PseudoJet> const & jets
){
size_t first_valid_jet = 0;
size_t num_valid_jets = jets.size();
const double R_eff = 5./3.*jet_def_.R();
// if there is an unordered jet too far away from the FKL jets
// then extra gluon constituents of the unordered jet would
// violate the FKL rapidity ordering
if(unob_ && jets[0].delta_R(jets[1]) > R_eff){
++first_valid_jet;
--num_valid_jets;
}
else if(unof_ && jets[jets.size()-1].delta_R(jets[jets.size()-2]) > R_eff){
--num_valid_jets;
}
std::vector<int> np(jets.size(), 1);
for(int i = 0; i < ng_jets; ++i){
++np[first_valid_jet + ran_.flat() * num_valid_jets];
}
weight_ *= std::pow(num_valid_jets, ng_jets);
return np;
}
#ifndef NDEBUG
namespace{
bool tagged_FKL_backward(
std::vector<fastjet::PseudoJet> const & jet_partons
){
return std::find_if(
begin(jet_partons), end(jet_partons),
[](fastjet::PseudoJet const & p){
return p.user_index() == y_min_user_idx;
}
) != end(jet_partons);
}
bool tagged_FKL_forward(
std::vector<fastjet::PseudoJet> const & jet_partons
){
// the most forward FKL parton is most likely near the end of jet_partons;
// start search from there
return std::find_if(
rbegin(jet_partons), rend(jet_partons),
[](fastjet::PseudoJet const & p){
return p.user_index() == y_min_user_idx;
}
) != rend(jet_partons);
}
bool tagged_FKL_extremal(
std::vector<fastjet::PseudoJet> const & jet_partons
){
return tagged_FKL_backward(jet_partons) && tagged_FKL_forward(jet_partons);
}
} // end anonymous namespace
#endif
std::vector<fastjet::PseudoJet> PhaseSpacePoint::split(
std::vector<fastjet::PseudoJet> const & jets,
int ng_jets
){
return split(jets, distribute_jet_partons(ng_jets, jets));
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::split(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<int> const & np
){
assert(! jets.empty());
assert(jets.size() == np.size());
assert(pass_resummation_cuts(jets));
const size_t most_backward_FKL_idx = 0 + unob_;
const size_t most_forward_FKL_idx = jets.size() - 1 - unof_;
std::vector<fastjet::PseudoJet> jet_partons;
// randomly distribute jet gluons among jets
for(size_t i = 0; i < jets.size(); ++i){
weight_ *= splitter_.Split(jets[i], np[i]);
if(weight_ == 0) return {};
assert(
std::all_of(
begin(splitter_.get_jcons()), end(splitter_.get_jcons()),
is_jet_parton
)
);
const auto first_new_parton = jet_partons.insert(
end(jet_partons),
begin(splitter_.get_jcons()), end(splitter_.get_jcons())
);
auto extremal = end(jet_partons);
if((unob_ && i == 0) || i == most_backward_FKL_idx){
// unordered or FKL backward emission
extremal = std::min_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
if(i == most_backward_FKL_idx) extremal->set_user_index(y_min_user_idx);
}
else if((unof_ && i == jets.size() - 1) || i == most_forward_FKL_idx){
// unordered or FKL forward emission
extremal = std::max_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
if(i == most_forward_FKL_idx) extremal->set_user_index(y_max_user_idx);
}
if(extremal != end(jet_partons) && extremal->pt() < extpartonptmin_){
weight_ = 0;
return {};
}
}
assert(tagged_FKL_extremal(jet_partons));
std::sort(begin(jet_partons), end(jet_partons), rapidity_less{});
if(
!extremal_FKL_ok(jet_partons)
|| !split_preserved_jets(jets, jet_partons)
){
weight_ = 0.;
return {};
}
return jet_partons;
}
bool PhaseSpacePoint::extremal_FKL_ok(
std::vector<fastjet::PseudoJet> const & partons
) const{
assert(std::is_sorted(begin(partons), end(partons), rapidity_less{}));
return
most_backward_FKL(partons).user_index() == y_min_user_idx
&& most_forward_FKL(partons).user_index() == y_max_user_idx;
}
bool PhaseSpacePoint::split_preserved_jets(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<fastjet::PseudoJet> const & jet_partons
) const{
assert(std::is_sorted(begin(jets), end(jets), rapidity_less{}));
const auto split_jets = sorted_by_rapidity(cluster_jets(jet_partons));
// this can happen if two overlapping jets
// are both split into more than one parton
if(split_jets.size() != jets.size()) return false;
for(size_t i = 0; i < split_jets.size(); ++i){
// this can happen if there are two overlapping jets
// and a parton is assigned to the "wrong" jet
if(!nearby_ep(jets[i].rapidity(), split_jets[i].rapidity(), 1e-2)){
return false;
}
}
return true;
}
template<class Particle>
Particle const & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> const & partons
) const{
return partons[0 + unob_];
}
template<class Particle>
Particle const & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> const & partons
) const{
const size_t idx = partons.size() - 1 - unof_;
assert(idx < partons.size());
return partons[idx];
}
template<class Particle>
Particle & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> & partons
) const{
return partons[0 + unob_];
}
template<class Particle>
Particle & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> & partons
) const{
const size_t idx = partons.size() - 1 - unof_;
assert(idx < partons.size());
return partons[idx];
}
namespace{
bool contains_idx(
fastjet::PseudoJet const & jet, fastjet::PseudoJet const & parton
){
auto const & constituents = jet.constituents();
const int idx = parton.user_index();
return std::find_if(
begin(constituents), end(constituents),
[idx](fastjet::PseudoJet const & con){return con.user_index() == idx;}
) != end(constituents);
}
}
/**
* final jet test:
* - number of jets must match Born kinematics
* - no partons designated as nonjet may end up inside jets
* - all other outgoing partons *must* end up inside jets
* - the extremal (in rapidity) partons must be inside the extremal jets
* - rapidities must be the same (by construction)
*/
bool PhaseSpacePoint::jets_ok(
std::vector<fastjet::PseudoJet> const & Born_jets,
std::vector<fastjet::PseudoJet> const & partons
) const{
fastjet::ClusterSequence cs(partons, jet_def_);
const auto jets = sorted_by_rapidity(cs.inclusive_jets(jetptmin_));
if(jets.size() != Born_jets.size()) return false;
int in_jet = 0;
for(size_t i = 0; i < jets.size(); ++i){
assert(jets[i].has_constituents());
for(auto && parton: jets[i].constituents()){
if(is_nonjet_parton(parton)) return false;
}
in_jet += jets[i].constituents().size();
}
const int expect_in_jet = std::count_if(
partons.cbegin(), partons.cend(), is_jet_parton
);
if(in_jet != expect_in_jet) return false;
// note that PseudoJet::contains does not work here
if(! (
contains_idx(most_backward_FKL(jets), most_backward_FKL(partons))
&& contains_idx(most_forward_FKL(jets), most_forward_FKL(partons))
)) return false;
for(size_t i = 0; i < jets.size(); ++i){
assert(nearby_ep(jets[i].rapidity(), Born_jets[i].rapidity(), 1e-2));
}
return true;
}
namespace{
}
void PhaseSpacePoint::reconstruct_incoming(
std::array<Sparticle, 2> const & Born_incoming
){
std::tie(incoming_[0].p, incoming_[1].p) = incoming_momenta(outgoing_);
for(size_t i = 0; i < incoming_.size(); ++i){
incoming_[i].type = Born_incoming[i].type;
}
assert(momentum_conserved(1e-7));
}
double PhaseSpacePoint::phase_space_normalisation(
int num_Born_jets, int num_out_partons
) const{
return pow(16*pow(M_PI,3), num_Born_jets - num_out_partons);
}
bool PhaseSpacePoint::momentum_conserved(double ep) const{
fastjet::PseudoJet diff;
for(auto const & in: incoming()) diff += in.p;
for(auto const & out: outgoing()) diff -= out.p;
return nearby_ep(diff, fastjet::PseudoJet{}, ep);
}
}
diff --git a/src/PhaseSpacePoint.hpp b/src/PhaseSpacePoint.hpp
index 2f97d74..2b2b420 100644
--- a/src/PhaseSpacePoint.hpp
+++ b/src/PhaseSpacePoint.hpp
@@ -1,121 +1,124 @@
#pragma once
#include <vector>
#include <CLHEP/Random/Randomize.h>
#include <CLHEP/Random/RanluxEngine.h>
#include "Common.h"
#include "Event.hh"
#include "splitter.h"
namespace RHEJ{
// A point in resummation phase space
class PhaseSpacePoint{
public:
PhaseSpacePoint() = default;
PhaseSpacePoint(
Event const & ev,
fastjet::JetDefinition jet_def, double jetptmin,
fastjet::JetDefinition Born_jet_def, double Born_jetptmin,
double extpartonptmin
);
double weight() const{
return weight_;
}
std::array<Sparticle, 2> const & incoming() const{
return incoming_;
}
std::vector<Sparticle> const & outgoing() const{
return outgoing_;
}
static constexpr double ccut = 0.2; // universal min pt cut
static constexpr int ng_max = 1000; // maximum number of extra gluons
+ static void reset_ranlux(std::string const & init_file);
+ static void reset_ranlux(char const * init_file);
+
private:
std::vector<fastjet::PseudoJet> cluster_jets(
std::vector<fastjet::PseudoJet> const & partons
) const;
bool pass_resummation_cuts(
std::vector<fastjet::PseudoJet> const & jets
) const;
int sample_ng(std::vector<fastjet::PseudoJet> const & Born_jets);
int sample_ng_jets(int ng, std::vector<fastjet::PseudoJet> const & Born_jets);
double probability_in_jet(
std::vector<fastjet::PseudoJet> const & Born_jets
) const;
std::vector<fastjet::PseudoJet> gen_non_jet(
int ng_non_jet,
double ptmin, double ptmax
);
void rescale_rapidities(
std::vector<fastjet::PseudoJet> & partons,
double ymin, double ymax
);
std::vector<fastjet::PseudoJet> reshuffle(
std::vector<fastjet::PseudoJet> const & Born_jets,
fastjet::PseudoJet const & q
);
bool jets_ok(
std::vector<fastjet::PseudoJet> const & Born_jets,
std::vector<fastjet::PseudoJet> const & partons
) const;
void reconstruct_incoming(std::array<Sparticle, 2> const & Born_incoming);
double phase_space_normalisation(
int num_Born_jets,
int num_res_partons
) const;
std::vector<fastjet::PseudoJet> split(
std::vector<fastjet::PseudoJet> const & jets, int ng_jets
);
std::vector<int> distribute_jet_partons(
int ng_jets, std::vector<fastjet::PseudoJet> const & jets
);
std::vector<fastjet::PseudoJet> split(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<int> const & np_in_jet
);
bool split_preserved_jets(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<fastjet::PseudoJet> const & jet_partons
) const;
template<class Particle>
Particle const & most_backward_FKL(
std::vector<Particle> const & partons
) const;
template<class Particle>
Particle const & most_forward_FKL(
std::vector<Particle> const & partons
) const;
template<class Particle>
Particle & most_backward_FKL(std::vector<Particle> & partons) const;
template<class Particle>
Particle & most_forward_FKL(std::vector<Particle> & partons) const;
bool extremal_FKL_ok(
std::vector<fastjet::PseudoJet> const & partons
) const;
bool momentum_conserved(double ep) const;
bool unob_, unof_;
double weight_;
double extpartonptmin_;
double jetptmin_, Born_jetptmin_;
fastjet::JetDefinition jet_def_, Born_jet_def_;
std::array<Sparticle, 2> incoming_;
std::vector<Sparticle> outgoing_;
static CLHEP::Ranlux64Engine ran_;
HejSplit splitter_;
};
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 21, 3:37 PM (1 d, 6 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4023312
Default Alt Text
(29 KB)
Attached To
rHEJ HEJ
Event Timeline
Log In to Comment