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 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
00048
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
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 edm::ParameterSet pythia_params =
00090 ps.getParameter<edm::ParameterSet>("PythiaParameters") ;
00091
00092
00093
00094 std::vector<std::string> setNames =
00095 pythia_params.getParameter<std::vector<std::string> >("parameterSets");
00096
00097
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
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
00222 call_pyupda(1, fUnitPYUPDA);
00223 } else {
00224 std::cout<<"=== READING PYUPDA FILE "<<file<<" ==="<<std::endl;
00225 fioopn_( &fUnitPYUPDA, file, strlen(file) );
00226
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
00268 std::string shortfile = iter->substr( start, end - start + 1 );
00269 FileInPath f1( shortfile );
00270 std::string file = f1.fullPath();
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
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
00299
00300
00301
00302 for (std::vector<std::string>::const_iterator iter = fParamPYUPDA.begin();
00303 iter != fParamPYUPDA.end(); iter++ )
00304 {
00305
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
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
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
00423
00424
00425
00426
00427
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 }