CMS 3D CMS Logo

ConcurrentGeneratorFilter.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 //
4 
5 // class template ConcurrentGeneratorFilter<HAD> provides an EDFilter which uses
6 // the hadronizer type HAD to generate partons, hadronize them,
7 // and decay the resulting particles, in the CMS framework.
8 
9 #ifndef GeneratorInterface_Core_ConcurrentGeneratorFilter_h
10 #define GeneratorInterface_Core_ConcurrentGeneratorFilter_h
11 
12 #include <memory>
13 #include <string>
14 #include <vector>
15 #include <atomic>
16 
31 #include "CLHEP/Random/RandomEngine.h"
32 
33 // LHE Run
36 
37 // LHE Event
40 
46 
47 namespace edm {
48  namespace gen {
49  struct GenRunCache {
50  mutable std::atomic<GenRunInfoProduct*> product_{nullptr};
51  ~GenRunCache() { delete product_.load(); }
52 
53  // This is called from globalEndRunProduce which is known to
54  // be safe as the framework would not be calling any other
55  // methods of this module using this run at that time
56  std::unique_ptr<GenRunInfoProduct> release() const noexcept {
57  auto retValue = product_.load();
58  product_.store(nullptr);
59  return std::unique_ptr<GenRunInfoProduct>(retValue);
60  }
61  };
62  struct GenLumiSummary {
63  mutable std::unique_ptr<GenLumiInfoProduct> lumiInfo_;
64  };
65  template <typename HAD, typename DEC>
66  struct GenStreamCache {
67  GenStreamCache(ParameterSet const& iPSet) : hadronizer_{iPSet}, nEventsInLumiBlock_{0} {}
69  std::unique_ptr<DEC> decayer_;
70  unsigned int nEventsInLumiBlock_;
71  bool initialized_ = false;
72  };
73  } // namespace gen
74 
75  template <class HAD, class DEC>
76  class ConcurrentGeneratorFilter : public global::EDFilter<EndRunProducer,
77  BeginLuminosityBlockProducer,
78  EndLuminosityBlockProducer,
79  RunCache<gen::GenRunCache>,
80  LuminosityBlockSummaryCache<gen::GenLumiSummary>,
81  StreamCache<gen::GenStreamCache<HAD, DEC>>> {
82  public:
83  typedef HAD Hadronizer;
84  typedef DEC Decayer;
85 
86  // The given ParameterSet will be passed to the contained Hadronizer object.
87  explicit ConcurrentGeneratorFilter(ParameterSet const& ps);
88 
89  bool filter(StreamID id, Event& e, EventSetup const& es) const override;
90  std::unique_ptr<gen::GenStreamCache<HAD, DEC>> beginStream(StreamID) const override;
91  std::shared_ptr<gen::GenRunCache> globalBeginRun(Run const&, EventSetup const&) const override;
92  std::shared_ptr<gen::GenLumiSummary> globalBeginLuminosityBlockSummary(LuminosityBlock const&,
93  EventSetup const&) const override;
94  void globalBeginLuminosityBlockProduce(LuminosityBlock&, EventSetup const&) const override;
95  void streamBeginLuminosityBlock(StreamID, LuminosityBlock const&, EventSetup const&) const override;
96  void streamEndLuminosityBlock(StreamID, LuminosityBlock const&, EventSetup const&) const override;
97  void streamEndLuminosityBlockSummary(StreamID,
98  LuminosityBlock const&,
99  EventSetup const&,
100  gen::GenLumiSummary*) const override;
101  void globalEndLuminosityBlockSummary(LuminosityBlock const&,
102  EventSetup const&,
103  gen::GenLumiSummary*) const override;
104  void globalEndLuminosityBlockProduce(LuminosityBlock&,
105  EventSetup const&,
106  gen::GenLumiSummary const*) const override;
107  void streamEndRun(StreamID, Run const&, EventSetup const&) const override;
108  void globalEndRun(Run const&, EventSetup const&) const override;
109  void globalEndRunProduce(Run&, EventSetup const&) const override;
110 
111  private:
112  void initLumi(gen::GenStreamCache<HAD, DEC>* cache, LuminosityBlock const& index, EventSetup const& es) const;
114  mutable std::atomic<gen::GenStreamCache<HAD, DEC>*> useInLumi_{nullptr};
115  };
116 
117  //------------------------------------------------------------------------
118  //
119  // Implementation
120 
121  template <class HAD, class DEC>
123  // TODO:
124  // Put the list of types produced by the filters here.
125  // The current design calls for:
126  // * LHEGeneratorInfo
127  // * LHEEvent
128  // * HepMCProduct
129  // But I can not find the LHEGeneratorInfo class; it might need to
130  // be invented.
131 
132  this->template produces<HepMCProduct>("unsmeared");
133  this->template produces<GenEventInfoProduct>();
134  this->template produces<GenLumiInfoHeader, edm::Transition::BeginLuminosityBlock>();
135  this->template produces<GenLumiInfoProduct, edm::Transition::EndLuminosityBlock>();
136  this->template produces<GenRunInfoProduct, edm::Transition::EndRun>();
137  }
138 
139  template <class HAD, class DEC>
140  std::unique_ptr<gen::GenStreamCache<HAD, DEC>> ConcurrentGeneratorFilter<HAD, DEC>::beginStream(StreamID) const {
141  auto cache = std::make_unique<gen::GenStreamCache<HAD, DEC>>(config_);
142 
143  if (config_.exists("ExternalDecays")) {
144  ParameterSet ps1 = config_.getParameter<ParameterSet>("ExternalDecays");
145  cache->decayer_.reset(new Decayer(ps1));
146  }
147 
148  // We need a hadronizer during globalBeginLumiProduce, doesn't matter which one
149  gen::GenStreamCache<HAD, DEC>* expected = nullptr;
150  useInLumi_.compare_exchange_strong(expected, cache.get());
151 
152  return cache;
153  }
154 
155  template <class HAD, class DEC>
156  std::shared_ptr<gen::GenRunCache> ConcurrentGeneratorFilter<HAD, DEC>::globalBeginRun(Run const&,
157  EventSetup const&) const {
158  return std::make_shared<gen::GenRunCache>();
159  }
160 
161  template <class HAD, class DEC>
163  LuminosityBlock const&, EventSetup const&) const {
164  return std::make_shared<gen::GenLumiSummary>();
165  }
166 
167  template <class HAD, class DEC>
169  LuminosityBlock const& lumi,
170  EventSetup const& es) const {
171  cache->nEventsInLumiBlock_ = 0;
172 
173  // We need all copies to see same random # for begin lumi
175  auto enginePtr = rng->cloneEngine(lumi.index());
176  cache->hadronizer_.setRandomEngine(enginePtr.get());
177  cache->decayer_->setRandomEngine(enginePtr.get());
178 
179  auto unsetH = [](HAD* h) { h->setRandomEngine(nullptr); };
180  auto unsetD = [](DEC* d) { d->setRandomEngine(nullptr); };
181 
182  std::unique_ptr<HAD, decltype(unsetH)> randomEngineSentry(&cache->hadronizer_, unsetH);
183  std::unique_ptr<DEC, decltype(unsetD)> randomEngineSentryDecay(cache->decayer_.get(), unsetD);
184 
185  cache->hadronizer_.randomizeIndex(lumi, enginePtr.get());
186 
187  if (!cache->hadronizer_.readSettings(0))
189  << "Failed to read settings for the hadronizer " << cache->hadronizer_.classname() << " \n";
190 
191  if (cache->decayer_) {
192  cache->decayer_->init(es);
193  if (!cache->hadronizer_.declareStableParticles(cache->decayer_->operatesOnParticles()))
195  << "Failed to declare stable particles in hadronizer " << cache->hadronizer_.classname()
196  << " for internal parton generation\n";
197  if (!cache->hadronizer_.declareSpecialSettings(cache->decayer_->specialSettings()))
199  << "Failed to declare special settings in hadronizer " << cache->hadronizer_.classname() << "\n";
200  }
201 
202  if (!cache->hadronizer_.initializeForInternalPartons())
204  << "Failed to initialize hadronizer " << cache->hadronizer_.classname()
205  << " for internal parton generation\n";
206 
207  cache->initialized_ = true;
208  }
209 
210  template <class HAD, class DEC>
212  auto cache = this->streamCache(id);
213  RandomEngineSentry<HAD> randomEngineSentry(&cache->hadronizer_, ev.streamID());
214  RandomEngineSentry<DEC> randomEngineSentryDecay(cache->decayer_.get(), ev.streamID());
215 
216  cache->hadronizer_.setEDMEvent(ev);
217 
218  bool passEvtGenSelector = false;
219  std::unique_ptr<HepMC::GenEvent> event(nullptr);
220 
221  while (!passEvtGenSelector) {
222  event.reset();
223  cache->hadronizer_.setEDMEvent(ev);
224 
225  if (!cache->hadronizer_.generatePartonsAndHadronize())
226  return false;
227 
228  // this is "fake" stuff
229  // in principle, decays are done as part of full event generation,
230  // except for particles that are marked as to be kept stable
231  // but we currently keep in it the design, because we might want
232  // to use such feature for other applications
233  //
234  if (!cache->hadronizer_.decay())
235  return false;
236 
237  event = cache->hadronizer_.getGenEvent();
238  if (!event.get())
239  return false;
240 
241  //
242  // The external decay driver is being added to the system, it should be called here
243  //
244  if (cache->decayer_) {
245  auto t = cache->decayer_->decay(event.get());
246  if (t != event.get()) {
247  event.reset(t);
248  }
249  }
250  if (!event.get())
251  return false;
252 
253  passEvtGenSelector = cache->hadronizer_.select(event.get());
254  }
255 
256  // check and perform if there're any unstable particles after
257  // running external decay packages
258  //
259  // fisrt of all, put back modified event tree (after external decay)
260  //
261  cache->hadronizer_.resetEvent(std::move(event));
262 
263  //
264  // now run residual decays
265  //
266  if (!cache->hadronizer_.residualDecay())
267  return false;
268 
269  cache->hadronizer_.finalizeEvent();
270 
271  event = cache->hadronizer_.getGenEvent();
272  if (!event.get())
273  return false;
274 
275  event->set_event_number(ev.id().event());
276 
277  //
278  // finally, form up EDM products !
279  //
280  std::unique_ptr<GenEventInfoProduct> genEventInfo(cache->hadronizer_.getGenEventInfo());
281  if (!genEventInfo.get()) {
282  // create GenEventInfoProduct from HepMC event in case hadronizer didn't provide one
283  genEventInfo = std::make_unique<GenEventInfoProduct>(event.get());
284  }
285 
287 
288  std::unique_ptr<HepMCProduct> bare_product(new HepMCProduct());
289  bare_product->addHepMCData(event.release());
290  ev.put(std::move(bare_product), "unsmeared");
291  cache->nEventsInLumiBlock_++;
292  return true;
293  }
294 
295  template <class HAD, class DEC>
297  EventSetup const& es) const {
298  // need one of the streams to finish
299  while (useInLumi_.load() == nullptr) {
300  }
301  initLumi(useInLumi_, lumi, es);
302  std::unique_ptr<GenLumiInfoHeader> genLumiInfoHeader(useInLumi_.load()->hadronizer_.getGenLumiInfoHeader());
304  }
305 
306  template <class HAD, class DEC>
308  LuminosityBlock const& lumi,
309  EventSetup const& es) const {
310  if (useInLumi_ != this->streamCache(id)) {
311  initLumi(this->streamCache(id), lumi, es);
312  } else {
313  useInLumi_.store(nullptr);
314  }
315  }
316 
317  template <class HAD, class DEC>
319  LuminosityBlock const&,
320  EventSetup const&) const {
321  this->streamCache(id)->hadronizer_.cleanLHE();
322  }
323 
324  template <class HAD, class DEC>
326  LuminosityBlock const&,
327  EventSetup const&,
328  gen::GenLumiSummary* iSummary) const {
329  auto cache = this->streamCache(id);
330  cache->hadronizer_.statistics();
331  if (cache->decayer_)
332  cache->decayer_->statistics();
333 
334  GenRunInfoProduct genRunInfo = GenRunInfoProduct(cache->hadronizer_.getGenRunInfo());
335  std::vector<GenLumiInfoProduct::ProcessInfo> GenLumiProcess;
336  const GenRunInfoProduct::XSec& xsec = genRunInfo.internalXSec();
338  unsigned int nEvtInLumiBlock_ = cache->nEventsInLumiBlock_;
339  temp.setProcess(0);
340  temp.setLheXSec(xsec.value(), xsec.error()); // Pythia gives error of -1
341  temp.setNPassPos(nEvtInLumiBlock_);
342  temp.setNPassNeg(0);
343  temp.setNTotalPos(nEvtInLumiBlock_);
344  temp.setNTotalNeg(0);
345  temp.setTried(nEvtInLumiBlock_, nEvtInLumiBlock_, nEvtInLumiBlock_);
346  temp.setSelected(nEvtInLumiBlock_, nEvtInLumiBlock_, nEvtInLumiBlock_);
347  temp.setKilled(nEvtInLumiBlock_, nEvtInLumiBlock_, nEvtInLumiBlock_);
348  temp.setAccepted(0, -1, -1);
349  temp.setAcceptedBr(0, -1, -1);
350  GenLumiProcess.push_back(temp);
351 
352  GenLumiInfoProduct genLumiInfo;
353  genLumiInfo.setHEPIDWTUP(-1);
354  genLumiInfo.setProcessInfo(GenLumiProcess);
355 
356  if (iSummary->lumiInfo_) {
357  iSummary->lumiInfo_->mergeProduct(genLumiInfo);
358  } else {
359  iSummary->lumiInfo_ = std::make_unique<GenLumiInfoProduct>(std::move(genLumiInfo));
360  }
361 
362  cache->nEventsInLumiBlock_ = 0;
363 
364  gen::GenStreamCache<HAD, DEC>* expected = nullptr;
365  //make it available for beginLuminosityBlockProduce
366  useInLumi_.compare_exchange_strong(expected, this->streamCache(id));
367  }
368 
369  template <class HAD, class DEC>
371  EventSetup const&,
372  gen::GenLumiSummary*) const {}
373 
374  template <class HAD, class DEC>
376  EventSetup const&,
377  gen::GenLumiSummary const* iSummary) const {
378  lumi.put(std::move(iSummary->lumiInfo_));
379  }
380 
381  template <class HAD, class DEC>
383  auto rCache = this->runCache(run.index());
384  auto cache = this->streamCache(id);
385 
386  // If relevant, record the integrated luminosity for this run
387  // here. To do so, we would need a standard function to invoke on
388  // the contained hadronizer that would report the integrated
389  // luminosity.
390 
391  if (cache->initialized_) {
392  cache->hadronizer_.statistics();
393  if (cache->decayer_)
394  cache->decayer_->statistics();
395  }
396  GenRunInfoProduct& genRunInfo = cache->hadronizer_.getGenRunInfo();
397  GenRunInfoProduct* expect = nullptr;
398 
399  std::unique_ptr<GenRunInfoProduct> griproduct(new GenRunInfoProduct(genRunInfo));
400  // All the GenRunInfoProducts for all streams shoule be identical, therefore we only need one
401  if (rCache->product_.compare_exchange_strong(expect, griproduct.get())) {
402  griproduct.release();
403  }
404  }
405 
406  template <class HAD, class DEC>
408 
409  template <class HAD, class DEC>
411  run.put(this->runCache(run.index())->release());
412  }
413 
414 } // namespace edm
415 
416 #endif // GeneratorInterface_Core_ConcurrentGeneratorFilter_h
ConcurrentGeneratorFilter(ParameterSet const &ps)
T getParameter(std::string const &) const
EventNumber_t event() const
Definition: EventID.h:41
void setTried(unsigned int n, double sum, double sum2)
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
void streamEndLuminosityBlock(StreamID, LuminosityBlock const &, EventSetup const &) const override
void setSelected(unsigned int n, double sum, double sum2)
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
LuminosityBlockIndex index() const
std::unique_ptr< GenRunInfoProduct > release() const
void streamBeginLuminosityBlock(StreamID, LuminosityBlock const &, EventSetup const &) const override
std::atomic< GenRunInfoProduct * > product_
void setKilled(unsigned int n, double sum, double sum2)
bool exists(std::string const &parameterName) const
checks if a parameter exists
PROD const & get(EDGetTokenT< PROD > token) const (false)
bool ev
void initLumi(gen::GenStreamCache< HAD, DEC > *cache, LuminosityBlock const &index, EventSetup const &es) const
void globalEndLuminosityBlockProduce(LuminosityBlock &, EventSetup const &, gen::GenLumiSummary const *) const override
std::atomic< gen::GenStreamCache< HAD, DEC > * > useInLumi_
void setAccepted(unsigned int n, double sum, double sum2)
bool filter(StreamID id, Event &e, EventSetup const &es) const override
void setAcceptedBr(unsigned int n, double sum, double sum2)
void globalEndRun(Run const &, EventSetup const &) const override
void globalEndLuminosityBlockSummary(LuminosityBlock const &, EventSetup const &, gen::GenLumiSummary *) const override
void put(std::unique_ptr< PROD > product)
Put a new product.
GenStreamCache(ParameterSet const &iPSet)
RunIndex index() const
Definition: Run.cc:21
void streamEndRun(StreamID, Run const &, EventSetup const &) const override
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
#define noexcept
std::shared_ptr< gen::GenRunCache > globalBeginRun(Run const &, EventSetup const &) const override
void globalEndRunProduce(Run &, EventSetup const &) const override
void put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Run.h:108
void setLheXSec(double value, double err)
void setHEPIDWTUP(const int id)
std::shared_ptr< gen::GenLumiSummary > globalBeginLuminosityBlockSummary(LuminosityBlock const &, EventSetup const &) const override
const XSec & internalXSec() const
edm::EventID id() const
Definition: EventBase.h:59
HLT enums.
def cache(function)
Definition: utilities.py:3
StreamID streamID() const
Definition: Event.h:95
void streamEndLuminosityBlockSummary(StreamID, LuminosityBlock const &, EventSetup const &, gen::GenLumiSummary *) const override
std::unique_ptr< gen::GenStreamCache< HAD, DEC > > beginStream(StreamID) const override
std::unique_ptr< GenLumiInfoProduct > lumiInfo_
std::unique_ptr< DEC > decayer_
void globalBeginLuminosityBlockProduce(LuminosityBlock &, EventSetup const &) const override
void setProcessInfo(const std::vector< ProcessInfo > &processes)
def move(src, dest)
Definition: eostools.py:511
Definition: Run.h:45