CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
SherpaHadronizer.cc
Go to the documentation of this file.
1 #include <cassert>
2 #include <iostream>
3 #include <sstream>
4 #include <string>
5 #include <memory>
6 #include <cstdint>
7 #include <vector>
8 
9 
10 #include "SHERPA/Main/Sherpa.H"
11 #include "ATOOLS/Math/Random.H"
12 
13 #include "ATOOLS/Org/Run_Parameter.H"
14 #include "ATOOLS/Org/MyStrStream.H"
15 #include "ATOOLS/Org/CXXFLAGS.H"
16 #include "ATOOLS/Org/CXXFLAGS_PACKAGES.H"
17 #include "ATOOLS/Org/My_MPI.H"
18 
19 
25 
26 #include "CLHEP/Random/RandomEngine.h"
27 
28 
29 //This unnamed namespace is used (instead of static variables) to pass the
30 //randomEngine passed to doSetRandomEngine to the External Random
31 //Number Generator CMS_SHERPA_RNG of sherpa
32 //The advantage of the unnamed namespace over static variables is
33 //that it is only accessible in this file
34 
35 namespace {
36  CLHEP::HepRandomEngine* ExternalEngine=nullptr;
37  CLHEP::HepRandomEngine* GetExternalEngine() { return ExternalEngine; }
38  void SetExternalEngine(CLHEP::HepRandomEngine* v) { ExternalEngine=v; }
39 }
40 
42 public:
43  SherpaHadronizer(const edm::ParameterSet &params);
45 
46  bool readSettings( int ) { return true; }
48  bool declareStableParticles(const std::vector<int> &pdgIds);
49  bool declareSpecialSettings( const std::vector<std::string>& ) { return true; }
50  void statistics();
52  bool decay();
54  bool residualDecay();
55  void finalizeEvent();
56  GenLumiInfoHeader *getGenLumiInfoHeader() const override;
57  const char *classname() const { return "SherpaHadronizer"; }
58 
59 
60 private:
61 
62  void doSetRandomEngine(CLHEP::HepRandomEngine* v) override;
63 
71  unsigned int maxEventsToPrint;
72  std::vector<std::string> arguments;
76 // bool rearrangeWeights;
77  std::vector<std::string> weightlist;
78  std::vector<std::string> variationweightlist;
79 };
80 
81 
82 
83 
84 class CMS_SHERPA_RNG: public ATOOLS::External_RNG {
85 public:
86 
88  edm::LogVerbatim("SherpaHadronizer") << "Use stored reference for the external RNG";
89  setRandomEngine(GetExternalEngine());
90  }
91  void setRandomEngine(CLHEP::HepRandomEngine* v) { randomEngine = v; }
92 
93 private:
94  double Get() override;
95  CLHEP::HepRandomEngine* randomEngine;
96 };
97 
98 
99 void SherpaHadronizer::doSetRandomEngine(CLHEP::HepRandomEngine* v) {
100  CMS_SHERPA_RNG* cmsSherpaRng = dynamic_cast<CMS_SHERPA_RNG*>(ATOOLS::ran->GetExternalRng());
101  //~ assert(cmsSherpaRng != nullptr);
102  if (cmsSherpaRng ==nullptr) {
103  //First time call to this function makes the interface store the reference in the unnamed namespace
104  if (!isRNGinitialized){
105  isRNGinitialized=true;
106  edm::LogVerbatim("SherpaHadronizer") << "Store assigned reference of the randomEngine";
107  SetExternalEngine(v);
108  // Throw exception if there is no reference to an external RNG and it is not the first call!
109  } else {
111  << "The Sherpa interface got a randomEngine reference but there is no reference to the external RNG to hand it over to\n";
112  }
113  } else {
114  cmsSherpaRng->setRandomEngine(v);
115  }
116 }
117 
119  BaseHadronizer(params),
120  SherpaParameterSet(params.getParameter<edm::ParameterSet>("SherpaParameters")),
121  isRNGinitialized(false)
122 {
123  if (!params.exists("SherpaProcess")) SherpaProcess="";
124  else SherpaProcess=params.getParameter<std::string>("SherpaProcess");
125  if (!params.exists("SherpaPath")) SherpaPath="";
126  else SherpaPath=params.getParameter<std::string>("SherpaPath");
127  if (!params.exists("SherpaPathPiece")) SherpaPathPiece="";
128  else SherpaPathPiece=params.getParameter<std::string>("SherpaPathPiece");
129  if (!params.exists("SherpaResultDir")) SherpaResultDir="Result";
130  else SherpaResultDir=params.getParameter<std::string>("SherpaResultDir");
131  if (!params.exists("SherpaDefaultWeight")) SherpaDefaultWeight=1.;
132  else SherpaDefaultWeight=params.getParameter<double>("SherpaDefaultWeight");
133  if (!params.exists("maxEventsToPrint")) maxEventsToPrint=0;
134  else maxEventsToPrint=params.getParameter<int>("maxEventsToPrint");
135 // if hepmcextendedweights is used the event weights have to be reordered ( unordered list can be accessed via event->weights().write() )
136 // two lists have to be provided:
137 // 1) SherpaWeights
138 // - containing nominal event weight, combined matrix element and phase space weight, event normalization, and possibly other sherpa weights
139 // 2) SherpaVariationsWeights
140 // - containing weights from scale and PDF variations ( have to be defined in the runcard )
141 // - in case of unweighted events these weights are also divided by the event normalization (see list 1 )
142 // Sherpa Documentation: http://sherpa.hepforge.org/doc/SHERPA-MC-2.2.0.html#Scale-and-PDF-variations
143  if (!params.exists("SherpaWeightsBlock")) {
144  rearrangeWeights=false;
145  } else {
146  rearrangeWeights=true;
147  edm::ParameterSet WeightsBlock = params.getParameter<edm::ParameterSet>("SherpaWeightsBlock");
148  if (WeightsBlock.exists("SherpaWeights"))
149  weightlist=WeightsBlock.getParameter< std::vector<std::string> >("SherpaWeights");
150  else
151  throw cms::Exception("SherpaInterface") <<"SherpaWeights does not exists in SherpaWeightsBlock" << std::endl;
152  if (WeightsBlock.exists("SherpaVariationWeights"))
153  variationweightlist=WeightsBlock.getParameter< std::vector<std::string> >("SherpaVariationWeights");
154  else
155  throw cms::Exception("SherpaInterface") <<"SherpaVariationWeights does not exists in SherpaWeightsBlock" << std::endl;
156  edm::LogVerbatim("SherpaHadronizer") << "SherpaHadronizer will try rearrange the event weights according to SherpaWeights and SherpaVariationWeights";
157  }
158 
159 
160  spf::SherpackFetcher Fetcher(params);
161  int retval=Fetcher.Fetch();
162  if (retval != 0) {
163  throw cms::Exception("SherpaInterface") <<"SherpaHadronizer: Preparation of Sherpack failed ... ";
164  }
165  // The ids (names) of parameter sets to be read (Analysis,Run) to create Analysis.dat, Run.dat
166  //They are given as a vstring.
167  std::vector<std::string> setNames = SherpaParameterSet.getParameter<std::vector<std::string> >("parameterSets");
168  //Loop all set names...
169  for ( unsigned i=0; i<setNames.size(); ++i ) {
170  // ...and read the parameters for each set given in vstrings
171  std::vector<std::string> pars = SherpaParameterSet.getParameter<std::vector<std::string> >(setNames[i]);
172  edm::LogVerbatim("SherpaHadronizer") << "Write Sherpa parameter set " << setNames[i] <<" to "<<setNames[i]<<".dat ";
173  std::string datfile = SherpaPath + "/" + setNames[i] +".dat";
174  std::ofstream os(datfile.c_str());
175  // Loop over all strings and write the according *.dat
176  for(std::vector<std::string>::const_iterator itPar = pars.begin(); itPar != pars.end(); ++itPar ) {
177  os<<(*itPar)<<std::endl;
178  }
179  }
180 
181  //To be conform to the default Sherpa usage create a command line:
182  //name of executable (only for demonstration, could also be empty)
183  std::string shRun = "./Sherpa";
184  //Path where the Sherpa libraries are stored
185  std::string shPath = "PATH=" + SherpaPath;
186  // new for Sherpa 1.3.0, suggested by authors
187  std::string shPathPiece = "PATH_PIECE=" + SherpaPathPiece;
188  //Path where results are stored
189  std::string shRes = "RESULT_DIRECTORY=" + SherpaResultDir; // from Sherpa 1.2.0 on
190  //Name of the external random number class
191  std::string shRng = "EXTERNAL_RNG=CMS_SHERPA_RNG";
192 
193  //create the command line
194  arguments.push_back(shRun);
195  arguments.push_back(shPath);
196  arguments.push_back(shPathPiece);
197  arguments.push_back(shRes);
198  arguments.push_back(shRng);
199 
200  isInitialized=false;
201  //initialization of Sherpa moved to initializeForInternalPartons
202 }
203 
205 {
206  Generator->~Sherpa();
207  #ifdef USING__MPI
208  MPI::Finalize();
209  #endif
210 
211 }
212 
214 {
215  //initialize Sherpa but only once
216  if (!isInitialized){
217  int argc=arguments.size();
218  char* argv[argc];
219  for (int l=0; l<argc; l++) argv[l]=(char*)arguments[l].c_str();
220  #ifdef USING__MPI
221  MPI::Init();
222  #endif
223  Generator->InitializeTheRun(argc,argv);
224  Generator->InitializeTheEventHandler();
225  isInitialized=true;
226  }
227  return true;
228 }
229 
230 //FIXME
231 bool SherpaHadronizer::declareStableParticles(const std::vector<int> &pdgIds)
232 {
233  return false;
234 }
235 
236 
238 {
239  //calculate statistics
240  Generator->SummarizeRun();
241 
242  //get the xsec & err
243  double xsec_val = Generator->TotalXS();
244  double xsec_err = Generator->TotalErr();
245 
246  //set the internal cross section in pb in GenRunInfoProduct
247  runInfo().setInternalXSec(GenRunInfoProduct::XSec(xsec_val,xsec_err));
248 
249 }
250 
251 
253 {
254  //get the next event and check if it produced
255  bool rc = false;
256  int itry = 0;
257  bool gen_event = true;
258  while((itry < 3) && gen_event){
259  try{
260  rc = Generator->GenerateOneEvent();
261  gen_event = false;
262  } catch(...){
263  ++itry;
264  std::cerr << "Exception from Generator->GenerateOneEvent() catch. Call # "
265  << itry << " for this event\n";
266  }
267  }
268  if (rc) {
269  //convert it to HepMC2
270  HepMC::GenEvent* evt = new HepMC::GenEvent();
271  Generator->FillHepMCEvent(*evt);
272 
273  // in case of unweighted events sherpa puts the max weight as event weight.
274  // this is not optimal, we want 1 for unweighted events, so we check
275  // whether we are producing unweighted events ("EVENT_GENERATION_MODE" == "1")
276  // the information about the weights to the HepMC weight vector:
277  // [0] event weight
278  // [1] combined matrix element and phase space weight (missing only PDF information, thus directly suitable for PDF reweighting)
279  // [2] event weight normalisation (in case of unweighted events event weights of ~ +/-1 can be obtained by (event weight)/(event weight normalisation))
280  // [3] number of trials.
281  // see also: https://sherpa.hepforge.org/doc/SHERPA-MC-2.1.0.html#Event-output-formats
282  bool unweighted = false;
283  double weight_normalization = -1;
284  if(ATOOLS::ToType<int>(ATOOLS::rpa->gen.Variable("EVENT_GENERATION_MODE")) == 1){
285  if (evt->weights().size()>2) {
286  unweighted = true;
287  weight_normalization = evt->weights()[2];
288  }else{
289  throw cms::Exception("SherpaInterface") <<"Requested unweighted production. Missing normalization weight." << std::endl;
290  }
291  }
292 
293  // vector to fill new weights in correct order
294  std::vector<double> newWeights;
295  if (rearrangeWeights){
296  for ( auto &i : weightlist ) {
297  if (evt->weights().has_key(i)) {
298  newWeights.push_back(evt->weights()[i]);
299  } else {
300  throw cms::Exception("SherpaInterface") <<"Missing weights! Key " << i << " not found, please check the weight definition!" << std::endl;
301  }
302  }
303  for ( auto &i : variationweightlist ) {
304  if (evt->weights().has_key(i)) {
305  if(unweighted){
306  newWeights.push_back(evt->weights()[i]/weight_normalization);
307  }else{
308  newWeights.push_back(evt->weights()[i]);
309  }
310  } else {
311  throw cms::Exception("SherpaInterface") <<"Missing weights! Key " << i << " not found, please check the weight definition!" << std::endl;
312  }
313 
314  }
315 
316  //Change original weights for reordered ones
317  evt->weights().clear();
318  for (auto& elem: newWeights) {
319  evt->weights().push_back(elem);
320  }
321  }
322 
323  if(unweighted){
324  evt->weights()[0]/=weight_normalization;
325  }
326  resetEvent(evt);
327  return true;
328  }
329  else {
330  return false;
331  }
332 }
333 
335 {
336  return true;
337 }
338 
340 {
341  return true;
342 }
343 
345 {
346  //******** Verbosity *******
347  if (maxEventsToPrint > 0) {
349  event()->print();
350  }
351 }
352 
353 
354 //GETTER for the external random numbers
355 DECLARE_GETTER(CMS_SHERPA_RNG,"CMS_SHERPA_RNG",ATOOLS::External_RNG,ATOOLS::RNG_Key);
356 
357 ATOOLS::External_RNG *ATOOLS::Getter<ATOOLS::External_RNG,ATOOLS::RNG_Key,CMS_SHERPA_RNG>::operator()(const ATOOLS::RNG_Key &) const
358 { return new CMS_SHERPA_RNG(); }
359 
360 void ATOOLS::Getter<ATOOLS::External_RNG,ATOOLS::RNG_Key,CMS_SHERPA_RNG>::PrintInfo(std::ostream &str,const size_t) const
361 { str<<"CMS_SHERPA_RNG interface"; }
362 
364  if(randomEngine == nullptr) {
366  << "The Sherpa code attempted to a generate random number while\n"
367  << "the engine pointer was null. This might mean that the code\n"
368  << "was modified to generate a random number outside the event and\n"
369  << "beginLuminosityBlock methods, which is not allowed.\n";
370  }
371  return randomEngine->flat();
372 
373 }
374 
376  GenLumiInfoHeader *genLumiInfoHeader = BaseHadronizer::getGenLumiInfoHeader();
377 
378  if(rearrangeWeights){
379  edm::LogPrint("SherpaHadronizer") << "The order of event weights was changed!" ;
380  for(auto &i: weightlist){
381  genLumiInfoHeader->weightNames().push_back(i);
382  edm::LogVerbatim("SherpaHadronizer") << i;
383  }
384  for(auto &i: variationweightlist) {
385  genLumiInfoHeader->weightNames().push_back(i);
386  edm::LogVerbatim("SherpaHadronizer") << i;
387  }
388  }
389  return genLumiInfoHeader;
390 }
391 
392 
394 
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
CLHEP::HepRandomEngine * randomEngine
const std::vector< std::string > & weightNames() const
bool exists(std::string const &parameterName) const
checks if a parameter exists
std::vector< std::string > weightlist
std::string SherpaPathPiece
unsigned int maxEventsToPrint
edm::GeneratorFilter< SherpaHadronizer, gen::ExternalDecayDriver > SherpaGeneratorFilter
#define nullptr
void setInternalXSec(const XSec &xsec)
bool declareStableParticles(const std::vector< int > &pdgIds)
std::auto_ptr< HepMC::GenEvent > & event()
GenRunInfoProduct & runInfo()
edm::ParameterSet SherpaParameterSet
bool initializeForInternalPartons()
std::vector< std::string > variationweightlist
bool generatePartonsAndHadronize()
std::string SherpaPath
bool declareSpecialSettings(const std::vector< std::string > &)
void setRandomEngine(CLHEP::HepRandomEngine *v)
void doSetRandomEngine(CLHEP::HepRandomEngine *v) override
std::string SherpaProcess
tuple argc
Definition: dir2webdir.py:38
GenLumiInfoHeader * getGenLumiInfoHeader() const override
std::string SherpaResultDir
std::vector< std::string > arguments
SherpaHadronizer(const edm::ParameterSet &params)
void resetEvent(HepMC::GenEvent *event)
volatile std::atomic< bool > shutdown_flag false
DECLARE_GETTER(CMS_SHERPA_RNG,"CMS_SHERPA_RNG", ATOOLS::External_RNG, ATOOLS::RNG_Key)
const char * classname() const
std::string SherpaChecksum
double Get() override