Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-30 23:17:20

0001 #include <iostream>
0002 #include <memory>
0003 
0004 #include "FWCore/Framework/interface/stream/EDProducer.h"
0005 #include "FWCore/Framework/interface/Event.h"
0006 #include "FWCore/Framework/interface/MakerMacros.h"
0007 #include "FWCore/Framework/interface/EventSetup.h"
0008 #include "FWCore/Framework/interface/Run.h"
0009 
0010 #include "FWCore/PluginManager/interface/PluginManager.h"
0011 #include "FWCore/Framework/interface/MakerMacros.h"
0012 #include "FWCore/Framework/interface/ConsumesCollector.h"
0013 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0014 
0015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0016 #include "FWCore/ServiceRegistry/interface/Service.h"
0017 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
0018 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
0019 #include "FWCore/Utilities/interface/Exception.h"
0020 
0021 #include "SimG4Core/Application/interface/OscarMTMasterThread.h"
0022 #include "SimG4Core/Application/interface/RunManagerMT.h"
0023 #include "SimG4Core/Application/interface/RunManagerMTWorker.h"
0024 #include "SimG4Core/Notification/interface/G4SimEvent.h"
0025 #include "SimG4Core/Notification/interface/G4SimVertex.h"
0026 #include "SimG4Core/Notification/interface/G4SimTrack.h"
0027 
0028 #include "SimG4Core/SensitiveDetector/interface/SensitiveTkDetector.h"
0029 #include "SimG4Core/SensitiveDetector/interface/SensitiveCaloDetector.h"
0030 
0031 #include "SimG4Core/Watcher/interface/SimProducer.h"
0032 
0033 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
0034 #include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
0035 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
0036 #include "SimDataFormats/CaloHit/interface/PCaloHitContainer.h"
0037 
0038 #include "SimG4Core/Application/interface/ThreadHandoff.h"
0039 
0040 #include "Randomize.hh"
0041 
0042 // for some reason void doesn't compile
0043 class OscarMTProducer : public edm::stream::EDProducer<edm::GlobalCache<OscarMTMasterThread>, edm::RunCache<int> > {
0044 public:
0045   typedef std::vector<std::shared_ptr<SimProducer> > Producers;
0046 
0047   explicit OscarMTProducer(edm::ParameterSet const& p, const OscarMTMasterThread*);
0048   ~OscarMTProducer() override;
0049 
0050   static std::unique_ptr<OscarMTMasterThread> initializeGlobalCache(const edm::ParameterSet& iConfig);
0051   static std::shared_ptr<int> globalBeginRun(const edm::Run& iRun,
0052                                              const edm::EventSetup& iSetup,
0053                                              const OscarMTMasterThread* masterThread);
0054   static void globalEndRun(const edm::Run& iRun, const edm::EventSetup& iSetup, const RunContext* iContext);
0055   static void globalEndJob(OscarMTMasterThread* masterThread);
0056 
0057   void beginRun(const edm::Run& r, const edm::EventSetup& c) override;
0058   void endRun(const edm::Run& r, const edm::EventSetup& c) override;
0059   void produce(edm::Event& e, const edm::EventSetup& c) override;
0060 
0061 private:
0062   omt::ThreadHandoff m_handoff;
0063   std::unique_ptr<RunManagerMTWorker> m_runManagerWorker;
0064   const OscarMTMasterThread* m_masterThread = nullptr;
0065   int m_verbose;
0066 };
0067 
0068 namespace edm {
0069   class StreamID;
0070 }
0071 
0072 namespace {
0073   //
0074   // this machinery allows to set CLHEP static engine
0075   // to the one defined by RandomNumberGenerator service
0076   // at the beginning of an event, and reset it back to
0077   // "default-default" at the end of the event;
0078   // Dave D. has decided to implement it this way because
0079   // we don't know if there're other modules using CLHEP
0080   // static engine, thus we want to ensure that the one
0081   // we use for OscarMTProducer is unique to OscarMTProducer
0082   //
0083   // !!! This not only sets the random engine used by GEANT.
0084   // There are a few SimWatchers/SimProducers that generate
0085   // random number and also use the global CLHEP random engine
0086   // set by this code. If we ever change this design be careful
0087   // not to forget about them!!!
0088 
0089   class StaticRandomEngineSetUnset {
0090   public:
0091     StaticRandomEngineSetUnset(edm::StreamID const&);
0092     explicit StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine);
0093     ~StaticRandomEngineSetUnset();
0094 
0095     CLHEP::HepRandomEngine* currentEngine() { return m_currentEngine; }
0096 
0097   private:
0098     CLHEP::HepRandomEngine* m_currentEngine;
0099     CLHEP::HepRandomEngine* m_previousEngine;
0100   };
0101 }  // namespace
0102 
0103 OscarMTProducer::OscarMTProducer(edm::ParameterSet const& p, const OscarMTMasterThread* ms)
0104     : m_handoff{p.getUntrackedParameter<int>("workerThreadStackSize", 10 * 1024 * 1024)} {
0105   m_verbose = p.getParameter<int>("EventVerbose");
0106   // Random number generation not allowed here
0107   StaticRandomEngineSetUnset random(nullptr);
0108 
0109   auto token = edm::ServiceRegistry::instance().presentToken();
0110   m_handoff.runAndWait([this, &p, token]() {
0111     edm::ServiceRegistry::Operate guard{token};
0112     StaticRandomEngineSetUnset random(nullptr);
0113     m_runManagerWorker = std::make_unique<RunManagerMTWorker>(p, consumesCollector());
0114   });
0115   m_masterThread = ms;
0116   m_masterThread->callConsumes(consumesCollector());
0117 
0118   // List of produced containers
0119   produces<edm::SimTrackContainer>().setBranchAlias("SimTracks");
0120   produces<edm::SimVertexContainer>().setBranchAlias("SimVertices");
0121   produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelLowTof");
0122   produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelHighTof");
0123   produces<edm::PSimHitContainer>("TrackerHitsTIBLowTof");
0124   produces<edm::PSimHitContainer>("TrackerHitsTIBHighTof");
0125   produces<edm::PSimHitContainer>("TrackerHitsTIDLowTof");
0126   produces<edm::PSimHitContainer>("TrackerHitsTIDHighTof");
0127   produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapLowTof");
0128   produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapHighTof");
0129   produces<edm::PSimHitContainer>("TrackerHitsTOBLowTof");
0130   produces<edm::PSimHitContainer>("TrackerHitsTOBHighTof");
0131   produces<edm::PSimHitContainer>("TrackerHitsTECLowTof");
0132   produces<edm::PSimHitContainer>("TrackerHitsTECHighTof");
0133 
0134   produces<edm::PSimHitContainer>("TotemHitsT1");
0135   produces<edm::PSimHitContainer>("TotemHitsT2Gem");
0136   produces<edm::PSimHitContainer>("TotemHitsRP");
0137   produces<edm::PSimHitContainer>("CTPPSPixelHits");
0138   produces<edm::PSimHitContainer>("CTPPSTimingHits");
0139   produces<edm::PSimHitContainer>("FP420SI");
0140   produces<edm::PSimHitContainer>("BSCHits");
0141   produces<edm::PSimHitContainer>("PLTHits");
0142   produces<edm::PSimHitContainer>("BCM1FHits");
0143   produces<edm::PSimHitContainer>("BHMHits");
0144   produces<edm::PSimHitContainer>("FastTimerHitsBarrel");
0145   produces<edm::PSimHitContainer>("FastTimerHitsEndcap");
0146 
0147   produces<edm::PCaloHitContainer>("EcalHitsEB");
0148   produces<edm::PCaloHitContainer>("EcalHitsEE");
0149   produces<edm::PCaloHitContainer>("EcalHitsES");
0150   produces<edm::PCaloHitContainer>("HcalHits");
0151   produces<edm::PCaloHitContainer>("CaloHitsTk");
0152   produces<edm::PCaloHitContainer>("HGCHitsEE");
0153   produces<edm::PCaloHitContainer>("HGCHitsHEfront");
0154   produces<edm::PCaloHitContainer>("HGCHitsHEback");
0155 
0156   produces<edm::PSimHitContainer>("MuonDTHits");
0157   produces<edm::PSimHitContainer>("MuonCSCHits");
0158   produces<edm::PSimHitContainer>("MuonRPCHits");
0159   produces<edm::PSimHitContainer>("MuonGEMHits");
0160   produces<edm::PSimHitContainer>("MuonME0Hits");
0161   produces<edm::PCaloHitContainer>("CastorPL");
0162   produces<edm::PCaloHitContainer>("CastorFI");
0163   produces<edm::PCaloHitContainer>("CastorBU");
0164   produces<edm::PCaloHitContainer>("CastorTU");
0165   produces<edm::PCaloHitContainer>("EcalTBH4BeamHits");
0166   produces<edm::PCaloHitContainer>("HcalTB06BeamHits");
0167   produces<edm::PCaloHitContainer>("ZDCHITS");
0168   produces<edm::PCaloHitContainer>("ChamberHits");
0169   produces<edm::PCaloHitContainer>("FibreHits");
0170   produces<edm::PCaloHitContainer>("WedgeHits");
0171   produces<edm::PCaloHitContainer>("HFNoseHits");
0172   produces<edm::PCaloHitContainer>("TotemHitsT2Scint");
0173 
0174   //register any products
0175   auto& producers = m_runManagerWorker->producers();
0176   for (auto& ptr : producers) {
0177     ptr->registerProducts(producesCollector());
0178   }
0179   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer is constructed";
0180 }
0181 
0182 OscarMTProducer::~OscarMTProducer() {
0183   auto token = edm::ServiceRegistry::instance().presentToken();
0184   m_handoff.runAndWait([this, token]() {
0185     edm::ServiceRegistry::Operate guard{token};
0186     m_runManagerWorker.reset();
0187   });
0188 }
0189 
0190 std::unique_ptr<OscarMTMasterThread> OscarMTProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
0191   // Random number generation not allowed here
0192   StaticRandomEngineSetUnset random(nullptr);
0193   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::initializeGlobalCache";
0194 
0195   return std::make_unique<OscarMTMasterThread>(iConfig);
0196 }
0197 
0198 std::shared_ptr<int> OscarMTProducer::globalBeginRun(const edm::Run&,
0199                                                      const edm::EventSetup& iSetup,
0200                                                      const OscarMTMasterThread* masterThread) {
0201   // Random number generation not allowed here
0202   StaticRandomEngineSetUnset random(nullptr);
0203   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun";
0204   masterThread->beginRun(iSetup);
0205   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun done";
0206   return std::shared_ptr<int>();
0207 }
0208 
0209 void OscarMTProducer::globalEndRun(const edm::Run&, const edm::EventSetup&, const RunContext* iContext) {
0210   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndRun";
0211   iContext->global()->endRun();
0212 }
0213 
0214 void OscarMTProducer::globalEndJob(OscarMTMasterThread* masterThread) {
0215   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndJob";
0216   masterThread->stopThread();
0217 }
0218 
0219 void OscarMTProducer::beginRun(const edm::Run&, const edm::EventSetup& es) {
0220   int id = m_runManagerWorker->getThreadIndex();
0221   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun threadID=" << id;
0222   auto token = edm::ServiceRegistry::instance().presentToken();
0223   m_handoff.runAndWait([this, &es, token]() {
0224     edm::ServiceRegistry::Operate guard{token};
0225     m_runManagerWorker->beginRun(es);
0226     m_runManagerWorker->initializeG4(m_masterThread->runManagerMasterPtr(), es);
0227   });
0228   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun done threadID=" << id;
0229 }
0230 
0231 void OscarMTProducer::endRun(const edm::Run&, const edm::EventSetup&) {
0232   StaticRandomEngineSetUnset random(nullptr);
0233   int id = m_runManagerWorker->getThreadIndex();
0234   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun threadID=" << id;
0235   auto token = edm::ServiceRegistry::instance().presentToken();
0236   m_handoff.runAndWait([this, token]() {
0237     edm::ServiceRegistry::Operate guard{token};
0238     m_runManagerWorker->endRun();
0239   });
0240   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun done threadID=" << id;
0241 }
0242 
0243 void OscarMTProducer::produce(edm::Event& e, const edm::EventSetup& es) {
0244   StaticRandomEngineSetUnset random(e.streamID());
0245   auto engine = random.currentEngine();
0246   int id = m_runManagerWorker->getThreadIndex();
0247   if (0 < m_verbose) {
0248     edm::LogVerbatim("SimG4CoreApplication")
0249         << "Produce event " << e.id() << " stream " << e.streamID() << " threadID=" << id;
0250     //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
0251   }
0252 
0253   auto& sTk = m_runManagerWorker->sensTkDetectors();
0254   auto& sCalo = m_runManagerWorker->sensCaloDetectors();
0255 
0256   G4SimEvent* evt = nullptr;
0257   auto token = edm::ServiceRegistry::instance().presentToken();
0258   m_handoff.runAndWait([this, &e, &es, &evt, token, engine]() {
0259     edm::ServiceRegistry::Operate guard{token};
0260     StaticRandomEngineSetUnset random(engine);
0261     evt = m_runManagerWorker->produce(e, es, globalCache()->runManagerMaster());
0262   });
0263 
0264   std::unique_ptr<edm::SimTrackContainer> p1(new edm::SimTrackContainer);
0265   std::unique_ptr<edm::SimVertexContainer> p2(new edm::SimVertexContainer);
0266   evt->load(*p1);
0267   evt->load(*p2);
0268 
0269   if (0 < m_verbose) {
0270     edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p2->size() << " SimVertex objects";
0271     if (1 < m_verbose) {
0272       int nn = p2->size();
0273       for (int i = 0; i < nn; ++i) {
0274         edm::LogVerbatim("Vertex") << " " << (*p2)[i] << " " << (*p2)[i].processType();
0275       }
0276     }
0277     edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p1->size() << " SimTrack objects";
0278     if (1 < m_verbose) {
0279       int nn = p1->size();
0280       for (int i = 0; i < nn; ++i) {
0281         edm::LogVerbatim("Track") << " " << i << ". " << (*p1)[i] << " " << (*p1)[i].crossedBoundary() << " "
0282                                   << (*p1)[i].getIDAtBoundary();
0283       }
0284     }
0285   }
0286   e.put(std::move(p1));
0287   e.put(std::move(p2));
0288 
0289   for (auto& tracker : sTk) {
0290     const std::vector<std::string>& v = tracker->getNames();
0291     for (auto& name : v) {
0292       std::unique_ptr<edm::PSimHitContainer> product(new edm::PSimHitContainer);
0293       tracker->fillHits(*product, name);
0294       if (0 < m_verbose && product != nullptr && !product->empty())
0295         edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " tracker hits <" << name << ">";
0296       e.put(std::move(product), name);
0297     }
0298   }
0299   for (auto& calo : sCalo) {
0300     const std::vector<std::string>& v = calo->getNames();
0301     for (auto& name : v) {
0302       std::unique_ptr<edm::PCaloHitContainer> product(new edm::PCaloHitContainer);
0303       calo->fillHits(*product, name);
0304       if (0 < m_verbose && product != nullptr && !product->empty())
0305         edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " calo hits <" << name << ">";
0306       e.put(std::move(product), name);
0307     }
0308   }
0309 
0310   auto& producers = m_runManagerWorker->producers();
0311   for (auto& prod : producers) {
0312     prod.get()->produce(e, es);
0313   }
0314   if (0 < m_verbose) {
0315     edm::LogVerbatim("SimG4CoreApplication")
0316         << "Event is produced event " << e.id() << " streamID=" << e.streamID() << " threadID=" << id;
0317     //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
0318   }
0319 }
0320 
0321 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(edm::StreamID const& streamID) {
0322   edm::Service<edm::RandomNumberGenerator> rng;
0323   if (!rng.isAvailable()) {
0324     throw cms::Exception("Configuration")
0325         << "The OscarMTProducer module requires the RandomNumberGeneratorService\n"
0326            "which is not present in the configuration file.  You must add the service\n"
0327            "in the configuration file if you want to run OscarMTProducer";
0328   }
0329   m_currentEngine = &(rng->getEngine(streamID));
0330 
0331   m_previousEngine = G4Random::getTheEngine();
0332   G4Random::setTheEngine(m_currentEngine);
0333 }
0334 
0335 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine) {
0336   m_currentEngine = engine;
0337   m_previousEngine = G4Random::getTheEngine();
0338   G4Random::setTheEngine(m_currentEngine);
0339 }
0340 
0341 StaticRandomEngineSetUnset::~StaticRandomEngineSetUnset() { G4Random::setTheEngine(m_previousEngine); }
0342 
0343 DEFINE_FWK_MODULE(OscarMTProducer);