CMS 3D CMS Logo

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