LCOV - code coverage report
Current view: top level - PYTHIA8/pythia8210dev/src - SLHAinterface.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 433 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 3 0.0 %

          Line data    Source code
       1             : // SLHAinterface.cc is a part of the PYTHIA event generator.
       2             : // Copyright (C) 2015 Torbjorn Sjostrand.
       3             : // Main authors of this file: N. Desai, P. Skands
       4             : // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
       5             : // Please respect the MCnet Guidelines, see GUIDELINES for details.
       6             : 
       7             : #include "Pythia8/SLHAinterface.h"
       8             : 
       9             : namespace Pythia8 {
      10             : 
      11             : //==========================================================================
      12             : 
      13             : // The SLHAinterface class.
      14             : 
      15             : //--------------------------------------------------------------------------
      16             : 
      17             : // Initialize and switch to SUSY couplings if reading SLHA spectrum.
      18             : 
      19             : void SLHAinterface::init( Settings& settings, Rndm* rndmPtr,
      20             :   Couplings* couplingsPtrIn, ParticleData* particleDataPtr,
      21             :   bool& useSLHAcouplings, stringstream& particleDataBuffer) {
      22             : 
      23             :   // Initialize SLHA couplingsPtr to PYTHIA one by default
      24           0 :   couplingsPtr     = couplingsPtrIn;
      25           0 :   useSLHAcouplings = false;
      26             : 
      27             :   // Check if SUSY couplings need to be read in
      28           0 :   if( !initSLHA(settings, particleDataPtr))
      29           0 :     infoPtr->errorMsg("Error in SLHAinterface::init: "
      30             :       "Could not read SLHA file");
      31             : 
      32             :   // Reset any particle-related user settings.
      33           0 :   string line;
      34           0 :   string warnPref = "Warning in SLHAinterface::init: ";
      35           0 :   while (getline(particleDataBuffer, line)
      36           0 :     && settings.flag("SLHA:allowUserOverride")) {
      37           0 :     bool pass = particleDataPtr->readString(line, true);
      38           0 :     if (!pass) infoPtr->errorMsg(warnPref + "Unable to process line " + line);
      39           0 :     else infoPtr->errorMsg(warnPref + "Overwriting SLHA by " + line);
      40             :   }
      41             : 
      42             :   // SLHA sets isSUSY flag to tell us if there was an SLHA SUSY spectrum
      43           0 :   if (couplingsPtr->isSUSY) {
      44             :     // Initialize the derived SUSY couplings class (SM first, then SUSY)
      45           0 :     coupSUSY.init( settings, rndmPtr);
      46           0 :     coupSUSY.initSUSY(&slha, infoPtr, particleDataPtr, &settings);
      47             :     // Switch couplingsPtr to point to the derived class
      48             :     // and tell PYTHIA to use it
      49           0 :     couplingsPtr = (Couplings *) &coupSUSY;
      50           0 :     useSLHAcouplings = true;
      51           0 :   }
      52             : 
      53           0 : }
      54             : 
      55             : //--------------------------------------------------------------------------
      56             : 
      57             : // Initialize SUSY Les Houches Accord data.
      58             : 
      59             : bool SLHAinterface::initSLHA(Settings& settings,
      60             :   ParticleData* particleDataPtr) {
      61             : 
      62             :   // Error and warning prefixes for this method
      63           0 :   string errPref  = "Error in SLHAinterface::initSLHA: ";
      64           0 :   string warnPref = "Warning in SLHAinterface::initSLHA: ";
      65           0 :   string infoPref = "Info from SLHAinterface::initSLHA: ";
      66             : 
      67             :   // Initial and settings values.
      68             :   int    ifailLHE    = 1;
      69             :   int    ifailSpc    = 1;
      70           0 :   int    readFrom    = settings.mode("SLHA:readFrom");
      71           0 :   string lhefFile    = settings.word("Beams:LHEF");
      72           0 :   string lhefHeader  = settings.word("Beams:LHEFheader");
      73           0 :   string slhaFile    = settings.word("SLHA:file");
      74           0 :   int    verboseSLHA = settings.mode("SLHA:verbose");
      75           0 :   bool   slhaUseDec  = settings.flag("SLHA:useDecayTable");
      76           0 :   bool   noSLHAFile  = ( slhaFile == "none" || slhaFile == "void"
      77           0 :                       || slhaFile == ""     || slhaFile == " " );
      78             : 
      79             :   // Set internal data members
      80           0 :   meMode      = settings.mode("SLHA:meMode");
      81             : 
      82             :   // No SUSY by default
      83           0 :   couplingsPtr->isSUSY = false;
      84             : 
      85             :   // Option with no SLHA read-in at all.
      86           0 :   if (readFrom == 0) return true;
      87             : 
      88             :   // First check LHEF header (if reading from LHEF)
      89           0 :   if (readFrom == 1) {
      90             :     // Check if there is a <slha> tag in the LHEF header
      91             :     // Note: if the <slha> tag is NOT inside the <header>, it will be ignored.
      92           0 :     string slhaInHeader( infoPtr->header("slha") );
      93           0 :     if (slhaInHeader == "" && noSLHAFile) return true;
      94             :     // If there is an <slha> tag, read file.
      95           0 :     if (lhefHeader != "void")
      96           0 :       ifailLHE = slha.readFile(lhefHeader, verboseSLHA, slhaUseDec );
      97           0 :     else if (lhefFile != "void")
      98           0 :       ifailLHE = slha.readFile(lhefFile, verboseSLHA, slhaUseDec );
      99           0 :     else if (noSLHAFile) {
     100           0 :       istringstream slhaInHeaderStream(slhaInHeader);
     101           0 :       ifailLHE = slha.readFile(slhaInHeaderStream, verboseSLHA, slhaUseDec );
     102           0 :     }
     103           0 :   }
     104             : 
     105             :   // If LHEF read successful, everything needed should already be ready
     106           0 :   if (ifailLHE == 0) {
     107             :     ifailSpc = 0;
     108           0 :     couplingsPtr->isSUSY = true;
     109             :     // If no LHEF file or no SLHA info in header, read from SLHA:file
     110           0 :   } else {
     111           0 :     lhefFile = "void";
     112           0 :     if ( noSLHAFile ) return true;
     113           0 :     ifailSpc = slha.readFile(slhaFile,verboseSLHA, slhaUseDec);
     114             :   }
     115             : 
     116             :   // In case of problems, print error and fail init.
     117           0 :   if (ifailSpc != 0) {
     118           0 :     infoPtr->errorMsg(errPref + "problem reading SLHA file", slhaFile);
     119           0 :     return false;
     120             :   } else {
     121           0 :     couplingsPtr->isSUSY = true;
     122             :   }
     123             : 
     124             :   // Check spectrum for consistency. Switch off SUSY if necessary.
     125           0 :   ifailSpc = slha.checkSpectrum();
     126             : 
     127             :   // ifail >= 1 : no MODSEL found -> don't switch on SUSY
     128           0 :   if (ifailSpc == 1) {
     129             :     // no SUSY, but MASS ok
     130           0 :     couplingsPtr->isSUSY = false;
     131           0 :     infoPtr->errorMsg(infoPref +
     132             :       "No MODSEL found, keeping internal SUSY switched off");
     133           0 :   } else if (ifailSpc >= 2) {
     134             :     // no SUSY, but problems
     135           0 :     infoPtr->errorMsg(warnPref + "Problem with SLHA MASS or QNUMBERS.");
     136           0 :     couplingsPtr->isSUSY = false;
     137           0 :   }
     138             :   // ifail = 0 : MODSEL found, spectrum OK
     139           0 :   else if (ifailSpc == 0) {
     140             :     // Print spectrum. Done.
     141           0 :     slha.printSpectrum(0);
     142             :   }
     143           0 :   else if (ifailSpc < 0) {
     144           0 :     infoPtr->errorMsg(warnPref + "Problem with SLHA spectrum.",
     145           0 :       "\n Only using masses and switching off SUSY.");
     146           0 :     settings.flag("SUSY:all", false);
     147           0 :     couplingsPtr->isSUSY = false;
     148           0 :     slha.printSpectrum(ifailSpc);
     149             :   }
     150             : 
     151             :   // SLHA1 : SLHA2 compatibility
     152             :   // Check whether scalar particle masses are ordered
     153             :   bool isOrderedQ = true;
     154             :   bool isOrderedL = true;
     155           0 :   int idSdown[6]={1000001,1000003,1000005,2000001,2000003,2000005};
     156           0 :   int idSup[6]={1000002,1000004,1000006,2000002,2000004,2000006};
     157           0 :   int idSlep[6]={1000011,1000013,1000015,2000011,2000013,2000015};
     158           0 :   for (int j=0;j<=4;j++) {
     159           0 :     if (slha.mass(idSlep[j+1]) < slha.mass(idSlep[j]))
     160           0 :       isOrderedL  = false;
     161           0 :     if (slha.mass(idSup[j+1]) < slha.mass(idSup[j]))
     162           0 :       isOrderedQ  = false;
     163           0 :     if (slha.mass(idSdown[j+1]) < slha.mass(idSdown[j]))
     164           0 :       isOrderedQ  = false;
     165             :   }
     166             : 
     167             :   // If ordered, change sparticle labels to mass-ordered enumeration
     168           0 :   for (int i=1;i<=6;i++) {
     169           0 :     ostringstream indx;
     170           0 :     indx << i;
     171           0 :     string uName = "~u_"+indx.str();
     172           0 :     string dName = "~d_"+indx.str();
     173           0 :     string lName = "~e_"+indx.str();
     174           0 :     if (isOrderedQ) {
     175           0 :       particleDataPtr->names(idSup[i-1],uName,uName+"bar");
     176           0 :       particleDataPtr->names(idSdown[i-1],dName,dName+"bar");
     177           0 :     }
     178           0 :     if (isOrderedL) particleDataPtr->names(idSlep[i-1],lName+"-",lName+"+");
     179           0 :   }
     180             : 
     181             :   // NMSSM spectrum (modify existing Higgs names and add particles)
     182           0 :   if ( (ifailSpc == 1 || ifailSpc == 0) &&  slha.modsel(3) >= 1 ) {
     183             :     // Modify Higgs names
     184           0 :     particleDataPtr->name(25,"H_1");
     185           0 :     particleDataPtr->name(35,"H_2");
     186           0 :     particleDataPtr->name(45,"H_3");
     187           0 :     particleDataPtr->name(36,"A_1");
     188           0 :     particleDataPtr->name(46,"A_2");
     189           0 :     particleDataPtr->name(1000045,"~chi_50");
     190           0 :   }
     191             : 
     192             :   // SLHA2 spectrum with flavour mixing (modify squark and/or slepton names)
     193           0 :   if ( (ifailSpc == 1 || ifailSpc == 0) &&  slha.modsel(6) >= 1 ) {
     194             :     // Squark flavour violation
     195           0 :     if ( (slha.modsel(6) == 1 || slha.modsel(6) >= 3)
     196           0 :          && slha.usqmix.exists() && slha.dsqmix.exists() ) {
     197             :       // Modify squark names
     198           0 :       particleDataPtr->names(1000001,"~d_1","~d_1bar");
     199           0 :       particleDataPtr->names(1000002,"~u_1","~u_1bar");
     200           0 :       particleDataPtr->names(1000003,"~d_2","~d_2bar");
     201           0 :       particleDataPtr->names(1000004,"~u_2","~u_2bar");
     202           0 :       particleDataPtr->names(1000005,"~d_3","~d_3bar");
     203           0 :       particleDataPtr->names(1000006,"~u_3","~u_3bar");
     204           0 :       particleDataPtr->names(2000001,"~d_4","~d_4bar");
     205           0 :       particleDataPtr->names(2000002,"~u_4","~u_4bar");
     206           0 :       particleDataPtr->names(2000003,"~d_5","~d_5bar");
     207           0 :       particleDataPtr->names(2000004,"~u_5","~u_5bar");
     208           0 :       particleDataPtr->names(2000005,"~d_6","~d_6bar");
     209           0 :       particleDataPtr->names(2000006,"~u_6","~u_6bar");
     210           0 :     }
     211             :     // Slepton flavour violation
     212           0 :     if ( (slha.modsel(6) == 2 || slha.modsel(6) >= 3)
     213           0 :          && slha.selmix.exists()) {
     214             :       // Modify slepton names
     215           0 :       particleDataPtr->names(1000011,"~e_1-","~e_1+");
     216           0 :       particleDataPtr->names(1000013,"~e_2-","~e_2+");
     217           0 :       particleDataPtr->names(1000015,"~e_3-","~e_3+");
     218           0 :       particleDataPtr->names(2000011,"~e_4-","~e_4+");
     219           0 :       particleDataPtr->names(2000013,"~e_5-","~e_5+");
     220           0 :       particleDataPtr->names(2000015,"~e_6-","~e_6+");
     221           0 :     }
     222             :     // Neutrino flavour violation
     223           0 :     if ( (slha.modsel(6) == 2 || slha.modsel(6) >= 3)
     224           0 :          && slha.upmns.exists()) {
     225             :       // Modify neutrino names (note that SM processes may not use UPMNS)
     226           0 :       particleDataPtr->names(12,"nu_1","nu_1bar");
     227           0 :       particleDataPtr->names(14,"nu_2","nu_2bar");
     228           0 :       particleDataPtr->names(16,"nu_3","nu_3bar");
     229           0 :     }
     230             :     // Sneutrino flavour violation
     231           0 :     if ( (slha.modsel(6) == 2 || slha.modsel(6) >= 3)
     232           0 :          && slha.snumix.exists()) {
     233             :       // Modify sneutrino names
     234           0 :       particleDataPtr->names(1000012,"~nu_1","~nu_1bar");
     235           0 :       particleDataPtr->names(1000014,"~nu_2","~nu_2bar");
     236           0 :       particleDataPtr->names(1000016,"~nu_3","~nu_3bar");
     237           0 :     }
     238             :     // Optionally allow for separate scalar and pseudoscalar sneutrinos
     239           0 :     if ( slha.snsmix.exists() && slha.snamix.exists() ) {
     240             :       // Scalar sneutrinos
     241           0 :       particleDataPtr->names(1000012,"~nu_S1","~nu_S1bar");
     242           0 :       particleDataPtr->names(1000014,"~nu_S2","~nu_S2bar");
     243           0 :       particleDataPtr->names(1000016,"~nu_S3","~nu_S3bar");
     244             :       // Add the pseudoscalar sneutrinos
     245           0 :       particleDataPtr->addParticle(1000017, "~nu_A1", "~nu_A1bar",1, 0., 0);
     246           0 :       particleDataPtr->addParticle(1000018, "~nu_A2", "~nu_A2bar",1, 0., 0);
     247           0 :       particleDataPtr->addParticle(1000019, "~nu_A3", "~nu_A3bar",1, 0., 0);
     248           0 :     }
     249             :   }
     250             : 
     251             :   // SLHA2 spectrum with RPV
     252           0 :   if ( (ifailSpc == 1 || ifailSpc == 0) &&  slha.modsel(4) >= 1 ) {
     253           0 :     if ( slha.rvnmix.exists() ) {
     254             :       // Neutralinos -> neutrinos
     255             :       // Maintain R-conserving names since mass-ordering unlikely to change.
     256           0 :       particleDataPtr->names(12,"nu_1","nu_1bar");
     257           0 :       particleDataPtr->names(14,"nu_2","nu_2bar");
     258           0 :       particleDataPtr->names(16,"nu_3","nu_3bar");
     259           0 :       particleDataPtr->name(1000022,"~chi_10");
     260           0 :       particleDataPtr->name(1000023,"~chi_20");
     261           0 :       particleDataPtr->name(1000025,"~chi_30");
     262           0 :       particleDataPtr->name(1000035,"~chi_40");
     263           0 :     }
     264           0 :     if ( slha.rvumix.exists() && slha.rvvmix.exists() ) {
     265             :       // Charginos -> charged leptons (note sign convention)
     266             :       // Maintain R-conserving names since mass-ordering unlikely to change.
     267           0 :       particleDataPtr->names(11,"e-","e+");
     268           0 :       particleDataPtr->names(13,"mu-","mu+");
     269           0 :       particleDataPtr->names(15,"tau-","tau+");
     270           0 :       particleDataPtr->names(1000024,"~chi_1+","~chi_1-");
     271           0 :       particleDataPtr->names(1000037,"~chi_2+","~chi_2-");
     272           0 :     }
     273           0 :     if ( slha.rvhmix.exists() ) {
     274             :       // Sneutrinos -> higgses (general mass-ordered names)
     275           0 :       particleDataPtr->name(25,"H_10");
     276           0 :       particleDataPtr->name(35,"H_20");
     277           0 :       particleDataPtr->names(1000012,"H_30","H_30");
     278           0 :       particleDataPtr->names(1000014,"H_40","H_40");
     279           0 :       particleDataPtr->names(1000016,"H_50","H_50");
     280           0 :     }
     281           0 :     if ( slha.rvamix.exists() ) {
     282             :       // Sneutrinos -> higgses (general mass-ordered names)
     283           0 :       particleDataPtr->name(36,"A_10");
     284           0 :       particleDataPtr->names(1000017,"A_20","A_20");
     285           0 :       particleDataPtr->names(1000018,"A_30","A_30");
     286           0 :       particleDataPtr->names(1000019,"A_40","A_40");
     287           0 :     }
     288           0 :     if ( slha.rvlmix.exists() ) {
     289             :       // sleptons -> charged higgses (note sign convention)
     290           0 :       particleDataPtr->names(37,"H_1+","H_1-");
     291           0 :       particleDataPtr->names(1000011,"H_2-","H_2+");
     292           0 :       particleDataPtr->names(1000013,"H_3-","H_3+");
     293           0 :       particleDataPtr->names(1000015,"H_4-","H_4+");
     294           0 :       particleDataPtr->names(2000011,"H_5-","H_5+");
     295           0 :       particleDataPtr->names(2000013,"H_6-","H_6+");
     296           0 :       particleDataPtr->names(2000015,"H_7-","H_7+");
     297           0 :     }
     298             :   }
     299             : 
     300             :   // SLHA2 spectrum with CPV
     301           0 :   if ( (ifailSpc == 1 || ifailSpc == 0) &&  slha.modsel(5) >= 1 ) {
     302             :     // no scalar/pseudoscalar distinction
     303           0 :     particleDataPtr->name(25,"H_10");
     304           0 :     particleDataPtr->name(35,"H_20");
     305           0 :     particleDataPtr->name(36,"H_30");
     306           0 :   }
     307             : 
     308             : 
     309             :   // Import qnumbers
     310           0 :   vector<int> isQnumbers;
     311             :   bool foundLowCode = false;
     312           0 :   if ( (ifailSpc == 1 || ifailSpc == 0) && slha.qnumbers.size() > 0) {
     313           0 :     for (int iQnum=0; iQnum < int(slha.qnumbers.size()); iQnum++) {
     314             :       // Always use positive id codes
     315           0 :       int id = abs(slha.qnumbers[iQnum](0));
     316           0 :       ostringstream idCode;
     317           0 :       idCode << id;
     318           0 :       if (particleDataPtr->isParticle(id)) {
     319           0 :         infoPtr->errorMsg(warnPref + "ignoring QNUMBERS", "for id = "
     320           0 :           + idCode.str() + " (already exists)", true);
     321           0 :       } else {
     322           0 :         int qEM3    = slha.qnumbers[iQnum](1);
     323           0 :         int nSpins  = slha.qnumbers[iQnum](2);
     324           0 :         int colRep  = slha.qnumbers[iQnum](3);
     325           0 :         int hasAnti = slha.qnumbers[iQnum](4);
     326             :         // Translate colRep to PYTHIA colType
     327             :         int colType = 0;
     328           0 :         if (colRep == 3) colType = 1;
     329           0 :         else if (colRep == -3) colType = -1;
     330           0 :         else if (colRep == 8) colType = 2;
     331           0 :         else if (colRep == 6) colType = 3;
     332           0 :         else if (colRep == -6) colType = -3;
     333             :         // Default name: PDG code
     334           0 :         string name, antiName;
     335           0 :         ostringstream idStream;
     336           0 :         idStream<<id;
     337           0 :         name     = idStream.str();
     338           0 :         antiName = "-"+name;
     339           0 :         if (iQnum < int(slha.qnumbersName.size())) {
     340           0 :           name = slha.qnumbersName[iQnum];
     341           0 :           antiName = slha.qnumbersAntiName[iQnum];
     342           0 :           if (antiName == "") {
     343           0 :             if (name.find("+") != string::npos) {
     344           0 :               antiName = name;
     345           0 :               antiName.replace(antiName.find("+"),1,"-");
     346           0 :             } else if (name.find("-") != string::npos) {
     347           0 :               antiName = name;
     348           0 :               antiName.replace(antiName.find("-"),1,"+");
     349             :             } else {
     350           0 :               antiName = name+"bar";
     351             :             }
     352             :           }
     353             :         }
     354           0 :         if ( hasAnti == 0) {
     355           0 :           antiName = "";
     356           0 :           particleDataPtr->addParticle(id, name, nSpins, qEM3, colType);
     357           0 :         } else {
     358           0 :           particleDataPtr->addParticle(id, name, antiName, nSpins, qEM3,
     359             :             colType);
     360             :         }
     361             :         // Store list of particle codes added by QNUMBERS
     362           0 :         isQnumbers.push_back(id);
     363           0 :         if (id < 1000000) foundLowCode = true;
     364           0 :       }
     365           0 :     }
     366           0 :   }
     367             :   // Inform user that BSM particles should ideally be assigned id codes > 1M
     368           0 :   if (foundLowCode)
     369           0 :     infoPtr->errorMsg(warnPref
     370           0 :       + "using QNUMBERS for id codes < 1000000 may clash with SM.");
     371             : 
     372             :   // Import mass spectrum.
     373           0 :   bool   keepSM            = settings.flag("SLHA:keepSM");
     374           0 :   double minMassSM         = settings.parm("SLHA:minMassSM");
     375           0 :   vector<int> idModified;
     376           0 :   if (ifailSpc == 1 || ifailSpc == 0) {
     377             : 
     378             :     // Start at beginning of mass array
     379           0 :     int    id = slha.mass.first();
     380             :     // Loop through to update particle data.
     381           0 :     for (int i = 1; i <= slha.mass.size() ; i++) {
     382             :       // Step to next mass entry
     383           0 :       if (i>1) id = slha.mass.next();
     384           0 :       ostringstream idCode;
     385           0 :       idCode << id;
     386           0 :       double mass = abs(slha.mass(id));
     387             : 
     388             :       // Check if this ID was added by qnumbers
     389             :       bool isInternal = true;
     390           0 :       for (unsigned int iq = 0; iq<isQnumbers.size(); ++iq)
     391           0 :         if (id == isQnumbers[iq]) isInternal = false;
     392             : 
     393             :       // Ignore masses for known SM particles or particles with
     394             :       // default masses < minMassSM; overwrite masses for rest.
     395           0 :       if (keepSM && (id < 25 || (id > 80 && id < 1000000)) && isInternal)
     396           0 :         infoPtr->errorMsg(warnPref + "ignoring MASS entry", "for id = "
     397           0 :           + idCode.str()
     398           0 :           + " (SLHA:keepSM. Use id > 1000000 for new particles)", true);
     399           0 :       else if (id < 1000000 && particleDataPtr->m0(id) < minMassSM
     400           0 :         && isInternal) {
     401           0 :         infoPtr->errorMsg(warnPref + "ignoring MASS entry", "for id = "
     402           0 :           + idCode.str() + " (m0 < SLHA:minMassSM)", true);
     403           0 :       }
     404             :       else {
     405           0 :         particleDataPtr->m0(id,mass);
     406           0 :         idModified.push_back(id);
     407             :       }
     408           0 :     };
     409             : 
     410           0 :   }
     411             : 
     412             :   // Update decay data.
     413           0 :   for (int iTable=0; iTable < int(slha.decays.size()); iTable++) {
     414             : 
     415             :     // Pointer to this SLHA table
     416           0 :     LHdecayTable* slhaTable=&(slha.decays[iTable]);
     417             : 
     418             :     // Extract ID and create pointer to corresponding particle data object
     419           0 :     int idRes     = slhaTable->getId();
     420           0 :     ostringstream idCode;
     421           0 :     idCode << idRes;
     422             :     ParticleDataEntry* particlePtr
     423           0 :       = particleDataPtr->particleDataEntryPtr(idRes);
     424             : 
     425             :     // Check if this ID was added by qnumbers
     426             :     bool isInternal = true;
     427           0 :     for (unsigned int iq = 0; iq<isQnumbers.size(); ++iq)
     428           0 :       if (idRes == isQnumbers[iq]) isInternal = false;
     429             : 
     430             :     // Ignore decay channels for known SM particles or particles with
     431             :     // default masses < minMassSM; overwrite masses for rest.
     432           0 :     if (keepSM && (idRes < 25 || (idRes > 80 && idRes < 1000000))
     433           0 :         && isInternal) {
     434           0 :       infoPtr->errorMsg(warnPref + "ignoring DECAY table", "for id = "
     435           0 :         + idCode.str()
     436           0 :         + " (SLHA:keepSM. Use id > 1000000 for new particles)", true);
     437           0 :       continue;
     438             :     }
     439           0 :     else if (idRes < 1000000 && particleDataPtr->m0(idRes) < minMassSM
     440           0 :              && isInternal) {
     441           0 :       infoPtr->errorMsg(warnPref + "ignoring DECAY table", "for id = "
     442           0 :         + idCode.str() + " (m0 < SLHA:minMassSM)", true);
     443           0 :       continue;
     444             :     }
     445             : 
     446             :     // Verbose output. Let user know we are using these tables.
     447           0 :     if (verboseSLHA <= 1)
     448           0 :       infoPtr->errorMsg(infoPref + "importing SLHA decay table(s)","");
     449             :     else
     450           0 :       infoPtr->errorMsg(infoPref + "importing SLHA decay table","for id = "
     451           0 :         +idCode.str(),true);
     452             : 
     453             :     // Extract and store total width (absolute value, neg -> switch off)
     454           0 :     double widRes         = abs(slhaTable->getWidth());
     455           0 :     double pythiaMinWidth = settings.parm("ResonanceWidths:minWidth");
     456           0 :     if (widRes > 0. && widRes < pythiaMinWidth) {
     457           0 :       infoPtr->errorMsg(warnPref + "forcing width = 0 ","for id = "
     458           0 :         + idCode.str() + " (width < ResonanceWidths:minWidth)" , true);
     459           0 :       widRes = 0.0;
     460           0 :     }
     461           0 :     particlePtr->setMWidth(widRes);
     462             : 
     463             :     // Set lifetime in mm for displaced vertex calculations
     464             :     // (convert GeV^-1 to mm)
     465           0 :     if (widRes > 0.) {
     466           0 :       double decayLength = 1.97e-13/widRes;
     467           0 :       particlePtr->setTau0(decayLength);
     468             : 
     469             :       // Reset decay table of the particle. Allow decays, treat as resonance.
     470           0 :       if (slhaTable->size() > 0) {
     471           0 :         particlePtr->clearChannels();
     472           0 :         particleDataPtr->mayDecay(idRes,true);
     473           0 :         particleDataPtr->isResonance(idRes,true);
     474             :       } else {
     475           0 :         infoPtr->errorMsg(warnPref + "empty DECAY table ","for id = "
     476           0 :           + idCode.str() + " (total width provided but no branching"
     477           0 :           + " fractions)", true);
     478             :       }
     479           0 :     }
     480             :     // Reset to stable if width <= 0.0
     481             :     else {
     482           0 :       particlePtr->clearChannels();
     483           0 :       particleDataPtr->mayDecay(idRes,false);
     484           0 :       particleDataPtr->isResonance(idRes,false);
     485             :     }
     486             : 
     487             :     // Set initial minimum mass.
     488             :     double brWTsum   = 0.;
     489             :     double massWTsum = 0.;
     490             : 
     491             :     // Loop over SLHA channels, import into Pythia, treating channels
     492             :     // with negative branching fractions as having the equivalent positive
     493             :     // branching fraction, but being switched off for this run
     494           0 :     for (int iChannel=0 ; iChannel<slhaTable->size(); iChannel++) {
     495           0 :       LHdecayChannel slhaChannel = slhaTable->getChannel(iChannel);
     496           0 :       double brat      = slhaChannel.getBrat();
     497           0 :       vector<int> idDa = slhaChannel.getIdDa();
     498           0 :       if (idDa.size() >= 9) {
     499           0 :         infoPtr->errorMsg(errPref + "max number of DECAY products is 8");
     500           0 :       } else if (idDa.size() <= 1) {
     501           0 :         infoPtr->errorMsg(errPref + "min number of DECAY products is 2");
     502           0 :       }
     503             :       else {
     504             :         int onMode = 1;
     505           0 :         if (brat < 0.0) onMode = 0;
     506           0 :         int meModeNow = meMode;
     507             : 
     508             :         // Check phase space, including margin ~ sqrt(sum(widths^2))
     509             :         double massSum(0.);
     510           0 :         double widSqSum = pow2(widRes);
     511           0 :         int nDa = idDa.size();
     512           0 :         for (int jDa=0; jDa<nDa; ++jDa) {
     513           0 :           massSum  += particleDataPtr->m0( idDa[jDa] );
     514           0 :           widSqSum +=  pow2(particleDataPtr->mWidth( idDa[jDa] ));
     515             :         }
     516           0 :         double deltaM = particleDataPtr->m0(idRes) - massSum;
     517             :         // Negative mass difference: intrinsically off shell
     518           0 :         if (onMode == 1 && brat > 0.0 && deltaM < 0.) {
     519             :           // String containing decay name
     520           0 :           ostringstream errCode;
     521           0 :           errCode << idRes <<" ->";
     522           0 :           for (int jDa=0; jDa<nDa; ++jDa) errCode<<" "<<idDa[jDa];
     523             :           // Could mass fluctuations at all give the needed deltaM ?
     524           0 :           if (abs(deltaM) > 100. * sqrt(widSqSum)) {
     525           0 :             infoPtr->errorMsg(warnPref + "switched off DECAY mode",
     526           0 :               ": " + errCode.str()+" (too far off shell)",true);
     527             :             onMode = 0;
     528           0 :           }
     529             :           // If ~ OK within fluctuations
     530             :           else {
     531             :             // Ignore user-selected meMode
     532           0 :             if (meModeNow != 100) {
     533           0 :               infoPtr->errorMsg(warnPref + "adding off shell DECAY mode",
     534           0 :                 ": "+errCode.str()+" (forced meMode = 100)",true);
     535             :               meModeNow = 100;
     536           0 :             } else {
     537           0 :               infoPtr->errorMsg(warnPref + "adding off shell DECAY mode",
     538           0 :                 errCode.str(), true);
     539             :             }
     540             :           }
     541           0 :         }
     542             :         // Branching-ratio-weighted average mass in decay.
     543           0 :         brWTsum   += abs(brat);
     544           0 :         massWTsum += abs(brat) * massSum;
     545             : 
     546             :         // Add channel
     547           0 :         int id0 = idDa[0];
     548           0 :         int id1 = idDa[1];
     549           0 :         int id2 = (idDa.size() >= 3) ? idDa[2] : 0;
     550           0 :         int id3 = (idDa.size() >= 4) ? idDa[3] : 0;
     551           0 :         int id4 = (idDa.size() >= 5) ? idDa[4] : 0;
     552           0 :         int id5 = (idDa.size() >= 6) ? idDa[5] : 0;
     553           0 :         int id6 = (idDa.size() >= 7) ? idDa[6] : 0;
     554           0 :         int id7 = (idDa.size() >= 8) ? idDa[7] : 0;
     555           0 :         particlePtr->addChannel(onMode,abs(brat),meModeNow,
     556             :                                 id0,id1,id2,id3,id4,id5,id6,id7);
     557             : 
     558             :       }
     559           0 :     }
     560             : 
     561             :     // Set minimal mass, but always below nominal one.
     562           0 :     if (slhaTable->size() > 0) {
     563           0 :       double massAvg = massWTsum / brWTsum;
     564           0 :       double massMin = min( massAvg, particlePtr->m0()) ;
     565           0 :       particlePtr->setMMin(massMin);
     566           0 :     }
     567             : 
     568             :     // Add to list of particles that have been modified
     569           0 :     idModified.push_back(idRes);
     570             : 
     571           0 :   }
     572             : 
     573             :   // Sanity check of all decay tables with modified MASS or DECAY info
     574           0 :   for (int iMod = 0; iMod < int(idModified.size()); ++iMod) {
     575           0 :     int id = idModified[iMod];
     576           0 :     ostringstream idCode;
     577           0 :     idCode << id;
     578             :     ParticleDataEntry* particlePtr
     579           0 :       = particleDataPtr->particleDataEntryPtr(id);
     580           0 :     double m0  = particlePtr->m0();
     581           0 :     double wid = particlePtr->mWidth();
     582             :     // Always set massless particles stable
     583           0 :     if (m0 <= 0.0 && (wid > 0.0 || particlePtr->mayDecay())) {
     584           0 :       infoPtr->errorMsg(warnPref + "massless particle forced stable"," id = "
     585           0 :         + idCode.str(), true);
     586           0 :       particlePtr->clearChannels();
     587           0 :       particlePtr->setMWidth(0.0);
     588           0 :       particlePtr->setMayDecay(false);
     589           0 :       particleDataPtr->isResonance(id,false);
     590           0 :       continue;
     591             :     }
     592             :     // Declare zero-width particles to be stable (for now)
     593           0 :     if (wid == 0.0 && particlePtr->mayDecay()) {
     594           0 :       particlePtr->setMayDecay(false);
     595           0 :       continue;
     596             :     }
     597             :     // Check at least one on-shell channel is available
     598           0 :     double mSumMin = 10. * m0;
     599           0 :     int nChannels = particlePtr->sizeChannels();
     600           0 :     if (nChannels >= 1) {
     601           0 :       for (int iChannel=0; iChannel<nChannels; ++iChannel) {
     602           0 :         DecayChannel channel = particlePtr->channel(iChannel);
     603           0 :         if (channel.onMode() <= 0) continue;
     604           0 :         int nProd = channel.multiplicity();
     605           0 :         double mSum = 0.;
     606           0 :         for (int iDa = 0; iDa < nProd; ++iDa) {
     607           0 :           int idDa   = channel.product(iDa);
     608           0 :           mSum += particleDataPtr->m0(idDa);
     609             :         }
     610           0 :         mSumMin = min(mSumMin, mSum);
     611           0 :       }
     612             :       // Require at least one on-shell channel
     613           0 :       if (mSumMin > m0 && particlePtr->id() != 25) {
     614           0 :         infoPtr->errorMsg(warnPref + "particle forced stable"," id = "
     615           0 :           + idCode.str() + " (no on-shell decay channels)", true);
     616           0 :         particlePtr->setMWidth(0.0);
     617           0 :         particlePtr->setMayDecay(false);
     618           0 :         continue;
     619             :       }
     620           0 :       else if (mSumMin > m0 && particlePtr->id() == 25) {
     621           0 :         infoPtr->errorMsg(warnPref
     622           0 :           + "allowing particle with no on-shell decays ",
     623           0 :           " id = " + idCode.str() , true);
     624           0 :       }
     625             :       else {
     626             :       // mMin: lower cutoff on Breit-Wigner: default is mMin = m0 - 5*Gamma
     627             :       // (User is allowed to specify a lower value if desired.)
     628             :       // Increase minimum if needed to ensure at least one channel on shell
     629           0 :         double mMin = min(particlePtr->mMin(), max(0.0,m0 - 5.*wid));
     630           0 :         mMin = max(mSumMin,mMin);
     631           0 :         particlePtr->setMMin(mMin);
     632           0 :       }
     633             :     }
     634           0 :   }
     635             : 
     636             :   return true;
     637             : 
     638           0 : }
     639             : 
     640             : //--------------------------------------------------------------------------
     641             : 
     642             : // Initialize SLHA blocks SMINPUTS and MASS from PYTHIA SM parameter values.
     643             : // E.g., to make sure that there are no important unfilled entries
     644             : 
     645             : void SLHAinterface::pythia2slha(ParticleData* particleDataPtr) {
     646             : 
     647             :   // Initialize block SMINPUTS.
     648           0 :   string blockName = "sminputs";
     649           0 :   double mZ = particleDataPtr->m0(23);
     650           0 :   slha.set(blockName,1,1.0/couplingsPtr->alphaEM(pow2(mZ)));
     651           0 :   slha.set(blockName,2,couplingsPtr->GF());
     652           0 :   slha.set(blockName,3,couplingsPtr->alphaS(pow2(mZ)));
     653           0 :   slha.set(blockName,4,mZ);
     654             :   // b mass (should be running mass, here pole for time being)
     655           0 :   slha.set(blockName,5,particleDataPtr->m0(5));
     656           0 :   slha.set(blockName,6,particleDataPtr->m0(6));
     657           0 :   slha.set(blockName,7,particleDataPtr->m0(15));
     658           0 :   slha.set(blockName,8,particleDataPtr->m0(16));
     659           0 :   slha.set(blockName,11,particleDataPtr->m0(11));
     660           0 :   slha.set(blockName,12,particleDataPtr->m0(12));
     661           0 :   slha.set(blockName,13,particleDataPtr->m0(13));
     662           0 :   slha.set(blockName,14,particleDataPtr->m0(14));
     663             :   // Force 3 lightest quarks massless
     664           0 :   slha.set(blockName,21,double(0.0));
     665           0 :   slha.set(blockName,22,double(0.0));
     666           0 :   slha.set(blockName,23,double(0.0));
     667             :   // c mass (should be running mass, here pole for time being)
     668           0 :   slha.set(blockName,24,particleDataPtr->m0(4));
     669             : 
     670             :   // Initialize block MASS.
     671           0 :   blockName = "mass";
     672             :   int id = 1;
     673             :   int count = 0;
     674           0 :   while (particleDataPtr->nextId(id) > id) {
     675           0 :     slha.set(blockName,id,particleDataPtr->m0(id));
     676           0 :     id = particleDataPtr->nextId(id);
     677           0 :     ++count;
     678           0 :     if (count > 10000) {
     679           0 :       infoPtr->errorMsg("Error in SLHAinterface::pythia2slha(): "
     680             :         "encountered infinite loop when saving mass block");
     681           0 :       break;
     682             :     }
     683             :   }
     684             : 
     685           0 : }
     686             : 
     687             : //==========================================================================
     688             : 
     689             : } // end namespace Pythia8

Generated by: LCOV version 1.11