Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:19:20

0001 // -*- C++ -*-
0002 //
0003 // This file is part of LHAPDF
0004 // Copyright (C) 2012-2024 The LHAPDF collaboration (see AUTHORS for details)
0005 //
0006 #pragma once
0007 #ifndef LHAPDF_PDF_H
0008 #define LHAPDF_PDF_H
0009 
0010 #include "LHAPDF/PDFInfo.h"
0011 #include "LHAPDF/PDFIndex.h"
0012 #include "LHAPDF/Factories.h"
0013 #include "LHAPDF/AlphaS.h"
0014 #include "LHAPDF/Utils.h"
0015 #include "LHAPDF/Paths.h"
0016 #include "LHAPDF/Exceptions.h"
0017 #include "LHAPDF/Version.h"
0018 #include "LHAPDF/Config.h"
0019 
0020 namespace LHAPDF {
0021 
0022 
0023   /// @defgroup partonids Parton ID codes
0024   /// @{
0025   /// Convenience/clarity enum for specifying parton IDs
0026   namespace PIDs { //< for scoping to avoid conflicts, e.g. PID::GLUON rather than just GLUON
0027     enum PIDCode {
0028       ATOP = -6, ABOTTOM = -5, ACHARM = -4, ASTRANGE = -3, AUP = -2, ADOWN = -1,
0029       GLUON = 0, // equivalent to 21
0030       DOWN = 1, UP = 2, STRANGE = 3, CHARM = 4, BOTTOM = 5, TOP = 6
0031     };
0032   }
0033   /// @}
0034 
0035 
0036 
0037   /// @brief PDF is the general interface for access to parton density information.
0038   ///
0039   /// The PDF interface declares the general form of all PDF types, such as Grid based or analytic.
0040   class PDF {
0041   protected: //< These constructors should only be called by subclasses
0042 
0043     /// Internal convenience typedef for the AlphaS object handle
0044     typedef unique_ptr<AlphaS> AlphaSPtr;
0045 
0046     /// Force initialization of the only non-class member.
0047     PDF() : _forcePos(0) { }
0048 
0049 
0050   public:
0051 
0052     /// Virtual destructor, to allow unfettered inheritance
0053     virtual ~PDF() { }
0054 
0055 
0056   protected:
0057 
0058 
0059     /// @name Helper methods for info loading / path setting, used by derived types
0060     ///@{
0061 
0062     void _loadInfo(const std::string& mempath);
0063 
0064     void _loadInfo(const std::string& setname, int member) {
0065       const string searchpath = findpdfmempath(setname, member);
0066       if (searchpath.empty())
0067         throw UserError("Can't find a valid PDF " + setname + "/" + to_str(member));
0068       _loadInfo(searchpath);
0069     }
0070 
0071     void _loadInfo(int lhaid) {
0072       const pair<string,int> setname_memid = lookupPDF(lhaid);
0073       if (setname_memid.second == -1)
0074         throw IndexError("Can't find a PDF with LHAPDF ID = " + to_str(lhaid));
0075       _loadInfo(setname_memid.first, setname_memid.second);
0076     }
0077 
0078     ///@}
0079 
0080 
0081   public:
0082 
0083     /// @name PDF values
0084     ///@{
0085 
0086     /// @brief Get the PDF xf(x) value at (x,q2) for the given PID.
0087     ///
0088     /// All grids are defined in Q2 rather than Q since the natural value
0089     /// in MC programs is squared, so we typically avoid an expensive sqrt() call.
0090     ///
0091     /// @param id PDG parton ID
0092     /// @param x Momentum fraction
0093     /// @param q2 Squared energy (renormalization) scale
0094     /// @return The value of xf(x,q2)
0095     double xfxQ2(int id, double x, double q2) const;
0096 
0097 
0098     /// @brief Get the PDF xf(x) value at (x,q) for the given PID.
0099     ///
0100     /// xfxQ will square the given q and return the value from xfxQ2.
0101     /// All grids are defined in q2 rather than q since the natural value
0102     /// in MC programs is squared, so we typically avoid an expensive sqrt() call.
0103     ///
0104     /// @param id PDG parton ID
0105     /// @param x Momentum fraction
0106     /// @param q Energy (renormalization) scale
0107     /// @return The value of xf(x,q2)
0108     double xfxQ(int id, double x, double q) const {
0109       return xfxQ2(id, x, q*q);
0110     }
0111 
0112 
0113     /// @brief Get the PDF xf(x) value at (x,q2) for all supported PIDs.
0114     ///
0115     /// This version fills a user-supplied map to avoid container construction
0116     /// costs on every call.
0117     ///
0118     /// @param x Momentum fraction
0119     /// @param q2 Squared energy (renormalization) scale
0120     /// @param rtn Map of PDF xf(x,q2) values, to be filled
0121     void xfxQ2(double x, double q2, std::map<int, double>& rtn) const;
0122 
0123 
0124     /// @brief Get the PDF xf(x) value at (x,q) for all supported PIDs.
0125     ///
0126     /// This version fills a user-supplied map to avoid container construction
0127     /// costs on every call.
0128     ///
0129     /// @param x Momentum fraction
0130     /// @param q Energy (renormalization) scale
0131     /// @param rtn Map of PDF xf(x,q) values, to be filled
0132     void xfxQ(double x, double q, std::map<int, double>& rtn) const {
0133       xfxQ2(x, q*q, rtn);
0134     }
0135 
0136 
0137     /// @brief Get the PDF xf(x) value at (x,q2) for "standard" PIDs.
0138     ///
0139     /// This version fills a user-supplied vector to avoid container
0140     /// construction costs on every call.
0141     ///
0142     /// The filled vector follows the LHAPDF5 convention, with 13 entries
0143     /// running in the PDF ID order [-6, -5, ..., -1, 21, 1, ... 5, 6], i.e.
0144     /// quark PDF values will be at vector index pid+6 and the gluon at index 6.
0145     ///
0146     /// @param x Momentum fraction
0147     /// @param q2 Squared energy (renormalization) scale
0148     /// @param rtn Vector of PDF xf(x,q2) values, to be filled
0149     void xfxQ2(double x, double q2, std::vector<double>& rtn) const;
0150 
0151 
0152     /// @brief Get the PDF xf(x) value at (x,q) for "standard" PIDs.
0153     ///
0154     /// This version fills a user-supplied vector to avoid container
0155     /// construction costs on every call.
0156     ///
0157     /// The filled vector follows the LHAPDF5 convention, with 13 entries
0158     /// running in the PDF ID order [-6, -5, ..., -1, 21, 1, ... 5, 6], i.e.
0159     /// quark PDF values will be at vector index pid+6 and the gluon at index 6.
0160     ///
0161     /// @param x Momentum fraction
0162     /// @param q Energy (renormalization) scale
0163     /// @param rtn Vector of PDF xf(x,q) values, to be filled
0164     void xfxQ(double x, double q, std::vector<double>& rtn) const {
0165       xfxQ2(x, q*q, rtn);
0166     }
0167 
0168 
0169     /// @brief Get the PDF xf(x) value at (x,q2) for all supported PIDs.
0170     ///
0171     /// This version creates a new map on every call: prefer to use the
0172     /// fill-in-place version with a user-supplied map for many calls.
0173     ///
0174     /// @param x Momentum fraction
0175     /// @param q2 Squared energy (renormalization) scale
0176     /// @return A map of PDF xf(x,q2) values
0177     std::map<int, double> xfxQ2(double x, double q2) const;
0178 
0179     /// @brief Get the PDF xf(x) value at (x,q) for all supported PIDs.
0180     ///
0181     /// This version creates a new map on every call: prefer to use the
0182     /// fill-in-place version with a user-supplied map for many calls.
0183     ///
0184     /// xfxQ will square the given q and return the value from xfxQ2.
0185     /// All grids are defined in q2 rather than q since the natural value
0186     /// in MC programs is squared, so we typically avoid an expensive sqrt() call.
0187     ///
0188     /// @param x Momentum fraction
0189     /// @param q Energy (renormalization) scale
0190     /// @return A map of PDF xf(x,q) values
0191     std::map<int, double> xfxQ(double x, double q) const {
0192       return xfxQ2(x, q*q);
0193     }
0194 
0195 
0196   protected:
0197 
0198     /// @brief Calculate the PDF xf(x) value at (x,q2) for the given PID.
0199     ///
0200     /// This is the key function to be overridden in concrete PDF types, since
0201     /// it actually does the calculation of xf(x,Q2) by analytic, interpolation,
0202     /// or other means. The user-called xfxQ2 method exists so that the physical
0203     /// range and PID checks need only be done in one place, rather than need to
0204     /// be re-implemented in each concrete implementation.
0205     ///
0206     /// @param id Parton ID in the PDG scheme
0207     /// @param x Momentum fraction
0208     /// @param q2 Squared energy (renormalization) scale
0209     /// @return the value of xf(x,q2)
0210     virtual double _xfxQ2(int id, double x, double q2) const = 0;
0211 
0212     virtual void _xfxQ2(double x, double q2, std::vector<double>& ret) const = 0;
0213 
0214     ///@}
0215 
0216 
0217   public:
0218 
0219     /// @name Ranges of validity
0220     ///@{
0221 
0222     /// Minimum valid x value for this PDF.
0223     virtual double xMin() {
0224       if (info().has_key("XMin"))
0225         return info().get_entry_as<double>("XMin");
0226       return numeric_limits<double>::epsilon();
0227     }
0228 
0229     /// Maximum valid x value for this PDF.
0230     virtual double xMax() {
0231       if (info().has_key("XMax"))
0232         return info().get_entry_as<double>("XMax");
0233       return 1.0;
0234     }
0235 
0236     /// Minimum valid Q value for this PDF (in GeV).
0237     /// @note This function calls sqrt(q2Min()). For better CPU efficiency and accuracy use q2Min() directly.
0238     virtual double qMin() {
0239       return info().get_entry_as<double>("QMin", 0);
0240     }
0241 
0242     /// @brief Maximum valid Q value for this PDF (in GeV).
0243     /// @note This function calls sqrt(q2Max()). For better CPU efficiency and accuracy use q2Max() directly.
0244     virtual double qMax() {
0245       return info().get_entry_as<double>("QMax", numeric_limits<double>::max());
0246     }
0247 
0248     /// Minimum valid Q2 value for this PDF (in GeV2).
0249     virtual double q2Min() {
0250       return sqr(this->qMin());
0251     }
0252 
0253     /// Maximum valid Q2 value for this PDF (in GeV2).
0254     virtual double q2Max() {
0255       // Explicitly re-access this from the info, to avoid an overflow from squaring double_max
0256       return (info().has_key("QMax")) ? sqr(info().get_entry_as<double>("QMax")) : numeric_limits<double>::max();
0257     }
0258 
0259 
0260     /// @brief Check whether the PDF is set to only return positive (definite) values or not.
0261     ///
0262     /// This is to avoid overshooting in to negative values when
0263     /// interpolating/extrapolating PDFs that sharply decrease towards zero.
0264     /// 0 = unforced, 1 = forced positive, 2 = forced positive definite (>= 1e-10)
0265     int forcePositive() const {
0266       if (_forcePos < 0) //< Caching
0267         _forcePos = info().get_entry_as<unsigned int>("ForcePositive", 0);
0268       return _forcePos;
0269     }
0270     /// @brief Set whether the PDF will only return positive (definite) values or not.
0271     void setForcePositive(int mode) {
0272       _forcePos = mode;
0273     }
0274 
0275 
0276     /// @brief Check whether the given x is physically valid
0277     ///
0278     /// Returns false for x less than 0 or greater than 1, since it
0279     /// is a momentum fraction and not valid outside those values.
0280     bool inPhysicalRangeX(double x) const {
0281       return x >= 0.0 && x <= 1.0;
0282     }
0283 
0284     /// @brief Check whether the given Q2 is physically valid
0285     ///
0286     /// Returns false for Q2 less than 0 (Q must be real-valued).
0287     bool inPhysicalRangeQ2(double q2) const {
0288       return q2 >= 0.0;
0289     }
0290 
0291     /// @brief Check whether the given Q is physically valid
0292     ///
0293     /// Returns false for Q less than 0 (Q must be positive).
0294     bool inPhysicalRangeQ(double q) const {
0295       return inPhysicalRangeQ2(q*q);
0296     }
0297 
0298     /// Check whether the given (x,Q2) is physically valid
0299     bool inPhysicalRangeXQ2(double x, double q2) const {
0300       return inPhysicalRangeX(x) && inPhysicalRangeQ2(q2);
0301     }
0302 
0303     /// Check whether the given (x,Q) is physically valid
0304     bool inPhysicalRangeXQ(double x, double q) const {
0305       return inPhysicalRangeX(x) && inPhysicalRangeQ(q);
0306     }
0307 
0308     /// @brief Grid range check for Q
0309     ///
0310     /// Return true when given Q is in the coverage range of this PDF.
0311     /// It actually squares the given Q and returns value from inRangeQ2.
0312     ///
0313     /// @param q Energy scale
0314     /// @return Whether q is in range
0315     virtual bool inRangeQ(double q) const {
0316       return inRangeQ2(q*q);
0317     }
0318 
0319     /// @brief Grid range check for Q2
0320     ///
0321     /// Return true when given Q2 is in the coverage range of this PDF.
0322     ///
0323     /// @param q2 Squared energy scale
0324     /// @return Whether q2 is in range
0325     virtual bool inRangeQ2(double q2) const = 0;
0326 
0327     /// @brief Grid range check for x
0328     ///
0329     /// Return true when given x is in the coverage range of this PDF.
0330     ///
0331     /// @param x Momentum fraction
0332     /// @return Whether x is in range
0333     virtual bool inRangeX(double x) const = 0;
0334 
0335     /// Combined range check for x and Q
0336     virtual bool inRangeXQ(double x, double q) const {
0337       return inRangeX(x) && inRangeQ(q);
0338     }
0339 
0340     /// Combined range check for x and Q2
0341     bool inRangeXQ2(double x, double q2) const {
0342       return inRangeX(x) && inRangeQ2(q2);
0343     }
0344 
0345     ///@}
0346 
0347 
0348     /// @name Generic member-level metadata (including cascaded metadata from set & config level)
0349     ///@{
0350 
0351     /// Get the info class that actually stores and handles the metadata
0352     PDFInfo& info() { return _info; }
0353 
0354     /// Get the info class that actually stores and handles the metadata (const version)
0355     const PDFInfo& info() const { return _info; }
0356 
0357     /// @brief Get the PDF set of which this is a member
0358     ///
0359     /// Obtained from the member file path, not Info-based metadata.
0360     PDFSet& set() const {
0361       return getPDFSet(_setname());
0362     }
0363 
0364     ///@}
0365 
0366 
0367     /// @name Member-level metadata
0368     ///@{
0369 
0370     /// @brief PDF member local ID number
0371     ///
0372     /// Obtained from the member file path, not Info-based metadata.
0373     int memberID() const {
0374       const string memname = file_stem(_mempath);
0375       assert(memname.length() > 5); // There must be more to the filename stem than just the _nnnn suffix
0376       const int memid = lexical_cast<int>(memname.substr(memname.length()-4)); //< Last 4 chars should be the member number
0377       return memid;
0378     }
0379 
0380     /// @brief PDF member global LHAPDF ID number
0381     ///
0382     /// Obtained from the member ID and the set's LHAPDF ID index
0383     int lhapdfID() const;
0384 
0385     /// Description of this PDF member
0386     std::string description() const {
0387       return info().get_entry("MemDesc", info().get_entry("PdfDesc", ""));
0388     }
0389 
0390     /// Version of this PDF's data file
0391     int dataversion() const {
0392       return info().get_entry_as<int>("DataVersion", -1);
0393     }
0394 
0395     /// Get the type of PDF member that this object represents (central, error)
0396     std::string type() const {
0397       return to_lower(info().get_entry("MemType", info().get_entry("PdfType")));
0398     }
0399 
0400     ///@}
0401 
0402 
0403     /// Summary printout
0404     void print(std::ostream& os=std::cout, int verbosity=1) const;
0405 
0406 
0407     /// @name Parton content and QCD parameters
0408     ///@{
0409 
0410     /// @brief List of flavours defined by this PDF set.
0411     ///
0412     /// This list is stored locally after its initial read from the Info object
0413     /// to avoid unnecessary lookups and string decoding, since e.g. it is
0414     /// looked at by every call to the GridPDF's Interpolator and Extrapolator
0415     /// classes.
0416     ///
0417     /// @todo Make virtual for AnalyticPDF? Or allow manual setting of the Info?
0418     virtual const std::vector<int>& flavors() const {
0419       if (_flavors.empty()) {
0420         _flavors = info().get_entry_as< vector<int> >("Flavors");
0421         sort(_flavors.begin(), _flavors.end());
0422       }
0423       return _flavors;
0424     }
0425 
0426     /// @brief Manually set/override the list of flavours defined by this PDF set.
0427     ///
0428     /// @note The provided vector will be internally sorted into ascending numeric order.
0429     void setFlavors(std::vector<int> const& flavors) {
0430       _flavors = flavors;
0431       sort(_flavors.begin(), _flavors.end());
0432     }
0433 
0434     /// Checks whether @a id is a valid parton for this PDF.
0435     bool hasFlavor(int id) const;
0436 
0437     /// @brief Order of QCD at which this PDF has been constructed
0438     ///
0439     /// "Order" is defined here and throughout LHAPDF as the maximum number of
0440     /// loops included in the matrix elements, in order to have an integer value
0441     /// for easy use in comparisons, as opposed to "LO", "NLO", etc. strings.
0442     ///
0443     /// @todo Provide a setter function?
0444     int orderQCD() const {
0445       return info().get_entry_as<int>("OrderQCD");
0446     }
0447     /// @deprecated Use orderQCD instead
0448     int qcdOrder() const { return orderQCD(); }
0449 
0450     /// @brief Get a quark mass in GeV by PDG code (|PID| = 1-6 only)
0451     ///
0452     /// Convenience interface to the Mass* info keywords.
0453     /// Returns -1 for an undefined PID.
0454     ///
0455     /// @todo Provide a setter function?
0456     double quarkMass(int id) const;
0457 
0458     /// @brief Get a flavor scale threshold in GeV by PDG code (|PID| = 1-6 only)
0459     /// Convenience interface to the Mass* and Threshold* info keywords.
0460     /// Returns -1 for an undefined PID.
0461     ///
0462     /// @todo Provide a setter function?
0463     double quarkThreshold(int id) const;
0464 
0465     ///@}
0466 
0467 
0468     /// @name QCD running coupling calculation
0469     ///@{
0470 
0471     /// @brief Set the AlphaS calculator by pointer
0472     ///
0473     /// The provided AlphaS must have been new'd, as it will not be copied and
0474     /// ownership passes to this GridPDF: it will be deleted when this PDF goes
0475     /// out of scope or another setAlphaS call is made.
0476     void setAlphaS(AlphaS* alphas) {
0477       _alphas.reset(alphas);
0478     }
0479 
0480     /// @brief Set the AlphaS calculator by smart pointer
0481     void setAlphaS(AlphaSPtr alphas) {
0482       _alphas = std::move(alphas);
0483     }
0484 
0485     /// @brief Check if an AlphaS calculator is set
0486     bool hasAlphaS() const {
0487       return bool(_alphas);
0488     }
0489 
0490     /// @brief Retrieve the AlphaS object for this PDF
0491     AlphaS& alphaS() {
0492       return *_alphas;
0493     }
0494 
0495     /// @brief Retrieve the AlphaS object for this PDF (const)
0496     const AlphaS& alphaS() const {
0497       return *_alphas;
0498     }
0499 
0500     /// @brief Value of alpha_s(Q2) used by this PDF
0501     ///
0502     /// Calculated numerically, analytically, or interpolated according to
0503     /// metadata, using the AlphaS classes.
0504     double alphasQ(double q) const {
0505       return alphasQ2(q*q);
0506     }
0507 
0508     /// @brief Value of alpha_s(Q2) used by this PDF
0509     ///
0510     /// Calculated numerically, analytically, or interpolated according to
0511     /// metadata, using the AlphaS classes.
0512     double alphasQ2(double q2) const {
0513       if (!hasAlphaS()) throw Exception("No AlphaS pointer has been set");
0514       return _alphas->alphasQ2(q2);
0515     }
0516 
0517     ///@}
0518 
0519 
0520   protected:
0521 
0522     void _loadAlphaS() {
0523       _alphas.reset( mkAlphaS(info()) );
0524     }
0525 
0526     /// Get the set name from the member data file path (for internal use only)
0527     std::string _setname() const {
0528       return basename(dirname(_mempath));
0529     }
0530 
0531     /// Member data file path
0532     std::string _mempath;
0533 
0534     /// Metadata container
0535     PDFInfo _info;
0536 
0537     /// Locally cached list of supported PIDs (mutable for laziness/caching)
0538     mutable vector<int> _flavors;
0539 
0540     /// Optionally loaded AlphaS object (mutable for laziness/caching)
0541     mutable AlphaSPtr _alphas;
0542 
0543     /// @brief Cached flag for whether to return only positive (or positive definite) PDF values
0544     ///
0545     /// A negative value indicates that the flag has not been set. 0 = no
0546     /// forcing, 1 = force positive (i.e. 0 is permitted, negative values are
0547     /// not), 2 = force positive definite (i.e. no values less than 1e-10).
0548     mutable int _forcePos;
0549 
0550   };
0551 
0552 
0553 }
0554 #endif