file src/ProcessCatalog.cpp

[No description available] More…

Namespaces

Name
Gambit
TODO: see if we can use this one:
Gambit::DarkBit

Detailed Description

Author: Pat Scott (p.scott@imperial.ac.uk)

Date: 2015 Mar

Implementation file for DarkBit Process Catalog constituents types.


Authors (add name and date if you modify):


Source code

//   GAMBIT: Global and Modular BSM Inference Tool
//   *********************************************
///  \file
///
///  Implementation file for DarkBit Process
///  Catalog constituents types.
///
///  *********************************************
///
///  Authors (add name and date if you modify):
///
///  \author Pat Scott
///          (p.scott@imperial.ac.uk)
///  \date 2015 Mar
///
///  *********************************************

#include "gambit/Elements/gambit_module_headers.hpp"
#include "gambit/DarkBit/DarkBit_rollcall.hpp"
#include "gambit/DarkBit/ProcessCatalog.hpp"

//#define DARKBIT_DEBUG

namespace Gambit {
  namespace DarkBit {


    // TH_ParticleProperty definitions

    TH_ParticleProperty::TH_ParticleProperty(double mass, unsigned int spin2)
      : mass(mass), spin2(spin2)
    {}


    // TH_Channel definitions

    /// Constructor
    TH_Channel::TH_Channel(std::vector<str> finalStateIDs, daFunk::Funk genRate)
      :  finalStateIDs(finalStateIDs), nFinalStates(finalStateIDs.size()),
      genRate(genRate)
    {
      if ( nFinalStates < 2 )
      {
        DarkBit_error().raise(LOCAL_INFO, "Need at least two final state particles.");
      }
    }

    /// Print information about this channel.
    void TH_Channel::printChannel() const
    {
      logger() << "Channel: ";
      for ( auto it = finalStateIDs.begin(); it != finalStateIDs.end(); it++ )
      {
        logger() << *it << " ";
      }
      logger() << EOM;
    }

    /*! \brief Indicate whether or not the final states of this channel contain
     * a specific particle.
     */
    bool TH_Channel::channelContains(str p) const
    {
      return std::find(finalStateIDs.begin(),
          finalStateIDs.end(), p) != finalStateIDs.end();
    }

    /*! \brief Indicate whether or not this channel is the one defined by some
     * specific final states.  Particle name version.
     */
    bool TH_Channel::isChannel(str p0, str p1, str p2, str p3) const
    {
      str vals[] = {p0, p1};
      std::vector<str> inIDs(std::begin(vals), std::end(vals));
      if (p2 != "") inIDs.push_back(p2);
      if (p3 != "") inIDs.push_back(p3);
      return isChannel(inIDs);
    }

    /*! \brief Indicate whether or not this channel is the one defined by some
     * specific final states.  Particle vector version.
     */
    bool TH_Channel::isChannel(std::vector<str> particles) const
    {
      if (particles.size() != finalStateIDs.size()) return false;
      return std::is_permutation(
          finalStateIDs.begin(), finalStateIDs.end(), particles.begin());
    }


    // TH_Process definitions

    /// Constructor for decay process
    TH_Process::TH_Process(const str & particle1ID)
      : isAnnihilation (false),
      particle1ID    (particle1ID),
      particle2ID    (""),
      genRateMisc    (daFunk::zero())
    {}

    /// Constructor for annihilation process
    TH_Process::TH_Process(const str & particle1ID, const str & particle2ID)
      : isAnnihilation (true),
      particle1ID(particle1ID),
      particle2ID(particle2ID),
      genRateMisc(daFunk::zero("v"))
    {
      if (particle1ID.compare(particle2ID) > 0)
      {
        DarkBit_error().raise(LOCAL_INFO,
            "Particle identifiers should be in alphabetical order.");
      }
    }

    /// Compare initial states
    bool TH_Process::isProcess(const str & p1, const str & p2) const
    {
      sspair candidate_process(p1, p2);
      sspair this_process(this->particle1ID, this->particle2ID);
      return candidate_process == this_process;
    }

    /// Check for given channel.  Return a pointer to it if found, NULL if not.
    const TH_Channel* TH_Process::find(std::vector<str> final_states) const
    {
      for (auto it = channelList.begin(); it != channelList.end(); ++it)
      {
        if (it->isChannel(final_states)) return &(*it);
      }
      return NULL;
    }


    // TH_ProcessCatalog definitions

    /// Retrieve a specific process from the catalog
    TH_Process TH_ProcessCatalog::getProcess(str id1, str id2) const
    {
      const TH_Process* temp = find(id1, id2);
      if (temp == NULL)
      {
        DarkBit_error().raise(LOCAL_INFO,
            "Process with initial states " + id1 + " " + id2 + " missing.");
      }
      return *temp;
    }

    /// Check for a specific process in the catalog
    const TH_Process* TH_ProcessCatalog::find(str id1, str id2) const
    {
      for (std::vector<TH_Process>::const_iterator it = processList.begin();
          it != processList.end(); ++it)
      {
        if ( it -> isProcess(id1, id2) ) return &(*it);
      }
      return NULL;
    }

    /*! \brief Retrieve properties of a given particle involved in one or more
     * processes in this catalog
     */
    TH_ParticleProperty TH_ProcessCatalog::getParticleProperty(str id) const
    {
      auto it = particleProperties.find(id);
      if ( it == particleProperties.end() )
      {
        DarkBit_error().raise(LOCAL_INFO,
            "Cannot find entry for " + id +
            " in particleProperties of TH_ProcessCatalog.");
      }
      return it->second;
    }

    bool TH_ProcessCatalog::hasParticleProperty(str id) const
    {
      auto it = particleProperties.find(id);
      return (it != particleProperties.end());
    }


    void TH_ProcessCatalog::validate()
    {
#ifdef DARKBIG_DEBUG
      std::cout << std::endl;
      std::cout << "********************************" << std::endl;
      std::cout << "*** Validate Process catalog ***" << std::endl;
      std::cout << "********************************" << std::endl;
      std::cout << std::endl;
#endif

      for (auto it = processList.begin(); it != processList.end(); it++)
      {
        if (it->isAnnihilation) // Annihilation
        {
          std::string p1ID = it->particle1ID;
          std::string p2ID = it->particle2ID;
          double m1 = getParticleProperty(p1ID).mass;
          double m2 = getParticleProperty(p2ID).mass;
          double E_in = m1 + m2;
#ifdef DARKBIT_DEBUG
          std::cout << "Annihilation process for: " << p1ID << " " << p2ID << std::endl;
          std::cout << "  Masses (GeV): " << m1 << " " << m2 << std::endl;
#endif

          if ((it->genRateMisc->getNArgs() != 1) or not(it->genRateMisc->hasArg("v")))
            DarkBit_error().raise(LOCAL_INFO,
                "Invalid TH_ProcessCatalog annihilation entry for " + it->particle1ID + " " + it->particle2ID + "\n"
                "  genRateMisc must have relative velocity v as only argument.");

#ifdef DARKBIT_DEBUG
          std::cout << "  genRateMisc(v=0) = " << it->genRateMisc->bind("v")->eval(0) << std::endl;
#endif

          for (auto it2 = it->channelList.begin(); it2 != it->channelList.end(); it2++)
          {
            double E_out = 0;
            std::string outstring = "";
            for (size_t i = 0; i < it2->finalStateIDs.size(); i++)
            {
              E_out += getParticleProperty(it2->finalStateIDs[i]).mass;
              outstring += it2->finalStateIDs[i] + " ";
            }
#ifdef DARKBIT_DEBUG
            std::cout << "  Channel: " << outstring << std::endl;
            std::cout << "    Total mass: " << E_out << std::endl;
#endif
            if (it2->nFinalStates != it2->finalStateIDs.size())
              DarkBit_error().raise(LOCAL_INFO,
                  "Invalid TH_ProcessCatalog annihilation entry for " + it->particle1ID + " " + it->particle2ID + "\n"
                  "  inconsistent nFinalStates entry for final states " + outstring);
            if ((it2->finalStateIDs.size() < 2) or (it2->finalStateIDs.size() > 3))
              DarkBit_error().raise(LOCAL_INFO,
                "Invalid TH_ProcessCatalog annihilation entry for " + it->particle1ID + " " + it->particle2ID + "\n"
                "  number of final states not supported for annihilation into " + outstring);
            if (it2->finalStateIDs.size() == 2)
              if ((it2->genRate->getNArgs() != 1) or not it2->genRate->hasArg("v"))
                DarkBit_error().raise(LOCAL_INFO,
                  "Invalid TH_ProcessCatalog annihilation entry for " + it->particle1ID + " " + it->particle2ID + "\n"
                  "  genRate must have relative velocity v as only argument for annihilation into " + outstring);
            if (it2->finalStateIDs.size() == 3)
              if (it2->genRate->getNArgs() != 3 or not it2->genRate->hasArg("E") or not it2->genRate->hasArg("E1") or not it2->genRate->hasArg("v"))
                DarkBit_error().raise(LOCAL_INFO,
                  "Invalid TH_ProcessCatalog annihilation entry for " + it->particle1ID + " " + it->particle2ID + "\n"
                  "  genRate must have three arguments (v, E and E1) for annihilation into " + outstring);
            if ((it2->finalStateIDs.size() == 3) and E_out > E_in)
            {
              // TODO: This could be defined more generally (allowing three-body final states that are closed for v=0)
              DarkBit_error().raise(LOCAL_INFO,
                "Invalid TH_ProcessCatalog annihilation entry for " + it->particle1ID + " " + it->particle2ID + "\n"
                "  three-body final states kinematically not allowed for v=0 for annihilation into " + outstring);
            }
            // Test whether channels kinematically closed for v=0 are indeed closed
            if ((it2->finalStateIDs.size() == 2) and (E_out > E_in))
            {
              double v_min = sqrt(1-1/pow(E_out/E_in,2));
              if ( it2->genRate->bind("v")->eval(v_min*0.999) != 0 )
                DarkBit_error().raise(LOCAL_INFO,
                  "Invalid TH_ProcessCatalog annihilation entry for " + it->particle1ID + " " + it->particle2ID + "\n"
                  "  genRate must be zero for values of v that are below kinematic threshold for annihilation into " + outstring);
            }
#ifdef DARKBIT_DEBUG
            if (it2->finalStateIDs.size() == 2)
              std::cout << "    genRate(v=0) = " << it2->genRate->bind("v")->eval() << std::endl;
            else
              std::cout << "    genRate(v=0) = f(E, E1)" << std::endl;
#endif
          }
        }
        else // Decay
        {
          double E_in = getParticleProperty(it->particle1ID).mass;

#ifdef DARKBIT_DEBUG
          std::cout << "Decay process for: " << it->particle1ID << std::endl;
          std::cout << "  Mass (GeV): " << E_in << std::endl;
          std::cout << "  genRateMisc = " << it->genRateMisc->bind()->eval() << std::endl;
#endif

          if (it->genRateMisc->getNArgs() != 0)
            DarkBit_error().raise(LOCAL_INFO,
                "Invalid TH_ProcessCatalog decay entry for " + it->particle1ID + "\n"
                "  genRateMisc must have zero arguments.");
          for (auto it2 = it->channelList.begin(); it2 != it->channelList.end(); it2++)
          {
            double E_out = 0;
            std::string outstring = "";
            for (size_t i = 0; i < it2->finalStateIDs.size(); i++)
            {
              E_out += getParticleProperty(it2->finalStateIDs[i]).mass;
              outstring += it2->finalStateIDs[i] + " ";
            }
#ifdef DARKBIT_DEBUG
            std::cout << "  Channel: " << outstring << std::endl;
            std::cout << "    Total mass: " << E_out << std::endl;
#endif
            if (it2->nFinalStates != it2->finalStateIDs.size())
              DarkBit_error().raise(LOCAL_INFO,
                  "Invalid TH_ProcessCatalog decay entry for " + it->particle1ID + "\n"
                  "  inconsistent nFinalStates entry for final states " + outstring);
            if ((it2->finalStateIDs.size() < 2) or (it2->finalStateIDs.size() > 3))
              DarkBit_error().raise(LOCAL_INFO,
                "Invalid TH_ProcessCatalog decay entry for " + it->particle1ID + "\n"
                "  number of final states not supported for decay into " + outstring);
            if (it2->finalStateIDs.size() == 2)
              if (it2->genRate->getNArgs() != 0)
                DarkBit_error().raise(LOCAL_INFO,
                  "Invalid TH_ProcessCatalog decay entry for " + it->particle1ID + "\n"
                  "  genRate must have zero arguments for decay into " + outstring);
            if (it2->finalStateIDs.size() == 3)
              if (it2->genRate->getNArgs() != 2 or not it2->genRate->hasArg("E") or not it2->genRate->hasArg("E1"))
                DarkBit_error().raise(LOCAL_INFO,
                  "Invalid TH_ProcessCatalog decay entry for " + it->particle1ID + "\n"
                  "  genRate must have two arguments (E and E1) for decay into " + outstring);
            if (E_out > E_in)
              DarkBit_error().raise(LOCAL_INFO,
                "Invalid TH_ProcessCatalog decay entry for " + it->particle1ID + "\n"
                "  kinematically forbidden decay into " + outstring);
#ifdef DARKBIT_DEBUG
            if (it2->finalStateIDs.size() == 2)
              std::cout << "    genRate = " << it2->genRate->bind()->eval() << std::endl;
            else
              std::cout << "    genRate = f(E, E1)" << std::endl;
#endif
          }
        }
      }
#ifdef DARKBIT_DEBUG
      std::cout << std::endl;
      std::cout << "*****************" << std::endl;
      std::cout << "*** Validated ***" << std::endl;
      std::cout << "*****************" << std::endl;
      std::cout << std::endl;
#endif
    }
  } // namespace DarkBit
} // namespace Gambit

#undef DARKBIT_DEBUG

Updated on 2024-07-18 at 13:53:34 +0000