// LesHouches.cc is a part of the PYTHIA event generator. // Copyright (C) 2017 Torbjorn Sjostrand. // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details. // Please respect the MCnet Guidelines, see GUIDELINES for details. // Function definitions (not found in the header) for the LHAup and // LHAupLHEF classes. #include "Pythia8/LesHouches.h" // Access time information. #include namespace Pythia8 { //========================================================================== // LHAup class. //-------------------------------------------------------------------------- // Constants: could be changed here if desired, but normally should not. // These are of technical nature, as described for each. // LHA convention with cross section in pb may require conversion from mb. const double LHAup::CONVERTMB2PB = 1e9; //-------------------------------------------------------------------------- // Print the initialization info; to check it worked. void LHAup::listInit() { // Header. cout << "\n -------- LHA initialization information ------------ \n"; // Beam info. cout << fixed << setprecision(3) << "\n beam kind energy pdfgrp pdfset \n" << " A " << setw(6) << idBeamASave << setw(12) << eBeamASave << setw(8) << pdfGroupBeamASave << setw(8) << pdfSetBeamASave << "\n" << " B " << setw(6) << idBeamBSave << setw(12) << eBeamBSave << setw(8) << pdfGroupBeamBSave << setw(8) << pdfSetBeamBSave << "\n"; // Event weighting strategy. cout << "\n Event weighting strategy = " << setw(2) << strategySave << "\n" ; // Process list. cout << scientific << setprecision(4) << "\n Processes, with strategy-dependent cross section info \n" << " number xsec (pb) xerr (pb) xmax (pb) \n" ; for (int ip = 0; ip < int(processes.size()); ++ip) { cout << setw(8) << processes[ip].idProc << setw(15) << processes[ip].xSecProc << setw(15) << processes[ip].xErrProc << setw(15) << processes[ip].xMaxProc << "\n"; } // Finished. cout << "\n -------- End LHA initialization information -------- \n"; } //-------------------------------------------------------------------------- // Print the event info; to check it worked. void LHAup::listEvent() { // Header. cout << "\n -------- LHA event information and listing -------------" << "--------------------------------------------------------- \n"; // Basic event info. cout << scientific << setprecision(4) << "\n process = " << setw(8) << idProc << " weight = " << setw(12) << weightProc << " scale = " << setw(12) << scaleProc << " (GeV) \n" << " " << " alpha_em = " << setw(12) << alphaQEDProc << " alpha_strong = " << setw(12) << alphaQCDProc << "\n"; // Particle list cout << fixed << setprecision(3) << "\n Participating Particles \n" << " no id stat mothers colours p_x " << "p_y p_z e m tau spin \n" ; for (int ip = 1; ip < int(particles.size()); ++ip) { cout << setw(6) << ip << setw(10) << particles[ip].idPart << setw(5) << particles[ip].statusPart << setw(6) << particles[ip].mother1Part << setw(6) << particles[ip].mother2Part << setw(6) << particles[ip].col1Part << setw(6) << particles[ip].col2Part << setw(11) << particles[ip].pxPart << setw(11) << particles[ip].pyPart << setw(11) << particles[ip].pzPart << setw(11) << particles[ip].ePart << setw(11) << particles[ip].mPart << setw(8) << particles[ip].tauPart << setw(8) << particles[ip].spinPart << "\n"; } // PDF info - optional. if (pdfIsSetSave) cout << "\n pdf: id1 =" << setw(5) << id1pdfSave << " id2 =" << setw(5) << id2pdfSave << " x1 =" << scientific << setw(10) << x1pdfSave << " x2 =" << setw(10) << x2pdfSave << " scalePDF =" << setw(10) << scalePDFSave << " pdf1 =" << setw(10) << pdf1Save << " pdf2 =" << setw(10) << pdf2Save << "\n"; // Finished. cout << "\n -------- End LHA event information and listing ---------" << "--------------------------------------------------------- \n"; } //-------------------------------------------------------------------------- // Open and write header to a Les Houches Event File. bool LHAup::openLHEF(string fileNameIn) { // Open file for writing. Reset it to be empty. fileName = fileNameIn; const char* cstring = fileName.c_str(); osLHEF.open(cstring, ios::out | ios::trunc); if (!osLHEF) { infoPtr->errorMsg("Error in LHAup::openLHEF:" " could not open file", fileName); return false; } // Read out current date and time. time_t t = time(0); strftime(dateNow,12,"%d %b %Y",localtime(&t)); strftime(timeNow,9,"%H:%M:%S",localtime(&t)); // Write header. osLHEF << "\n" << "" << endl; // Done. return true; } //-------------------------------------------------------------------------- // Write initialization information to a Les Houches Event File. bool LHAup::initLHEF() { // Write information on beams. osLHEF << "\n" << scientific << setprecision(6) << " " << idBeamASave << " " << idBeamBSave << " " << eBeamASave << " " << eBeamBSave << " " << pdfGroupBeamASave << " " << pdfGroupBeamBSave << " " << pdfSetBeamASave << " " << pdfSetBeamBSave << " " << strategySave << " " << processes.size() << "\n"; // Write information on all the subprocesses. for (int ip = 0; ip < int(processes.size()); ++ip) osLHEF << " " << setw(13) << processes[ip].xSecProc << " " << setw(13) << processes[ip].xErrProc << " " << setw(13) << processes[ip].xMaxProc << " " << setw(6) << processes[ip].idProc << "\n"; // Done. osLHEF << "" << endl; return true; } //-------------------------------------------------------------------------- // Write event information to a Les Houches Event File. // Normal mode is to line up event info in columns, but the non-verbose // altnernative saves space at the expense of human readability. bool LHAup::eventLHEF(bool verbose) { // Default verbose option. if (verbose) { // Write information on process as such. osLHEF << "\n" << scientific << setprecision(6) << " " << setw(5) << particles.size() - 1 << " " << setw(5) << idProc << " " << setw(13) << weightProc << " " << setw(13) << scaleProc << " " << setw(13) << alphaQEDProc << " " << setw(13) << alphaQCDProc << "\n"; // Write information on the particles, excluding zeroth. for (int ip = 1; ip < int(particles.size()); ++ip) { LHAParticle& ptNow = particles[ip]; osLHEF << " " << setw(8) << ptNow.idPart << " " << setw(5) << ptNow.statusPart << " " << setw(5) << ptNow.mother1Part << " " << setw(5) << ptNow.mother2Part << " " << setw(5) << ptNow.col1Part << " " << setw(5) << ptNow.col2Part << setprecision(10) << " " << setw(17) << ptNow.pxPart << " " << setw(17) << ptNow.pyPart << " " << setw(17) << ptNow.pzPart << " " << setw(17) << ptNow.ePart << " " << setw(17) << ptNow.mPart << setprecision(6); if (ptNow.tauPart == 0.) osLHEF << " 0."; else osLHEF << " " << setw(13) << ptNow.tauPart; if (ptNow.spinPart == 9.) osLHEF << " 9."; else osLHEF << " " << setw(13) << ptNow.spinPart; osLHEF << "\n"; } // Optionally write information on PDF values at hard interaction. if (pdfIsSetSave) osLHEF << "#pdf" << " " << setw(4) << id1pdfSave << " " << setw(4) << id2pdfSave << " " << setw(13) << x1pdfSave << " " << setw(13) << x2pdfSave << " " << setw(13) << scalePDFSave << " " << setw(13) << pdf1Save << " " << setw(13) << pdf2Save << "\n"; // Alternative non-verbose option. } else { // Write information on process as such. osLHEF << "\n" << scientific << setprecision(6) << particles.size() - 1 << " " << idProc << " " << weightProc << " " << scaleProc << " " << alphaQEDProc << " " << alphaQCDProc << "\n"; // Write information on the particles, excluding zeroth. for (int ip = 1; ip < int(particles.size()); ++ip) { LHAParticle& ptNow = particles[ip]; osLHEF << ptNow.idPart << " " << ptNow.statusPart << " " << ptNow.mother1Part << " " << ptNow.mother2Part << " " << ptNow.col1Part << " " << ptNow.col2Part << setprecision(10) << " " << ptNow.pxPart << " " << ptNow.pyPart << " " << ptNow.pzPart << " " << ptNow.ePart << " " << ptNow.mPart << setprecision(6); if (ptNow.tauPart == 0.) osLHEF << " 0."; else osLHEF << " " << setw(13) << ptNow.tauPart; if (ptNow.spinPart == 9.) osLHEF << " 9."; else osLHEF << " " << setw(13) << ptNow.spinPart; osLHEF << "\n"; } // Optionally write information on PDF values at hard interaction. if (pdfIsSetSave) osLHEF << "#pdf" << " " << id1pdfSave << " " << id2pdfSave << " " << x1pdfSave << " " << x2pdfSave << " " << scalePDFSave << " " << pdf1Save << " " << pdf2Save << "\n"; } // Done. osLHEF << "" << endl; return true; } //-------------------------------------------------------------------------- // Write end of a Les Houches Event File and close it. bool LHAup::closeLHEF(bool updateInit) { // Write an end to the file. osLHEF << "" << endl; osLHEF.close(); // Optionally update the cross section information. if (updateInit) { const char* cstring = fileName.c_str(); osLHEF.open(cstring, ios::in | ios::out); // Rewrite header; identically with what openLHEF did. osLHEF << "\n" << "" << endl; // Redo initialization information. initLHEF(); osLHEF.close(); } // Done. return true; } //-------------------------------------------------------------------------- // Read in initialization information from a Les Houches Event File. bool LHAup::setInitLHEF(istream& is, bool readHeaders) { // Check that first line is consistent with proper LHEF file. string line; if (!getline(is, line)) return false; if (line.find("" : ") tag // is found first on a line. string tag = " "; do { if (!getline(is, line)) return false; if (line.find_first_not_of(" \n\t\v\b\r\f\a") != string::npos) { istringstream getfirst(line); getfirst >> tag; if (!getfirst) return false; } } while (tag != "" && tag != " headerMap; // Loop over lines until an tag is found. bool read = true, newKey = false; string key = "base"; vector < string > keyVec; while (true) { if (!getline(is, line)) return false; // Break lines containing multiple tags into two segments. // (Could be generalized to multiple segments but this is // sufficient to handle at least info on same line. size_t firstTagEnd = line.find_first_of(">"); size_t secondTagBegin = line.find_first_of("<",firstTagEnd); vector lineVec; if (firstTagEnd != string::npos && secondTagBegin != string::npos) { lineVec.push_back(line.substr(0,secondTagBegin)); lineVec.push_back(line.substr(secondTagBegin, line.size()-secondTagBegin)); } else { lineVec.push_back(line); } // Loop over segments of current line for (int iVec=0; iVec= posEnd) continue; // PZS Jan 2015: Allow multiple open/close tags on a single line. size_t tagBeg = lineClean.find_first_of("<"); size_t tagEnd = lineClean.find_first_of(">"); while (tagBeg != string::npos && tagBeg < tagEnd) { // Update remainder (non-tag) part of line, for later storage posBeg = tagEnd+1; // Only take the first word of the tag, tag = lineClean.substr(tagBeg + 1, tagEnd - tagBeg - 1); istringstream getfirst(tag); getfirst >> tag; // Prepare for next while iteration: // Look for next tag on line and update posBeg and posEnd. tagBeg = lineClean.find_first_of("<",tagEnd); tagEnd = lineClean.find_first_of(">",tagBeg+1); // Tag present, so handle here if (getfirst) { // Exit condition if (tag == "init") break; // End of header block; keep reading until tag, // but do not store any further information else if (tag == "/header") { read = false; continue; // Opening tag } else if (tag[0] != '/') { keyVec.push_back(tag); newKey = true; continue; // Closing tag that matches current key } else if (tag == "/" + keyVec.back()) { keyVec.pop_back(); newKey = true; continue; // Also check for forgotten close tag: next-to-last element } else if (keyVec.size() >= 2 && tag == "/" + keyVec[keyVec.size()-2]) { infoPtr->errorMsg("Warning in LHAup::setInitLHEF:" " corrupt LHEF end tag",keyVec.back()); keyVec.pop_back(); keyVec.pop_back(); newKey = true; continue; } } // if (getfirst) } // Loop over tags // Exit condition if (tag == "init") break; // At this point the (rest of) the line is not a tag; // If no longer reading anything, skip. if (!read) continue; // Check for key change if (newKey) { if (keyVec.empty()) key = "base"; else key = keyVec[0]; for (size_t i = 1; i < keyVec.size(); i++) key += "." + keyVec[i]; newKey = false; } // Check if anything remains to store of this line posBeg = line.find_first_not_of(" \n\t\v\b\r\f\a",posBeg); if (posBeg == string::npos || posBeg > posEnd) continue; // Append information to local storage headerMap[key] += line.substr(posBeg,posEnd - posBeg + 1) + "\n"; } // Loop over line segments // Exit condition if (tag == "init") break; } // while (true) // Copy information to info using LHAup::setInfoHeader for (map < string, string >::iterator it = headerMap.begin(); it != headerMap.end(); it++) setInfoHeader(it->first, it->second); } // if (readHeaders == true && tag == headerTag) // Read in first info line; done if empty. if (!getline(is, line)) return false; if (line.find("> idbmupA >> idbmupB >> ebmupA >> ebmupB >> pdfgupA >> pdfgupB >> pdfsupA >> pdfsupB >> idwtup >> nprup; if (!getbms) return false; setBeamA(idbmupA, ebmupA, pdfgupA, pdfsupA); setBeamB(idbmupB, ebmupB, pdfgupB, pdfsupB); setStrategy(idwtup); // Read in process info, one process at a time, and store it. double xsecup, xerrup, xmaxup; xSecSumSave = 0.; xErrSumSave = 0.; int lprup; for (int ip = 0; ip < nprup; ++ip) { if (!getline(is, line)) return false; istringstream getpro(line); getpro >> xsecup >> xerrup >> xmaxup >> lprup ; if (!getpro) return false; addProcess(lprup, xsecup, xerrup, xmaxup); xSecSumSave += xsecup; xErrSumSave += pow2(xerrup); } xErrSumSave = sqrt(xErrSumSave); // Reading worked. return true; } //-------------------------------------------------------------------------- // Read in event information from a Les Houches Event File, // into a staging area where it can be reused by setOldEventLHEF. bool LHAup::setNewEventLHEF(istream& is) { // Loop over lines until an > tag; if (!getfirst) return false; } } while (tag != "" && tag != "> nupSave >> idprupSave >> xwgtupSave >> scalupSave >> aqedupSave >> aqcdupSave; if (!getpro) return false; // Reset particlesSave vector, add slot-0 empty particle. particlesSave.clear(); particlesSave.push_back( LHAParticle() ); // Read in particle info one by one, and store it. // Note unusual C++ loop range, to better reflect LHA/Fortran standard. // (Recall that process(...) above added empty particle at index 0.) int idup, istup, mothup1, mothup2, icolup1, icolup2; double pup1, pup2, pup3, pup4, pup5, vtimup, spinup; for (int ip = 1; ip <= nupSave; ++ip) { if (!getline(is, line)) return false; istringstream getall(line); getall >> idup >> istup >> mothup1 >> mothup2 >> icolup1 >> icolup2 >> pup1 >> pup2 >> pup3 >> pup4 >> pup5 >> vtimup >> spinup; if (!getall) return false; particlesSave.push_back( LHAParticle( idup, istup, mothup1, mothup2, icolup1, icolup2, pup1, pup2, pup3, pup4, pup5, vtimup, spinup, -1.) ); } // Flavour and x values of hard-process initiators. id1InSave = particlesSave[1].idPart; id2InSave = particlesSave[2].idPart; x1InSave = (eBeamASave > 0.) ? particlesSave[1].ePart / eBeamASave : 0.; x2InSave = (eBeamBSave > 0.) ? particlesSave[2].ePart / eBeamBSave : 0.; // Continue parsing till . Look for optional info on the way. getPDFSave = false; getScale = false; do { if (!getline(is, line)) return false; istringstream getinfo(line); getinfo >> tag; if (!getinfo) return false; // Extract PDF info if present. if (tag == "#pdf" && !getPDFSave) { getinfo >> id1pdfInSave >> id2pdfInSave >> x1pdfInSave >> x2pdfInSave >> scalePDFInSave >> pdf1InSave >> pdf2InSave; if (!getinfo) return false; getPDFSave = true; // Extract scale info if present. } else if (tag == "#" && !getScale) { double scaleIn = 0; for (int i = 3; i < int(particlesSave.size()); ++i) if (particlesSave[i].statusPart == 1) { if ( !(getinfo >> scaleIn) ) return false; particlesSave[i].scalePart = scaleIn; } if (!getinfo) return false; getScale = true; } } while (tag != "" && tag != "\n"; comments+="
\n"; comments+=reader.headerComments; comments+="
\n"; comments+="\n"; comments+=reader.initComments; comments+="\n"; istringstream is1(comments); bool useComments = (headerfile == NULL); istream & iss((useComments ? is1 : isIn)); // Check that first line is consistent with proper LHEF file. string line; if ( useComments && !getline(iss,line)) return false; if (!useComments && !getLine(line)) return false; // What to search for if reading headers; if not reading // headers then return to default behaviour string headerTag = (readHead) ? "
" : ") tag // is found first on a line. string tag = " "; do { if ( useComments && !getline(iss,line)) return false; if (!useComments && !getLine(line)) return false; if (line.find_first_not_of(" \n\t\v\b\r\f\a") != string::npos) { istringstream getfirst(line); getfirst >> tag; if (!getfirst) return false; } } while (tag != "" && tag != " headerMap; // Loop over lines until an tag is found. bool read = true, newKey = false; int commentDepth = 0; string key = "base"; vector < string > keyVec; while (true) { if ( useComments && !getline(iss,line)) return false; if (!useComments && !getLine(line)) return false; // Tell XML parser to ignore comment and CDATA blocks // If we are currently inside a comment block, check for block end if (commentDepth >= 1 && line.find("-->") != string::npos) { commentDepth--; size_t comBeg = line.find("-->")+2; size_t comEnd = line.find_last_not_of("\n\t\v\b\r\f\a "); if( comEnd == comBeg ) continue; line = line.substr(comBeg,comEnd-comBeg+1); } if (commentDepth >= 1 && line.find("]]>") != string::npos) commentDepth--; // If the comment block did not end on this line, skip to next line if (commentDepth >= 1) continue; // Check for beginning of comment blocks (parse until comment begins) if (line.find("") == string::npos) commentDepth++; int comBeg = line.find("