diff --git a/include/HEJ/PDG_codes.hh b/include/HEJ/PDG_codes.hh index e0b3cd7..381c006 100644 --- a/include/HEJ/PDG_codes.hh +++ b/include/HEJ/PDG_codes.hh @@ -1,307 +1,316 @@ /** \file PDG_codes.hh * \brief Contains the Particle IDs of all relevant SM particles. * * Large enumeration included which has multiple entries for potential * alternative names of different particles. There are also functions * which can be used to determine if a particle is a parton or if * it is a non-gluon boson. * * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2020 * \copyright GPLv2 or later */ #pragma once #include #include +#include "boost/rational.hpp" + namespace HEJ { //! particle ids according to PDG namespace pid { //! The possible particle identities. We use PDG IDs as standard. enum ParticleID: int{ //! Unspecified type, should never be used!, debug only unspecified = 0, d = 1, /*!< Down Quark */ down = d, /*!< Down Quark */ u = 2, /*!< Up Quark */ up = u, /*!< Up Quark */ s = 3, /*!< Strange Quark */ strange = s, /*!< Strange Quark */ c = 4, /*!< Charm Quark */ charm = c, /*!< Charm Quark */ b = 5, /*!< Bottom Quark */ bottom = b, /*!< Bottom Quark */ t = 6, /*!< Top Quark */ top = t, /*!< Top Quark */ e = 11, /*!< Electron */ electron = e, /*!< Electron */ nu_e = 12, /*!< Electron Neutrino */ electron_neutrino = nu_e, /*!< Electron neutrino */ mu = 13, /*!< Muon */ muon = mu, /*!< Muon */ nu_mu = 14, /*!< Muon Neutrino */ muon_neutrino = nu_mu, /*!< Muon Neutrino */ tau = 15, /*!< Tau */ nu_tau = 16, /*!< Tau Neutrino */ tau_neutrino = nu_tau, /*!< Tau Neutrino */ d_bar = -d, /*!< Anti-Down Quark */ antidown = d_bar, /*!< Anti-Down Quark */ u_bar = -u, /*!< Anti-Up quark */ antiup = -u, /*!< Anti-Up quark */ s_bar = -s, /*!< Anti-Strange Quark */ antistrange = -s, /*!< Anti-Strange Quark */ c_bar = -c, /*!< Anti-Charm Quark */ anticharm = -c, /*!< Anti-Charm Quark */ b_bar = -b, /*!< Anti-Bottom Quark */ antibottom = -b, /*!< Anti-Bottom Quark */ t_bar = -t, /*!< Anti-Top Quark */ antitop = -t, /*!< Anti-Top Quark */ e_bar = -e, /*!< Positron */ positron = e_bar, /*!< Positron */ antielectron = positron, /*!< Positron */ nu_e_bar = -nu_e, /*!< Electron Anti-Neutrino */ electron_antineutrino = nu_e_bar,/*!< Electron Anti-Neutrino */ mu_bar = -mu, /*!< Anti-Muon */ antimuon = -mu, /*!< Anti-Muon */ nu_mu_bar = -nu_mu, /*!< Muon Anti-Neutrino */ muon_antineutrino = nu_mu_bar, /*!< Muon Anti-Neutrino */ tau_bar = -tau, /*!< Anti-Tau */ antitau = tau_bar, /*!< Anti-Tau */ nu_tau_bar = -nu_tau, /*!< Tau Anti-Neutrino */ tau_antineutrino = nu_tau_bar, /*!< Tau Anti-Neutrino */ gluon = 21, /*!< Gluon */ g = gluon, /*!< Gluon */ photon = 22, /*!< Photon */ gamma = photon, /*!< Photon */ Z = 23, /*!< Z Boson */ Z_photon_mix = 81, /*!< Z/photon superposition */ Z_gamma_mix = Z_photon_mix, /*!< Z/photon superposition */ Wp = 24, /*!< W- Boson */ Wm = -Wp, /*!< W+ Boson */ h = 25, /*!< Higgs Boson */ Higgs = h, /*!< Higgs Boson */ higgs = h, /*!< Higgs Boson */ p = 2212, /*!< Proton */ proton = p, /*!< Proton */ p_bar = -p, /*!< Anti-Proton */ antiproton = p_bar, /*!< Anti-Proton */ }; //! Get the of the particle with the given PDG ID std::string name(ParticleID id); //! return the negative flavour of the given PDG ID ParticleID anti(ParticleID id); } // namespace pid using ParticleID = pid::ParticleID; //! Convert a particle name to the corresponding PDG particle ID ParticleID to_ParticleID(std::string const & name); /** * \brief Determine if the PDG ID denotes an antiparticle * @param id PDG ID of particle * @returns true if the PDG ID denotes an antiparticle, false otherwise */ inline constexpr bool is_antiparticle(ParticleID id) { return id < 0; } /** * \brief Function to determine if particle is a quark * @param id PDG ID of particle * @returns true if the particle is a quark, false otherwise */ inline constexpr bool is_quark(ParticleID id){ return (id >= pid::down && id <= pid::top); } /** * \brief Function to determine if particle is an antiquark * @param id PDG ID of particle * @returns true if the particle is an antiquark, false otherwise */ inline constexpr bool is_antiquark(ParticleID id){ return (id <= pid::d_bar && id >= pid::t_bar); } /** * \brief Function to determine if particle is an (anti-)quark * @param id PDG ID of particle * @returns true if the particle is a quark or antiquark, false otherwise */ inline constexpr bool is_anyquark(ParticleID id){ return is_quark(id) || is_antiquark(id); } /** * \brief Function to determine if particle is a gluon * @param id PDG ID of particle * @returns true if the particle is a gluon, false otherwise */ inline constexpr bool is_gluon(ParticleID id){ return id == pid::gluon; } /** * \brief Function to determine if particle is a parton * @param id PDG ID of particle * @returns true if the particle is a parton, false otherwise */ inline constexpr bool is_parton(ParticleID id){ return is_gluon(id) || (is_anyquark(id) && std::abs(id) != pid::top); } /** * \brief function to determine if the particle is a photon, W or Z * @param id PDG ID of particle * @returns true if the partice is an A,W,Z, or H, false otherwise */ inline constexpr bool is_AWZ_boson(ParticleID id){ return id == pid::Wm || (id >= pid::photon && id <= pid::Wp) || id == pid::Z_photon_mix; } /** * \brief function to determine if the particle is a photon, W, Z, or Higgs * boson * @param id PDG ID of particle * @returns true if the partice is an A,W,Z, or H, false otherwise */ inline constexpr bool is_AWZH_boson(ParticleID id){ return is_AWZ_boson(id) || (id == pid::Higgs); } /** * \brief Function to determine if particle is a lepton * @param id PDG ID of particle * @returns true if the particle is a lepton, false otherwise */ inline constexpr bool is_lepton(ParticleID id){ return (id >= pid::electron && id <= pid::tau_neutrino); } /** * \brief Function to determine if particle is an antilepton * @param id PDG ID of particle * @returns true if the particle is an antilepton, false otherwise */ inline constexpr bool is_antilepton(ParticleID id){ return (id <= pid::positron && id >= pid::nu_tau_bar); } /** * \brief Function to determine if particle is an (anti-)lepton * @param id PDG ID of particle * @returns true if the particle is a lepton or antilepton, * false otherwise */ inline constexpr bool is_anylepton(ParticleID id){ return ( is_lepton(id) || is_antilepton(id)); } /** * \brief Function to determine if particle is a neutrino * @param id PDG ID of particle * @returns true if the particle is a neutrino, false otherwise */ inline constexpr bool is_neutrino(ParticleID id){ return (id == pid::nu_e || id == pid::tau_neutrino || id == pid::muon_neutrino); } /** * \brief Function to determine if particle is an antineutrino * @param id PDG ID of particle * @returns true if the particle is an antineutrino, false otherwise */ inline constexpr bool is_antineutrino(ParticleID id){ return (id == pid::nu_e_bar || id == pid::nu_tau_bar || id == pid::nu_mu_bar); } /** * \brief Function to determine if particle is an (anti-)neutrino * @param id PDG ID of particle * @returns true if the particle is a neutrino or antineutrino, * false otherwise */ inline constexpr bool is_anyneutrino(ParticleID id){ return ( is_neutrino(id) || is_antineutrino(id)); } //! Check if a particle is massless inline constexpr bool is_massless(ParticleID id){ // cannot use `std::abs` because it's not `constexpr` const int abs_id = (id >= 0)?id:-id; switch(abs_id){ case pid::bottom: case pid::top: case pid::tau: case pid::Z: case pid::Z_photon_mix: case pid::Wp: case pid::Higgs: case pid::proton: return false; default: return true; } } //! Check if a particle is massive inline constexpr bool is_massive(ParticleID id){ return !is_massless(id); } /** * \brief Function to determine if particle is a charged lepton * @param id PDG ID of particle * @returns true if the particle is a charged lepton, false otherwise */ inline constexpr bool is_charged_lepton(ParticleID id){ return is_lepton(id) && !is_neutrino(id); } /** * \brief Function to determine if particle is a charged lepton * @param id PDG ID of particle * @returns true if the particle is a charged lepton, false otherwise */ inline constexpr bool is_charged_antilepton(ParticleID id){ return is_antilepton(id) && !is_antineutrino(id); } /** * \brief Function to determine if particle is a charged lepton or charged antilepton * @param id PDG ID of particle * @returns true if the particle is a charged lepton or charged antilepton, false otherwise */ inline constexpr bool is_charged_anylepton(ParticleID id){ return is_anylepton(id) && !is_anyneutrino(id); } + /** + * \brief Electric charge of the given particle + * @param id PDG ID of particle + * @returns The electric charge in units of the elementary charge + */ + boost::rational charge(ParticleID id); + } // namespace HEJ diff --git a/include/HEJ/Particle.hh b/include/HEJ/Particle.hh index 76b8065..a78e47f 100644 --- a/include/HEJ/Particle.hh +++ b/include/HEJ/Particle.hh @@ -1,287 +1,292 @@ /** * \file Particle.hh * \brief Contains the particle struct * * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2022 * \copyright GPLv2 or later */ #pragma once #include #include #include +#include "boost/rational.hpp" #include "fastjet/PseudoJet.hh" #include "HEJ/PDG_codes.hh" namespace HEJ { using Colour = std::pair; //! Class representing a particle struct Particle { //! particle type ParticleID type = pid::unspecified; //! particle momentum fastjet::PseudoJet p; //! (optional) colour & anti-colour std::optional colour; //! get rapidity double rapidity() const{ return p.rapidity(); } //! get transverse momentum double perp() const{ return p.perp(); } //! get transverse momentum double pt() const{ return perp(); } //! get momentum in x direction double px() const{ return p.px(); } //! get momentum in y direction double py() const{ return p.py(); } //! get momentum in z direction double pz() const{ return p.pz(); } //! get energy double E() const{ return p.E(); } //! get mass double m() const{ return p.m(); } }; //! Functor to compare rapidities /** * This can be used whenever a rapidity comparison function is needed, * for example in many standard library functions. * * @see pz_less */ struct rapidity_less{ template bool operator()(FourVector const & p1, FourVector const & p2){ return p1.rapidity() < p2.rapidity(); } }; //! Functor to compare momenta in z direction /** * This can be used whenever a pz comparison function is needed, * for example in many standard library functions. * * @see rapidity_less */ struct pz_less{ template bool operator()(FourVector const & p1, FourVector const & p2){ return p1.pz() < p2.pz(); } }; //! Convert a vector of Particles to a vector of particle momenta inline std::vector to_PseudoJet( std::vector const & v ){ std::vector result; result.reserve(v.size()); for(auto && sp: v) result.emplace_back(sp.p); return result; } //! Functor to compare particle type (PDG) /** * This can be used whenever a particle-type comparison is needed * for example in many standard library functions. */ struct type_less{ template bool operator()(Particle const & p1, Particle const & p2){ return p1.type < p2.type; } }; //! Check if the argument is an antiparticle inline constexpr bool is_antiparticle(Particle const & p){ return is_antiparticle(p.type); } //! Check if a particle is a parton, i.e. quark, antiquark, or gluon inline constexpr bool is_parton(Particle const & p){ return is_parton(p.type); } //! Check if a particle is a quark inline constexpr bool is_quark(Particle const & p){ return is_quark(p.type); } //! Check if a particle is an anti-quark inline constexpr bool is_antiquark(Particle const & p){ return is_antiquark(p.type); } //! Check if a particle is a quark or anit-quark inline constexpr bool is_anyquark(Particle const & p){ return is_anyquark(p.type); } /** * \brief Function to determine if particle is a lepton * @param p the particle * @returns true if the particle is a lepton, false otherwise */ inline constexpr bool is_lepton(Particle const & p){ return is_lepton(p.type); } /** * \brief Function to determine if particle is an antilepton * @param p the particle * @returns true if the particle is an antilepton, false otherwise */ inline constexpr bool is_antilepton(Particle const & p){ return is_antilepton(p.type); } /** * \brief Function to determine if particle is an (anti-)lepton * @param p the particle * @returns true if the particle is a lepton or antilepton, false otherwise */ inline constexpr bool is_anylepton(Particle const & p){ return is_anylepton(p.type); } /** * \brief Function to determine if particle is a neutrino * @param p the particle * @returns true if the particle is a neutrino, false otherwise */ inline constexpr bool is_neutrino(Particle const & p){ return is_neutrino(p.type); } /** * \brief Function to determine if particle is an antineutrino * @param p the particle * @returns true if the particle is an antineutrino, false otherwise */ inline constexpr bool is_antineutrino(Particle const & p){ return is_antineutrino(p.type); } /** * \brief Function to determine if particle is an (anti-)neutrino * @param p the particle * @returns true if the particle is a neutrino or antineutrino, false otherwise */ inline constexpr bool is_anyneutrino(Particle const & p){ return is_anyneutrino(p.type); } //! Check if a particle is massless inline constexpr bool is_massless(Particle const & p){ return is_massless(p.type); } //! Check if a particle is massive inline constexpr bool is_massive(Particle const & p){ return is_massive(p.type); } /** * \brief Function to determine if particle is a charged lepton * @param p the particle * @returns true if the particle is a charged lepton, false otherwise */ inline constexpr bool is_charged_lepton(Particle const & p){ return is_charged_lepton(p.type); } /** * \brief Function to determine if particle is a charged lepton * @param p the particle * @returns true if the particle is a charged lepton, false otherwise */ inline constexpr bool is_charged_antilepton(Particle const & p){ return is_charged_antilepton(p.type); } /** * \brief Function to determine if particle is a charged lepton or charged antilepton * @param p the particle * @returns true if the particle is a charged lepton or charged antilepton, false otherwise */ inline constexpr bool is_charged_anylepton(Particle const & p){ return is_charged_anylepton(p.type); } //! Check if a particle is a photon, W or Z boson inline constexpr bool is_AWZ_boson(Particle const & particle){ return is_AWZ_boson(particle.type); } //! Check if a particle is a photon, W, Z, or Higgs boson inline constexpr bool is_AWZH_boson(Particle const & particle){ return is_AWZH_boson(particle.type); } //! Extract all partons from a vector of particles inline std::vector filter_partons( std::vector const & v ){ std::vector result; result.reserve(v.size()); std::copy_if( begin(v), end(v), std::back_inserter(result), [](Particle const & p){ return is_parton(p); } ); return result; } //! Extract all AWZH bosons from a vector of particles inline std::vector filter_AWZH_bosons( std::vector const & v ){ std::vector result; std::copy_if( begin(v), end(v), std::back_inserter(result), [](Particle const & p){ return is_AWZH_boson(p); } ); return result; } + + //! Particle electric charge + boost::rational charge(Particle const & p); + } // namespace HEJ diff --git a/src/PDG_codes.cc b/src/PDG_codes.cc index 7c3ffe7..5b1787b 100644 --- a/src/PDG_codes.cc +++ b/src/PDG_codes.cc @@ -1,117 +1,147 @@ /** * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2020 * \copyright GPLv2 or later */ #include "HEJ/PDG_codes.hh" +#include #include #include "HEJ/exceptions.hh" namespace HEJ { ParticleID to_ParticleID(std::string const & name){ using namespace HEJ::pid; static const std::map known = { {"d", d}, {"down", down}, {"1",static_cast(1)}, {"u", u}, {"up", up}, {"2",static_cast(2)}, {"s", s}, {"strange", strange}, {"3",static_cast(3)}, {"c", c}, {"charm", charm}, {"4",static_cast(4)}, {"b", b}, {"bottom", bottom}, {"5",static_cast(5)}, {"t", t}, {"top", top}, {"6",static_cast(6)}, {"e", e}, {"electron", electron}, {"e-", e}, {"11",static_cast(11)}, {"nu_e", nu_e}, {"electron_neutrino", electron_neutrino}, {"electron-neutrino", electron_neutrino}, {"12",static_cast(12)}, {"mu", mu}, {"muon", muon}, {"mu-", mu}, {"13",static_cast(13)}, {"nu_mu", nu_mu}, {"muon_neutrino", muon_neutrino}, {"muon-neutrino", muon_neutrino}, {"14",static_cast(14)}, {"tau", tau}, {"tau-", tau}, {"15",static_cast(15)}, {"nu_tau", nu_tau}, {"tau_neutrino", tau_neutrino}, {"tau-neutrino", tau_neutrino}, {"16",static_cast(16)}, {"d_bar", d_bar}, {"antidown", antidown}, {"-1",static_cast(-1)}, {"u_bar", u_bar}, {"antiup", antiup}, {"-2",static_cast(-2)}, {"s_bar", s_bar}, {"antistrange", antistrange}, {"-3",static_cast(-3)}, {"c_bar", c_bar}, {"anticharm", anticharm}, {"-4",static_cast(-4)}, {"b_bar", b_bar}, {"antibottom", antibottom}, {"-5",static_cast(-5)}, {"t_bar", t_bar}, {"antitop", antitop}, {"-6",static_cast(-6)}, {"e_bar", e_bar}, {"antielectron", antielectron}, {"positron", positron}, {"e+", e_bar}, {"-11",static_cast(-11)}, {"nu_e_bar", nu_e_bar}, {"electron_antineutrino", electron_antineutrino}, {"electron-antineutrino", electron_antineutrino}, {"-12",static_cast(-12)}, {"mu_bar", mu_bar}, {"mu+", mu_bar}, {"antimuon", antimuon}, {"-13",static_cast(-13)}, {"nu_mu_bar", nu_mu_bar}, {"muon_antineutrino", muon_antineutrino}, {"muon-antineutrino", muon_antineutrino}, {"-14",static_cast(-14)}, {"tau_bar", tau_bar}, {"tau+", tau_bar}, {"antitau", antitau}, {"-15",static_cast(-15)}, {"nu_tau_bar", nu_tau_bar}, {"tau_antineutrino", tau_antineutrino}, {"tau-antineutrino", tau_antineutrino}, {"-16",static_cast(-16)}, {"gluon", gluon}, {"g", g}, {"21",static_cast(21)}, {"photon", photon}, {"gamma", gamma}, {"22",static_cast(22)}, {"Z", Z}, {"23",static_cast(23)}, {"Z_photon_mix", Z_photon_mix}, {"Z_gamma_mix", Z_gamma_mix}, {"Z/photon superposition",Z_photon_mix}, {"81",static_cast(81)}, {"Wp", Wp}, {"W+", Wp}, {"24",static_cast(24)}, {"Wm", Wm}, {"W-", Wm}, {"-24",static_cast(-24)}, {"h", h}, {"H", h}, {"Higgs", Higgs}, {"higgs", higgs}, {"25",static_cast(25)}, {"p", p}, {"proton", proton}, {"2212",static_cast(2212)}, {"p_bar", p_bar}, {"antiproton", antiproton}, {"-2212",static_cast(-2212)} }; const auto res = known.find(name); if(res == known.end()){ throw std::invalid_argument("Unknown particle " + name); } return res->second; } namespace pid { std::string name(ParticleID id) { using namespace HEJ::pid; switch (id) { case unspecified: return "unspecified"; case down: return "down"; case up: return "up"; case strange: return "strange"; case charm: return "charm"; case bottom: return "bottom"; case top: return "top"; case electron: return "electron"; case muon: return "muon"; case tau: return "tau"; case electron_neutrino: return "electron-neutrino"; case muon_neutrino: return "muon-neutrino"; case tau_neutrino: return "tau-neutrino"; case antidown: return "antidown"; case antiup: return "antiup"; case antistrange: return "antistrange"; case anticharm: return "anticharm"; case antibottom: return "antibottom"; case antitop: return "antitop"; case positron: return "positron"; case antimuon: return "antimuon"; case antitau: return "antitau"; case electron_antineutrino: return "electron-antineutrino"; case muon_antineutrino: return "muon-antineutrino"; case tau_antineutrino: return "tau-antineutrino"; case gluon: return "gluon"; case photon: return "photon"; case Z: return "Z"; case Z_photon_mix: return "Z/photon superposition"; case Wp: return "W+"; case Wm: return "W-"; case Higgs: return "Higgs"; case proton: return "proton"; case antiproton: return "antiproton"; } throw std::logic_error{"unreachable"}; } ParticleID anti(ParticleID const id){ return static_cast(-id); } } // namespace pid + + boost::rational charge(ParticleID id) { + using Ratio = boost::rational; + using namespace pid; + if(is_antiparticle(id)) return -charge(anti(id)); + switch(id) { + case electron: + case muon: + case tau: + return Ratio{-1}; + + case down: + case strange: + case bottom: + return Ratio{-1, 3}; + + case up: + case charm: + case top: + return Ratio{2, 3}; + + case Wp: + case proton: + return Ratio{1}; + default: + return Ratio{0}; + } + } + } // namespace HEJ diff --git a/src/Particle.cc b/src/Particle.cc new file mode 100644 index 0000000..7e21860 --- /dev/null +++ b/src/Particle.cc @@ -0,0 +1,8 @@ +#include "HEJ/Particle.hh" +#include + +namespace HEJ { + boost::rational charge(Particle const & p){ + return charge(p.type); + } +}