main426
Back to index.
// main426.cc is a part of the PYTHIA event generator.
// Copyright (C) 2025 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:
// Christian Bierlich
// Keywords:
// Heavy ions
// Glauber
// Npart
// Ncoll
// Fixed target
// p‑Ne
// Angantyr
// Total cross sections
// This test program is intended to showcase how initial state
// quantities from the heavy ion model Angantyr can be extracted.
// In the example, Neon is added as a target, Angantyr is run
// in fixed target mode, and cross section and Glauber quantities
// are extracted from the program, as well as calculated directly,
// to illustrate how the numbers are obtained.
#include "Pythia8/Pythia.h"
// You need to include this to get access to the HIInfo object for
// HeavyIons.
#include "Pythia8/HeavyIons.h"
using namespace Pythia8;
//==========================================================================
int main() {
Pythia pythia;
// We want to do fixed target, proton on neon. Since 20Ne is not
// a standard particle in Pythia, we add it to the database before
// setting the beam.
pythia.particleData.addParticle(1000100200, "20Ne", 6, 30, 0, 19.992440);
// Set up beams, use the newly added Ne.
pythia.readString("Beams:idA = 2212");
pythia.readString("Beams:idB = 1000100200");
// Run fixed target. When beam energy is lower than the mass per nucleon,
// it is assumed at rest.
pythia.readString("Beams:eA = 2500");
pythia.readString("Beams:eB = 0");
pythia.readString("Beams:frameType = 2");
// Parameters for cross section model.
pythia.readString("Angantyr:CollisionModel = 2");
pythia.readString("HeavyIon:SigFitDefPar = "
"21.06,27.80,0.15");
pythia.readString("HeavyIon:SigFitNGen = 10");
// If Pythia fails to initialize, exit with error.
if (!pythia.init()) return 1;
// Count the number of inelastic non-diffractive subcollisions.
// In proton-Ion, this is the same as wounded nucleons in the target.
// Compare to the ones output by built-in methods.
Hist nColl1("nColl1", 15, 0, 15);
Hist nColl2("nColl2", 15, 0, 15);
Hist nCollGlauber("nCollGlauber", 15, 0, 15);
// Number of participants in the target.
Hist nPart("nPart", 15, 0, 15);
// Sum of weights.
double sumW = 0;
// Loop over events.
for ( int iEvent = 0; iEvent < 100000; ++iEvent ) {
if ( !pythia.next() ) continue;
// Short-hand for the pointer to Heavy Ion Info.
auto hiPtr = pythia.info.hiInfo;
// Short-hand for the pointer to SubCollisions.
auto scPtr = hiPtr->subCollisionsPtr();
// nColl are all the subcollisions which ended up generating
// particles, i.e. did not fail due to non-conservation of
// momentum.
int nColl = 0;
// nCollGlauber are all subcollisions from the Glauber
// calculation. Not all of them will be realized.
int nCollG = 0;
// Count subcollisions by type. Inelastic non-diffractive are
// called "absorptive", code ABS.
for (auto sc : *scPtr) {
if (sc.type == SubCollision::ABS) ++nCollG;
if (sc.type == SubCollision::ABS && !sc.failed) ++nColl;
}
// The event weight is needed to fill histograms.
const double weight = pythia.info.weight();
sumW += weight;
nColl1.fill(nColl, weight);
nColl2.fill(hiPtr->nCollND(), weight);
nCollGlauber.fill(nCollG, weight);
nPart.fill(hiPtr->nAbsTarg(), weight);
}
pythia.stat();
// Extract the incoherent, inelastic proton-ion cross sections,
// and print it, i.e. the cross section of everything that produces
// particles in the final state. It is the sum of all inelastic
// nucleon-nucleon channels.
double sigmaInel = 0.;
double sigmaInel2Err = 0.;
for (int i : {101, 103, 104, 105}) {
sigmaInel += pythia.info.sigmaGen(i);
sigmaInel2Err += pow2(pythia.info.sigmaErr(i));
}
// Convenient short-hands.
const string projName = pythia.particleData.name(pythia.event[1].id());
const string targName = pythia.particleData.name(pythia.event[2].id());
const double eCM = pythia.info.eCM();
cout << "\n=======Output from main426=====================" << endl;
cout << "Incoherent, inelastic cross section for:" << endl;
cout << projName << " on " << targName << " at sqrt(s_NN) = ";
cout << eCM << " GeV." << endl;
cout << "sigma = " << sigmaInel << " +/- " << sqrt(sigmaInel2Err) <<
" mb." << endl;
cout << "===============================================" << endl;
// Plot the histograms with matplotlib.
HistPlot hpl("plot426");
hpl.frame("fig426", "Glauber statistics "+projName+" on "+targName+
" $\\sqrt{s_{\\mathrm{NN}}}$ = "+to_string(eCM)+" GeV", "$N$", "$P(N)$" );
hpl.add(nColl1/sumW, "-,blue","Subcollisions from main426");
hpl.add(nColl2/sumW, "x,green","Subcollisions from hiInfo");
hpl.add(nCollGlauber/sumW, "-,red", "Subcollisions from main426, "
"including failed");
hpl.add(nPart/sumW, "*,orange", "Participants from hiInfo");
hpl.plot(0, 15, 1e-6, 1, true);
return 0;
}