Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879846
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
28 KB
Subscribers
None
View Options
diff --git a/src/Event.cc b/src/Event.cc
index 002d6fb..66ec30f 100644
--- a/src/Event.cc
+++ b/src/Event.cc
@@ -1,795 +1,795 @@
/**
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/Event.hh"
#include <algorithm>
#include <assert.h>
#include <numeric>
#include <utility>
#include "LHEF/LHEF.h"
#include "fastjet/JetDefinition.hh"
#include "HEJ/Constants.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/PDG_codes.hh"
namespace HEJ{
namespace{
constexpr int status_in = -1;
constexpr int status_decayed = 2;
constexpr int status_out = 1;
/// @name helper functions to determine event type
//@{
/**
* \brief check if final state valid for HEJ
*
* check if there is at most one photon, W, H, Z in the final state
* and all the rest are quarks or gluons
*/
bool final_state_ok(std::vector<Particle> const & outgoing){
bool has_AWZH_boson = false;
for(auto const & out: outgoing){
if(is_AWZH_boson(out.type)){
if(has_AWZH_boson) return false;
has_AWZH_boson = true;
}
else if(! is_parton(out.type)) return false;
}
return true;
}
template<class Iterator>
Iterator remove_AWZH(Iterator begin, Iterator end){
return std::remove_if(
begin, end, [](Particle const & p){return is_AWZH_boson(p);}
);
}
template<class Iterator>
bool valid_outgoing(Iterator begin, Iterator end){
return std::distance(begin, end) >= 2
&& std::is_sorted(begin, end, rapidity_less{})
&& std::count_if(
begin, end, [](Particle const & s){return is_AWZH_boson(s);}
) < 2;
}
/**
* \brief function which determines if type change is consistent with W emission.
* @param in incoming Particle
* @param out outgoing Particle
*
* Ensures that change type of quark line is possible by a flavour changing
* W emission.
*/
bool is_W_Current(ParticleID in, ParticleID out){
if((in==1 && out==2)||(in==2 && out==1)){
return true;
}
else if((in==-1 && out==-2)||(in==-2 && out==-1)){
return true;
}
else if((in==3 && out==4)||(in==4 && out==3)){
return true;
}
else if((in==-3 && out==-4)||(in==-4 && out==-3)){
return true;
}
else{
return false;
}
}
/**
* \brief checks if particle type remains same from incoming to outgoing
* @param in incoming Particle
* @param out outgoing Particle
*/
bool is_Pure_Current(ParticleID in, ParticleID out){
if(abs(in)<=6 || in==21) return (in==out);
else return false;
}
// @note that this changes the outgoing range!
template<class ConstIterator, class Iterator>
bool is_FKL(
ConstIterator begin_incoming, ConstIterator end_incoming,
Iterator begin_outgoing, Iterator end_outgoing
){
assert(std::distance(begin_incoming, end_incoming) == 2);
assert(std::distance(begin_outgoing, end_outgoing) >= 2);
// One photon, W, H, Z in the final state is allowed.
// Remove it for remaining tests,
end_outgoing = remove_AWZH(begin_outgoing, end_outgoing);
if(std::all_of(
begin_outgoing + 1, end_outgoing - 1,
[](Particle const & p){ return p.type == pid::gluon; })
){
// Test if this is a standard FKL configuration.
if (is_Pure_Current(begin_incoming->type, begin_outgoing->type)
&& is_Pure_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
return true;
}
}
return false;
}
template<class ConstIterator, class Iterator>
bool is_W_FKL(
ConstIterator begin_incoming, ConstIterator end_incoming,
Iterator begin_outgoing, Iterator end_outgoing
){
assert(std::distance(begin_incoming, end_incoming) == 2);
assert(std::distance(begin_outgoing, end_outgoing) >= 2);
// One photon, W, H, Z in the final state is allowed.
// Remove it for remaining tests,
end_outgoing = remove_AWZH(begin_outgoing, end_outgoing);
if(std::all_of(
begin_outgoing + 1, end_outgoing - 1,
[](Particle const & p){ return p.type == pid::gluon; })
){
// Test if this is a standard FKL configuration.
if(is_W_Current(begin_incoming->type, begin_outgoing->type)
&& is_Pure_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
return true;
}
else if(is_Pure_Current(begin_incoming->type, begin_outgoing->type)
&& is_W_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
return true;
}
}
return false;
}
bool is_FKL(
std::array<Particle, 2> const & incoming,
std::vector<Particle> outgoing
){
assert(std::is_sorted(begin(incoming), end(incoming), pz_less{}));
assert(valid_outgoing(begin(outgoing), end(outgoing)));
const auto WEmit = std::find_if(
begin(outgoing), end(outgoing),
[](Particle const & s){ return abs(s.type) == pid::Wp; }
);
- if (abs(WEmit->type) == pid::Wp){
+ if (WEmit != end(outgoing) && abs(WEmit->type) == pid::Wp){
return is_W_FKL(
begin(incoming), end(incoming),
begin(outgoing), end(outgoing)
);
}
else{
return is_FKL(
begin(incoming), end(incoming),
begin(outgoing), end(outgoing)
);
}
}
bool has_2_jets(Event const & event){
return event.jets().size() >= 2;
}
/**
* \brief Checks whether event is unordered backwards
* @param ev Event
* @returns Is Event Unordered Backwards
*
* - Checks there is more than 3 constuents in the final state
* - Checks there is more than 3 jets
* - Checks the most backwards parton is a gluon
* - Checks the most forwards jet is not a gluon
* - Checks the rest of the event is FKL
* - Checks the second most backwards is not a different boson
* - Checks the unordered gluon actually forms a jet
*/
bool is_unordered_backward(Event const & ev){
auto const & in = ev.incoming();
auto const & out = ev.outgoing();
assert(std::is_sorted(begin(in), end(in), pz_less{}));
assert(valid_outgoing(begin(out), end(out)));
if(out.size() < 3) return false;
if(ev.jets().size() < 3) return false;
if(in.front().type == pid::gluon) return false;
if(out.front().type != pid::gluon) return false;
// When skipping the unordered emission
// the remainder should be a regular FKL event,
// except that the (new) first outgoing particle must not be a A,W,Z,H.
const auto FKL_begin = next(begin(out));
if(is_AWZH_boson(*FKL_begin)) return false;
if(!is_FKL(in, {FKL_begin, end(out)})) return false;
// check that the unordered gluon forms an extra jet
const auto jets = sorted_by_rapidity(ev.jets());
const auto indices = ev.particle_jet_indices({jets.front()});
return indices[0] >= 0 && indices[1] == -1;
}
/**
* \brief Checks for a forward unordered gluon emission
* @param ev Event
* @returns Is the event a forward unordered emission
*
* \see is_unordered_backward
*/
bool is_unordered_forward(Event const & ev){
auto const & in = ev.incoming();
auto const & out = ev.outgoing();
assert(std::is_sorted(begin(in), end(in), pz_less{}));
assert(valid_outgoing(begin(out), end(out)));
if(out.size() < 3) return false;
if(ev.jets().size() < 3) return false;
if(in.back().type == pid::gluon) return false;
if(out.back().type != pid::gluon) return false;
// When skipping the unordered emission
// the remainder should be a regular FKL event,
// except that the (new) last outgoing particle must not be a A,W,Z,H.
const auto FKL_end = prev(end(out));
if(is_AWZH_boson(*prev(FKL_end))) return false;
if(!is_FKL(in, {begin(out), FKL_end})) return false;
// check that the unordered gluon forms an extra jet
const auto jets = sorted_by_rapidity(ev.jets());
const auto indices = ev.particle_jet_indices({jets.back()});
return indices.back() >= 0 && indices[indices.size()-2] == -1;
}
/**
* \brief Checks for a forward extremal qqx
* @param ev Event
* @returns Is the event a forward extremal qqx event
*
* Checks there is 3 or more than 3 constituents in the final state
* Checks there is 3 or more than 3 jets
* Checks most forwards incoming is gluon
* Checks most extremal particle is not a Higgs (either direction)
* Checks the second most forwards particle is not Higgs boson
* Checks the most forwards parton is a either quark or anti-quark.
* Checks the second most forwards parton is anti-quark or quark.
* Checks the qqbar pair form 2 separate jets.
*/
bool is_Ex_qqxf(Event const & ev){
auto const & in = ev.incoming();
auto const & out = ev.outgoing();
assert(std::is_sorted(begin(in), end(in), pz_less{}));
assert(valid_outgoing(begin(out), end(out)));
int fkl_end=2;
if(out.size() < 3) return false;
if(ev.jets().size() < 3) return false;
if(in.back().type != pid::gluon) return false;
if(out.back().type == pid::Higgs || out.front().type == pid::Higgs
|| out.rbegin()[1].type == pid::Higgs) return false;
// if extremal AWZ
if(is_AWZ_boson(out.back())){ // if extremal AWZ
fkl_end++;
if (is_quark(out.rbegin()[1])){ //if second quark
if (!(is_antiquark(out.rbegin()[2]))) return false;// third must be anti-quark
}
else if (is_antiquark(out.rbegin()[1])){ //if second anti-quark
if (!(is_quark(out.rbegin()[2]))) return false;// third must be quark
}
else return false;
}
else if (is_quark(out.rbegin()[0])){ //if extremal quark
if(is_AWZ_boson(out.rbegin()[1])){ // if second AWZ
fkl_end++;
if (!(is_antiquark(out.rbegin()[2]))) return false;// third must be anti-quark
}
else if (!(is_antiquark(out.rbegin()[1]))) return false;// second must be anti-quark
}
else if (is_antiquark(out.rbegin()[0])){ //if extremal anti-quark
if(is_AWZ_boson(out.rbegin()[1])){ // if second AWZ
fkl_end++;
if (!(is_quark(out.rbegin()[2]))) return false;// third must be quark
}
else if (!(is_quark(out.rbegin()[1]))) return false;// second must be quark
}
else return false;
// When skipping the qqbar
// New last outgoing particle must not be a Higgs
if (out.rbegin()[fkl_end].type == pid::Higgs) return false;
const auto jets = fastjet::sorted_by_rapidity(ev.jets());
const auto indices = ev.particle_jet_indices({jets});
// Ensure qqbar pair are in separate jets
if(indices[indices.size()-2] != indices[indices.size()-1]-1) return false;
// Opposite current should be logical to process
if (is_AWZ_boson(out.front().type)){
return (is_Pure_Current(in.front().type, out[1].type)
|| is_W_Current(in.front().type,out[1].type));
}
else
return (is_Pure_Current(in.front().type, out[0].type)
|| is_W_Current(in.front().type,out[0].type));
}
/**
* \brief Checks for a backward extremal qqx
* @param ev Event
* @returns Is the event a backward extremal qqx event
*
* Checks there is 3 or more than 3 constituents in the final state
* Checks there is 3 or more than 3 jets
* Checks most backwards incoming is gluon
* Checks most extremal particle is not a Higgs (either direction) y
* Checks the second most backwards particle is not Higgs boson y
* Checks the most backwards parton is a either quark or anti-quark. y
* Checks the second most backwards parton is anti-quark or quark. y
* Checks the qqbar pair form 2 separate jets.
*/
bool is_Ex_qqxb(Event const & ev){
auto const & in = ev.incoming();
auto const & out = ev.outgoing();
assert(std::is_sorted(begin(in), end(in), pz_less{}));
assert(valid_outgoing(begin(out), end(out)));
int fkl_start=2;
if(out.size() < 3) return false;
if(ev.jets().size() < 3) return false;
if(in.front().type != pid::gluon) return false;
if(out.back().type == pid::Higgs || out.front().type == pid::Higgs
|| out[1].type == pid::Higgs) return false;
if(is_AWZ_boson(out.front())){ // if extremal AWZ
fkl_start++;
if (is_quark(out[1])){ //if second quark
if (!(is_antiquark(out[2]))) return false;// third must be anti-quark
}
else if (is_antiquark(out[1])){ //if second anti-quark
if (!(is_quark(out[2]))) return false;// third must be quark
}
else return false;
}
else if (is_quark(out[0])){ // if extremal quark
if(is_AWZ_boson(out[1])){ // if second AWZ
fkl_start++;
if (!(is_antiquark(out[2]))) return false;// third must be anti-quark
}
else if (!(is_antiquark(out[1]))) return false;// second must be anti-quark
}
else if (is_antiquark(out[0])){ //if extremal anti-quark
if(is_AWZ_boson(out[1])){ // if second AWZ
fkl_start++;
if (!(is_quark(out[2]))) return false;// third must be quark
}
else if (!(is_quark(out[1]))) return false;// second must be quark
}
else return false;
// When skipping the qqbar
// New last outgoing particle must not be a Higgs.
if (out[fkl_start].type == pid::Higgs) return false;
const auto jets = fastjet::sorted_by_rapidity(ev.jets());
const auto indices = ev.particle_jet_indices({jets});
// Ensure qqbar pair form separate jets.
if(indices[0] != indices[1]-1) return false;
// Other current should be logical to process
if (is_AWZ_boson(out.back())){
return (is_Pure_Current(in.back().type, out.rbegin()[1].type)
|| is_W_Current(in.back().type,out.rbegin()[1].type));
}
else
return (is_Pure_Current(in.back().type, out.rbegin()[0].type)
|| is_W_Current(in.back().type, out.rbegin()[0].type));
}
/**
* \brief Checks for a central qqx
* @param ev Event
* @returns Is the event a central extremal qqx event
*
* Checks there is 4 or more than 4 constuents in the final state
* Checks there is 4 or more than 4 jets
* Checks most extremal particle is not a Higgs (either direction) y
* Checks for a central quark in the outgoing states
* Checks for adjacent anti-quark parton. (allowing for AWZ boson emission between)
* Checks external currents are logically sound.
*/
bool is_Mid_qqx(Event const & ev){
auto const & in = ev.incoming();
auto const & out = ev.outgoing();
assert(std::is_sorted(begin(in), end(in), pz_less{}));
assert(valid_outgoing(begin(out), end(out)));
if(out.size() < 4) return false;
if(ev.jets().size() < 4) return false;
if(out.back().type == pid::Higgs || out.front().type == pid::Higgs)
return false;
size_t start_FKL=0;
size_t end_FKL=0;
if (is_AWZ_boson(out.back())){
end_FKL++;
}
if (is_AWZ_boson(out.front())){
start_FKL++;
}
if ((is_Pure_Current(in.back().type,out.rbegin()[end_FKL].type)
&& is_Pure_Current(in.front().type,out[start_FKL].type))){
//nothing to do
}
else if (is_W_Current(in.back().type,out.rbegin()[end_FKL].type)
&& is_Pure_Current(in.front().type,out[start_FKL].type)){
//nothing to do
}
else if (!(is_Pure_Current(in.back().type,out.rbegin()[end_FKL].type)
&& is_W_Current(in.front().type,out[start_FKL].type))){
return false;
}
const auto jets = fastjet::sorted_by_rapidity(ev.jets());
const auto indices = ev.particle_jet_indices({jets});
auto const out_partons = filter_partons(out);
for (size_t i = 1; i<out_partons.size()-2; i++){
if ((is_quark(out_partons[i]) && (is_antiquark(out_partons[i+1])))
|| (is_antiquark(out_partons[i]) && (is_quark(out_partons[i+1])))){
return (indices[i+1] == indices[i]+1 && indices[i] != -1);
}
}
return false;
}
using event_type::EventType;
EventType classify(Event const & ev){
if(! final_state_ok(ev.outgoing()))
return EventType::bad_final_state;
if(! has_2_jets(ev))
return EventType::no_2_jets;
if(is_FKL(ev.incoming(), ev.outgoing()))
return EventType::FKL;
if(is_unordered_backward(ev))
return EventType::unordered_backward;
if(is_unordered_forward(ev))
return EventType::unordered_forward;
if(is_Ex_qqxb(ev))
return EventType::extremal_qqxb;
if(is_Ex_qqxf(ev))
return EventType::extremal_qqxf;
if(is_Mid_qqx(ev))
return EventType::central_qqx;
return EventType::nonHEJ;
}
//@}
Particle extract_particle(LHEF::HEPEUP const & hepeup, int i){
const ParticleID id = static_cast<ParticleID>(hepeup.IDUP[i]);
const fastjet::PseudoJet momentum{
hepeup.PUP[i][0], hepeup.PUP[i][1],
hepeup.PUP[i][2], hepeup.PUP[i][3]
};
if(is_parton(id))
return Particle{ id, std::move(momentum), hepeup.ICOLUP[i] };
return Particle{ id, std::move(momentum), {} };
}
bool is_decay_product(std::pair<int, int> const & mothers){
if(mothers.first == 0) return false;
return mothers.second == 0 || mothers.first == mothers.second;
}
} // namespace anonymous
Event::EventData::EventData(LHEF::HEPEUP const & hepeup){
parameters.central = EventParameters{
hepeup.scales.mur, hepeup.scales.muf, hepeup.weight()
};
size_t in_idx = 0;
for (int i = 0; i < hepeup.NUP; ++i) {
// skip decay products
// we will add them later on, but we have to ensure that
// the decayed particle is added before
if(is_decay_product(hepeup.MOTHUP[i])) continue;
auto particle = extract_particle(hepeup, i);
// needed to identify mother particles for decay products
particle.p.set_user_index(i+1);
if(hepeup.ISTUP[i] == status_in){
if(in_idx > incoming.size()) {
throw std::invalid_argument{
"Event has too many incoming particles"
};
}
incoming[in_idx++] = std::move(particle);
}
else outgoing.emplace_back(std::move(particle));
}
// add decay products
for (int i = 0; i < hepeup.NUP; ++i) {
if(!is_decay_product(hepeup.MOTHUP[i])) continue;
const int mother_id = hepeup.MOTHUP[i].first;
const auto mother = std::find_if(
begin(outgoing), end(outgoing),
[mother_id](Particle const & particle){
return particle.p.user_index() == mother_id;
}
);
if(mother == end(outgoing)){
throw std::invalid_argument{"invalid decay product parent"};
}
const int mother_idx = std::distance(begin(outgoing), mother);
assert(mother_idx >= 0);
decays[mother_idx].emplace_back(extract_particle(hepeup, i));
}
}
Event::Event(
UnclusteredEvent const & ev,
fastjet::JetDefinition const & jet_def, double const min_jet_pt
):
Event( Event::EventData{
ev.incoming, ev.outgoing, ev.decays,
Parameters<EventParameters>{ev.central, ev.variations}
}.cluster(jet_def, min_jet_pt) )
{}
//! @TODO remove in HEJ 2.3.0
UnclusteredEvent::UnclusteredEvent(LHEF::HEPEUP const & hepeup){
Event::EventData const evData{hepeup};
incoming = evData.incoming;
outgoing = evData.outgoing;
decays = evData.decays;
central = evData.parameters.central;
variations = evData.parameters.variations;
}
void Event::EventData::sort(){
// sort particles
std::sort(
begin(incoming), end(incoming),
[](Particle o1, Particle o2){return o1.p.pz()<o2.p.pz();}
);
auto old_outgoing = std::move(outgoing);
std::vector<size_t> idx(old_outgoing.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&old_outgoing](size_t i, size_t j){
return old_outgoing[i].rapidity() < old_outgoing[j].rapidity();
});
outgoing.clear();
outgoing.reserve(old_outgoing.size());
for(size_t i: idx) {
outgoing.emplace_back(std::move(old_outgoing[i]));
}
// find decays again
if(!decays.empty()){
auto old_decays = std::move(decays);
decays.clear();
for(size_t i=0; i<idx.size(); ++i) {
auto decay = old_decays.find(idx[i]);
if(decay != old_decays.end())
decays.emplace(i, std::move(decay->second));
}
assert(old_decays.size() == decays.size());
}
}
Event Event::EventData::cluster(
fastjet::JetDefinition const & jet_def, double const min_jet_pt
){
sort();
Event ev{ std::move(incoming), std::move(outgoing), std::move(decays),
std::move(parameters),
jet_def, min_jet_pt
};
assert(std::is_sorted(begin(ev.outgoing_), end(ev.outgoing_),
rapidity_less{}));
ev.type_ = classify(ev);
return ev;
}
namespace {
void connect_incoming(Particle & in, int & colour, int & anti_colour){
in.colour = std::make_pair(anti_colour, colour);
// gluon
if(in.type == pid::gluon)
return;
if(in.type > 0){
// quark
assert(is_quark(in));
in.colour->second = 0;
colour*=-1;
return;
}
// anti-quark
assert(is_antiquark(in));
in.colour->first = 0;
anti_colour*=-1;
return;
}
}
bool Event::generate_colours(RNG & ran){
// generate only for HEJ events
if(!event_type::is_HEJ(type()))
return false;
assert(std::is_sorted(
begin(outgoing()), end(outgoing()), rapidity_less{}));
assert(incoming()[0].pz() < incoming()[1].pz());
// positive (anti-)colour -> can connect
// negative (anti-)colour -> not available/used up by (anti-)quark
int colour = COLOUR_OFFSET;
int anti_colour = colour+1;
// initialise first
connect_incoming(incoming_[0], colour, anti_colour);
for(auto & part: outgoing_){
assert(colour>0 || anti_colour>0);
if(part.type == ParticleID::gluon){
// gluon
if(colour>0 && anti_colour>0){
// on g line => connect to colour OR anti-colour (random)
if(ran.flat() < 0.5){
part.colour = std::make_pair(colour+2,colour);
colour+=2;
} else {
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(colour > 0){
// on q line => connect to available colour
part.colour = std::make_pair(colour+2, colour);
colour+=2;
} else {
assert(colour<0 && anti_colour>0);
// on qx line => connect to available anti-colour
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(is_quark(part)) {
// quark
assert(anti_colour>0);
if(colour>0){
// on g line => connect and remove anti-colour
part.colour = std::make_pair(anti_colour, 0);
anti_colour+=2;
anti_colour*=-1;
} else {
// on qx line => new colour
colour*=-1;
part.colour = std::make_pair(colour, 0);
}
} else if(is_antiquark(part)) {
// anti-quark
assert(colour>0);
if(anti_colour>0){
// on g line => connect and remove colour
part.colour = std::make_pair(0, colour);
colour+=2;
colour*=-1;
} else {
// on q line => new anti-colour
anti_colour*=-1;
part.colour = std::make_pair(0, anti_colour);
}
}
// else not a parton
}
// Connect last
connect_incoming(incoming_[1], anti_colour, colour);
return true;
} // generate_colours
std::vector<fastjet::PseudoJet> Event::jets() const{
return cs_.inclusive_jets(min_jet_pt_);
}
/**
* \brief Returns the invarient mass of the event
* @param ev Event
* @returns s hat
*
* Makes use of the FastJet PseudoJet function m2().
* Applies this function to the sum of the incoming partons.
*/
double shat(Event const & ev){
return (ev.incoming()[0].p + ev.incoming()[1].p).m2();
}
LHEF::HEPEUP to_HEPEUP(Event const & event, LHEF::HEPRUP * heprup){
LHEF::HEPEUP result;
result.heprup = heprup;
result.weights = {{event.central().weight, nullptr}};
for(auto const & var: event.variations()){
result.weights.emplace_back(var.weight, nullptr);
}
size_t num_particles = event.incoming().size() + event.outgoing().size();
for(auto const & decay: event.decays()) num_particles += decay.second.size();
result.NUP = num_particles;
// the following entries are pretty much meaningless
result.IDPRUP = event.type()+1; // event ID
result.AQEDUP = 1./128.; // alpha_EW
//result.AQCDUP = 0.118 // alpha_QCD
// end meaningless part
result.XWGTUP = event.central().weight;
result.SCALUP = event.central().muf;
result.scales.muf = event.central().muf;
result.scales.mur = event.central().mur;
result.scales.SCALUP = event.central().muf;
result.pdfinfo.p1 = event.incoming().front().type;
result.pdfinfo.p2 = event.incoming().back().type;
result.pdfinfo.scale = event.central().muf;
result.IDUP.reserve(num_particles); // PID
result.ISTUP.reserve(num_particles); // status (in, out, decay)
result.PUP.reserve(num_particles); // momentum
result.MOTHUP.reserve(num_particles); // index mother particle
result.ICOLUP.reserve(num_particles); // colour
// incoming
for(Particle const & in: event.incoming()){
result.IDUP.emplace_back(in.type);
result.ISTUP.emplace_back(status_in);
result.PUP.push_back({in.p[0], in.p[1], in.p[2], in.p[3], in.p.m()});
result.MOTHUP.emplace_back(0, 0);
assert(in.colour);
result.ICOLUP.emplace_back(*in.colour);
}
// outgoing
for(size_t i = 0; i < event.outgoing().size(); ++i){
Particle const & out = event.outgoing()[i];
result.IDUP.emplace_back(out.type);
const int status = event.decays().count(i)?status_decayed:status_out;
result.ISTUP.emplace_back(status);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
result.MOTHUP.emplace_back(1, 2);
if(out.colour)
result.ICOLUP.emplace_back(*out.colour);
else{
assert(is_AWZH_boson(out));
result.ICOLUP.emplace_back(std::make_pair(0,0));
}
}
// decays
for(auto const & decay: event.decays()){
for(auto const out: decay.second){
result.IDUP.emplace_back(out.type);
result.ISTUP.emplace_back(status_out);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
const size_t mother_idx = 1 + event.incoming().size() + decay.first;
result.MOTHUP.emplace_back(mother_idx, mother_idx);
result.ICOLUP.emplace_back(0,0);
}
}
assert(result.ICOLUP.size() == num_particles);
static constexpr double unknown_spin = 9.; //per Les Houches accord
result.VTIMUP = std::vector<double>(num_particles, unknown_spin);
result.SPINUP = result.VTIMUP;
return result;
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 9:16 PM (1 d, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3800097
Default Alt Text
(28 KB)
Attached To
rHEJ HEJ
Event Timeline
Log In to Comment