## main203

Back to index.

    // main203.cc is a part of the PYTHIA event generator.
    // Copyright (C) 2026 Torbjorn Sjostrand.
    // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
    // Please respect the MCnet Guidelines, see GUIDELINES for details.

    // Authors:
    //            Juan Rojo

    // Keywords:
    //            Parton distribution
    //            LHAPDF

    // This program compares the internal and LHAPDF implementations of
    // some NNPDF 2.3 QCD+QED sets, for results and for timing.
    // Warning: this example is constructed to work for LHAPDF5,
    // but current choice is LHAPDF6, which gives some differences.

    #include "Pythia8/Pythia.h"
    #include "Pythia8/Plugins.h"
    using namespace Pythia8;

    //==========================================================================

    int main() {

      cout<<"\n NNPDF3.1 QED LO phenomenology \n "<<endl;
      cout<<"\n Check access to NNPDF3.1 NNLO QED sets \n "<<endl;

      // Generator.
      Pythia pythia;

      // Access the PDFs.
      int idBeamIn = 2212;
      string pdfPath = pythia.settings.word("xmlPath") + "../pdfdata";
      Logger logger;

      // Grid of studied points.
      string xpdf[] = {"x*g","x*d","x*u","x*s"};
      double xlha[] = {1e-5, 1e-1};
      double Q2[] = { 2.0, 10000.0 };
      string setName;
      string setName_lha;

      // For timing checks.
      int const nq = 500;
      int const nx = 500;
      int const iqMax = sizeof( xlha )/sizeof( xlha[0] );

      // Loop over two internal PDF sets in Pythia8
      // and compare with their LHAPDF correspondents.
      for (int iFitIn = 3; iFitIn < 5; iFitIn++) {

        // Constructor for LHAPDF.
        if (iFitIn == 3) setName = "NNPDF31_nlo_as_0118_luxqed";
        if (iFitIn == 4) setName = "NNPDF31_nnlo_as_0118_luxqed";
        PDFPtr pdfs_nnpdf_lha =
          make_plugin<PDF>("libpythia8lhapdf6.so", "LHAPDF6");
        if (pdfs_nnpdf_lha == nullptr) return -1;
        pdfs_nnpdf_lha->init(idBeamIn, setName, 0, &logger);
        cout << "\n PDF set = " << setName << " \n" << endl;

        // Constructor for internal PDFs.
        LHAGrid1 pdfs_nnpdf(
          idBeamIn, setName + "_0000.dat", pdfPath, &logger);

        // Check quarks and gluons.
        cout << setprecision(6);
        for (int f = 0; f < 4; f++) {
          for (int iq = 0; iq < iqMax; iq++) {
            cout << "  " << xpdf[f] << ", Q2 = " << Q2[iq] << endl;
            cout << "   x \t     Pythia8\t   LHAPDF\t   diff(%) " << endl;
            for (int ix = 0; ix < 2; ix++) {
              double a = pdfs_nnpdf.xf( f, xlha[ix], Q2[iq]);
              double b = pdfs_nnpdf_lha->xf( f, xlha[ix], Q2[iq]);
              double diff = b != 0 ? 1e2 * abs((a-b)/b) :
                std::numeric_limits<double>::infinity();
              cout << scientific << xlha[ix] << " " << a << " " << b
                   << " " << diff << endl;
            }
          }
        }

        // Check photon.
        cout << "\n Now checking the photon PDF \n" << endl;
        for (int iq = 0; iq < iqMax; iq++) {
          cout << "  " << "x*gamma" << ", Q2 = " << Q2[iq] << endl;
          cout << "   x \t     Pythia8\t   LHAPDF\t   diff(%) " << endl;
          for (int ix = 0; ix < 2; ix++) {
            double a = pdfs_nnpdf.xf( 22, xlha[ix], Q2[iq]);
            double b = pdfs_nnpdf_lha->xf( 22, xlha[ix], Q2[iq]);
            double diff = b != 0 ? 1e2 * abs((a-b)/b) :
              std::numeric_limits<double>::infinity();
            cout << scientific << xlha[ix] << " " << a << " " << b
                 << " " << diff << endl;
          }
        }

        // Now check the timings for evolution.
        cout << "\n Checking timings " << endl;

        // Internal timing.
        clock_t tBegin = clock();
        for (int f = -4; f < 4; f++) {
          for (int iq = 0; iq < nq; iq++) {
            double qq2 = 2.0 * pow( 1e6 / 2.0, double(iq)/nq);
            for (int ix = 0; ix < nx; ix++) {
              double xx = 1e-6 * pow( 9e-1 / 1e-6, double(ix)/nx);
              pdfs_nnpdf.xf(f,xx,qq2);
            }
          }
        }
        clock_t tEnd = clock();
        double tUsed = double(tEnd - tBegin) / double(CLOCKS_PER_SEC);
        cout << " NNPDF internal timing = " << tUsed << endl;

        // External timing.
        tBegin = clock();
        for (int f = -4; f < 4; f++) {
          for (int iq = 0; iq < nq; iq++) {
            double qq2 = 2.0 * pow(1e6 / 2.0, double(iq)/nq);
            for (int ix = 0; ix < nx; ix++) {
              double xx = 1e-6 * pow( 9e-1 / 1e-6, double(ix)/nx);
              pdfs_nnpdf_lha->xf(f,xx,qq2);
            }
          }
        }
        tEnd = clock();
        tUsed = double(tEnd - tBegin) / double(CLOCKS_PER_SEC);
        cout << " NNPDF LHAPDF   timing = " << tUsed << endl;

      } // End loop over NNPDF internal sets

      // Done.
      cout << "\n Compared LHAPDF and internal Pythia8 results.\n" << endl;

      return 0;
    }