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