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 = (nullptr != 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  produces<edm::PCaloHitContainer>("CalibrationHGCHitsEE");
163  produces<edm::PCaloHitContainer>("CalibrationHGCHitsHEfront");
164  produces<edm::PCaloHitContainer>("CalibrationHGCHitsHEback");
165 
166  produces<edm::PSimHitContainer>("MuonDTHits");
167  produces<edm::PSimHitContainer>("MuonCSCHits");
168  produces<edm::PSimHitContainer>("MuonRPCHits");
169  produces<edm::PSimHitContainer>("MuonGEMHits");
170  produces<edm::PSimHitContainer>("MuonME0Hits");
171  produces<edm::PCaloHitContainer>("CastorPL");
172  produces<edm::PCaloHitContainer>("CastorFI");
173  produces<edm::PCaloHitContainer>("CastorBU");
174  produces<edm::PCaloHitContainer>("CastorTU");
175  produces<edm::PCaloHitContainer>("EcalTBH4BeamHits");
176  produces<edm::PCaloHitContainer>("HcalTB06BeamHits");
177  produces<edm::PCaloHitContainer>("ZDCHITS");
178  produces<edm::PCaloHitContainer>("ChamberHits");
179  produces<edm::PCaloHitContainer>("FibreHits");
180  produces<edm::PCaloHitContainer>("WedgeHits");
181  produces<edm::PCaloHitContainer>("HFNoseHits");
182  produces<edm::PCaloHitContainer>("TotemHitsT2Scint");
183 
184  //register any products
185  auto& producers = m_runManagerWorker->producers();
186  for (auto& ptr : producers) {
187  ptr->registerProducts(producesCollector());
188  }
189  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer is constructed";
190 }
191 
194  m_handoff.runAndWait([this, token]() {
196  m_runManagerWorker.reset();
197  });
198 }
199 
200 std::unique_ptr<OscarMTMasterThread> OscarMTProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
201  // Random number generation not allowed here
202  StaticRandomEngineSetUnset random(nullptr);
203  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::initializeGlobalCache";
204  if (nullptr == s_masterThread) {
205  auto ret = std::make_unique<OscarMTMasterThread>(iConfig);
206  s_masterThread = ret.get();
207  s_psetID = iConfig.id();
208  return ret;
209  }
210  return {};
211 }
212 
213 std::shared_ptr<int> OscarMTProducer::globalBeginRun(const edm::Run&,
214  const edm::EventSetup& iSetup,
215  const OscarMTMasterThread* masterThread) {
216  // Random number generation not allowed here
217  StaticRandomEngineSetUnset random(nullptr);
218  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun";
219  if (masterThread) {
220  masterThread->beginRun(iSetup);
221  }
222  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun done";
223  return std::shared_ptr<int>();
224 }
225 
226 void OscarMTProducer::globalEndRun(const edm::Run&, const edm::EventSetup&, const RunContext* iContext) {
227  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndRun";
228  if (nullptr != iContext->global()) {
229  iContext->global()->endRun();
230  }
231 }
232 
234  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndJob";
235  if (masterThread) {
236  masterThread->stopThread();
237  }
238 }
239 
241  if (s_psetID != m_psetID) {
242  throw cms::Exception("DiffOscarMTProducers")
243  << "At least two different OscarMTProducer instances have been"
244  "loaded into the job and they have different configurations.\n"
245  " All OscarMTProducers in a job must have exactly the same configuration.";
246  }
247  int id = m_runManagerWorker->getThreadIndex();
248  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun threadID=" << id;
250  m_handoff.runAndWait([this, &es, token]() {
252  m_runManagerWorker->beginRun(es);
254  });
255  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun done threadID=" << id;
256 }
257 
259  StaticRandomEngineSetUnset random(nullptr);
260  int id = m_runManagerWorker->getThreadIndex();
261  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun threadID=" << id;
263  m_handoff.runAndWait([this, token]() {
265  m_runManagerWorker->endRun();
266  });
267  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun done threadID=" << id;
268 }
269 
271  StaticRandomEngineSetUnset random(e.streamID());
272  auto engine = random.currentEngine();
273  int id = m_runManagerWorker->getThreadIndex();
274  if (0 < m_verbose) {
275  edm::LogVerbatim("SimG4CoreApplication")
276  << "Produce event " << e.id() << " stream " << e.streamID() << " threadID=" << id;
277  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
278  }
279 
280  auto& sTk = m_runManagerWorker->sensTkDetectors();
281  auto& sCalo = m_runManagerWorker->sensCaloDetectors();
282 
283  TmpSimEvent* evt = nullptr;
285  m_handoff.runAndWait([this, &e, &es, &evt, token, engine]() {
287  StaticRandomEngineSetUnset random(engine);
288  evt = m_runManagerWorker->produce(e, es, m_masterThread->runManagerMaster());
289  });
290 
291  std::unique_ptr<edm::SimTrackContainer> p1(new edm::SimTrackContainer);
292  std::unique_ptr<edm::SimVertexContainer> p2(new edm::SimVertexContainer);
293  evt->load(*p1);
294  evt->load(*p2);
295 
296  if (0 < m_verbose) {
297  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p2->size() << " SimVertex objects";
298  if (1 < m_verbose) {
299  int nn = p2->size();
300  for (int i = 0; i < nn; ++i) {
301  edm::LogVerbatim("Vertex") << " " << (*p2)[i] << " " << (*p2)[i].processType();
302  }
303  }
304  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p1->size() << " SimTrack objects";
305  if (1 < m_verbose) {
306  int nn = p1->size();
307  for (int i = 0; i < nn; ++i) {
308  edm::LogVerbatim("Track") << " " << i << ". " << (*p1)[i] << " " << (*p1)[i].crossedBoundary() << " "
309  << (*p1)[i].getIDAtBoundary();
310  }
311  }
312  }
313  e.put(std::move(p1));
314  e.put(std::move(p2));
315 
316  for (auto& tracker : sTk) {
317  const std::vector<std::string>& v = tracker->getNames();
318  for (auto& name : v) {
319  std::unique_ptr<edm::PSimHitContainer> product(new edm::PSimHitContainer);
320  tracker->fillHits(*product, name);
321  if (0 < m_verbose && product != nullptr && !product->empty())
322  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " tracker hits <" << name << ">";
323  e.put(std::move(product), name);
324  }
325  }
326  for (auto& calo : sCalo) {
327  const std::vector<std::string>& v = calo->getNames();
328  for (auto& name : v) {
329  std::unique_ptr<edm::PCaloHitContainer> product(new edm::PCaloHitContainer);
330  calo->fillHits(*product, name);
331  if (0 < m_verbose && product != nullptr && !product->empty())
332  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " calo hits <" << name << ">";
333  e.put(std::move(product), name);
334  }
335  }
336 
337  auto& producers = m_runManagerWorker->producers();
338  for (auto& prod : producers) {
339  prod.get()->produce(e, es);
340  }
341  if (0 < m_verbose) {
342  edm::LogVerbatim("SimG4CoreApplication")
343  << "Event is produced event " << e.id() << " streamID=" << e.streamID() << " threadID=" << id;
344  //edm::LogWarning("SimG4CoreApplication") << "EventID=" << e.id() << " rand=" << G4UniformRand();
345  }
346 }
347 
348 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(edm::StreamID const& streamID) {
350  if (!rng.isAvailable()) {
351  throw cms::Exception("Configuration")
352  << "The OscarMTProducer module requires the RandomNumberGeneratorService\n"
353  "which is not present in the configuration file. You must add the service\n"
354  "in the configuration file if you want to run OscarMTProducer";
355  }
356  m_currentEngine = &(rng->getEngine(streamID));
357 
358  m_previousEngine = G4Random::getTheEngine();
359  G4Random::setTheEngine(m_currentEngine);
360 }
361 
362 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine) {
363  m_currentEngine = engine;
364  m_previousEngine = G4Random::getTheEngine();
365  G4Random::setTheEngine(m_currentEngine);
366 }
367 
368 StaticRandomEngineSetUnset::~StaticRandomEngineSetUnset() { G4Random::setTheEngine(m_previousEngine); }
369 
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.
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
void load(edm::SimTrackContainer &c) const
Definition: TmpSimEvent.cc:29
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