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
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
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
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 }
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
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
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
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
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
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
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
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);