CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/GeneratorInterface/Pythia6Interface/src/Pythia6Service.cc

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include <functional>
00003 #include <iostream>
00004 #include <sstream>
00005 #include <fstream> 
00006 #include <cmath>
00007 #include <string>
00008 #include <set>
00009 
00010 #include <boost/bind.hpp>
00011 #include <boost/algorithm/string/classification.hpp>
00012 #include <boost/algorithm/string/split.hpp>
00013 
00014 #include <CLHEP/Random/RandomEngine.h>
00015 
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 
00018 #include "FWCore/ParameterSet/interface/FileInPath.h"
00019 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00020 
00021 #include "GeneratorInterface/Core/interface/RNDMEngineAccess.h"
00022 
00023 #include "GeneratorInterface/Pythia6Interface/interface/Pythia6Service.h"
00024 #include "GeneratorInterface/Pythia6Interface/interface/Pythia6Declarations.h"
00025 // #include "GeneratorInterface/Core/interface/ParameterCollector.h"
00026 
00027 extern "C"
00028 {
00029    void fioopn_( int* unit, const char* line, int length );
00030    void fioopnw_( int* unit, const char* line, int length );
00031    void fiocls_( int* unit );
00032    void pyslha_( int*, int*, int* );
00033    static int call_pyslha(int mupda, int kforig = 0)
00034    {
00035       int iretrn = 0;
00036       pyslha_(&mupda, &kforig, &iretrn);
00037       return iretrn;
00038    }
00039 
00040    void pyupda_(int*, int*);
00041    static void call_pyupda( int opt, int iunit ){ 
00042      pyupda_( &opt, &iunit ); 
00043    }
00044 
00045    double gen::pyr_(int *idummy)
00046    {
00047       // getInstance will throw if no one used enter/leave
00048       // or this is the wrong caller class, like e.g. Herwig6Instance
00049       Pythia6Service* service = FortranInstance::getInstance<Pythia6Service>();
00050       return service->fRandomEngine->flat(); 
00051    }
00052 }
00053 
00054 using namespace gen;
00055 using namespace edm;
00056 
00057 Pythia6Service* Pythia6Service::fPythia6Owner = 0;
00058 
00059 Pythia6Service::Pythia6Service()
00060   : fRandomEngine(&getEngineReference()), fUnitSLHA(24), fUnitPYUPDA(25)
00061 {
00062 }
00063 
00064 Pythia6Service::Pythia6Service( const ParameterSet& ps )
00065   : fRandomEngine(&getEngineReference()), fUnitSLHA(24), fUnitPYUPDA(25)
00066 {
00067    if (fPythia6Owner)
00068       throw cms::Exception("PythiaError") <<
00069             "Two Pythia6Service instances claiming Pythia6 ownership." <<
00070             std::endl;
00071 
00072    fPythia6Owner = this;
00073 
00074 /*
00075    ParameterCollector collector(ps.getParameter<edm::ParameterSet>("PythiaParameters"));
00076 
00077    fParamGeneral.clear();
00078    fParamCSA.clear();
00079    fParamSLHA.clear();
00080    
00081    fParamGeneral = std::vector<std::string>(collector.begin(), collector.end());
00082    fParamCSA     = std::vector<std::string>(collector.begin("CSAParameters"), collector.end());
00083    fParamSLHA    = std::vector<std::string>(collector.begin("SLHAParameters"), collector.end());
00084 */
00085      
00086 
00087    // Set PYTHIA parameters in a single ParameterSet
00088    //
00089    edm::ParameterSet pythia_params = 
00090       ps.getParameter<edm::ParameterSet>("PythiaParameters") ;
00091       
00092    // read and sort Pythia6 cards
00093    //
00094    std::vector<std::string> setNames =
00095       pythia_params.getParameter<std::vector<std::string> >("parameterSets");
00096       
00097    // std::vector<std::string>  paramLines;
00098    fParamGeneral.clear();
00099    fParamCSA.clear();
00100    fParamSLHA.clear();
00101    fParamPYUPDA.clear();
00102    
00103 
00104    for(std::vector<std::string>::const_iterator iter = setNames.begin();
00105                                                 iter != setNames.end(); ++iter) 
00106    {
00107       std::vector<std::string> lines =
00108          pythia_params.getParameter< std::vector<std::string> >(*iter);
00109 
00110       for(std::vector<std::string>::const_iterator line = lines.begin();
00111                                                    line != lines.end(); ++line ) 
00112       {
00113          if (line->substr(0, 7) == "MRPY(1)")
00114             throw cms::Exception("PythiaError") <<
00115             "Attempted to set random number"
00116             " using Pythia command 'MRPY(1)'."
00117             " Please use the"
00118             " RandomNumberGeneratorService." <<
00119             std::endl;
00120 
00121          if ( *iter == "CSAParameters" )
00122          {
00123             fParamCSA.push_back(*line);
00124          }
00125          else if ( *iter == "SLHAParameters" )
00126          {
00127             fParamSLHA.push_back(*line);
00128          }
00129          else if ( *iter == "PYUPDAParameters" )
00130          {
00131             fParamPYUPDA.push_back(*line);
00132          }
00133          else
00134          {
00135             fParamGeneral.push_back(*line);
00136          }
00137       }
00138    }
00139 }
00140 
00141 Pythia6Service::~Pythia6Service()
00142 {
00143    if (fPythia6Owner == this)
00144       fPythia6Owner = 0;
00145 
00146    fParamGeneral.clear();
00147    fParamCSA.clear();
00148    fParamSLHA.clear();
00149    fParamPYUPDA.clear();
00150 }
00151 
00152 void Pythia6Service::enter()
00153 {
00154    FortranInstance::enter();
00155 
00156    if (!fPythia6Owner) {
00157      edm::LogInfo("Generator|Pythia6Interface") <<
00158           "gen::Pythia6Service is going to initialise Pythia, as no other "
00159           "instace has done so yet, and Pythia service routines have been "
00160           "requested by a dummy instance." << std::endl;
00161 
00162      call_pygive("MSTU(12)=12345");
00163      call_pyinit("NONE", "", "", 0.0);
00164 
00165      fPythia6Owner = this;
00166    }
00167 }
00168 
00169 void Pythia6Service::setGeneralParams()
00170 {
00171    // now pass general config cards 
00172    //
00173    for(std::vector<std::string>::const_iterator iter = fParamGeneral.begin();
00174                                                 iter != fParamGeneral.end(); ++iter)
00175    {
00176       if (!call_pygive(*iter))
00177          throw cms::Exception("PythiaError")
00178          << "Pythia did not accept \""
00179          << *iter << "\"." << std::endl;
00180    }
00181    
00182    return ;
00183 }
00184 
00185 void Pythia6Service::setCSAParams()
00186 {
00187       
00188    txgive_init_();
00189    
00190    for(std::vector<std::string>::const_iterator iter = fParamCSA.begin();
00191                                                 iter != fParamCSA.end(); ++iter)
00192    {
00193       txgive_( iter->c_str(), iter->length() );
00194    }   
00195    
00196    return ;
00197 }
00198 
00199 void Pythia6Service::openSLHA( const char* file )
00200 {
00201 
00202         std::ostringstream pyCard1 ;
00203         pyCard1 << "IMSS(21)=" << fUnitSLHA;
00204         call_pygive( pyCard1.str() );
00205         std::ostringstream pyCard2 ;
00206         pyCard2 << "IMSS(22)=" << fUnitSLHA;
00207         call_pygive( pyCard2.str() );
00208 
00209         fioopn_( &fUnitSLHA, file, strlen(file) );
00210         
00211         return;
00212 
00213 }
00214 
00215 void Pythia6Service::openPYUPDA( const char* file, bool write_file )
00216 {
00217 
00218         if (write_file) {
00219           std::cout<<"=== WRITING PYUPDA FILE "<<file<<" ==="<<std::endl;
00220           fioopnw_( &fUnitPYUPDA, file, strlen(file) );
00221           // Write Pythia particle table to this card file.
00222           call_pyupda(1, fUnitPYUPDA);
00223         } else {
00224           std::cout<<"=== READING PYUPDA FILE "<<file<<" ==="<<std::endl;
00225           fioopn_( &fUnitPYUPDA, file, strlen(file) );
00226           // Update Pythia particle table with this card file.
00227           call_pyupda(3, fUnitPYUPDA);
00228         }
00229         
00230         return;
00231 
00232 }
00233 
00234 void Pythia6Service::closeSLHA() 
00235 {
00236 
00237    fiocls_(&fUnitSLHA);
00238    
00239    return;
00240 }
00241 
00242 void Pythia6Service::closePYUPDA() 
00243 {
00244 
00245    fiocls_(&fUnitPYUPDA);
00246    
00247    return;
00248 
00249 }
00250 
00251 void Pythia6Service::setSLHAParams()
00252 {
00253    for (std::vector<std::string>::const_iterator iter = fParamSLHA.begin();
00254                                                  iter != fParamSLHA.end(); iter++ )
00255    {
00256 
00257         if( iter->find( "SLHAFILE", 0 ) == std::string::npos ) continue;
00258         std::string::size_type start = iter->find_first_of( "=" ) + 1;
00259         std::string::size_type end = iter->length() - 1;
00260         std::string::size_type temp = iter->find_first_of( "'", start );
00261         if( temp != std::string::npos ) {
00262                         start = temp + 1;
00263                         end = iter->find_last_of( "'" ) - 1;
00264         } 
00265         start = iter->find_first_not_of( " ", start );
00266         end = iter->find_last_not_of( " ", end );
00267         //std::cout << " start, end = " << start << " " << end << std::endl;            
00268         std::string shortfile = iter->substr( start, end - start + 1 );
00269         FileInPath f1( shortfile );
00270         std::string file = f1.fullPath();
00271 
00272 /*
00273         //
00274         // override what might have be given via the external config
00275         //
00276         std::ostringstream pyCard ;
00277         pyCard << "IMSS(21)=" << fUnitSLHA;
00278         call_pygive( pyCard.str() );
00279         pyCard << "IMSS(22)=" << fUnitSLHA;
00280         call_pygive( pyCard.str() );
00281 
00282         fioopn_( &fUnitSLHA, file.c_str(), file.length() );
00283 */
00284 
00285         openSLHA( file.c_str() );
00286 
00287    }
00288    
00289    return;
00290 }
00291 
00292 void Pythia6Service::setPYUPDAParams(bool afterPyinit)
00293 {
00294    std::string shortfile;
00295    bool write_file = false;
00296    bool usePostPyinit = false;
00297 
00298    //   std::cout<<"=== CALLING setPYUPDAParams === "<<afterPyinit<<" "<<fParamPYUPDA.size()<<std::endl;
00299 
00300    // This assumes that PYUPDAFILE only appears once ...
00301 
00302    for (std::vector<std::string>::const_iterator iter = fParamPYUPDA.begin();
00303                                                  iter != fParamPYUPDA.end(); iter++ )
00304    {
00305      //     std::cout<<"PYUPDA check "<<*iter<<std::endl;
00306         if( iter->find( "PYUPDAFILE", 0 ) != std::string::npos ) {
00307           std::string::size_type start = iter->find_first_of( "=" ) + 1;
00308           std::string::size_type end = iter->length() - 1;
00309           std::string::size_type temp = iter->find_first_of( "'", start );
00310           if( temp != std::string::npos ) {
00311             start = temp + 1;
00312             end = iter->find_last_of( "'" ) - 1;
00313           } 
00314           start = iter->find_first_not_of( " ", start );
00315           end = iter->find_last_not_of( " ", end );
00316           //std::cout << " start, end = " << start << " " << end << std::endl;          
00317           shortfile = iter->substr( start, end - start + 1 );
00318         } else if ( iter->find( "PYUPDAWRITE", 0 ) != std::string::npos ) {
00319           write_file = true;
00320         } else if ( iter->find( "PYUPDApostPYINIT", 0 ) != std::string::npos ) {
00321           usePostPyinit = true;
00322         }
00323    }
00324    
00325    if (!shortfile.empty()) {
00326      std::string file;
00327      if (write_file) {
00328        file = shortfile;
00329      } else {
00330        // If reading, get full path to file and require it to exist.
00331        FileInPath f1( shortfile );
00332        file = f1.fullPath();
00333      }
00334 
00335      if (afterPyinit == usePostPyinit || (write_file && afterPyinit)) {
00336        openPYUPDA( file.c_str(), write_file );
00337      }
00338    }
00339 
00340    return;
00341 }
00342 
00343 void Pythia6Service::setSLHAFromHeader( const std::vector<std::string> &lines )
00344 {
00345 
00346         std::set<std::string> blocks;
00347         unsigned int model = 0, subModel = 0;
00348 
00349         const char *fname = std::tmpnam(NULL);
00350         std::ofstream file(fname, std::fstream::out | std::fstream::trunc);
00351         std::string block;
00352         for(std::vector<std::string>::const_iterator iter = lines.begin();
00353             iter != lines.end(); ++iter) {
00354                 file << *iter;
00355 
00356                 std::string line = *iter;
00357                 std::transform(line.begin(), line.end(),
00358                                line.begin(), (int(*)(int))std::toupper);
00359                 std::string::size_type pos = line.find('#');
00360                 if (pos != std::string::npos)
00361                         line.resize(pos);
00362 
00363                 if (line.empty())
00364                         continue;
00365 
00366                 if (!boost::algorithm::is_space()(line[0])) {
00367                         std::vector<std::string> tokens;
00368                         boost::split(tokens, line,
00369                                      boost::algorithm::is_space(),
00370                                      boost::token_compress_on);
00371                         if (!tokens.size())
00372                                 continue;
00373                         block.clear();
00374                         if (tokens.size() < 2)
00375                                 continue;
00376                         if (tokens[0] == "BLOCK") {
00377                                 block = tokens[1];
00378                                 blocks.insert(block);
00379                                 continue;
00380                         }
00381 
00382                         if (tokens[0] == "DECAY") {
00383                                 block = "DECAY";
00384                                 blocks.insert(block);
00385                         }
00386                 } else if (block == "MODSEL") {
00387                         std::istringstream ss(line);
00388                         ss >> model >> subModel;
00389                 } else if (block == "SMINPUTS") {
00390                         std::istringstream ss(line);
00391                         int index;
00392                         double value;
00393                         ss >> index >> value;
00394                         switch(index) {
00395                             case 1:
00396                                 pydat1_.paru[103 - 1] = 1.0 / value;
00397                                 break;
00398                             case 2:
00399                                 pydat1_.paru[105 - 1] = value;
00400                                 break;
00401                             case 4:
00402                                 pydat2_.pmas[0][23 - 1] = value;
00403                                 break;
00404                             case 6:
00405                                 pydat2_.pmas[0][6 - 1] = value;
00406                                 break;
00407                             case 7:
00408                                 pydat2_.pmas[0][15 - 1] = value;
00409                                 break;
00410                         }
00411                 }
00412         }
00413         file.close();
00414 
00415         if (blocks.count("SMINPUTS"))
00416                 pydat1_.paru[102 - 1] = 0.5 - std::sqrt(0.25 -
00417                         pydat1_.paru[0] * M_SQRT1_2 *
00418                         pydat1_.paru[103 - 1] / pydat1_.paru[105 - 1] /
00419                         (pydat2_.pmas[0][23 - 1] * pydat2_.pmas[0][23 - 1]));
00420 
00421 /*
00422         int unit = 24;
00423         fioopn_(&unit, fname, std::strlen(fname));
00424         std::remove(fname);
00425 
00426         call_pygive("IMSS(21)=24");
00427         call_pygive("IMSS(22)=24");
00428 */
00429         
00430         openSLHA( fname ) ;
00431         std::remove( fname );
00432         
00433         if (model ||
00434             blocks.count("HIGMIX") ||
00435             blocks.count("SBOTMIX") ||
00436             blocks.count("STOPMIX") ||
00437             blocks.count("STAUMIX") ||
00438             blocks.count("AMIX") ||
00439             blocks.count("NMIX") ||
00440             blocks.count("UMIX") ||
00441             blocks.count("VMIX"))
00442                 call_pyslha(1);
00443         if (model ||
00444             blocks.count("QNUMBERS") ||
00445             blocks.count("PARTICLE") ||
00446             blocks.count("MINPAR") ||
00447             blocks.count("EXTPAR") ||
00448             blocks.count("SMINPUTS") ||
00449             blocks.count("SMINPUTS"))
00450                 call_pyslha(0);
00451         if (blocks.count("MASS"))
00452                 call_pyslha(5, 0);
00453         if (blocks.count("DECAY"))
00454                 call_pyslha(2);
00455 
00456       return ;
00457 
00458 }