CMS 3D CMS Logo

OscarMTProducer.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <memory>
3 
9 
14 
20 
27 
30 
32 
37 
39 
40 #include "Randomize.hh"
41 
42 // for some reason void doesn't compile
43 class OscarMTProducer : public edm::stream::EDProducer<edm::GlobalCache<OscarMTMasterThread>, edm::RunCache<int> > {
44 public:
45  typedef std::vector<std::shared_ptr<SimProducer> > Producers;
46 
47  explicit OscarMTProducer(edm::ParameterSet const& p, const OscarMTMasterThread*);
48  ~OscarMTProducer() override;
49 
50  static std::unique_ptr<OscarMTMasterThread> initializeGlobalCache(const edm::ParameterSet& iConfig);
51  static std::shared_ptr<int> globalBeginRun(const edm::Run& iRun,
52  const edm::EventSetup& iSetup,
53  const OscarMTMasterThread* masterThread);
54  static void globalEndRun(const edm::Run& iRun, const edm::EventSetup& iSetup, const RunContext* iContext);
55  static void globalEndJob(OscarMTMasterThread* masterThread);
56 
57  void beginRun(const edm::Run& r, const edm::EventSetup& c) override;
58  void endRun(const edm::Run& r, const edm::EventSetup& c) override;
59  void produce(edm::Event& e, const edm::EventSetup& c) override;
60 
61 private:
63  std::unique_ptr<RunManagerMTWorker> m_runManagerWorker;
66  int m_verbose;
69 };
70 
73 
74 namespace edm {
75  class StreamID;
76 }
77 
78 namespace {
79  //
80  // this machinery allows to set CLHEP static engine
81  // to the one defined by RandomNumberGenerator service
82  // at the beginning of an event, and reset it back to
83  // "default-default" at the end of the event;
84  // Dave D. has decided to implement it this way because
85  // we don't know if there're other modules using CLHEP
86  // static engine, thus we want to ensure that the one
87  // we use for OscarMTProducer is unique to OscarMTProducer
88  //
89  // !!! This not only sets the random engine used by GEANT.
90  // There are a few SimWatchers/SimProducers that generate
91  // random number and also use the global CLHEP random engine
92  // set by this code. If we ever change this design be careful
93  // not to forget about them!!!
94 
95  class StaticRandomEngineSetUnset {
96  public:
97  StaticRandomEngineSetUnset(edm::StreamID const&);
98  explicit StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine);
99  ~StaticRandomEngineSetUnset();
100 
101  CLHEP::HepRandomEngine* currentEngine() { return m_currentEngine; }
102 
103  private:
104  CLHEP::HepRandomEngine* m_currentEngine;
105  CLHEP::HepRandomEngine* m_previousEngine;
106  };
107 } // namespace
108 
110  : m_handoff{p.getUntrackedParameter<int>("workerThreadStackSize", 10 * 1024 * 1024)}, m_psetID{p.id()} {
111  m_verbose = p.getParameter<int>("EventVerbose");
112  // Random number generation not allowed here
113  StaticRandomEngineSetUnset random(nullptr);
114 
116  m_handoff.runAndWait([this, &p, token]() {
118  StaticRandomEngineSetUnset random(nullptr);
119  m_runManagerWorker = std::make_unique<RunManagerMTWorker>(p, consumesCollector());
120  });
121  m_masterThread = ms ? ms : s_masterThread;
122  assert(m_masterThread);
123  m_masterThread->callConsumes(consumesCollector());
124 
125  // List of produced containers
126  produces<edm::SimTrackContainer>().setBranchAlias("SimTracks");
127  produces<edm::SimVertexContainer>().setBranchAlias("SimVertices");
128  produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelLowTof");
129  produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelHighTof");
130  produces<edm::PSimHitContainer>("TrackerHitsTIBLowTof");
131  produces<edm::PSimHitContainer>("TrackerHitsTIBHighTof");
132  produces<edm::PSimHitContainer>("TrackerHitsTIDLowTof");
133  produces<edm::PSimHitContainer>("TrackerHitsTIDHighTof");
134  produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapLowTof");
135  produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapHighTof");
136  produces<edm::PSimHitContainer>("TrackerHitsTOBLowTof");
137  produces<edm::PSimHitContainer>("TrackerHitsTOBHighTof");
138  produces<edm::PSimHitContainer>("TrackerHitsTECLowTof");
139  produces<edm::PSimHitContainer>("TrackerHitsTECHighTof");
140 
141  produces<edm::PSimHitContainer>("TotemHitsT1");
142  produces<edm::PSimHitContainer>("TotemHitsT2Gem");
143  produces<edm::PSimHitContainer>("TotemHitsRP");
144  produces<edm::PSimHitContainer>("CTPPSPixelHits");
145  produces<edm::PSimHitContainer>("CTPPSTimingHits");
146  produces<edm::PSimHitContainer>("FP420SI");
147  produces<edm::PSimHitContainer>("BSCHits");
148  produces<edm::PSimHitContainer>("PLTHits");
149  produces<edm::PSimHitContainer>("BCM1FHits");
150  produces<edm::PSimHitContainer>("BHMHits");
151  produces<edm::PSimHitContainer>("FastTimerHitsBarrel");
152  produces<edm::PSimHitContainer>("FastTimerHitsEndcap");
153 
154  produces<edm::PCaloHitContainer>("EcalHitsEB");
155  produces<edm::PCaloHitContainer>("EcalHitsEE");
156  produces<edm::PCaloHitContainer>("EcalHitsES");
157  produces<edm::PCaloHitContainer>("HcalHits");
158  produces<edm::PCaloHitContainer>("CaloHitsTk");
159  produces<edm::PCaloHitContainer>("HGCHitsEE");
160  produces<edm::PCaloHitContainer>("HGCHitsHEfront");
161  produces<edm::PCaloHitContainer>("HGCHitsHEback");
162 
163  produces<edm::PSimHitContainer>("MuonDTHits");
164  produces<edm::PSimHitContainer>("MuonCSCHits");
165  produces<edm::PSimHitContainer>("MuonRPCHits");
166  produces<edm::PSimHitContainer>("MuonGEMHits");
167  produces<edm::PSimHitContainer>("MuonME0Hits");
168  produces<edm::PCaloHitContainer>("CastorPL");
169  produces<edm::PCaloHitContainer>("CastorFI");
170  produces<edm::PCaloHitContainer>("CastorBU");
171  produces<edm::PCaloHitContainer>("CastorTU");
172  produces<edm::PCaloHitContainer>("EcalTBH4BeamHits");
173  produces<edm::PCaloHitContainer>("HcalTB06BeamHits");
174  produces<edm::PCaloHitContainer>("ZDCHITS");
175  produces<edm::PCaloHitContainer>("ChamberHits");
176  produces<edm::PCaloHitContainer>("FibreHits");
177  produces<edm::PCaloHitContainer>("WedgeHits");
178  produces<edm::PCaloHitContainer>("HFNoseHits");
179  produces<edm::PCaloHitContainer>("TotemHitsT2Scint");
180 
181  //register any products
182  auto& producers = m_runManagerWorker->producers();
183  for (auto& ptr : producers) {
184  ptr->registerProducts(producesCollector());
185  }
186  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer is constructed";
187 }
188 
191  m_handoff.runAndWait([this, token]() {
193  m_runManagerWorker.reset();
194  });
195 }
196 
197 std::unique_ptr<OscarMTMasterThread> OscarMTProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
198  // Random number generation not allowed here
199  StaticRandomEngineSetUnset random(nullptr);
200  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::initializeGlobalCache";
201  if (nullptr == s_masterThread) {
202  auto ret = std::make_unique<OscarMTMasterThread>(iConfig);
203  s_masterThread = ret.get();
204  s_psetID = iConfig.id();
205  return ret;
206  }
207  return {};
208 }
209 
210 std::shared_ptr<int> OscarMTProducer::globalBeginRun(const edm::Run&,
211  const edm::EventSetup& iSetup,
212  const OscarMTMasterThread* masterThread) {
213  // Random number generation not allowed here
214  StaticRandomEngineSetUnset random(nullptr);
215  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun";
216  if (masterThread) {
217  masterThread->beginRun(iSetup);
218  }
219  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun done";
220  return std::shared_ptr<int>();
221 }
222 
223 void OscarMTProducer::globalEndRun(const edm::Run&, const edm::EventSetup&, const RunContext* iContext) {
224  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndRun";
225  if (nullptr != iContext->global()) {
226  iContext->global()->endRun();
227  }
228 }
229 
231  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndJob";
232  if (masterThread) {
233  masterThread->stopThread();
234  }
235 }
236 
238  if (s_psetID != m_psetID) {
239  throw cms::Exception("DiffOscarMTProducers")
240  << "At least two different OscarMTProducer instances have been"
241  "loaded into the job and they have different configurations.\n"
242  " All OscarMTProducers in a job must have exactly the same configuration.";
243  }
244  int id = m_runManagerWorker->getThreadIndex();
245  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun threadID=" << id;
247  m_handoff.runAndWait([this, &es, token]() {
249  m_runManagerWorker->beginRun(es);
251  });
252  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun done threadID=" << id;
253 }
254 
256  StaticRandomEngineSetUnset random(nullptr);
257  int id = m_runManagerWorker->getThreadIndex();
258  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun threadID=" << id;
260  m_handoff.runAndWait([this, token]() {
262  m_runManagerWorker->endRun();
263  });
264  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun done threadID=" << id;
265 }
266 
268  StaticRandomEngineSetUnset random(e.streamID());
269  auto engine = random.currentEngine();
270  int id = m_runManagerWorker->getThreadIndex();
271  if (0 < m_verbose) {
272  edm::LogVerbatim("SimG4CoreApplication")
273  << "Produce event " << e.id() << " stream " << e.streamID() << " threadID=" << id;
274  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
275  }
276 
277  auto& sTk = m_runManagerWorker->sensTkDetectors();
278  auto& sCalo = m_runManagerWorker->sensCaloDetectors();
279 
280  G4SimEvent* evt = nullptr;
282  m_handoff.runAndWait([this, &e, &es, &evt, token, engine]() {
284  StaticRandomEngineSetUnset random(engine);
285  evt = m_runManagerWorker->produce(e, es, m_masterThread->runManagerMaster());
286  });
287 
288  std::unique_ptr<edm::SimTrackContainer> p1(new edm::SimTrackContainer);
289  std::unique_ptr<edm::SimVertexContainer> p2(new edm::SimVertexContainer);
290  evt->load(*p1);
291  evt->load(*p2);
292 
293  if (0 < m_verbose) {
294  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p2->size() << " SimVertex objects";
295  if (1 < m_verbose) {
296  int nn = p2->size();
297  for (int i = 0; i < nn; ++i) {
298  edm::LogVerbatim("Vertex") << " " << (*p2)[i] << " " << (*p2)[i].processType();
299  }
300  }
301  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p1->size() << " SimTrack objects";
302  if (1 < m_verbose) {
303  int nn = p1->size();
304  for (int i = 0; i < nn; ++i) {
305  edm::LogVerbatim("Track") << " " << i << ". " << (*p1)[i] << " " << (*p1)[i].crossedBoundary() << " "
306  << (*p1)[i].getIDAtBoundary();
307  }
308  }
309  }
310  e.put(std::move(p1));
311  e.put(std::move(p2));
312 
313  for (auto& tracker : sTk) {
314  const std::vector<std::string>& v = tracker->getNames();
315  for (auto& name : v) {
316  std::unique_ptr<edm::PSimHitContainer> product(new edm::PSimHitContainer);
317  tracker->fillHits(*product, name);
318  if (0 < m_verbose && product != nullptr && !product->empty())
319  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " tracker hits <" << name << ">";
320  e.put(std::move(product), name);
321  }
322  }
323  for (auto& calo : sCalo) {
324  const std::vector<std::string>& v = calo->getNames();
325  for (auto& name : v) {
326  std::unique_ptr<edm::PCaloHitContainer> product(new edm::PCaloHitContainer);
327  calo->fillHits(*product, name);
328  if (0 < m_verbose && product != nullptr && !product->empty())
329  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " calo hits <" << name << ">";
330  e.put(std::move(product), name);
331  }
332  }
333 
334  auto& producers = m_runManagerWorker->producers();
335  for (auto& prod : producers) {
336  prod.get()->produce(e, es);
337  }
338  if (0 < m_verbose) {
339  edm::LogVerbatim("SimG4CoreApplication")
340  << "Event is produced event " << e.id() << " streamID=" << e.streamID() << " threadID=" << id;
341  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
342  }
343 }
344 
345 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(edm::StreamID const& streamID) {
347  if (!rng.isAvailable()) {
348  throw cms::Exception("Configuration")
349  << "The OscarMTProducer module requires the RandomNumberGeneratorService\n"
350  "which is not present in the configuration file. You must add the service\n"
351  "in the configuration file if you want to run OscarMTProducer";
352  }
353  m_currentEngine = &(rng->getEngine(streamID));
354 
355  m_previousEngine = G4Random::getTheEngine();
356  G4Random::setTheEngine(m_currentEngine);
357 }
358 
359 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine) {
360  m_currentEngine = engine;
361  m_previousEngine = G4Random::getTheEngine();
362  G4Random::setTheEngine(m_currentEngine);
363 }
364 
365 StaticRandomEngineSetUnset::~StaticRandomEngineSetUnset() { G4Random::setTheEngine(m_previousEngine); }
366 
Log< level::Info, true > LogVerbatim
RunManagerMT * runManagerMasterPtr() const
std::vector< PCaloHit > PCaloHitContainer
#define CMS_SA_ALLOW
static std::shared_ptr< int > globalBeginRun(const edm::Run &iRun, const edm::EventSetup &iSetup, const OscarMTMasterThread *masterThread)
std::unique_ptr< RunManagerMTWorker > m_runManagerWorker
ret
prodAgent to be discontinued
OscarMTProducer(edm::ParameterSet const &p, const OscarMTMasterThread *)
void beginRun(const edm::EventSetup &iSetup) const
~OscarMTProducer() override
std::vector< std::shared_ptr< SimProducer > > Producers
static edm::ParameterSetID s_psetID
void runAndWait(F &&iF)
Definition: ThreadHandoff.h:42
assert(be >=bs)
virtual CLHEP::HepRandomEngine & getEngine(StreamID const &)=0
Use this engine in event methods.
void load(edm::SimTrackContainer &c) const
Definition: G4SimEvent.cc:36
static const OscarMTMasterThread * s_masterThread
RunManagerMT & runManagerMaster() const
ParameterSetID id() const
const OscarMTMasterThread * m_masterThread
const edm::ParameterSetID m_psetID
static ServiceRegistry & instance()
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void produce(edm::Event &e, const edm::EventSetup &c) override
static void globalEndRun(const edm::Run &iRun, const edm::EventSetup &iSetup, const RunContext *iContext)
static std::unique_ptr< OscarMTMasterThread > initializeGlobalCache(const edm::ParameterSet &iConfig)
void endRun(const edm::Run &r, const edm::EventSetup &c) override
std::vector< SimVertex > SimVertexContainer
HLT enums.
G const * global() const
Definition: Contexts.h:35
bool isAvailable() const
Definition: Service.h:40
std::vector< PSimHit > PSimHitContainer
omt::ThreadHandoff m_handoff
static void globalEndJob(OscarMTMasterThread *masterThread)
std::vector< SimTrack > SimTrackContainer
ServiceToken presentToken() const
def move(src, dest)
Definition: eostools.py:511
Definition: Common.h:9
Definition: Run.h:45
void beginRun(const edm::Run &r, const edm::EventSetup &c) override