CMS 3D CMS Logo

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