Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-05 08:46:57

0001 // HeavyIons.h is a part of the PYTHIA event generator.
0002 // Copyright (C) 2025 Torbjorn Sjostrand.
0003 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
0004 // Please respect the MCnet Guidelines, see GUIDELINES for details.
0005 
0006 // This file contains the definition of the HeavyIons class which
0007 // Provides Pythia with infrastructure to combine several nucleon
0008 // collisions into a single heavy ion collision event. This file also
0009 // includes the definition of the Angantyr class which implements the
0010 // default model for heavy ion collisions in Pythia.
0011 
0012 #ifndef Pythia8_HeavyIons_H
0013 #define Pythia8_HeavyIons_H
0014 
0015 #include "Pythia8/HIInfo.h"
0016 #include "Pythia8/PhysicsBase.h"
0017 
0018 namespace Pythia8 {
0019 
0020 // Forward declaration of the Pythia class.
0021 class Pythia;
0022 
0023 //==========================================================================
0024 
0025 // HeavyIons contains several standard Pythia objects to allow for
0026 // the combination of different kinds of nucleon-nucleon events into
0027 // a heavy ion collision event. The actual model for doing this must
0028 // be implemented in a subclass overriding the the virtual'init()'
0029 // and 'next()' functions.
0030 
0031 class HeavyIons : public PhysicsBase {
0032 
0033 public:
0034 
0035   // The constructor needs a reference to the main Pythia object to
0036   // which it will belong. A HeavyIons object cannot belong to more
0037   // than one main Pythia object.
0038   HeavyIons(Pythia& mainPythiaIn)
0039     : mainPythiaPtr(&mainPythiaIn), HIHooksPtr(0),
0040       pythia(vector<Pythia*>(1, &mainPythiaIn)) {
0041   }
0042 
0043   // Destructor.
0044   virtual ~HeavyIons() {}
0045 
0046   // Virtual function to be implemented in a subclass. This will be
0047   // called in the beginning of the Pythia::init function if the mode
0048   // HeavyIon:mode is set non zero. The return value should be true
0049   // if this object is able to handle the requested collision
0050   // type. If false Pythia::init will set HeavyIon:mode to zero but
0051   // will try to cope anyway.
0052   virtual bool init() = 0;
0053 
0054   // Virtual function to be implemented in a subclass. This will be
0055   // called in the beginning of the Pythia::next function if
0056   // HeavyIon:mode is set non zero. After the call, Pythia::next will
0057   // return immediately with the return value of this function.
0058   virtual bool next() = 0;
0059 
0060   // Static function to allow Pythia to duplicate some setting names
0061   // to be used for secondary Pythia objects.
0062   static void addSpecialSettings(Settings& settings);
0063 
0064   // Return true if the beams in the Primary Pythia object contains
0065   // heavy ions.
0066   static bool isHeavyIon(Settings& settings);
0067 
0068   // Possibility to pass in pointer for special heavy ion user hooks.
0069   bool setHIUserHooksPtr(HIUserHooksPtr userHooksPtrIn) {
0070     HIHooksPtr = userHooksPtrIn; return true;
0071   }
0072 
0073   // Set beam kinematics.
0074   virtual bool setKinematics(double /*eCMIn*/) {
0075     loggerPtr->ERROR_MSG("method not implemented for this heavy ion model");
0076     return false; }
0077   virtual bool setKinematics(double /*eAIn*/, double /*eBIn*/) {
0078     loggerPtr->ERROR_MSG("method not implemented for this heavy ion model");
0079     return false; }
0080   virtual bool setKinematics(double, double, double, double, double, double) {
0081     loggerPtr->ERROR_MSG("method not implemented for this heavy ion model");
0082     return false; }
0083   virtual bool setKinematics(Vec4, Vec4) {
0084     loggerPtr->ERROR_MSG("method not implemented for this heavy ion model");
0085     return false; }
0086 
0087   // Set beam particles.
0088   virtual bool setBeamIDs(int /*idAIn*/, int /*idBIn*/ = 0) {
0089     loggerPtr->ERROR_MSG("method not implemented for this heavy ion model");
0090     return false; }
0091 
0092   // The HIInfo object contains information about the last generated heavy
0093   // ion event as well as overall statistics of the generated events.
0094   HIInfo hiInfo;
0095 
0096   // Print out statistics.
0097   virtual void stat();
0098 
0099 protected:
0100 
0101   // Update the cross section in the main Pythia Info object using
0102   // information in the hiInfo object.
0103   void updateInfo();
0104 
0105   // If subclasses has additional Pythia objects for generating
0106   // minimum bias nucleon collisions and the main Pythia object is
0107   // set up to generated a hard signal process, this function can be
0108   // used to clear all selected processes in a clone of the main
0109   // Pythia object.
0110   void clearProcessLevel(Pythia& pyt);
0111 
0112   // Duplicate setting on the form match: to settings on the form HImatch:
0113   static void setupSpecials(Settings& settings, string match);
0114 
0115   // Copy settings on the form HImatch: to the corresponding match:
0116   // in the given Pythia object.
0117   static void setupSpecials(Pythia& p, string match);
0118 
0119   // Save current beam configuration.
0120   int idProj, idTarg;
0121 
0122   // This is the pointer to the main Pythia object to which this
0123   // object is assigned.
0124   Pythia * mainPythiaPtr;
0125 
0126   // Object containing information on inclusive pp cross sections to
0127   // be used in Glauber calculations in subclasses.
0128   SigmaTotal sigTotNN;
0129 
0130   // Optional HIUserHooks object able to modify the behavior of the
0131   // HeavyIon model.
0132   HIUserHooksPtr HIHooksPtr;
0133 
0134   // The internal Pythia objects. Index zero will always correspond
0135   // to the mainPythiaPtr.
0136   vector<Pythia *> pythia;
0137 
0138   // The names associated with the secondary pythia objects.
0139   vector<string> pythiaNames;
0140 
0141   // The Info objects associated to the secondary Pythia objects.
0142   vector<Info*> info;
0143 
0144   // Helper class to gain access to the Info object in a Pythia
0145   // instance.
0146   struct InfoGrabber : public UserHooks {
0147 
0148     // Only one function: return the info object.
0149     Info* getInfo() {
0150       return infoPtr;
0151     }
0152 
0153   };
0154 
0155 };
0156 
0157 //==========================================================================
0158 
0159 // The default HeavyIon model in Pythia.
0160 
0161 class Angantyr : public HeavyIons {
0162 
0163 public:
0164 
0165   // Enumerate the different internal Pythia objects.
0166   enum PythiaObject {
0167     HADRON = 0,   // For hadronization only.
0168     MBIAS = 1,    // Minimum Bias processed.
0169     SASD = 2,     // Single diffractive as one side of non-diffractive.
0170     SIGPP = 3,    // Optional object for signal processes (pp).
0171     SIGPN = 4,    // Optional object for signal processes (pn).
0172     SIGNP = 5,    // Optional object for signal processes (np).
0173     SIGNN = 6,    // Optional object for signal processes (nn).
0174     ALL = 7       // Indicates all objects.
0175   };
0176 
0177 public:
0178 
0179   // The constructor needs a reference to the main Pythia object to
0180   // which it will belong. A Angantyr object cannot belong to more
0181   // than one main Pythia object.
0182   Angantyr(Pythia& mainPythiaIn);
0183 
0184   virtual ~Angantyr();
0185 
0186   // Initialize Angantyr.
0187   virtual bool init() override;
0188 
0189   // Produce a collision involving heavy ions.
0190   virtual bool next() override;
0191 
0192   // Set UserHooks for specific (or ALL) internal Pythia objects.
0193   bool setUserHooksPtr(PythiaObject sel, UserHooksPtr userHooksPtrIn);
0194 
0195   // Set beam kinematics.
0196   bool setKinematicsCM();
0197   bool setKinematics(double eCMIn) override;
0198   bool setKinematics(double eAIn, double eBIn) override;
0199   bool setKinematics(double, double, double, double, double, double) override;
0200   bool setKinematics(Vec4, Vec4) override;
0201   bool setKinematics();
0202 
0203   // Set beam IDs.
0204   bool setBeamIDs(int idAIn, int idBIn = 0) override;
0205 
0206   // Make sure the correct information is available irrespective of frame type.
0207   void unifyFrames();
0208 
0209   // Print the Angantyr banner.
0210   void banner() const;
0211 
0212   // Subcollisions for the current event.
0213   const SubCollisionSet& subCollisions() const {
0214     return subColls; }
0215 
0216   // Get the underlying subcollision model.
0217   const SubCollisionModel& subCollisionModel() const {
0218     return *collPtr.get(); }
0219 
0220   SubCollisionModel* subCollPtr() {
0221     return collPtr.get();
0222   }
0223 
0224   // Get the underlying impact parameter generator.
0225   const ImpactParameterGenerator impactParameterGenerator() const {
0226     return *bGenPtr.get(); }
0227 
0228   // Projectile nucleus configuration for the current event.
0229   const Nucleus& projectile() const {
0230     return proj; }
0231 
0232   // Target nucleus configuration for the current event.
0233   const Nucleus& target() const {
0234     return targ; }
0235 
0236   // The underlying projectile nucleus model.
0237   const NucleusModel& projectileModel() const {
0238     return *projPtr.get(); }
0239 
0240   // The underlying target nucleus model.
0241   const NucleusModel& targetModel() const {
0242     return *targPtr.get(); }
0243 
0244   // Hadronic cross sections used by the subcollision model.
0245   const SigmaTotal sigmaNN() const {
0246     return sigTotNN; }
0247 
0248 protected:
0249 
0250   virtual void onInitInfoPtr() override {
0251     registerSubObject(sigTotNN); }
0252 
0253   // Figure out what beams the user want.
0254   void setBeamKinematics(int idA, int idB);
0255 
0256   // Initiaize a specific Pythia object and optionally run a number
0257   // of events to get a handle of the cross section.
0258   bool init(PythiaObject sel, string name, int n = 0);
0259 
0260   // Setup an EventInfo object from a Pythia instance.
0261   EventInfo mkEventInfo(Pythia &, Info &, const SubCollision * coll = 0);
0262 
0263   // Generate events from the internal Pythia oblects;
0264   EventInfo getSignal(const SubCollision& coll);
0265   EventInfo getND() { return getMBIAS(0, 101); }
0266   EventInfo getND(const SubCollision& coll) { return getMBIAS(&coll, 101); }
0267   EventInfo getEl(const SubCollision& coll) { return getMBIAS(&coll, 102); }
0268   EventInfo getSDP(const SubCollision& coll) { return getMBIAS(&coll, 103); }
0269   EventInfo getSDT(const SubCollision& coll) { return getMBIAS(&coll, 104); }
0270   EventInfo getDD(const SubCollision& coll) { return getMBIAS(&coll, 105); }
0271   EventInfo getCD(const SubCollision& coll) { return getMBIAS(&coll, 106); }
0272   EventInfo getSDabsP(const SubCollision& coll)
0273     { return getSASD(&coll, 103); }
0274   EventInfo getSDabsT(const SubCollision& coll)
0275     { return getSASD(&coll, 104); }
0276   EventInfo getMBIAS(const SubCollision * coll, int procid);
0277   EventInfo getSASD(const SubCollision * coll, int procid);
0278 
0279   bool genAbs(SubCollisionSet& subCollsIn, list<EventInfo>& subEventsIn);
0280   void addSASD(const SubCollisionSet& subCollsIn);
0281   bool addDD(const SubCollisionSet& subCollsIn, list<EventInfo>& subEventsIn);
0282   bool addSD(const SubCollisionSet& subCollsIn, list<EventInfo>& subEventsIn);
0283   void addSDsecond(const SubCollisionSet& subCollsIn);
0284   bool addCD(const SubCollisionSet& subCollsIn, list<EventInfo>& subEventsIn);
0285   void addCDsecond(const SubCollisionSet& subCollsIn);
0286   bool addEL(const SubCollisionSet& subCollsIn, list<EventInfo>& subEventsIn);
0287   void addELsecond(const SubCollisionSet& subCollsIn);
0288 
0289   void resetEvent();
0290   bool buildEvent(list<EventInfo>& subEventsIn);
0291 
0292   bool setupFullCollision(EventInfo& ei, const SubCollision& coll,
0293     Nucleon::Status projStatus, Nucleon::Status targStatus);
0294   bool isRemnant(const EventInfo& ei, int i, int past = 1 ) const {
0295     int statNow = ei.event[i].status()*past;
0296     if ( statNow == 63 ) return true;
0297     if ( statNow > 70 && statNow < 80 )
0298       return isRemnant(ei, ei.event[i].mother1(), -1);
0299     return false;
0300   }
0301   bool fixIsoSpin(EventInfo& ei);
0302   EventInfo& shiftEvent(EventInfo& ei);
0303   static int getBeam(Event& ev, int i);
0304 
0305   // Generate a single diffractive
0306   bool nextSASD(int proc);
0307 
0308   // Add a diffractive event to an exsisting one. Optionally connect
0309   // the colours of the added event to the original.
0310   bool addNucleonExcitation(EventInfo& orig, EventInfo& add,
0311                             bool colConnect = false);
0312 
0313   // Find the recoilers in the current event to conserve energy and
0314   // momentum in addNucleonExcitation.
0315   vector<int> findRecoilers(const Event& e, bool tside, int beam, int end,
0316                             const Vec4& pdiff, const Vec4& pbeam);
0317 
0318   // Add a sub-event to the final event record.
0319   void addSubEvent(Event& evnt, Event& sub);
0320   static void addJunctions(Event& evnt, Event& sub, int coloff);
0321 
0322   // Add a nucleus remnant to the given event. Possibly introducing
0323   // a new particle type.
0324   bool addNucleusRemnants();
0325 
0326 public:
0327 
0328   // Helper function to construct two transformations that would give
0329   // the vectors p1 and p2 the total four momentum of p1p + p2p.
0330   static bool
0331   getTransforms(Vec4 p1, Vec4 p2, const Vec4& p1p,
0332                 pair<RotBstMatrix,RotBstMatrix>& R12);
0333   static double mT2(const Vec4& p) { return p.pPos()*p.pNeg(); }
0334   static double mT(const Vec4& p) { return sqrt(max(mT2(p), 0.0)); }
0335 
0336 private:
0337 
0338   // Private UserHooks class to select a specific process.
0339   struct ProcessSelectorHook: public UserHooks {
0340 
0341     ProcessSelectorHook(): proc(0), b(-1.0) {}
0342 
0343     // Yes we can veto event after process-level selection.
0344     virtual bool canVetoProcessLevel() {
0345       return true;
0346     }
0347 
0348     // Veto any unwanted process.
0349     virtual bool doVetoProcessLevel(Event&) {
0350       return proc > 0 && infoPtr->code() != proc;
0351     }
0352 
0353     // Can set the overall impact parameter for the MPI treatment.
0354     virtual bool canSetImpactParameter() const {
0355       return b >= 0.0;
0356     }
0357 
0358     // Set the overall impact parameter for the MPI treatment.
0359     virtual double doSetImpactParameter() {
0360       return b;
0361     }
0362 
0363     // The wanted process;
0364     int proc;
0365 
0366     // The selected b-value.
0367     double b;
0368 
0369   };
0370 
0371   // Holder class to temporarily select a specific process
0372   struct HoldProcess {
0373 
0374     // Set the given process for the given hook object.
0375     HoldProcess(shared_ptr<ProcessSelectorHook> hook, int proc,
0376       double b = -1.0) : saveHook(hook), saveProc(hook->proc), saveB(hook->b) {
0377       hook->proc = proc;
0378       hook->b = b;
0379     }
0380 
0381     // Reset the process of the hook object given in the constructor.
0382     ~HoldProcess() {
0383       if ( saveHook ) {
0384         saveHook->proc = saveProc;
0385         saveHook->b = saveB;
0386       }
0387     }
0388 
0389     // The hook object.
0390     shared_ptr<ProcessSelectorHook> saveHook;
0391 
0392     // The previous process of the hook object.
0393     int saveProc;
0394 
0395     // The previous b-value of the hook object.
0396     double saveB;
0397 
0398   };
0399 
0400   // The process selector for standard minimum bias processes.
0401   shared_ptr<ProcessSelectorHook> selectMB;
0402 
0403   // The process selector for the SASD object.
0404   shared_ptr<ProcessSelectorHook> selectSASD;
0405 
0406 private:
0407 
0408   static const int MAXTRY = 999;
0409   static const int MAXEVSAVE = 999;
0410 
0411   // Flag set if there is a specific signal process specified beyond
0412   // minimum bias.
0413   bool hasSignal;
0414 
0415   // Whether to do hadronization and hadron level effects.
0416   bool doHadronLevel;
0417 
0418   // Flag to determine whether to do single diffractive test.
0419   bool doSDTest;
0420 
0421   // Flag to determine whether to do only Glauber modelling.
0422   bool glauberOnly;
0423 
0424   // All subcollisions in current collision.
0425   SubCollisionSet subColls;
0426 
0427   // The underlying SubCollisionModel for generating nucleon-nucleon
0428   // subcollisions.
0429   shared_ptr<SubCollisionModel> collPtr;
0430 
0431   // The impact parameter generator.
0432   shared_ptr<ImpactParameterGenerator> bGenPtr;
0433 
0434   // The projectile and target nuclei in the current collision.
0435   Nucleus proj;
0436   Nucleus targ;
0437 
0438   // The underlying nucleus model for generating nuclons inside the
0439   // projectile and target nucleus.
0440   shared_ptr<NucleusModel> projPtr;
0441   shared_ptr<NucleusModel> targPtr;
0442 
0443   // Flag to indicate whether variable energy is enabled.
0444   bool doVarECM;
0445 
0446   // Different choices in choosing recoilers when adding
0447   // diffractively excited nucleon.
0448   int recoilerMode;
0449 
0450   // Different choices for handling impact parameters.
0451   int bMode;
0452 
0453   // Critical internal error, abort the event.
0454   bool doAbort;
0455 
0456 };
0457 
0458 //==========================================================================
0459 
0460 } // end namespace Pythia8
0461 
0462 #endif // Pythia8_HeavyIons_H