CMS 3D CMS Logo

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