CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/GeneratorInterface/Herwig6Interface/src/Herwig6Instance.cc

Go to the documentation of this file.
00001 #include <iostream>
00002 #include <sstream>
00003 #include <cstdlib>
00004 #include <cstring>
00005 #include <cctype>
00006 #include <string>
00007 
00008 #ifdef _POSIX_C_SOURCE
00009 #       include <sys/time.h>
00010 #       include <signal.h>
00011 #       include <setjmp.h>
00012 #endif
00013 
00014 #include <CLHEP/Random/RandomEngine.h>
00015 
00016 #include <HepMC/HerwigWrapper6_4.h>
00017 
00018 #include "FWCore/Utilities/interface/Exception.h"
00019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00020 
00021 #include "GeneratorInterface/Core/interface/RNDMEngineAccess.h"
00022 
00023 #include "GeneratorInterface/Herwig6Interface/interface/herwig.h"
00024 #include "GeneratorInterface/Herwig6Interface/interface/Herwig6Instance.h"
00025 
00026 #include "params.inc"
00027 
00028 extern "C" void jminit_();
00029 __attribute__((visibility("hidden"))) void dummy()
00030 {
00031   int dummyInt = 0;
00032   jminit_();
00033   jimmin_();
00034   jminit_();
00035   hwmsct_(&dummyInt);
00036   jmefin_();
00037 }
00038 
00039 using namespace gen;
00040 
00041 // implementation for the Fortran callbacks from Herwig
00042 
00043 // this gets a random number from the currently running instance
00044 // so, if the have separate instances for let's say decayers based on
00045 // Herwig than the Herwig pp collision instance, we get independent
00046 // random numbers.  Also true for FastSim, since FastSim uses its own
00047 // random numbers.  This means FastSim needs take a Herwig6Instance
00048 // instance of its own instead of calling into Herwig directly.
00049 double gen::hwrgen_(int *idummy)
00050 { return FortranInstance::getInstance<Herwig6Instance>()->randomEngine->flat(); }
00051 
00052 void gen::cms_hwwarn_(char fn[6], int *code, int *exit)
00053 {
00054         std::string function(fn, fn + sizeof fn);
00055         *exit = FortranInstance::getInstance<Herwig6Instance>()->hwwarn(function, *code);
00056 }
00057 
00058 extern "C" {
00059         void hwaend_()
00060         {}
00061 
00062         void cmsending_(int *ecode)
00063         {
00064                 throw cms::Exception("Herwig6Error")
00065                         << "Herwig6 stopped run with error code " << *ecode
00066                         << "." << std::endl;
00067         }
00068 }
00069 
00070 // Herwig6Instance methods
00071 
00072 Herwig6Instance::Herwig6Instance(CLHEP::HepRandomEngine *randomEngine) :
00073         randomEngine(randomEngine ? randomEngine : &getEngineReference()),
00074         timeoutPrivate(0)
00075 {
00076 }
00077 
00078 Herwig6Instance::Herwig6Instance(int dummy) :
00079         randomEngine(0),
00080         timeoutPrivate(0)
00081 {
00082 }
00083 
00084 Herwig6Instance::~Herwig6Instance()
00085 {
00086 }
00087 
00088 // timeout tool
00089 
00090 #ifdef _POSIX_C_SOURCE
00091 // some deep POSIX hackery to catch HERWIG sometimes (O(10k events) with
00092 // complicated topologies) getting caught in and endless loop :-(
00093 
00094 void Herwig6Instance::_timeout_sighandler(int signr)
00095 { siglongjmp(*(sigjmp_buf*)FortranInstance::getInstance<Herwig6Instance>()->timeoutPrivate, 1); }
00096 
00097 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)())
00098 {
00099         if (timeoutPrivate)
00100                 throw cms::Exception("ReentrancyProblem")
00101                         << "Herwig6Instance::timeout() called recursively."
00102                         << std::endl;
00103         struct sigaction saOld;
00104         std::memset(&saOld, 0, sizeof saOld);
00105 
00106         struct itimerval itv;
00107         timerclear(&itv.it_value);
00108         timerclear(&itv.it_interval);
00109         itv.it_value.tv_sec = 0;
00110         itv.it_interval.tv_sec = 0;
00111         setitimer(ITIMER_VIRTUAL, &itv, NULL);
00112 
00113         sigset_t ss;
00114         sigemptyset(&ss);
00115         sigaddset(&ss, SIGVTALRM);
00116 
00117         sigprocmask(SIG_UNBLOCK, &ss, NULL);
00118         sigprocmask(SIG_BLOCK, &ss, NULL);
00119 
00120         timeoutPrivate = new sigjmp_buf;
00121         if (sigsetjmp(*(sigjmp_buf*)timeoutPrivate, 1)) {
00122                 delete (sigjmp_buf*)timeoutPrivate;
00123                 timeoutPrivate = 0;
00124 
00125                 itv.it_value.tv_sec = 0;
00126                 itv.it_interval.tv_sec = 0;
00127                 setitimer(ITIMER_VIRTUAL, &itv, NULL);
00128                 sigprocmask(SIG_UNBLOCK, &ss, NULL);
00129                 return true;
00130         }
00131 
00132         itv.it_value.tv_sec = secs;
00133         itv.it_interval.tv_sec = secs;
00134         setitimer(ITIMER_VIRTUAL, &itv, NULL);
00135 
00136         struct sigaction sa;
00137         std::memset(&sa, 0, sizeof sa);
00138         sa.sa_handler = &Herwig6Instance::_timeout_sighandler;
00139         sa.sa_flags = SA_ONESHOT;
00140         sigemptyset(&sa.sa_mask);
00141 
00142         sigaction(SIGVTALRM, &sa, &saOld);
00143         sigprocmask(SIG_UNBLOCK, &ss, NULL);
00144 
00145         try {
00146                 fn();
00147         } catch(...) {
00148                 delete (sigjmp_buf*)timeoutPrivate;
00149                 timeoutPrivate = 0;
00150 
00151                 itv.it_value.tv_sec = 0;
00152                 itv.it_interval.tv_sec = 0;
00153                 setitimer(ITIMER_VIRTUAL, &itv, NULL);
00154 
00155                 sigaction(SIGVTALRM, &saOld, NULL);
00156 
00157                 throw;
00158         }
00159 
00160         delete (sigjmp_buf*)timeoutPrivate;
00161         timeoutPrivate = 0;
00162 
00163         itv.it_value.tv_sec = 0;
00164         itv.it_interval.tv_sec = 0;
00165         setitimer(ITIMER_VIRTUAL, &itv, NULL);
00166 
00167         sigaction(SIGVTALRM, &saOld, NULL);
00168 
00169         return false;
00170 }
00171 #else
00172 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)())
00173 {
00174         fn();
00175         return false;
00176 }
00177 #endif
00178 
00179 bool Herwig6Instance::hwwarn(const std::string &fn, int code)
00180 {
00181         return false;
00182 }
00183 
00184 // regular Herwig6Instance methods
00185 
00186 bool Herwig6Instance::give(const std::string &line)
00187 {       
00188         typedef std::istringstream::traits_type traits;
00189 
00190         const char *p = line.c_str(), *q;
00191         p += std::strspn(p, " \t\r\n");
00192 
00193         for(q = p; std::isalnum(*q); q++);
00194         std::string name(p, q - p);
00195 
00196         const ConfigParam *param;
00197         for(param = configParams; param->name; param++)
00198                 if (name == param->name)
00199                         break;
00200         if (!param->name)
00201                 return false;
00202 
00203         p = q + std::strspn(q, " \t\r\n");  
00204 
00205         std::size_t pos = 0;
00206         std::size_t mult = 1;
00207         for(unsigned int i = 0; i < 3; i++) {
00208                 if (!param->dim[i].size)
00209                         break;
00210 
00211                 if (*p++ != (i ? ',' : '('))
00212                         return false;
00213 
00214                 p += std::strspn(p, " \t\r\n");
00215 
00216                 for(q = p; std::isdigit(*q); q++);
00217                 std::istringstream ss(std::string(p, q - p));
00218                 std::size_t index;
00219                 ss >> index;
00220                 if (ss.bad() || ss.peek() != traits::eof())
00221                         return false;
00222 
00223                 if (index < param->dim[i].offset)
00224                         return false;
00225                 index -= param->dim[i].offset;
00226                 if (index >= param->dim[i].size)
00227                         return false;
00228 
00229                 p = q + std::strspn(q, " \t\r\n");
00230 
00231                 pos += mult * index;
00232                 mult *= param->dim[i].size;
00233         }
00234 
00235         if (param->dim[0].size) {
00236                 if (*p++ != ')')
00237                         return false;
00238                 p += std::strspn(p, " \t\r\n");
00239         }
00240 
00241         if (*p++ != '=')
00242                 return false;
00243         p += std::strspn(p, " \t\r\n");
00244 
00245         for(q = p; *q && (std::isalnum(*q) || std::strchr(".-+", *q)); q++);
00246         std::istringstream ss(std::string(p, q - p));
00247 
00248         p = q + std::strspn(q, " \t\r\n");
00249         if (*p && *p != '!')
00250                 return false;
00251 
00252         switch(param->type) {
00253             case kInt: {
00254                 int value;
00255                 ss >> value;
00256                 if (ss.bad() || ss.peek() != traits::eof())
00257                         return false;
00258 
00259                 ((int*)param->ptr)[pos] = value;
00260                 break;
00261             }
00262             case kDouble: {
00263                 double value;
00264                 ss >> value;
00265                 if (ss.bad() || ss.peek() != traits::eof())
00266                         return false;
00267 
00268                 ((double*)param->ptr)[pos] = value;
00269                 break;
00270             }
00271             case kLogical: {
00272                 std::string value_;
00273                 ss >> value_;
00274                 if (ss.bad() || ss.peek() != traits::eof())
00275                         return false;
00276 
00277                 for(std::string::iterator iter = value_.begin();
00278                     iter != value_.end(); ++iter)
00279                         *iter = std::tolower(*iter);
00280                 bool value;
00281                 if (value_ == "yes" || value_ == "true" || value_ == "1")
00282                         value = true;
00283                 else if (value_ == "no" || value_ == "false" || value_ == "0")
00284                         value = false;
00285                 else
00286                         return false;
00287 
00288                 ((int*)param->ptr)[pos] = value;
00289                 break;
00290             }
00291         }
00292 
00293         return true;
00294 }