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;
65  int m_verbose;
66 };
67 
68 namespace edm {
69  class StreamID;
70 }
71 
72 namespace {
73  //
74  // this machinery allows to set CLHEP static engine
75  // to the one defined by RandomNumberGenerator service
76  // at the beginning of an event, and reset it back to
77  // "default-default" at the end of the event;
78  // Dave D. has decided to implement it this way because
79  // we don't know if there're other modules using CLHEP
80  // static engine, thus we want to ensure that the one
81  // we use for OscarMTProducer is unique to OscarMTProducer
82  //
83  // !!! This not only sets the random engine used by GEANT.
84  // There are a few SimWatchers/SimProducers that generate
85  // random number and also use the global CLHEP random engine
86  // set by this code. If we ever change this design be careful
87  // not to forget about them!!!
88 
89  class StaticRandomEngineSetUnset {
90  public:
91  StaticRandomEngineSetUnset(edm::StreamID const&);
92  explicit StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine);
93  ~StaticRandomEngineSetUnset();
94 
95  CLHEP::HepRandomEngine* currentEngine() { return m_currentEngine; }
96 
97  private:
98  CLHEP::HepRandomEngine* m_currentEngine;
99  CLHEP::HepRandomEngine* m_previousEngine;
100  };
101 } // namespace
102 
104  : m_handoff{p.getUntrackedParameter<int>("workerThreadStackSize", 10 * 1024 * 1024)} {
105  m_verbose = p.getParameter<int>("EventVerbose");
106  // Random number generation not allowed here
107  StaticRandomEngineSetUnset random(nullptr);
108 
110  m_handoff.runAndWait([this, &p, token]() {
112  StaticRandomEngineSetUnset random(nullptr);
113  m_runManagerWorker = std::make_unique<RunManagerMTWorker>(p, consumesCollector());
114  });
115  m_masterThread = ms;
116  m_masterThread->callConsumes(consumesCollector());
117 
118  // List of produced containers
119  produces<edm::SimTrackContainer>().setBranchAlias("SimTracks");
120  produces<edm::SimVertexContainer>().setBranchAlias("SimVertices");
121  produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelLowTof");
122  produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelHighTof");
123  produces<edm::PSimHitContainer>("TrackerHitsTIBLowTof");
124  produces<edm::PSimHitContainer>("TrackerHitsTIBHighTof");
125  produces<edm::PSimHitContainer>("TrackerHitsTIDLowTof");
126  produces<edm::PSimHitContainer>("TrackerHitsTIDHighTof");
127  produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapLowTof");
128  produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapHighTof");
129  produces<edm::PSimHitContainer>("TrackerHitsTOBLowTof");
130  produces<edm::PSimHitContainer>("TrackerHitsTOBHighTof");
131  produces<edm::PSimHitContainer>("TrackerHitsTECLowTof");
132  produces<edm::PSimHitContainer>("TrackerHitsTECHighTof");
133 
134  produces<edm::PSimHitContainer>("TotemHitsT1");
135  produces<edm::PSimHitContainer>("TotemHitsT2Gem");
136  produces<edm::PSimHitContainer>("TotemHitsRP");
137  produces<edm::PSimHitContainer>("CTPPSPixelHits");
138  produces<edm::PSimHitContainer>("CTPPSTimingHits");
139  produces<edm::PSimHitContainer>("FP420SI");
140  produces<edm::PSimHitContainer>("BSCHits");
141  produces<edm::PSimHitContainer>("PLTHits");
142  produces<edm::PSimHitContainer>("BCM1FHits");
143  produces<edm::PSimHitContainer>("BHMHits");
144  produces<edm::PSimHitContainer>("FastTimerHitsBarrel");
145  produces<edm::PSimHitContainer>("FastTimerHitsEndcap");
146 
147  produces<edm::PCaloHitContainer>("EcalHitsEB");
148  produces<edm::PCaloHitContainer>("EcalHitsEE");
149  produces<edm::PCaloHitContainer>("EcalHitsES");
150  produces<edm::PCaloHitContainer>("HcalHits");
151  produces<edm::PCaloHitContainer>("CaloHitsTk");
152  produces<edm::PCaloHitContainer>("HGCHitsEE");
153  produces<edm::PCaloHitContainer>("HGCHitsHEfront");
154  produces<edm::PCaloHitContainer>("HGCHitsHEback");
155 
156  produces<edm::PSimHitContainer>("MuonDTHits");
157  produces<edm::PSimHitContainer>("MuonCSCHits");
158  produces<edm::PSimHitContainer>("MuonRPCHits");
159  produces<edm::PSimHitContainer>("MuonGEMHits");
160  produces<edm::PSimHitContainer>("MuonME0Hits");
161  produces<edm::PCaloHitContainer>("CastorPL");
162  produces<edm::PCaloHitContainer>("CastorFI");
163  produces<edm::PCaloHitContainer>("CastorBU");
164  produces<edm::PCaloHitContainer>("CastorTU");
165  produces<edm::PCaloHitContainer>("EcalTBH4BeamHits");
166  produces<edm::PCaloHitContainer>("HcalTB06BeamHits");
167  produces<edm::PCaloHitContainer>("ZDCHITS");
168  produces<edm::PCaloHitContainer>("ChamberHits");
169  produces<edm::PCaloHitContainer>("FibreHits");
170  produces<edm::PCaloHitContainer>("WedgeHits");
171  produces<edm::PCaloHitContainer>("HFNoseHits");
172  produces<edm::PCaloHitContainer>("TotemHitsT2Scint");
173 
174  //register any products
175  auto& producers = m_runManagerWorker->producers();
176  for (auto& ptr : producers) {
177  ptr->registerProducts(producesCollector());
178  }
179  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer is constructed";
180 }
181 
184  m_handoff.runAndWait([this, token]() {
186  m_runManagerWorker.reset();
187  });
188 }
189 
190 std::unique_ptr<OscarMTMasterThread> OscarMTProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
191  // Random number generation not allowed here
192  StaticRandomEngineSetUnset random(nullptr);
193  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::initializeGlobalCache";
194 
195  return std::make_unique<OscarMTMasterThread>(iConfig);
196 }
197 
198 std::shared_ptr<int> OscarMTProducer::globalBeginRun(const edm::Run&,
199  const edm::EventSetup& iSetup,
200  const OscarMTMasterThread* masterThread) {
201  // Random number generation not allowed here
202  StaticRandomEngineSetUnset random(nullptr);
203  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun";
204  masterThread->beginRun(iSetup);
205  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun done";
206  return std::shared_ptr<int>();
207 }
208 
209 void OscarMTProducer::globalEndRun(const edm::Run&, const edm::EventSetup&, const RunContext* iContext) {
210  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndRun";
211  iContext->global()->endRun();
212 }
213 
215  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndJob";
216  masterThread->stopThread();
217 }
218 
220  int id = m_runManagerWorker->getThreadIndex();
221  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun threadID=" << id;
223  m_handoff.runAndWait([this, &es, token]() {
225  m_runManagerWorker->beginRun(es);
227  });
228  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun done threadID=" << id;
229 }
230 
232  StaticRandomEngineSetUnset random(nullptr);
233  int id = m_runManagerWorker->getThreadIndex();
234  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun threadID=" << id;
236  m_handoff.runAndWait([this, token]() {
238  m_runManagerWorker->endRun();
239  });
240  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun done threadID=" << id;
241 }
242 
244  StaticRandomEngineSetUnset random(e.streamID());
245  auto engine = random.currentEngine();
246  int id = m_runManagerWorker->getThreadIndex();
247  if (0 < m_verbose) {
248  edm::LogVerbatim("SimG4CoreApplication")
249  << "Produce event " << e.id() << " stream " << e.streamID() << " threadID=" << id;
250  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
251  }
252 
253  auto& sTk = m_runManagerWorker->sensTkDetectors();
254  auto& sCalo = m_runManagerWorker->sensCaloDetectors();
255 
256  G4SimEvent* evt = nullptr;
258  m_handoff.runAndWait([this, &e, &es, &evt, token, engine]() {
260  StaticRandomEngineSetUnset random(engine);
261  evt = m_runManagerWorker->produce(e, es, globalCache()->runManagerMaster());
262  });
263 
264  std::unique_ptr<edm::SimTrackContainer> p1(new edm::SimTrackContainer);
265  std::unique_ptr<edm::SimVertexContainer> p2(new edm::SimVertexContainer);
266  evt->load(*p1);
267  evt->load(*p2);
268 
269  if (0 < m_verbose) {
270  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p2->size() << " SimVertex objects";
271  if (1 < m_verbose) {
272  int nn = p2->size();
273  for (int i = 0; i < nn; ++i) {
274  edm::LogVerbatim("Vertex") << " " << (*p2)[i] << " " << (*p2)[i].processType();
275  }
276  }
277  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p1->size() << " SimTrack objects";
278  if (1 < m_verbose) {
279  int nn = p1->size();
280  for (int i = 0; i < nn; ++i) {
281  edm::LogVerbatim("Track") << " " << i << ". " << (*p1)[i] << " " << (*p1)[i].crossedBoundary() << " "
282  << (*p1)[i].getIDAtBoundary();
283  }
284  }
285  }
286  e.put(std::move(p1));
287  e.put(std::move(p2));
288 
289  for (auto& tracker : sTk) {
290  const std::vector<std::string>& v = tracker->getNames();
291  for (auto& name : v) {
292  std::unique_ptr<edm::PSimHitContainer> product(new edm::PSimHitContainer);
293  tracker->fillHits(*product, name);
294  if (0 < m_verbose && product != nullptr && !product->empty())
295  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " tracker hits <" << name << ">";
296  e.put(std::move(product), name);
297  }
298  }
299  for (auto& calo : sCalo) {
300  const std::vector<std::string>& v = calo->getNames();
301  for (auto& name : v) {
302  std::unique_ptr<edm::PCaloHitContainer> product(new edm::PCaloHitContainer);
303  calo->fillHits(*product, name);
304  if (0 < m_verbose && product != nullptr && !product->empty())
305  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " calo hits <" << name << ">";
306  e.put(std::move(product), name);
307  }
308  }
309 
310  auto& producers = m_runManagerWorker->producers();
311  for (auto& prod : producers) {
312  prod.get()->produce(e, es);
313  }
314  if (0 < m_verbose) {
315  edm::LogVerbatim("SimG4CoreApplication")
316  << "Event is produced event " << e.id() << " streamID=" << e.streamID() << " threadID=" << id;
317  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
318  }
319 }
320 
321 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(edm::StreamID const& streamID) {
323  if (!rng.isAvailable()) {
324  throw cms::Exception("Configuration")
325  << "The OscarMTProducer module requires the RandomNumberGeneratorService\n"
326  "which is not present in the configuration file. You must add the service\n"
327  "in the configuration file if you want to run OscarMTProducer";
328  }
329  m_currentEngine = &(rng->getEngine(streamID));
330 
331  m_previousEngine = G4Random::getTheEngine();
332  G4Random::setTheEngine(m_currentEngine);
333 }
334 
335 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine) {
336  m_currentEngine = engine;
337  m_previousEngine = G4Random::getTheEngine();
338  G4Random::setTheEngine(m_currentEngine);
339 }
340 
341 StaticRandomEngineSetUnset::~StaticRandomEngineSetUnset() { G4Random::setTheEngine(m_previousEngine); }
342 
Log< level::Info, true > LogVerbatim
RunManagerMT * runManagerMasterPtr() const
std::vector< PCaloHit > PCaloHitContainer
static std::shared_ptr< int > globalBeginRun(const edm::Run &iRun, const edm::EventSetup &iSetup, const OscarMTMasterThread *masterThread)
std::unique_ptr< RunManagerMTWorker > m_runManagerWorker
OscarMTProducer(edm::ParameterSet const &p, const OscarMTMasterThread *)
void beginRun(const edm::EventSetup &iSetup) const
~OscarMTProducer() override
std::vector< std::shared_ptr< SimProducer > > Producers
void runAndWait(F &&iF)
Definition: ThreadHandoff.h:42
virtual CLHEP::HepRandomEngine & getEngine(StreamID const &)=0
Use this engine in event methods.
void load(edm::SimTrackContainer &c) const
Definition: G4SimEvent.cc:36
const OscarMTMasterThread * m_masterThread
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