Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:08:25

0001 // HISubCollisionModel.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 ImpactParameterGenerator,
0007 // SubCollision, and SubCollisionModel classes, as well as a set of
0008 // subclasses of SubCollisionModel.
0009 //
0010 // ImpactParameterGenerator: distributes nuclei in impact parameter space.
0011 // SubCollision: a collision between a projectile and a target Nucleon.
0012 // SubCollisionModel: Models the collision probabilities of nucleons.
0013 // BlackSubCollisionModel: A very simple SubCollisionModel.
0014 // NaiveSubCollisionModel: A very simple SubCollisionModel.
0015 // DoubleStrikmanSubCollisionModel: A more advanced SubCollisionModel.
0016 
0017 #ifndef Pythia8_HISubCollisionModel_H
0018 #define Pythia8_HISubCollisionModel_H
0019 
0020 #include "Pythia8/Pythia.h"
0021 #include "Pythia8/HINucleusModel.h"
0022 
0023 namespace Pythia8 {
0024 
0025 //==========================================================================
0026 
0027 // SubCollision represents a possible collision between a projectile
0028 // and a target nucleon.
0029 
0030 class SubCollision {
0031 
0032 public:
0033 
0034   // This defines the type of a binary nucleon collison.
0035   enum CollisionType {
0036     NONE,       // This is not a collision.
0037     ELASTIC,    // This is an elastic scattering
0038     SDEP,       // The projectile is diffractively excited.
0039     SDET,       // The target is diffractively excited.
0040     DDE,        // Both projectile and target are diffractively excited.
0041     CDE,        // Both excited but with central diffraction.
0042     ABS         // This is an absorptive (non-diffractive) collision.
0043   };
0044 
0045   // Constructor with configuration.
0046   SubCollision(Nucleon & projIn, Nucleon & targIn,
0047                double bIn, double bpIn, CollisionType typeIn)
0048     : proj(&projIn), targ(&targIn), b(bIn), bp(bpIn), type(typeIn),
0049     failed(false) {}
0050 
0051   // Default constructor.
0052   SubCollision()
0053     : proj(0), targ(0), b(0.0), bp(0.0), type(NONE) {}
0054 
0055   // Used to order sub-collisions in a set.
0056   bool operator< (const SubCollision& s) const { return b < s.b; }
0057 
0058   // Return 0 if neither proj or target are neutrons, 1 if target is
0059   // neutron, 2 if projectile is neutron, and 3 if both are neutrons.
0060   int nucleons() const {return ( abs(targ->id()) == 2112? 1: 0 ) +
0061       ( abs(proj->id()) == 2112? 2: 0 );}
0062 
0063   // The projectile nucleon.
0064   Nucleon* proj;
0065 
0066   // The target nucleon.
0067   Nucleon* targ;
0068 
0069   // The impact parameter distance between the nucleons in femtometer.
0070   double b;
0071 
0072   // The impact parameter distance between the nucleons scaled like
0073   // in Pythia to have unit average for non-diffractive collisions.
0074   double bp;
0075 
0076   // The type of collision.
0077   CollisionType type;
0078 
0079   // Whether the subcollision failed, i.e. has a failed excitation.
0080   mutable bool failed;
0081 
0082 };
0083 
0084 //==========================================================================
0085 
0086 // The SubCollisionSet gives a set of subcollisions between two nuclei.
0087 
0088 class SubCollisionSet {
0089 
0090 public:
0091 
0092   // Default constructor.
0093   SubCollisionSet() = default;
0094 
0095   // Constructor with subcollisions.
0096   SubCollisionSet(multiset<SubCollision> subCollisionsIn, double TIn,
0097                   double T12In = 0.0, double T21In = 0.0, double T22In = 0.0)
0098     : subCollisionsSave(subCollisionsIn), TSave({TIn, T12In, T21In, T22In}) {}
0099 
0100   // Reset the subcollisions.
0101   bool empty() const { return subCollisionsSave.empty(); }
0102 
0103   // The full elastic amplitude, optionally returning altenate states
0104   // to gauge fluctuations.
0105   double T(unsigned i = 0) const { return TSave[i]; }
0106 
0107   // Iterators over the subcollisions.
0108   multiset<SubCollision>::const_iterator begin() const {
0109     return subCollisionsSave.begin(); }
0110   multiset<SubCollision>::const_iterator end() const {
0111     return subCollisionsSave.end(); }
0112 
0113 private:
0114 
0115   // Saved subcollisions.
0116   multiset<SubCollision> subCollisionsSave;
0117 
0118   // The full elastic amplitude together with alternate states gauging
0119   // fluctuations.
0120   vector<double> TSave = {};
0121 
0122 };
0123 
0124 //==========================================================================
0125 
0126 // The SubCollisionModel is is able to model the collision between two
0127 // nucleons to tell which type of collision has occurred. The model
0128 // may manipulate the corresponding state of the nucleons.
0129 
0130 class SubCollisionModel {
0131 
0132 public:
0133 
0134   // Internal class to report cross section estimates.
0135   struct SigEst {
0136     // The cross sections (tot, nd, dd, sdp, sdt, cd, el, bslope).
0137     vector<double> sig;
0138 
0139     // The estimated error (squared)
0140     vector<double> dsig2;
0141 
0142     // Which cross sections were actually fitted
0143     vector<bool> fsig;
0144 
0145     // The estimate of the average (and squared error) impact
0146     // parameter for inelastic non-diffractive collisions.
0147     double avNDb, davNDb2;
0148 
0149     // Constructor for zeros.
0150     SigEst(): sig(8, 0.0), dsig2(8, 0.0), fsig(8, false),
0151               avNDb(0.0), davNDb2(0.0) {}
0152 
0153   };
0154 
0155   // The default constructor is empty.
0156   // The avNDb has units femtometer.
0157   SubCollisionModel(int nParm): sigTarg(8, 0.0), sigErr(8, 0.05),
0158     parmSave(nParm),
0159     NInt(100000), NPop(20), sigFuzz(0.2), impactFudge(1),
0160     fitPrint(true), avNDb(1.0),
0161     projPtr(), targPtr(), sigTotPtr(), settingsPtr(), infoPtr(), rndmPtr() {}
0162 
0163   // Virtual destructor.
0164   virtual ~SubCollisionModel() {}
0165 
0166   // Create a new SubCollisionModel of the given model.
0167   static shared_ptr<SubCollisionModel> create(int model);
0168 
0169   // Virtual init method.
0170   virtual bool init(int idAIn, int idBIn, double eCMIn);
0171 
0172   // Initialize the pointers.
0173   void initPtr(NucleusModel & projIn, NucleusModel & targIn,
0174                SigmaTotal & sigTotIn, Settings & settingsIn,
0175                Info & infoIn, Rndm & rndmIn) {
0176     projPtr = &projIn;
0177     targPtr = &targIn;
0178     sigTotPtr = &sigTotIn;
0179     settingsPtr = &settingsIn;
0180     infoPtr = &infoIn;
0181     rndmPtr = &rndmIn;
0182     loggerPtr = infoIn.loggerPtr;
0183   }
0184 
0185   // Access the nucleon-nucleon cross sections assumed
0186   // for this model.
0187 
0188   // The target total nucleon-nucleon cross section.
0189   double sigTot() const { return sigTarg[0]; }
0190 
0191   // The target elastic cross section.
0192   double sigEl() const { return sigTarg[6]; }
0193 
0194   // The target central diffractive excitation cross section.
0195   double sigCDE() const { return sigTarg[5]; }
0196 
0197   // The target single diffractive excitation cross section (both sides).
0198   double sigSDE() const { return sigTarg[3] + sigTarg[4]; }
0199 
0200   // The target single diffractive excitation cross section (projectile).
0201   double sigSDEP() const { return sigTarg[3]; }
0202 
0203   // The target single diffractive excitation cross section (target).
0204   double sigSDET() const { return sigTarg[4]; }
0205 
0206   // The target double diffractive excitation cross section.
0207   double sigDDE() const { return sigTarg[2]; }
0208 
0209   // The target non-diffractive (absorptive) cross section.
0210   double sigND() const { return sigTarg[1]; }
0211 
0212   // The target elastic b-slope parameter.
0213   double bSlope() const { return sigTarg[7]; }
0214 
0215   // Return the average non-diffractive impact parameter.
0216   double avNDB() const { return avNDb; }
0217 
0218   // Update internally stored cross sections.
0219   void updateSig();
0220 
0221   // Calculate the Chi2 for the given cross section estimates.
0222   double Chi2(const SigEst & sigs, int npar) const;
0223 
0224   // Set beam kinematics.
0225   void setKinematics(double eCMIn);
0226 
0227   // Set projectile particle.
0228   void setIDA(int idA);
0229 
0230   // Use a genetic algorithm to fit the parameters.
0231   bool evolve(int nGenerations, double eCM, int idANow);
0232 
0233   // Get the number of free parameters for the model.
0234   int nParms() const { return parmSave.size(); }
0235 
0236   // Set the parameters of this model.
0237   void setParm(const vector<double>& parmIn) {
0238     for (size_t i = 0; i < parmSave.size(); ++i)
0239       parmSave[i] = parmIn[i];
0240   }
0241 
0242   // Get the current parameters of this model.
0243   vector<double> getParm() const { return parmSave; }
0244 
0245   // Get the minimum allowed parameter values for this model.
0246   virtual vector<double> minParm() const = 0;
0247 
0248   // Get the default parameter values for this model.
0249   virtual vector<double> defParm() const = 0;
0250 
0251   // Get the maximum allowed parameter values for this model.
0252   virtual vector<double> maxParm() const = 0;
0253 
0254   // Take two nuclei and produce the corresponding subcollisions. The states
0255   // of the nucleons may be changed if fluctuations are allowed by the model.
0256   virtual SubCollisionSet getCollisions(Nucleus& proj, Nucleus& targ) = 0;
0257 
0258   // Calculate the cross sections for the given set of parameters.
0259   virtual SigEst getSig() const = 0;
0260 
0261 private:
0262 
0263   // The nucleon-nucleon cross sections targets for this model
0264   // (tot, nd, dd, sdp, sdt, cd, el, bslope) and the required precision.
0265   vector<double> sigTarg, sigErr;
0266 
0267   // Generate parameters based on run settings and the evolutionary algorithm.
0268   bool genParms();
0269 
0270   // Save/load parameter configuration to/from settings/disk.
0271   bool saveParms(string fileName) const;
0272   bool loadParms(string fileName);
0273 
0274 protected:
0275 
0276   // Saved parameters.
0277   vector<double> parmSave;
0278 
0279   // The parameters stearing the fitting of internal parameters to
0280   // the different nucleon-nucleon cross sections.
0281   int NInt, NPop;
0282   double sigFuzz;
0283   double impactFudge;
0284   bool fitPrint;
0285 
0286   // The estimated average impact parameter distance (in femtometer)
0287   // for absorptive collisions.
0288   double avNDb;
0289 
0290   // Info from the controlling HeavyIons object.
0291   NucleusModel* projPtr;
0292   NucleusModel* targPtr;
0293   SigmaTotal* sigTotPtr;
0294   Settings* settingsPtr;
0295   Info* infoPtr;
0296   Rndm* rndmPtr;
0297   Logger* loggerPtr;
0298 
0299   // For variable energies.
0300   int idASave, idBSave;
0301   bool doVarECM, doVarBeams;
0302   double eMin, eMax, eSave;
0303   int eCMPts;
0304 
0305   // The list of particles that have been fitted.
0306   vector<int> idAList;
0307 
0308   // A vector of interpolators for the current particle. Each entry
0309   // corresponds to one parameter, each interpolator is over the energy range.
0310   vector<LogInterpolator> *subCollParms;
0311 
0312   // Mapping id -> interpolator, one entry for each particle.
0313   map<int, vector<LogInterpolator>> subCollParmsMap;
0314 
0315 };
0316 
0317 //==========================================================================
0318 
0319 // The most naive sub-collision model, assuming static nucleons and
0320 // an absorptive cross section equal to the total inelastic. No
0321 // fluctuations, meaning no diffraction.
0322 
0323 class BlackSubCollisionModel : public SubCollisionModel {
0324 
0325 public:
0326 
0327   // The default constructor simply lists the nucleon-nucleon cross sections.
0328   BlackSubCollisionModel() : SubCollisionModel(0) {}
0329 
0330   // Virtual destructor.
0331   virtual ~BlackSubCollisionModel() override {}
0332 
0333   // Get the minimum and maximum allowed parameter values for this model.
0334   vector<double> minParm() const override { return vector<double>(); }
0335   vector<double> defParm() const override { return vector<double>(); }
0336   vector<double> maxParm() const override { return vector<double>(); }
0337 
0338   // Get cross sections used by this model.
0339   virtual SigEst getSig() const override {
0340     SigEst s;
0341     s.sig[0] = 56.52;//sigTot();
0342     s.sig[1] = sigND();
0343     s.sig[6] = s.sig[0] - s.sig[1];
0344     s.sig[7] = bSlope();
0345     return s;
0346   }
0347 
0348   // Take two nuclei and return the corresponding sub-collisions.
0349   virtual SubCollisionSet getCollisions(Nucleus& proj, Nucleus& targ) override;
0350 
0351 };
0352 
0353 //==========================================================================
0354 
0355 // A very simple sub-collision model, assuming static nucleons and
0356 // just assuring that the individual nucleon-nucleon cross sections
0357 // are preserved.
0358 
0359 class NaiveSubCollisionModel : public SubCollisionModel {
0360 
0361 public:
0362 
0363   // The default constructor simply lists the nucleon-nucleon cross sections.
0364   NaiveSubCollisionModel() : SubCollisionModel(0) {}
0365 
0366   // Virtual destructor.
0367   virtual ~NaiveSubCollisionModel() override {}
0368 
0369   // Get the minimum and maximum allowed parameter values for this model.
0370   vector<double> minParm() const override { return vector<double>(); }
0371   vector<double> defParm() const override { return vector<double>(); }
0372   vector<double> maxParm() const override { return vector<double>(); }
0373 
0374   // Get cross sections used by this model.
0375   virtual SigEst getSig() const override {
0376     SigEst s;
0377     s.sig[0] = sigTot();
0378     s.sig[1] = sigND();
0379     s.sig[3] = sigSDEP();
0380     s.sig[4] = sigSDET();
0381     s.sig[2] = sigDDE();
0382     s.sig[6] = sigEl();
0383     s.sig[7] = bSlope();
0384     return s;
0385   }
0386 
0387   // Take two nuclei and return the corresponding sub-collisions.
0388   virtual SubCollisionSet getCollisions(Nucleus& proj, Nucleus& targ) override;
0389 
0390 };
0391 
0392 //==========================================================================
0393 
0394 // A base class for sub-collision models where each nucleon has a
0395 // fluctuating "radius". The base model has two parameters, sigd and alpha,
0396 // which are used for opacity calculations. Subclasses may have additional
0397 // parameters to describe the radius distributions of that specific model.
0398 
0399 class FluctuatingSubCollisionModel : public SubCollisionModel {
0400 
0401 public:
0402 
0403   // The default constructor simply lists the nucleon-nucleon cross sections.
0404   FluctuatingSubCollisionModel(int nParmIn, int modein)
0405     : SubCollisionModel(nParmIn + 2), opacityMode(modein),
0406       sigd(parmSave[nParmIn]), alpha(parmSave[nParmIn + 1]) {}
0407 
0408 
0409   // Virtual destructor.
0410   virtual ~FluctuatingSubCollisionModel() override {}
0411 
0412   // Take two nuclei and pick specific states for each nucleon,
0413   // then get the corresponding sub-collisions.
0414   virtual SubCollisionSet getCollisions(Nucleus& proj, Nucleus& targ) override;
0415 
0416   // Calculate the cross sections for the given set of parameters.
0417   virtual SigEst getSig() const override;
0418 
0419 protected:
0420 
0421   // Pick a radius for the nucleon, depending on the specific model.
0422   virtual double pickRadiusProj() const = 0;
0423   virtual double pickRadiusTarg() const = 0;
0424 
0425   // Optional mode for opacity.
0426   int opacityMode;
0427 
0428 private:
0429 
0430   // Saturation scale of the nucleus.
0431   double& sigd;
0432 
0433   // Power of the saturation scale
0434   double& alpha;
0435 
0436   // The opacity of the collision at a given sigma.
0437   double opacity(double sig) const {
0438     sig /= sigd;
0439     if ( opacityMode == 1 )
0440       return pow(-expm1(-sig), alpha);
0441     return sig > numeric_limits<double>::epsilon() ?
0442       pow(-expm1(-1.0/sig), alpha) : 1.0;
0443   }
0444 
0445   // Return the elastic amplitude for a projectile and target state
0446   // and the impact parameter between the corresponding nucleons.
0447   double Tpt(const Nucleon::State & p,
0448              const Nucleon::State & t, double b) const {
0449     double sig = M_PI*pow2(p[0] + t[0]);
0450     double grey = opacity(sig);
0451     return sig/grey > b*b*2.0*M_PI? grey: 0.0;
0452   }
0453 
0454 };
0455 
0456 //==========================================================================
0457 
0458 // A sub-collision model where each nucleon has a fluctuating
0459 // "radius" according to a Strikman-inspired distribution.
0460 
0461 class DoubleStrikmanSubCollisionModel : public FluctuatingSubCollisionModel {
0462 
0463 public:
0464 
0465   // The default constructor simply lists the nucleon-nucleon cross sections.
0466   DoubleStrikmanSubCollisionModel(int modeIn = 0)
0467     : FluctuatingSubCollisionModel(1, modeIn), k0(parmSave[0]) {}
0468 
0469   // Virtual destructor.
0470   virtual ~DoubleStrikmanSubCollisionModel() override {}
0471 
0472   // Get the minimum and maximum allowed parameter values for this model.
0473   vector<double> minParm() const override { return {  0.01,  1.0,  0.0  }; }
0474   vector<double> defParm() const override { return {  2.15, 17.24, 0.33 }; }
0475   vector<double> maxParm() const override {
0476     return { 60.00, 60.0, (opacityMode == 0? 20.0: 2.0 )  }; }
0477 
0478 protected:
0479 
0480   double pickRadiusProj() const override {
0481     double r =  rndmPtr->gamma(k0, r0());
0482     return (r < numeric_limits<double>::epsilon() ?
0483       numeric_limits<double>::epsilon() : r);
0484   }
0485   double pickRadiusTarg() const override {
0486     double r =  rndmPtr->gamma(k0, r0());
0487     return (r < numeric_limits<double>::epsilon() ?
0488       numeric_limits<double>::epsilon() : r);
0489   }
0490 
0491 private:
0492 
0493   // The power in the Gamma distribution.
0494   double& k0;
0495 
0496   // Return the average radius deduced from other parameters and
0497   // the total cross section.
0498   double r0() const {
0499     return sqrt(sigTot() / (M_PI * (2.0 * k0 + 4.0 * k0 * k0)));
0500   }
0501 
0502 };
0503 
0504 //==========================================================================
0505 
0506 // ImpactParameterGenerator is able to generate a specific impact
0507 // parameter together with a weight such that aweighted average over
0508 // any quantity X(b) corresponds to the infinite integral over d^2b
0509 // X(b). This base class gives a Gaussian profile, d^2b exp(-b^2/2w^2).
0510 
0511 class ImpactParameterGenerator {
0512 
0513 public:
0514 
0515   // The default constructor takes a general width (in femtometers) as
0516   // argument.
0517   ImpactParameterGenerator() = default;
0518 
0519   // Virtual destructor.
0520   virtual ~ImpactParameterGenerator() {}
0521 
0522   // Virtual init method.
0523   virtual bool init();
0524   void initPtr(Info & infoIn, SubCollisionModel & collIn,
0525     NucleusModel & projIn, NucleusModel & targIn);
0526 
0527   // Return a new impact parameter and set the corresponding weight provided.
0528   virtual Vec4 generate(double & weight) const;
0529 
0530   // Return the scaling of the cross section used together with the
0531   // weight in genrate() to obtain the cross section. This is by
0532   // default 1 unless forceUnitWeight is specified.
0533   virtual double xSecScale() const {
0534     return forceUnitWeight? M_PI*pow2(width()*cut): 2.0*M_PI *pow2(width());
0535   }
0536 
0537   // Set the width (in femtometers).
0538   void width(double widthIn) { widthSave = widthIn; }
0539 
0540   // Get the width.
0541   double width() const { return widthSave; }
0542 
0543   // Update width based on the associated subcollision and nucleus models.
0544   void updateWidth();
0545 
0546 private:
0547 
0548   // The width of a distribution.
0549   double widthSave = 0.0;
0550 
0551   // The the cut multiplied with widthSave to give the maximum allowed
0552   // impact parameter.
0553   double cut = 3.0;
0554 
0555   // Sample flat instead of with a Gaussian.
0556   bool forceUnitWeight = false;
0557 
0558 protected:
0559 
0560   // Pointers from the controlling HeavyIons object.
0561   Info* infoPtr{};
0562   SubCollisionModel* collPtr{};
0563   NucleusModel* projPtr{};
0564   NucleusModel* targPtr{};
0565   Settings* settingsPtr{};
0566   Rndm* rndmPtr{};
0567   Logger* loggerPtr{};
0568 
0569 };
0570 
0571 //==========================================================================
0572 
0573 // A sub-collision model where each nucleon fluctuates independently
0574 // according to a log-normal distribution. Nucleons in the projectile and
0575 // target may fluctuate according to different parameters, which is relevant
0576 // e.g. for hadron-ion collisions with generic hadron species.
0577 
0578 class LogNormalSubCollisionModel : public FluctuatingSubCollisionModel {
0579 
0580 public:
0581 
0582   // The default constructor simply lists the nucleon-nucleon cross sections.
0583   LogNormalSubCollisionModel(int modeIn = 0)
0584     : FluctuatingSubCollisionModel(4, modeIn),
0585     kProj(parmSave[0]), kTarg(parmSave[1]),
0586     rProj(parmSave[2]), rTarg(parmSave[3]) {}
0587 
0588   // Virtual destructor.
0589   virtual ~LogNormalSubCollisionModel() {}
0590 
0591   //virtual SigEst getSig() const override;
0592 
0593   // Get the minimum and maximum allowed parameter values for this model.
0594   vector<double> minParm() const override {
0595     return { 0.01, 0.01, 0.10, 0.10,  1.00, 0.00 }; }
0596   vector<double> defParm() const override {
0597     return { 1.00, 1.00, 0.54, 0.54, 17.24, 0.33 }; }
0598   vector<double> maxParm() const override {
0599     return { 2.00, 2.00, 4.00, 4.00, 20.00, 2.00 }; }
0600 
0601 protected:
0602 
0603   double pickRadiusProj() const override { return pickRadius(kProj, rProj); }
0604   double pickRadiusTarg() const override { return pickRadius(kTarg, rTarg); }
0605 
0606 private:
0607 
0608   // The standard deviation of each log-normal distribution.
0609   double& kProj;
0610   double& kTarg;
0611 
0612   // The mean radius of each nucleon.
0613   double& rProj;
0614   double& rTarg;
0615 
0616   double pickRadius(double k0, double r0) const {
0617     double logSig = log(M_PI * pow2(r0)) + k0 * rndmPtr->gauss();
0618     return sqrt(exp(logSig) / M_PI);
0619   }
0620 };
0621 
0622 //==========================================================================
0623 
0624 } // end namespace Pythia8
0625 
0626 #endif // Pythia8_HISubCollisionModel_H