File indexing completed on 2024-04-06 12:13:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #ifndef GeneratorInterface_Core_ConcurrentGeneratorFilter_h
0047 #define GeneratorInterface_Core_ConcurrentGeneratorFilter_h
0048
0049 #include <memory>
0050 #include <string>
0051 #include <vector>
0052 #include <atomic>
0053
0054 #include "FWCore/Framework/interface/global/EDFilter.h"
0055 #include "FWCore/Framework/interface/Event.h"
0056 #include "FWCore/Framework/interface/EventSetup.h"
0057 #include "FWCore/Framework/interface/FileBlock.h"
0058 #include "FWCore/Framework/interface/LuminosityBlock.h"
0059 #include "FWCore/Framework/interface/MakerMacros.h"
0060 #include "FWCore/Framework/interface/Run.h"
0061 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0062 #include "FWCore/ServiceRegistry/interface/RandomEngineSentry.h"
0063 #include "FWCore/Utilities/interface/BranchType.h"
0064 #include "FWCore/Utilities/interface/EDMException.h"
0065 #include "FWCore/Utilities/interface/EDGetToken.h"
0066 #include "FWCore/Utilities/interface/TypeID.h"
0067 #include "DataFormats/Provenance/interface/BranchDescription.h"
0068 #include "CLHEP/Random/RandomEngine.h"
0069
0070
0071 #include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h"
0072 #include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h"
0073
0074
0075 #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h"
0076 #include "GeneratorInterface/LHEInterface/interface/LHEEvent.h"
0077
0078 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
0079 #include "SimDataFormats/GeneratorProducts/interface/GenRunInfoProduct.h"
0080 #include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h"
0081 #include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoProduct.h"
0082 #include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h"
0083
0084 namespace edm {
0085 namespace gen {
0086 struct GenRunCache {
0087 mutable std::atomic<GenRunInfoProduct*> product_{nullptr};
0088 ~GenRunCache() { delete product_.load(); }
0089
0090
0091
0092
0093 std::unique_ptr<GenRunInfoProduct> release() const noexcept {
0094 auto retValue = product_.load();
0095 product_.store(nullptr);
0096 return std::unique_ptr<GenRunInfoProduct>(retValue);
0097 }
0098 };
0099 struct GenLumiSummary {
0100 mutable std::unique_ptr<GenLumiInfoProduct> lumiInfo_;
0101 };
0102 template <typename HAD, typename DEC>
0103 struct GenStreamCache {
0104 GenStreamCache(ParameterSet const& iPSet) : hadronizer_{iPSet}, nEventsInLumiBlock_{0} {}
0105 HAD hadronizer_;
0106 std::unique_ptr<DEC> decayer_;
0107 unsigned int nEventsInLumiBlock_;
0108 bool initialized_ = false;
0109 };
0110 template <typename HAD, typename DEC>
0111 struct GenLumiCache {
0112 gen::GenStreamCache<HAD, DEC>* useInLumi_{nullptr};
0113 unsigned long long nGlobalBeginLumis_{0};
0114 };
0115 }
0116
0117 template <class HAD, class DEC>
0118 class ConcurrentGeneratorFilter : public global::EDFilter<EndRunProducer,
0119 BeginLuminosityBlockProducer,
0120 EndLuminosityBlockProducer,
0121 RunCache<gen::GenRunCache>,
0122 LuminosityBlockCache<gen::GenLumiCache<HAD, DEC>>,
0123 LuminosityBlockSummaryCache<gen::GenLumiSummary>,
0124 StreamCache<gen::GenStreamCache<HAD, DEC>>> {
0125 public:
0126 typedef HAD Hadronizer;
0127 typedef DEC Decayer;
0128
0129
0130 explicit ConcurrentGeneratorFilter(ParameterSet const& ps);
0131
0132 bool filter(StreamID id, Event& e, EventSetup const& es) const override;
0133 std::unique_ptr<gen::GenStreamCache<HAD, DEC>> beginStream(StreamID) const override;
0134 std::shared_ptr<gen::GenRunCache> globalBeginRun(Run const&, EventSetup const&) const override;
0135 std::shared_ptr<gen::GenLumiSummary> globalBeginLuminosityBlockSummary(LuminosityBlock const&,
0136 EventSetup const&) const override;
0137 std::shared_ptr<gen::GenLumiCache<HAD, DEC>> globalBeginLuminosityBlock(LuminosityBlock const&,
0138 EventSetup const&) const override;
0139 void globalBeginLuminosityBlockProduce(LuminosityBlock&, EventSetup const&) const override;
0140 void streamBeginLuminosityBlock(StreamID, LuminosityBlock const&, EventSetup const&) const override;
0141 void streamEndLuminosityBlock(StreamID, LuminosityBlock const&, EventSetup const&) const override;
0142 void streamEndLuminosityBlockSummary(StreamID,
0143 LuminosityBlock const&,
0144 EventSetup const&,
0145 gen::GenLumiSummary*) const override;
0146 void globalEndLuminosityBlock(LuminosityBlock const&, EventSetup const&) const override;
0147 void globalEndLuminosityBlockSummary(LuminosityBlock const&,
0148 EventSetup const&,
0149 gen::GenLumiSummary*) const override;
0150 void globalEndLuminosityBlockProduce(LuminosityBlock&,
0151 EventSetup const&,
0152 gen::GenLumiSummary const*) const override;
0153 void streamEndRun(StreamID, Run const&, EventSetup const&) const override;
0154 void globalEndRun(Run const&, EventSetup const&) const override;
0155 void globalEndRunProduce(Run&, EventSetup const&) const override;
0156
0157 private:
0158 void initLumi(gen::GenStreamCache<HAD, DEC>* cache, LuminosityBlock const& index, EventSetup const& es) const;
0159 ParameterSet config_;
0160
0161
0162
0163
0164
0165 mutable std::atomic<gen::GenStreamCache<HAD, DEC>*> useInLumi_{nullptr};
0166 mutable std::atomic<unsigned long long> nextNGlobalBeginLumis_{1};
0167 mutable std::atomic<bool> streamEndRunComplete_{true};
0168 mutable unsigned long long nGlobalBeginRuns_{0};
0169 mutable unsigned long long nInitializedInGlobalLumiAfterNewRun_{0};
0170 mutable unsigned long long nGlobalBeginLumis_{0};
0171 };
0172
0173
0174
0175
0176
0177 template <class HAD, class DEC>
0178 ConcurrentGeneratorFilter<HAD, DEC>::ConcurrentGeneratorFilter(ParameterSet const& ps) : config_(ps) {
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 this->template produces<HepMCProduct>("unsmeared");
0189 this->template produces<GenEventInfoProduct>();
0190 this->template produces<GenLumiInfoHeader, edm::Transition::BeginLuminosityBlock>();
0191 this->template produces<GenLumiInfoProduct, edm::Transition::EndLuminosityBlock>();
0192 this->template produces<GenRunInfoProduct, edm::Transition::EndRun>();
0193 }
0194
0195 template <class HAD, class DEC>
0196 std::unique_ptr<gen::GenStreamCache<HAD, DEC>> ConcurrentGeneratorFilter<HAD, DEC>::beginStream(StreamID) const {
0197 auto cache = std::make_unique<gen::GenStreamCache<HAD, DEC>>(config_);
0198
0199 if (config_.exists("ExternalDecays")) {
0200 ParameterSet ps1 = config_.getParameter<ParameterSet>("ExternalDecays");
0201 cache->decayer_.reset(new Decayer(ps1));
0202 }
0203
0204
0205 gen::GenStreamCache<HAD, DEC>* expected = nullptr;
0206 useInLumi_.compare_exchange_strong(expected, cache.get());
0207
0208 return cache;
0209 }
0210
0211 template <class HAD, class DEC>
0212 std::shared_ptr<gen::GenRunCache> ConcurrentGeneratorFilter<HAD, DEC>::globalBeginRun(Run const&,
0213 EventSetup const&) const {
0214 ++nGlobalBeginRuns_;
0215 return std::make_shared<gen::GenRunCache>();
0216 }
0217
0218 template <class HAD, class DEC>
0219 std::shared_ptr<gen::GenLumiSummary> ConcurrentGeneratorFilter<HAD, DEC>::globalBeginLuminosityBlockSummary(
0220 LuminosityBlock const&, EventSetup const&) const {
0221 return std::make_shared<gen::GenLumiSummary>();
0222 }
0223
0224 template <class HAD, class DEC>
0225 void ConcurrentGeneratorFilter<HAD, DEC>::initLumi(gen::GenStreamCache<HAD, DEC>* cache,
0226 LuminosityBlock const& lumi,
0227 EventSetup const& es) const {
0228 cache->nEventsInLumiBlock_ = 0;
0229
0230
0231 Service<RandomNumberGenerator> rng;
0232 auto enginePtr = rng->cloneEngine(lumi.index());
0233 cache->hadronizer_.setRandomEngine(enginePtr.get());
0234 if (cache->decayer_) {
0235 cache->decayer_->setRandomEngine(enginePtr.get());
0236 }
0237
0238 auto unsetH = [](HAD* h) { h->setRandomEngine(nullptr); };
0239 auto unsetD = [](DEC* d) {
0240 if (d) {
0241 d->setRandomEngine(nullptr);
0242 }
0243 };
0244
0245 std::unique_ptr<HAD, decltype(unsetH)> randomEngineSentry(&cache->hadronizer_, unsetH);
0246 std::unique_ptr<DEC, decltype(unsetD)> randomEngineSentryDecay(cache->decayer_.get(), unsetD);
0247
0248 cache->hadronizer_.randomizeIndex(lumi, enginePtr.get());
0249
0250 if (!cache->hadronizer_.readSettings(0))
0251 throw edm::Exception(errors::Configuration)
0252 << "Failed to read settings for the hadronizer " << cache->hadronizer_.classname() << " \n";
0253
0254 if (cache->decayer_) {
0255 cache->decayer_->init(es);
0256 if (!cache->hadronizer_.declareStableParticles(cache->decayer_->operatesOnParticles()))
0257 throw edm::Exception(errors::Configuration)
0258 << "Failed to declare stable particles in hadronizer " << cache->hadronizer_.classname()
0259 << " for internal parton generation\n";
0260 if (!cache->hadronizer_.declareSpecialSettings(cache->decayer_->specialSettings()))
0261 throw edm::Exception(errors::Configuration)
0262 << "Failed to declare special settings in hadronizer " << cache->hadronizer_.classname() << "\n";
0263 }
0264
0265 if (!cache->hadronizer_.initializeForInternalPartons())
0266 throw edm::Exception(errors::Configuration)
0267 << "Failed to initialize hadronizer " << cache->hadronizer_.classname()
0268 << " for internal parton generation\n";
0269
0270 cache->initialized_ = true;
0271 }
0272
0273 template <class HAD, class DEC>
0274 bool ConcurrentGeneratorFilter<HAD, DEC>::filter(StreamID id, Event& ev, EventSetup const& ) const {
0275 auto cache = this->streamCache(id);
0276 RandomEngineSentry<HAD> randomEngineSentry(&cache->hadronizer_, ev.streamID());
0277 RandomEngineSentry<DEC> randomEngineSentryDecay(cache->decayer_.get(), ev.streamID());
0278
0279 cache->hadronizer_.setEDMEvent(ev);
0280
0281 bool passEvtGenSelector = false;
0282 std::unique_ptr<HepMC::GenEvent> event(nullptr);
0283
0284 while (!passEvtGenSelector) {
0285 event.reset();
0286 cache->hadronizer_.setEDMEvent(ev);
0287
0288 if (!cache->hadronizer_.generatePartonsAndHadronize())
0289 return false;
0290
0291
0292
0293
0294
0295
0296
0297 if (!cache->hadronizer_.decay())
0298 return false;
0299
0300 event = cache->hadronizer_.getGenEvent();
0301 if (!event.get())
0302 return false;
0303
0304
0305
0306
0307 if (cache->decayer_) {
0308 auto t = cache->decayer_->decay(event.get());
0309 if (t != event.get()) {
0310 event.reset(t);
0311 }
0312 }
0313 if (!event.get())
0314 return false;
0315
0316 passEvtGenSelector = cache->hadronizer_.select(event.get());
0317 }
0318
0319
0320
0321
0322
0323
0324 cache->hadronizer_.resetEvent(std::move(event));
0325
0326
0327
0328
0329 if (!cache->hadronizer_.residualDecay())
0330 return false;
0331
0332 cache->hadronizer_.finalizeEvent();
0333
0334 event = cache->hadronizer_.getGenEvent();
0335 if (!event.get())
0336 return false;
0337
0338 event->set_event_number(ev.id().event());
0339
0340
0341
0342
0343 std::unique_ptr<GenEventInfoProduct> genEventInfo(cache->hadronizer_.getGenEventInfo());
0344 if (!genEventInfo.get()) {
0345
0346 genEventInfo = std::make_unique<GenEventInfoProduct>(event.get());
0347 }
0348
0349 ev.put(std::move(genEventInfo));
0350
0351 std::unique_ptr<HepMCProduct> bare_product(new HepMCProduct());
0352 bare_product->addHepMCData(event.release());
0353 ev.put(std::move(bare_product), "unsmeared");
0354 cache->nEventsInLumiBlock_++;
0355 return true;
0356 }
0357
0358 template <class HAD, class DEC>
0359 std::shared_ptr<gen::GenLumiCache<HAD, DEC>> ConcurrentGeneratorFilter<HAD, DEC>::globalBeginLuminosityBlock(
0360 edm::LuminosityBlock const&, edm::EventSetup const&) const {
0361
0362 while (useInLumi_.load() == nullptr) {
0363 }
0364
0365 ++nGlobalBeginLumis_;
0366
0367
0368
0369 if (nInitializedInGlobalLumiAfterNewRun_ < nGlobalBeginRuns_) {
0370 while (!streamEndRunComplete_.load()) {
0371 }
0372 nInitializedInGlobalLumiAfterNewRun_ = nGlobalBeginRuns_;
0373 }
0374
0375 auto lumiCache = std::make_shared<gen::GenLumiCache<HAD, DEC>>();
0376 lumiCache->useInLumi_ = useInLumi_.load();
0377 lumiCache->nGlobalBeginLumis_ = nGlobalBeginLumis_;
0378 return lumiCache;
0379 }
0380
0381 template <class HAD, class DEC>
0382 void ConcurrentGeneratorFilter<HAD, DEC>::globalBeginLuminosityBlockProduce(LuminosityBlock& lumi,
0383 EventSetup const& es) const {
0384 initLumi(useInLumi_, lumi, es);
0385 std::unique_ptr<GenLumiInfoHeader> genLumiInfoHeader(useInLumi_.load()->hadronizer_.getGenLumiInfoHeader());
0386 lumi.put(std::move(genLumiInfoHeader));
0387 useInLumi_.store(nullptr);
0388 }
0389
0390 template <class HAD, class DEC>
0391 void ConcurrentGeneratorFilter<HAD, DEC>::streamBeginLuminosityBlock(StreamID id,
0392 LuminosityBlock const& lumi,
0393 EventSetup const& es) const {
0394 gen::GenStreamCache<HAD, DEC>* streamCachePtr = this->streamCache(id);
0395 if (this->luminosityBlockCache(lumi.index())->useInLumi_ != streamCachePtr) {
0396 initLumi(streamCachePtr, lumi, es);
0397 }
0398 }
0399
0400 template <class HAD, class DEC>
0401 void ConcurrentGeneratorFilter<HAD, DEC>::streamEndLuminosityBlock(StreamID id,
0402 LuminosityBlock const&,
0403 EventSetup const&) const {
0404 this->streamCache(id)->hadronizer_.cleanLHE();
0405 }
0406
0407 template <class HAD, class DEC>
0408 void ConcurrentGeneratorFilter<HAD, DEC>::streamEndLuminosityBlockSummary(StreamID id,
0409 LuminosityBlock const& lumi,
0410 EventSetup const&,
0411 gen::GenLumiSummary* iSummary) const {
0412 auto cache = this->streamCache(id);
0413 cache->hadronizer_.statistics();
0414 if (cache->decayer_)
0415 cache->decayer_->statistics();
0416
0417 GenRunInfoProduct genRunInfo = GenRunInfoProduct(cache->hadronizer_.getGenRunInfo());
0418 std::vector<GenLumiInfoProduct::ProcessInfo> GenLumiProcess;
0419 const GenRunInfoProduct::XSec& xsec = genRunInfo.internalXSec();
0420 GenLumiInfoProduct::ProcessInfo temp;
0421 unsigned int nEvtInLumiBlock_ = cache->nEventsInLumiBlock_;
0422 temp.setProcess(0);
0423 temp.setLheXSec(xsec.value(), xsec.error());
0424 temp.setNPassPos(nEvtInLumiBlock_);
0425 temp.setNPassNeg(0);
0426 temp.setNTotalPos(nEvtInLumiBlock_);
0427 temp.setNTotalNeg(0);
0428 temp.setTried(nEvtInLumiBlock_, nEvtInLumiBlock_, nEvtInLumiBlock_);
0429 temp.setSelected(nEvtInLumiBlock_, nEvtInLumiBlock_, nEvtInLumiBlock_);
0430 temp.setKilled(nEvtInLumiBlock_, nEvtInLumiBlock_, nEvtInLumiBlock_);
0431 temp.setAccepted(0, -1, -1);
0432 temp.setAcceptedBr(0, -1, -1);
0433 GenLumiProcess.push_back(temp);
0434
0435 GenLumiInfoProduct genLumiInfo;
0436 genLumiInfo.setHEPIDWTUP(-1);
0437 genLumiInfo.setProcessInfo(GenLumiProcess);
0438
0439 if (iSummary->lumiInfo_) {
0440 iSummary->lumiInfo_->mergeProduct(genLumiInfo);
0441 } else {
0442 iSummary->lumiInfo_ = std::make_unique<GenLumiInfoProduct>(std::move(genLumiInfo));
0443 }
0444
0445 cache->nEventsInLumiBlock_ = 0;
0446
0447 gen::GenStreamCache<HAD, DEC>* streamCachePtr = this->streamCache(id);
0448 unsigned long long expected = this->luminosityBlockCache(lumi.index())->nGlobalBeginLumis_;
0449 unsigned long long nextValue = expected + 1;
0450
0451
0452 if (nextNGlobalBeginLumis_.compare_exchange_strong(expected, nextValue)) {
0453 streamEndRunComplete_ = false;
0454 useInLumi_ = streamCachePtr;
0455 }
0456 }
0457
0458 template <class HAD, class DEC>
0459 void ConcurrentGeneratorFilter<HAD, DEC>::globalEndLuminosityBlock(edm::LuminosityBlock const&,
0460 edm::EventSetup const&) const {}
0461
0462 template <class HAD, class DEC>
0463 void ConcurrentGeneratorFilter<HAD, DEC>::globalEndLuminosityBlockSummary(LuminosityBlock const&,
0464 EventSetup const&,
0465 gen::GenLumiSummary*) const {}
0466
0467 template <class HAD, class DEC>
0468 void ConcurrentGeneratorFilter<HAD, DEC>::globalEndLuminosityBlockProduce(LuminosityBlock& lumi,
0469 EventSetup const&,
0470 gen::GenLumiSummary const* iSummary) const {
0471 lumi.put(std::move(iSummary->lumiInfo_));
0472 }
0473
0474 template <class HAD, class DEC>
0475 void ConcurrentGeneratorFilter<HAD, DEC>::streamEndRun(StreamID id, Run const& run, EventSetup const&) const {
0476 auto rCache = this->runCache(run.index());
0477 auto cache = this->streamCache(id);
0478
0479
0480
0481
0482
0483
0484 if (cache->initialized_) {
0485 cache->hadronizer_.statistics();
0486 if (cache->decayer_)
0487 cache->decayer_->statistics();
0488 }
0489 GenRunInfoProduct& genRunInfo = cache->hadronizer_.getGenRunInfo();
0490 GenRunInfoProduct* expect = nullptr;
0491
0492 std::unique_ptr<GenRunInfoProduct> griproduct(new GenRunInfoProduct(genRunInfo));
0493
0494 if (rCache->product_.compare_exchange_strong(expect, griproduct.get())) {
0495 griproduct.release();
0496 }
0497 if (cache == useInLumi_.load()) {
0498 streamEndRunComplete_ = true;
0499 }
0500 }
0501
0502 template <class HAD, class DEC>
0503 void ConcurrentGeneratorFilter<HAD, DEC>::globalEndRun(Run const&, EventSetup const&) const {}
0504
0505 template <class HAD, class DEC>
0506 void ConcurrentGeneratorFilter<HAD, DEC>::globalEndRunProduce(Run& run, EventSetup const&) const {
0507 run.put(this->runCache(run.index())->release());
0508 }
0509
0510 }
0511
0512 #endif