CMS 3D CMS Logo

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