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
00026
00027
00028
00029
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
00069
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
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 edm::ParameterSet pythia_params =
00111 ps.getParameter<edm::ParameterSet>("PythiaParameters") ;
00112
00113
00114
00115 std::vector<std::string> setNames =
00116 pythia_params.getParameter<std::vector<std::string> >("parameterSets");
00117
00118
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
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 #define SETCSAPARBUFSIZE 514
00209 char buf[SETCSAPARBUFSIZE];
00210
00211 txgive_init_();
00212 for(std::vector<std::string>::const_iterator iter = fParamCSA.begin();
00213 iter != fParamCSA.end(); ++iter)
00214 {
00215
00216
00217 for (size_t i = 0; i < SETCSAPARBUFSIZE; ++i)
00218 buf[i] = ' ';
00219
00220 if (iter->length() <= 0)
00221 continue;
00222
00223 size_t maxSize = iter->length() > (SETCSAPARBUFSIZE-2) ? (SETCSAPARBUFSIZE-2) : iter->length();
00224 strncpy(buf, iter->c_str(), maxSize);
00225
00226 if (buf[maxSize-1] != '\n')
00227 {
00228 buf[maxSize] = '\n';
00229
00230
00231 buf[maxSize + 1] = 0;
00232 }
00233 txgive_(buf, iter->length() );
00234 }
00235
00236 return ;
00237 #undef SETCSAPARBUFSIZE
00238 }
00239
00240 void Pythia6Service::openSLHA( const char* file )
00241 {
00242
00243 std::ostringstream pyCard1 ;
00244 pyCard1 << "IMSS(21)=" << fUnitSLHA;
00245 call_pygive( pyCard1.str() );
00246 std::ostringstream pyCard2 ;
00247 pyCard2 << "IMSS(22)=" << fUnitSLHA;
00248 call_pygive( pyCard2.str() );
00249
00250 fioopn_( &fUnitSLHA, file, strlen(file) );
00251
00252 return;
00253
00254 }
00255
00256 void Pythia6Service::openPYUPDA( const char* file, bool write_file )
00257 {
00258
00259 if (write_file) {
00260 std::cout<<"=== WRITING PYUPDA FILE "<<file<<" ==="<<std::endl;
00261 fioopnw_( &fUnitPYUPDA, file, strlen(file) );
00262
00263 call_pyupda(1, fUnitPYUPDA);
00264 } else {
00265 std::cout<<"=== READING PYUPDA FILE "<<file<<" ==="<<std::endl;
00266 fioopn_( &fUnitPYUPDA, file, strlen(file) );
00267
00268 call_pyupda(3, fUnitPYUPDA);
00269 }
00270
00271 return;
00272
00273 }
00274
00275 void Pythia6Service::closeSLHA()
00276 {
00277
00278 fiocls_(&fUnitSLHA);
00279
00280 return;
00281 }
00282
00283 void Pythia6Service::closePYUPDA()
00284 {
00285
00286 fiocls_(&fUnitPYUPDA);
00287
00288 return;
00289
00290 }
00291
00292 void Pythia6Service::setSLHAParams()
00293 {
00294 for (std::vector<std::string>::const_iterator iter = fParamSLHA.begin();
00295 iter != fParamSLHA.end(); iter++ )
00296 {
00297
00298 if( iter->find( "SLHAFILE", 0 ) == std::string::npos ) continue;
00299 std::string::size_type start = iter->find_first_of( "=" ) + 1;
00300 std::string::size_type end = iter->length() - 1;
00301 std::string::size_type temp = iter->find_first_of( "'", start );
00302 if( temp != std::string::npos ) {
00303 start = temp + 1;
00304 end = iter->find_last_of( "'" ) - 1;
00305 }
00306 start = iter->find_first_not_of( " ", start );
00307 end = iter->find_last_not_of( " ", end );
00308
00309 std::string shortfile = iter->substr( start, end - start + 1 );
00310 FileInPath f1( shortfile );
00311 std::string file = f1.fullPath();
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 openSLHA( file.c_str() );
00327
00328 }
00329
00330 return;
00331 }
00332
00333 void Pythia6Service::setPYUPDAParams(bool afterPyinit)
00334 {
00335 std::string shortfile;
00336 bool write_file = false;
00337 bool usePostPyinit = false;
00338
00339
00340
00341
00342
00343 for (std::vector<std::string>::const_iterator iter = fParamPYUPDA.begin();
00344 iter != fParamPYUPDA.end(); iter++ )
00345 {
00346
00347 if( iter->find( "PYUPDAFILE", 0 ) != std::string::npos ) {
00348 std::string::size_type start = iter->find_first_of( "=" ) + 1;
00349 std::string::size_type end = iter->length() - 1;
00350 std::string::size_type temp = iter->find_first_of( "'", start );
00351 if( temp != std::string::npos ) {
00352 start = temp + 1;
00353 end = iter->find_last_of( "'" ) - 1;
00354 }
00355 start = iter->find_first_not_of( " ", start );
00356 end = iter->find_last_not_of( " ", end );
00357
00358 shortfile = iter->substr( start, end - start + 1 );
00359 } else if ( iter->find( "PYUPDAWRITE", 0 ) != std::string::npos ) {
00360 write_file = true;
00361 } else if ( iter->find( "PYUPDApostPYINIT", 0 ) != std::string::npos ) {
00362 usePostPyinit = true;
00363 }
00364 }
00365
00366 if (!shortfile.empty()) {
00367 std::string file;
00368 if (write_file) {
00369 file = shortfile;
00370 } else {
00371
00372 FileInPath f1( shortfile );
00373 file = f1.fullPath();
00374 }
00375
00376 if (afterPyinit == usePostPyinit || (write_file && afterPyinit)) {
00377 openPYUPDA( file.c_str(), write_file );
00378 }
00379 }
00380
00381 return;
00382 }
00383
00384 void Pythia6Service::setSLHAFromHeader( const std::vector<std::string> &lines )
00385 {
00386
00387 std::set<std::string> blocks;
00388 unsigned int model = 0, subModel = 0;
00389
00390 const char *fname = std::tmpnam(NULL);
00391 std::ofstream file(fname, std::fstream::out | std::fstream::trunc);
00392 std::string block;
00393 for(std::vector<std::string>::const_iterator iter = lines.begin();
00394 iter != lines.end(); ++iter) {
00395 file << *iter;
00396
00397 std::string line = *iter;
00398 std::transform(line.begin(), line.end(),
00399 line.begin(), (int(*)(int))std::toupper);
00400 std::string::size_type pos = line.find('#');
00401 if (pos != std::string::npos)
00402 line.resize(pos);
00403
00404 if (line.empty())
00405 continue;
00406
00407 if (!boost::algorithm::is_space()(line[0])) {
00408 std::vector<std::string> tokens;
00409 boost::split(tokens, line,
00410 boost::algorithm::is_space(),
00411 boost::token_compress_on);
00412 if (!tokens.size())
00413 continue;
00414 block.clear();
00415 if (tokens.size() < 2)
00416 continue;
00417 if (tokens[0] == "BLOCK") {
00418 block = tokens[1];
00419 blocks.insert(block);
00420 continue;
00421 }
00422
00423 if (tokens[0] == "DECAY") {
00424 block = "DECAY";
00425 blocks.insert(block);
00426 }
00427 } else if (block == "MODSEL") {
00428 std::istringstream ss(line);
00429 ss >> model >> subModel;
00430 } else if (block == "SMINPUTS") {
00431 std::istringstream ss(line);
00432 int index;
00433 double value;
00434 ss >> index >> value;
00435 switch(index) {
00436 case 1:
00437 pydat1_.paru[103 - 1] = 1.0 / value;
00438 break;
00439 case 2:
00440 pydat1_.paru[105 - 1] = value;
00441 break;
00442 case 4:
00443 pydat2_.pmas[0][23 - 1] = value;
00444 break;
00445 case 6:
00446 pydat2_.pmas[0][6 - 1] = value;
00447 break;
00448 case 7:
00449 pydat2_.pmas[0][15 - 1] = value;
00450 break;
00451 }
00452 }
00453 }
00454 file.close();
00455
00456 if (blocks.count("SMINPUTS"))
00457 pydat1_.paru[102 - 1] = 0.5 - std::sqrt(0.25 -
00458 pydat1_.paru[0] * M_SQRT1_2 *
00459 pydat1_.paru[103 - 1] / pydat1_.paru[105 - 1] /
00460 (pydat2_.pmas[0][23 - 1] * pydat2_.pmas[0][23 - 1]));
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 openSLHA( fname ) ;
00472 std::remove( fname );
00473
00474 if (model ||
00475 blocks.count("HIGMIX") ||
00476 blocks.count("SBOTMIX") ||
00477 blocks.count("STOPMIX") ||
00478 blocks.count("STAUMIX") ||
00479 blocks.count("AMIX") ||
00480 blocks.count("NMIX") ||
00481 blocks.count("UMIX") ||
00482 blocks.count("VMIX"))
00483 call_pyslha(1);
00484 if (model ||
00485 blocks.count("QNUMBERS") ||
00486 blocks.count("PARTICLE") ||
00487 blocks.count("MINPAR") ||
00488 blocks.count("EXTPAR") ||
00489 blocks.count("SMINPUTS") ||
00490 blocks.count("SMINPUTS"))
00491 call_pyslha(0);
00492 if (blocks.count("MASS"))
00493 call_pyslha(5, 0);
00494 if (blocks.count("DECAY"))
00495 call_pyslha(2);
00496
00497 return ;
00498
00499 }