CMS 3D CMS Logo

Pythia6Service.cc
Go to the documentation of this file.
1 #include <algorithm>
2 #include <functional>
3 #include <iostream>
4 #include <sstream>
5 #include <fstream>
6 #include <cmath>
7 #include <string>
8 #include <set>
9 
10 #include <boost/bind.hpp>
11 #include <boost/algorithm/string/classification.hpp>
12 #include <boost/algorithm/string/split.hpp>
13 #include <boost/filesystem.hpp>
14 
15 #include "CLHEP/Random/RandomEngine.h"
16 
18 
21 
24 // #include "GeneratorInterface/Core/interface/ParameterCollector.h"
25 
26 // This will force the symbols below to be kept, even in the case pythia6
27 // is an archive library.
28 //extern "C" void pyexec_(void);
29 extern "C" void pyedit_(void);
30 __attribute__((visibility("hidden"))) void dummy()
31 {
32  using namespace gen;
33  int dummy = 0;
34  double dummy2 = 0;
35  char * dummy3 = nullptr;
36  pyexec_();
37  pystat_(nullptr);
38  pyjoin_(dummy, &dummy);
39  py1ent_(dummy, dummy, dummy2, dummy2, dummy2);
40  pygive_(dummy3, dummy);
41  pycomp_(dummy);
42  pylist_(nullptr);
43  pyevnt_();
44  pyedit_();
45 }
46 
47 extern "C"
48 {
49  void fioopn_( int* unit, const char* line, int length );
50  void fioopnw_( int* unit, const char* line, int length );
51  void fiocls_( int* unit );
52  void pyslha_( int*, int*, int* );
53  static int call_pyslha(int mupda, int kforig = 0)
54  {
55  int iretrn = 0;
56  pyslha_(&mupda, &kforig, &iretrn);
57  return iretrn;
58  }
59 
60  void pyupda_(int*, int*);
61  static void call_pyupda( int opt, int iunit ){
62  pyupda_( &opt, &iunit );
63  }
64 
65  double gen::pyr_(int *idummy)
66  {
67  // getInstance will throw if no one used enter/leave
68  // or this is the wrong caller class, like e.g. Herwig6Instance
69  Pythia6Service* service = FortranInstance::getInstance<Pythia6Service>();
70  return service->fRandomEngine->flat();
71  }
72 }
73 
74 using namespace gen;
75 using namespace edm;
76 
78 
80  : fRandomEngine(nullptr), fUnitSLHA(24), fUnitPYUPDA(25)
81 {
82 }
83 
85  : fRandomEngine(nullptr), fUnitSLHA(24), fUnitPYUPDA(25)
86 {
87  if (fPythia6Owner)
88  throw cms::Exception("PythiaError") <<
89  "Two Pythia6Service instances claiming Pythia6 ownership." <<
90  std::endl;
91 
92  fPythia6Owner = this;
93 
94 /*
95  ParameterCollector collector(ps.getParameter<edm::ParameterSet>("PythiaParameters"));
96 
97  fParamGeneral.clear();
98  fParamCSA.clear();
99  fParamSLHA.clear();
100 
101  fParamGeneral = std::vector<std::string>(collector.begin(), collector.end());
102  fParamCSA = std::vector<std::string>(collector.begin("CSAParameters"), collector.end());
103  fParamSLHA = std::vector<std::string>(collector.begin("SLHAParameters"), collector.end());
104 */
105 
106 
107  // Set PYTHIA parameters in a single ParameterSet
108  //
109  edm::ParameterSet pythia_params =
110  ps.getParameter<edm::ParameterSet>("PythiaParameters") ;
111 
112  // read and sort Pythia6 cards
113  //
114  std::vector<std::string> setNames =
115  pythia_params.getParameter<std::vector<std::string> >("parameterSets");
116 
117  // std::vector<std::string> paramLines;
118  fParamGeneral.clear();
119  fParamCSA.clear();
120  fParamSLHA.clear();
121  fParamPYUPDA.clear();
122 
123 
124  for(std::vector<std::string>::const_iterator iter = setNames.begin();
125  iter != setNames.end(); ++iter)
126  {
127  std::vector<std::string> lines =
128  pythia_params.getParameter< std::vector<std::string> >(*iter);
129 
130  for(std::vector<std::string>::const_iterator line = lines.begin();
131  line != lines.end(); ++line )
132  {
133  if (line->substr(0, 7) == "MRPY(1)")
134  throw cms::Exception("PythiaError") <<
135  "Attempted to set random number"
136  " using Pythia command 'MRPY(1)'."
137  " Please use the"
138  " RandomNumberGeneratorService." <<
139  std::endl;
140 
141  if ( *iter == "CSAParameters" )
142  {
143  fParamCSA.push_back(*line);
144  }
145  else if ( *iter == "SLHAParameters" )
146  {
147  fParamSLHA.push_back(*line);
148  }
149  else if ( *iter == "PYUPDAParameters" )
150  {
151  fParamPYUPDA.push_back(*line);
152  }
153  else
154  {
155  fParamGeneral.push_back(*line);
156  }
157  }
158  }
159 }
160 
162 {
163  if (fPythia6Owner == this)
164  fPythia6Owner = nullptr;
165 
166  fParamGeneral.clear();
167  fParamCSA.clear();
168  fParamSLHA.clear();
169  fParamPYUPDA.clear();
170 }
171 
173 {
175 
176  if (!fPythia6Owner) {
177  edm::LogInfo("Generator|Pythia6Interface") <<
178  "gen::Pythia6Service is going to initialise Pythia, as no other "
179  "instace has done so yet, and Pythia service routines have been "
180  "requested by a dummy instance." << std::endl;
181 
182  call_pygive("MSTU(12)=12345");
183  call_pyinit("NONE", "", "", 0.0);
184 
185  fPythia6Owner = this;
186  }
187 }
188 
190 {
191  // now pass general config cards
192  //
193  for(std::vector<std::string>::const_iterator iter = fParamGeneral.begin();
194  iter != fParamGeneral.end(); ++iter)
195  {
196  if (!call_pygive(*iter))
197  throw cms::Exception("PythiaError")
198  << "Pythia did not accept \""
199  << *iter << "\"." << std::endl;
200  }
201 
202  return ;
203 }
204 
206 {
207 #define SETCSAPARBUFSIZE 514
208  char buf[SETCSAPARBUFSIZE];
209 
210  txgive_init_();
211  for(std::vector<std::string>::const_iterator iter = fParamCSA.begin();
212  iter != fParamCSA.end(); ++iter)
213  {
214  // Null pad the string should not be needed because it uses
215  // read, which will look for \n, but just in case...
216  for (size_t i = 0; i < SETCSAPARBUFSIZE; ++i)
217  buf[i] = ' ';
218  // Skip empty parameters.
219  if (iter->length() <= 0)
220  continue;
221  // Limit the size of the string to something which fits the buffer.
222  size_t maxSize = iter->length() > (SETCSAPARBUFSIZE-2) ? (SETCSAPARBUFSIZE-2) : iter->length();
223  strncpy(buf, iter->c_str(), maxSize);
224  // Add extra \n if missing, otherwise "read" continues reading.
225  if (buf[maxSize-1] != '\n')
226  {
227  buf[maxSize] = '\n';
228  // Null terminate in case the string is passed back to C.
229  // Not sure that is actually needed.
230  buf[maxSize + 1] = 0;
231  }
232  txgive_(buf, iter->length() );
233  }
234 
235  return ;
236 #undef SETCSAPARBUFSIZE
237 }
238 
239 void Pythia6Service::openSLHA( const char* file )
240 {
241 
242  std::ostringstream pyCard1 ;
243  pyCard1 << "IMSS(21)=" << fUnitSLHA;
244  call_pygive( pyCard1.str() );
245  std::ostringstream pyCard2 ;
246  pyCard2 << "IMSS(22)=" << fUnitSLHA;
247  call_pygive( pyCard2.str() );
248 
249  fioopn_( &fUnitSLHA, file, strlen(file) );
250 
251  return;
252 
253 }
254 
255 void Pythia6Service::openPYUPDA( const char* file, bool write_file )
256 {
257 
258  if (write_file) {
259  std::cout<<"=== WRITING PYUPDA FILE "<<file<<" ==="<<std::endl;
260  fioopnw_( &fUnitPYUPDA, file, strlen(file) );
261  // Write Pythia particle table to this card file.
263  } else {
264  std::cout<<"=== READING PYUPDA FILE "<<file<<" ==="<<std::endl;
265  fioopn_( &fUnitPYUPDA, file, strlen(file) );
266  // Update Pythia particle table with this card file.
268  }
269 
270  return;
271 
272 }
273 
275 {
276 
277  fiocls_(&fUnitSLHA);
278 
279  return;
280 }
281 
283 {
284 
286 
287  return;
288 
289 }
290 
292 {
293  for (std::vector<std::string>::const_iterator iter = fParamSLHA.begin();
294  iter != fParamSLHA.end(); iter++ )
295  {
296 
297  if( iter->find( "SLHAFILE", 0 ) == std::string::npos ) continue;
298  std::string::size_type start = iter->find_first_of( "=" ) + 1;
299  std::string::size_type end = iter->length() - 1;
300  std::string::size_type temp = iter->find_first_of( "'", start );
301  if( temp != std::string::npos ) {
302  start = temp + 1;
303  end = iter->find_last_of( "'" ) - 1;
304  }
305  start = iter->find_first_not_of( " ", start );
306  end = iter->find_last_not_of( " ", end );
307  //std::cout << " start, end = " << start << " " << end << std::endl;
308  std::string shortfile = iter->substr( start, end - start + 1 );
309  FileInPath f1( shortfile );
310  std::string file = f1.fullPath();
311 
312 /*
313  //
314  // override what might have be given via the external config
315  //
316  std::ostringstream pyCard ;
317  pyCard << "IMSS(21)=" << fUnitSLHA;
318  call_pygive( pyCard.str() );
319  pyCard << "IMSS(22)=" << fUnitSLHA;
320  call_pygive( pyCard.str() );
321 
322  fioopn_( &fUnitSLHA, file.c_str(), file.length() );
323 */
324 
325  openSLHA( file.c_str() );
326 
327  }
328 
329  return;
330 }
331 
332 void Pythia6Service::setPYUPDAParams(bool afterPyinit)
333 {
334  std::string shortfile;
335  bool write_file = false;
336  bool usePostPyinit = false;
337 
338  // std::cout<<"=== CALLING setPYUPDAParams === "<<afterPyinit<<" "<<fParamPYUPDA.size()<<std::endl;
339 
340  // This assumes that PYUPDAFILE only appears once ...
341 
342  for (std::vector<std::string>::const_iterator iter = fParamPYUPDA.begin();
343  iter != fParamPYUPDA.end(); iter++ )
344  {
345  // std::cout<<"PYUPDA check "<<*iter<<std::endl;
346  if( iter->find( "PYUPDAFILE", 0 ) != std::string::npos ) {
347  std::string::size_type start = iter->find_first_of( "=" ) + 1;
348  std::string::size_type end = iter->length() - 1;
349  std::string::size_type temp = iter->find_first_of( "'", start );
350  if( temp != std::string::npos ) {
351  start = temp + 1;
352  end = iter->find_last_of( "'" ) - 1;
353  }
354  start = iter->find_first_not_of( " ", start );
355  end = iter->find_last_not_of( " ", end );
356  //std::cout << " start, end = " << start << " " << end << std::endl;
357  shortfile = iter->substr( start, end - start + 1 );
358  } else if ( iter->find( "PYUPDAWRITE", 0 ) != std::string::npos ) {
359  write_file = true;
360  } else if ( iter->find( "PYUPDApostPYINIT", 0 ) != std::string::npos ) {
361  usePostPyinit = true;
362  }
363  }
364 
365  if (!shortfile.empty()) {
367  if (write_file) {
368  file = shortfile;
369  } else {
370  // If reading, get full path to file and require it to exist.
371  FileInPath f1( shortfile );
372  file = f1.fullPath();
373  }
374 
375  if (afterPyinit == usePostPyinit || (write_file && afterPyinit)) {
376  openPYUPDA( file.c_str(), write_file );
377  }
378  }
379 
380  return;
381 }
382 
383 void Pythia6Service::setSLHAFromHeader( const std::vector<std::string> &lines )
384 {
385  std::set<std::string> blocks;
386  unsigned int model = 0, subModel = 0;
387 
388  std::string fnamest = boost::filesystem::unique_path().string();
389  const char *fname = fnamest.c_str();
390  std::ofstream file(fname, std::fstream::out | std::fstream::trunc);
392  for(std::vector<std::string>::const_iterator iter = lines.begin();
393  iter != lines.end(); ++iter) {
394  file << *iter;
395 
396  std::string line = *iter;
397  std::transform(line.begin(), line.end(),
398  line.begin(), (int(*)(int))std::toupper);
399  std::string::size_type pos = line.find('#');
400  if (pos != std::string::npos)
401  line.resize(pos);
402 
403  if (line.empty())
404  continue;
405 
406  if (!boost::algorithm::is_space()(line[0])) {
407  std::vector<std::string> tokens;
408  boost::split(tokens, line,
409  boost::algorithm::is_space(),
410  boost::token_compress_on);
411  if (tokens.empty())
412  continue;
413  block.clear();
414  if (tokens.size() < 2)
415  continue;
416  if (tokens[0] == "BLOCK") {
417  block = tokens[1];
418  blocks.insert(block);
419  continue;
420  }
421 
422  if (tokens[0] == "DECAY") {
423  block = "DECAY";
424  blocks.insert(block);
425  }
426  } else if (block == "MODSEL") {
427  std::istringstream ss(line);
428  ss >> model >> subModel;
429  } else if (block == "SMINPUTS") {
430  std::istringstream ss(line);
431  int index;
432  double value;
433  ss >> index >> value;
434  switch(index) {
435  case 1:
436  pydat1_.paru[103 - 1] = 1.0 / value;
437  break;
438  case 2:
439  pydat1_.paru[105 - 1] = value;
440  break;
441  case 4:
442  pydat2_.pmas[0][23 - 1] = value;
443  break;
444  case 6:
445  pydat2_.pmas[0][6 - 1] = value;
446  break;
447  case 7:
448  pydat2_.pmas[0][15 - 1] = value;
449  break;
450  }
451  }
452  }
453  file.close();
454 
455  if (blocks.count("SMINPUTS"))
456  pydat1_.paru[102 - 1] = 0.5 - std::sqrt(0.25 -
457  pydat1_.paru[0] * M_SQRT1_2 *
458  pydat1_.paru[103 - 1] / pydat1_.paru[105 - 1] /
459  (pydat2_.pmas[0][23 - 1] * pydat2_.pmas[0][23 - 1]));
460 
461 /*
462  int unit = 24;
463  fioopn_(&unit, fname, std::strlen(fname));
464  std::remove(fname);
465 
466  call_pygive("IMSS(21)=24");
467  call_pygive("IMSS(22)=24");
468 */
469 
470  openSLHA( fname ) ;
471  std::remove( fname );
472 
473  if (model ||
474  blocks.count("HIGMIX") ||
475  blocks.count("SBOTMIX") ||
476  blocks.count("STOPMIX") ||
477  blocks.count("STAUMIX") ||
478  blocks.count("AMIX") ||
479  blocks.count("NMIX") ||
480  blocks.count("UMIX") ||
481  blocks.count("VMIX"))
482  call_pyslha(1);
483  if (model ||
484  blocks.count("QNUMBERS") ||
485  blocks.count("PARTICLE") ||
486  blocks.count("MINPAR") ||
487  blocks.count("EXTPAR") ||
488  blocks.count("SMINPUTS") ||
489  blocks.count("SMINPUTS"))
490  call_pyslha(0);
491  if (blocks.count("MASS"))
492  call_pyslha(5, 0);
493  if (blocks.count("DECAY"))
494  call_pyslha(2);
495 
496  return ;
497 
498 }
Definition: start.py:1
T getParameter(std::string const &) const
static void call_pyupda(int opt, int iunit)
__attribute__((visibility("hidden"))) void dummy()
void pyedit_(void)
void pyupda_(int *, int *)
void fioopn_(int *unit, const char *line, int length)
struct gen::@665 pydat1_
void fiocls_(int *unit)
void enter() override
bool call_pygive(const std::string &line)
void pyjoin_(int &njoin, int ijoin[])
void pylist_(int *)
#define nullptr
uint16_t size_type
void pygive_(const char *, int)
return((rh^lh)&mask)
void fioopnw_(int *unit, const char *line, int length)
void pyslha_(int *, int *, int *)
T sqrt(T t)
Definition: SSEVec.h:18
void setSLHAFromHeader(const std::vector< std::string > &lines)
~Pythia6Service() override
std::vector< std::string > fParamPYUPDA
static int call_pyslha(int mupda, int kforig=0)
virtual void enter()
void setPYUPDAParams(bool afterPyinit)
#define end
Definition: vmac.h:39
std::vector< std::string > fParamGeneral
static Pythia6Service * fPythia6Owner
#define SETCSAPARBUFSIZE
void txgive_init_(void)
int pycomp_(int &)
CLHEP::HepRandomEngine * fRandomEngine
std::vector< std::string > fParamCSA
void openSLHA(const char *)
def remove(d, key, TELL=False)
Definition: MatrixUtil.py:211
string fname
main script
void py1ent_(int &ip, int &kf, double &pe, double &the, double &phi)
HLT enums.
void openPYUPDA(const char *, bool write_file)
std::string fullPath() const
Definition: FileInPath.cc:197
std::vector< std::string > fParamSLHA
double pyr_(int *idummy)
void txgive_(const char *, int)
double split
Definition: MVATrainer.cc:139
void pyexec_()