## main322

Back to index.

    // main322.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.

    // Keywords:
    //            Basic usage
    //            Biasing
    //            pT bias

    // This is a simple test program.
    // It illustrates methods to emphasize generation at high pT.

    #include "Pythia8/Pythia.h"

    using namespace Pythia8;

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

    int main() {

      // Different modes are illustrated for setting the pT ranges.
      // 1 - 3 are for hard jets only, 4 - 5 also for soft physics.
      // 1 : Hardcoded in the main program.
      // 2 : Using the Main:subrun keyword in a separate command file.
      // A third method instead biases selection continuously.
      // 3 : Bias high-pT selection by a pT^4 factor.
      // Matching also to low-pT processes is more complicated.
      // 4 : Matching between low- and high-pT. (No diffraction.)
      // 5: As 4, but bias high-pT selection by a pT^4 factor.
      int mode = 5;

      // Number of events to generate per bin.
      int nEvent = 10000;

      // One does not need complete events to study pThard spectrum only.
      bool completeEvents = false;

      // Optionally minimize output (almost) to final results.
      bool smallOutput = true;

      // Book histograms.
      int nRange = 100;
      double pTrange = (mode < 4) ? 1000. : 100.;
      Hist pTraw("pTHat distribution, unweighted", nRange, 0., pTrange);
      Hist pTnorm("pTHat distribution, weighted", nRange, 0., pTrange);
      Hist pTpow3("pTHat distribution, pT3*weighted", nRange, 0., pTrange);
      Hist pTpow5("pTHat distribution, pT5*weighted", nRange, 0., pTrange);
      Hist pTnormPart("pTHat distribution, weighted", nRange, 0., pTrange);
      Hist pTpow3Part("pTHat distribution, pT3*weighted", nRange, 0., pTrange);
      Hist pTpow5Part("pTHat distribution, pT5*weighted", nRange, 0., pTrange);

      // Generator.
      Pythia pythia;

      // Shorthand for some public members of pythia (also static ones).
      Settings& settings = pythia.settings;
      const Info& info = pythia.info;

      // Optionally limit output to minimal one.
      if (smallOutput) {
        pythia.readString("Init:showProcesses = off");
        pythia.readString("Init:showMultipartonInteractions = off");
        pythia.readString("Init:showChangedSettings = off");
        pythia.readString("Init:showChangedParticleData = off");
        pythia.readString("Next:numberCount = 1000000000");
        pythia.readString("Next:numberShowInfo = 0");
        pythia.readString("Next:numberShowProcess = 0");
        pythia.readString("Next:numberShowEvent = 0");
      }

      // Number of bins to use. In mode 2 read from main322.cmnd file.
      int nBin = 5;
      if (mode == 2) {
        pythia.readFile("main322.cmnd");
        nBin = pythia.mode("Main:numberOfSubruns");
      }
      else if (mode == 3) nBin = 1;
      else if (mode == 4) nBin = 4;
      else if (mode == 5) nBin = 2;

      // Mode 1: set up five pT bins - last one open-ended.
      double pTlimit[6] = {100., 150., 250., 400., 600., 0.};

      // Modes 4 & 5: set up pT bins for range [0, 100]. The lowest bin
      // is generated with soft processes, to regularize pT -> 0 blowup.
      // Warning: if pTlimitLow[1] is picked too low there will be a
      // visible discontinuity, since soft processes are generated with
      // dampening and "Sudakov" for pT -> 0, while hard processes are not.
      double pTlimitLow[6] = {0., 20., 40., 70., 100.};
      double pTlimitTwo[3] = {0., 20., 100.};

      // Loop over number of bins, i.e. number of subruns.
      for (int iBin = 0; iBin < nBin; ++iBin) {

        // Normally HardQCD, but in two cases nonDiffractive.
        // Need MPI on in nonDiffractive to get first interaction, but not else.
        if (mode > 3 && iBin == 0) {
          pythia.readString("HardQCD:all = off");
          pythia.readString("SoftQCD:nonDiffractive = on");
          if (!completeEvents) {
          pythia.readString("PartonLevel:all = on");
            pythia.readString("PartonLevel:ISR = off");
            pythia.readString("PartonLevel:FSR = off");
            pythia.readString("HadronLevel:all = off");
          }
        } else {
          pythia.readString("HardQCD:all = on");
          pythia.readString("SoftQCD:nonDiffractive = off");
          if (!completeEvents) pythia.readString("PartonLevel:all = off");
        }

        // Mode 1: hardcoded here. Use settings.parm for non-string input.
        if (mode == 1) {
          settings.parm("PhaseSpace:pTHatMin", pTlimit[iBin]);
          settings.parm("PhaseSpace:pTHatMax", pTlimit[iBin + 1]);
        }

        // Mode 2: subruns stored in the main322.cmnd file.
        else if (mode == 2) pythia.readFile("main322.cmnd", iBin);

        // Mode 3: The whole range in one step, but pT-weighted.
        else if (mode == 3) {
          settings.parm("PhaseSpace:pTHatMin", pTlimit[0]);
          settings.parm("PhaseSpace:pTHatMax", 0.);
          pythia.readString("PhaseSpace:bias2Selection = on");
          pythia.readString("PhaseSpace:bias2SelectionPow = 4.");
          pythia.readString("PhaseSpace:bias2SelectionRef = 100.");
        }

        // Mode 4: hardcoded here. Use settings.parm for non-string input.
        else if (mode == 4) {
          settings.parm("PhaseSpace:pTHatMin", pTlimitLow[iBin]);
          settings.parm("PhaseSpace:pTHatMax", pTlimitLow[iBin + 1]);
        }

        // Mode 5: hardcoded here. Use settings.parm for non-string input.
        // Hard processes in one step, but pT-weighted.
        else if (mode == 5) {
          settings.parm("PhaseSpace:pTHatMin", pTlimitTwo[iBin]);
          settings.parm("PhaseSpace:pTHatMax", pTlimitTwo[iBin + 1]);
          if (iBin == 1) {
            pythia.readString("PhaseSpace:bias2Selection = on");
            pythia.readString("PhaseSpace:bias2SelectionPow = 4.");
            pythia.readString("PhaseSpace:bias2SelectionRef = 20.");
          }
        }

        // Initialize for LHC at 14 TeV.
        pythia.readString("Beams:eCM = 14000.");

        // If Pythia fails to initialize, exit with error.
        if (!pythia.init()) return 1;

        // Reset local histograms (that need to be rescaled before added).
        pTnormPart.null();
        pTpow3Part.null();
        pTpow5Part.null();

        // Begin event loop.
        for (int iEvent = 0; iEvent < nEvent; ++iEvent) {

          // Generate events. Skip if failure.
          if (!pythia.next()) continue;

          // Soft events have no upper pT limit. They therefore overlap
          // with hard events, and the overlap must be removed by hand.
          // No overlap for elastic/diffraction, which is only part of soft.
          double pTHat  = info.pTHat();
          if (mode > 3 && iBin == 0 && info.isNonDiffractive()
            && pTHat > pTlimitLow[1]) continue;

          // Fill hard scale of event.
          double weight = info.weight();
          pTraw.fill( pTHat );
          pTnormPart.fill( pTHat, weight);
          pTpow3Part.fill( pTHat, weight * pow3(pTHat) );
          pTpow5Part.fill( pTHat, weight * pow5(pTHat) );

        // End of event loop. Statistics.
        }
        if (!smallOutput) pythia.stat();

        // Normalize to cross section for each case, and add to sum.
        double sigmaNorm = (info.sigmaGen() / info.weightSum())
                         * (nRange / pTrange);
        pTnorm += sigmaNorm * pTnormPart;
        pTpow3 += sigmaNorm * pTpow3Part;
        pTpow5 += sigmaNorm * pTpow5Part;

      // End of pT-bin loop.
      }

      // Output histograms.
      cout << pTraw << pTnorm << pTpow3 << pTpow5;

      // Done.
      return 0;
    }