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