// SusyLesHouches.cc is a part of the PYTHIA event generator. // Copyright (C) 2017 Torbjorn Sjostrand. // Main authors of this file: N. Desai, P. Skands // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details. // Please respect the MCnet Guidelines, see GUIDELINES for details. #include "Pythia8/SusyLesHouches.h" #include "Pythia8/Streams.h" namespace Pythia8 { //========================================================================== // The SusyLesHouches class. //-------------------------------------------------------------------------- // Main routine to read in SLHA and LHEF+SLHA files int SusyLesHouches::readFile(string slhaFileIn, int verboseIn, bool useDecayIn) { slhaFile = slhaFileIn; // Check that input file is OK. const char* cstring = slhaFile.c_str(); igzstream file(cstring); // Exit if input file not found. Else print file name. if (!file.good()) { message(2,"readFile",slhaFile+" not found",0); return -1; slhaRead=false; } if (verboseSav >= 3) { message(0,"readFile","parsing "+slhaFile,0); filePrinted = true; } return readFile( file, verboseIn, useDecayIn ); } int SusyLesHouches::readFile(istream& is, int verboseIn, bool useDecayIn) { int iFailFile=0; // Copy inputs to local verboseSav = verboseIn; useDecay = useDecayIn; // Array of particles read in. vector idRead; // Array of block names read in. vector processedBlocks; //Initial values for read-in variables. slhaRead=true; lhefRead=false; lhefSlha=false; bool foundSlhaTag = false; bool xmlComment = false; bool decayPrinted = false; string line=""; string blockIn=""; string decay=""; string comment=""; string blockName=""; string nameNow=""; int idNow=0; double width=0.0; //Initialize line counter int iLine=0; // Read in one line at a time. while ( getline(is, line) ) { iLine++; //Rewrite string in lowercase, removing initial and tralining blanks //as well as garbage characters toLowerRep(line); //Detect whether read-in is from a Les Houches Event File (LHEF). if (line.find("") != string::npos) { xmlComment = false; } else if (xmlComment) continue; else if (line.find(" SLHA2 interoperability //Note: the mass basis is NOT mass-ordered in SLHA1, so be careful! //Here, the mass basis is hence by PDG code, not by mass-ordered value. if (stopmix.exists() && ! usqmix.exists() ) { //1000002 = ~uL, 1000004 = ~cL, 2000002 = ~uR, 2000004 = ~cR usqmix.set(1,1, 1.0); usqmix.set(2,2, 1.0); usqmix.set(4,4, 1.0); usqmix.set(5,5, 1.0); //Fill (1000006,2000006) sector from stopmix usqmix.set(3,3, stopmix(1,1)); usqmix.set(3,6, stopmix(1,2)); usqmix.set(6,3, stopmix(2,1)); usqmix.set(6,6, stopmix(2,2)); }; if (sbotmix.exists() && ! dsqmix.exists() ) { //1000001 = ~dL, 1000003 = ~sL, 2000001 = ~dR, 2000003 = ~sR dsqmix.set(1,1, 1.0); dsqmix.set(2,2, 1.0); dsqmix.set(4,4, 1.0); dsqmix.set(5,5, 1.0); //Fill (1000005,2000005) sector from sbotmix dsqmix.set(3,3, sbotmix(1,1)); dsqmix.set(3,6, sbotmix(1,2)); dsqmix.set(6,3, sbotmix(2,1)); dsqmix.set(6,6, sbotmix(2,2)); }; if (staumix.exists() && ! selmix.exists() ) { //1000011 = ~eL, 1000013 = ~muL, 2000011 = ~eR, 2000013 = ~muR selmix.set(1,1, 1.0); selmix.set(2,2, 1.0); selmix.set(4,4, 1.0); selmix.set(5,5, 1.0); //Fill (1000015,2000015) sector from staumix selmix.set(3,3, staumix(1,1)); selmix.set(3,6, staumix(1,2)); selmix.set(6,3, staumix(2,1)); selmix.set(6,6, staumix(2,2)); }; if (! snumix.exists() && ! snsmix.exists()) { //1000012 = ~nu_e, 1000014 = ~nu_mu, 1000016 = ~nu_tau snumix.set(1,1, 1.0); snumix.set(2,2, 1.0); snumix.set(3,3, 1.0); }; // Step 4) Check mass ordering and unitarity/orthogonality of mixing matrices // Check expected mass orderings if (mass.exists()) { // CP-even Higgs if (abs(mass(25)) > abs(mass(35)) || (modsel(3) == 1 && abs(mass(35)) > abs(mass(45))) ) message(0,"checkSpectrum","Note: Higgs sector is not mass-ordered",0); // CP-odd Higgs if (modsel(3) == 1 && abs(mass(36)) > abs(mass(46))) message(0,"checkSpectrum", "Note: CP-odd Higgs sector is not mass-ordered",0); // Neutralinos if (abs(mass(1000022)) > abs(mass(1000023)) || abs(mass(1000023)) > abs(mass(1000025)) || abs(mass(1000025)) > abs(mass(1000035)) || (modsel(3) == 1 && abs(mass(1000035)) > abs(mass(1000045))) ) message(0,"checkSpectrum","Note: Neutralino sector is not mass-ordered" ,0); // Charginos if (abs(mass(1000024)) > abs(mass(1000037))) message(0,"checkSpectrum","Note: Chargino sector is not mass-ordered",0); } //NMIX if (nmix.exists()) { for (int i=1;i<=4;i++) { double cn1=0.0; double cn2=0.0; for (int j=1;j<=4;j++) { cn1 += pow(nmix(i,j),2); cn2 += pow(nmix(j,i),2); if (imnmix.exists()) { cn1 += pow(imnmix(i,j),2); cn2 += pow(imnmix(j,i),2); } } if (abs(1.0-cn1) > 1e-3 || abs(1.0-cn2) > 1e-3) { ifail=2; message(2,"checkSpectrum","NMIX is not unitary (wrong format?)",0); break; } } } //VMIX, UMIX if (vmix.exists() && umix.exists()) { // First check for non-standard "madgraph" convention // (2,2) entry not given explicitly for (int i=1;i<=2;i++) { double cu1=0.0; double cu2=0.0; double cv1=0.0; double cv2=0.0; for (int j=1;j<=2;j++) { cu1 += pow(umix(i,j),2); cu2 += pow(umix(j,i),2); cv1 += pow(vmix(i,j),2); cv2 += pow(vmix(j,i),2); if (imumix.exists()) { cu1 += pow(imumix(i,j),2); cu2 += pow(imumix(j,i),2); } if (imvmix.exists()) { cv1 += pow(imvmix(i,j),2); cv2 += pow(imvmix(j,i),2); } } if (abs(1.0-cu1) > 1e-3 || abs(1.0-cu2) > 1e-3) { cu1 += pow(umix(1,1),2); cu2 += pow(umix(1,1),2); if (abs(1.0-cu1) > 1e-3 || abs(1.0-cu2) > 1e-3) { ifail=max(1,ifail); message(2,"checkSpectrum","UMIX is not unitary (wrong format?)",0); break; } else { // Fix madgraph non-standard convention problem message(1,"checkSpectrum","UMIX is not unitary (repaired)",0); umix.set(2,2,umix(1,1)); } } if (abs(1.0-cv1) > 1e-3 || abs(1.0-cv2) > 1e-3) { cv1 += pow(vmix(1,1),2); cv2 += pow(vmix(1,1),2); if (abs(1.0-cv1) > 1e-3 || abs(1.0-cv2) > 1e-3) { ifail=max(1,ifail); message(2,"checkSpectrum","VMIX is not unitary (wrong format?)",0); break; } else { // Fix madgraph non-standard convention problem message(1,"checkSpectrum","VMIX is not unitary (repaired)",0); vmix.set(2,2,vmix(1,1)); } } } } //STOPMIX, SBOTMIX if (stopmix.exists() && sbotmix.exists()) { for (int i=1;i<=2;i++) { double ct1=0.0; double ct2=0.0; double cb1=0.0; double cb2=0.0; for (int j=1;j<=2;j++) { ct1 += pow(stopmix(i,j),2); ct2 += pow(stopmix(j,i),2); cb1 += pow(sbotmix(i,j),2); cb2 += pow(sbotmix(j,i),2); } if (abs(1.0-ct1) > 1e-3 || abs(1.0-ct2) > 1e-3) { ifail=-1; message(2,"checkSpectrum","STOPMIX is not unitary (wrong format?)",0); break; } if (abs(1.0-cb1) > 1e-3 || abs(1.0-cb2) > 1e-3) { ifail=-1; message(2,"checkSpectrum","SBOTMIX is not unitary (wrong format?)",0); break; } } } //STAUMIX if (staumix.exists()) { for (int i=1;i<=2;i++) { double ct1=0.0; double ct2=0.0; for (int j=1;j<=2;j++) { ct1 += pow(staumix(i,j),2); ct2 += pow(staumix(j,i),2); } if (abs(1.0-ct1) > 1e-3 || abs(1.0-ct2) > 1e-3) { ifail=-1; message(2,"checkSpectrum","STAUMIX is not unitary (wrong format?)",0); break; } } } //DSQMIX if (dsqmix.exists()) { for (int i=1;i<=6;i++) { double sr=0.0; double sc=0.0; for (int j=1;j<=6;j++) { sr += pow(dsqmix(i,j),2); sc += pow(dsqmix(j,i),2); if (imdsqmix.exists()) { sr += pow(imdsqmix(i,j),2); sc += pow(imdsqmix(j,i),2); } } if (abs(1.0-sr) > 1e-3 || abs(1.0-sc) > 1e-3) { ifail=-1; message(2,"checkSpectrum","DSQMIX is not unitary (wrong format?)",0); break; } } } //USQMIX if (usqmix.exists()) { for (int i=1;i<=6;i++) { double sr=0.0; double sc=0.0; for (int j=1;j<=6;j++) { sr += pow(usqmix(i,j),2); sc += pow(usqmix(j,i),2); if (imusqmix.exists()) { sr += pow(imusqmix(i,j),2); sc += pow(imusqmix(j,i),2); } } if (abs(1.0-sr) > 1e-3 || abs(1.0-sc) > 1e-3) { ifail=-1; message(2,"checkSpectrum","USQMIX is not unitary (wrong format?)",0); break; } } } //SELMIX if (selmix.exists()) { for (int i=1;i<=6;i++) { double sr=0.0; double sc=0.0; for (int j=1;j<=6;j++) { sr += pow(selmix(i,j),2); sc += pow(selmix(j,i),2); if (imselmix.exists()) { sr += pow(imselmix(i,j),2); sc += pow(imselmix(j,i),2); } } if (abs(1.0-sr) > 1e-3 || abs(1.0-sc) > 1e-3) { ifail=-1; message(2,"checkSpectrum","SELMIX is not unitary (wrong format?)",0); break; } } } //NMSSM: if (modsel(3) == 1) { //NMNMIX if ( nmnmix.exists() ) { for (int i=1;i<=5;i++) { double cn1=0.0; double cn2=0.0; for (int j=1;j<=5;j++) { cn1 += pow(nmnmix(i,j),2); cn2 += pow(nmnmix(j,i),2); if (imnmnmix.exists()) { cn1 += pow(imnmnmix(i,j),2); cn2 += pow(imnmnmix(j,i),2); } } if (abs(1.0-cn1) > 1e-3 || abs(1.0-cn2) > 1e-3) { ifail=-1; message(2,"checkSpectrum","NMNMIX is not unitary (wrong format?)",0); break; } } } else { ifail=-1; message(1,"checkSpectrum","MODSEL 3 = 1 (NMSSM) but no NMNMIX found",0); } //NMAMIX if ( nmamix.exists() ) { for (int i=1;i<=2;i++) { double cn1=0.0; for (int j=1;j<=3;j++) { cn1 += pow(nmamix(i,j),2); } if (abs(1.0-cn1) > 1e-3) { ifail=-1; message(2,"checkSpectrum","NMAMIX is not unitary (wrong format?)",0); } } } else { ifail=-1; message(1,"checkSpectrum","MODSEL 3 = 1 (NMSSM) but no NMAMIX found",0); } //NMHMIX if ( nmhmix.exists() ) { for (int i=1;i<=3;i++) { double cn1=0.0; double cn2=0.0; for (int j=1;j<=3;j++) { cn1 += pow(nmhmix(i,j),2); cn2 += pow(nmhmix(j,i),2); } if (abs(1.0-cn1) > 1e-3 || abs(1.0-cn2) > 1e-3) { ifail=-1; message(2,"checkSpectrum","NMHMIX is not unitary (wrong format?)",0); } } } else { ifail=-1; message(1,"checkSpectrum","MODSEL 3 = 1 (NMSSM) but no NMHMIX found",0); } //NMSSMRUN if (! nmssmrun.exists() ) { ifail=-1; message(2,"checkSpectrum","MODSEL 3 = 1 (NMSSM) but no NMSSMRUN found", 0); } } //Check for documentation if (slhaRead && ! spinfo.exists(1)) spinfo.set(1,"unknown"); if (slhaRead && ! spinfo.exists(2)) spinfo.set(2,"unknown"); if (! slhaRead && ! spinfo.exists(1)) { spinfo.set(1,"DEFAULT"); spinfo.set(2,"n/a"); } //Give status if (ifail >= 2) message(0,"checkSpectrum","one or more serious problems were found"); //Print Footer listFooter(); //Return return ifail; } //-------------------------------------------------------------------------- // Simple utility to print messages, warnings, and errors void SusyLesHouches::message(int level, string place,string themessage, int line) { if (verboseSav == 0) return; // By default all output to cout, but lines below allow finer control. ostream* outstream = &cout; //Send normal messages and warnings to stdout, errors to stderr. //ostream* outstream = &cerr; //if (level <= 1) outstream = &cout; // if (level == 2) { *outstream << endl; } if (place != "") *outstream << " | (SLHA::"+place+") "; else *outstream << " | "; if (level == 1) *outstream << "Warning: "; if (level == 2) { *outstream << "ERROR: "; } if (line != 0) *outstream << "line " << line << " - "; *outstream << themessage << endl; // if (level == 2) *outstream << endl; footerPrinted=false; return; } //========================================================================== } // end namespace Pythia8