diff --git a/Changes-API.md b/Changes-API.md index 86be069..b78cc9b 100644 --- a/Changes-API.md +++ b/Changes-API.md @@ -1,130 +1,132 @@ # Changelog for HEJ API This log lists only changes on the HEJ API. These are primarily code changes relevant for calling HEJ as an API. This file should only be read as an addition to [`Changes.md`](Changes.md), where the main features are documented. ## Version 2.2 ### 2.2.0 #### New and updated functions +* New functions to decide whether particles are massive, charged, + charged leptons, antiparticles. * Updated function `Event::EventData.reconstruct_intermediate()` - Now requires an `EWConstants` argument - Added support for WpWp and WmWm events. - In the case of WW same-flavour the reconstruction will minimise the total off-shell momentum. * Renamed `no_2_jets` error flag to `not_enough_jets`. * Added helper functions `is_backward_g_to_h`, `is_forward_g_to_h` to detect incoming gluon to outgoing Higgs transitions. * Updated function `implemented_types()` to now be in HEJ namespace. ## Version 2.1 ### 2.1.0 #### Changes to Event class * Restructured `Event` class - `Event` can now only be build from a (new) `Event::EventData` class - Removed default constructor for `Event` - `Event::EventData` replaces the old `UnclusteredEvent` struct. - `UnclusteredEvent` is now **deprecated**, and will be removed in version 2.2.0 - Removed `Event.unclustered()` function - Added new member function `Events.parameters()`, to directly access (underlying) `Parameters` - New member functions `begin_partons`, `end_partons` (`rbegin_partons`, `rend_partons`) with aliases `cbegin_partons`, `cend_partons` (`crbegin_partons`, `crend_partons`) for constant (reversed) iterators over outgoing partons. * New function `Event::EventData.reconstruct_intermediate()` to reconstruct bosons from decays, e.g. `positron + nu_e => Wp` * Added optional Colour charges to particles (`Particle.colour`) - Colour connection in the HEJ limit can be generated via `Event.generate_colours` (automatically done in the resummation) - Colour configuration of input events can be checked with `Event.is_leading_colour` * Added function `Event.valid_hej_state` to check if event _could have_ been produced by `HEJ` according to the `soft pt regulator` cut on the jets #### New and updated functions * Renamed `EventType::nonHEJ` to `EventType::non_resummable` and `is_HEJ()` to `is_resummable()` such that run card is consistent with internal workings * Made `MatrixElement.tree_kin(...)` and `MatrixElement.tree_param(...)` public * New `EventReweighter` member function `treatment` to query the treatment with respect to resummation for the various event types. * Added auxiliary functions to obtain a `std::string` from `EventDescription` (`to_string` for human readable, and `to_simple_string` for easy parsable string) * New `get_analyses` function to read in multiple `HEJ::Analysis` at once, similar to `get_analysis` * New `get_ew_parameters` function to extract electroweak parameters from YAML configuration. #### New classes * New class `Unweighter` to do unweighting * New class `CrossSectionAccumulator` to keep track of Cross Section of the different subprocess * New template struct `Parameters` similar to old `Weights` - `Weights` are now an alias for `Parameters`. Calling `Weights` did not change - `Weights.hh` was replaced by `Parameters.hh`. The old `Weights.hh` header will be removed in version 2.2.0 * Function to multiplication and division of `EventParameters.weight` by double - This can be combined with `Parameters`, e.g. `Parameters*Weights`, see also `Events.parameters()` - Moved `EventParameters` to `Parameters.hh` header * new class `EWConstants` replaces previously hard coded `vev` - `EWConstants` have to be set in the general `Config` and the `MatrixElementConfig` #### Input/Output * New abstract `EventReader` class, as base for reading events from files - Moved LHE file reader to `HEJ::LesHouchesReader` * New (optional) function `finish()` in abstract class `EventWriter`. `finish()` is called _after_ all events are written. * Support reading (`HDF5Reader`) and writing (`HDF5Writer`) `hdf5` files * New `BufferedEventReader` class that allows to put events back into the reader. * New `SherpaLHEReader` to read Sherpa LHE files with correct weights * `get_analysis` now requires `YAML::Node` and `LHEF::HEPRUP` as arguments * Replaced `HepMCInterface` and `HepMCWriter` by `HepMCInterfaceX` and `HepMCWriterX` respectively, with `X` being the major version of HepMC (2 or 3) - Renamed `HepMCInterfaceX::init_kinematics` to `HepMCInterfaceX::init_event` and protected it, use `HepMCInterfaceX::operator()` instead - Removed redundant `HepMCInterfaceX::add_variation` function #### Linking * Export cmake target `HEJ::HEJ` to link directly against `libHEJ` * Preprocessor flags (`HEJ_BUILD_WITH_XYZ`) for enabled/disabled dependencies are now written to `ConfigFlags.hh` * Provide links to version specific object files, e.g. `libHEJ.so -> libHEJ.so.2.1 (soname) -> libHEJ.so.2.1.0` * Removed `LHAPDF` from public interface #### Miscellaneous * Capitalisation of `Config.hh` now matches class `Config` (was `config.hh`) * Renamed `Config::max_ext_soft_pt_fraction` to `Config::soft_pt_regulator`. The new `Config::soft_pt_regulator` parameter is optional and the old `Config::max_ext_soft_pt_fraction` is **deprecated**. * Replaced redundant member `EventReweighterConfig::jet_param` with getter function `EventReweighter.jet_param()` (`JetParameters` are already in `PhaseSpacePointConfig`) * Avoid storing reference to the Random Number Generator inside classes - Constructors of `EventReweighter` now expect `std::shared_ptr` (was reference) - Moved reference to `HEJ::RNG` from constructor of `JetSplitter` to `JetSplitter.split` ## Version 2.0 ### 2.0.4 * Fixed wrong path of `HEJ_INCLUDE_DIR` in `hej-config.cmake` ### 2.0.0 * First release diff --git a/include/HEJ/PDG_codes.hh b/include/HEJ/PDG_codes.hh index f520144..381c006 100644 --- a/include/HEJ/PDG_codes.hh +++ b/include/HEJ/PDG_codes.hh @@ -1,268 +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 62e70da..a78e47f 100644 --- a/include/HEJ/Particle.hh +++ b/include/HEJ/Particle.hh @@ -1,251 +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); + } +}