Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-08-25 00:42:14

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/TmpSimEvent.h"
0025 #include "SimG4Core/Notification/interface/TmpSimVertex.h"
0026 #include "SimG4Core/Notification/interface/TmpSimTrack.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;
0065   const edm::ParameterSetID m_psetID;
0066   int m_verbose;
0067   CMS_SA_ALLOW static const OscarMTMasterThread* s_masterThread;
0068   CMS_SA_ALLOW static edm::ParameterSetID s_psetID;
0069 };
0070 
0071 const OscarMTMasterThread* OscarMTProducer::s_masterThread = nullptr;
0072 edm::ParameterSetID OscarMTProducer::s_psetID{};
0073 
0074 namespace edm {
0075   class StreamID;
0076 }
0077 
0078 namespace {
0079   //
0080   // this machinery allows to set CLHEP static engine
0081   // to the one defined by RandomNumberGenerator service
0082   // at the beginning of an event, and reset it back to
0083   // "default-default" at the end of the event;
0084   // Dave D. has decided to implement it this way because
0085   // we don't know if there're other modules using CLHEP
0086   // static engine, thus we want to ensure that the one
0087   // we use for OscarMTProducer is unique to OscarMTProducer
0088   //
0089   // !!! This not only sets the random engine used by GEANT.
0090   // There are a few SimWatchers/SimProducers that generate
0091   // random number and also use the global CLHEP random engine
0092   // set by this code. If we ever change this design be careful
0093   // not to forget about them!!!
0094 
0095   class StaticRandomEngineSetUnset {
0096   public:
0097     StaticRandomEngineSetUnset(edm::StreamID const&);
0098     explicit StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine);
0099     ~StaticRandomEngineSetUnset();
0100 
0101     CLHEP::HepRandomEngine* currentEngine() { return m_currentEngine; }
0102 
0103   private:
0104     CLHEP::HepRandomEngine* m_currentEngine;
0105     CLHEP::HepRandomEngine* m_previousEngine;
0106   };
0107 }  // namespace
0108 
0109 OscarMTProducer::OscarMTProducer(edm::ParameterSet const& p, const OscarMTMasterThread* ms)
0110     : m_handoff{p.getUntrackedParameter<int>("workerThreadStackSize", 10 * 1024 * 1024)}, m_psetID{p.id()} {
0111   m_verbose = p.getParameter<int>("EventVerbose");
0112   // Random number generation not allowed here
0113   StaticRandomEngineSetUnset random(nullptr);
0114 
0115   auto token = edm::ServiceRegistry::instance().presentToken();
0116   m_handoff.runAndWait([this, &p, token]() {
0117     edm::ServiceRegistry::Operate guard{token};
0118     StaticRandomEngineSetUnset random(nullptr);
0119     m_runManagerWorker = std::make_unique<RunManagerMTWorker>(p, consumesCollector());
0120   });
0121   m_masterThread = (nullptr != ms) ? ms : s_masterThread;
0122   assert(m_masterThread);
0123   m_masterThread->callConsumes(consumesCollector());
0124 
0125   // List of produced containers
0126   produces<edm::SimTrackContainer>().setBranchAlias("SimTracks");
0127   produces<edm::SimVertexContainer>().setBranchAlias("SimVertices");
0128   produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelLowTof");
0129   produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelHighTof");
0130   produces<edm::PSimHitContainer>("TrackerHitsTIBLowTof");
0131   produces<edm::PSimHitContainer>("TrackerHitsTIBHighTof");
0132   produces<edm::PSimHitContainer>("TrackerHitsTIDLowTof");
0133   produces<edm::PSimHitContainer>("TrackerHitsTIDHighTof");
0134   produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapLowTof");
0135   produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapHighTof");
0136   produces<edm::PSimHitContainer>("TrackerHitsTOBLowTof");
0137   produces<edm::PSimHitContainer>("TrackerHitsTOBHighTof");
0138   produces<edm::PSimHitContainer>("TrackerHitsTECLowTof");
0139   produces<edm::PSimHitContainer>("TrackerHitsTECHighTof");
0140 
0141   produces<edm::PSimHitContainer>("TotemHitsT1");
0142   produces<edm::PSimHitContainer>("TotemHitsT2Gem");
0143   produces<edm::PSimHitContainer>("TotemHitsRP");
0144   produces<edm::PSimHitContainer>("CTPPSPixelHits");
0145   produces<edm::PSimHitContainer>("CTPPSTimingHits");
0146   produces<edm::PSimHitContainer>("FP420SI");
0147   produces<edm::PSimHitContainer>("BSCHits");
0148   produces<edm::PSimHitContainer>("PLTHits");
0149   produces<edm::PSimHitContainer>("BCM1FHits");
0150   produces<edm::PSimHitContainer>("BHMHits");
0151   produces<edm::PSimHitContainer>("FastTimerHitsBarrel");
0152   produces<edm::PSimHitContainer>("FastTimerHitsEndcap");
0153 
0154   produces<edm::PCaloHitContainer>("EcalHitsEB");
0155   produces<edm::PCaloHitContainer>("EcalHitsEE");
0156   produces<edm::PCaloHitContainer>("EcalHitsES");
0157   produces<edm::PCaloHitContainer>("HcalHits");
0158   produces<edm::PCaloHitContainer>("CaloHitsTk");
0159   produces<edm::PCaloHitContainer>("HGCHitsEE");
0160   produces<edm::PCaloHitContainer>("HGCHitsHEfront");
0161   produces<edm::PCaloHitContainer>("HGCHitsHEback");
0162 
0163   produces<edm::PSimHitContainer>("MuonDTHits");
0164   produces<edm::PSimHitContainer>("MuonCSCHits");
0165   produces<edm::PSimHitContainer>("MuonRPCHits");
0166   produces<edm::PSimHitContainer>("MuonGEMHits");
0167   produces<edm::PSimHitContainer>("MuonME0Hits");
0168   produces<edm::PCaloHitContainer>("CastorPL");
0169   produces<edm::PCaloHitContainer>("CastorFI");
0170   produces<edm::PCaloHitContainer>("CastorBU");
0171   produces<edm::PCaloHitContainer>("CastorTU");
0172   produces<edm::PCaloHitContainer>("EcalTBH4BeamHits");
0173   produces<edm::PCaloHitContainer>("HcalTB06BeamHits");
0174   produces<edm::PCaloHitContainer>("ZDCHITS");
0175   produces<edm::PCaloHitContainer>("ChamberHits");
0176   produces<edm::PCaloHitContainer>("FibreHits");
0177   produces<edm::PCaloHitContainer>("WedgeHits");
0178   produces<edm::PCaloHitContainer>("HFNoseHits");
0179   produces<edm::PCaloHitContainer>("TotemHitsT2Scint");
0180 
0181   //register any products
0182   auto& producers = m_runManagerWorker->producers();
0183   for (auto& ptr : producers) {
0184     ptr->registerProducts(producesCollector());
0185   }
0186   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer is constructed";
0187 }
0188 
0189 OscarMTProducer::~OscarMTProducer() {
0190   auto token = edm::ServiceRegistry::instance().presentToken();
0191   m_handoff.runAndWait([this, token]() {
0192     edm::ServiceRegistry::Operate guard{token};
0193     m_runManagerWorker.reset();
0194   });
0195 }
0196 
0197 std::unique_ptr<OscarMTMasterThread> OscarMTProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
0198   // Random number generation not allowed here
0199   StaticRandomEngineSetUnset random(nullptr);
0200   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::initializeGlobalCache";
0201   if (nullptr == s_masterThread) {
0202     auto ret = std::make_unique<OscarMTMasterThread>(iConfig);
0203     s_masterThread = ret.get();
0204     s_psetID = iConfig.id();
0205     return ret;
0206   }
0207   return {};
0208 }
0209 
0210 std::shared_ptr<int> OscarMTProducer::globalBeginRun(const edm::Run&,
0211                                                      const edm::EventSetup& iSetup,
0212                                                      const OscarMTMasterThread* masterThread) {
0213   // Random number generation not allowed here
0214   StaticRandomEngineSetUnset random(nullptr);
0215   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun";
0216   if (masterThread) {
0217     masterThread->beginRun(iSetup);
0218   }
0219   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun done";
0220   return std::shared_ptr<int>();
0221 }
0222 
0223 void OscarMTProducer::globalEndRun(const edm::Run&, const edm::EventSetup&, const RunContext* iContext) {
0224   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndRun";
0225   if (nullptr != iContext->global()) {
0226     iContext->global()->endRun();
0227   }
0228 }
0229 
0230 void OscarMTProducer::globalEndJob(OscarMTMasterThread* masterThread) {
0231   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndJob";
0232   if (masterThread) {
0233     masterThread->stopThread();
0234   }
0235 }
0236 
0237 void OscarMTProducer::beginRun(const edm::Run&, const edm::EventSetup& es) {
0238   if (s_psetID != m_psetID) {
0239     throw cms::Exception("DiffOscarMTProducers")
0240         << "At least two different OscarMTProducer instances have been"
0241            "loaded into the job and they have different configurations.\n"
0242            " All OscarMTProducers in a job must have exactly the same configuration.";
0243   }
0244   int id = m_runManagerWorker->getThreadIndex();
0245   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun threadID=" << id;
0246   auto token = edm::ServiceRegistry::instance().presentToken();
0247   m_handoff.runAndWait([this, &es, token]() {
0248     edm::ServiceRegistry::Operate guard{token};
0249     m_runManagerWorker->beginRun(es);
0250     m_runManagerWorker->initializeG4(m_masterThread->runManagerMasterPtr(), es);
0251   });
0252   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun done threadID=" << id;
0253 }
0254 
0255 void OscarMTProducer::endRun(const edm::Run&, const edm::EventSetup&) {
0256   StaticRandomEngineSetUnset random(nullptr);
0257   int id = m_runManagerWorker->getThreadIndex();
0258   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun threadID=" << id;
0259   auto token = edm::ServiceRegistry::instance().presentToken();
0260   m_handoff.runAndWait([this, token]() {
0261     edm::ServiceRegistry::Operate guard{token};
0262     m_runManagerWorker->endRun();
0263   });
0264   edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun done threadID=" << id;
0265 }
0266 
0267 void OscarMTProducer::produce(edm::Event& e, const edm::EventSetup& es) {
0268   StaticRandomEngineSetUnset random(e.streamID());
0269   auto engine = random.currentEngine();
0270   int id = m_runManagerWorker->getThreadIndex();
0271   if (0 < m_verbose) {
0272     edm::LogVerbatim("SimG4CoreApplication")
0273         << "Produce event " << e.id() << " stream " << e.streamID() << " threadID=" << id;
0274     //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
0275   }
0276 
0277   auto& sTk = m_runManagerWorker->sensTkDetectors();
0278   auto& sCalo = m_runManagerWorker->sensCaloDetectors();
0279 
0280   TmpSimEvent* evt = nullptr;
0281   auto token = edm::ServiceRegistry::instance().presentToken();
0282   m_handoff.runAndWait([this, &e, &es, &evt, token, engine]() {
0283     edm::ServiceRegistry::Operate guard{token};
0284     StaticRandomEngineSetUnset random(engine);
0285     evt = m_runManagerWorker->produce(e, es, m_masterThread->runManagerMaster());
0286   });
0287 
0288   std::unique_ptr<edm::SimTrackContainer> p1(new edm::SimTrackContainer);
0289   std::unique_ptr<edm::SimVertexContainer> p2(new edm::SimVertexContainer);
0290   evt->load(*p1);
0291   evt->load(*p2);
0292 
0293   if (0 < m_verbose) {
0294     edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p2->size() << " SimVertex objects";
0295     if (1 < m_verbose) {
0296       int nn = p2->size();
0297       for (int i = 0; i < nn; ++i) {
0298         edm::LogVerbatim("Vertex") << " " << (*p2)[i] << " " << (*p2)[i].processType();
0299       }
0300     }
0301     edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p1->size() << " SimTrack objects";
0302     if (1 < m_verbose) {
0303       int nn = p1->size();
0304       for (int i = 0; i < nn; ++i) {
0305         edm::LogVerbatim("Track") << " " << i << ". " << (*p1)[i] << " " << (*p1)[i].crossedBoundary() << " "
0306                                   << (*p1)[i].getIDAtBoundary();
0307       }
0308     }
0309   }
0310   e.put(std::move(p1));
0311   e.put(std::move(p2));
0312 
0313   for (auto& tracker : sTk) {
0314     const std::vector<std::string>& v = tracker->getNames();
0315     for (auto& name : v) {
0316       std::unique_ptr<edm::PSimHitContainer> product(new edm::PSimHitContainer);
0317       tracker->fillHits(*product, name);
0318       if (0 < m_verbose && product != nullptr && !product->empty())
0319         edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " tracker hits <" << name << ">";
0320       e.put(std::move(product), name);
0321     }
0322   }
0323   for (auto& calo : sCalo) {
0324     const std::vector<std::string>& v = calo->getNames();
0325     for (auto& name : v) {
0326       std::unique_ptr<edm::PCaloHitContainer> product(new edm::PCaloHitContainer);
0327       calo->fillHits(*product, name);
0328       if (0 < m_verbose && product != nullptr && !product->empty())
0329         edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " calo hits <" << name << ">";
0330       e.put(std::move(product), name);
0331     }
0332   }
0333 
0334   auto& producers = m_runManagerWorker->producers();
0335   for (auto& prod : producers) {
0336     prod.get()->produce(e, es);
0337   }
0338   if (0 < m_verbose) {
0339     edm::LogVerbatim("SimG4CoreApplication")
0340         << "Event is produced event " << e.id() << " streamID=" << e.streamID() << " threadID=" << id;
0341     //edm::LogWarning("SimG4CoreApplication") << "EventID=" << e.id() << " rand=" << G4UniformRand();
0342   }
0343 }
0344 
0345 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(edm::StreamID const& streamID) {
0346   edm::Service<edm::RandomNumberGenerator> rng;
0347   if (!rng.isAvailable()) {
0348     throw cms::Exception("Configuration")
0349         << "The OscarMTProducer module requires the RandomNumberGeneratorService\n"
0350            "which is not present in the configuration file.  You must add the service\n"
0351            "in the configuration file if you want to run OscarMTProducer";
0352   }
0353   m_currentEngine = &(rng->getEngine(streamID));
0354 
0355   m_previousEngine = G4Random::getTheEngine();
0356   G4Random::setTheEngine(m_currentEngine);
0357 }
0358 
0359 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine) {
0360   m_currentEngine = engine;
0361   m_previousEngine = G4Random::getTheEngine();
0362   G4Random::setTheEngine(m_currentEngine);
0363 }
0364 
0365 StaticRandomEngineSetUnset::~StaticRandomEngineSetUnset() { G4Random::setTheEngine(m_previousEngine); }
0366 
0367 DEFINE_FWK_MODULE(OscarMTProducer);