\documentclass[12pt]{article}
%%  TO DO - Program
%%
%% - Add coefficient functions at NNLO 
%% - Routines to build structure functions
%% - Implement DIS scheme at NNLO
%% - Time-like evolution
%%

% We need slightly different text in the manual and in the release note.
\newif\ifreleasenote
%\releasenotetrue % comment out to hide answers

\input{preamble.tex}
\hypersetup{
  colorlinks = true,
  linkcolor  = blue,
  citecolor  = blue,
  urlcolor   = blue,
 }
\usepackage[sort&compress,numbers]{natbib}


%-----------------------------------------
\title{A Higher Order Perturbative Parton Evolution Toolkit \\
(\hoppet)\\
%% DO NOT EDIT the next line -- it is modified automatically by scripts/set-version.sh
version 2.1.0%% VERSION-NUMBER 
%  a.k.a.\ HOPPETv1
}
\author{%
  Fr\'ed\'eric Dreyer,
  Alexander Karlberg,
  Paolo Nason,
  Juan Rojo,\\
  Gavin P.\ Salam and
  Giulia Zanderighi
}

\date{}


%======================================================================
\begin{document}


\maketitle 

\begin{abstract}
  This document describes \hoppet, a Fortran package for carrying out DGLAP
  evolution and other common manipulations of parton distribution
  functions (PDFs). The PDFs are represented on a grid in $x$--space so
  as to avoid limitations on the functional form of input
  distributions.  Good speed and accuracy are obtained through the
  representation of splitting functions in terms of their convolution
  with a set of piecewise polynomial basis functions, and Runge-Kutta
  techniques are used for the evolution in $Q$.
  %
  Unpolarised evolution
  is provided to N$^3$LO, including heavy-quark thresholds in the
  pole and $\MSbar$ schemes (the latter only to NNLO),
  %
  and longitudinally polarised evolution to NLO.
  %
  The code also includes QED evolution and N$^3$LO massless structure
  functions.
  %
  The
  code is structured so as to provide simple access to the objects
  representing splitting functions and PDFs, making it possible for a
  user to extend the facilities already provided.
%
  A streamlined interface is also available, facilitating use of the
  evolution part of the code from F77, C/\CPP and Python.  \smallskip
\end{abstract}

\begin{textblock*}{2cm}(0.55\textwidth,0.1\textheight)  % (width)(x,y position)
  %\includegraphics[width=3cm]{logo/2025-09-logo-cropped.pdf}
  \includegraphics[width=2cm]{logo/2025-09-logo.png}
\end{textblock*}


% \newpage


% \noindent {\Large \textbf{Program Summary}}\\
% 
% \noindent {\em Title of program\/}: \hoppet \\[2mm]
% {\em Version\/}: 1.1.5%
% %  (including documentation of some updates upto 2011-02-21)
% \\[2mm]
% {\em Catalogue identifier\/}: \\[2mm]
% {\em Program obtainable from\/}:
% \url{http://projects.hepforge.org/hoppet/}
% \\[2mm]
% {\em Distribution format\/}: compressed tar file \\[2mm]
% {\em E-mail\/}: {\tt salam@lpthe.jussieu.fr}, 
% {\tt rojo@lpthe.jussieu.fr} \\[2mm]
% {\em License\/}: GNU Public License \\[2mm]
% {\em Computers\/}: all \\[2mm]
% {\em Operating systems\/}: all \\[2mm]
% {\em Program language\/}: Fortran~95 \\[2mm]
% {\em Memory required to execute\/}:  $\lesssim$ 10 MB \\[2mm]
% {\em Other programs called\/}: none \\[2mm]
% {\em External files needed\/}: none \\[2mm]
% {\em Number of bytes in distributed program, including test data
%   etc.\/}: $\sim 350$~kB\\[2mm]
% {\em Keywords\/}: unpolarised and longitudinally polarised parton
% space-like distribution functions (PDFs), DGLAP evolution equations,
% $x$--space solutions.
% \\[2mm]
% {\em Nature of the physical problem\/}: Solution of the DGLAP
% evolution equations up to NNLO (NLO) for unpolarised (longitudinally
% polarised) PDFs, and provision of tools to facilitate manipulation
% (convolutions, etc.) of PDFs with user-defined coefficient and
% splitting functions.
% \\[2mm]
% %
% {\em Method of solution\/}:
% representation of PDFs on a grid in $x$, adaptive integration of
% splitting functions to reduce them to a discretised
% form, obtaining fast
% convolutions that are equivalent to integration with an interpolated
% form of the PDFs; Runge Kutta solution of the $Q$ evolution, and
% its caching so as to speed up repeated evolution with different
% initial conditions.
% \\[2mm]
% {\em Restrictions on complexity of the problem\/}: PDFs should be
% smooth on the scale of the discretisation in $x$.
% \\[2mm]
% {\em Typical running time\/}: a few seconds for initialisation, then
% $\sim 10$~ms for creating a tabulation with a relative accuracy of
% $10^{-4}$ from a new initial condition (on a 3.4~GHz Pentium~IV
% processor). Further details in section~\ref{sec:Timing}.

\newpage
\noindent \fbox{\parbox{\textwidth}{%
\textbf{Note:} this manual is structured as follows: it
   consists of the original v1 manual with a few key updates, such as
   N$^3$LO evolution in section~\ref{sec:pqcd},
   %
   followed by sections~\ref{sec:v2-additions} onwards, describing the
   main additions in v2 and with updated performance studies,
   whose timings notably supersede those in section~\ref{sec:Timing}.
 }}

\tableofcontents



%======================================================================
%======================================================================


\section{Introduction}
\label{sec:intro}

There has been considerable discussion over the past years
(\eg~\cite{\AllDGLAP}) of numerical solutions of the 
Dokshitzer-Gribov-Lipatov-Altarelli-Parisi (DGLAP)
 equation~\cite{Gribov:1972ri,Altarelli:1977zs,Dokshitzer:1977sg} for the Quantum Chromodynamics
(QCD)
evolution  of parton distribution functions (PDFs).


The DGLAP equation
\cite{Gribov:1972ri,Altarelli:1977zs,Dokshitzer:1977sg} is a renormalisation group equation for the quantity
$q_i(x,Q^2)$, the density of partons of type (or flavour) $i$ carrying
a fraction $x$ of the longitudinal momentum of a hadron, when resolved
at a scale $Q$. It is one of the fundamental equations of perturbative
QCD, being central to all theoretical
predictions for hadron-hadron and lepton-hadron colliders.

Technically, it is a matrix integro-differential equation,
\begin{equation}
  \label{eq:dglap}
  \frac{\partial q_i(x,Q^2)}{\partial \ln Q^2} = \frac{\aq}{2\pi}
 \int_x^1 \frac{dz}{z}
  P_{ij}\lp z,\aq\rp q_j\lp \frac{x}{z},Q^2\rp\,,
\end{equation}
whose kernel elements $P_{ij}(z,Q^2)$ are known as splitting
functions, since they describe the splitting of a parton of kind $j$
into a parton of kind $i$ carrying a fraction $z$ of the longitudinal
momentum of $j$. The parton densities themselves $q_i(x,Q^2)$ are
essentially non-perturbative, since they depend on physics at hadronic
mass scales $\lesssim 1 \GeV$, where the QCD coupling is large. On the
other hand the splitting functions are given by a perturbative
expansion in the QCD coupling $\as(Q^2)$. Thus given partial
experimental information on the parton densities\footnote{Of course it
  is not the parton densities, but rather structure functions, which
  can be derived from them perturbatively, that are measured
  experimentally.} %
--- for example over a limited range of $Q$, or for only a subset of
parton flavours --- the DGLAP equations can be used to reconstruct the
parton densities over the full range of $Q$ and for all flavours.

The pivotal role played by the DGLAP equation has motivated a
considerable body of literature discussing its numerical solution
\cite{\AllDGLAP}. There exist two main classes of approaches: those that
solve the equation directly in $x$--space and those that solve it for
Mellin transforms of the
parton densities, defined as
\be
q_{N}\lp N,Q^2\rp = \int_0^1 dx x^N q_i(x,Q^2) \ ,
\ee 
 and subsequently invert the transform back to
$x$--space.
 Recently, a novel approach has been proposed which combines
advantages of the $N-$space and $x-$space methods \cite{nnpdf}.
$N-$space based methods are of interest because the Mellin transform
converts the convolution of eq.~(\ref{eq:dglap}) into a multiplication,
resulting in a continuum of independent matrix differential (rather
than integro-differential) equations, one for each value of $N$,
making the evolution more efficient numerically.

The drawback of the Mellin method is that one needs to know the Mellin
transforms of both the splitting functions and the initial conditions.
There can also be subtleties associated with the inverse Mellin
transform.
%
The $x$--space method is in contrast more flexible, since the inputs
are only required in $x$--space; however it is generally considered to
less efficient numerically, because of the need to carry out the
convolution in eq.~(\ref{eq:dglap}).

To understand the question of efficiencies one should analyse the
number of operations needed to carry out the evolution. Assuming that
one needs to establish the results of the evolution at $N_x$ values of
$x$, and $N_Q$ values of $Q$, one essentially needs $\order{N_x^2
  N_Q}$ operations with an $x$--space method, where the $N_x^2$ factor
comes from the convolutions. In the Mellin-space method, one needs
$\order{N_x N_Q M}$ operations, where $M$ is the number of points used
for Mellin inversion. One source of drawback of the $x$--space method
is that, nearly always, $N_x \sim \ln 1/x_{\min}$ and so the method
scales as the square of $\ln 1/x_{\min}$, where the Mellin method is
linear (and $M$ can be kept roughly independent of $x_{\min}$). 
%

The other issue relates to how one goes to higher numerical
integration and interpolation orders.
In $x$--space methods one tends to choose $x$ values that are uniformly
distributed (be it in $\ln 1/x$ or some other more complex function)
--- this limits one to higher-order extensions of the Trapezium and
Simpson-rule type integrations, whose order in general is $n_p-1$
where $n_p$ is the number of points used for the integration. The
precision of the integration is given by $\lp\delta x\rp^{n_p}$ where
$\delta x$ is the grid spacing. Higher $n_p$ improves the accuracy,
but typically $n_p$ can not be taken too large because of large
cancellations between weights that arise for large $n_p$.
%
%
In the Mellin method one is free to position the $M$ points as one
likes, and one can then use Gaussian type
integration~\cite{Weinzierl:2002mv,Pegasus,Kosower:1997hg}; using $n_p$
points one manages to get a numerical order $2n_p-1$, \ie accuracy
$\lp \delta x\rp^{2n_p}$, and furthermore the integration weights do not suffer
from cancellations at large $n_p$, allowing one to increase
$n_p$, and thus the accuracy, quite considerably.

Despite it being more difficult to obtain high accuracy with $x$--space
methods, their greater flexibility means that they are widespread,
serving as the basis of the well-known  QCDNUM program \cite{Botje},
and  used also by the CTEQ~\cite{CTEQ} and MRST/MSTW~\cite{MRST}
global fitting
collaborations. Higher-order methods in $x$--space have been developed
in \cite{Schoeffel:1998tz,Pascaud:2001bi,Cafarella:2003jr,Cafarella:2005zj,Cafarella:2008du,GuzziThesis,Dasgupta:2001eq,Dasgupta:2002dc}, and
more recently have been incorporated also in QCDNUM.

\hoppet, the program presented here, uses higher-order methods both for
the $x$-integrations and $Q$ evolution. It combines this with multiple
grids in $x$--space: a high-density grid at large $x$ where it is
hardest to obtain good accuracy, and coarser grids at smaller $x$
where the smoothness of the PDFs facilitates the integrations. One of
the other crucial features of the program is that it pre-calculates as
much information as possible, so as to reduce the 
evolution of a new PDF initial condition to a modest set of addition
and multiplication operations. Additionally, the program provides
access to a range of low and medium-level operations on PDFs which
should allow a user to extend the facilities already provided.


The functionality described in this article has been present in
\hoppet's predecessors for several years (they were available on
request), but had
never been documented. 
Those predecessors have  been used in a number of different
contexts, like resummation of event shapes
in DIS \cite{Dasgupta:2001eq,Dasgupta:2002dc}, automated resummation
of event shapes \cite{caesar}, studies of
resummation in the small-$x$ limit \cite{Ciafaloni:2003rd}, 
and in a posteriori inclusion
of PDFs in NLO final-state calculations \cite{Carli:2005ji,Carli:2010rw,Banfi:2007gu}, as well
as  used for benchmark
comparisons with Pegasus~\cite{Pegasus} in \cite{Giele:2002hx,Dittmar:2005ed}.
Since the code had
not hitherto been released in a documented form, 
it is the authors' hope that availability of
this documentation may make the package somewhat more useful.

This manual is structured as follows: section~\ref{sec:pqcd}
briefly summarises the perturbative QCD ingredients contained in
\hoppet, while section~\ref{tricks} describes the numerical techniques
used to solve the DGLAP equation. 
sections~\ref{sec:singleflav}--\ref{sec:tabulated-pdfs} present in detail the capabilities
of the \hoppet package with its general F95 interface, 
with emphasis on those aspects that
can be adapted by a user to tailor it to their own needs. 
section~\ref{sec:vanilla} describes a streamlined interface
to \hoppet which embodies its essential capabilities in
a simple interface available in a variety of programming languages: 
F77 and C/\CPP{}.
Finally, section~\ref{sec:benchmarks} presents a detailed 
quantitative study of
the performance of \hoppet, and in the final section we conclude.
A set of appendices contain various example programs,
both for the general and the streamlined interfaces, a reference
guide with the most important \hoppet modules,
details on technical aspects and a set of useful tips on
Fortran 95. 


A reader 
whose interest is to use \hoppet to perform
fast and efficient evolution of PDFs 
may wish to skip 
sections~\ref{sec:singleflav} to \ref{sec:tabulated-pdfs}
and move directly to
 section~\ref{sec:vanilla}, which describes the 
user-friendlier streamlined interface,
accessible from F95, F77 and C/\CPP{}, and which contains the essential
functionalities of \hoppet. He/she is also encouraged to go through the
various example programs which contain detailed 
descriptions and explanations. 
On the other hand, a reader interested in the
more flexible and general 
functionalities of \hoppet should also consult
sections~\ref{sec:singleflav} to \ref{sec:tabulated-pdfs}. 

Note 
that throughout this documentation, a PDF refers always to a momentum
density rather than a parton density, that is, when we refer to
a gluon, we mean $xg(x)$ rather than $g(x)$, the same convention
as used in the LHAPDF PDF library \cite{LHAPDF}.


%----------------------------------------------------------------------

\input{perturbative-evolution-in-qcd.tex}
%-----------------------------------------------------------------
\section{Numerical techniques}
\label{tricks}
We briefly introduce now the numerical techniques used to perform
parton evolution: the discretisation of PDFs and
their convolutions with splitting functions on a grid in $x$,
and the subsequent DGLAP evolution in $Q^2$. 

The first aspect that we discuss is how to represent PDFs
and associated convolutions in terms of an interpolating grid
in $x-$space.
%Note that 
These techniques can be applied to a range of problems
that involve convolutions, so are not restricted
to parton distributions. Then in later sections we will describe how
to obtain the solution of the DGLAP evolution equations.

%......................................................................
\subsection{Higher order matrix representation}
\label{sec:highord}


Given a set of $N_x$ grid points $y_\alpha=\ln 1/x_{\alpha}$, 
labelled by an
index $\alpha$ and
(for later convenience) a uniform grid spacing, $y_\alpha = \alpha \delta
y$, one can approximate a parton distribution function 
$xq \lp x,t \rp$ by
interpolating the PDF at the grid points,\footnote{From the 
numerical point of view, it is
advantageous to interpolate $xq$ rather than $q$ itself because
the former is in general smoother.}
\begin{equation}
  xq(y=\ln 1/x,t) = \sum_\alpha w_\alpha(y) q_\alpha(t)\,,
\end{equation}
where $w_\alpha(y)$ are the interpolation weights, 
we have defined
\begin{equation}
 q_{\alpha}(t) \equiv
x_{\alpha}q(y_\alpha,t) \ ,
\end{equation}
and the sum over $\alpha$ runs over $n+1$ points in the
vicinity of $y$ for an interpolation order $n$. Note that Greek
indices represent the $y$ dimension, while  Roman indices
are  used to represent the flavour dimension.


The convolution of a single-flavour PDF with a splitting function
$P(z,t)$ can be written as
\begin{equation}
  (P \otimes q)(y,t) = \sum_{\alpha} \omega_{\alpha}(y)
 (P \otimes q)_\alpha(t) \ ,
\end{equation}
where we have replaced the convolution by its grid representation,
\begin{equation}
  (P \otimes q)_\alpha(t) = \sum_{\beta} P_{\alpha\beta}(t) \, q_\beta(t)\,,
\end{equation}
where $\beta$ runs over $\mathcal{O}\lp N_x \rp$ points of the grid and we have
defined
\begin{equation}
  \label{eq:Palphabeta}
  P_{\alpha\beta}(t) = \int_{e^{-y_{\alpha}}}^1 dz
 \,P(z,t)\, w_\beta(y_\alpha + \ln z)\  .
\end{equation}



A virtue
 of having a uniform grid in $y = \ln 1/x$ is that the
interpolation functions can be arranged to have a structure
$w_\alpha(y) = w(y - y_\alpha)$ (where $w(y)$ is non-zero for $0\le y <
n \delta y$), so that $P_{\alpha\beta}$ just depends
on $\alpha - \beta$, and can be rewritten $\mathcal{P}_{\alpha - \beta}$. A
slight subtlety arises at large $x$, where if one writes $w_\alpha(y) =
w(y - y_\alpha)$ one is effectively assuming an interpolation that uses
identically zero interpolation points for $x\ge 1$~\cite{Cafarella:2003jr,Cafarella:2005zj,Cafarella:2008du,
Ratcliffe:2000kp},
even though $xq(x)$ is not formally defined for $x > 1$. In practice
this is often not too important (because PDFs drop rapidly towards
$x=1$), but we shall include two options: one that uses effective
zero-points beyond $x=1$ and one that ensures that the interpolation
is based only on the physically valid domain of the PDFs.

These two choices are represented in
Fig.~\ref{fig:interpolation-orders}.  For an interpolation of order
$n$ (that is, which uses information from $n+1$ grid points), the
option of using only points with $x\le 1$ is denoted by $\tt order=n$.
This has the consequence that for $\beta \le n$ we cannot write
$P_{\alpha\beta} = \mathcal{P}_{\alpha-\beta}$, and so must explicitly
store $\order{N_x n}$ distinct $P_{\alpha\beta}$ entries.
%
The option of using artificial (zero-valued) points at $x>1$ is denoted by $\tt
order=-n$, and does allow us to write $P_{\alpha\beta} =
\mathcal{P}_{\alpha-\beta}$ (thus we store only $\order{N_x}$
entries), with $\mathcal{P}_{\alpha-\beta} = 0$ for $\alpha < \beta$.
%
In general we recommend the use of negative orders, because they give
faster initialisation time.

\begin{figure}
  \centering
  \includegraphics[width=0.72\textwidth]{figs-v1/interpolation-order}%
  \caption{The different strategies (+ve and $-$ve order) for
    interpolation of the grid near $x=1$. The dotted (blue, red) boxes
    indicate two regions in which we illustrate the interpolation of
    the PDF, while the (blue, red) lines with arrows indicate the
    corresponding range of grid points on which the interpolation is
    based.
    %
    This strategy choice affects only the interpolation as used for
    creating a representation of splitting functions.
    %
    Interpolation for evaluation of a PDF is always centred around the
    point of interest.
  }
  \label{fig:interpolation-orders}
\end{figure}


Note that the piecewise interpolating polynomials that we use effectively
imply a PDF that is not smooth at
the grid points. In practice this is a small effect. We could, in
principle, have enforced smoothness, for example by using
splines. However analytical studies indicate suggest that for a given
polynomial interpolation order this would actually reduce the accuracy
of the convolutions. It would also complicate somewhat the internal
bookkeeping during convolutions.



%......................................................................
\subsection{Evolution operators}
\label{sec:evop}
The DGLAP evolution equation, eq.~(\ref{eq:dglap-ns}), is easily 
approximated in terms of its grid representation by
\begin{equation}
\label{eq:evol}
  \frac{\partial q_{\alpha}(t)}{\partial t}  = \frac{\alpha_s(t)}{2\pi}
\sum_{\beta} P_{\alpha\beta}(t) q_\beta(t) \ ,
\end{equation}
where for a general value of $\alpha$ the sum over $\beta$ extends over
$\mathcal{O}\lp \alpha + |\ttt{order}| \rp$ 
points of the grid.
Introducing $M_{\alpha\beta}(t_0) = \delta_{\alpha\beta}$ as an initial
condition at some initial scale $t_0$, one can
alternatively solve
\begin{equation}
\label{eq:evolop}
  \frac{\partial M_{\alpha\beta}(t) }{\partial t} = \frac{\alpha_s(t)}{2\pi}
\sum_{\gamma} P_{\alpha\gamma}(t)
  M_{\gamma\beta}(t)\,.
\end{equation}
Then the evolved parton distribution at the grid points is
given by
\begin{equation}
  q_{\alpha}(t)  = \sum_{\beta} M_{\alpha\beta}(t) q_\beta(t_0)\,.
\end{equation}
We refer to $M_{\alpha\beta}(t)$ as the evolution operator. From 
a practical point of view, we will solve eqs.~(\ref{eq:evol})
and (\ref{eq:evolop})
with higher order iterative Runge-Kutta methods, as described in
section~\ref{sec:direct-evolution}.

A further simplification occurs if one can rewrite the splitting
functions $P$ as translationally invariant objects, \ie
$P_{\alpha\beta} = \cal P_{\alpha-\beta}$.
%
Then similarly one can rewrite $M_{\alpha\beta} = \cal
M_{\alpha-\beta}$, and it is as simple to determine
$M_{\alpha\beta}(t)$ as it is to determine the evolution of a single
vector $q_\alpha$, i.e.\ one just evolves a single column, $\beta =
0$, of $M_{\alpha\beta}(t)$.



%----------------------------------------------------------------------
\section{Single-flavour grids and convolutions}
\label{sec:singleflav}


\hoppet is written in Fortran~95 (F95). This has considerable
advantages compared to F77, as will be seen in the discussion of the
program, though it does lack a number of fully object-oriented
features and this sometimes restricts the scope for expressiveness.
Fortran~95 perhaps not being the best known language in the
high-energy physics community, occasionally some indications will be give to
help the reader with less-known language constructs, with further
information in Appendix~\ref{sec:f95appendix}.

All routines described in this section need access to the
\texttt{convolution} module, which can either be obtained directly by
adding a 
\begin{lstlisting}
  use convolution
\end{lstlisting}
statement at the beginning of the relevant subprogram (before
any \ttt{implicit none} or similar declarations). Alternatively, as
with the rest of the routines described in this documentation, it can
be accessed indirectly through the \ttt{hoppet} module
\begin{lstlisting}
  use hoppet
\end{lstlisting}
Unless you are delving into the innards of  \hoppet, the latter is
more convenient since it provides access to everything you are likely
to need. Some of the more internal \hoppet routines and functions
have however been left out of the  \ttt{hoppet} module, in order
to reduce the likelihood of conflicts with objects in the
user's namespace.

%......................................................................
\subsection{Grid definitions (\texttt{grid\_def})}
\label{sec:grid}

The grid (in $y$) is the central element of the PDF evolution.
Information concerning the grid is stored in a derived type
\texttt{grid\_def}:
% which could be initialised  for example as follows:
\begin{lstlisting}
  type(grid_def) :: grid
  call InitGridDef(grid,dy=0.1_dp,ymax=12.0_dp,order=-6)
\end{lstlisting}
This initialises a grid between $x=1$ and down to $x =
e^{-\texttt{ymax}}$, with uniform grid spacing in $y = \ln 1/x$ of
\texttt{dy=0.1}, with a grid that uses order 5 interpolation
with only $x\le 1$ points.
The user can modify this choice to better
suit his/her particular needs, as explained
in section~\ref{sec:highord}.
%
Notes
the use of keyword arguments --- the keywords are not
mandatory in this case, but have been included to improve the
legibility. Having defined a grid, 
the user need not worry about the details of
the grid representation.

In line with the convention set out in the Fortran~90 edition of
Numerical Recipes \cite{NRf90} we shall use \texttt{\_dp} to indicate
that floating-point numbers are in double precision, and \ttt{real(dp)} to declare
double precision variables. The integer parameter \ttt{dp} is defined
in the \texttt{module types} (and available indirectly through
\ttt{module hoppet}).

It is often useful to have multiple grids, with
coarser coverage at small $x$ and finer coverage at high $x$, to
improve the precision of the convolution\footnote{
The reason that denser grids are required at large-$x$ is that
if a typical parton distributions goes as
\be
\lim_{x\to 1} q(x,Q^2) \sim (1-x)^m \ ,
\ee
then its logarithmic derivative with respect to $x$ is divergent,
\be
\lim_{x \to 1} \frac{\partial  \ln q(x,Q^2) }{\partial \ln x} = 
\lim_{x \to 1} \frac{-mx}{1-x} \to -\infty \ ,
\ee
and therefore to maintain the relative accuracy of the evolution, grids
with denser coverage at large-$x$ are required.} at large-$x$ without
introducing an unnecessarily large density of points
at small-$x$.
To support
this option, we can first define an array of sub-grids, and then use them to
initialise a combined grid as follows:
\begin{lstlisting}
  type(grid_def) :: grid, subgrids(3)

  ! define the various sub-grids
  call InitGridDef(subgrids(1),dy=0.30_dp, ymax=10.0_dp, order=-6)
  call InitGridDef(subgrids(2),dy=0.10_dp, ymax= 2.0_dp, order=-6)
  call InitGridDef(subgrids(3),dy=0.03333_dp, ymax= 0.6_dp, order=-6) 
               ! Smaller dy at small ymax / large xmin 

  ! put them together into a single combined grid
  call InitGridDef(grid, subgrids, locked=.true.)
\end{lstlisting}
When combining them, the \ttt{locked=.true.} option has been specified,
which ensures that after any convolution, information from the finer
grids is propagated into the coarser ones. This places some
requirements on the grid spacings, notably that a coarse grid have a
spacing that is a multiple of that of the next finest grid. If the
requirements are not satisfied by the \ttt{subgrids} that have been
provided, then new similar, but more suitable subgrids are
automatically generated. When nested sub-grids are put together,
the values of the $x$ points of the combined grid will in general
not be ordered.

Note that the two kinds of invocation of \ttt{InitGridDef} actually
correspond to different (overloaded) subroutines. The Fortran~95 compiler
automatically selects the correct one on the basis of the types of
arguments passed.

For general usage, \hoppet provides a standard arrange of the
subgrids, which can be obtained by calling
%
the \ttt{InitGridDefDefault(grid, dy, ymax[, order])} routine.
%
That sets up the following grid
\begin{lstlisting}
  call InitGridDef(gdarray(4),dy/27.0_dp, 0.2_dp, order)
  call InitGridDef(gdarray(3),dy/9.0_dp,  0.5_dp, order)
  call InitGridDef(gdarray(2),dy/3.0_dp,  2.0_dp, order)
  call InitGridDef(gdarray(1),dy,         ymax  , order)
  call InitGridDef(grid,gdarray(1:4),locked=.true.)
\end{lstlisting}
Users will usually only need a different choice if they plan studies
at $x$ very close to $1$ or if they wish to explore fine optimisation of
grid choices.

Though only grids that are uniform in $y$ have been implemented
(and the option of a simultaneous combination of them),
nearly all of the description that follows and all code outside the
\texttt{convolution} module are independent of this detail, the only
exception being certain statements about timings. Therefore were
there to be a strong motivation for an alternative, non-uniform grid,
it would suffice to modify the \texttt{convolution} module, while the
rest of the library (and its interfaces) would remain unchanged.

%......................................................................
\subsection[$x$--space functions]{$\boldsymbol{x}$-space functions}
\label{sec:xspc}

Normal $x$--space functions (such as PDFs) are
held in double precision arrays, which are to be allocated as follows
\begin{lstlisting}
  real(dp), pointer :: xgluon(:)
  call AllocGridQuant(grid,xgluon)
\end{lstlisting}
Note that for this to work, \texttt{xgluon(:)}\ should be a
\texttt{pointer}, and not just 
have the \texttt{allocatable} attribute. To
deallocate a grid quantity, one may safely use the F95
\texttt{deallocate} command.

Since \texttt{xgluon(:)}\ is just an array, it carries no information
about the \texttt{grid}. Therefore to set and access its value, one
must always provide the information about the \texttt{grid}. This is
not entirely satisfactory, and is one of the drawbacks of the use of
F95.
% as will be explained later on.

There are a number of ways of setting a grid quantity. Suppose 
for example  that we have
a function
\begin{lstlisting}
  function example_xgluon(y)
    use types                !! defines "dp" (double precision) kind
    implicit none
    real(dp), intent(in)  :: y
    real(dp) :: x    
    x = exp(-y)
    example_xgluon = 1.7_dp * x**(-0.1_dp) * (1-x)**5 !! returns xg(x)  
  end function example_xgluon
\end{lstlisting}
which
returns the gluon
momentum density $xg(x)$ (\cf section~\ref{sec:highord}).
%
Then we can call
\begin{lstlisting}
  call InitGridQuant(grid,xgluon,example_xgluon)
\end{lstlisting}
to initialise \texttt{xgluon} with a representation of the return value
from the function \texttt{example\_xgluon}.
Alternative methods for initialising grid quantities
are described in Appendix \ref{sec:gridinit}.

To then access the gluon at a given value of $y = \ln 1/x$, one
proceeds as follows
\begin{lstlisting}
  real(dp) :: y, xgluon_at_y
  ...
  y = 5.0_dp
  xgluon_at_y = EvalGridQuant(grid,xgluon,y) !! again this returns xg(x), x=exp(-y)
\end{lstlisting}
Note that again we have to supply 
the \texttt{grid} argument to \ttt{EvalGridQuant}
because the \ttt{xgluon} array itself carries no information about the
grid (other than its size).

A less efficient, but perhaps more `object-oriented' way of accessing
the gluon is via the notation 
\begin{lstlisting}
  xgluon_at_y = xgluon .aty. (y.with.grid)
\end{lstlisting}
There also exists an \ttt{.atx.} operator for evaluating the PDF at a
given $x$ value.  Many of these procedures and operators are
overloaded so as to work with higher-dimensional arrays of grid
quantities, for example a multi-flavour
PDF array \texttt{pdf(:,:)}. The first index will
always correspond to the representation on the grid, while the second
index would here indicate the flavour.

Note that arithmetic operators all have higher precedence than
library-defined operators such as \texttt{.aty.}; accordingly some
ways of writing things are more efficient than others:
\begin{lstlisting}
  xgluon_at_y_times_2 = 2 * xgluon .aty. (y.with.grid)   ! very inefficient
  xgluon_at_y_times_2 = 2 * (xgluon .aty. (y.with.grid)) ! fairly efficient
  xgluon_at_y_times_2 = 2 * EvalGridQuant(grid,xgluon,y) ! most efficient
\end{lstlisting}
In the first case the whole of the array \texttt{xgluon} is multiplied
by 2, and then the result is evaluated at $y$, whereas in the second
and third
cases only the result of the gluon at $y$ is multiplied by 2.

%......................................................................
\subsection{Grid convolution operators}
\label{sec:conv}

While it is relatively straightforward internally to represent a
grid-quantity (e.g. a PDF) as an array, for convolution
operators  it is generally useful to have certain extra
information. Accordingly a derived type has been defined to hold a
convolution operator, and routines are provided for allocation and
initialisation of splitting functions.
%
The following example describes how the $gg$ LO splitting function
would be used to initialise the corresponding 
convolution operator:
\begin{lstlisting}
  type(grid_conv) :: xPgg
  call AllocGridConv(grid,xPgg)
  call InitGridConv(grid,xPgg, xPgg_func)
\end{lstlisting}
where the $P_{gg}$ splitting function is provided in the form of the
function \texttt{xPgg\_func}. Note that this function
must return $xP_{gg}(x)$:
\begin{lstlisting}
  ! returns various components of exp(-y) P_gg (exp(-y))
  real(dp) function xPgg_func(y)
    use types
    use convolution_communicator ! provides cc_piece, and cc_REAL,...
    use qcd                      ! provides CA, TR, nf, ...
    implicit none
    real(dp), intent(in) :: y
    real(dp)             :: x

    x = exp(-y); xPgg_func = zero
    if (cc_piece == cc_DELTA) then   ! Delta function term
       xPgg_func = (11*CA - 4*nf*TR)/6.0_dp
    else
       if (cc_piece == cc_REAL .or. cc_piece == cc_REALVIRT) & 
           & xPgg_func = 2*CA*(x/(one-x) + (one-x)/x + x*(one-x))
       if (cc_piece == cc_VIRT .or. cc_piece == cc_REALVIRT) & 
           & xPgg_func = xPgg_func - 2*CA*one/(one-x)
       xPgg_func = xPgg_func * x     ! remember to return x * Pgg
    end if
  end function xPgg_func
\end{lstlisting}
To address the issue that convolution operators can involve
plus-distributions and delta functions, the module
\texttt{convolution\_communicator} contains a variable
\texttt{cc\_piece} which indicates which part of the splitting
function is to be returned --- the real, virtual, real + virtual, or
$\delta$-function pieces. 

The initialisation of a \texttt{grid\_conv} object uses adaptive
Gaussian integration (a variant of CERNLIB's \texttt{dgauss}) to
calculate the convolution of the splitting function with trial weight
functions. The default accuracy for these integrations is $10^{-7}$.
It can be modified to value \texttt{eps} with the following subroutine
call
\begin{lstlisting}
  call SetDefaultConvolutionEps(eps)
\end{lstlisting}
which is to be made before creating the \ttt{grid\_def}
object. Alternatively, an optional \ttt{eps} argument can be
  included in the call to \ttt{InitGridDef} as follows:
\begin{lstlisting}
  type(grid_def) :: grid
  real(dp) :: eps
  [ ... set eps ... ]
  call InitGridDef(grid,dy=0.1_dp,ymax=10.0_dp,order=3,eps)
\end{lstlisting}
Note that {\tt eps} is just
one of the parameters affecting the final accuracy of convolutions. In
practice (unless going to extremely high accuracies) the grid spacing
and interpolation scheme are more critical.

Having allocated and initialised a \texttt{xPgg} splitting function, we
can go on to use it. For example: 
\begin{lstlisting}
  real(dp), pointer :: xPgg_x_xgluon(:)
  ...
  call AllocGridQuant(grid,xPgg_x_xgluon) !! Allocate memory for result of convolution
  xPgg_x_xgluon = xPgg .conv. xgluon      !! Convolution of xPgg with xgluon
\end{lstlisting}  
Since the return value of \texttt{xPgg .conv.\ xgluon} is just an F95
array, one can also write more complex expressions. Supposing we had
defined also a \texttt{xPgq} splitting function and a singlet
quark distribution \ttt{xquark}, 
as well as $\texttt{as2pi} = \as/2\pi$,
then to first order in $\as$ we could write the gluon evolution
through a step \texttt{dt} in $\ln Q^2$ as
\begin{lstlisting}
  xgluon = xgluon + (as2pi*dt) * ((xPgg .conv. xgluon) + (xPgq .conv. xquark))
\end{lstlisting}
Note that like \texttt{.aty.}, \texttt{.conv.} has a low precedence,
so the use of brackets is important to ensure that the above
expressions are sensible. Alternatively, the issues of precedence can
be addressed by using \texttt{*} (also defined as convolution when it
appears between a splitting function and a PDF) instead of
\texttt{.conv.}:
\begin{lstlisting}
  xgluon = xgluon + (as2pi*dt) * (xPgg*xgluon + xPgq*xquark)
\end{lstlisting}
Note that, for brevity, from now on we will drop the explicit use of
$x$ in front of names PDF and convolution operator variables.

As of version 2.1.0, it is also possible to initialise a
\ttt{grid\_def} with a class rather than a function.
%
In the \ttt{convolution} module, there is a \ttt{cong\_ignd} abstract
base class, with a procedure \ttt{f} that should be implemented in the
user's derived class:
\begin{lstlisting}
  type, extends(conv_ignd) :: my_splifn_class
    ! [...]
  contains
    procedure :: f => my_splitfn_f !< f(y,piece) function
  end type
\end{lstlisting}
The function takes two arguments: \ttt{y} as in the example above, and
also the \ttt{piece}, which is passed as an argument rather than using
the global \ttt{cc\_piece} variable.
%
This is intended to facilitate a path towards potential thread-safe
initialisation.
%
For an illustration of how one might use the class interface, users
can examine the \ttt{mvv\_splitting\_function} class in
\masterlink{src/splitting_function_interfaces.f90}, which makes it
possible to use functions with the standard MVV~\cite{NNLO-NS} interface as
\begin{lstlisting}
 call InitGridConv(grid, pgg2, mvv_splitting_function(P2GGA, P2GGB , P2GGC , 0.5_dp**3))
 call InitGridConv(grid, pqg2, mvv_splitting_function(P2QGA, null(), null(), 0.5_dp**3))
\end{lstlisting}
In this particular interface, the \ttt{A}, \ttt{B} and \ttt{C}
arguments are the regular, plus and delta-function functions, which
may be left as \ttt{null()} where the function is absent.
%
The last argument is a normalisation factor to convert from the $(\as/(4\pi))^3$
normalisation of the MVV functions to the $(\as/(2\pi))^3$
normalisation used in \hoppet.
%
It currently uses \hoppet's global $n_f$.
%
Note that as of v.2.1.0, this specific interface is not widely used
inside \hoppet and accordingly its details may evolve in future
releases.

%......................................................................
\subsubsection{Other operations on \texttt{grid\_conv} objects}
\label{sec:other_grid_conv_ops}
%
It is marginally less transparent to manipulate \texttt{grid\_conv} types
than PDF distributions, but still fairly simple:
\begin{lstlisting}
  call AllocGridConv(grid,Pab)         ! Pab memory allocated 
  call InitGridConv(grid,Pab)          ! Pab = 0             (opt.alloc)
  call InitGridConv(Pab,Pcd[,factor])  ! Pab = Pcd [*factor] (opt.alloc)
  call InitGridConv(grid,Pab,function) ! Pab = function      (opt.alloc)

  call SetToZero(Pab)                  ! Pab = 0
  call Multiply (Pab,factor)           ! Pab = Pab * factor
  call AddWithCoeff(Pab,Pcd[,coeff])   ! Pab = Pab + Pcd [*coeff]
  call AddWithCoeff(Pab,function)      ! Pab = Pab + function

  call SetToConvolution(Pab,Pac,Pcb)   ! Pab = Pac.conv.Pcb  (opt.alloc)
  call SetToConvolution(P(:,:),Pa(:,:),Pb(:,:))            ! (opt.alloc)
                                       ! P(:,:) = matmul(Pa(:,:),Pb(:,:))
  call SetToCommutator(P(:,:),Pa(:,:),Pb(:,:))             ! (opt.alloc)
                                       ! P(:,:) = matmul(Pa(:,:),Pb(:,:))
                                       !         -matmul(Pb(:,:),Pa(:,:))    

  call Delete(Pab)                     ! Pab memory freed
\end{lstlisting}
Routines labelled ``\texttt{(opt.alloc.)}''\ allocate the memory for
the \texttt{grid\_conv} object if the memory has not already been
allocated. (If it has already been allocated it is assumed to
correspond to the same grid as any other \texttt{grid\_conv} objects
in the same subroutine call). Some calls require that one specify the
grid definition being used (\texttt{grid}), because otherwise there is
no way for the subroutine to deduce which grid is being used.

If repeatedly creating a \texttt{grid\_conv} object for temporary use, it is
important to remember to \texttt{Delete} it afterwards, so as to avoid
memory leaks.

Nearly all the routines are partially overloaded so as to be able to
deal with one and two-dimensional arrays of \texttt{grid\_conv}
objects as well. The exceptions are those that initialise the
\texttt{grid\_conv} object from a function (arrays of functions do not
exist), as well as the convolution routines (for which the extension
to arrays might be considered non-obvious) and the commutation routine
which only has sense for matrices of \texttt{grid\_conv} objects.

%......................................................................
\subsubsection{Derived \texttt{grid\_conv} objects}
\label{sec:derived_grid_conv}

Sometimes it can be cumbersome to manipulate the \texttt{grid\_conv}
objects directly, for example when trying to create a
\texttt{grid\_conv} that represents not a fixed order splitting
function, but the resummed evolution from one scale to another. For
such situations the following approach can be used
\begin{lstlisting}
  real(dp), pointer :: probes(:,:)
  type(grid_conv)   :: Pqg, Pgq, Presult
  integer           :: i

  call GetDerivedProbes(grid,probes) ! get a set of 'probes'
  do i = 1, size(probes,dim=2)       ! carry out operations on each of the probes
    probes(:,i) = Pqg*(Pgq*probes(:,i)) - Pgq*(Pqg*probes(:,i))
  end do
  call AllocGridConv(grid,Presult)
  call SetDerivedConv(Presult,probes) ! Presult = [Pqg,Pgq]
\end{lstlisting}
Here \texttt{GetDerivedProbes} allocates and sets up an array of probe
parton distributions. Since a single-flavour parton distribution is a
one-dimensional array of \texttt{real(dp)}, the array of probes is a
two-dimensional array of \texttt{real(dp)}, the second dimension
corresponding to the index of the probe. One then carries out whatever
operations one wishes on each of the probes. Finally with the call to
\texttt{SetDerivedConv}, one can reconstruct a \texttt{grid\_conv}
object that corresponds to the set of operations just carried out

Some comments about memory allocation: the probes are automatically
allocated and deallocated; in contrast the call to
\texttt{SetDerivedConv(Presult,probes)} knows nothing about the grid,
so \texttt{Presult} must have been explicitly allocated for a specific
grid beforehand.

A note of caution: when one's grid is made of nested subgrids with the
locking option set to \texttt{.true.}, after a convolution of a
\texttt{grid\_def} object with a parton distribution, the coarser
grids for the parton distribution are supplemented with more accurate
information from the finer grids. When carrying out multiple
convolutions, this happens after each convolution.  There is no way to
emulate this with a single \texttt{grid\_def} object, and the locking
would actually confuse the reconstruction of resulting
\texttt{grid\_def} object. So when the user requests the probes,
locking is temporarily turned off globally and then reestablished
after the derived \texttt{grid\_object} has been constructed. Among
other things this means that acting with a derived
\texttt{grid\_object} will not be fully equivalent to carrying out the
individual operations separately. In particular the accuracy may be
slightly lower (whatever is lost due to the absence of intermediate
locking).


%------------------------------------------------------------
\subsection{Truncated moments}
\label{sec:sum-rules}

There are various contexts in which it is useful to evaluate moments
of PDFs, notably in checking sum rules. Since \hoppet doesn't store
PDFs over the full range of $x$, one cannot calculate full moments,
but only truncated moments.
%
%
Truncated moments are calculated via the function
\begin{lstlisting}
  TruncatedMoment(grid, xparton, N [,ymax])
\end{lstlisting}
with the convention that the result $M_N$ is 
\begin{equation}
  \label{eq:truncMom}
  %M_N\lc xq(x,Q^2)\rc \equiv \int_0^{y_{\rm max}} dy e^{-yN} xq\lp y,Q^2 \rp \ ,
  M_N [\ttt{xparton}] \equiv \int_0^{y_{\rm max}} dy \,e^{-yN}\,
  \ttt{xparton.aty.(}y\ttt{.with.grid)}\,.
\end{equation}
The moment index $N$ must be a double precision number, and if the argument
\ttt{ymax} is not supplied, the integral extends to largest $y$ value
present in the grid, \ttt{grid\%ymax}. The integral is evaluated using
adaptive Gaussian integration with the same default precision that was
set for the determination of grid convolution operators. 
%
The use of adaptive Gaussian integration implies that the evaluation
of moments is not optimally efficient for repeated use of the same
moment index with different PDFs.\footnote{Should a user have an
  application in which the repeated evaluation of truncated moments is
  the main time-consuming step, then they are advised to contact the
  authors for further advice.}

As as example, the calculation of the momentum contained in the gluon
would proceed as follows:
\begin{lstlisting}
  real(dp), pointer :: xgluon(:)
  real(dp)          :: N, gluon_momentum
  ! [ ... other vars, allocation, intialisation ...]
  N = 1.0_dp
  gluon_momentum = TruncatedMoment(grid, N, xgluon)
\end{lstlisting}
For a further example, see also section~\ref{sec:acc_table}.
%
Note that for $\ttt{ymax}= 12$ (a value used in many of the example
programs), the truncation can underestimate the sum rules by a
fraction of a percent. This underestimation is largest
at higher values of $Q^2$, due to the perturbative growth of PDFs
at small-$x$ at large-$Q^2$.

%------------------------------------------------------------
\subsection{Parton Luminosities}
\label{sec:parton-luminosities}

The parton luminosity function ${\cal L}(\tau)$ obtained from two
parton distributions $x q_i(x)$ and $x q_j(x)$, defined as
\begin{equation}
  \label{eq:parton-lumi}
  {\cal L}_{ij}(\tau) = \int_{\tau}^1 \frac{dx}{x} \,  x q_i(x) \, \frac{\tau}{x}
  q_j\left(\frac{\tau}{x} \right) 
  = 
  \tau \int_{\tau}^1 \frac{dx}{x}   q_i(x) \,
  q_j\left(\frac{\tau}{x} \right)
\end{equation}
is a quantity that enters evaluations of many total cross sections at
hadron-hadron colliders: e.g.\ the LO cross section for producing a
boson with mass $M$ through fusion of partons of types $i$ and $j$ is
proportional to ${\cal L}_{ij}(M^2/s)$, where $s$ is the squared centre of
mass energy of the hadron-hadron collision.

The parton luminosity function is represented as a grid quantity
\begin{lstlisting}
  real(dp), pointer :: lumi(:), xqi(:), xqj(:)
  ! [... lumi, xqi and xqj should all be allocated as standard grid quantities]
  lumi = PartonLuminosity(grid, xqi, xqj)
\end{lstlisting}
and all standard operations on grid quantities can be used with it,
for example convolutions with splitting functions, evaluations at
particular values of $y$ or $x$, and so forth.

Parton luminosities are a new feature of the 1.1.5 release of \hoppet
and should be considered ``beta'' functionality, valid only for PDFs
that vanish smoothly for $x\to 1$, the same assumption that enters
the use of negative \ttt{order} values (cf.\
Fig.~\ref{fig:interpolation-orders}). 
%
In particular, for grids with a single spacing, they are evaluated
through the sum
\begin{equation}
  \label{eq:lumi-tricks}
  {\cal L}_{ij,\alpha} = \texttt{dy} \times \sum_{\beta=0}^{\alpha}
  \,q_{i,\beta}\, q_{j,\alpha-\beta} \,.
\end{equation}
At first sight, this might appear to be a low-order integration
formula.
%
However one can show that if one superposes multiple higher-order
integration formulae, each shifted by one grid unit, then one obtains
Eq.~(\ref{eq:lumi-tricks}) as long as the integrand vanishes
sufficiently smoothly at its upper and lower limits, as is the case
with physical PDFs.
%
When using multiple locked grid spacings, say a coarse and a fine
grid, $\ttt{dy}_1 > \ttt{dy}_{2}$, $\ttt{ymax}_1 > \ttt{ymax}_{2}$,
then for $y$ up to $2\ttt{ymax}_2$ the luminosity sum is evaluated
using the fine grid spacing, taking information directly from the fine
grid for the PDFs up to $\ttt{ymax}_2$, plus interpolation from
the coarse grid onto the fine grid for points up to $2\ttt{ymax}_2$
(the interpolation order is that of the coarse grid).
%
This procedure has been found to give accuracies comparable to those obtained
for convolutions. 
%
Note that it may be modified in future versions of HOPPET.

%======================================================================
%======================================================================
\section{Multi-flavour grids and convolutions}
\label{sec:dglapstructs}

The discussion in the previous section 
about how to represent functions and associated convolutions
in a general $x-$space grid holds for any kind of problem involving
convolutions, even if the examples were given in the context of DGLAP
evolution. In this section we shall examine the tools made available
specifically to address the DGLAP evolution problem.


%----------------------------------------------------------------------
\subsection{Full-flavour PDFs and flavour representations}
\label{sec:pdf-objects}

The routines described in this section
 are available from the \ttt{pdf\_general}
and \ttt{pdf\_representation} modules, or via the \ttt{hoppet}
general module.

Full flavour PDFs sets are just like single flavour PDFs except that they
have an extra dimension. They are represented by arrays, and if you
want \hoppet to deal with allocation for you, they should be pointer
arrays. One can allocate a single PDF (two dimensional
\texttt{real(dp)} array) or an array of PDFs (three-dimensional
\texttt{real(dp)} array)
\begin{lstlisting}
  real(dp), pointer :: PDF(:,:), PDFarray(:,:,:)
  call AllocPDF(grid,PDF)            ! allocates PDF(0:,-6:7)
  call AllocPDF(grid,PDFarray,0,10)  ! allocates PDFarray(0:,-6:7,0:10)
\end{lstlisting}
The first dimension corresponds to the grid in $y$; the second
dimension corresponds to the flavour index. Its lower bound is $-6$,
as one would expect. 

What takes a bit more getting used to is that its
upper bound is \textbf{7}. The reason is as follows: the flavour
information can be represented in different ways, for example each
flavour separately, or alternatively as singlet and non-singlet
combinations. In practice both are used inside the program and it is
useful for a PDF distribution to have information about the
representation, and this is stored in
\texttt{PDF(:,7)}\footnote{
In the current release of \hoppet, 
in particular, for PDFs in the \ttt{human} representation one
has \texttt{PDF(:,7)=0}, while for PDFs in the \ttt{evln}
representation, the information on the active number of flavours
is encoded as
\ttt{nf = (abs(q(2,7))+abs(q(3,7)))/(abs(q(0,7))+abs(q(1,7)))},
so that it is conserved under linear operations.
%
However the details of the encoding may evolve in future
versions of the program.
}.


%......................................................................
\subsubsection{Human representation.}
\label{sec:human-rep}
When a PDF is allocated it is automatically labelled as being in the
\ttt{human} representation, described in
section~\ref{sec:pqcd}. Constants with names like
\ttt{iflv\_bbar}, \ttt{iflv\_g}, \ttt{iflv\_b}, are defined in
\ttt{module pdf\_representation}, to facilitate symbolic access to the
different flavours.

If you are creating a PDF as an automatic array (one whose bounds are
decided not by the allocation routine, but on the fly), for example in
a function that returns a PDF, then you should label it yourself as
being in the \ttt{human} representation, either with the
\ttt{LabelPdfAsHuman(pdf)} subroutine call, or by setting
\ttt{pdf(:,7)} to zero:
\begin{lstlisting}
module pdf_initial_condition
  use hoppet; implicit none
contains
  function unpolarized_dummy_pdf(xvals) result(pdf)
    real(dp), intent(in) :: xvals(:)
    real(dp)             :: pdf(size(xvals),-6:7)

    ! clean method for labelling a PDF as being in the human representation
    call LabelPdfAsHuman(pdf)
    ! Alternatively, by setting everything to zero 
    ! (notably pdf(:,7)), the PDF representation
    ! is automatically set to be human
    pdf(:,:) = 0
    
    ! iflv_g is pre-defined integer parameter (=0) for symbolic ref. to gluon
    pdf(:,iflv_g) = 1.7_dp * xvals**(-0.1_dp) * (1-xvals)**5 ! Returns x*g(x)
    [... set other flavours here ...]
  end function unpolarized_dummy_pdf
end module pdf_initial_condition
\end{lstlisting}
The function has been placed in a module so as to provide an easy way
for a calling routine to have access to its interface (this is needed
for the dimension of \ttt{xvals} to be correctly passed).  Writing a
function such as that above is probably the easiest way of
initialising a PDF:
\begin{lstlisting}
  use hoppet; use pdf_initial_condition; implicit none
  type(grid_def)    :: grid
  real(dp), pointer :: pdf(:,:)
  [...]
  call AllocPDF(grid,pdf)
  pdf = unpolarized_dummy_pdf(xValues(grid))
\end{lstlisting}
There exist a number of other options, which can be found by browsing
through \ttt{src/pdf\_general.f90}. Of these a sometimes handy one is
\begin{lstlisting}
  call AllocPDF(grid,pdf)
  call InitPDF_LHAPDF(grid, pdf, LHAsub, Q)
\end{lstlisting}
where \texttt{LHAsub} is the name of a subroutine 
with the same interface as LHAPDF's \ttt{evolvePDF}~\cite{LHAPDF}:
\begin{lstlisting}
  subroutine LHAsub(x,Q,res)
    use types; implicit none
    real(dp), intent(in)  :: x,Q
    real(dp), intent(out) :: res(-6:6) ! on output contains flavours -6:6 at x,Q
    [...]                              ! Note that it should return momentum densities
  end subroutine LHAsub
\end{lstlisting}
Note that {\tt LHAsub} should return momentum densities, as
happens with the LHAPDF routines \cite{LHAPDF}.


Having initialised a PDF, to then extract it at a given $y$ value, one
can either examine a particular flavour using the methods described in
section~\ref{sec:xspc}
\begin{lstlisting}
  real(dp) :: y, gluon_at_y
  gluon_at_y = pdf(:,iflv_g) .aty. (y.with.grid)
  ! OR
 gluon_at_y = EvalGridQuant(grid,pdf(:,iflv_g),y) 
\end{lstlisting}
or one can extract all flavours simultaneously
\begin{lstlisting}
  real(dp) :: pdf_at_y(-6:6)
  pdf_at_y = pdf(:,-6:6) .aty. (y.with.grid)
  ! OR
  pdf_at_y =  EvalGridQuant(grid,pdf(:,-6:6),y) 
\end{lstlisting}
with the latter being more efficient if one needs to extract all
flavours simultaneously. Note that here we have explicitly specified
the flavours, \ttt{-6:6}, that we want.\footnote{If instead we had
  said \ttt{pdf(:,:)} the result would have corresponded to a slice of
  flavours \ttt{-6:7}, \ie including an interpolation of the
  representation labelling information, which would be meaningless.}


%......................................................................
\subsubsection{Evolution representation} 
\label{sec:evln-rep}
%
For the purpose of carrying out convolutions, the \ttt{human}
representation is not very advantageous because the splitting matrix
in flavour space is quite complicated. Accordingly \hoppet uses a
different representation of the flavour internally when carrying out
convolution of splitting matrices with PDFs. For most purposes the
user need not be aware of this. The two exceptions are when a user
plans to create derived splitting matrices (being careless about the
flavour representation will lead to mistakes) or wishes to carry out
repeated convolutions for a fixed $n_f$ value (appropriate manual
changes of the flavour representation can speed things up).


The splitting matrix can be simplified considerably by switching to a different
flavour representation, as can be seen in Table \ref{eq:diag_split}. 
 When carrying out a convolution, the only non-diagonal part is the
block containing indices $0,1$. This representation is referred to as
the \ttt{evln} representation. Whereas the \ttt{human} representation
is $n_f$-independent, the \ttt{evln} depends on $n_f$ through the
$\Sigma$ and $q_{\mathrm{NS}}^{V}$ entries and the fact that flavours
beyond $n_f$ are left in the human representation (since they are
inactive for evolution with $n_f$ flavours).

To take a PDF in the \ttt{human} representation and make a copy in an
\ttt{evln} representation, one uses the \ttt{CopyHumanPdfToEvln} routine
\begin{lstlisting}
  real(dp), pointer :: pdf_human(:,:), pdf_evln(:,:)
  integer           :: nf_lcl ! NB: nf would conflict with global variable
  [... setting up pdf_human, nf_lcl, etc. ...] 
  call AllocPDF(grid,pdf_evln)  ! or it might be an automatic array
  call CopyHumanPdfToEvln(nf_lcl, pdf_human, pdf_evln) ! From human to evolution representation
\end{lstlisting}
where one specifies the $n_f$ value for the \ttt{evln} representation.
One can go in the opposite direction with
\begin{lstlisting}
  call CopyEvlnPdfToHuman(nf_lcl, pdf_evln, pdf_human)
\end{lstlisting}
At any time one can check which is the representation of a given
PDF using the \ttt{GetPdfRep} function,
\begin{lstlisting}
  integer nf_rep
  real(dp), pointer :: pdf(:,:)

  [... set up pdf, ...]
  nf_rep = GetPdfRep(pdf)
\end{lstlisting}
which returns the number of active flavours if the PDF is in the
\ttt{evln} representation, or a negative integer if 
the PDF is in the
\ttt{human} representation.


%----------------------------------------------------------------------
\subsection{Splitting function matrices}
\label{sec:splitt-funct-matr}

Splitting function matrices and their actions on PDFs are defined in
   ~\ttt{module dglap\_objects} (accessible as usual from \ttt{module
  hoppet}). They have type \ttt{split\_mat}. Below we shall discuss
routines for creating specific predefined DGLAP splitting matrices,
but for now we consider a general splitting matrix.

The allocation of \ttt{split\_mat} objects,
\begin{lstlisting}
  type(split_mat) :: P
  integer         :: nf_lcl
  call AllocSplitMat(grid, P, nf_lcl)
\end{lstlisting}
is similar to that for \ttt{grid\_conv} objects. The crucial difference is
that one must supply a value for $n_f$, so that when the splitting
matrix acts on a PDF it knows which flavours are decoupled. From the
point of view of subsequent initialisation a \ttt{split\_mat} object
just consists of a set of splitting functions. 
If need be, they can be
initialised by hand, for example
\begin{lstlisting}
  call InitGridConv(grid,P%qq      , P_function_qq      )
  call InitGridConv(grid,P%qg      , P_function_qg      )
  call InitGridConv(grid,P%gq      , P_function_gq      )
  call InitGridConv(grid,P%gg      , P_function_gg      )
  call InitGridConv(grid,P%NS_plus , P_function_NS_plus )
  call InitGridConv(grid,P%NS_minus, P_function_NS_minus)
  call InitGridConv(grid,P%NS_V    , P_function_NS_V    )
\end{lstlisting}
One can then write
\begin{lstlisting}
  real(dp), pointer :: q(:,:), delta_q(:,:)
  [... allocations, etc. ...]
  delta_q = P .conv. q
  ! OR
  delta_q = P * q
\end{lstlisting}
and $\ttt{delta\_q}$ will have the following components
\begin{align}
  \label{eq:Pmat_on_q}
  \left(\!\!
    \begin{array}{c}
      \delta\Sigma\\
       \delta g
    \end{array}
  \!\!\right)
    \;&= \;
  \left(
    \begin{array}{cc}
      \ttt{P\%qq} & \ttt{P\%qg}\\
      \ttt{P\%gq} & \ttt{P\%gg}
    \end{array}
  \right) 
  \otimes
  \left(\!\!
    \begin{array}{c}
      \Sigma\\
       g
    \end{array}
    \!\!\right) 
  \nonumber\\[3pt]
%
  \delta q^+_{\mathrm{NS},i} \;&=\; \ttt{P\%NS\_plus} \otimes
  q^+_{\mathrm{NS},i}\\[3pt] 
%
  \delta q^-_{\mathrm{NS},i} \;&=\; \ttt{P\%NS\_minus} \otimes
  q^-_{\mathrm{NS},i}\nonumber \\[3pt]
% 
  \delta q^V_{\mathrm{NS}} \;&=\; \ttt{P\%NS\_V} \otimes
  q^V_{\mathrm{NS}} \nonumber
\end{align}
We have written the result in terms of components in the \ttt{evln}
representation (and this is the representation used for the actual
convolutions). When a convolution with a PDF in \ttt{human}
representation is carried out, the program automatically copies the
PDF to the \ttt{evln} representation, carries out the convolution and
converts the result back to the \ttt{human} representation.
%
The cost of changing a representation is $\order{N_x}$, whereas the
convolution is $\order{N^2_x}$, so in principle the former is
negligible. In practice, especially when aiming for high speed at low
$N_x$, the change of representation can imply a significant cost. In
such cases, if multiple convolutions are to be carried out, it may be
advantageous to manually change into the appropriate \ttt{evln}
representation, carry out all the convolutions and then change back
manually to
the \ttt{human}  representation at the end, see
section~\ref{sec:pdf-objects}.
%

As for \ttt{grid\_conv} objects, a variety of routines have been
implemented to help manipulate splitting matrices:
\begin{lstlisting}
  type(split_mat) :: PA, PB, PC
  real(dp) :: factor

  call InitSplitMat(PA,PB[,factor])   ! PA = PB [*factor]   (opt.alloc)

  call SetToZero(PA)                  ! PA = 0
  call Multiply(PA,factor)            ! PA = PA * factor               
  call AddWithCoeff(PA,PB[,factor])   ! PA = PA + PB [*factor]

  call SetToConvolution(PA,PB,PC)     ! PA = PB*PC          (opt.alloc)
  call SetToCommutator(PA,PB,PC)      ! PA = PB*PC-PC*PB    (opt.alloc)
  
  call Delete(split_mat)              ! PA's memory freed
\end{lstlisting}


%......................................................................
\subsubsection{Derived splitting matrices}
\label{sec:derived-split-matrices}

As with \ttt{grid\_conv} objects, \hoppet provides means to construct
a \ttt{split\_mat} object that corresponds to an arbitrary series of
\ttt{split\_mat} operations, as long as they all involve the same
value of $n_f$. One proceeds in a very similar way as
in section~\ref{sec:derived_grid_conv},
\begin{lstlisting}
  real(dp), pointer :: probes(:,:,:)
  type(split_mat)  :: PA, PB, Pcomm
  integer           :: i

  [...set nf_lcl,...]
  call GetDerivedSplitMatProbes(grid,nf_lcl,probes) ! get the probes
  do i = 1, size(probes,dim=3)               ! carry out operations on each probe
    probes(:,:,i) = PA*(PB*probes(:,:,i)) - PB*(PA*probes(:,:,i))
  end do
  call AllocSplitMat(grid,Pcomm,nf_lcl)      ! provide nf info in initialisation
  call SetDerivedConv(Pcomm,probes)          ! Presult = [Pqg,Pgq]
\end{lstlisting}
Note that we need to provide the number of active quark flavours
to \ttt{GetDerivedSplitMatProbes}.
As in section~\ref{sec:derived_grid_conv}, we first need to set up
some `probe' PDFs (note the extra dimension compared to earlier, since
we also have flavour information; the probe index always corresponds
to the last dimension); then we act on those probes; finally we
allocate the splitting matrix, and set its contents based on the
probes, which are then automatically deallocated.



%----------------------------------------------------------------------
\subsection{The DGLAP convolution components}
\label{sec:dglap_holder}

%......................................................................
\subsubsection{QCD constants}
\label{sec:qcd}

The splitting functions that we set up will depend on various QCD
constants ($n_f$, colour factors), so it is useful to here to
summarise how they are dealt with within the program.

The treatment of the QCD constants is \emph{not} object oriented.
There is a module (\ttt{qcd}) that provides access to commonly used
constants in QCD:
\begin{lstlisting}
  real(dp) :: ca, cf, tr, nf
  integer  :: nf_int
  
  real(dp) :: beta0, beta1, beta2
  [ ... ]
\end{lstlisting}
Note that \ttt{nf} is in double precision
 --- if you want the integer value of $n_f$, use \ttt{nf\_int}. 

To set the value of $n_f$, call
\begin{lstlisting}
  integer :: nf_lcl
  call qcd_SetNf(nf_lcl)  
\end{lstlisting}
where we have used the local 
variable \ttt{nf\_lcl} to avoid conflicting with
the \ttt{nf} variable provided by the \ttt{qcd} module. Whatever you
do, do not simply modify the value of the \ttt{nf} variable by hand
--- when you call \ttt{qcd\_SetNf} it adjusts a whole set of other
constants (\eg the $\beta$ function coefficients) appropriately.

There are situations in which it's of interest to vary the other
colour factors of QCD, for example, if these
colour factors are to be determined from a fit
to deep-inelastic scattering experimental data. For that purpose, use
\begin{lstlisting}
  real(dp) :: ca_lcl, cf_lcl, tr_lcl
  call qcd_SetGroup(ca_lcl, cf_lcl, tr_lcl)
\end{lstlisting}
Again all other constants in the \ttt{qcd} module will be adjusted. A
word of caution: the NNLO splitting functions actually depend on a
colour structure that goes beyond the usual $C_A$, $C_F$ and $T_R$,
namely $d_{abc}d^{abc}$, which in the present version of \hoppet
is hard-wired to its default QCD value.




%......................................................................
\subsubsection{DGLAP splitting matrices}
\label{sec:dglap-split}

The module \ttt{dglap\_objects} includes a number of routines for
providing access to the \ttt{split\_mat} objects corresponding to
DGLAP splitting functions
\begin{lstlisting}
  type(split_mat) :: P_LO, P_NLO, P_NNLO
  type(split_mat) :: Pp_LO, Pp_NLO        ! polarised

  ! MSbar unpolarised case
  call InitSplitMatLO  (grid, P_LO)
  call InitSplitMatNLO (grid, P_NLO)
  call InitSplitMatNNLO(grid, P_NNLO)

  ! the MSbar polarised case...
  call InitSplitMatPolLO (grid, Pp_LO)
  call InitSplitMatPolNLO(grid, Pp_NLO)
\end{lstlisting}
In each case the splitting function is set up for the $n_f$ and
colour-factor values that are current in the $\ttt{qcd}$ module, as
set with the \ttt{qcd\_SetNf} and \ttt{qcd\_SetGroup} subroutine calls. If one
subsequently resets the $n_f$ or colour factor values, the \ttt{split\_mat}
objects continue to correspond to the $n_f$ and colour factor values
for which they were initially calculated.
With the above subroutines for initialising DGLAP splitting functions,
the normalisation is as given in eq.~(\ref{eq:dpdf}).

When carrying out DGLAP evolution it is most
efficient to first sum the splitting matrices and then carry out the
convolution,
\begin{lstlisting}
  type(split_mat)   :: P_sum
  real(dp), pointer :: q(:,:), dq(:,:)
  [ ... ]
  call InitSplitMat(P_sum, P_LO)            ! P_sum = P_LO
  call AddWithCoeff(P_sum, P_NLO, as2pi)    ! P_sum = P_sum + as2pi * P_NLO
  dq = (as2pi * dt) * (P_sum .conv. q)      ! Step dt in evolution
  call Delete(P_sum)                        ! Memory freed
\end{lstlisting}
This is because convolutions take a time $\order{N^2}$, where $N$ is the
number of points in the grid, whereas additions and multiplications
take a time $\order{N}$.
%
Note the use of brackets in the line setting \ttt{dq}: all scalar
factors are first multiplied together ($\order{1}$) so that we only
have one multiplication of a PDF ($\order{N_x}$). Note also that we have
chosen to include the \ttt{(as2pi * dt)} factor as multiplying the
pdf, rather than the other option of multiplying {P\_sum}, \ie 
\begin{lstlisting}
  call Multiply(P_sum, (as2pi * dt))
  dq =  P_sum .conv. q
\end{lstlisting}
The result would have been identical, but splitting matrices with
positive interpolation \ttt{order} essentially amount to an
$\order{7\times \ttt{order} \times N}$ sized array, whereas the PDF is
an $\order{13 N}$ sized array and the for high positive orders that
are sometimes used, it is cheaper to multiply the latter. 

The default for the NNLO splitting functions are the interpolated
expressions, which are very fast
to evaluate. Other possibilities, like
the exact splitting functions or a previous set of approximated NNLO
splitting functions which was used before the full
calculation was available are described in Appendix \ref{sect:nnlo}.
Note that the QCD colour factors introduced in section~\ref{sec:qcd}
cannot be modified if the interpolated NNLO splitting functions
are used, since these expressions use the default QCD values.





%......................................................................
\subsubsection{Mass threshold matrices}
\label{sec:mtm}

Still in the \ttt{dglap\_objects} module, we have a type dedicated to
crossing heavy quark mass thresholds.
\begin{lstlisting}
  type(grid_def)           :: grid
  type(mass_threshold_mat) :: MTM_NNLO

  call InitMTMNNLO(grid, MTM_NNLO)   ! MTM_NNLO is coeff of (as/2pi)**2
\end{lstlisting}
This is the coefficient of $(\as/2\pi)^2$ for the convolution matrix
that accounts for crossing a heavy flavour threshold in $\MSbar$
factorisation scheme, at $\mu_F = m_h$, where $m_h$ is the heavy-quark
pole mass (or $\MSbar$ mass), as has been described in
section~\ref{sec:pqcd}. Since the corresponding NLO term is zero, the
number of flavours in $\as$ is immaterial at NNLO.

The treatment of $n_f$ in the \ttt{mass\_threshold\_mat} is very
specific because at NNLO, the only order in the $\MSbar$ factorisation
scheme at which it's non-zero and currently known, it is independent of $n_f$.
Its action does of course however depend on $n_f$. 
%
Since, as for \ttt{split\_mat} objects, we don't want the action of
the \ttt{mass\_threshold\_mat} to depend on the availability of the
current $n_f$ information from the \ttt{qcd} module, instead we
require that before using a \ttt{mass\_threshold\_mat}, you should
explicitly indicate the number of flavours (defined as including the
new heavy flavour).
%
This is done using a call to the
\ttt{SetNfMTM(MTM\_NNLO,nf\_incl\_heavy)} subroutine. A similar function
\ttt{SetMassSchemeMTM( MTM\_NNLO, masses\_are\_MSbar)} can be used to
specify whether the threshold is being crossed at a pole mass or
$\MSbar$ mass.
%
So for example to take a PDF in the effective theory with $n_f=3$
active flavours \ttt{pdf\_nf3}, and convert it to the corresponding
PDF in the effective theory with $n_f=4$ active flavours
\ttt{pdf\_nf4} at $m_h^2$ (pole mass), one uses code analogous to the following
\begin{lstlisting}
  real(dp) :: pdf_nf3(:,:), pdf_nf4(:,:)
  logical  :: masses_are_MSbar = .false.
  [ ... ]
  call SetNfMTM(MTM, 4)
  call SetMassSchemeMTM(MTM, masses_are_MSbar)
  pdf_nf4 = pdf_nf3 + (as2pi)**2 * (MTM_NNLO.conv.pdf_nf3)
\end{lstlisting}
The convolution only works if the \ttt{pdf}'s are in the \ttt{human}
representation and an error is given if this is not the case. Any
heavy flavour (like for example intrinsic charm) 
present in \ttt{pdf\_nf3} would be left in unchanged.

Note that the type {\tt mass\_threshold\_mat}
is not currently suitable for general changes of
flavour-number. For example if you wish to carry out a change in the
DIS scheme or at a scale $\mu_F \neq m_h$ then you have
to combine a series of different convolutions (essentially correcting
with the lower number of flavours to the $\MSbar$ factorisation scheme
at $\mu_F = m_h$ before changing the number of flavours
and then correcting back to the original scheme and scale using the
higher number of flavours).


As for the NNLO splitting functions, the mass threshold corrections
come in exact and parametrised variants. By default it is the latter
that is used (provided by Vogt \cite{VogtMTMParam}).  The cost of
initialising with the exact variants of the mass thresholds is much
lower than for the exact NNLO splitting functions (partly because
there is no $n_f$ dependence, partly because it is only one flavour
component of the mass-threshold function that is complex enough to
warrant parametrisation). The variant can be chosen by the user
before initialising the \ttt{mass\_threshold\_mat} by making the
following subroutine call:
\begin{lstlisting}
  integer :: threshold_variant
  call dglap_Set_nnlo_nfthreshold(threshold_variant)
\end{lstlisting}
with the following variants defined (as integer parameters), again in
the module \ttt{dglap\_choices}:
\begin{lstlisting}
  nnlo_nfthreshold_exact
  nnlo_nfthreshold_param                 [default]
\end{lstlisting}


%......................................................................
\subsubsection{Putting it together: \ttt{dglap\_holder}}

The discussion so far in this subsection was intended to provide the
reader with an overview of the different DGLAP components that have
been implemented and of how they can be initialised individually. This
is useful above all if the user needs to tune the program to some
specific unusual application.

In practice, we foresee that most users will need just a standard
DGLAP evolution framework, and so will prefer not to manage
all these components individually. Accordingly \hoppet provides a
type, $\ttt{dglap\_holder}$ which holds all the components 
required for
a given kind of evolution. To initialise all information for a
fixed-flavour number evolution, one does as follows
%
\begin{lstlisting}
  use hoppet
  type(dglap_holder) :: dglap_h
  integer            :: factscheme, nloop, nf_lcl  

  nloop      = 3                 ! NNLO
  factscheme = factscheme_MSbar  ! or: factscheme_DIS; factscheme_PolMSbar
  nf_lcl = 4
  call qcd_SetNf(nf_lcl)         ! set the fixed number of flavours
  ! call qcd_SetGroup(...)       ! if you want different colour factors

  ! now do the initialisation
  call InitDglapHolder(grid, dglap_h, factscheme, nloop)
\end{lstlisting}
The constants \ttt{factscheme\_*} are defined in \ttt{module
  dglap\_choices}. %
The corrections to the splitting functions to get the DIS scheme are
implemented by carrying out appropriate convolutions of the $\MSbar$
splitting and coefficient functions. Currently the DIS scheme is only
implemented to NLO.\footnote{Its NNLO implementation would actually be fairly
straightforward given the parametrisation provided in
\cite{White:2005wm}, and may be performed in
future releases of \hoppet.} %
The polarised splitting functions are only currently known to NLO.

Initialisation can also be carried out with a single call for a range of
different numbers of flavours:
\begin{lstlisting}
  integer :: nflo, nfhi
  [...]
  nflo = 3; nfhi = 6    ! [calls to qcd_SetNf handled automatically]
  call InitDglapHolder(grid, dglap_h, factscheme, nloop, nflo, nfhi)
\end{lstlisting}
Mass thresholds are not currently correctly supported in the DIS
scheme, even at NLO.

For all the above calls, at NNLO the choice of exact of parametrised
splitting functions and mass thresholds is determined by the calls to
\ttt{dglap\_Set\_nnlo\_splitting} and
\ttt{dglap\_Set\_nnlo\_nfthreshold}, as described in
sections~\ref{sec:dglap-split} and \ref{sec:mtm} respectively. These
calls must be made prior to the call to \ttt{InitDglapHolder}.

Having initialised a \ttt{dglap\_holder} one has access to various components:
\begin{lstlisting}
  type dglap_holder
    type(split_mat), pointer :: allP(1:nloop, nflo:nfhi)  ! FFNS: nflo=nfhi=nf_lcl
    type(split_mat), pointer :: P_LO, P_NLO, P_NNLO
    type(mass_threshold_mat) :: MTM2
    logical                  :: MTM2_exists
    integer                  :: factscheme, nloop
    integer                  :: nf
    [ ... ]
  end type dglap holder
\end{lstlisting}
Some just record information passed on initialisation, for example
\ttt{factscheme} and \ttt{nloop}. Other parts are set up once and for
all on initialisation, notably the \ttt{allP} matrix, which contains
the 1-loop, 2-loop, etc. splitting matrices for the requested $n_f$
range.

Yet other parts of the \ttt{dglap\_holder} type depend on $n_f$.
Before accessing these, one should first perform the following call:
\begin{lstlisting}
  call SetNfDglapHolder(dglap_h, nf_lcl)
\end{lstlisting}
This creates links:
\begin{lstlisting}
  dglap_h%P_LO   => dglap_h%allP(1,nf_lcl)
  dglap_h%P_NLO  => dglap_h%allP(2,nf_lcl)
  dglap_h%P_NNLO => dglap_h%allP(3,nf_lcl)
\end{lstlisting}
for convenient named access to the various splitting matrices, and it
also sets the global (\ttt{qcd}) $n_f$ value (via a call to
\ttt{qcd\_SetNf}) and where relevant updates the internal $n_f$ value
associated with \ttt{MTM2} (via a call to \ttt{SetNfMTM}).

As with other types that allocate memory for derived types, that
memory can be freed via a call to the \ttt{Delete} subroutine,
\begin{lstlisting}
  call Delete(dglap_h)
\end{lstlisting}

%======================================================================
\section{DGLAP evolution}
So far we have described all the tools that are required
to perform  DGLAP convolutions of PDFs. In this section
we describe how the different ingredients are put together
to perform the actual evolution.


%----------------------------------------------------------------------
\subsection{Running coupling}
\label{sec:run-coupl}

Before carrying out any DGLAP evolutions, one first needs to set up 
a \ttt{running\_coupling} object (defined in \ttt{module
  qcd\_coupling}):
\begin{lstlisting}
  type(running_coupling) :: coupling
  real(dp) :: alfas, Q, quark_masses(4:6), muMatch_mQuark
  integer  :: nloop, fixnf

  [... set parameters ...]
  call InitRunningCoupling(coupling [, alfas] [, Q] [, nloop] [, fixnf]&
                          & [, quark_masses] [, masses_are_MSbar] [, muMatch_mQuark])
\end{lstlisting}
As can be seen, many of the arguments are optional. Their default
values are as follows:
\begin{lstlisting}
  Q     = 91.2_dp
  alfas = 0.118_dp  ! Value of coupling at scale Q
 
  nloop = 2
  fixnf = [.not. present]
                       !     charm,      bottom,   top
  quark_masses(4:6) = (/ 1.414213563_dp, 4.5_dp, 175.0_dp /) ! Heavy quark pole masses
  muMatch_mQuark    = 1.0_dp
\end{lstlisting}
The running coupling object is initialised so that at scale \ttt{Q}
the coupling is equal to \ttt{alfas}. The running is carried out with
the \ttt{nloop} $\beta$-function. 
%
The highest value currently supported is 4 loops.
%
If the \ttt{fixnf} argument is
present, then the number of flavours is kept fixed at that
value. Otherwise flavour thresholds are implemented at scales
\begin{lstlisting}
  muMatch_mQuark * quark_masses(4:6)
\end{lstlisting}
By default the quark masses are taken to be \emph{pole} masses.
%
This choice (and the particular default values) was inspired by the
PDF evolution benchmark comparison~\cite{Giele:2002hx,Dittmar:2005ed} in which \hoppet
results were compared to those of Vogt's moment-space code
QCD-Pegasus~\cite{Pegasus}. 
%
If the user instead prefers to supply $\MSbar$ masses,
$m_h^{\MSbar}(m_h^{\MSbar})$, and have flavour thresholds implemented
at the $\MSbar$ masses, then she/he should specify
\ttt{masses\_are\_MSbar = .true.}\,.

The default value of the QCD coupling is
taken to be close to the world average at the time of initial release
of \hoppet \cite{Bethke:2006ac}.
%


To access the coupling at some scale \ttt{Q} one uses the following
function call:\footnote{\texttt{RunningCoupling(...)} can be used as a
    synonym for \texttt{Value(...)}, which helps code readability when the
    \texttt{coupling} argument is left out (i.e.\ when using the
    global \texttt{coupling} object).}
\begin{lstlisting}
  alfas = Value(coupling, Q [, fixnf])
\end{lstlisting}
This is the value of the coupling as obtained from the Runge-Kutta
solution of the \ttt{nloop} version of eq.~(\ref{eq:as-ev}) (the
numerical solution is actually carried out for $1/\as$), together with the
appropriate mass thresholds. 
%
For typical values of $\as(M_Z)$ the coupling is guaranteed to be reliably
determined in the range $0.5 \GeV < Q < 10^{19}\GeV$. The values of
the $\beta$ function coefficients used in the evolution correspond to
those obtained with the values of the QCD colour factors that were in
vigour at the moment of initialisation of the coupling.

In the variable flavour-number case, the \ttt{fixnf} argument allows
one to obtain the coupling for \ttt{fixnf} flavours even outside the
natural range of scales for that number of flavours. This is only
really intended to be used close to the natural range of scales, and
can be slow if one goes far from that range (a warning message will be
output). If one is interested in a coupling that (say) never has more
than 5 active flavours, then rather than using the \ttt{fixnf} option
in the \ttt{Value} subroutine, it is best to initialise the coupling
with a fictitious large value for the top mass.

Often it is convenient to be able to enquire about the mass information
embodied in a \ttt{running\_coupling}. For example in the PDF
evolution below, all information about the location of mass thresholds is
obtained from the \ttt{running\_coupling} type.

The quark mass for flavour \ttt{iflv} can be obtained with the
call
\begin{lstlisting}
  quark_mass = QuarkMass(coupling, iflv)
\end{lstlisting}
This is the pole mass, unless the function \ttt{QuarkMassesAreMSbar}
returns \ttt{.true.}, in which case it is an $\MSbar$ mass.
%
The range of scales, $\ttt{Qlo} < Q < \ttt{Qhi}$ for which \ttt{iflv}
is the heaviest active flavour is obtained by the subroutine call
\begin{lstlisting}
  call QRangeAtNf(coupling, iflv, Qlo, Qhi [, muM_mQ])
\end{lstlisting}
The optional argument \ttt{muM\_mQ} allows one to obtain the answer as
if one had initialised the coupling with a different value of
\ttt{muMatch\_mQuark} than that actually used. One can also establish
the number of active flavours, \ttt{nf\_active}, at a given scale
\ttt{Q} with the following function:
\begin{lstlisting}
  nf_active = NfAtQ(coupling, Q [, Qlo, Qhi] [, muM_mQ])
\end{lstlisting}
As well as returning the number of active flavours, it can also set
\ttt{Qlo} and \ttt{Qhi}, which correspond to the range of scales in
which the number of active flavours is unchanged. The optional
\ttt{muM\_mQ} argument has the same purpose as in the \ttt{QRangeAtNf}
subroutine. The last of the enquiry functions allows one to obtain the
range of number of flavours covered in this coupling, $\ttt{nflo} \le
n_f \le \ttt{nfhi}$:
\begin{lstlisting}
  call NfRange(coupling, nflo, nfhi)
\end{lstlisting}

Finally, as usual, once you no longer need a \ttt{running\_coupling}
object, you may free the memory associated with it using the
\ttt{Delete} call:
\begin{lstlisting}
  call Delete(coupling)
\end{lstlisting}



%----------------------------------------------------------------------
\subsection{DGLAP evolution}
\label{sec:dglap-ev}


%......................................................................
\subsubsection{Direct evolution}
\label{sec:direct-evolution}

We are now, at last,
 ready to evolve a multi-flavour PDF. This is done by breaking the
evolution into steps, and for each one using a Runge-Kutta
approximation for the solution of a first-order matrix differential
equation. The steps are of uniform size in a variable $u$ that
satisfies the following approximate relation
\begin{equation}
  \label{eq:du}
  \frac{du}{d\ln Q^2} \simeq \as(Q^2) \ .
\end{equation}
For a 1-loop running coupling one has $u = (\ln \ln
Q^2/\Lambda)/\beta_0$, which is the variable that appears in
analytical solutions to the $1$-loop DGLAP equation.
%
The step size in u, du, can be set with the following call
\begin{lstlisting}
  real(dp) :: du = 0.1_dp ! or some smaller value
  call SetDefaultEvolutionDu(du)
\end{lstlisting}
The error on the evolution from the finite step size should scale as
$(\ttt{du})^4$. With the default value of $\ttt{du}=0.1$, errors are
typically somewhat smaller than $10^{-3}$ (see
section~\ref{sec:benchmarks} for the detailed benchmarks).

To actually carry out the evolution, one uses the following subroutine
call:
\begin{lstlisting}
  type(dglap_holder)     :: dglap_h
  type(running_coupling) :: coupling
  real(dp), pointer      :: initial_pdf(:,:)
  real(dp)               :: Q_init, Q_end
  integer                :: nloop
  integer                :: untie_nf
  [...]
  call EvolvePDF(dglap_h, initial_pdf, coupling, Q_init, Q_end &
                        & [, muR_Q] [, nloop] [, untie_nf] [, du] )
\end{lstlisting}
which takes a PDF array 
\ttt{pdf} and uses the splitting matrices in \ttt{dglap\_h}  to
evolve it from scale \ttt{Q\_init} to scale \ttt{Q\_end}.
%
By default the renormalisation to factorisation scale ratio is
$\ttt{muR\_Q} = 1.0$ and the number of loops in the evolution is the
same as was used for the running \ttt{coupling} (the \ttt{nloop}
optional argument makes it possible to override this choice). Variable
flavour-number switching takes place at the quark masses as associated
with the \ttt{coupling}.
%
The choice to switch at the pole masses or $\MSbar$ masses is the same
as was specified by the user for the coupling.

If the \ttt{dglap\_holder} object \ttt{dglap\_h} does not support the
relevant number of loops or flavours, the program will give an error
message and stop. With the \ttt{untie\_nf} option you can request that
the number of flavours in the evolution be `untied' from that in the
coupling in the regions where \ttt{dglap\_h} does not support the number of
flavours used in the coupling. Instead the closest number of flavours
will be used.\footnote{For example if \ttt{dglap\_h} was initialised with
  $n_f = 3\ldots5$ while the coupling has $n_f = 3\ldots 6$, then
  variable flavour number evolution will be used up to $n_f = 5$, but
  beyond the top mass the evolution will carry on with $5$ flavours,
  while the coupling uses $6$ flavours. There probably aren't too many
  good reasons for doing this (other than for examining how much it
  differs from a `proper' procedure).}

Mass thresholds (NNLO) are implemented as described in
section~\ref{sec:pqcd}:
\begin{subequations}
\label{eq:mass_threshold}
\begin{align}
  \ttt{pdf}_{n_f} &= \ttt{pdf}_{n_f-1} +
  \left(\frac{\alpha_{s}^{(n_f)}(x_\mu m_h^2)}{2\pi}\right)^2
  (\mbox{\ttt{dglap\_h\%MTM2 .conv.}}\; \ttt{pdf}_{n_f-1}) \ ,\\
  %
  \ttt{pdf}_{n_f-1} &= \ttt{pdf}_{n_f} \;\;\;\;-
  \left(\frac{\alpha_{s}^{(n_f)}(x_\mu m_h^2)}{2\pi}\right)^2
  (\mbox{\ttt{dglap\_h\%MTM2 .conv.}}\; \ttt{pdf}_{n_f}) \ ,
\end{align}
\end{subequations}
when crossing the threshold upwards and downwards, respectively. Note
that the two operations are not perfect inverses of each other,
because the number of flavours of the \ttt{pdf} used in the
convolution differs in the two cases. The mismatch however is only of
order $\as^4$ (NNNNLO), \ie well beyond currently known accuracies.

A general remark is that crossing a flavour threshold downwards will
result in some (almost certainly physically spurious)
intrinsic heavy-flavour being left over below threshold.

%......................................................................
\subsubsection{Precomputed evolution and the \ttt{evln\_operator}}
\label{sec:precomputed-evolution}

Each Runge-Kutta evolution step involves multiple evaluations of the
derivative of the PDFs, and the evolution between two scales may be
broken up into multiple Runge-Kutta steps. This amounts to a large
number of convolutions. It can therefore be useful to create a single
\emph{derived} splitting matrix that is equivalent to the whole
evolution between the two scales. 

A complication arises because evolutions often cross flavour
thresholds, whereas a derived splitting matrix is only valid for fixed
$n_f$. Therefore a new type has to be created, \ttt{evln\_operator},
which consists of a linked list of splitting and mass threshold
matrices, breaking an evolution into a chain of interleaved
fixed-flavour evolution steps and flavour changing steps. An
\ttt{evln\_operator} is created with a call that is almost identical
to that used to evolve a PDF:
\begin{lstlisting}
  type(evln_operator) :: evop
  real(dp), pointer   :: pdf_init(:,:), pdf_end(:,:)
  [...]
  call InitEvlnOperator(dglap_h, evop, coupling, Q_init, Q_end &
                           & [, muR_Q] [, nloop] [, untie_nf] [, du] )
\end{lstlisting}
It can then be applied to PDF in the same way that a normal
\ttt{split\_mat} would:
\begin{lstlisting}
  pdf_end = evop * pdf_init       ! assume both pdfs already allocated
  ! OR (alternative form) 
  pdf_end = evop .conv. pdf_init  
\end{lstlisting}
As usual the \ttt{Delete} subroutine can be used to clean up any
memory associated with an evolution operator that is no longer needed.


%======================================================================
%======================================================================
\section{Tabulated PDFs}
\label{sec:tabulated-pdfs}

The tools in the previous section are useful if one knows that one
needs DGLAP evolution results at a small number of predetermined $Q$
values. Often however one simply wishes to provide a PDF distribution
at some initial scale and then subsequently be able to access it at
arbitrary values of $x$ and $Q$. For this purpose it is useful 
(and most efficient) to
produce a table of the PDF as a function of $Q$, which then allows
for access to the PDF at arbitrary $x$ and $Q$ using an interpolation. All
types and routines discussed in this section are in the
\ttt{pdf\_tabulate} module, or accessible also from \ttt{hoppet}.

\subsection{Preparing a PDF table}
The type that contains a PDF table is \ttt{pdf\_table}. It first needs
to be allocated,
\begin{lstlisting}
  type(pdf_table) :: table
  [...]

  call AllocPdfTable(grid, table, Qmin, Qmax &
                     & [, dlnlnQ ] [, lnlnQ_order ] [, freeze_at_Qmin] )
\end{lstlisting}
where one specifies the range of Q values to be tabulated, from
\ttt{Qmin} to \ttt{Qmax}, and optionally the interpolation step size
\ttt{dlnlnQ} in the variable $\ln \ln Q/(0.1\GeV)$ (default
$\ttt{dlnlnQ}=0.07$, sufficient for $10^{-3}$ accuracy), the
interpolation order \ttt{lnlnQ\_order}, equal to $3$ by default, and
finally whether PDFs are to be frozen below \ttt{Qmin}, or instead set
to zero (the default is \ttt{freeze\_at\_Qmin=.false.}, \ie they are
set to zero).\footnote{Note that the spacing and interpolation in $Q$
  are treated independently of what's done in the PDF evolution. A
  reason for this is that in the PDF evolution one uses a variable
  related to the running coupling, which is similar to $\ln \ln Q$ but
  whose precise details depend on the particular value of the
  coupling.  Using this in the tabulation would have prevented one
  from having a tabulation disconnected from any coupling.
  Unfortunately \ttt{du} and \ttt{dlnlnQ} are not normalised
  equivalently --- roughly speaking for $n_f = 4$ they correspond to
  the same spacing if $\ttt{dlnlnQ} \simeq 0.7 \ttt{du}$.}

By default a tabulation knows nothing about $n_f$ thresholds, which
means that in the neighbourhood of thresholds the tabulation would be
attempting to interpolate a discontinuous function (at NNLO). To
attribute information about $n_f$ thresholds to the tabulation, set
them up first in a running \ttt{coupling} object and then transfer
them:
\begin{lstlisting}
  call AddNfInfoToPdfTable(table,coupling)
\end{lstlisting}
When interpolating the table (see below), the set of $Q$ values for
the interpolation will be chosen so as to always have a common $n_f$
value. Note that \ttt{AddNfInfoToPdfTable} may only be called once for
an allocated table: if you need to change the information about $n_f$
thresholds, \ttt{Delete} the table, reallocate it and then reset the
$n_f$ information. This is not necessary if you just
change the value of the coupling.

Given an existing table, \ttt{ref\_table}, a new table,
\ttt{new\_table}, can be allocated with identical properties
(including any $n_f$ information) as follows
\begin{lstlisting}
  call AllocPdfTable(new_table, ref_table)
\end{lstlisting}
All of the above routines can be used with $1$-dimensional arrays of
tables as well (in \ttt{AllocPdfTable} the reference table must always
be a scalar).

A table can be filled either from a routine that provides the PDFs as
a function of $x$ and $Q$, or alternatively by evolving a PDF at an
initial scale. The former can be achieved with
\begin{lstlisting}
  call FillPdfTable_LHAPDF(table, LHAsub)
\end{lstlisting}
where \ttt{LHAsub} is any subroutine with the LHAPDF interface,
{\it i.e.}, as shown earlier
in section~\ref{sec:human-rep}.

To fill a table via an evolution from an initial scale, one uses 
\begin{lstlisting}
  type(pdf_table)        :: table
  type(dglap_holder)     :: dglap_h
  type(running_coupling) :: coupling
  real(dp), pointer      :: initial_pdf(:,:)
  real(dp)               :: Q0
  integer                :: nloop
  integer                :: untie_nf
  [...]
  call EvolvePdfTable(table, Q0, initial_pdf, dglap_h, coupling &
                      & [, muR_Q] [, nloop] [, untie_nf] )
\end{lstlisting}
which takes an the \ttt{initial\_pdf} at scale \ttt{Q0}, and evolves
it across the whole range of $Q$ values in the table, using the
\ttt{EvolvePDF} routine. The arguments have the same meaning as
corresponding ones in \ttt{EvolvePDF}, explained in
section~\ref{sec:direct-evolution}. The $\ttt{du}$ value that's used
is the default one for \ttt{EvolvePDF} which, we recall, may be set
using \ttt{SetDefaultEvolutionDu(du)}. If the $Q$ spacing in the
tabulation is such that steps in \ttt{du} would be too large, then the
steps are automatically resized to the tabulation spacing.

One may also use the precomputed evolution facilities of
section~\ref{sec:precomputed-evolution}, by calling the routine
\begin{lstlisting}
  call PreEvolvePdfTable(table, Q0, dglap_h, coupling, &
                         & [, muR_Q] [, nloop] [, untie_nf] )
\end{lstlisting}
which prepares \ttt{evln\_operator}s for all successive $Q$ intervals in the
table. An accelerated evolution, which uses these operators instead of
explicit Runge-Kutta steps, may then be obtained by calling
\begin{lstlisting}
  call EvolvePdfTable(table, initial_pdf)
\end{lstlisting}
The \ttt{EvolvePdfTable} routine may be called as many times as one
likes, for different initial PDFs for example;
however, if one wishes to change the parameters of
the evolution (coupling, perturbative order, etc.) 
in the precomputed option, one must
first \ttt{Delete} the table and then prepare again it.


%......................................................................
\subsection{Accessing a table}
\label{sec:acc_table}

The main way to access a table is as follows
\begin{lstlisting}
real(dp) :: pdf(-6:6), y, x, Q
  [...]
  call EvalPdfTable_yQ(table, y, Q, pdf)
  ! or using x
  call EvalPdfTable_xQ(table, x, Q, pdf)
\end{lstlisting}
There may be situations where it is useful to access the internals of
a \ttt{pdf\_table}, for example because one would like to carry out a
convolution systematically on the whole contents of the table. Among
the main elements are
\begin{lstlisting}
  type pdf_table
    integer           :: nQ           ! arrays run from 0:nQ
    real(dp), pointer :: tab(:,:,:)   ! the actual tabulation
    real(dp), pointer :: Q_vals(:)    ! the Q values 
    integer,  pointer :: nf_int(:)    ! nf values at each Q
    real(dp), pointer :: as2pi(:)     ! alphas(Q)/2pi at each Q
    [...]
  end type pdf_table
\end{lstlisting}
where the third dimension of \ttt{tab} spans the range of tabulated
$Q$ values, and the $n_f$ and coupling information are only allocated
and set if one has called \ttt{AddNfInfoToPdfTable} for the table.


An example of usage of the low-level information contained in the
table is the following, which initialises \ttt{table\_deriv\_LO} with
the LO derivative of \ttt{table}:
\begin{lstlisting}
  do iQ = 0, table%nQ
    table_deriv_LO%tab(:,:,iQ) = table%as2pi(iQ) * &
                     & ( dglap_h%allP(1,table%nf_int(iQ)) * table%tab(:,:,iQ))
  end do
\end{lstlisting}
where we assume \ttt{table\_deriv\_LO} to have been allocated with an
appropriate structure at some point, \eg via 
\begin{lstlisting}
  call AllocPdfTable(table_deriv_LO, table)
\end{lstlisting}
The above mechanism has found use in the a-posteriori PDF
library~\cite{Carli:2005ji,Carli:2010rw,Banfi:2007gu} 
and in work matching event shapes with fixed-order
calculations~\cite{caesar,Dasgupta:2001eq,Dasgupta:2002dc}.
%
One could also imagine using it to obtain tables of
(flavour-separated) structure functions, if one were to convolute with
coefficient functions rather than splitting functions. As of version
2.0.0 this is possible and we provide some details in
section~\ref{sec:structure-funcs}.

There are instances in which it is useful to extract the PDF at all
$x$ values for a given $Q$. This is the case, for efficiency reasons,
if one wishes to evaluate it at very many $x$ values and a single $Q$
value. It's also the case if one wishes to evaluate
sum rules. One then uses the routine \ttt{EvalPdfTable\_Q}, as in
the following example for calculating the momentum sum rule
\begin{lstlisting}
  real(dp), pointer :: pdf_at_Q(:,:)
  real(dp)          :: moment_index, momentum_sum
  ! [...]
  call AllocPDF(table%grid, pdf_at_Q)        ! reserve space
  call EvalPdfTable_Q(table, Q, pdf_at_Q)    ! evaluate the PDF at Q
  moment_index = 1.0_dp
  ! (truncated) momentum-sum of the sum of all flavours of pdf_at_Q
  momentum_sum = TruncatedMoment(table%grid, moment_index, &
                               & sum(pdf_at_Q(:,-6:6),dim=2)) ! dim=2 -> sum over flav
\end{lstlisting}
where the \ttt{TruncatedMoment} function was described in detail in
section~\ref{sec:sum-rules}. Recall that
if the goal is to extract accurate sum-rule estimates or in general
full (non-truncated) moments, the value of {\tt ymax} of the
grid should be large enough.

As with all other objects, a \ttt{pdf\_table} object can be deleted
using
\begin{lstlisting}
  call Delete(table) 
\end{lstlisting}
Notice that a table is a variable that is local to the scope in which
it is defined. So table variables defined separately in each of two
different procedures will effectively be different variables in the
two procedures.
%
If ones needs to use a common PDF table across different procedures,
it has to be defined within a module and then the module should
be \ttt{use}d in both procedures.  In Appendix \ref{sec:example_program},
there is a detailed example of different ways of accessing a table.






%======================================================================
%======================================================================
\section{Streamlined interface}
\label{sec:vanilla}

Now we present the streamlined interface to \hoppet,
intended to allow easy access
to the essential evolution functionality from languages other than
F95.  It hides all the object-oriented nature of the program, and
provides access to one \ttt{pdf\_table}, based on a single grid
definition. The description will be given as if one is calling from
F77. An include file \ttt{src/hoppet.h} is provided for calling
from \CPP{} --- the interface is essentially identical to the Fortran
one, with the caveat that names are case sensitive (the cases are as
given below), and that PDF components referred to below as
\ttt{pdf(-6:6)} become \ttt{pdf[0..12]}. A summary of the
most relevant procedures of this interface 
and their description can be found 
in the reference guide, Appendix~\ref{sec:refguide}.

%......................................................................
\subsection{Initialisation}
\label{sec:vanilla_initialisation}

The simplest way of initialising the 
streamlined interface is by calling
\begin{lstlisting}
  call hoppetStart(dy,nloop)
\end{lstlisting}
which will set up a compound (four different spacings) grid with
spacing \ttt{dy} at small $x$, extending to $y = 12$, and numerical
order $\ttt=-6$.  The $Q$ range for the tabulation will be $1\GeV <
Q<28 \TeV$ and a reasonable choice will be made for the \ttt{dlnlnQ}
spacing (related to \ttt{dy}). It will initialise splitting functions
up to \ttt{nloop} loops (though one can still carry out evolutions
with fewer loops).
%
If you need more control over the initialisation, you should use
\begin{lstlisting}
  call hoppetStartExtended(ymax,dy,Qmin,Qmax,dlnlnQ,nloop,order,factscheme)
\end{lstlisting}
which will again set up compound grid, but give control over the
numerical \ttt{order} and the $y$ and $Q$ ranges and spacings (as
before \ttt{dy} is the spacing at small $x$). It also allows one to
choose the type of evolution according to \ttt{factscheme}.


%......................................................................
\subsection{Usage}
\label{sec:vanilla_usage}

To carry out an evolution, one should first decide whether one wants a
fixed-flavour number scheme or a variable flavour number scheme (the
default). Either can be set with its parameters as follows:
\begin{lstlisting}
  call hoppetSetFFN(fixed_nf)
  call hoppetSetPoleMassVFN(mc, mb, mt)  ! Heavy quark pole masses
  call hoppetSetMSbarMassVFN(mc, mb, mt) ! Heavy quark MSbar masses, m(m)
\end{lstlisting}
where for the VFNs one specifies either the pole-masses or the
$\MSbar$ masses for the quarks (thresholds are then implemented at the
pole or $\MSbar$ masses accordingly). An evolution is carried out with
the following routine
\begin{lstlisting}
  call hoppetEvolve(asQ, Q0alphas, nloop, muR_Q, LHAsub, Q0pdf)
\end{lstlisting}
where one specifies the coupling \ttt{asQ} at a scale \ttt{Q0alphas},
the number of loops for the evolution, \ttt{nloop}, the ratio of
renormalisation to factorisation scales \ttt{muR\_Q},\footnote{Note
  that in the streamlined interface, with $\ttt{muR\_Q}\ne 1$, the running
  coupling flavour thresholds are still placed at the quark masses;
  the evolution needs the coupling for a given number of flavours
  outside the standard range for that number of flavours (precisely
  because $\ttt{muR\_Q}\ne 1$) and this is done automatically in the
  evolution. In contrast in the benchmark studies~\cite{Giele:2002hx,Dittmar:2005ed},
  the flavour thresholds for the coupling were placed at $\ttt{muR\_Q}
  \times m_Q$.  This is a perfectly valid alternative, but can
  complicate the specification of the $\as$ value --- for example with
  $\ttt{muR\_Q} = 0.5$ the matching for the top threshold would be
  carried out at $\mu = 0.5 m_t \simeq 85 \GeV$, and if one specified
  the coupling at scale $M_Z$, it wouldn't be clearer whether this was
  a $5$-flavour value or a $6$-flavour value. With the procedure
  adopted in the streamlined interface the issue does not arise. (While in
  F95 the user has the freedom to do as they prefer). } %
the name of a subroutine \ttt{LHAsub} with interface
\begin{lstlisting}
  subroutine LHAsub(x,Q,pdf)
    implicit none
    double precision x,Q,pdf(-6:6)
    [...]   ! sets pdf to be momentum densities, e.g. pdf(0) = xg(x)
  end subroutine 
\end{lstlisting}
to return the initial condition for the evolution and the scale
\ttt{Q0pdf} at which one starts the PDF evolution. Note that the
LHAsub subroutine will only be called with $\ttt{Q}=\ttt{Q0pdf}$.
To access the coupling one uses
\begin{lstlisting}
  alphas = hoppetAlphaS(Q)
\end{lstlisting}
while the PDF at a given value of $\ttt{x}$ and $\ttt{Q}$ is obtained with 
\begin{lstlisting}
  call hoppetEval(x,Q,f)
\end{lstlisting}
which sets \ttt{f(-6:6)} (recall that it is $xg(x)$, etc., that is
returned, since this is what is
used through \hoppet).

It is also possible to prepare an evolution in cached form. This is
useful if one needs to evolve many different PDF sets with the same
evolution properties (coupling, initial scale, etc.), as is the
usual situation in global analyses of PDFs, because though
the preparation may take a bit longer than a normal evolution
($2$--$10$ times depending on the \ttt{order}), once it is done,
cached evolutions run $3$--$4$ faster than a normal evolution. The
preparation of the cache is carried out with
\begin{lstlisting}
  call hoppetPreEvolve(asQ, Q0alphas, nloop, muR_Q, Q0pdf)
\end{lstlisting}
and then the cached evolution is carried out with 
\begin{lstlisting}
  call hoppetCachedEvolve(LHAsub)
\end{lstlisting}
The results may be very slightly different from those in a normal
evolution (some information is lost when caching), and the user 
may wish to check on a case-by-case basis that such differences
don't matter in practice.

If one wishes to use the exact rather than the default parametrised
expressions for the NNLO splitting functions and mass thresholds, this
can be done through a call to
\begin{lstlisting}
  call hoppetSetExactDGLAP(exact_nfthreshold, exact_splitting)
\end{lstlisting}

The tabulation can also be filled with the contents of an external PDF
package, by calling
\begin{lstlisting}
  call hoppetAssign(LHAsub)
\end{lstlisting}
where \ttt{LHAsub} is the name of any subroutine with the interface
given above, which will now be called with a range of \ttt{Q} values
corresponding to the internal tabulation scales. This essentially just
transfers an external tabulation into \hoppet's internal
representation. 

Finally given an evolved or assigned PDF, one can obtain information
about convolutions of the splitting functions with the PDFs:
\begin{lstlisting}
  call hoppetEvalSplit(x,Q,iloop,nf,f)
\end{lstlisting}
sets \ttt{f(-6:6)} equal to the value at \ttt{x}, \ttt{Q} of
convolution of the \ttt{iloop} splitting function matrix (with
\ttt{nf} flavours) with the currently tabulated PDF. If $\ttt{nf}<0$
the number of flavours used is the one appropriate at the specified
$Q$ scale (as long as the information is available, \ie one of
\ttt{hoppetEvolve} or \ttt{hoppetCachedEvolve} has been called). The
first call with a given \ttt{nf} for a specified \ttt{iloop} will be
slow ($\sim$ the time for a cached evolution), but subsequent calls
with the same values will be fast.

If \ttt{iloop} has a value composed of two digits, \ttt{ij},
then one obtains the convolution of the \ttt{i}-loop splitting function
with the result of the convolution of the \ttt{j}-loop splitting
function with the PDF. 
%
Analogously for a three-digit value, \ttt{ijk}.
%
Currently there is a limit that $i+j \le 3$ and $i+j+k \le 3$, which
is adequate, e.g., for carrying out factorisation scale variation up
the N$^3$LO.
%
The support for multi-digit \ttt{iloop} values is new as of \hoppet
version 1.2.0.

The routines described here 
%(and associated data storage) 
are to be 
found in \ttt{src/streamlined\_interface.f90} and may provide inspiration
for the user wishing to write their own F95 code for \hoppet.

\section{Benchmarks}
\label{sec:benchmarks}

Key questions in assessing the usefulness of a PDF evolution code include
that of its correctness, its accuracy and its speed. \hoppet's
correctness has been established with a reasonable degree of
confidence in the benchmark tests~\cite{Giele:2002hx,Dittmar:2005ed} where it was
compared with the Mellin space based
evolution code QCD-Pegasus \cite{Pegasus}. 
The program used to carry out those tests
is available as \ttt{benchmarks/benchmarks.f90}. The user should
carefully read the detailed
comments at the beginning for usage instructions.

The results used in \cite{Giele:2002hx,Dittmar:2005ed} were obtained with very finely
spaced grids, in order to guarantee small numerical errors ($\lesssim
10^{-7}$).  Such accuracies are useful when comparing and testing two
independent codes, because differences or bugs in the
implementation of the physics (especially the higher-order parts) may
only manifest themselves as small changes in the results.

In contrast, for use in most physical applications, an accuracy in the
range $10^{-3}$ to $10^{-4}$ is generally more than adequate, since it
is rare for other sources of numerical uncertainty (\eg Monte Carlo
integration errors in NLO codes, or experimental errors) to be
comparably small. The critical issue in such cases is more likely to
be the speed of the code, for example in PDF fitting
applications.

\hoppet's accuracy and speed both depend on the choice of grid (in
$y$) and the evolution and/or tabulation steps in $Q$. We shall start
with the question of the accuracy.


%......................................................................
\subsection{Accuracy}
\label{sec:Accuracy}
To measure the accuracy, 
we use the same initial condition and evolution parameters as
in~\cite{Giele:2002hx,Dittmar:2005ed}:
\begin{subequations}
  \label{eq:init}
  \begin{align}
    x u_v(x)   &= 5.107200 x^{0.8} (1-x)^3\,,\\
    x d_v(x)   &= 3.064320 x^{0.8} (1-x)^4\,,\\
    x\bar d(x) &= 0.1939875 x^{-0.1} (1-x)^6\,,\\
    x\bar u(x) &= x\bar d(x) (1-x)\,,\\
    x     s(x) &= x\bar s(x) = 0.2(x\bar d(x) + x\bar u(x))\,,\\
    x g(x) &= 1.7 x^{-0.1} (1-x)^5\,,
  \end{align}
\end{subequations}
where $u_v \equiv u - \bar u$, $d_v \equiv d - \bar d$, and all other
flavours are zero. The initial scale%
\footnote{With $\bar{\epsilon}$ an infinitesimal number. Note that
this is unrelated to the evolution accuracy $\epsilon$, introduced later
in this section.} is $Q_0 = \lp \sqrt{2}-\bar{\epsilon}
\rp \GeV$,
$\as(Q_0) = 0.35$ and the charm, bottom and top pole masses are kept
at the default values, $\sqrt{2}$, $4.5$ and $175\GeV$ respectively
(as used also in the streamlined interface).
Observe that the initial conditions 
and coupling are actually both given for three active
flavours (\ie infinitesimally below the charm mass). The evolution is
carried out to NNLO accuracy in a variable flavour number scheme,
including the mass thresholds in the coupling and PDF.

All tests here are carried out based on tabulations of the PDF
evolution, section~\ref{sec:tabulated-pdfs}.
%
We first run \hoppet with a very fine grid spacing to provide a
reference result. Then we run the evolution for a coarser grid ---
the accuracy of the coarser grid is determined by comparing its
results with those from the reference grid. We determine the relative
accuracy for each flavour at $5000$ points in the $x, Q$ plane, as
shown in Fig.~\ref{fig:grid}. The points are uniformly spaced in
$\zeta = \ln 1/x + 9(1-x)$ so as to obtain fine coverage at small and
large $x$. The $Q$ values are chosen more closely spaced at low $Q$
where the $Q$-dependence is strongest and they are taken slightly correlated
with $\zeta$ so as to cover a nearly continuous range of
$Q$.\footnote{This procedure differs from that in \cite{Giele:2002hx,Dittmar:2005ed}
  where fewer (500) points were used and one compared not individual
  flavours, but combinations intended to be more directly revealing of
  any deficiencies in the evolution. This reflects the difference in
  needs between obtaining a global measure of the accuracy and
  providing benchmarks intended in part to facilitate the debugging of
  independent codes.}


\begin{figure}
  \centering
  \includegraphics[width=0.7\textwidth]{figs-v1/grid}%
  \caption{The set of points in $x, Q$ used to determine the accuracy
    of the evolution. The areas shaded in grey are regions where one
    of the flavours is in the neighbourhood of a sign-change
    (bottom-left: $c,\bar c$, right: $\bar u$) and so is ignored in
    the accuracy determination.  The accuracies shown here correspond
    to a $y$ grid with a base spacing of $\ttt{dy}=0.2$ and other
    parameters as described in the text for
    Fig.~\ref{fig:acc-fixed-dy-dlnlnQ}.
    %, and
    %subsiduary grids with $3$, $9$ and $27$ times the resolution,
    %extending to $y=2.0, 0.5, 0.2$ and interpolation order $-6$; the
    %scale grid has a spacing $\ttt{dlnlnQ}=0.05$ and an interpolation
    %order of $4$ \comment{check}. 
    %
    The colour coding indicates the error in the least-well determined
    (non-excluded) flavour channel ($\bar b \ldots b$) at each point.
  }
  \label{fig:grid}
\end{figure}


One difficulty that arises when examining relative accuracies is that
some flavours change sign as one varies $x$ or $Q$. Close to the zero
the relative accuracy diverges because of the small value of the
denominator. Therefore in global accuracy estimates, we eliminate
flavours in the region where they change sign (within $\Delta
\zeta=0.4$ and at the two $Q$ values straddling a sign
change). Specifically, for our 
initial conditions, this corresponds to $c,\bar c$ for the two lowest
$Q$ values below $x\sim 10^{-2}$ and $\bar u$ for $x\gtrsim
0.9$.\footnote{The change in sign of the charm distribution is not
  worrying physically since it is close to threshold where it will be
  compensated for by finite mass effects in the coefficient functions;
  for $\bar u$ the sign change is more surprising, though it may be
  related to non-trivial interactions between the evolutions of the
  $u$ and $\bar u$ components at NNLO (note that in the region of the
  sign change they differ by many orders of magnitude).  } %
The exact regions are shaded in grey in Fig.~\ref{fig:grid}.

Our tabulation covers the range $10^{-5}<x<1$, $\sqrt{2} < Q<
10^4\GeV$. The grid in $y=\ln1/x$ will consist of 4 nested subgrids:
one covering the whole $y$ range with spacing $\ttt{dy}$ and others
with spacings $\ttt{dy}/3, \ttt{dy}/9, \ttt{dy}/27$ extending to
$y=2,0.5,0.2$ respectively. Except where stated we shall use
$\ttt{order}=-6$. In $Q$ the default interpolation order will be $4$.
The reference grids use $\dy=0.025$ and $\dlnlnQ=0.005$.

Fig.~\ref{fig:acc-fixed-dy-dlnlnQ} shows the relative accuracy
$\epsilon$ as a function of $x$ for two grid-spacing choices (left
$\dy=0.2$, right $\dy=0.05$, $\dlnlnQ=\dy/4$ in both cases). Each
solid line corresponds to one $Q$ value and shows the error in the
least-well-determined flavour channel at each $x$, excluding flavour
channels close to a sign-change. The relative accuracy $\epsilon$
is poorest as
one approaches $x=1$, where the PDFs all go to zero very rapidly and
so have divergent logarithmic derivatives in $x$, $d\ln q/d\ln x$,
adversely affecting the accuracy of the convolutions. This region is
always the most difficult in $x$--space methods, however the use of
multiple subgrids in $x$ allows to one to obtain acceptable results
for $x<0.9$ which is likely to be the largest value of any
phenomenological relevance. 

At $x\sim0.1$, $0.6$ and $0.8$ one notices
step-like structures --- these are the points where one switches
between subgrids, with a significant degradation in accuracy at $x$
values below the transition. These structures are also visible in the
colour-coded accuracy representation in Fig.~\ref{fig:grid}, which
corresponds to $\dy=0.2$ and allows one to visualise more clearly the
$Q$ dependence of the accuracy. The effect of the grid spacing is
clearly visible as one goes from the left to the right-hand plots of
Fig.~\ref{fig:acc-fixed-dy-dlnlnQ},
with the reduction in the spacings by a factor of $4$ leading to an
improvement in accuracy by a factor $\sim 100$.



For completeness we also show the parts of the charm channel that have
been excluded because of the proximity to a sign change (dashed lines,
lower-left shaded region of Fig.\ref{fig:grid}).  One observes in
particular a spike near $x\simeq 7 \times 10^{-3}$ where the charm
distribution has its zero. Including this in a estimate of the global
accuracy would be senseless since it actually corresponds to a
divergence and the peak-value for the spike is arbitrary, depending on
the precise choice of points used to estimate the accuracy. The
question of the exact region to exclude is somewhat arbitrary, but the
choice made above seems not unreasonable in the light of
Fig.~\ref{fig:acc-fixed-dy-dlnlnQ}.

\begin{figure}
  \centering
  \includegraphics[width=0.48\textwidth]{figs-v1/acc-dy0_2-dlnlnQ0_05}\hfill
  \includegraphics[width=0.48\textwidth]{figs-v1/acc-dy0_05-dlnlnQ0_0125}
  \caption{The relative accuracy $\epsilon$ of the least well
    determined flavour channel at each $x, Q$ point, shown as a
    function of $x$ for many $Q$ values. The results for the part of
    the charm distribution excluded from the analysis (near sign
    change) are shown separately. }
  \label{fig:acc-fixed-dy-dlnlnQ}
\end{figure}

Fig.~\ref{fig:acc-fixed-dy-dlnlnQ} is useful in order to obtain a
detailed picture of the accuracy of the evolution with a given set of
parameters. To quote a single, global, number for the relative 
accuracy $\epsilon$ we make
the conservative choice of taking the largest value of $\epsilon$ that
occurs in a chosen $x$ range. We will examine a restricted range,
$x<0.7$, studying just the $g,u,d,s$ flavours, and also a wider range,
$x<0.9$ with all flavours.

\begin{figure}
  \centering
  \includegraphics[width=0.48\textwidth]{figs-v1/dy}%
  \hfill
  \includegraphics[width=0.495\textwidth]{figs-v1/dlnlnQ}%
  \caption{Left: the (globally) worst relative accuracy $\epsilon$ as
    a function of the base $y$-grid resolution parameter, \ttt{dy} ---
    shown for two $y$-grid configurations and two $x$-ranges and
    flavour-sets.
  Right: the relative accuracy as a function of the
    resolution in $\ln \ln Q$ of the tabulation, \ttt{dlnlnQ}, for
    different $x$/flavour ranges and for different $\ttt{lnlnQ\_order}$
    values (\ttt{o}).}
  \label{fig:dy+dlnlnQ}
\end{figure}

Fig.~\ref{fig:dy+dlnlnQ} shows the effect of varying the base $\dy$
and $\dlnlnQ$ separately, while the other is fixed at the reference
value. The `guds' flavours in the $x<0.7$ range are generally better
determined, for a given set of grid parameters, than the full set of
flavours up to $x<0.9$. This is as one would expect since the
large-$x$ region is usually the hardest and the `guds' flavours are
generally somewhat smoother than the others. Using only three $y$
subgrids worsens the situation when including the largest $x$ values,
and reducing the order in the $Q$ interpolation also adversely affects
the accuracy (also for $x<0.7$, not shown).

From Fig.~\ref{fig:dy+dlnlnQ}, we deduce that inaccuracies from the
$Q$ and $y$ parts of the grid are similar when $\dlnlnQ = \dy /4$.
This is the combination that we shall use as standard.


%......................................................................
\subsection{Timing}
\label{sec:Timing}

\noindent \fbox{\parbox{\textwidth}{%
    NOTE: the timings shown here date from 2008 and have been
    kept for historical reasons.
    %
    Updated timings as of 2025 are to be found in
    Section~\ref{sec:v2-performance}.
}}\medskip

The time spent in \hoppet for a given analysis can be expressed as
follows, according to whether or not one carries out pre-evolution:
\begin{subequations}
  \label{eq:timing}
  \begin{align}
    t_\text{no pre-ev}   &= t_s + n_\alpha t_\alpha + n_i (t_i  + n_{xQ}\, t_{xQ})\,,\\
    t_\text{with pre-ev} &= t_s + n_\alpha (t_\alpha + t_p) + n_i (t_c + n_{xQ}\,
    t_{xQ})\,,
  \end{align}
\end{subequations}
where $t_s$ is the time for setting up the splitting functions,
$n_\alpha$ is the number of different running couplings that one has,
$t_\alpha$ is the time for initialising the coupling,
%
$n_i$ is the number of PDF initial conditions that one wishes to
consider, $t_i$ is the time to carry out the tabulation for a single
initial condition, $n_{xQ}$ is the number of points in $x,Q$ at which
one evaluates the full set of flavours once per PDF initial condition;
in the case with pre-prepared cached evolution, $t_p$ is the time for
preparing a cached evolution and $t_c$ is the time for performing the
cached evolution. Finally $t_{xQ}$ is the time it takes to evaluate
the PDFs at a given value of $(x,Q)$ once the tabulation has
been performed.

\begin{table}
  \centering
  \begin{tabular}{|ll|c|c|c|}\hline
          &&     lf95  &  ifort   & g95    \\\hline
   $t_s$ &[s]  &  0.9  &  0.66    & 2.8    \\
   $t_\alpha$ & [ms]                
               &  0.16 &  0.12    & 0.13   \\
   $t_i$ &[ms] &  37   &   38     & 330    \\
   $t_p$ &[ms] &  51   &   44     & 310    \\
   $t_c$ &[ms] &  8.8  &   9.8    & 110    \\
   $t_{xQ}$ &[$\mu$s]           
               &  2.7  &   3.1    &  25    \\
   \hline
  \end{tabular}
  \caption{Contributions to the run time in eqs.~(\ref{eq:timing})
 for    $\dy=0.2$ and 
    $\dlnlnQ=0.05$ and standard values for the other parameters 
    (on a 3.4GHz Pentium IV (D) with 2~MB cache).
    %
    These are timings from 2008, see Section~\ref{sec:v2-performance}
    for 2025 timings.
  }
  \label{tab:timings}
\end{table}

The various contributions to the run-time are shown in
table~\ref{tab:timings} for $\dy=0.2$ and $\dlnlnQ=0.05$ (giving an
accuracy $\sim 10^{-4}$), for various compilers.  In a typical
analysis where run-times matter, such as a PDF fit, it is to be
expected that the time will be dominated by $t_c$ (or $t_i$), or if
the number of $x,Q$ points is rather large ($\gtrsim 3000$), by
$n_{xQ} t_{xQ}$.\footnote{
With these numbers, it is easy to check that a global fit with
$n_{xQ}\sim 3000$ and $n_i\sim 10^5$ could be completed
in less than half an hour, assuming cached evolution
and the use of commercial compilers.} We note (with regret)\ the
considerable speed advantage (almost an order
of magnitude) that is to be had with commercial
compilers.\footnote{As this article was going to press, a development
  version of gfortran (4.4) became available that gives correct
  results with \hoppet and is found to be comparable in speed to
  commercial compilers.}

\begin{figure}
  \centering
  \includegraphics[width=0.7\textwidth]{figs-v1/acc-v-time}%
  \caption{relative accuracy obtained as a function of the time taken
    to perform the evolution (lf95, 3.4GHz Pentium IV (D) with 2~MB
    cache).
    %
    The timings are from 2008. See Section~\ref{sec:v2-performance}
    for 2025 timings.
  }
  \label{fig:acc-v-time}
\end{figure}

We study $t_c$ and $t_i$ in more detail in Fig.~\ref{fig:acc-v-time},
where we relate them to the accuracy obtained from the evolution. As
one would expect, studying just the `guds' flavours for $x<0.7$ one
obtains better accuracy for a given speed than with all flavours for
$x<0.9$. Overall one can obtain $10^{-4}$ accuracy with $t_c \simeq
10^{-2}$\,s and $10^{-6}$ accuracy with $t_c \simeq 10^{-1}$\,s. In
general $t_i$ is about $4-5$ larger than $t_c$, highlighting the
advantage of the cached evolution. 

We note that the time $t_{xQ}$ for evaluating each point is
essentially independent of $\dy$ and $\dlnlnQ$. If a computation is
dominated by $t_{xQ}$, then it can be made somewhat faster by
lowering the interpolation orders, at the expense of needing a finer
grid (and so longer evolution times).

The timings shown here are roughly similar, for accuracies $\sim
10^{-4}$, to those obtained with the $N$--space code
Pegasus~\cite{Pegasus} when the number of $x,Q$ points to be
evaluated is $\order{10^3}$. For much smaller numbers of points
Pegasus becomes superior (because of the significantly smaller ratio
$t_c/t_{xQ}$), while for much larger numbers of points \hoppet becomes
better. Other NNLO evolution codes published in recent years 
\cite{Weinzierl:2002mv,Cafarella:2003jr,Cafarella:2005zj,Cafarella:2008du,Botje}
 are generally less competitive
either in terms of accuracy or speed.

To close this section, we summarise in table~\ref{tab:acc-param} the
different parameters that are relevant in determining the accuracy of
the evolution and tabulation, together with comments about the
components of the timing affected by each parameter.


\begin{table}
  \centering
  \begin{tabular}{|l|c|c|l|} \hline
    Parameter & Default & Timing impact & Notes \\ \hline
    base \ttt{dy}  &  $-$    &   $t_s, t_i, t_p, t_c$    & Default subgrids
    in ratio 1:3:9:27 \\
    \ttt{order} &  $[-6]$    &   $t_s, t_p, t_{xQ} (t_i, t_c)$ & \\ 
    \ttt{DefaultConvolutionEps} & $10^{-7}$ & $t_s$ & final acc.\
    limited by $\sim$ twice this.\\ \hline
    \ttt{du}  &  $0.1$ &  $t_i, t_p$ & immaterial if $\gtrsim 1.4\,
    \ttt{dlnlnQ}$\\
    \ttt{dlnlnQ}       &  $[\ttt{dy}/4] $ &  $t_i, t_p, t_c$ &  \\
    \ttt{lnlnQ\_order} &  $4$ &  $t_{xQ}$ &  \\ \hline
    \ttt{DefaultCouplingDt} & $0.2$ & $t_\alpha$ & default sufficient for 
$\epsilon \sim 10^{-9}$\\
    \hline
  \end{tabular}
  \caption{Parameters involved in the accuracy
of a tabulated evolution. Default values shown in square
    brackets are to be specified by hand in the F95 interface, but are
    automatically set in the simpler of the initialisation calls with
    the streamlined interface.} 
%\comment{new section for subgrids? Exact
%      v. Param}}
  \label{tab:acc-param}
\end{table}

\section{Additions in version 2}
\label{sec:v2-additions}
The following sections detail additions in \hoppet{} that appeared in
v2.0.0. 

\input{v2-updates.tex}


%======================================================================
\section{Conclusions}

\hoppet is an $x$--space evolution code that is novel both in terms of
the accuracy and speed that it provides compared to other $x$--space
codes, and in terms of its interface, designed to provide a
straightforward and physical way of manipulating PDFs beyond the
built-in task of DGLAP evolution.

Features that might be envisaged for future releases include DIS
coefficient functions, full support for the DIS factorisation scheme,
and the addition of time-like evolution, relevant
for phenomenological fits to fragmentation functions
as in \cite{deFlorian:2007hc}.  
In principle, the
information presented here is sufficient to allow a user to implement
the coefficient functions themselves, while the DIS scheme and
timelike evolution would require somewhat more knowledge of the
internals of the program. 

More ambitious possible extensions cover a wide range of physics.
Just within QCD, a general physical feature absent from mainstream PDF
evolution codes is that of evolution that includes matching with
various types of resummed calculations. Although studies in this direction
have already been performed, both for small $x$ resummations, 
as in \cite{White:2005wm}
 and for large $x$ resummation, as in \cite{Corcella:2005us},
no general public code exists which performs a matching between
resummed 
 and fixed (NLO, NNLO) order
splitting functions, either in the time-like case or in
the space-like case. In particular, work to extend
\hoppet in order to deal with general interpolated
splitting functions and coefficient functions, required
to implement small-$x$ resummation, is in progress.

Another interesting extension of \hoppet would be to
implement a more general mass treatment of heavy quarks.
A proper treatment of heavy quark mass effects is required to
obtain a good description of heavy flavour structure function
as measured in HERA. Although there are by now several studies
of the effect of heavy quark masses in global analysis
of PDFs \cite{Martin:2007bv,Tung:2006tb},
 which show sizable effects on predictions for
LHC observables, there does not exist right now a public code
were this General Mass heavy quark schemes are implemented.

Also of interest are non-QCD effects. Evolutions with QED radiation
have been presented in \cite{Weinzierl:2002mv,Martin:2004dh}, 
however so far no public code
exists for evolution including both QCD and electroweak (EW) effects
\cite{Ciafaloni:2000df,Ciafaloni:2005fm}.
This is of particular relevance at LHC energies, since flavour is
associated with an SU(2) charge and so soft divergences (above $M_W$)
do not cancel in the PDF evolution between real and virtual
contributions, leading one to expect
non-negligible effects in the flavour structure of the PDFs at high
scales.
%
The full QCD+EW evolution is a rather task complicated because of the
need to include the EW flavour couplings, including the CKM matrix,
and polarisation. For this kind of problem a code such as \hoppet
provides a good starting point, since it has a clean separation of the
numerical and flavour aspects of evolution, and verified unpolarised
and polarised evolution.


%======================================================================
\section*{Acknowledgements}

This work was initiated in the context of DIS event shape resummation
and matching studies \cite{Dasgupta:2001eq,Dasgupta:2002dc} with Mrinal Dasgupta.
%
Its subsequent development into a fully-featured NNLO evolution code
owes much to Andreas Vogt's regular encouragement, and his suggestions
about features that would be useful to include for benchmark tests.
We are grateful also to Wu-Ki Tung for comments on the documentation.
%
We are also grateful to Luca Buonocore for his contribution of the
implementation of the $P_{\ell q}$ term in the QED evolution.

This work was supported in part by grant ANR-05-JCJC-0046-01 from the
French Agence Nationale de la Recherche,
%
by a Royal Society Research Professorship
(RP$\backslash$R1$\backslash$180112 and RSRP$\backslash$R$\backslash$231001),
%
and by the Science and Technology Facilities Council (STFC) under grants
ST/T000864/1 and ST/X000761/1 (GPS).

%======================================================================
\appendix


%======================================================================
\section{Example programs}
\label{sec:example_program}

\subsection{General interface}
\label{sec:example_gen}

The program below generates a subset of table~15 of the NNLO benchmark
evolution in the second reference of~\cite{Giele:2002hx,Dittmar:2005ed}. It is to be
found (in a slightly more commented form) in
\ttt{example\_f90/tabulation\_example.f90}. Compilation instructions
are to be found in the \ttt{README} file in the main directory of the
release. A program that has the same functionality but in F77, using
the streamlined interface of section~\ref{sec:vanilla}, is to be found as
\ttt{example\_f77/tabulation\_example.f} (cf.\ section~\ref{sec:stream-example}).


\begin{lstlisting}
program tabulation_example
  use hoppet
  implicit none
  real(dp)         :: dy, ymax, quark_masses(4:6)
  integer          :: order, nloop, ix
  type(grid_def)   :: grid, gdarray(4) ! holds information about the grid
  type(dglap_holder)     :: dh         ! holds the splitting functions
  type(pdf_table)        :: table      ! holds the PDF tabulation
  type(running_coupling) :: coupling  
  real(dp), pointer      :: pdf0(:,:)  ! holds the initial pdf
  real(dp)               :: Q0, Q, pdf_at_xQ(-6:6)
  real(dp), parameter :: heralhc_xvals(9) = &
       & (/1e-5_dp,1e-4_dp,1e-3_dp,1e-2_dp,0.1_dp,0.3_dp,0.5_dp,0.7_dp,0.9_dp/)

  ! set up parameters for grid
  order = -6
  ymax  = 12.0_dp
  dy    = 0.1_dp
  
  ! set up the grid itself -- we use 4 nested subgrids
  call InitGridDef(gdarray(4),dy/27.0_dp, 0.2_dp, order=order)
  call InitGridDef(gdarray(3),dy/9.0_dp,  0.5_dp, order=order)
  call InitGridDef(gdarray(2),dy/3.0_dp,  2.0_dp, order=order)
  call InitGridDef(gdarray(1),dy,          ymax , order=order)
  call InitGridDef(grid,gdarray(1:4),locked=.true.)

  ! initialise the splitting-function holder
  nloop = 3
  call InitDglapHolder(grid,dh,factscheme=factscheme_MSbar,&
       &                      nloop=nloop,nflo=3,nfhi=6)

  ! initialise a PDF from the function below (must be contained,
  ! in a "used" module, or with an explicitly defined interface)
  call AllocPDF(grid, pdf0)
  pdf0 = unpolarized_dummy_pdf(xValues(grid))
  Q0 = sqrt(2.0_dp)  ! the initial scale

  ! allocate and initialise the running coupling with a given
  ! set of quark masses (NB: charm mass just above Q0).
  quark_masses(4:6) = (/1.414213563_dp, 4.5_dp, 175.0_dp/)
  call InitRunningCoupling(coupling,alfas=0.35_dp,Q=Q0,nloop=nloop,&
       &                   quark_masses = quark_masses)

  ! create the tables that will contain our copy of the user's pdf
  ! as well as the convolutions with the pdf.
  call AllocPdfTable(grid, table, Qmin=1.0_dp, Qmax=10000.0_dp, & 
       & dlnlnQ = dy/4.0_dp, freeze_at_Qmin=.true.)
  ! add information about the nf transitions to the table (improves
  ! interpolation quality)
  call AddNfInfoToPdfTable(table,coupling)

  ! create the tabulation based on the evolution of pdf0 from scale Q0
  call EvolvePdfTable(table, Q0, pdf0, dh, coupling, nloop=nloop)
  ! alternatively "pre-evolve" so that subsequent evolutions are faster
  !call PreEvolvePdfTable(table, Q0, dh, coupling)
  !call EvolvePdfTable(table,pdf0)

  ! get the value of the tabulation at some point
  Q = 100.0_dp
  write(6,'(a,f8.3,a)') "           Evaluating PDFs at Q = ",Q," GeV"
  write(6,'(a5,2a12,a14,a10,a12)') "x",&
       & "u-ubar","d-dbar","2(ubr+dbr)","c+cbar","gluon"
  do ix = 1, size(heralhc_xvals)
     call EvalPdfTable_xQ(table,heralhc_xvals(ix),Q,pdf_at_xQ)
     write(6,'(es7.1,5es12.4)') heralhc_xvals(ix), &
          &  pdf_at_xQ(2)-pdf_at_xQ(-2),  pdf_at_xQ(1)-pdf_at_xQ(-1), &
          &  2*(pdf_at_xQ(-1)+pdf_at_xQ(-2)), (pdf_at_xQ(-4)+pdf_at_xQ(4)), &
          &  pdf_at_xQ(0)
  end do
  
  ! some cleaning up (not strictly speaking needed, but illustrative)
  call Delete(table); call Delete(pdf0); call Delete(dh)
  call Delete(coupling);  call Delete(grid)

contains 
  !======================================================================
  !! The dummy PDF suggested by Vogt as the initial condition for the 
  !! unpolarized evolution (as used in hep-ph/0511119).
  function unpolarized_dummy_pdf(xvals) result(pdf)
    real(dp), intent(in) :: xvals(:)
    real(dp)             :: pdf(size(xvals),-6:7) ! note upper bound!
    real(dp) :: uv(size(xvals)), dv(size(xvals))
    real(dp) :: ubar(size(xvals)), dbar(size(xvals))
    !---------------------
    real(dp), parameter :: N_g = 1.7_dp, N_ls = 0.387975_dp
    real(dp), parameter :: N_uv=5.107200_dp, N_dv = 3.064320_dp
    real(dp), parameter :: N_db = half*N_ls
  
    pdf = zero

    !-- remember that these are all xvals*q(xvals)
    uv = N_uv * xvals**0.8_dp * (1-xvals)**3
    dv = N_dv * xvals**0.8_dp * (1-xvals)**4
    dbar = N_db * xvals**(-0.1_dp) * (1-xvals)**6
    ubar = dbar * (1-xvals)

    ! labels iflv_g, etc., come from the hoppet module
    pdf(:, iflv_g) = N_g * xvals**(-0.1_dp) * (1-xvals)**5
    pdf(:,-iflv_s) = 0.2_dp*(dbar + ubar)
    pdf(:, iflv_s) = pdf(:,-iflv_s)
    pdf(:, iflv_u) = uv + ubar
    pdf(:,-iflv_u) = ubar
    pdf(:, iflv_d) = dv + dbar
    pdf(:,-iflv_d) = dbar
  end function unpolarized_dummy_pdf

end program tabulation_example
\end{lstlisting}

\noindent The expected output from the program is:
{\small
\begin{lstlisting}
           Evaluating PDFs at Q =  100.000 GeV
    x      u-ubar      d-dbar    2(ubr+dbr)    c+cbar       gluon
1.0E-05  3.1907E-03  1.9532E-03  3.4732E+01  1.5875E+01  2.2012E+02
1.0E-04  1.4023E-02  8.2749E-03  1.5617E+01  6.7244E+00  8.8804E+01
1.0E-03  6.0019E-02  3.4519E-02  6.4173E+00  2.4494E+00  3.0404E+01
1.0E-02  2.3244E-01  1.3000E-01  2.2778E+00  6.6746E-01  7.7912E+00
1.0E-01  5.4993E-01  2.7035E-01  3.8526E-01  6.4466E-02  8.5266E-01
3.0E-01  3.4622E-01  1.2833E-01  3.4600E-02  4.0134E-03  7.8898E-02
5.0E-01  1.1868E-01  3.0811E-02  2.3198E-03  2.3752E-04  7.6398E-03
7.0E-01  1.9486E-02  2.9901E-03  5.2352E-05  5.6038E-06  3.7080E-04
9.0E-01  3.3522E-04  1.6933E-05  2.5735E-08  4.3368E-09  1.1721E-06
\end{lstlisting}
}

\noindent The file
\ttt{example\_f90/tabulation\_example.default\_output} contains a copy
of these results, so as to allow easy comparison. The numbers
correspond to evolution with variable flavour number, $\mu_F = \mu_R$,
and the parametrised versions of the NNLO splitting functions and mass
threshold terms.
%
The reader may verify that they correspond to those given in the top
panel of table~15 of the second reference of \cite{Giele:2002hx,Dittmar:2005ed} ($\mu_F
= \mu_R$).

\subsection{Streamlined interface}
\label{sec:stream-example}

The program below generates exactly the same output
as the previous example program, but this time
using the streamlined interface introduced
in section~\ref{sec:vanilla}. It is to be
found in
\ttt{example\_f90/tabulation\_example\_streamlined.f90}. 
A program with same interface and same output 
but in F77, is to be found in
\ttt{example\_f77/tabulation\_example.f}.

\begin{lstlisting}
program tabulation_example_streamlined
  use hoppet
  !! if using LHAPDF, rename a couple of hoppet functions which
  !! would otherwise conflict with LHAPDF 
  !use hoppet, EvolvePDF_hoppet => EvolvePDF, InitPDF_hoppet => InitPDF
  implicit none
  real(dp) :: dy, ymax, dlnlnQ, Qmin, Qmax, muR_Q
  real(dp) :: asQ, Q0alphas, Q0pdf
  real(dp) :: mc,mb,mt
  integer  :: order, nloop
  !! holds information about the grid
  type(grid_def) :: grid, gdarray(4)
  !! hold results at some x, Q
  real(dp) :: Q, pdf_at_xQ(-6:6)
  real(dp), parameter :: heralhc_xvals(9) = &
       & (/1e-5_dp,1e-4_dp,1e-3_dp,1e-2_dp,0.1_dp,0.3_dp,0.5_dp,0.7_dp,0.9_dp/)
  integer  :: ix

  ! set up parameters for grid
  order = -6
  ymax  = 12.0_dp
  dy    = 0.1_dp

  ! set up the grid itself -- we use 4 nested subgrids
  call InitGridDef(gdarray(4),dy/27.0_dp,0.2_dp, order=order)
  call InitGridDef(gdarray(3),dy/9.0_dp,0.5_dp, order=order)
  call InitGridDef(gdarray(2),dy/3.0_dp,2.0_dp, order=order)
  call InitGridDef(gdarray(1),dy,       ymax  ,order=order)
  call InitGridDef(grid,gdarray(1:4),locked=.true.)

  ! Streamlined initialisation
  Qmin=1_dp
  Qmax=28000_dp
  dlnlnQ = dy/4.0_dp
  nloop = 3
  call hoppetStartExtended(ymax,dy,Qmin,Qmax,dlnlnQ,nloop,&
       &         order,factscheme_MSbar)
    
  ! Set heavy flavour scheme
  mc = 1.414213563_dp
  mb = 4.5_dp
  mt = 175.0_dp
  call hoppetSetVFN(mc, mb, mt)
  
    ! Set parameters of running coupling
  asQ = 0.35_dp
  Q0alphas = sqrt(2.0_dp)
  muR_Q = 1.0_dp
  Q0pdf = sqrt(2.0_dp) ! The initial evolution scale
  ! Normal evolution
  call hoppetEvolve(asQ, Q0alphas, nloop,muR_Q,&
       &       LHAsub, Q0pdf)

  ! Uncomment to perform  cached evolution
  ! call hoppetPreEvolve(asQ, Q0alphas, nloop,muR_Q,Q0pdf) 
  ! call hoppetCachedEvolve(LHAsub)
    
  ! get the value of the tabulation at some point
  Q = 100.0_dp
  write(6,'(a)')
  write(6,'(a,f8.3,a)') "           Evaluating PDFs at Q = ",Q," GeV"
  write(6,'(a5,2a12,a14,a10,a12)') "x",&
       & "u-ubar","d-dbar","2(ubr+dbr)","c+cbar","gluon"
  do ix = 1, size(heralhc_xvals)
     call hoppetEval(heralhc_xvals(ix),Q,pdf_at_xQ)
     write(6,'(es7.1,5es12.4)') heralhc_xvals(ix), &
          &  pdf_at_xQ(2)-pdf_at_xQ(-2), &
          &  pdf_at_xQ(1)-pdf_at_xQ(-1), &
          &  2*(pdf_at_xQ(-1)+pdf_at_xQ(-2)), &
          &  (pdf_at_xQ(-4)+pdf_at_xQ(4)), &
          &  pdf_at_xQ(0)
  end do
  
contains 
 
  subroutine LHAsub(x,Q,pdf)
    ! Same as in the previous example program
  end subroutine LHAsub

end program tabulation_example_streamlined
\end{lstlisting}

\subsection{Interface example with QED included}
  The following is an example program using the QED extension of \hoppet{}.
  It can be found in \ttt{example\_f90/tabulation\_example\_qed.f90}.
  
\begin{lstlisting}
!! An example program using a tabulation. It should yield an output identical
!! to the content of the file tabulation_example_qed.default_output
!!
!!
program tabulation_example_qed
  use hoppet
  
  !! if using LHAPDF, rename the hoppet functions EvolvePDF and InitPDF, which
  !! would otherwise conflict with LHAPDF, by replacing the use
  !! statement above with:
  !use hoppet, EvolvePDF_hoppet => EvolvePDF, InitPDF_hoppet => InitPDF

  implicit none
  real(dp) :: dy, ymax
  integer  :: order, nloop_qcd
  !! holds information about the grid in y=log(1/x)
  type(grid_def) :: grid
  !! holds the splitting functions
  type(dglap_holder) :: dh
  !! holds the PDF tabulation
  type(pdf_table)       :: table
  !! holds the coupling
  real(dp)               :: effective_light_quark_masses, quark_masses(4:6)
  type(running_coupling) :: coupling
  !! holds the initial pdf
  real(dp), pointer :: pdf0(:,:)
  real(dp) :: Q0
  !! holds results at some x, Q
  real(dp) :: Q, pdf_at_xQ(ncompmin:ncompmaxLeptons)
  real(dp), parameter :: heralhc_xvals(9) = &
       & (/1e-5_dp,1e-4_dp,1e-3_dp,1e-2_dp,0.1_dp,0.3_dp,0.5_dp,0.7_dp,0.9_dp/)
  integer  :: ix
  !! Additional things for QED
  type(qed_coupling)  :: coupling_qed
  type(qed_split_mat) :: qed_split


  !! define the interfaces for LHA pdf (by default not used)
  !! (NB: unfortunately this conflicts with an internal hoppet name,
  !! so make sure that you "redefine" the internal hoppet name, 
  !! as illustrated in the commented "use" line above:
  !! use hoppet, EvolvePDF_hoppet => EvolvePDF, ...)
  ! interface
  !    subroutine EvolvePDF(x,Q,res)
  !      use types; implicit none
  !      real(dp), intent(in)  :: x,Q
  !      real(dp), intent(out) :: res(*)
  !    end subroutine EvolvePDF
  ! end interface

  ! set up parameters for grid
  order = -6
  ymax  = 12.0_dp
  dy    = 0.1_dp

  ! set up the grid itself (this call sets up a nested grid composed of 4 subgrids)
  call InitGridDefDefault(grid, dy, ymax, order=order)

  ! initialise the splitting-function holder
  nloop_qcd = 3
  nqcdloop_qed = 1
  with_Plp_nnloqed=.false.
  
  call InitDglapHolder(grid,dh,factscheme=factscheme_MSbar,&
       &                      nloop=nloop_qcd,nflo=3,nfhi=6)

  ! and the QED splitting matrices
  call InitQEDSplitMat(grid, qed_split)

  write(6,'(a)') "Splitting functions initialised!"

  ! allocate a pdf0 array including leptons
  call AllocPDFWithLeptons(grid, pdf0)

  ! initialise a PDF from the function below (must be contained,
  ! in a "used" module, or with an explicitly defined interface)
  ! pdf0(:,-6:6) are the standard pdf for quarks and gluons,
  ! pdf0(:,8) is the photon density,
  ! pdf0(:,9:11) are the sum of lepton-antilepton densities
  ! for the electron, the muon and the tau.
  pdf0(:,:) = unpolarized_dummy_pdf(xValues(grid))  

  Q0 = sqrt(2.0_dp)  ! the initial scale

  ! allocate and initialise the running coupling with a given
  ! set of quark masses (NB: charm mass just above Q0).
  quark_masses(4:6) = (/1.414213563_dp, 4.5_dp, 175.0_dp/)
  call InitRunningCoupling(coupling,alfas=0.35_dp,Q=Q0,nloop=nloop_qcd,&
       &                   quark_masses = quark_masses)

  ! Initialises coupling_qed object, including thresholds. All light
  ! quarks turn on simultaneously at some specified effective scale; the
  ! choice of m_light_quarks_default (defined in qed_coupling_module, to
  ! be 0.1055 GeV, as of 2025-10-10) results in values of 
  ! alpha(mZ) and alpha(m_tau) and that are within 1 sigma of the PDG
  ! MSbar value
  effective_light_quark_masses = m_light_quarks_default
  call InitQEDCoupling(coupling_qed, effective_light_quark_masses, quark_masses(4:6))

  ! create the table object that will contain the values of the parton
  ! densities in a grid of x and Q interpolation points.
  call AllocPdfTableWithLeptons(grid, table, Qmin=1.0_dp, Qmax=28000.0_dp, & 
       & dlnlnQ = dy/4.0_dp, freeze_at_Qmin=.true.)
  ! add information about the nf transitions to the table (improves
  ! interpolation quality)
  call AddNfInfoToPdfTable(table,coupling)

  ! create the tabulation based on the evolution of pdf0 from scale Q0
  ! up to qmax and down to qmin
  call EvolvePdfTableQED(table, Q0, pdf0, dh, qed_split, &
                         coupling, coupling_qed, nloop_qcd, nqcdloop_qed)

  write(6,'(a)') "Evolution done!"

  ! get the value of the tabulation at some point
  Q = 91.1876_dp;
  write(6,'(a)')
  write(6,'(a,f9.4,a,f8.5)') " At Q = ",Q," GeV, QCD coupling is alpha_s     = ", value(coupling, Q)
  write(6,'(a,f9.4,a,f8.3)') " At Q = ",Q," GeV, QED coupling is 1/alpha_qed = ", one/value(coupling_qed, Q)
  write(6,'(a,f6.4,a,f8.3)') " At mtau = ",m_tau," GeV, QED coupling is 1/alpha_qed = ", one/value(coupling_qed, m_tau/1.0000001_dp)
  write(6,'(a)')

  ! Get values at some points and print them 
  Q = 100.0_dp
  write(6,'(a,f9.4,a)') "           Evaluating PDFs at Q = ",Q," GeV"
  write(6,'(a5,2a12,a14,a10,a11,4a13)') "x",&
       & "u-ubar","d-dbar","2(ubr+dbr)","c+cbar","gluon",&
       & "photon","e+ + e-","mu+ + mu-","tau+ + tau-"
  do ix = 1, size(heralhc_xvals)
     call EvalPdfTable_xQ(table,heralhc_xvals(ix),Q,pdf_at_xQ)
     write(6,'(es7.1,9es12.4)') heralhc_xvals(ix), &
          &  pdf_at_xQ(2)-pdf_at_xQ(-2), &
          &  pdf_at_xQ(1)-pdf_at_xQ(-1), &
          &  2*(pdf_at_xQ(-1)+pdf_at_xQ(-2)), &
          &  (pdf_at_xQ(-4)+pdf_at_xQ(4)), &
          &  pdf_at_xQ(0), &
          &  pdf_at_xQ(iflv_photon), &
          &  pdf_at_xQ(iflv_electron), &
          &  pdf_at_xQ(iflv_muon),&
          &  pdf_at_xQ(iflv_tau)          
  end do
  
  ! some cleaning up (not strictly speaking needed, but illustrates
  ! how it's done)
  call Delete(table)
  call Delete(pdf0)
  call Delete(dh)
  call Delete(coupling)
  call Delete(grid)
  call Delete(qed_split)
  call Delete(coupling_qed)

contains 
  !======================================================================
  !! The dummy PDF suggested by Vogt as the initial condition for the 
  !! unpolarized evolution (as used in hep-ph/0511119).
  function unpolarized_dummy_pdf(xvals) result(pdf)
    real(dp), intent(in) :: xvals(:)
    real(dp)             :: pdf(size(xvals),ncompmin:ncompmaxLeptons)
    real(dp) :: gluon(size(xvals)), uv(size(xvals)), dv(size(xvals))
    real(dp) :: ubar(size(xvals)), dbar(size(xvals))
    !---------------------
    real(dp), parameter :: N_g = 1.7_dp, N_ls = 0.387975_dp
    real(dp), parameter :: N_uv=5.107200_dp, N_dv = 3.064320_dp
    real(dp), parameter :: N_db = half*N_ls
  
    pdf = zero
    ! clean method for labelling as PDF as being in the human representation
    ! (not actually needed after setting pdf=0
    call LabelPdfAsHuman(pdf)

    !-- remember that these are all xvals*q(xvals)
    gluon = N_g * xvals**(-0.1_dp) * (1-xvals)**5
    uv = N_uv * xvals**0.8_dp * (1-xvals)**3
    dv = N_dv * xvals**0.8_dp * (1-xvals)**4
    dbar = N_db * xvals**(-0.1_dp) * (1-xvals)**6
    ubar = dbar * (1-xvals)

    ! labels iflv_g, etc., come from the hoppet module, inherited
    ! from the main program
    pdf(:, iflv_g) = 0.99_dp * gluon
    pdf(:,-iflv_s) = 0.2_dp*(dbar + ubar)
    pdf(:, iflv_s) = pdf(:,-iflv_s)
    pdf(:, iflv_u) = uv + 0.9_dp * ubar
    pdf(:,-iflv_u) = 0.9_dp * ubar
    pdf(:, iflv_d) = dv + 0.9_dp * dbar
    pdf(:,-iflv_d) = 0.9_dp * dbar
    pdf(:,iflv_photon) = gluon/100._dp + ubar/10._dp 
    pdf(:,iflv_electron) = dbar/10._dp
    pdf(:,iflv_muon) = ubar/10._dp
    pdf(:,iflv_tau) = dbar/10._dp         

  end function unpolarized_dummy_pdf

end program tabulation_example_qed



\end{lstlisting}

\subsection{Other general-interface examples}

To help better illustrate the usage of the general interface,
additional examples are available in the \ttt{examples\_f90/} and
\ttt{benchmarking/} directories. One,
\ttt{examples\_f90/tabulation\_example\_2.f90}, summarised briefly
below, illustrates how to distribute initialisation and evolution
tasks across different parts of the program, and also illustrates how
to verify sum rules. A second example for sum rules,
\ttt{examples\_f90/sumrules.f90}, also illustrates the use of
evolution without tabulation.
%
The programs in the \ttt{benchmarking/} directory are the ones that
have been used in benchmark PDF evolution
comparisons~\cite{Giele:2002hx,Dittmar:2005ed} and in determining the accuracies and
speeds shown in section~\ref{sec:benchmarks}.

One particular usage question that has arisen, relative to the example
in appendix~\ref{sec:example_gen}, is what to do when a table (or
other evolution components) need to be accessed from different
subprograms, as would be the case in a typical global-fit code.  The
answer is that the derived-type variables that should persist outside
a specific subroutine call must be placed in a \ttt{module} that is
then accessed from each of the subprograms. The module might be
\begin{lstlisting}
! common location for your table and other evolution components
module external_table_module 
   use hoppet
   implicit none
   type(pdf_table) :: table
   type(dglap_holder) :: dh
   type(running_coupling) :: coupling
   type(grid_def) :: grid  ! here for convenience, not strictly necessary
end module external_table_module
\end{lstlisting}
Here \texttt{table}, \texttt{dh} and \ttt{coupling} have all been
placed in the module insofar as they are initialised/used in more than
one location in the schematic subprograms below
\begin{lstlisting}
subroutine A
   use external_table_module
   ! initialisation/allocation of grid, dh, table, coupling, ...
end subroutine A

subroutine B
   use external_table_module
   call PreEvolvePdfTable(table, Q0, dh, coupling)
end subroutine B

subroutine C
   use external_table_module
   ...
   call EvolvePdfTable(table,pdf0)
end subroutine C

subroutine D
   use external_table_module
   ...
   call EvalPdfTable_xQ(table, x, Q, pdf)
end subroutine D

\end{lstlisting}
%
A more detailed description of the above technique 
can be found in a 
second example program, called \ttt{tabulation\_example\_2.f90},
which is available in the \ttt{example\_f90} 
directory. It generates exactly
the same output as the previous example program, as well as additional
output about truncated moments (sum rules), while
providing an example of how to access a table from
external procedures, as explained in section~\ref{sec:acc_table}.




%===================================================================


%==========================================================
% In future releases of the documentation

%\section{Public objects}
%In this Appendix we list some of the
%most important public objects that are
%accessible through the common {\tt hoppet} module. For
%simplicity we describe here only the public procedures and
%not the public variables.

%\begin{table}
%\scriptsize
%\begin{center}
%\begin{tabular}{|c|c|c|c|}
%\hline
%{\bf module}  & {\bf procedure}  &  {\bf arguments}  & {\bf description} \\
%\hline
%\ttt{pdf\_tabulate}  &   & & \\
%  &  \ttt{AllocPdfTable} & &\\
%\hline
%\ttt{pdf\_representation} && &\\
%\hline
%\end{tabular}
%\end{center}
%\end{table}

%=======================================================

\section{HOPPET reference guide}
\label{sec:refguide}

In this section we present the \hoppet reference guide, a 
summary of the most important modules in the package with
the corresponding description, both the streamlined interface,
Table \ref{tab:streamlined} and for the general interface,
Table  \ref{tab:general}.

\begin{table}
\begin{center}
{\bf \large STREAMLINED INTERFACE}
\\
\vspace{0.2cm}
\begin{tabular}{|c|c|}
\hline
\bf METHOD  & \bf DESCRIPTION \\
\hline
\bf Initialisation & \\
\hline
\begin{lstlisting}
 hoppetStart(dy,nloop)
\end{lstlisting} 
& \scriptsize
Sets up a compound grid with
spacing in $\ln 1/x$ of \ttt{dy} at small $x$,\\ &
\fn~  extending to $y = 12$ and numerical
order $\ttt=-6$. \\ & \fn~  The $Q$ range for the tabulation will be $1\GeV <
Q<28 \TeV$, \\
& \fn~ \ttt{dlnlnQ=dy/4} and the factorisation scheme is ${\overline{\rm MS}}$\\
\hline
\begin{lstlisting}
 hoppetStartExtended(ymax,dy,Qmin,
 Qmax,dlnlnQ,nloop,order,factscheme)
\end{lstlisting} & \fn
  ~More general initialisation \\
\hline 
\begin{lstlisting}
 hoppetSetFFN(fixed_nf)
 hoppetSetVFN(mc, mb, mt)
\end{lstlisting} &
\fn ~Set heavy flavour scheme
\\
\hline
\begin{lstlisting}
  alphas = hoppetAlphaS(Q)
\end{lstlisting} &
\fn~Accessing the coupling \\
\hline&\\[-0.5em]
\bf Normal evolution & \\
\hline
\texttt{\footnotesize
 hoppetEvolve(asQ,Q0alphas,}
& \fn\ PDF evolution: specifies the coupling \ttt{asQ} at a 
scale \ttt{Q0alphas}, \\
 \texttt{\footnotesize nloop,muR\_Q,LHAsub,Q0pdf)}&
 \fn the number of loops for  evol., \ttt{nloop}, \\
&\fn the ratio (\ttt{muR\_Q}) of ren. to fact. scales. \\ 
&  \fn the name of a subroutine \ttt{LHAsub} with an LHAPDF-like interface \\
&  \fn and the scale
\ttt{Q0pdf} at which one starts the PDF evolution \\
&  \fn Note:  \ttt{LHAsub} only called at scale \ttt{Q0pdf}\\
\hline
\begin{lstlisting}
 hoppetEval(x,Q,f)
\end{lstlisting} &
\fn On return, \ttt{f(-6:6)} contains all flavours of the PDF set\\ 
%The PDF at a given value of  is obtained \\
& \fn ~
(multiplied by $x$) at the given $\ttt{x}$ and $\ttt{Q}$ values \\
\hline&\\[-0.5em]
\bf Cached evolution & \\
\hline
\begin{lstlisting}
 hoppetPreEvolve(asQ,Q0alphas, 
          nloop, muR_Q, Q0pdf)
\end{lstlisting} & \fn ~
 Preparation of the cached evolution\\
\hline
\begin{lstlisting}
 hoppetCachedEvolve(LHAsub)
\end{lstlisting} &
\fn  Perform cached evolution with the initial condition\\
& \fn at \ttt{Q0pdf} from a routine \ttt{LHAsub} 
with LHAPDF-like interface\\
&  \fn Notice  \ttt{LHAsub} only called at scale \ttt{Q0pdf}\\
\hline
\begin{lstlisting}
 hoppetEval(x,Q,f)
\end{lstlisting} &
\fn On return, \ttt{f(-6:6)} contains all flavours of the PDF set\\ 
%The PDF at a given value of  is obtained \\
& \fn ~
(multiplied by $x$) at the given $\ttt{x}$ and $\ttt{Q}$ values \\
& \fn [as for normal evolution]\\
\hline
\end{tabular}
\end{center}
\caption{\label{tab:streamlined} Reference guide for the streamlined
  interface. Note that \hoppet should be supplied with and returns parton
  densities multiplied by $x$.}
\end{table}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% \begin{table}
% 
% 
% \\
% 


\begin{table}
\scriptsize
\begin{center}
{\bf \large GENERAL INTERFACE} \\
\vspace{0.5cm} 
%\scalebox{0.01}{
\begin{tabular}{|c|c|}
\hline
\bf TYPES  & \bf DESCRIPTION \\
\hline
\texttt{type(grid\_def) :: grid} & $x-$space grid definition \\ 
\hline
\texttt{real(dp), pointer :: gluon(:)} & Holds a 
`grid quantity' (\eg gluon PDF) \\
\hline
\texttt{real(dp), pointer :: PDFset(:,:)} & 
Grid representation of a (13-flavour) PDF set \\
\hline
\texttt{type(grid\_conv) :: Pgg} 
 & Convolution operator ({\it i.e.} splitting function) \\ 
\hline
\texttt{ type(split\_mat) :: Pmat}
 & Splitting matrix (with full flavour structure)\\ 
\hline
 \texttt{type(mass\_threshold\_mat) :: MTM\_NNLO}
 & Heavy quark mass-threshold matrix\\ 
\hline
\texttt{ type(dglap\_holder) :: dglap\_h} & DGLAP holder (\ie all
splitting and mass-threshold matrices) \\
\hline
\texttt{type(running\_coupling) :: coupling} & Running coupling \\
\hline
\texttt{type(evln\_operator) :: evop} & Evolution operator (linked
list of split \& mass-threshold matrices)\\
\hline
\texttt{type(pdf\_table) :: table} & PDF set tabulated in $x$ \& $Q$\\
\hline
\end{tabular}
\vspace{0.7cm}\\
\begin{tabular}{|c|c|}
\hline
\bf METHOD  & \bf DESCRIPTION \\
\hline &\\[-0.5em]
\bf Initialisation & \\[0.3em]
\hline
\texttt{
 InitGridDef(grid,dy=0.1\_dp,ymax=10.0\_dp,order=3)
}
 &
~ ~Initialise a grid definition \\
\hline
\texttt{
InitGridDef(grid,subgrids(:),locked=.true.)
}
 &
~ ~Combine subgrids into a single grid \\
\hline
\texttt{
 AllocGridQuant(grid,gluon)
} 
 &
Allocate memory for a grid quantity (\eg gluon PDF) \\
\hline
\texttt{
 InitGridQuant(grid,gluon,example\_gluon\_fn)
} 
 &
~ ~Initialisation of a grid quantity (\eg gluon PDF) \\
\hline
\texttt{
 AllocPDF(grid,pdfset)
} 
 &
Allocate memory for a 13-flavour PDF set \\
\hline
\texttt{InitPDF\_LHAPDF(grid,pdfset,LHAsub,Q)} 
 &
   Initialisation of a (13-flavour) PDF set from LHAPDF \\
&  type routine. Note: it only calls \ttt{LHAsub} at the scale \ttt{Q}\\
\hline
\texttt{
InitGridConv(grid,Pgg,Pgg\_func)
}  (*)
 &
~ ~Initialisation of a convolution operator \\
\hline
\texttt{
InitDglapHolder(grid, dglap\_h, factscheme, nloop)
}  (*)
&
~ ~Initialisation of a {\tt dglap\_holder} type \\
\hline
\texttt{
 InitRunningCoupling(coupling [, alfas] [, Q]} 
&
~ ~Initialisation of a {\tt running\_coupling} type \\
\texttt{[, nloop] [, fixnf] [, quark\_masses] )}  (*)&
\\
\hline
\texttt{
 AllocPdfTable(grid, table, Qmin, Qmax}  
&
~ ~Allocate space for a {\tt pdf\_table} type \\
\texttt{[, dlnlnQ ] [, lnlnQ\_order ] [, freeze\_at\_Qmin] )
} (*) & \\
\hline &\\[-0.5em]
\bf Evaluation \& manipulation & \\[0.3em]
\hline
\texttt{
EvalGridQuant(grid,gluon,y)
}
 & ~~Evaluation of a grid quantity at $y=\ln 1/x$\\
\hline
\texttt{Pgg.conv.gluon} & Convolution of a splitting function with a
(1-flav) PDF  \\
\hline
\texttt{Pmat.conv.PDFset} & Convolution of a splitting matrix
with a PDF set  \\
\hline
\texttt{
SetToConvolution(Pab,Pac,Pcb) 
}
 & ~~Convolution of splitting functions, \ttt{Pab = Pac Pcb} \\
\hline
\texttt{
 EvalPdfTable\_yQ(table, y, Q, pdf)
}
 & Evaluate the 13 flavours, \ttt{pdf(-6:6)}, of a tabulated \\
 & PDF set at $y$ and $Q$\\
\hline&\\[-0.5em]
\bf Evolution  & \\[0.3em]
\hline 
\texttt{
 CopyHumanPdfToEvln(nf\_lcl, pdf\_human, pdf\_evln)
} & ~~
Transform PDF set from {\tt human} to {\tt evln}
representation \\
\hline
\texttt{
GetPdfRep(pdfset)
} & ~~
Check PDF set representation \\
\hline
\texttt{
 EvolvePDF(dglap\_h, initial\_pdfset, coupling,}
 & ~~
Evolution of an initial condition for a PDF set \\
\texttt{ Q\_init,Q\_end ,[, muR\_Q] [, nloop] [,du])} 
& at {\tt Q\_init} to  {\tt Q\_end} \\
\hline
\texttt{
 EvolvePdfTable(table, Q0, initial\_pdfset, dglap\_h,} 
 & ~~ 
Fill a table starting from an initial condition,\\
\texttt{ coupling  [, muR\_Q] [, nloop] [, untie\_nf])} 
& \ttt{initial\_pdfset}, at the scale {\tt Q0} \\ 
\hline
\end{tabular} \\
%}
%\vspace{0.7cm}
\end{center}
\caption{\label{tab:general}
Reference guide for the general interface.
The upper table describes the main
derived types defined in \hoppet.
%
The lower table summarises some of the most relevant methods. Note that arguments
between \texttt{[...]} are optional. For grid quantities and PDF sets
the user must explicitly make memory allocation calls; in other cases
(marked with a (*)), initialisation routines automatically
allocate the memory. For all types, allocated memory may be freed with
a call to the \ttt{Delete(...)} subroutine. }
\end{table}


%------------------------------------------------------


\section{Initialisation of grid quantities}
\label{sec:gridinit}
As has been mentioned in
section~\ref{sec:xspc},  
there exist several ways of setting a grid quantity. In this
Appendix we describe the most important methods for initialising
a grid quantity, which we take to be a parton distribution.

There are a number of ways of setting a grid quantity. Suppose we have
a subroutine
\begin{lstlisting}
  subroutine example_gluon(y,g)
    use types                !! defines "dp" (double precision) kind
    implicit none
    real(dp), intent(in)  :: y
    real(dp), intent(out) :: g
    real(dp) :: x
    
    x = exp(-y)
    g = 1.7_dp * x**(-0.1_dp) * (1-x)**5 
  end subroutine example_gluon
\end{lstlisting}
Then we can call
\begin{lstlisting}
call InitGridQuantSub(grid,gluon,example_gluon)
\end{lstlisting}
to initialise \texttt{gluon} with a representation of the return value
from the subroutine \texttt{example\_gluon}.

An alternative way is to
make use of functions \texttt{xValues} or \texttt{yValues} that
respectively return the $x$ or $y$ values of all points on the grid:
\begin{lstlisting}
  real(dp), pointer :: gluon,xvals
  call AllocGridQuant(grid,gluon)
  call AllocGridQuant(grid,xvals)
  xvals = xValues(grid)
  gluon = 1.7_dp * xvals**(-0.1_dp) * (1-xvals)**5 
  deallocate(xvals)
\end{lstlisting}
Though more laborious insofar as one has to worry about some extra
allocation and deallocation, it has the advantage that one no longer
has to write a separate subroutine.

Finally, there is an option to initialise a multi-flavour
PDF grid with a subroutine with the same format as
\ttt{evolvePDF} from the \ttt{LHAPDF} library. This
option works as follows:

\begin{lstlisting}
real(dp),pointer :: pdf_set(:,:)
real(dp)         :: y,Q
real(dp)         :: pdf_at_y(-6:6)

Q=2   ! Initial scale

! Initialise with LHAPDF-like routine
call AllocPDF(grid,pdf_set)
call InitGridQuantLHAPDF(grid, pdf_set, LHAsub, Q)

! Evaluate the multi-flavor pdf at y
pdf_at_y = EvalGridQuant(grid,pdf_set(:,-6:6),y)

\end{lstlisting}
where an example of  the \ttt{LHAsub} subroutine can be found in
section~\ref{sec:human-rep}

\section{NNLO splitting functions}
\label{sect:nnlo}
The exact NNLO splitting
functions derived by Moch, Vermaseren and Vogt
\cite{NNLO-NS,NNLO-singlet} involve long (multi-page) expressions in
terms of harmonic polylogarithms of up to weight 4. Very conveniently,
refs.~\cite{NNLO-NS,NNLO-singlet} provide the expressions directly in
terms of Fortran code.
%
The harmonic polylogarithms can be evaluated using the \ttt{hplog}
package of Gehrmann and Remiddi \cite{FortranPolyLog}, a copy of which
is included with the \hoppet package. 

The initial integrations needed to create the \ttt{split\_mat} objects
for the exact NNLO splitting functions for the full range of $n_f$
take of the order of minutes.  Since currently there is no option of
storing the splitting matrices in a file, this can be a bit
bothersome. So instead, by default, the program uses the approximate,
parametrised NNLO splitting functions also provided in
\cite{NNLO-NS,NNLO-singlet}. The parametrised splitting functions are
guaranteed to be accurate to within $0.1\%$ --- in practice since they
come in relatively suppressed by two powers of $\as$, the impact on
the evolution tends to be of the order of a  $10^{-5}$ relative effect
\cite{Giele:2002hx,Dittmar:2005ed}.

The user can choose whether to obtain the exact or parametrised NNLO
splitting functions using the following calls (to be made before
initialising the splitting matrices)
\begin{lstlisting}
  integer :: splitting_variant
  call dglap_Set_nnlo_splitting(splitting_variant)
\end{lstlisting}
with the following variants defined (as integer parameters) in the
module \ttt{dglap\_choices}:
\begin{lstlisting}
  nnlo_splitting_exact
  nnlo_splitting_param                   [default]
  nnlo_splitting_Nfitav
  nnlo_splitting_Nfiterr1
  nnlo_splitting_Nfiterr2
\end{lstlisting}
The last 3 are the parametrisations based on fits to reduced moment
information carried out in \cite{vanNeerven:1999ca,vanNeerven:2000uj}.
Though at the time they represented a valuable (and much used) step on
the way to full NNLO results, nowadays their interest is mainly
historical.

Note that only for the \ttt{nnlo\_splitting\_exact} can the colour
constants be varied (with the caveat about $d^{abc}d_{abc}$, as
discussed in section~\ref{sec:qcd}). For the other options the
NNLO splitting functions have been computed using the QCD values
for the colour factors.

%======================================================================
\section{Useful tips on Fortran~95}
\label{sec:f95appendix}

As Fortran~95's use in high-energy physics is not as widespread as
that of other languages such as Fortran~77 and \CPP{}, it is useful to
summarise some key novelties compared to Fortran~77, as well as some
points that might otherwise cause confusion. For further information
the reader is referred both to books about the language such as
\cite{F95Explained} and to web resources~\cite{F95WebResources}.

\paragraph{Free form.}  Most of the code in the \hoppet package is in
free-form. The standard extension for free-form form files is
\ttt{.f90}. There is no requirement to leave 6 blank spaces before
every line and lines can consist of up to 132 characters. The other
main difference relative to f77 fixed form is that to continue a line
one must append an append an ampersand, \ttt{\&}, to the line to be
continued. One may optionally include an ampersand as the first
non-space character of the continuation line.

For readability, many of the subprogram names in this documentation
are written with capitals at the start of each word. Note however that
free-form Fortran~95, like its fixed-form predecessors, is case
insensitive.

\paragraph{Modules, and features relating to arrays.} Fortran~95
allows one to package variables and subroutines into modules
\begin{lstlisting}
module test_module
  implicit none
  integer :: some_integer
contains
  subroutine print_array(array)
    integer, intent(in) :: array(:) ! size is known, first element is 1
                                    ! intent(in) == array will not be changed
    integer             :: i, n
    n = size(array)
    do i = 1, n
      print *, i, array(i)
    end do
  end subroutine hello_world
end module test_module
\end{lstlisting}
The variable \texttt{some\_integer} and the subroutine
\texttt{print\_array} are invisible to other routines unless they
explicitly \texttt{use} the module as in the following example:
\begin{lstlisting}
program test_program
  use test_module
  implicit none
  integer :: array1(5), array2(-2:2)
  integer :: i
  
  some_integer = 5   ! set the variable in test_module
  array1       = 0   ! set all elements of array1 to zero
  array2(-2:0) = 99  ! set elements 1..3 of array2 to equal to 3.
  array2(1:2)  = 2*array2(-1:0)  ! elements 1..2 equal twice elements -1..0

  print *, "Printing array 1"
  call print_array(array1)
  print *, "Printing array 2"
  call print_array(array2)
end program test_program
\end{lstlisting}
Constants can be assigned to arrays (\texttt{array1}) or array
subsections (\texttt{array2(-2:0)}), arrays can be assigned to arrays
of the same size (as is done for \texttt{array2(-2:0)}) and
mathematical operations apply to each element of the array (as with
the multiplication by 2).

When arrays are passed to function or subroutine that is defined in a
\texttt{use}d module, information about the size of the array is
passed along with the array itself. Note however that information
about the lower bound is \emph{not} passed, so that for both
\texttt{array1} and \texttt{array2}, \texttt{print\_array} will see
arrays whose valid indices will run from $1\ldots5$. Thus the output
from the program will be
\begin{lstlisting}
 Printing array 1
 1 0
 2 0
 3 0
 4 0
 5 0
 Printing array 2
 1 99
 2 99
 3 99
 4 198
 5 198
\end{lstlisting}
If \texttt{print\_array} wants \texttt{array} to have a different lower
bound it must specify it in the declaration, for example
\begin{lstlisting}
  integer, intent(in) :: array(-2:) ! size is known, first element is -2
\end{lstlisting}
While it may initially seem bizarre, there are good reasons for such
behaviour (for example in allowing a subroutine to manipulate multiple
arrays of the same size without having to worry about whether they all
have the same lower bounds).

\paragraph{Dynamic memory allocation, pointers.} One of the major
additions of f95 compared to f77 is that of dynamic memory allocation,
for example with pointers
\begin{lstlisting}
  integer, pointer :: dynamic_array(:)
  allocate(dynamic_array(-6:6))
  ! .. work with it ..
  deallocate(dynamic_array)
\end{lstlisting}
This is fundamental to our ability to decide parameters of the PDF
grid(s) at run-time. Pointers can be passed as arguments to subprograms.
If the subprogram does not specify the \texttt{pointer} attribute for
the dummy argument
\begin{lstlisting}
subroutine xyz(dummy_array)
  integer, intent(in) :: dummy_array(:)
\end{lstlisting}
then everything behaves as if the argument were a normal array (\eg
the default lower bound is $1$). Alternatively the subroutine can
specify that it expects a pointer argument
\begin{lstlisting}
subroutine xyz(dummy_pointer_array)
  integer, pointer :: dummy_pointer_array(:)
\end{lstlisting}
In this case the subroutine has the freedom to allocate and deallocate
the array. Note also that because a pointer to the full array
information is being passed, the lower bound of \texttt{dummy\_pointer\_array}
is now the same as in the calling routine. Though this sounds like a
technicality, it is important because a corollary is that a subroutine
can allocate a dummy pointer array with bounds that are passed back to
the calling subroutine (we need this for the flavour dimension of
PDFs, whose lower bound is most naturally $-6$). 

Note that in contrast to C/\CPP{} pointers, F95 pointers do
not explicitly need to be dereferenced --- in this respect they are
more like \CPP{} \emph{references}. To associate a pointer with an
object, one uses the \ttt{=>} syntax:
\begin{lstlisting}
  integer, target  :: target_object(10)
  integer, pointer :: pointer_to_object(:)
  pointer_to_object => target_object
  pointer_to_object(1:10) = 0        ! sets target_object(1:10)
\end{lstlisting}
One notes that the object that was pointed to had the \ttt{target}
attribute --- this is mandatory (unless the object is itself a
pointer).


\paragraph{Derived types.} Another feature of F95 that has been
heavily used is that of derived types (analogous to C's
\texttt{struct}):
\begin{lstlisting}
  type pair
    integer first, second
  end type pair 
\end{lstlisting}
Variables of this type can then be created and used as follows
\begin{lstlisting}
  type(pair) :: pair_object, another_pair_object
  pair_object%first  = 1
  pair_object%second = 2
  another_pair_object = pair_object
  print *, another_pair_object%second
\end{lstlisting}
where one sees that the entirety of the object can be copied with the
assignment (\texttt{=}) operator. Note that many of the derived types
used in \hoppet contain pointers and when such a derived type object
is copied, the copy's pointer just points to the same memory as the
original object's pointer. This is sometimes what you want, but on
other occasions will give unexpected behaviour: for example splitting
function types are derived types containing pointers, so when you
assign one splitting function object to another, they end up referring
to the same memory, so if you multiply one of them by a constant, the
other one will also be modified.

\paragraph{Operator overloading} While assignment behaves more or less
as expected by default with derived types (it can actually be modified
if one wants to), other operators do not have default definitions. So
if one wants to define, say, a multiplication of objects one may
associate a function with a given operator, using an interface block:
\begin{lstlisting}
module test_module
  interface operator(*)        ! provide access to dot_pairs through 
    module procedure dot_pairs ! the normal multiplication symbol
  end interface 
  interface operator(.dot.)    ! provide access to dot_pairs through
    module procedure dot_pairs ! a specially named operator
  end interface 
contains
  integer function dot_pairs(pair1, pair2)
    type(pair), intent(in) :: pair1, pair2
    dot_pairs = pair1%first*pair2%first + pair1%second*pair2%second
  end function dot_pairs
end module
\end{lstlisting}
given which we can then write
\begin{lstlisting}
  integer    :: i
  type(pair) :: pair1, pair2
  [... some code to set up pair values ...]
  ! now multiply them
  i = pair1 * pair2
  i = pair1 .dot. pair2  ! equivalent to previous statement
\end{lstlisting}
Since the multiplication operator (\texttt{*}) already exists for
all the default types, by defining it for a new type we have
\emph{overloaded} it. Note that there are some subtleties with
precedences of user-defined operators: operators (like \texttt{*})
that already exist have the same precedence as they have is usual
operators; operators that do not exist by default (\texttt{.dot}) have
the lowest possible preference, so, given the above definitions,
\begin{lstlisting}
  i = 2 + pair1 * pair2       ! legal
  i = 2 + pair1 .dot. pair2   ! illegal, means: (2+pair1).dot.pair2
  i = 2 + (pair1 .dot. pair2) ! legal
\end{lstlisting}
where the second line is illegal because we have not defined any
operator for adding an integer and a pair. Similarly care is needed
when using the \hoppet's operator \texttt{.conv.}.

\paragraph{Floating-point precision:}
A final point concerns floating-point variable types. Throughout we
have used definitions such as
\begin{lstlisting}
  real(dp), pointer :: pdf(:,:)
\end{lstlisting}
and written numbers with a trailing \texttt{\_dp}
\begin{lstlisting}
  param = 1.7_dp
\end{lstlisting}
Here \texttt{dp} is an integer parameter (defined in the
\texttt{types} module and accessible also through the
\texttt{hoppet} module), which specifies the \texttt{kind} of real
that we want to define, specifically double precision. We could also
have written \texttt{double precision} everywhere, but this is less
compact, and the use of a kind parameter has the advantage that we
can just modify its definition in one point in the program and the
precision will be modified everywhere. (Well, almost, since some
special functions are written in Fortran~77 using \texttt{double
  precision} declarations and do their numerics based on the
assumption that that truly is the type they're dealing with).

A word of caution: \ttt{1\_dp} is \emph{not} a double-precision
number, but rather an integer (\eg on many compilers \ttt{dp=8},
indicating a number with 8 bytes of storage, so that \ttt{1.0\_dp} is
an 8-byte floating-point number and \ttt{1\_dp} is an 8-byte integer).
%
Therefore trying to pass \ttt{1\_dp} as the value for a
double-precision dummy argument in a subprogram call will lead to a
compile-time error.

\paragraph{Optional and keyword arguments}

A feature of F95 that helps simplify user interfaces is that of
optional and keyword arguments. Suppose we have
\begin{lstlisting}
  subroutine hello(name, prefix, count)
    character(len=*),  intent(in)  :: name, prefix
    integer, optional, intent(in)  :: count
  end subroutine hello
\end{lstlisting}
Here the \ttt{count} argument is \ttt{optional} meaning that it need
not be supplied --- if it is absent the subroutine is should behave
sensibly all the same. Thus one can call the subroutine as
\begin{lstlisting}
  call hello(name, prefix)
  call hello(name, prefix, count)
\end{lstlisting}
Keyword arguments are useful if one doesn't want to remember the exact
order of a long list of arguments (or if one wants to specify just one
of several optional arguments). For example
\begin{lstlisting}
  call hello(name=name, prefix=prefix)
  call hello(prefix=prefix, name=name)
\end{lstlisting}
will do the same thing.


%=============================================================

%\input{bibliography}
\bibliographystyle{elsarticle-num}
\bibliography{hoppet.bib}

%=====================================================================



\end{document}
