Advanced Usage

On this page we collect information on a number of classes that the normal user would not encounter. There are cases where the information is essential, however, for instance to implement your own showers.

The subsystems

One aspect that complicates administration is that an event can contain several subsystems, each consisting of one MPI and its associated ISR and FSR. To first approximation these systems are assumed to evolve independently, but to second they are connected by the interleaved evolution, and potentially by rescattering effects. The partons of a given subsystem therefore do not have to be stored consecutively.

The PartonSystems class is primarily used to keep track of the current positions of all partons belonging to each system, represented by the index iPos for a parton stored in the event-record slot event[iPos]. With "all" we mean the currently defined two incoming partons, or none for a resonance decay, and the current set of outgoing partons, but with all ISR and FSR intermediate-state partons omitted. That is, it stores all partons that could be subject to some action in the next step of the combined MPI/ISR/FSR/BR description. As a special case, an outgoing parton is stored even if it undergoes a rescattering, and thus no longer belongs to the final state proper.

The partonSystems instance of PartonSystems class is a public member of the Pythia top-level class, but is also available as a pointer partonSystemsPtr in various PartonLevel classes, e.g. inside the current instances of the TimeShower and SpaceShower classes.

A number of PartonSystems methods can be used to set or get information on the subsystems:

New systems are created from the hard process and by the MPI, not from any of the other components. Both FSR and ISR modify the position of partons, however. Since an FSR or ISR branching typically implies a new state with one more parton than before, an outgoing parton must be added to the system. Furthermore, in a branching, several existing partons may also be moved to new slots, including the incoming beam ones. In a FSR 1 → 2 branching it is irrelevant which parton position you let overwrite the existing slot and which is added to the end of the system.

The system information must be kept up-to-date. Both the MPI, ISR, FSR and BR descriptions make extensive use of the existing information. As an example, the introduction of primordial kT in the beam remnants will fail if the information on which final-state partons belong to which system is out-of-date. The introduction of rescattering as part of the MPI framework adds further complications, where an outgoing parton of one subsystem may be the incoming one of another system. This part of the code is still under development.

Currently the system information is kept throughout the continued history of the event. Specifically, resonance decays create new systems, appended to the existing ones. This could be useful during the hadronization stage, to collect the partons that belong to a resonance with preserved mass when a small string collapses to one particle, but is not yet used for that.

The beams

The different subsystems are tied together by them sharing the same initial beam particles, and thereby being restricted by energy-momentum and flavour conservation issues. The information stored in the two beam particles, here called beamA and beamB, is therefore as crucial to keep correct as the above subsystem list.

Both beam objects are of the BeamParticle class. Each such object contains a vector with the partons extracted from it. The number of such partons, beamX.size() (X = A or B), of course is the same as the above number of subsystems in the event record. (The two diverge at the BR step, where further beam remnants are added to the beams without corresponding to new subsystems.) The individual partons are accessed by an overloaded indexing operator to a vector of ResolvedParton objects. The iPos() property corresponds to the iPos one above, i.e. providing the position in the main event record of a parton. In particular, beamA[iSys].iPos() = partonSystemsPtr->getInA(iSys) and beamB[iSys].iPos() = partonSystemsPtr->getInB(iSys). Whereas thus the indices of the two incoming partons to a subsystem are stored in two places, the ones of the outgoing partons only appear in the system part of the PartonSystems class.

Just as the subsystems in PartonSystems must be updated, so must the information in the two BeamParticle's, e.g. with methodsbeamX[iSys].iPos( iPosIn) when an incoming parton is replaced by a new one in line iPosIn. Furthermore the new parton identity should be set by beamX[iSys].id( idIn) and the new x energy-momentum fraction by beamX[iSys].x( xIn). The three can be combined in one go by beamX[iSys].update( iPosIn, idIn, xIn).

To be specific, it is assumed that, at each step, the two incoming partons are moving along the +-z axis and are massless. Since the event is constructed in the c.m. frame of the incoming beams this implies that x = 2 E / E_cm. If the x values are not defined accordingly or not kept up-to-date the BR treatment will not conserve energy-momentum.

In return, the BeamParticle objects give access to some useful methods. The beamX.xf( id, x, Q2) returns the standard PDF weight x f_id(x, Q^2). More interestingly, beamX.xfISR( iSys, id, x, Q2) returns the modified weight required when several subsystems have to share the energy and flavours. Thus iSys is added as an extra argument, and the momentum already assigned to the other subsystems is not available for evolution, i.e. the maximal x is correspondingly smaller than unity. Also flavour issues are handled in a similar spirit.

An additional complication is that a parton can be either valence or sea, and in the latter case the BR treatment also distinguishes companion quarks, i.e. quark-antiquark pairs that are assumed to come from the same original g → q qbar branching, whether perturbative or not. This can be queried either with the beamX[iSys].companion() method, for detailed information, or with the beamX[iSys].isValence(), beamX[iSys].isUnmatched() and beamX[iSys].isCompanion() methods for yes/no answers whether a parton is valence, unmatched sea or matched sea. This choice should affect the ISR evolution; e.g., a valence quark cannot be constructed back to come from a gluon.

To keep this info up-to-date, the beamX.pickValSeaComp() method should be called whenever a parton of a new flavour has been picked in the ISR backwards evolution, but not if the flavour has not been changed, since then one should not be allowed to switch back and forth between the same quark being considered as valence or as sea. Since the pickValSeaComp() method makes use of the current parton-density values, it should be preceded by a call to beamX.xfISR( iSys, id, x, Q2), where the values in the call are the now finally accepted ones for the newly-found mother. (Such a call is likely to have been made before, during the evolution, but is not likely to be the most recent one, i.e. still in memory, and therefore had better be redone.)