Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // VinciaMergingHooks.h is a part of the PYTHIA event generator.
0002 // Copyright (C) 2024 Torbjorn Sjostrand, Peter Skands.
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 was authored by Helen Brooks, Christian T Preuss.
0007 
0008 #ifndef Pythia8_VinciaMergingHooks_H
0009 #define Pythia8_VinciaMergingHooks_H
0010 
0011 #include "Pythia8/MergingHooks.h"
0012 #include "Pythia8/PartonLevel.h"
0013 #include "Pythia8/UserHooks.h"
0014 #include "Pythia8/VinciaCommon.h"
0015 
0016 namespace Pythia8 {
0017 
0018 //==========================================================================
0019 
0020 // Storage device for multiparticle.
0021 
0022 struct MultiParticle {
0023   vector<int> pidList;
0024   vector<int> coltypes;
0025   // id, if it has a unique one, otherwise 0.
0026   int id;
0027   // QED charge,if it has a unique one, otherwise 999.
0028   int charge;
0029   bool isRes, isFCN;
0030 };
0031 
0032 
0033 // Helper structure to identify where to find a given
0034 // hard process particle inside HardProcessParticleList.
0035 
0036 struct ParticleLocator {
0037   // Increment level for every resonance decay.
0038   int level;
0039   // Position in vector at a given level.
0040   int pos;
0041 };
0042 
0043 
0044 //==========================================================================
0045 
0046 // Class to store information about a particle in the hard process.
0047 
0048 class HardProcessParticleList;
0049 class HardProcessParticle {
0050 
0051   friend class HardProcessParticleList;
0052 
0053  public:
0054 
0055   // Construct from particle data.
0056   HardProcessParticle(int idIn, ParticleDataEntryPtr pdata,
0057     ParticleLocator locIn, HardProcessParticleList* listPtrIn,
0058     vector<ParticleLocator>& mothersIn) :
0059     isMultiparticle(false), pid(idIn), multiPtr(nullptr),
0060     loc(locIn), listPtr(listPtrIn), mothers(mothersIn) {
0061     isResSav = pdata->isResonance(); coltype = pdata->colType(pid);
0062     charge = pdata->chargeType(pid); isColSav = coltype != 0;
0063     nameSav = pdata->name(pid);}
0064 
0065   // Construct from multiparticle.
0066   HardProcessParticle(string nameIn, const MultiParticle* multiPtrIn,
0067     ParticleLocator locIn, HardProcessParticleList * listPtrIn,
0068     vector<ParticleLocator> & mothersIn) :
0069     isMultiparticle(true), nameSav(nameIn), multiPtr(multiPtrIn),
0070       loc(locIn), listPtr(listPtrIn), mothers(mothersIn) {
0071     pid = multiPtr->id; charge = multiPtr->charge;
0072     isResSav = multiPtr->isRes;
0073     coltype = multiPtr->coltypes.size() != 0 ? multiPtr->coltypes.at(0) : 0;
0074     isColSav = coltype !=0;}
0075 
0076   // Check if final.
0077   bool isFinal() const {return daughters.size() == 0;}
0078 
0079   // Check if beam particle.
0080   bool isBeam() const {return loc.level == 0;}
0081 
0082   // Check if intermediate particle.
0083   bool isIntermediate() const {return !isBeam() && !isFinal();}
0084 
0085   // Getter methods.
0086   bool isRes() const {return isResSav;}
0087   bool isCol() const {return isColSav;}
0088   bool isMulti() const { return isMultiparticle;}
0089   string name() const {return nameSav;}
0090   int id() const {return pid;}
0091   int chargeType() const {return charge;}
0092   int colType() const {return coltype;}
0093   vector<ParticleLocator> getDaughters() const {return daughters;}
0094   const MultiParticle* getMulti() const {return multiPtr;}
0095 
0096   // Print the particle.
0097   void print() const;
0098 
0099  private:
0100 
0101   bool isMultiparticle;
0102   bool isResSav;
0103   bool isColSav;
0104   string nameSav;
0105 
0106   // pid and coltype if not multiparticle.
0107   int pid;
0108   int coltype;
0109 
0110   // QED charge if it has a unique value (even if multiparticle).
0111   int charge;
0112 
0113   // Pointer to a multiparticle if is one,
0114   // null pointer otherwise.
0115   const MultiParticle* multiPtr;
0116 
0117   // Location of this particle - only used by particle list.
0118   ParticleLocator loc;
0119   // Pointer to the list in which this particle lives.
0120   HardProcessParticleList* listPtr;
0121 
0122   // Location of this particle's mother(s).
0123   vector<ParticleLocator> mothers;
0124 
0125   // Location of this particle's daughter(s).
0126   vector<ParticleLocator> daughters;
0127 
0128 };
0129 
0130 //==========================================================================
0131 
0132 // List of hard particles.
0133 
0134 class HardProcessParticleList {
0135 
0136  public:
0137 
0138   // List the hard particles.
0139   void list() const;
0140 
0141   // Fetch pointers to the beams.
0142   pair<HardProcessParticle*, HardProcessParticle*> getBeams() {
0143     HardProcessParticle* beamAPtr{nullptr}, *beamBPtr{nullptr};
0144     if (!particles.empty() && particles[0].size() == 2) {
0145       beamAPtr = &particles[0][0]; beamBPtr = &particles[0][1];}
0146     return make_pair(beamAPtr,beamBPtr);}
0147 
0148   // Fetch pointer to particles at i-th level.
0149   vector<HardProcessParticle>* getLevel(int i) {
0150     if (particles.find(i) != particles.end()) return &particles[i];
0151     else return nullptr;}
0152 
0153   // Get a single particle, given a location.
0154   HardProcessParticle* getPart(ParticleLocator loc) {
0155     if (particles.find(loc.level) != particles.end() &&
0156         int(particles[loc.level].size()) > loc.pos)
0157       return &particles[loc.level].at(loc.pos);
0158     return nullptr;}
0159 
0160   // Add multiparticle to list.
0161   ParticleLocator add(int level, string nameIn, const MultiParticle* multiPtr,
0162     vector<ParticleLocator>& mothersIn);
0163 
0164   // Add particle to list from data.
0165   ParticleLocator add(int level, int idIn, ParticleDataEntryPtr pdata,
0166     vector<ParticleLocator>& mothersIn);
0167 
0168   // Set daughters of particle at mother location.
0169   void setDaughters(ParticleLocator& mother,
0170     vector<ParticleLocator>& daughters);
0171 
0172   // Get the next location.
0173   ParticleLocator getNextLoc(int level) {
0174    // Does this level exist yet? Create.
0175    if (particles.find(level) == particles.end())
0176      particles[level] = vector<HardProcessParticle>();
0177    ParticleLocator loc; loc.level = level; loc.pos = particles[level].size();
0178    return loc;}
0179 
0180  private:
0181 
0182   // This is the list of all particles, by level (each nested decay
0183   // creates a new level).
0184   map<int, vector<HardProcessParticle>> particles;
0185 
0186 };
0187 
0188 //==========================================================================
0189 
0190 // Storage device for containing colour structure of hard process.
0191 
0192 struct ColourStructure {
0193   // Pointers to beam particles.
0194   HardProcessParticle* beamA{};
0195   HardProcessParticle* beamB{};
0196 
0197   // Pointers to coloured partons, leptons and resonances.
0198   vector<HardProcessParticle*> coloured;
0199   vector<HardProcessParticle*> leptons;
0200 
0201   // IDs of hadronically decaying resonances.
0202   vector<int> resPlusHad;
0203   vector<int> resMinusHad;
0204   vector<int> resNeutralFCHad;
0205   vector<int> resNeutralFNHad;
0206 
0207   // IDs of leptonically decaying resonances.
0208   vector<int> resPlusLep;
0209   vector<int> resMinusLep;
0210   vector<int> resNeutralFCLep;
0211   vector<int> resNeutralFNLep;
0212 
0213   // IDs of charged undecayed resonances
0214   // (only for hard process specification when MergeInResSystems = off).
0215   vector<int> resPlusUndecayed;
0216   vector<int> resMinusUndecayed;
0217   vector<int> resNeutralUndecayed;
0218 
0219   // Counters for partons (after all col res decayed).
0220   int nQQbarPairs{0};
0221   int nColoured{0};
0222 
0223   // Minimum and maximum number of chains associated with beams.
0224   int nMinBeamChains{0};
0225   int nMaxBeamChains{0};
0226 };
0227 
0228 //==========================================================================
0229 
0230 // Container for the hard process used in Vincia merging.
0231 
0232 class VinciaHardProcess : public HardProcess {
0233 
0234  public:
0235 
0236   // Constructor.
0237   VinciaHardProcess(Logger* loggerPtrIn, int verboseIn, bool resolveDecaysIn,
0238     bool doHEFTIn, bool doVBFIn) :
0239     verbose(verboseIn), loggerPtr(loggerPtrIn),
0240       resolveDecays(resolveDecaysIn), doHEFT(doHEFTIn), doVBF(doVBFIn),
0241       isInit(false) {defineMultiparticles();}
0242 
0243   // Initialise process.
0244   void initOnProcess(string process, ParticleData* particleData) override;
0245 
0246   // Redundant inherited methods - only dummy versions here.
0247   void storeCandidates(const Event&, string) override {;}
0248   bool matchesAnyOutgoing(int, const Event&) override {return false;}
0249   bool findOtherCandidates(int, const Event&, bool) override {return false;}
0250 
0251   // Print functions.
0252   void list() const {parts.list();}
0253   void listLookup() const;
0254 
0255   // Set verbosity.
0256   void setVerbose(int verboseIn) {verbose = verboseIn;}
0257 
0258   // Check if initialised.
0259   bool initSuccess() {return isInit;}
0260 
0261   // Return the colour structure of the hard process.
0262   void getColourStructure(ColourStructure& colStructNow);
0263 
0264 private:
0265 
0266   // Initialised multiparticle definitions.
0267   void defineMultiparticles();
0268   // Check if ID may be a beam particle.
0269   bool isBeamID(int id);
0270   // Initialise map of names to IDs.
0271   void initLookup(ParticleData* particleData);
0272 
0273   // Split process string into incoming, outgoing using ">".
0274   bool splitProcess(string process, vector<string>& inWords,
0275     vector<string>& outWords);
0276   // Split string into words by spaces, and append to the back
0277   // (or front) of wordsOut.
0278   void splitbyWhitespace(string wordIn, vector<string>& wordsOut,
0279     bool atFront = false);
0280 
0281   // Set the list of particles in the hard process.
0282   bool getParticles(ParticleData* particleDataPtr,
0283     vector<string> inWords,
0284     vector<string> outWords);
0285 
0286   // Recursive version (if decays are found).
0287   bool getParticles(ParticleData* particleDataPtr,
0288     vector<string> inWords,
0289     vector<string> outWords,
0290     int levelNow,
0291     vector<ParticleLocator>& mothersIn,
0292     vector<ParticleLocator>& mothersNow);
0293 
0294   // Add a particle to list, and save location in loc if successful.
0295   bool addParticle(ParticleData* particleDataPtr,int level, bool isIncoming,
0296     string name, vector<ParticleLocator>& mothersIn, ParticleLocator& loc);
0297 
0298   // Set daughters of particle at mother location.
0299   void setDaughters(ParticleLocator& mother,
0300     vector<ParticleLocator>& daughters) {parts.setDaughters(mother,daughters);}
0301 
0302   // Verbosity.
0303   int verbose;
0304 
0305   // Logger object.
0306   Logger* loggerPtr{};
0307 
0308   // Flag to control how resonances are handled.
0309   bool resolveDecays;
0310 
0311   // Flags to control how HEFT and VBF are handled.
0312   bool doHEFT, doVBF;
0313 
0314   // Provide a way to look up a particle data entry by its name.
0315   map<string, int> lookupIDfromName;
0316 
0317   // Store neutral flavour-changing resonances.
0318   map<int, bool> isFCNres;
0319 
0320   // Provide a way to define multparticles.
0321   map<string, MultiParticle> multiparticles;
0322 
0323   // Main way of storing the hard process particles.
0324   HardProcessParticleList parts;
0325 
0326   // Did initialisation succeed?
0327   bool isInit;
0328 
0329 };
0330 
0331 //==========================================================================
0332 
0333 // Class for Vincia to perform merging.
0334 
0335 class VinciaMergingHooks : public MergingHooks {
0336 
0337  public:
0338 
0339   // Constructor.
0340   VinciaMergingHooks() : vinHardProcessPtr(nullptr), isInit(false) {;}
0341   // Destructor.
0342   ~VinciaMergingHooks() {if (hardProcess) delete hardProcess;}
0343 
0344   // Initialise.
0345   void init() override;
0346 
0347   // Set starting scales.
0348   bool setShowerStartingScales(bool isTrial, bool,
0349     double& pTscaleIn, const Event& event, double& pTmaxFSRIn, bool&,
0350     double& pTmaxISRIn, bool&, double& pTmaxMPIIn, bool&) override;
0351 
0352   // This MergingHooks is for Vincia only.
0353   virtual bool usesVincia() override {return true;}
0354 
0355   // Calculate merging scale of current state.
0356   virtual double tmsNow(const Event& event) override;
0357 
0358   // Check whether an event should be vetoed due to branching above tMS.
0359   virtual bool canVetoStep() override;
0360   virtual bool doVetoStep(const Event& process, const Event& event, bool)
0361     override;
0362 
0363   // Overridden base class methods.
0364   virtual bool doVetoEmission(const Event&) override {return false;}
0365   virtual bool canVetoEmission() override {return false;}
0366   virtual double dampenIfFailCuts(const Event& ) override {return 0.;}
0367   virtual int getNumberOfClusteringSteps(const Event&, bool) override {
0368     return 0;}
0369   virtual bool canCutOnRecState() override {return false;}
0370   virtual bool doCutOnRecState(const Event&) override {return false;}
0371   virtual bool canVetoTrialEmission() override {return false;}
0372   virtual bool doVetoTrialEmission(const Event&, const Event&) override {
0373     return false;}
0374   virtual bool useShowerPlugin() override {return false;}
0375   virtual double hardProcessME(const Event&) override {return 0;}
0376 
0377   // Others.
0378   virtual double tmsDefinition( const Event&) override {return 0.;}
0379 
0380   // Set and get verbosity.
0381   void setVerbose(int verboseIn) {verbose = verboseIn;}
0382   int getVerbose() {return verbose;}
0383 
0384   // Check if initialisation succeeded.
0385   bool initSuccess() {return isInit;}
0386 
0387   // Get list of leptons in the hard process.
0388   vector<HardProcessParticle*> getLeptons() {return colStructSav.leptons;}
0389 
0390   // Get number of undecayed resonances.
0391   int getNResPlusUndecayed() {
0392     return int(colStructSav.resPlusUndecayed.size());}
0393   int getNResMinusUndecayed() {
0394     return int(colStructSav.resMinusUndecayed.size());}
0395   int getNResNeutralUndecayed() {
0396     return int(colStructSav.resNeutralUndecayed.size());}
0397 
0398   // Get list of undecayed resonances in the hard process.
0399   vector<int> getResPlusUndecayed() {
0400     return colStructSav.resPlusUndecayed;}
0401   vector<int> getResMinusUndecayed() {
0402     return colStructSav.resMinusUndecayed;}
0403   vector<int> getResNeutralUndecayed() {
0404     return colStructSav.resNeutralUndecayed;}
0405 
0406   // Get list of leptonically decaying resonances in the hard process.
0407   vector<int> getResPlusLep() {return colStructSav.resPlusLep;}
0408   vector<int> getResMinusLep() {return colStructSav.resMinusLep;}
0409   vector<int> getResNeutralFCLep() {return colStructSav.resNeutralFCLep;}
0410   vector<int> getResNeutralFNLep() {return colStructSav.resNeutralFNLep;}
0411 
0412   // Get list of hadronically decaying resonances in the hard process.
0413   vector<int> getResPlusHad() {return colStructSav.resPlusHad;}
0414   vector<int> getResMinusHad() {return colStructSav.resMinusHad;}
0415   vector<int> getResNeutralFCHad() {return colStructSav.resNeutralFCHad;}
0416   vector<int> getResNeutralFNHad() {return colStructSav.resNeutralFNHad;}
0417 
0418   // Get number of hadronically decaying resonances in the hard process.
0419   int getNResPlusHad() {return colStructSav.resPlusHad.size();}
0420   int getNResMinusHad() {return colStructSav.resMinusHad.size();}
0421   int getNResNeutralFCHad() {return colStructSav.resNeutralFCHad.size();}
0422   int getNResNeutralFNHad() {return colStructSav.resNeutralFNHad.size();}
0423   int getNResHad() {return getNResPlusHad() + getNResMinusHad() +
0424       getNResNeutralFCHad() + getNResNeutralFNHad();}
0425 
0426   // Get numbers of (either hadronically or leptonically decaying)
0427   // resonances in the hard process.
0428   int getNResPlus() {return colStructSav.resPlusHad.size() +
0429       colStructSav.resPlusLep.size();}
0430   int getNResMinus() {return colStructSav.resMinusHad.size() +
0431       colStructSav.resMinusLep.size();}
0432   int getNResNeutralFC() {return colStructSav.resNeutralFCHad.size() +
0433       colStructSav.resNeutralFCLep.size();}
0434   int getNResNeutralFN() {return colStructSav.resNeutralFNHad.size() +
0435       colStructSav.resNeutralFNLep.size();}
0436 
0437   // Get information about the beam chains.
0438   int getNChainsMin() {return colStructSav.nMinBeamChains;}
0439   int getNChainsMax() {return colStructSav.nMaxBeamChains;}
0440   int getNPartons() {return colStructSav.nColoured;}
0441   int getNQPairs() {return colStructSav.nQQbarPairs;}
0442 
0443   // Get informations about whether colour structure has been set yet.
0444   bool hasSetColourStructure() {return hasColStruct;}
0445 
0446   // Check if we are merging in resonance systems.
0447   bool canMergeRes() {return doMergeRes;}
0448 
0449   // Check if we are merging in VBF system.
0450   bool doMergeInVBF() {return doVBF;}
0451 
0452   // Check if we are allowing HEFT couplings.
0453   bool allowHEFT() {return doHEFT;}
0454 
0455   // Get maximum number of additional jets from resonance decay systems.
0456   int nMaxJetsRes() {return nJetMaxResSave;}
0457 
0458   // Fetch shower restarting scale for resonances.
0459   void setScaleRes(int iRes, double scale) {resSysRestartScale[iRes] = scale;}
0460 
0461   // Fetch shower starting scale for resonances.
0462   double getScaleRes(int iRes, const Event&) {
0463     return resSysRestartScale.find(iRes) != resSysRestartScale.end() ?
0464       resSysRestartScale[iRes] : tmsCut();}
0465 
0466   // Check if clusterings are allowed.
0467   bool canClusFF() {return doFF;}
0468   bool canClusRF() {return doRF;}
0469   bool canClusII() {return doII;}
0470   bool canClusIF() {return doIF;}
0471 
0472   // Veto showered event if branching is above merging scale.
0473   bool isAboveMS(const Event& event);
0474 
0475   // Same as HardProcess, but explicitly of VinciaHardProcess type.
0476   // Note both point to the same object.
0477   VinciaHardProcess* vinHardProcessPtr{};
0478 
0479  protected:
0480 
0481   // Maximal number of additional jets per resonance system.
0482   int nJetMaxResSave;
0483 
0484   // Number of resonance systems allowed to produce additional jets.
0485   int nMergeResSys;
0486 
0487   // Flag to decide if we can merge in resonance systems.
0488   bool doMergeRes;
0489 
0490   // Tell Vincia whether to veto emissions from non-resonance systems.
0491   bool doVetoNotInResSav;
0492 
0493   // Saved information about resonance restart scales.
0494   map<int,double> resSysRestartScale;
0495 
0496  private:
0497 
0498   // Merging scale implementations.
0499   double kTmin(const Event& event);
0500   vector<double> cutsMin(const Event& event);
0501 
0502   // Find the colour structure of the hard process.
0503   ColourStructure getColourStructure();
0504   bool setColourStructure();
0505   void printColStruct();
0506 
0507   // Check whether a particle is a resonance decay product.
0508   bool isResDecayProd(int iPtcl, const Event& event);
0509 
0510   // Get list of jets in event record according to jet definition.
0511   vector<int> getJetsInEvent(const Event& event);
0512 
0513   // Did we suceed in initialising?
0514   bool isInit;
0515 
0516   // Verbosity.
0517   int verbose;
0518 
0519   // Colour strucuture of the hard process.
0520   bool hasColStruct;
0521   ColourStructure colStructSav;
0522 
0523   // Flags to turn on/off FSR or ISR.
0524   bool doFF, doRF, doII, doIF;
0525 
0526   // Flags to turn on/off specific event topologies.
0527   bool doHEFT{false}, doVBF{false};
0528 
0529 };
0530 
0531 //==========================================================================
0532 
0533 // Mini UserHooks class for setting the scale of main shower in
0534 // resonance systems (if doing merging in these).
0535 
0536 class MergeResScaleHook : public UserHooks {
0537 
0538 public:
0539 
0540   // Constructor.
0541   MergeResScaleHook( MergingHooksPtr mergingHooksPtrIn) {
0542     // Cast as a VinciaMergingHooks object.
0543     vinMergingHooksPtr
0544       = dynamic_pointer_cast<VinciaMergingHooks>(mergingHooksPtrIn);
0545     if (vinMergingHooksPtr == nullptr || !vinMergingHooksPtr->initSuccess() )
0546       canMergeRes = false;
0547     else canMergeRes = vinMergingHooksPtr->canMergeRes();}
0548 
0549   // Start resonance showers at a scale of m.
0550   bool canSetResonanceScale() override {return canMergeRes;}
0551   double scaleResonance(int iRes, const Event& event) override {
0552     return vinMergingHooksPtr->getScaleRes(iRes,event);}
0553 
0554  private:
0555 
0556   bool canMergeRes;
0557   shared_ptr<VinciaMergingHooks> vinMergingHooksPtr;
0558 
0559 };
0560 
0561 //==========================================================================
0562 
0563 } // end namespace Pythia8
0564 
0565 #endif // Pythia8_MergingHooks_H