## main443

Back to index.

    // main443.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:
    //            Thermal model

    // Authors:
    //            Torbjörn Sjostrand

    // Compare pT spectra and particle composition in thermal vs ordinary
    // hadronization models, and also ina "straw man" alternative ("mT2").
    // Note that the models are out-of-the-box, without any parameter tuning.

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

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

    int main() {

      // Number of events. Histograms in line printer mode or as pdf file.
      const int nEvent = 2000;
      const int nModel = 4;
      const bool histAsPDF = true;

      // Histogram multiplicities and pT spectra.
      Hist nCh[nModel], pTpi[nModel], pTK[nModel], pTp[nModel];
      for (int iModel = 0; iModel < nModel; ++iModel) {
        nCh[iModel].book("charged multiplicity", 100, 1., 401.);
        pTpi[iModel].book("pT for pi+-", 100, 0., 5.);
        pTK[iModel].book("pT for K+-", 100, 0., 5.);
        pTp[iModel].book("pT for p/pbar", 100, 0., 5.);
      }

      // Tabulate particle composition.
      string nameHad[18] = { "pi+-", "pi0", "K+-", "K0S,L", "eta,eta'", "rho+-",
        "rho0,omega", "K*+-0", "phi0", "p(bar)", "n(bar)", "Lambda(bar)",
        "Sigma(bar)", "Xi(bar)", "Delta(bar)", "Sigma*(bar)", "Xi*(bar)",
        "Omega(bar)"};
      int rates[nModel][18] = {{0}};

      // Loop over normal and thermal generation.
      for (int iModel = 0; iModel < nModel; ++iModel) {

        // Generator. Common process selection. Reduce printout. pi0 stable.
        Pythia pythia;
        pythia.readString("Beams:eCM = 8000.");
        pythia.readString("SoftQCD:nonDiffractive = on");
        pythia.readString("Next:numberShowInfo = 0");
        pythia.readString("Next:numberShowProcess = 0");
        pythia.readString("Next:numberShowEvent = 0");
        pythia.readString("111:mayDecay = off");

        // Model-specific setup. Initialization.
        if (iModel == 1) pythia.readString("Fragmentation:model = 1");
        if (iModel == 2) pythia.readString("StringPT:widthPreStrange = 1.5");
        if (iModel == 3) pythia.readString("StringPT:widthPreQQ0 = 1.5");

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

        // Event shorthand.
        Event& event = pythia.event;

        // Begin event loop. Generate event. Skip if error.
        for (int iEvent = 0; iEvent < nEvent; ++iEvent) {
          if (!pythia.next()) continue;

          // Find charged multiplicity and fill histograms.
          int nCharged = 0;
          for (int i = 0; i < event.size(); ++i)
            if (event[i].isFinal() && event[i].isCharged()) ++nCharged;
          nCh[iModel].fill( nCharged );

          // Find pT spectra of some hadron species.
          for (int i = 0; i < event.size(); ++i) if (event[i].isFinal()) {
            int idAbs = event[i].idAbs();
            double pT = event[i].pT();
            if (idAbs ==  211) pTpi[iModel].fill( pT);
            if (idAbs ==  321) pTK[iModel].fill( pT);
            if (idAbs == 2212) pTp[iModel].fill( pT);
          }

          // Tabulate hadron composition, including unstable intermediaries,
          // but excluding charm and bottom.
          for (int i = 0; i < event.size(); ++i) {
            int idAbs = event[i].idAbs();
            if      (idAbs == 211) ++rates[iModel][0];
            else if (idAbs == 111) ++rates[iModel][1];
            else if (idAbs == 321) ++rates[iModel][2];
            else if (idAbs == 130 || idAbs == 310) ++rates[iModel][3];
            else if (idAbs == 221 || idAbs == 331) ++rates[iModel][4];
            else if (idAbs == 213) ++rates[iModel][5];
            else if (idAbs == 113 || idAbs == 223) ++rates[iModel][6];
            else if (idAbs == 313 || idAbs == 323) ++rates[iModel][7];
            else if (idAbs == 333) ++rates[iModel][8];
            else if (idAbs == 2212) ++rates[iModel][9];
            else if (idAbs == 2112) ++rates[iModel][10];
            else if (idAbs == 3122) ++rates[iModel][11];
            else if (idAbs == 3112 || idAbs == 3212 || idAbs == 3222)
              ++rates[iModel][12];
            else if (idAbs == 3312 || idAbs == 3322) ++rates[iModel][13];
            else if (idAbs == 1114 || idAbs == 2114 || idAbs == 2214
              || idAbs == 2224) ++rates[iModel][14];
            else if (idAbs == 3114 || idAbs == 3214 || idAbs == 3224)
              ++rates[iModel][15];
            else if (idAbs == 3314 || idAbs == 3324) ++rates[iModel][16];
            else if (idAbs == 3334) ++rates[iModel][17];
         }

        // End of event loop. Statistics. Normalize histograms.
        }
        pythia.stat();
        nCh[iModel]  *= 0.5 / double(nEvent);
        pTpi[iModel] *= 20. / double(nEvent);
        pTK[iModel]  *= 20. / double(nEvent);
        pTp[iModel]  *= 20. / double(nEvent);

      // End of model loop.
      }

      // Print historams.
      if (!histAsPDF) {
        for (int iModel = 0; iModel < nModel; ++iModel) cout << nCh[iModel];
        for (int iModel = 0; iModel < nModel; ++iModel) cout << pTpi[iModel];
        for (int iModel = 0; iModel < nModel; ++iModel) cout << pTK[iModel];
        for (int iModel = 0; iModel < nModel; ++iModel) cout << pTp[iModel];

      // Alternatively plot histograms.
      } else {
        HistPlot hpl("plot443");
        hpl.frame("fig443", "charged multiplicity",
          "$n_{\\mathrm{charged}}$", "Probability", 8.0, 5.4);
        hpl.add( nCh[0], "-,black",  "default");
        hpl.add( nCh[2], "-,blue",   "enh-pTstrange");
        hpl.add( nCh[3], "-,cyan",   "enh-pTqq0");
        hpl.add( nCh[1], "-,red",    "thermal");
        hpl.plot();
        hpl.frame("", "$\\pi^{\\pm}$ transverse momentum spectrum",
          "$p_{\\perp}$", "$\\mathrm{d}n/\\mathrm{d}p_{\\perp}$", 8.0, 5.4);
        hpl.add( pTpi[0], "-,black", "default");
        hpl.add( pTpi[2], "-,blue",  "enh-pTstrange");
        hpl.add( pTpi[3], "-,cyan",  "enh-pTqq0");
        hpl.add( pTpi[1], "-,red",   "thermal");
        hpl.plot();
        hpl.frame("", "K$^{\\pm}$ transverse momentum spectrum",
          "$p_{\\perp}$", "$\\mathrm{d}n/\\mathrm{d}p_{\\perp}$", 8.0, 5.4);
        hpl.add( pTK[0], "-,black",  "default");
        hpl.add( pTK[2], "-,blue",   "enh-pTstrange");
        hpl.add( pTK[3], "-,cyan",   "enh-pTqq0");
        hpl.add( pTK[1], "-,red",    "thermal");
        hpl.plot();
        hpl.frame("", "p,$\\overline{\\mathrm{p}}$ transverse momentum spectrum",
          "$p_{\\perp}$", "$\\mathrm{d}n/\\mathrm{d}p_{\\perp}$", 8.0, 5.4);
        hpl.add( pTp[0], "-,black",  "default");
        hpl.add( pTp[2], "-,blue",   "enh-pTstrange");
        hpl.add( pTp[3], "-,cyan",   "enh-pTqq0");
        hpl.add( pTp[1], "-,red",    "thermal");
        hpl.plot();
      }

      // Print table.
      double norm = 1. / double(nEvent);
      cout << "\n\n Particle composition per event, including unstable"
           << "\n    Particle     default     thermal    enh-strange  enh-qq0"
           << endl << fixed << setprecision(3);
      for (int i = 0; i < 18; ++i) {
        cout << setw(12) << nameHad[i];
        for (int iModel = 0; iModel < nModel; ++iModel)
          cout << setw(12) << norm * rates[iModel][i];
        cout << endl;
      }

      // Done.
      return 0;
    }