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 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
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
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
00243 call_pyupda(1, fUnitPYUPDA);
00244 } else {
00245 std::cout<<"=== READING PYUPDA FILE "<<file<<" ==="<<std::endl;
00246 fioopn_( &fUnitPYUPDA, file, strlen(file) );
00247
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
00289 std::string shortfile = iter->substr( start, end - start + 1 );
00290 FileInPath f1( shortfile );
00291 std::string file = f1.fullPath();
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
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
00320
00321
00322
00323 for (std::vector<std::string>::const_iterator iter = fParamPYUPDA.begin();
00324 iter != fParamPYUPDA.end(); iter++ )
00325 {
00326
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
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
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
00444
00445
00446
00447
00448
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 }