CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Herwig6Instance.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <sstream>
3 #include <cstdlib>
4 #include <cstring>
5 #include <cctype>
6 #include <string>
7 #include <cassert>
8 
9 #ifdef _POSIX_C_SOURCE
10 #include <sys/time.h>
11 #include <csignal>
12 #include <csetjmp>
13 #endif
14 
15 #include <CLHEP/Random/RandomEngine.h>
16 
17 #include <HepMC/HerwigWrapper.h>
18 
22 
25 
26 #include "params.inc"
27 
28 extern "C" void jminit_();
29 __attribute__((visibility("hidden"))) void dummy() {
30  int dummyInt = 0;
31  jminit_();
32  jimmin_();
33  jminit_();
34  hwmsct_(&dummyInt);
35  jmefin_();
36 }
37 
38 // Added for reading in the paremeter files (orig. L. Sonnenschein)
39 extern "C" void lunread_(const char filename[], const int length);
40 
41 using namespace gen;
42 
43 // implementation for the Fortran callbacks from Herwig
44 
45 // this gets a random number from the currently running instance
46 // so, if the have separate instances for let's say decayers based on
47 // Herwig than the Herwig pp collision instance, we get independent
48 // random numbers. Also true for FastSim, since FastSim uses its own
49 // random numbers. This means FastSim needs take a Herwig6Instance
50 // instance of its own instead of calling into Herwig directly.
51 double gen::hwrgen_(int *idummy) {
52  Herwig6Instance *instance = FortranInstance::getInstance<Herwig6Instance>();
53  assert(instance != nullptr);
54  assert(instance->randomEngine != nullptr);
55  return instance->randomEngine->flat();
56 }
57 
58 void gen::cms_hwwarn_(char fn[6], int *code, int *exit) {
59  std::string function(fn, 6);
60  *exit = FortranInstance::getInstance<Herwig6Instance>()->hwwarn(function, *code);
61 }
62 
63 extern "C" {
64 void hwaend_() {}
65 
66 void cmsending_(int *ecode) {
67  throw cms::Exception("Herwig6Error") << "Herwig6 stopped run with error code " << *ecode << "." << std::endl;
68 }
69 }
70 
72  sigjmp_buf buf;
73 };
74 
75 // Herwig6Instance methods
76 
77 Herwig6Instance::Herwig6Instance() : randomEngine(nullptr), timeoutPrivate() {}
78 
80 
81 // timeout tool
82 
83 #ifdef _POSIX_C_SOURCE
84 // some deep POSIX hackery to catch HERWIG sometimes (O(10k events) with
85 // complicated topologies) getting caught in and endless loop :-(
86 
88  Herwig6Instance *instance = FortranInstance::getInstance<Herwig6Instance>();
89  assert(instance != nullptr);
90  assert(instance->timeoutPrivate);
91  siglongjmp(instance->timeoutPrivate->buf, 1);
92 }
93 
94 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)()) {
95  if (timeoutPrivate)
96  throw cms::Exception("ReentrancyProblem") << "Herwig6Instance::timeout() called recursively." << std::endl;
97  struct sigaction saOld;
98  std::memset(&saOld, 0, sizeof saOld);
99 
100  struct itimerval itv;
101  timerclear(&itv.it_value);
102  timerclear(&itv.it_interval);
103  itv.it_value.tv_sec = 0;
104  itv.it_interval.tv_sec = 0;
105  setitimer(ITIMER_VIRTUAL, &itv, nullptr);
106 
107  sigset_t ss;
108  sigemptyset(&ss);
109  sigaddset(&ss, SIGVTALRM);
110 
111  sigprocmask(SIG_UNBLOCK, &ss, nullptr);
112  sigprocmask(SIG_BLOCK, &ss, nullptr);
113 
114  timeoutPrivate = std::make_unique<TimeoutHolder>();
115  if (sigsetjmp(timeoutPrivate->buf, 1)) {
116  timeoutPrivate.reset();
117 
118  itv.it_value.tv_sec = 0;
119  itv.it_interval.tv_sec = 0;
120  setitimer(ITIMER_VIRTUAL, &itv, nullptr);
121  sigprocmask(SIG_UNBLOCK, &ss, nullptr);
122  return true;
123  }
124 
125  itv.it_value.tv_sec = secs;
126  itv.it_interval.tv_sec = secs;
127  setitimer(ITIMER_VIRTUAL, &itv, nullptr);
128 
129  struct sigaction sa;
130  std::memset(&sa, 0, sizeof sa);
131  sa.sa_handler = &Herwig6Instance::_timeout_sighandler;
132  sa.sa_flags = SA_ONESHOT;
133  sigemptyset(&sa.sa_mask);
134 
135  sigaction(SIGVTALRM, &sa, &saOld);
136  sigprocmask(SIG_UNBLOCK, &ss, nullptr);
137 
138  try {
139  fn();
140  } catch (...) {
141  timeoutPrivate.reset();
142 
143  itv.it_value.tv_sec = 0;
144  itv.it_interval.tv_sec = 0;
145  setitimer(ITIMER_VIRTUAL, &itv, nullptr);
146 
147  sigaction(SIGVTALRM, &saOld, nullptr);
148 
149  throw;
150  }
151 
152  timeoutPrivate.reset();
153 
154  itv.it_value.tv_sec = 0;
155  itv.it_interval.tv_sec = 0;
156  setitimer(ITIMER_VIRTUAL, &itv, nullptr);
157 
158  sigaction(SIGVTALRM, &saOld, nullptr);
159 
160  return false;
161 }
162 #else
163 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)()) {
164  fn();
165  return false;
166 }
167 #endif
168 
169 bool Herwig6Instance::hwwarn(const std::string &fn, int code) { return false; }
170 
171 // regular Herwig6Instance methods
172 
174  typedef std::istringstream::traits_type traits;
175 
176  const char *p = line.c_str(), *q;
177  p += std::strspn(p, " \t\r\n");
178 
179  for (q = p; std::isalnum(*q); q++)
180  ;
181  std::string name(p, q - p);
182 
183  const ConfigParam *param;
184  for (param = configParams; param->name; param++)
185  if (name == param->name)
186  break;
187  if (!param->name)
188  return false;
189 
190  p = q + std::strspn(q, " \t\r\n");
191 
192  std::size_t pos = 0;
193  std::size_t mult = 1;
194  for (unsigned int i = 0; i < 3; i++) {
195  if (!param->dim[i].size)
196  break;
197 
198  if (*p++ != (i ? ',' : '('))
199  return false;
200 
201  p += std::strspn(p, " \t\r\n");
202 
203  for (q = p; std::isdigit(*q); q++)
204  ;
205  std::istringstream ss(std::string(p, q - p));
206  std::size_t index;
207  ss >> index;
208  if (ss.bad() || ss.peek() != traits::eof())
209  return false;
210 
211  if (index < param->dim[i].offset)
212  return false;
213  index -= param->dim[i].offset;
214  if (index >= param->dim[i].size)
215  return false;
216 
217  p = q + std::strspn(q, " \t\r\n");
218 
219  pos += mult * index;
220  mult *= param->dim[i].size;
221  }
222 
223  if (param->dim[0].size) {
224  if (*p++ != ')')
225  return false;
226  p += std::strspn(p, " \t\r\n");
227  }
228 
229  if (*p++ != '=')
230  return false;
231  p += std::strspn(p, " \t\r\n");
232 
233  for (q = p; *q && (std::isalnum(*q) || std::strchr(".-+", *q)); q++)
234  ;
235  std::istringstream ss(std::string(p, q - p));
236 
237  p = q + std::strspn(q, " \t\r\n");
238  if (*p && *p != '!')
239  return false;
240 
241  switch (param->type) {
242  case kInt: {
243  int value;
244  ss >> value;
245  if (ss.bad() || ss.peek() != traits::eof())
246  return false;
247 
248  ((int *)param->ptr)[pos] = value;
249  break;
250  }
251  case kDouble: {
252  double value;
253  ss >> value;
254  if (ss.bad() || ss.peek() != traits::eof())
255  return false;
256 
257  ((double *)param->ptr)[pos] = value;
258  break;
259  }
260  case kLogical: {
261  std::string value_;
262  ss >> value_;
263  if (ss.bad() || ss.peek() != traits::eof())
264  return false;
265 
266  for (std::string::iterator iter = value_.begin(); iter != value_.end(); ++iter)
267  *iter = std::tolower(*iter);
268  bool value;
269  if (value_ == "yes" || value_ == "true" || value_ == "1")
270  value = true;
271  else if (value_ == "no" || value_ == "false" || value_ == "0")
272  value = false;
273  else
274  return false;
275 
276  ((int *)param->ptr)[pos] = value;
277  break;
278  }
279  }
280 
281  return true;
282 }
283 
285  edm::FileInPath fileAndPath(fileName);
286  // WARING : This will call HWWARN if file does not exist.
287  lunread_(fileAndPath.fullPath().c_str(), strlen(fileAndPath.fullPath().c_str()));
288 
289  return;
290 }
CLHEP::HepRandomEngine * randomEngine
Definition: Dummies.cc:7
static PFTauRenderPlugin instance
void jmefin_(void)
bool timeout(unsigned int secs, void(*fn)())
static void _timeout_sighandler(int signr)
void openParticleSpecFile(const std::string fileName)
assert(be >=bs)
double p[5][pyjets_maxn]
void jminit_(void)
float __attribute__((vector_size(8))) cms_float32x2_t
Definition: ExtVec.h:12
void cmsending_(int *ecode)
Definition: Dummies.cc:12
void hwaend_()
Definition: Dummies.cc:10
bool give(const std::string &line)
void jimmin_(void)
void cms_hwwarn_(char fn[6], int *, int *)
double hwmsct_(int *)
virtual bool hwwarn(const std::string &fn, int code)
tuple filename
Definition: lut2db_cfg.py:20
CLHEP::HepRandomEngine * randomEngine
void lunread_(const char filename[], const int length)
std::string fullPath() const
Definition: FileInPath.cc:161
double hwrgen_(int *)
std::unique_ptr< TimeoutHolder > timeoutPrivate