Back to home page

EIC code displayed by LXR

 
 

    


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

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_AlphaS_H
0008 #define LHAPDF_AlphaS_H
0009 
0010 #include "LHAPDF/Utils.h"
0011 #include "LHAPDF/Exceptions.h"
0012 #include "LHAPDF/KnotArray.h"
0013 
0014 namespace LHAPDF {
0015 
0016 
0017   /// @brief Calculator interface for computing alpha_s(Q2) in various ways
0018   ///
0019   /// The design of the AlphaS classes is that they are substitutible
0020   /// (cf. polymorphism) and are entirely non-dependent on the PDF and Info
0021   /// objects: hence they can be used by external code that actually doesn't
0022   /// want to do anything at all with PDFs, but which just wants to do some
0023   /// alpha_s interpolation.
0024   class AlphaS {
0025   public:
0026 
0027     /// Base class constructor for default param setup
0028     AlphaS();
0029 
0030     /// Destructor
0031     virtual ~AlphaS() {};
0032 
0033     /// @name alpha_s values
0034     ///@{
0035 
0036     /// Calculate alphaS(Q)
0037     double alphasQ(double q) const { return alphasQ2(q*q); }
0038 
0039     /// Calculate alphaS(Q2)
0040     /// @todo Throw error in this base method if Q < Lambda?
0041     virtual double alphasQ2(double q2) const = 0;
0042 
0043     ///@}
0044 
0045 
0046     /// @name alpha_s metadata
0047     ///@{
0048 
0049     /// Calculate the number of active flavours at energy scale Q
0050     int numFlavorsQ(double q) const { return numFlavorsQ2(q*q); }
0051 
0052     /// Calculate the number of active flavours at energy scale Q2
0053     virtual int numFlavorsQ2(double q2) const;
0054 
0055     /// Get a quark mass by PDG code
0056     double quarkMass(int id) const;
0057 
0058     /// @brief Set quark masses by PDG code
0059     ///
0060     /// Used in the analytic and ODE solvers.
0061     void setQuarkMass(int id, double value);
0062 
0063     /// @brief Get a flavor scale threshold by PDG code
0064     ///
0065     /// Used in the analytic and ODE solvers.
0066     double quarkThreshold(int id) const;
0067 
0068     /// @brief Set a flavor threshold by PDG code (= quark masses by default)
0069     ///
0070     /// Used in the analytic and ODE solvers.
0071     void setQuarkThreshold(int id, double value);
0072 
0073     /// Get the order of QCD (expressed as number of loops)
0074     ///
0075     /// Used explicitly in the analytic and ODE solvers.
0076     int orderQCD() { return _qcdorder; }
0077 
0078     /// @brief Set the order of QCD (expressed as number of loops)
0079     ///
0080     /// Used in the analytic and ODE solvers.
0081     void setOrderQCD(int order) { _qcdorder = order; }
0082 
0083     /// @brief Set the Z mass used in this alpha_s
0084     ///
0085     /// Used in the ODE solver.
0086     void setMZ(double mz) { _mz = mz; }
0087 
0088     /// @brief Set the alpha_s(MZ) used in this alpha_s
0089     ///
0090     /// Used in the ODE solver.
0091     void setAlphaSMZ(double alphas) { _alphas_mz = alphas; }
0092 
0093     /// @brief Set the Z mass used in this alpha_s
0094     ///
0095     /// Used in the ODE solver.
0096     void setMassReference(double mref) { _mreference = mref; _customref = true; }
0097 
0098     /// @brief Set the alpha_s(MZ) used in this alpha_s
0099     ///
0100     /// Used in the ODE solver.
0101     void setAlphaSReference(double alphas) { _alphas_reference = alphas; _customref = true; }
0102 
0103     /// @brief Set the @a {i}th Lambda constant for @a i active flavors
0104     ///
0105     /// Used in the analytic solver.
0106     virtual void setLambda(unsigned int, double) {};
0107 
0108     /// Enum of flavor schemes
0109     enum FlavorScheme { FIXED, VARIABLE };
0110 
0111     /// Get the implementation type of this AlphaS
0112     virtual std::string type() const = 0;
0113 
0114     /// Set flavor scheme of alpha_s solver
0115     void setFlavorScheme(FlavorScheme scheme, int nf = -1);
0116 
0117     /// Get flavor scheme
0118     FlavorScheme flavorScheme() const { return _flavorscheme; }
0119 
0120     ///@}
0121 
0122 
0123   protected:
0124 
0125     /// @name Calculating beta function values
0126     ///@{
0127 
0128     /// Calculate the i'th beta function given the number of active flavours
0129     /// Currently limited to 0 <= i <= 3
0130     /// Calculated using the MSbar scheme
0131     double _beta(int i, int nf) const;
0132 
0133     /// Calculate a vector of beta functions given the number of active flavours
0134     /// Currently returns a 4-element vector of beta0 -- beta3
0135     std::vector<double> _betas(int nf) const;
0136 
0137     ///@}
0138 
0139 
0140   protected:
0141 
0142     /// Order of QCD evolution (expressed as number of loops)
0143     int _qcdorder;
0144 
0145     /// Mass of the Z boson in GeV
0146     double _mz;
0147 
0148     /// Value of alpha_s(MZ)
0149     double _alphas_mz;
0150 
0151     /// Reference mass in GeV
0152     double _mreference;
0153 
0154     /// Value of alpha_s(reference mass)
0155     double _alphas_reference;
0156 
0157     /// Decides whether to use custom reference values or fall back on MZ/AlphaS_MZ
0158     bool _customref;
0159 
0160     /// Masses of quarks in GeV
0161     /// Used for working out flavor thresholds and the number of quarks that are
0162     /// active at energy scale Q.
0163     std::map<int, double> _quarkmasses, _flavorthresholds;
0164 
0165     /// The flavor scheme in use
0166     FlavorScheme _flavorscheme;
0167 
0168     /// The allowed numbers of flavours in a fixed scheme
0169     int _fixflav;
0170 
0171   };
0172 
0173 
0174 
0175   /// Calculate alpha_s(Q2) by an analytic approximation
0176   class AlphaS_Analytic : public AlphaS {
0177   public:
0178 
0179     /// Implementation type of this solver
0180     std::string type() const { return "analytic"; }
0181 
0182     /// Calculate alphaS(Q2)
0183     double alphasQ2(double q2) const;
0184 
0185     /// Analytic has its own numFlavorsQ2 which respects the min/max nf set by the Lambdas
0186     int numFlavorsQ2(double q2) const;
0187 
0188     /// Set lambda_i (for i = flavour number)
0189     void setLambda(unsigned int i, double lambda);
0190 
0191 
0192   private:
0193 
0194     /// Get lambdaQCD for nf
0195     double _lambdaQCD(int nf) const;
0196 
0197     /// Recalculate min/max flavors in case lambdas have changed
0198     void _setFlavors();
0199 
0200 
0201     /// LambdaQCD values.
0202     std::map<int, double> _lambdas;
0203 
0204     /// Max number of flavors
0205     int _nfmax;
0206     /// Min number of flavors
0207     int _nfmin;
0208 
0209   };
0210 
0211 
0212 
0213   /// Interpolate alpha_s from tabulated points in Q2 via metadata
0214   ///
0215   /// @todo Extrapolation: log-gradient xpol at low Q, const at high Q?
0216   class AlphaS_Ipol : public AlphaS {
0217   public:
0218 
0219     /// Implementation type of this solver
0220     std::string type() const { return "ipol"; }
0221 
0222     /// Calculate alphaS(Q2)
0223     double alphasQ2(double q2) const;
0224 
0225     /// Set the array of Q values for interpolation
0226     ///
0227     /// Writes to the same internal arrays as setQ2Values, appropriately transformed.
0228     void setQValues(const std::vector<double>& qs);
0229 
0230     /// Set the array of Q2 values for interpolation
0231     ///
0232     /// Subgrids are represented by repeating the values which are the end of
0233     /// one subgrid and the start of the next. The supplied vector must match
0234     /// the layout of alpha_s values.
0235     void setQ2Values(const std::vector<double>& q2s) { _q2s = q2s; }
0236 
0237     /// Set the array of alpha_s(Q2) values for interpolation
0238     ///
0239     /// The supplied vector must match the layout of Q2 knots.  Subgrids may
0240     /// have discontinuities, i.e. different alpha_s values on either side of a
0241     /// subgrid boundary (for the same Q values).
0242     void setAlphaSValues(const std::vector<double>& as) { _as = as; }
0243 
0244 
0245   private:
0246 
0247     /// Standard cubic interpolation formula
0248     double _interpolateCubic(double T, double VL, double VDL, double VH, double VDH) const;
0249     /// Get the gradient for a patch in the middle of the grid
0250     double _ddq_central( size_t i ) const;
0251     /// Get the gradient for a patch at the low end of the grid
0252     double _ddq_forward( size_t i ) const;
0253     /// Get the gradient for a patch at the high end of the grid
0254     double _ddq_backward( size_t i ) const;
0255 
0256     /// Synchronise the contents of the single Q2 / alpha_s vectors into subgrid objects
0257     /// @note This is const so it can be called silently from a const method
0258     void _setup_grids() const;
0259 
0260 
0261     /// Map of AlphaSArrays "binned" for lookup by low edge in (log)Q2
0262     /// @note This is mutable so it can be initialized silently from a const method
0263     mutable std::map<double, AlphaSArray> _knotarrays;
0264 
0265     /// Array of ipol knots in Q2
0266     std::vector<double> _q2s;
0267     /// Array of alpha_s values for the Q2 knots
0268     std::vector<double> _as;
0269 
0270   };
0271 
0272 
0273 
0274   /// Solve the differential equation in alphaS using an implementation of RK4
0275   class AlphaS_ODE : public AlphaS {
0276   public:
0277 
0278     /// Implementation type of this solver
0279     std::string type() const { return "ode"; }
0280 
0281     /// Calculate alphaS(Q2)
0282     double alphasQ2( double q2 ) const;
0283 
0284     /// Set MZ, and also the caching flag
0285     void setMZ( double mz ) { _mz = mz; _calculated = false; }
0286 
0287     /// Set alpha_s(MZ), and also the caching flag
0288     void setAlphaSMZ( double alphas ) { _alphas_mz = alphas; _calculated = false; }
0289 
0290     /// Set reference mass, and also the caching flag
0291     void setMassReference( double mref ) { _mreference = mref; _calculated = false; _customref = true; }
0292 
0293     /// Set alpha_s(MZ), and also the caching flag
0294     void setAlphaSReference( double alphas ) { _alphas_reference = alphas; _calculated = false; _customref = true; }
0295 
0296     /// Set the array of Q values for interpolation, and also the caching flag
0297     void setQValues(const std::vector<double>& qs);
0298 
0299     /// @brief Set the array of Q2 values for interpolation, and also the caching flag
0300     ///
0301     /// Writes to the same internal array as setQValues, appropriately transformed.
0302     void setQ2Values( std::vector<double> q2s ) { _q2s = q2s; _calculated = false; }
0303 
0304 
0305   private:
0306 
0307     /// Calculate the derivative at Q2 = t, alpha_S = y
0308     double _derivative(double t, double y, const std::vector<double>& beta) const;
0309 
0310     /// Calculate the decoupling relation when going from num. flav. = ni -> nf
0311     /// abs(ni - nf) must be = 1
0312     double _decouple(double y, double t, unsigned int ni, unsigned int nf) const;
0313 
0314     /// Calculate the next step using RK4 with adaptive step size
0315     void _rk4(double& t, double& y, double h, const double allowed_change, const vector<double>& bs) const;
0316 
0317     /// Solve alpha_s for q2 using RK4
0318     void _solve(double q2, double& t, double& y, const double& allowed_relative, double h, double accuracy) const;
0319 
0320     /// Create interpolation grid
0321     void _interpolate() const;
0322 
0323 
0324     /// Vector of Q2s in case specific anchor points are used
0325     mutable std::vector<double> _q2s;
0326 
0327     /// Whether or not the ODE has been solved yet
0328     mutable bool _calculated;
0329 
0330     /// The interpolation used to get Alpha_s after the ODE has been solved
0331     mutable AlphaS_Ipol _ipol;
0332 
0333   };
0334 
0335 
0336 }
0337 #endif