## Heavy Ion Collisions

PYTHIA includes a facility in which simulation of heavy ion collisions can be implemented through models which combine several nucleon-nucleon collisions into one heavy ion collision. One such model, called Angantyr, is provided with PYTHIA and is in part inspired by the old Fritiof program from the Lund group [And87] with recent improvements [Bie16a].

In the following documentation, there is a split between the general facility in which a heavy ion model can be implemented, and the concrete implementation of Angantyr which uses the facility to implement a model. In order to run Angantyr, several settings from the base facility must, however, be used, so it is not advisible simply to skip to that section.

The implementation of the heavy ion facility is split between two main classes and a number of helper classes. The main classes are:

The `HIUserHooks` class is provided to simplify the customization of a model implemented as a `HeavyIons` subclass. It can be used to eg. change the `ImpactParameterGenerator` used, in a way similar to how the `UserHooks` and `MergingHooks` classes are used.

The `HeavyIons` class is very simple and flexible and basically only specifies that the `HeavyIons::init()` and `HeavyIons::next()` functions are overridden in a subclass. But the additional helper classes should be generic enough to be used by any model implemented.

### Heavy Ion beam selection

A heavy ion beam is selected in the same way as any other beams' beam parameters, ie. by specifying the PDG particle id for the two beams. A PDG id code for nuclei is on the form 100ZZZAAAI. To be able to specify a certain nucleus as a beam particle, the particle must be available in the particle data scheme, a number of nuclei are already added, including negative numbers for the corresponding anti-particle:

- 2H: `1000010020`
- 4He: `1000020040`
- 6Li: `1000030060`
- 12C: `1000060120`
- 16O: `1000080160`
- 63Cu: `1000290630`
- 84Kr: `1000360840`
- 129Xe: `1000541290`
- 197Au: `1000791970`
- 208Pb: `1000822080`

More can be added by the user, using the function `ParticleData::addParticle`, documented in the particle data scheme, but be mindful that a suitable model geometry must be available for the nucleus added, see the available nucleus models below. Angantyr supports beam switching if `Beams:allowIDAswitch` is turned on. In this case, `idA` is allowed to be any hadron, while `idB` is allowed to be a proton, nucleon or any ion.

### Top level flags

`mode` HeavyIon:mode (`default = 1`; `minimum = 1`; `maximum = 2`)
This is the master switch for heavy ions, and determines the mode of operation of the HeavyIon model.
`option` 1 : The heavy ion machinery will be used in case of ion beams.
`option` 2 : Even collisions without ions are treated using the heavy ion machinery. (Typically only used for debugging purposes.)

If `HeavyIon:mode` is on, the normal initialization in `Pythia::init()` is early on diverted to an object with the base class `HeavyIons` which may instantiate secondary `Pythia` objects needed to generate different types of nucleon-nucleon collisions that can be merged together into a full heavy ion event. This is all done in the virtual `HeavyIons::init()` function. Subsequent calls to `Pythia::next()` will then also be diverted to the virtual function `HeavyIons::next()` which will be responsible for building up the heavy ion collision. The final event will be available in the primary `Pythia` object.

`flag` HeavyIon:showInit (`default = on`)
Please note: this flag is not currently in use due to conflicts with the Parallelism framework, but is expected to be reintroduced in the future. Output detailed initialization information from the heavy ion model. Typically there will be several `Pythia` objects initialised in a heavy ion run, this flag can be used to reduce the amount of output. If off, only the output from initialisation of the primary `Pythia` object will be shown. The impact parameter between two colliding nuclei, is sampled by the code contained in `ImpactParameterGenerator`. The base class implements a Gaussian sampling, which means that the events produced will always be weighted. Other distributions can be implemented in subclasses.

`parm` HeavyIon:bWidth (`default = 0.0`; `minimum = 0.0`)
The width in fermi of the distribution by which the impact parameter is sampled. If zero, a suitable width will be guessed by the `ImpactParameterGenerator` itself.

`parm` HeavyIon:bWidthCut (`default = 3.0`; `minimum = 0.0`)
An additional upper cut for impact parameters, forcing it to always be smaller than `HeavyIon:bWidthCut` times `HeavyIon:bWidth`.

`flag` HeavyIon:forceUnitWeight (`default = off`)
Allows completely flat generation of impact parameter in within `HeavyIon:bWidthCut`, giving all events unit weight.

### Nucleus Models - the nuclear geometry

Several models and parametrizations exist to describe the distribution in the radial density of nucleons in a nucleus. The `NucleusModel` class is a base class for implementing such models. There are five ready-made models implemented already. When using Angantyr, the nuclear models can be selected using the following settings.

`mode` Angantyr:NucleusModelA (`default = 1`; `minimum = 1`; `maximum = 5`)

`mode` Angantyr:NucleusModelB (`default = 1`; `minimum = 1`; `maximum = 5`)
Select the model for nuclear geometry for beam A and B respectively. Models and associated parameters are documented below.
`option` 1 : GLISSANDO Woods-Saxon. This default model is suitable for large nuclei.
`option` 2 : Standard Woods-Saxon.
`option` 3 : Harmonic Oscillator Shell model.
`option` 4 : Gaussian model.
`option` 5 : Hulthen model.

For large nuclei, the Woods-Saxon potential is suitable. The `WoodsSaxonModel`, implements a standard Woods-Saxon distribution with parameters to be input by the user, and the `GLISSANDOModel`, implements the more advanced model from [Bro09,Ryb14]. For light nuclei (16O and lighter), several options are implemented. The `HulthenModel` implements the Hulthen potential suitable for deuterons, the `HOShellModel` a harmonic oscillator shell model density and `GaussianModel` a Gaussian radial distribution. Finally it is possible to read in externally generated nuclear configurations from a file, in the `ExternalNucleusModel`.

If a user wishes to specify own parameters for the `NucleusModel`s, parameters must be specified for beam A and B separately, using prefix `HeavyIonA:` or `HeavyIonB:` as specified below.

#### Standard Woods-Saxon

For sufficiently large nuclei, the Woods-Saxon distribution:
rho(r) = rho_0/(1 + exp((r-R)/a))
is a suitable choice. The model has two parameters, which can be set by:

`parm` HeavyIonA:WSR (`default = 0.0`; `minimum = 0.0`)

`parm` HeavyIonB:WSR (`default = 0.0`; `minimum = 0.0`)
The radius of a nucleon in units of fermi in the default Woods-Saxon model for nucleon distributions. If zero, the size is given by the formulae [Ryb14], based on the number of nucleons in the nuclei and whether a hard core is used or not.

`parm` HeavyIonA:WSa (`default = 0.0`; `minimum = 0.0`)

`parm` HeavyIonB:WSa (`default = 0.0`; `minimum = 0.0`)
The skin width of a nucleus in units of fermi in the default Woods-Saxon model for nucleon distributions. If zero, the size is given by the numbers in [Ryb14], based on the number of nucleons in the nucleus and whether a hard core is used or not.

#### GLISSANDO Woods-Saxon

In [Ryb14] it was shown that for a=0.54 fm, and sufficiently heavy nuclei, the Woods-Saxon radius parameter is well approximated by:
R = (1.1 A^(1/3) - 0.656 A^(-1/3)).
These values are used for all nuclei when this model is selected.

#### Harmonic Oscillator Shell

For lighter nuclei, a two-parameter Harmonic Oscillator Shell model is implemented. Here:
rho(r) = 4/(pi^(3/2)C^3)(1 + (A - 4)/6 * (r/C)^2)exp(-r^2/C^2) with:
C = (5/2 - 4/A)^(-1) (< r^2>_A - <r^2>_p).
The two model paramters are < r^2>_A (nuclear charge radius squared) and <r^2>_p (proton charge radius squared). These can be set, in units of fm^2.

`parm` HeavyIonA:HONuclearChargeRadius (`default = 0.0`; `minimum = 0.0`)

`parm` HeavyIonB:HONuclearChargeRadius (`default = 0.0`; `minimum = 0.0`)
If nothing is selected, the program includes the following reasonable defaults for the following often used nuclei, using units of fm^2 throughout:

Nucleus | w. hard core | w./o. hard core
--- | --- | ---
4He | 2.45 | 2.81
6Li | 6.4 | 6.7
7Be | 6.69 | 7.00
8Li | 5.1 | 5.42
9Be | 6.0 | 6.35
10B | 5.5 | 5.89
11B | 5.36 | 5.79
12C | 5.66 | 6.10
13C | 5.6 | 6.06
14N | 6.08 | 6.54
15N | 6.32 | 6.79
16N | 6.81 | 7.29

Note that you may need to add the nucleus as a particle as well.

`parm` HeavyIonA:HOProtonChargeRadius (`default = 0.7714`; `minimum = 0.0`)

`parm` HeavyIonB:HOProtonChargeRadius (`default = 0.7714`; `minimum = 0.0`)
The proton charge radius squared. Units of fm^2.

#### Gaussian model

The Gaussian model parametrizes the nuclear radial density as a Gaussian distribution. While this may not be a fully adequate physics based model, it provides a starting point for parametrization of some light nuclei. The model has a single parameter, the with of the distribution, intepreted as a nuclear charge radius.

`parm` HeavyIonA:GaussianChargeRadius (`default = 7.7`; `minimum = 0.0`)

`parm` HeavyIonB:GaussianChargeRadius (`default = 7.7`; `minimum = 0.0`)
The charge radius of the Gaussian parametrization. Units of fm. The default value gives a reasonable description of O16.

#### Hulthén model

The Hulthén distribution [Hul42] is given by:
rho(r) = rho_0(exp(-a r) - exp(-b r))
where b term regulates the a term at small distances so that rho(0) = 0. The a term can be written as sqrt(m E), where m is the mass of the nucleon and E is the binding energy. The b parameter can be written in terms of a using the triplet effective range parameter as roughly 3a [Adl75].

`parm` HeavyIonA:HulthenA (`default = 0.4`; `minimum = 0.0`)

`parm` HeavyIonB:HulthenA (`default = 0.4`; `minimum = 0.0`)
Hulthen a-parameter, units of fm^-1. Note that b > a > 0 always.

`parm` HeavyIonA:HulthenB (`default = 1.2`; `minimum = 0.0`)

`parm` HeavyIonB:HulthenB (`default = 1.2`; `minimum = 0.0`)
Hulthen b-parameter, units of fm^-1. Note that b > a > 0 always.

#### Externally generated configuration

For certain purposes it might be appropriate for a user to read in nuclear configurations from a file stored on disk, produced by another program. The `ExternalNucleusModel` acts as an interface for this operation. The file must be of the following format:

- One line corresponds to one nucleus.
- All nucleons in the nucleus must have an x, y and z coordinate, in that order, in the nucleus COM system, in units of fm.
- A line will thus have 3 * A (where A is the mass number) entries, separated by a whitespace character.
- Any line containing the "#" character is treated as a comment, and thus skipped.

Isospin information cannot currently by added, and is assigned randomly.
When the configurations are read in, they will be shuffled randomly, in order to avoid collisions between identical configurations. When the list of configurations is exhausted, elements will be reshuffled again.
Note: All configurations in the given file will be read in when Pythia is initialized. If your file is very large, this will consume a large amount of memory, so this is typically only advised for a few thousand configurations, or at least not orders of magnitude more.

`word` HeavyIonA:externalNucleusFile

`word` HeavyIonB:externalNucleusFile
The name of the file to be read in. Must be accessible, no default provided.

`flag` HeavyIonA:externalShuffle (`default = on`)

`flag` HeavyIonB:externalShuffle (`default = on`)
Randomly shuffle configurations when read in, and when the list is exhausted. Turning shuffling off is allowed mostly for debug purposes.

#### Nucleon hard core: Common parameters

As an attempt to model multi-nucleon correlations inside nuclei, nucleons have a "hard core", which cannot overlap with other nucleons' hard cores, when nucleons are sampled. All models except for the Hulthen model (where the same behaviour is directly encoded into the density function) have the possibility for either a fixed-size hard core of a given width, or a Gaussian hard core, where the hard core radius is sampled from a Gaussian at the per-nucleon level. The hard core repulsion is switched on by default.

`flag` HeavyIonA:HardCore (`default = on`)

`flag` HeavyIonB:HardCore (`default = on`)
Assume that there is a minimum distance between nucleons defined by a hard core radius in `HeavyIon:HardCoreRadius`.

`parm` HeavyIonA:HardCoreRadius (`default = 0.9`; `minimum = 0.0`)

`parm` HeavyIonB:HardCoreRadius (`default = 0.9`; `minimum = 0.0`)
The hard core radius in units of fm, defining the minimum distance between nucleons in a nucleus.

`flag` HeavyIonA:GaussHardCore (`default = off`)

`flag` HeavyIonB:GaussHardCore (`default = off`)
Option to use a Gaussian profile of the hard core instead of a sharp cut-off, inspired by [Bay95].

### Nucleons and subcollisions

The geometry models above, wil generate two lists of `Nucleon`s. Collisions between individual projectile and target nucleons are generated by `SubCollisionModel`s, outputting individual, potential nucleon-nucleon `SubCollision`s.

#### Nucleons

The `Nucleon` class represents a single nucleon in a nucleus. The class contains several methods for accessing information and modifying state, here only the ones deemed useful for a user are mentioned.

int Nucleon::id()
The nucleon particle id. Currently limited to protons and neutrons, ie. no hypernuclei possible.

const Vec4& Nucleon::nPos()
The nucleon position relative to the nucleus center.

const Vec4& Nucleon::bPos()
The nucleon absolute position in impact parameter space.

void Nucleon::bShift(const Vec4& bvec)
Shift the nucleon absolute position in impact parameter space.

Status Nucleon::status()
The nucleon status, meaning whether and how it is participating. It can take the following values:

- `Nucleon::UNWOUNDED`: The nucleon is not participating.
- `Nucleon::ELASTIC`: The nucleon is elastically scattered.
- `Nucleon::DIFF`: The nucleon is diffractively wounded.
- `Nucleon::ABS`: The nucleon is absorptively wounded.

#### Subcollisions

The `SubCollision` class represents a potential nucleon-nucleon collision between a projectile and a target `Nucleon`. From a subcollision, pointers to projectile and target nucleons participating can be accessed:

Nucleon* SubCollision::proj
Nucleon* SubCollision::targ
Pointers to projectile and target nucleons are public members of the `SubCollision` class The impact parameter distance between nucleons participating in a given subcollision can also be accessed directly.

double SubCollision::b
double SubCollision::bp
The impact parameter distance between the two participating nuclei, respectively in units of fm and scaled like in Pythia to have unit average for non-diffractive collisions. Information about whether a given potential sub-collision was actually realized as a final state particle producing sub-collision, or if it failed is given as:

bool SubCollision::failed
Finally the type of subcollision can be accessed by a method:

CollisionType SubCollision::type()
The subcollision type, meaning how the two nucleons interacted. It can take the following values:

- `SubCollision::NONE`: Not a collision.
- `SubCollision::ELASTIC`: Elastic scattering.
- `SubCollision::SDEP`: Projectile is diffractively excited.
- `SubCollision::SDET`: Target is diffractively excited.
- `SubCollision::DDE`: Both are diffractively excited.
- `SubCollision::CDE`: Central diffraction.
- `SubCollision::ABS`: Absorptive (inelastic non-diffractive) interaction.

#### Subcollision models

Presently three `SubCollisionModel`s are available. The `BlackSubCollisionModel`, which is the simplest black disk model possible, the `NaiveSubCollisionModel` which on top of a black disk model, allows less central subcollisions to be diffractive or elastic, and a more elaborate treatment called `DoubleStrikman`, described below.

The main idea behind currently implemented `SubCollisionModel`s, is that parameters should be fitted from semi-inclusive cross sections. Thus, the code includes a fitting machinery, based on a simple genetic algorithm. Cross sections are taken form the standard Pythia total cross sections. Parameters for the models are therefore not set in the normal sense, but initial values for the fit are set instead, an example for the default model given below.

The default model for nucleon fluctuations has three parameters, the general fitting machinery in `SubCollisionModel` allows for up to eight parameters.

`pvec` HeavyIon:SigFitDefPar (`default = {}`)
These are the default values of the parameters of the `SubCollisionModel` in Angantyr. They will be used as starting point when fitting to the inclusive nucleon cross sections. If left empty, the values will be set to the model default.

`parm` HeavyIon:SigFitDefAvNDb (`default = 0.0`)
This is the average non-diffractive impact parameter assumed in the `SubCollisionModel` in Angantyr. It is something that comes out the cross section fitting procedure but can be specified here if the fitting procedure is omitted and the `HeavyIon:SigFitDefPar` parameters are used instead.

The fitting procedure in `SubCollisionModel` is a kind of genetic algorith where a population of parameter values are allowed to evolve for a number of generations. In the end the the parameter set in the final population which gives the best inclusive cross sections is picked. Eight different cross sections may be fitted to but it is possible to select only some of them:

`pvec` HeavyIon:SigFitErr (`default = {0.02,0.02,0.1,0.05,0.05,0.0,0.1,0.15}`; `minimum = 0.0`; `maximum = 1.0`)
The relative error assumed in the calculation of goodness of fit corresponding to the different cross sections fitted to. The cross sections are obtained from the `SigmaTotal` and are given as (in order) total, non-diffractive, double diffractive, wounded target, wounded projectile, central diffractive, and elastic cross sections, and in addition the elastic slope parameter. A relative error of zero for one of these cross sections means the corresponding cross section not be used in the fit.

`mode` HeavyIon:SigFitNInt (`default = 100000`; `minimum = 0`)
The number of integration points used for each parameter setting to calculate the cross sections.

`mode` HeavyIon:SigFitNPop (`default = 20`; `minimum = 1`)
The number individuals (parameter settings) in a population in each generation.

`mode` HeavyIon:SigFitNGen (`default = 20`; `minimum = 0`)
The number of generation used in the genetic algorithm. If set to zero, no fitting will be performed and the values in `HeavyIon:SigFitDefPar` will be used.

`parm` HeavyIon:SigFitFuzz (`default = 0.2`; `minimum = 0.0`; `maximum = 0.5`)
A parameter determining the probability that an individual parameter setting will evolves further away from the best parameter set in each generation.

`flag` HeavyIon:SigFitPrint (`default = on`)
Controls the output from the fitting procedure. If on, extensive information about the fitting will be printed.

### Obtaining event information

The `HIInfo` class contains information related to the generated heavy ion events. In a run, it can be obtained from the usual Info object, by calling `pythia.info.hiInfo()`, which returns a pointer to the current `HIInfo` object. The methods of this class are:

double HIInfo::b()
The impact parameter distance of the heavy ion event.

double HIInfo::phi()
The impact parameter angle.

double HIInfo::T()
The summed elastic amplitude for this event, from which cross sections at Glauber level are calculated.

double HIInfo::avNDb()
The average NN non-diffractive impact parameter to be used to communicate to Pythia's MPI machinery.

int HIInfo::nAttempts()
The number of attempted impact parameter points.

int HIInfo::nAccepted()
The number of produced events. Several methods exist to extract information from the Glauber calculation. Caution should be taken when using this information directly, under the assumption that obtained numbers correspond one-to-one to numbers obtained from another calculation, as performed e.g. by an experiment. Since they are all model dependent quantities, a direct comparison can often not be made.

A user is often better off by extracting the full set of subcollisions, and extracting the relevant information from that.

multiset<SubCollision>* HIInfo::subCollisionsPtr()
A (pointer to) a multiset containing all `SubCollision`s of the current event. Can be modified by the user.

void HIInfo::subCollisionsPtr(multiset<SubCollision> * sPtrIn)
Sets this event's subcollision. Starting point for a user who wishes to interface their own or an external Glauber calculation.

int HIInfo::nCollTot()
The total number of subcollisions in the current event.

int HIInfo::nCollND()
The number of non-diffractive subcollisions in the current event.

int HIInfo::nCollSDP()
The number of single diffractive projectile excitation subcollisions in the current event.

int HIInfo::nCollSDT()
The number of single diffractive target excitation subcollisions in the current event.

int HIInfo::nCollDD()
The number of double diffractive subcollisions in the current event.

int HIInfo::nCollCD()
The number of central diffractive subcollisions in the current event.

int HIInfo::nCollEL
The number of elastic subcollisions in the current event.

int HIInfo::nPartProj()
int HIInfo::nPartTarg()
The number of interacting projectile/target nucleons in the current event (number of participants).

int HIInfo::nAbsProj()
int HIInfo::nAbsTarg()
The number of absorptively interacting projectile/target nucleons in the current event (number of absorptive participants).

int HIInfo::nDiffProj()
int HIInfo::nDiffTarg()
The number of diffractively interacting projectile/target nucleons in the current event (number of diffractive participants).

int HIInfo::nElProj()
int HIInfo::nElTarg()
The number of elastically interacting projectile/target nucleons in the current event (number of elastic participants).

double HIInfo::glauberTot()
double HIInfo::glauberND()
double HIInfo::glauberINEL()
double HIInfo::glauberEL()
double HIInfo::glauberDiffT()
double HIInfo::glauberDiffP()
double HIInfo::glauberDDiff()
double HIInfo::glauberBSlope()
Various semi-inclusive cross sections obtained from the Glauber calculation (total, non-diffractive, total inelastic, elastic, diffractive excitation of the target and projectile or both, elastic b-slope, respectively). Note that these are in general not the same as the generated cross sections, since Angantyr does not generate elastic scatterings correctly. Also the error of these cross sections are available from functions of the form `HIInfo::glauberTotErr()`. The cross sections are given in millibarns and the slope in Gev-2. Note also that when using variable beam id and energy, the Glauber statistics are reset any time the beams change.

double HIInfo::weight()
The weight for this collision. Note that heavy ion weights are propagated to the normal weights system, and a call to `pythia.info.weight()` contains the heavy ion weight as well. Normally a user would have no reason to access this method directly.

double HIInfo::weightSum()
The sum of weights for all produced events up to this point. Note that heavy ion weights are propagated to the normal weights system, and a call to `pythia.info.weightSum()` contains the heavy ion weights as well. Normally a user would have no reason to access this method directly.

### Angantyr - the default heavy ion model

The default model in PYTHIA is called Angantyr and is inspired by the old Fritiof model [And86] with improvements described in [Bie16a]. The main idea is to stack parton level events, corresponding to individual nucleon-nucleon sub-collisions, on top of each other and hadronize them together.

Please note:

- Although it is possible to use Rope Hadronization in heavy ion collisions, these two modules have not yet been validated to work properly together. Also the parameters in the model have not been properly tuned, so the results from running must not be taken as definitive predictions.
- A similar warning should be made regarding the use of Colour Reconnection models. By default the colour reconnection takes place only inside individual nucleon-nucleon sub-collisions, and not in the nucleus-nucleus collision as a whole. To get reconnections also between sub-collisions, the settings described in [Lon23] should be used.

To determine which projectile nucleon interacts with which target nucleon, special care is taken to determine in which way the nucleons interact. In a standard Glauber calculations one typicaly only cares about if a sub-collision is inelastic or not, but in Angantyr this is divided up, so that each inelastic sub-collision can either be single-diffractive, double-diffractive or absorptive (ie. non-diffractive). To achieve this, Angantyr uses a model with fluctuating radii of the nucleons resulting in a fluctuating nucleon-nucleon cross section inspired by the model by Strikman et al. [Alv13], called `DoubleStrikman`. The model for this includes a number of parameters which should be fitted to reproduce inclusive nucleon-nucleon cross sections. To be consistent, the values used comes from PYTHIA's internal model of total cross sections, see above for further documentation of this routine.

`mode` Angantyr:CollisionModel (`default = 2`; `minimum = 0`; `maximum = 5`)
The Angantyr model has a couple of option for the `SubCollisionModel`.
`option` 0 : A simplified model with fixed nucleon radii.
`option` 1 : The `DoubleStrikman` model with fluctuating radii and cross sections.
`option` 2 : Fluctuating radii and cross sections but an alternate treatment of opacity (default).
`option` 3 : Black disks with no fluctuations, ie. no diffraction.
`option` 4 : Model with fluctuations where the projectile and target can have different parameters, relevant for hadron-nucleon collisions. Note that this option requires much longer initialization time than option 1. Our studies indicate that option 1 is sufficiently precise in most cases.
`option` 5 : As option 4, but different treatment of opacity.

`flag` Angantyr:GlauberOnly (`default = off`)
If switched on, the event generation will stop after `SubCollision`s has been determined, allowing the user to read out the nucleon configuration only.

After all possible nucleon-nucleon sub-collisions has been determined, they are ordered in increasing nucleon-nucleon impact parameter. This list is then gone through in order several time. First all absorptive sub-collisions are treated. One full nucleon-nucleon non-diffractive minimum bias event is generated for each possible absorptive sub-colision. These are also ordered in impact parameter. Note that one target nucleon can interact absorptively with several target nucleons, in a first round only those absorptive sub-collisions involving nucleons that have not already interacted absorptively are are assigned a non-diffractive event.

If PYTHIA is not set up to generate minimum bias events, one or more of the generated non-diffractive events will be replaced by events generated with the selected signal process, and the cross section reported will be modified accordingly.

In a second round only those potential absorptive sub-collisions are considered where one nucleon has already been assinged a full non-diffractive event. In the Angantyr model it is then assumed that the other nuclean will contribute to the final state as if it had just been diffractively excited. Therefore a corresponding single-diffractive event is generated, the elastically scattered beam particle is discarded and the rest is added to the previous non-diffractive event, shuffling a bit with the kinematics so that the total emergy and momentum is conserved.

To generate these single-diffraction events to emulate multiple absorptive sub-collisions a special `Pythia` object is used. To allow flexibility this object need not have exactly the same settings as the the one generating events for normal single-diffraction sub-collisions. To manipulate this `Pythia` object a special form of settings can be used. All settings available for `Diffraction`, `MultipartonInteractions`, `PDF`, `SigmaDiffractive` and `PDF` can be set separately for this `Pythia` object by prefixing their names with `HI`. As an example, setting `HISigmaDiffractive:PomFlux` and `HIPDF:PomSet` will set the `SigmaDiffractive:PomFlux` and `PDF:PomSet` options for this `Pythia` object.

`mode` Angantyr:SASDmode (`default = 4`; `minimum = 0`; `maximum = 4`)
Determines how to generate single-diffraction events as secondary absorptive (SASD) sub-collisions.
`option` 0 : Standard singel-diffraction events as speicfied by `HIDiffraction` settings above.
`option` 1 : Always use `HIPDF:PomSet = 11` and use the same initial `HIMultipartonInteractions:pT0Ref` as for non-diffractive events for the total nucleon-nucleon collision energy, independent of the mass of the diffractive system.
`option` 2 : (Experimental) As for option `1` but also rescale the pomeron proton non-diffractive cross section to match the pp non-diffractive one.
`option` 3 : (Experimental) As for option `1` but use the full nucleon-nucleon cross section for the non-diffractive nucleon-Pomeron in the multiple interaction machinery. Also rescale the Pomeron PDF with the log of the ratio of maximum and minimum Pomeron-nucleon collision energy.
`option` 4 : As for option `3` but no rescaling of the Pomeron PDF.

`mode` Angantyr:impactMode (`default = 2`; `minimum = 0`; `maximum = 2`)
Determines how to bias non-diffractive minimum-bias sub-collisions in PYTHIA to be appropriately central.
`option` 0 : If we have N primary sub-collisions and Na secondary sub-collisions, generate N+Na non-diffractive events and pick the N most central.
`option` 1 : Use `UserHooks` to force Pythia to produce events with a particular impact parameter for the N primary sub collisions according to the generated impact parameter in the `SubCollisionModel`.
`option` 2 : As for option `1` but also the secondary absorptive sub-collisions have their impact parameter set.

`parm` Angantyr:impactFudge (`default = 0.85`; `minimum = 0.0`; `maximum = 4.0`)
Multiplicative factor used to compensate for the fact that the `SubColllisionModel` in Angantyr may have a different impact parameter profile than what is assumed in the MPI overlap calculation in Pythia.

`mode` Angantyr:SDTries (`default = 1`; `minimum = 1`)
When adding single diffractive sub-collisions to other sub-collisions, there might not be enough energy for the diffractive mass. One option here is to say that the diffractive sub-event simply fails, but setting this larger than unity allows for regenerating the single diffractive sub-event a number of times to see if a small enough diffractive system is produced.

`mode` Angantyr:SDRecoil (`default = 1`; `minimum = 1`; `maximum = 2`)
Determines which particles in a primary sub-collision will take the recoil when adding single diffractive sub-collisions to other sub-collisions. The choice may be overridded by a user-defined `HIUserHooks::findRecoilers` function.
`option` 1 : Only elastically scattered nucleons and nucleon remnants will take recoil.
`option` 2 : All particles outside the added diffractive system's rapidity range are considered.

`flag` Angantyr:SDTest (`default = off`)
Used in conjunction with `HeavyIon:mode = 2` and proton beams to generate single diffractive events that would be used as secondary non-diffractive scatterings in the Angantyr heavy ion model for the given nucleon energies. Used for tuning special `HI`-prefixed parameters of the secondary absorptive sub-collisions.

`parm` Angantyr:SDTestB (`default = -1.0`)
In conjunction with `Angantyr:SDTest = on` and `Angantyr:impactMode = 2` only pick diffractive events with a particular impact parameter (as defined by the scaled value given in `Info::bMPI()`). If negative, the standard impact parameter distribution is used.

After all absorptive sub-collisions have been dealt with, the diffractive and elastic sub-collisions are dealt with in a similar way. In the end there will be a number of parton level events which are finally stacked together, and then hadronized. Finally nucleus remnants constructed from the non-interacting nucleans, are added to complete the full nucleaus-nucleus collision.

It is possible to initialize Angantyr to allow changing the beam energy on an event-by-event basis. This is done by setting `Beams:allowVariableEnergy = on`, then changing the energy using the `Pythia::setKinematics` methods. When initializing this way, the `SubCollisionModel` fitting procedure calculates the parameter values at several different energies, using interpolation to get values between these energy points. The following settings are used when variable energies are allowed.

`parm` HeavyIon:varECMMin (`default = 100`; `minimum = 10`)
The minimum allowed energy. Note that Angantyr is currently not designed to properly handle energies below around 100 GeV.

`parm` HeavyIon:varECMMax (`default = 0`)
The maximum allowed energy. If it is set to 0, then the largest possible value will be given by the CM energy at which Pythia is initialized.

`mode` HeavyIon:varECMSigFitNPts (`default = 5`; `minimum = 2`)
Number of eCM points where the `SubCollisionModel` are calculated. The points are logarithmically spaced.

`flag` HeavyIon:varECMStepwiseEvolve (`default = on`)
If on, at each evolution point, the algorithm will use the generated parameters from the previous point. If off, it start from the default parameter set given by `HeavyIon:SigFitDefPar` at each point.

`mode` HeavyIon:SigFitReuseInit (`default = 0`; `minimum = -2`; `maximum = 3`)
If set, the parameters calculated from the evolutionary algorithm can be saved/loaded to disk, for faster initialization in subsequent runs.
`option` 0 : Initialize from scratch every time.
`option` 1 : Initialize from scratch, then save configuration.
`option` 2 : Load configuration from file. If the file is not found, initialization fails.
`option` 3 : Load configuration from file if it exists, otherwise initialize from scratch and save the file.
`option` -1 : Initialize fit from `Init:reuseHeavyIonSigFit` if not empty. In any case write the fitted parameters to `Init:reuseHeavyIonSigFit`.
`option` -2 : Same as `-1` but also read/write the setting from/to the file `HeavyIon:SigFitInitFile`.

`word` HeavyIon:SigFitInitFile (`default = Angantyr.sigfit`)
The file where the sigfit configuration is stored.

`wvec` Init:reuseHeavyIonSigFit (`default = {}`)
This is the internal setting where the fitted parameters are stored for `HeavyIon:SigFitReuseInit < 0`.

`mode` HeavyIon:SasdMpiReuseInit (`default = 0`; `minimum = -2`; `maximum = 3`)
This setting is similar to `MultipartonInteractions:reuseInit`, but pertains to the SASD Pythia subobject used internally by Angantyr.
`option` 0 : current run is self-contained.
`option` 1 : MPI initialization is done as usual, but afterwards the results of this initialization are saved on file.
`option` 2 : initialization data is read in from a file, saved from a previous initialization, thereby saving time. If the file is not found, initialization fails.
`option` 3 : as option 2, but if the file is not found, it will be generated and saved after normal initialization.
`option` -1 : read initialization data from `Init:reuseSasdMpiInit` if not empty. In any case write the the data to `Init:reuseSasdMPI...` setting.
`option` -2 : Same as `-1` but also read/write the setting from/to the file `HeavyIon:SasdMpiInitFile`.

`word` HeavyIon:SasdMpiInitFile (`default = Angantyr.sasd.mpi`)
The file name used to store or read MPI initialization data for the SASD Pythia object. It is up to the user to pick a suitable name (including path if relevant) for the case at hand.

`wvec` Init:reuseSasdMPIiDiffSys0
This is where the fitted parameters are stored for non-diffractive processes.

`wvec` Init:reuseSasdMPIiDiffSys1
This is where the fitted parameters are stored for single diffractive (XB) processes.

`wvec` Init:reuseSasdMPIiDiffSys2
This is where the fitted parameters are stored for single diffractive (AX) processes.

`wvec` Init:reuseSasdMPIiDiffSys3
This is where the fitted parameters are stored for doubly diffractive (AXB) processes.