CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
OscarMTProducer.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <memory>
3 
9 
14 
20 
25 
28 
30 
35 
37 
38 #include "Randomize.hh"
39 
40 // for some reason void doesn't compile
41 class OscarMTProducer : public edm::stream::EDProducer<edm::GlobalCache<OscarMTMasterThread>, edm::RunCache<int> > {
42 public:
43  typedef std::vector<std::shared_ptr<SimProducer> > Producers;
44 
45  explicit OscarMTProducer(edm::ParameterSet const& p, const OscarMTMasterThread*);
46  ~OscarMTProducer() override;
47 
48  static std::unique_ptr<OscarMTMasterThread> initializeGlobalCache(const edm::ParameterSet& iConfig);
49  static std::shared_ptr<int> globalBeginRun(const edm::Run& iRun,
50  const edm::EventSetup& iSetup,
51  const OscarMTMasterThread* masterThread);
52  static void globalEndRun(const edm::Run& iRun, const edm::EventSetup& iSetup, const RunContext* iContext);
53  static void globalEndJob(OscarMTMasterThread* masterThread);
54 
55  void beginRun(const edm::Run& r, const edm::EventSetup& c) override;
56  void endRun(const edm::Run& r, const edm::EventSetup& c) override;
57  void produce(edm::Event& e, const edm::EventSetup& c) override;
58 
59 private:
61  std::unique_ptr<RunManagerMTWorker> m_runManagerWorker;
63 };
64 
65 namespace edm {
66  class StreamID;
67 }
68 
69 namespace {
70  //
71  // this machinery allows to set CLHEP static engine
72  // to the one defined by RandomNumberGenerator service
73  // at the beginning of an event, and reset it back to
74  // "default-default" at the end of the event;
75  // Dave D. has decided to implement it this way because
76  // we don't know if there're other modules using CLHEP
77  // static engine, thus we want to ensure that the one
78  // we use for OscarMTProducer is unique to OscarMTProducer
79  //
80  // !!! This not only sets the random engine used by GEANT.
81  // There are a few SimWatchers/SimProducers that generate
82  // random number and also use the global CLHEP random engine
83  // set by this code. If we ever change this design be careful
84  // not to forget about them!!!
85 
86  class StaticRandomEngineSetUnset {
87  public:
88  StaticRandomEngineSetUnset(edm::StreamID const&);
89  explicit StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine);
90  ~StaticRandomEngineSetUnset();
91 
92  CLHEP::HepRandomEngine* currentEngine() { return m_currentEngine; }
93 
94  private:
95  CLHEP::HepRandomEngine* m_currentEngine;
96  CLHEP::HepRandomEngine* m_previousEngine;
97  };
98 } // namespace
99 
101  : m_handoff{p.getUntrackedParameter<int>("workerThreadStackSize", 10 * 1024 * 1024)} {
102  // Random number generation not allowed here
103  StaticRandomEngineSetUnset random(nullptr);
104 
106  m_handoff.runAndWait([this, &p, token]() {
108  StaticRandomEngineSetUnset random(nullptr);
109  m_runManagerWorker = std::make_unique<RunManagerMTWorker>(p, consumesCollector());
110  });
111  m_masterThread = ms;
112  m_masterThread->callConsumes(consumesCollector());
113 
114  // List of produced containers
115  produces<edm::SimTrackContainer>().setBranchAlias("SimTracks");
116  produces<edm::SimVertexContainer>().setBranchAlias("SimVertices");
117  produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelLowTof");
118  produces<edm::PSimHitContainer>("TrackerHitsPixelBarrelHighTof");
119  produces<edm::PSimHitContainer>("TrackerHitsTIBLowTof");
120  produces<edm::PSimHitContainer>("TrackerHitsTIBHighTof");
121  produces<edm::PSimHitContainer>("TrackerHitsTIDLowTof");
122  produces<edm::PSimHitContainer>("TrackerHitsTIDHighTof");
123  produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapLowTof");
124  produces<edm::PSimHitContainer>("TrackerHitsPixelEndcapHighTof");
125  produces<edm::PSimHitContainer>("TrackerHitsTOBLowTof");
126  produces<edm::PSimHitContainer>("TrackerHitsTOBHighTof");
127  produces<edm::PSimHitContainer>("TrackerHitsTECLowTof");
128  produces<edm::PSimHitContainer>("TrackerHitsTECHighTof");
129 
130  produces<edm::PSimHitContainer>("TotemHitsT1");
131  produces<edm::PSimHitContainer>("TotemHitsT2Gem");
132  produces<edm::PSimHitContainer>("TotemHitsRP");
133  produces<edm::PSimHitContainer>("CTPPSPixelHits");
134  produces<edm::PSimHitContainer>("CTPPSTimingHits");
135  produces<edm::PSimHitContainer>("FP420SI");
136  produces<edm::PSimHitContainer>("BSCHits");
137  produces<edm::PSimHitContainer>("PLTHits");
138  produces<edm::PSimHitContainer>("BCM1FHits");
139  produces<edm::PSimHitContainer>("BHMHits");
140  produces<edm::PSimHitContainer>("FastTimerHitsBarrel");
141  produces<edm::PSimHitContainer>("FastTimerHitsEndcap");
142 
143  produces<edm::PCaloHitContainer>("EcalHitsEB");
144  produces<edm::PCaloHitContainer>("EcalHitsEE");
145  produces<edm::PCaloHitContainer>("EcalHitsES");
146  produces<edm::PCaloHitContainer>("HcalHits");
147  produces<edm::PCaloHitContainer>("CaloHitsTk");
148  produces<edm::PCaloHitContainer>("HGCHitsEE");
149  produces<edm::PCaloHitContainer>("HGCHitsHEfront");
150  produces<edm::PCaloHitContainer>("HGCHitsHEback");
151 
152  produces<edm::PSimHitContainer>("MuonDTHits");
153  produces<edm::PSimHitContainer>("MuonCSCHits");
154  produces<edm::PSimHitContainer>("MuonRPCHits");
155  produces<edm::PSimHitContainer>("MuonGEMHits");
156  produces<edm::PSimHitContainer>("MuonME0Hits");
157  produces<edm::PCaloHitContainer>("CastorPL");
158  produces<edm::PCaloHitContainer>("CastorFI");
159  produces<edm::PCaloHitContainer>("CastorBU");
160  produces<edm::PCaloHitContainer>("CastorTU");
161  produces<edm::PCaloHitContainer>("EcalTBH4BeamHits");
162  produces<edm::PCaloHitContainer>("HcalTB06BeamHits");
163  produces<edm::PCaloHitContainer>("ZDCHITS");
164  produces<edm::PCaloHitContainer>("ChamberHits");
165  produces<edm::PCaloHitContainer>("FibreHits");
166  produces<edm::PCaloHitContainer>("WedgeHits");
167  produces<edm::PCaloHitContainer>("HFNoseHits");
168  produces<edm::PCaloHitContainer>("TotemHitsT2Scint");
169 
170  //register any products
171  auto& producers = m_runManagerWorker->producers();
172  for (auto& ptr : producers) {
173  ptr->registerProducts(producesCollector());
174  }
175  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer is constructed";
176 }
177 
180  m_handoff.runAndWait([this, token]() {
182  m_runManagerWorker.reset();
183  });
184 }
185 
186 std::unique_ptr<OscarMTMasterThread> OscarMTProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
187  // Random number generation not allowed here
188  StaticRandomEngineSetUnset random(nullptr);
189  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::initializeGlobalCache";
190 
191  return std::make_unique<OscarMTMasterThread>(iConfig);
192 }
193 
194 std::shared_ptr<int> OscarMTProducer::globalBeginRun(const edm::Run&,
195  const edm::EventSetup& iSetup,
196  const OscarMTMasterThread* masterThread) {
197  // Random number generation not allowed here
198  StaticRandomEngineSetUnset random(nullptr);
199  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun";
200  masterThread->beginRun(iSetup);
201  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun done";
202  return std::shared_ptr<int>();
203 }
204 
205 void OscarMTProducer::globalEndRun(const edm::Run&, const edm::EventSetup&, const RunContext* iContext) {
206  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndRun";
207  iContext->global()->endRun();
208 }
209 
211  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndJob";
212  masterThread->stopThread();
213 }
214 
216  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun";
218  m_handoff.runAndWait([this, &es, token]() {
220  m_runManagerWorker->beginRun(es);
222  });
223  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun done";
224 }
225 
227  // Random number generation not allowed here
228  StaticRandomEngineSetUnset random(nullptr);
229  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun";
231  m_handoff.runAndWait([this, token]() {
232  StaticRandomEngineSetUnset random(nullptr);
234  m_runManagerWorker->endRun();
235  });
236  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun done";
237 }
238 
240  StaticRandomEngineSetUnset random(e.streamID());
241  auto engine = random.currentEngine();
242  edm::LogVerbatim("SimG4CoreApplication") << "Produce event " << e.id() << " stream " << e.streamID();
243  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
244 
245  auto& sTk = m_runManagerWorker->sensTkDetectors();
246  auto& sCalo = m_runManagerWorker->sensCaloDetectors();
247 
248  std::unique_ptr<G4SimEvent> evt;
250  m_handoff.runAndWait([this, &e, &es, &evt, token, engine]() {
252  StaticRandomEngineSetUnset random(engine);
253  evt = m_runManagerWorker->produce(e, es, globalCache()->runManagerMaster());
254  });
255 
256  std::unique_ptr<edm::SimTrackContainer> p1(new edm::SimTrackContainer);
257  std::unique_ptr<edm::SimVertexContainer> p2(new edm::SimVertexContainer);
258  evt->load(*p1);
259  evt->load(*p2);
260 
261  e.put(std::move(p1));
262  e.put(std::move(p2));
263 
264  for (auto& tracker : sTk) {
265  const std::vector<std::string>& v = tracker->getNames();
266  for (auto& name : v) {
267  std::unique_ptr<edm::PSimHitContainer> product(new edm::PSimHitContainer);
268  tracker->fillHits(*product, name);
269  if (product != nullptr && !product->empty())
270  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " tracker hits <" << name << ">";
271  e.put(std::move(product), name);
272  }
273  }
274  for (auto& calo : sCalo) {
275  const std::vector<std::string>& v = calo->getNames();
276  for (auto& name : v) {
277  std::unique_ptr<edm::PCaloHitContainer> product(new edm::PCaloHitContainer);
278  calo->fillHits(*product, name);
279  if (product != nullptr && !product->empty())
280  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " calo hits <" << name << ">";
281  e.put(std::move(product), name);
282  }
283  }
284 
285  auto& producers = m_runManagerWorker->producers();
286  for (auto& prod : producers) {
287  prod.get()->produce(e, es);
288  }
289  edm::LogVerbatim("SimG4CoreApplication") << "Event is produced " << e.id() << " stream " << e.streamID();
290  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
291 }
292 
293 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(edm::StreamID const& streamID) {
295  if (!rng.isAvailable()) {
296  throw cms::Exception("Configuration")
297  << "The OscarMTProducer module requires the RandomNumberGeneratorService\n"
298  "which is not present in the configuration file. You must add the service\n"
299  "in the configuration file if you want to run OscarMTProducer";
300  }
301  m_currentEngine = &(rng->getEngine(streamID));
302 
303  m_previousEngine = G4Random::getTheEngine();
304  G4Random::setTheEngine(m_currentEngine);
305 }
306 
307 StaticRandomEngineSetUnset::StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine) {
308  m_currentEngine = engine;
309  m_previousEngine = G4Random::getTheEngine();
310  G4Random::setTheEngine(m_currentEngine);
311 }
312 
313 StaticRandomEngineSetUnset::~StaticRandomEngineSetUnset() { G4Random::setTheEngine(m_previousEngine); }
314 
Log< level::Info, true > LogVerbatim
T getUntrackedParameter(std::string const &, T const &) const
std::vector< PCaloHit > PCaloHitContainer
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:133
const edm::EventSetup & c
static std::shared_ptr< int > globalBeginRun(const edm::Run &iRun, const edm::EventSetup &iSetup, const OscarMTMasterThread *masterThread)
const TString p2
Definition: fwPaths.cc:13
std::unique_ptr< RunManagerMTWorker > m_runManagerWorker
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
OscarMTProducer(edm::ParameterSet const &p, const OscarMTMasterThread *)
~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.
ServiceToken presentToken() const
void beginRun(const edm::EventSetup &iSetup) const
const OscarMTMasterThread * m_masterThread
def move
Definition: eostools.py:511
bool isAvailable() const
Definition: Service.h:40
static ServiceRegistry & instance()
const TString p1
Definition: fwPaths.cc:12
void produce(edm::Event &e, const edm::EventSetup &c) override
G const * global() const
Definition: Contexts.h:35
static void globalEndRun(const edm::Run &iRun, const edm::EventSetup &iSetup, const RunContext *iContext)
RunManagerMT * runManagerMasterPtr() const
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
edm::EventID id() const
Definition: EventBase.h:59
StreamID streamID() const
Definition: Event.h:98
void callConsumes(edm::ConsumesCollector &&iC) const
std::vector< PSimHit > PSimHitContainer
omt::ThreadHandoff m_handoff
static void globalEndJob(OscarMTMasterThread *masterThread)
std::vector< SimTrack > SimTrackContainer
Definition: Run.h:45
void beginRun(const edm::Run &r, const edm::EventSetup &c) override