Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:25

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