CMS 3D CMS Logo

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